use nom::{
bytes::complete::{take, take_till},
combinator::peek,
IResult,
};
use std::ffi::CString;
pub fn maybe<'a, O, F>(mut child: F, input: &'a [u8]) -> IResult<&'a [u8], Option<O>>
where
F: FnMut(&'a [u8]) -> IResult<&'a [u8], O>,
{
let (input, first) = peek(take(1 as usize))(input)?;
if first == &[0] {
let (input, _) = take(1 as usize)(input)?;
Ok((input, None))
} else {
let (input, result) = child(input)?;
Ok((input, Some(result)))
}
}
pub fn vec_of<'a, O, F>(mut child: F, input: &'a [u8]) -> IResult<&'a [u8], Vec<O>>
where
F: FnMut(&'a [u8]) -> IResult<&'a [u8], O>,
{
let (mut input, count) = take(2 as usize)(input)?;
let count = u16::from_be_bytes([count[0], count[1]]);
let mut buf = Vec::with_capacity(count as usize);
for _ in 0..count as usize {
let (new_input, item) = child(input)?;
input = new_input;
buf.push(item);
}
Ok((input, buf))
}
pub fn cstring(input: &[u8]) -> IResult<&[u8], Option<CString>> {
let (input, bytes) = take_till(|x| x == '\0' as u8)(input)?;
Ok((input, CString::from_vec_with_nul(bytes.to_vec()).ok()))
}