feat(bytecode): add ability to serialize

This commit is contained in:
Alain Zscheile 2022-09-23 05:52:10 +02:00
parent e8f10c4f34
commit f9214f54db
4 changed files with 45 additions and 10 deletions

View file

@ -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 */
}

View file

@ -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.

View file

@ -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<W: std::io::Write>(&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<W: std::io::Write>(&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 {

View file

@ -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<W: std::io::Write>(&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 _ = <Value as crate::Parse<'_>>::parse(&inp[..]);
if let Ok((_, v)) = <Value as crate::Parse<'_>>::parse(&inp[..]) {
let mut buf = alloc::vec::Vec::with_capacity(inp.len());
v.write_to(&mut buf).unwrap();
}
}
}
}