//! DNS resolver module for `std`
use abi::net::dns::DnsSerialize;

pub use abi::net::dns::{DnsClass, DnsMessage, DnsMethod, DnsRecordData, DnsReplyCode, DnsType};

/// Interface for performing UDP communication
pub trait UdpRequester {
    /// Error returned by the requester
    type Error;

    /// Sends a message through the communication channel
    fn send_message(&mut self, message: &[u8]) -> Result<(), Self::Error>;

    /// Wait for a message, parses it and runs a function on it to determine whether to return
    fn receive_message<F: Fn(&[u8]) -> Option<DnsMessage>>(
        &mut self,
        map: F,
    ) -> Result<DnsMessage, Self::Error>;
}

/// Performs a raw DNS query without analyzing the reply
pub fn perform_query<R: UdpRequester>(
    requester: &mut R,
    name: &str,
    ty: DnsType,
    xid: u16,
    cookie: u64,
) -> Result<DnsMessage, R::Error> {
    let mut packet = alloc::vec![];
    let query = DnsMessage::query(name, ty, xid, cookie);
    query.serialize(&mut packet);
    requester.send_message(&packet)?;

    let message = requester.receive_message(|data| {
        let message = DnsMessage::parse(data)?;

        if message.xid != xid || message.method != DnsMethod::REPLY {
            return None;
        }

        Some(message)
    })?;

    Ok(message)
}
