diff --git a/crates/fogtix-bytecode/src/consts.rs b/crates/fogtix-bytecode/src/consts.rs index e1f9682..bc8da0a 100644 --- a/crates/fogtix-bytecode/src/consts.rs +++ b/crates/fogtix-bytecode/src/consts.rs @@ -1,8 +1,8 @@ #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)] pub enum Type { - Bytes = 0x42 /* B */, - Int_ = 0x49 /* I */, - Pointer = 0x50 /* P */, - PointerKey = 0x4b /* K */, + Bytes = 0x42, /* B */ + Int_ = 0x49, /* I */ + Pointer = 0x50, /* P */ + PointerKey = 0x4b, /* K */ } diff --git a/crates/fogtix-bytecode/src/lib.rs b/crates/fogtix-bytecode/src/lib.rs index 792478d..c974b26 100644 --- a/crates/fogtix-bytecode/src/lib.rs +++ b/crates/fogtix-bytecode/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(any(test, feature = "std")), no_std)] #![forbid(unsafe_code)] /// Fogtix bytecode is structured as type-(length?)-value items, which can be nested. diff --git a/crates/fogtix-bytecode/src/pointer.rs b/crates/fogtix-bytecode/src/pointer.rs index ce68c0c..7871649 100644 --- a/crates/fogtix-bytecode/src/pointer.rs +++ b/crates/fogtix-bytecode/src/pointer.rs @@ -66,6 +66,14 @@ impl crate::Parse<'_> for Pointer { Ok((&inp[16..], Self { hmac, payload })) } } +#[cfg(any(test, feature = "std"))] +impl Pointer { + #[inline] + pub fn write_to(&self, writer: W) -> std::io::Result<()> { + PointerKey::from(*self).write_to(writer) + } +} + impl crate::Parse<'_> for PointerKey { type Err = (); #[inline] @@ -74,6 +82,14 @@ impl crate::Parse<'_> for PointerKey { Ok((inp, p.into())) } } +#[cfg(any(test, feature = "std"))] +impl PointerKey { + pub fn write_to(&self, mut writer: W) -> std::io::Result<()> { + writer.write_all(&self.0.to_be_bytes())?; + writer.write_all(&self.1.to_be_bytes())?; + Ok(()) + } +} #[cfg(test)] mod tests { diff --git a/crates/fogtix-bytecode/src/value.rs b/crates/fogtix-bytecode/src/value.rs index ceb6606..55d2794 100644 --- a/crates/fogtix-bytecode/src/value.rs +++ b/crates/fogtix-bytecode/src/value.rs @@ -1,5 +1,6 @@ use crate::{consts::Type, Pointer, PointerKey}; use core::fmt; +use int_enum::IntEnum; #[derive(Clone, Debug, PartialEq)] pub enum Value<'a> { @@ -52,10 +53,7 @@ impl<'a> crate::Parse<'a> for Value<'a> { if inp.len() < 2 { return Err(ValueParseError); } - let (vtyp, inp) = { - use int_enum::IntEnum; - (Type::from_int(inp[0])?, &inp[1..]) - }; + let (vtyp, inp) = (Type::from_int(inp[0])?, &inp[1..]); match vtyp { Type::Bytes => { if inp.len() < 8 { @@ -90,6 +88,24 @@ impl<'a> crate::Parse<'a> for Value<'a> { } } +#[cfg(any(test, feature = "std"))] +impl Value<'_> { + pub fn write_to(&self, mut writer: W) -> std::io::Result<()> { + writer.write_all(&[self.typ().int_value()])?; + match self { + Value::Bytes(b) => { + let len: u64 = b.len().try_into().unwrap(); + writer.write_all(&len.to_be_bytes())?; + writer.write_all(b)?; + } + Value::Int(i) => writer.write_all(&i.to_be_bytes())?, + Value::Pointer(p) => p.write_to(writer)?, + Value::PointerKey(pk) => pk.write_to(writer)?, + } + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -97,7 +113,10 @@ mod tests { proptest::proptest! { #[test] fn doesnt_crash(inp in proptest::collection::vec(0..=u8::MAX, 0..256)) { - let _ = >::parse(&inp[..]); + if let Ok((_, v)) = >::parse(&inp[..]) { + let mut buf = alloc::vec::Vec::with_capacity(inp.len()); + v.write_to(&mut buf).unwrap(); + } } } }