use core::mem::size_of;
use crate::{Error, Name, QueryKind, QueryClass};
#[derive(Debug)]
pub struct Answer<'a> {
pub name: Name<'a>,
pub kind: QueryKind,
pub class: QueryClass,
pub ttl: u32,
pub rdata: &'a [u8],
}
fn read_ttl(buf: &[u8], i: &mut usize) -> Result<u32, Error> {
if *i + size_of::<u32>() <= buf.len() {
let ttl = u32::from_be_bytes([buf[*i], buf[*i + 1], buf[*i + 2], buf[*i + 3]]);
*i += size_of::<u32>();
return Ok(ttl)
}
Err(Error::MessageTooShort)
}
fn read_rdata<'a>(buf: &'a [u8], i: &'_ mut usize) -> Result<&'a [u8], Error> {
if *i + size_of::<u16>() <= buf.len() {
let rdata_len = u16::from_be_bytes([buf[*i], buf[*i + 1]]) as usize;
let rdata_i = *i + size_of::<u16>();
if rdata_i + rdata_len <= buf.len() {
let rdata = &buf[rdata_i..(rdata_i + rdata_len)];
*i = rdata_i + rdata_len;
return Ok(rdata);
}
}
Err(Error::MessageTooShort)
}
impl<'a> Answer<'a> {
pub(crate) fn read(buf: &'a [u8], i: &'_ mut usize) -> Result<Self, Error> {
let mut j = *i;
let answer = Self {
name: Name::read(buf, &mut j)?,
kind: QueryKind::read(buf, &mut j)?,
class: QueryClass::read(buf, &mut j)?,
ttl: read_ttl(buf, &mut j)?,
rdata: read_rdata(buf, &mut j)?,
};
*i = j;
Ok(answer)
}
pub fn name(&self) -> &Name<'a> {
&self.name
}
pub fn kind(&self) -> &QueryKind {
&self.kind
}
pub fn class(&self) -> &QueryClass {
&self.class
}
pub fn ttl(&self) -> u32 {
self.ttl
}
pub fn rdata(&self) -> &'a [u8] {
self.rdata
}
}
#[derive(Debug)]
pub struct Answers<'a> {
pub(crate) answer_count: usize,
pub(crate) current_answer: usize,
pub(crate) buf: &'a [u8],
pub(crate) buf_i: usize,
}
impl<'a> Iterator for Answers<'a> {
type Item = Answer<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_answer >= self.answer_count {
return None
}
let answer = Answer::read(self.buf, &mut self.buf_i).ok()?;
self.current_answer += 1;
Some(answer)
}
}