feat(bytecode): add ability to serialize
This commit is contained in:
parent
e8f10c4f34
commit
f9214f54db
4 changed files with 45 additions and 10 deletions
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue