Skip to content

Instantly share code, notes, and snippets.

@Lucretiel
Last active March 18, 2021 18:01
Show Gist options
  • Save Lucretiel/d9bb2704d9383ff8cfe05dadf54e9d9f to your computer and use it in GitHub Desktop.
Save Lucretiel/d9bb2704d9383ff8cfe05dadf54e9d9f to your computer and use it in GitHub Desktop.
Alternative implementation of DNS headers
pub trait BuildFlags: Sized {
type Error;
fn try_build_flags(payload: [u8; 2]) -> Result<Self, Self::Error>;
}
pub struct Headers<F> {
pub id: u16,
pub flags: F,
pub qdcount: u16,
pub ancount: u16,
pub nscount: u16,
pub arcount: u16,
}
pub fn parse_headers<'i, F, E>(input: &'i [u8]) -> IResult<&'i [u8], Headers<F>, E>
where
F: BuildFlags,
E: ParseError<&'i [u8]> + ContextError<&'i [u8]> + FromExternalError<&'i [u8], F::Error>,
{
tuple((
be_u16.context("id"),
take(2usize)
// Unwrap is safe here because we know (from take(2)) that this
// is a byte slice of length 2
.map_res(|flags: &[u8]| F::try_build_flags(flags.try_into().unwrap()))
.context("flags"),
be_u16.context("qdcount"),
be_u16.context("ancount"),
be_u16.context("nscount"),
be_u16.context("arcount"),
))
.map(|(id, flags, qdcount, ancount, nscount, arcount)| Headers {
id,
flags,
qdcount,
ancount,
nscount,
arcount,
})
.context("headers")
.parse(input)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment