diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 51352d60..16b14106 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -11,7 +11,7 @@ fn main() -> anyhow::Result<()> { println!("{:#?}", program); - let flat_bytes = program.flat()?; + let flat_bytes = program.to_flat()?; for byte in flat_bytes { print!("{:08b} ", byte); diff --git a/crates/flat/src/decode.rs b/crates/flat/src/decode.rs new file mode 100644 index 00000000..7bd7c7f4 --- /dev/null +++ b/crates/flat/src/decode.rs @@ -0,0 +1,5 @@ +use crate::decoder::Decoder; + +pub trait Decode<'b>: Sized { + fn decode(d: &mut Decoder<'b>) -> Result; +} diff --git a/crates/flat/src/decoder.rs b/crates/flat/src/decoder.rs new file mode 100644 index 00000000..21f41fec --- /dev/null +++ b/crates/flat/src/decoder.rs @@ -0,0 +1,19 @@ +use crate::decode::Decode; + +pub struct Decoder<'b> { + buffer: &'b [u8], + pos: usize, +} + +impl<'b> Decoder<'b> { + pub fn new(bytes: &'b [u8]) -> Decoder<'b> { + Decoder { + buffer: bytes, + pos: 0, + } + } + + pub fn decode>(&mut self) -> Result { + T::decode(self) + } +} diff --git a/crates/flat/src/encode.rs b/crates/flat/src/encode.rs index bcf077f7..13a5a21e 100644 --- a/crates/flat/src/encode.rs +++ b/crates/flat/src/encode.rs @@ -83,19 +83,6 @@ impl Encode for Box { } } -impl Encode for (T, K) -where - T: Encode, - K: Encode, -{ - fn encode(&self, e: &mut Encoder) -> Result<(), String> { - self.0.encode(e)?; - self.1.encode(e)?; - - Ok(()) - } -} - impl Encode for Filler { fn encode(&self, e: &mut Encoder) -> Result<(), String> { e.filler(); diff --git a/crates/flat/src/lib.rs b/crates/flat/src/lib.rs index cf0f6fc0..eb0769cd 100644 --- a/crates/flat/src/lib.rs +++ b/crates/flat/src/lib.rs @@ -1,3 +1,5 @@ +mod decode; +mod decoder; mod encode; mod encoder; mod filler; @@ -8,33 +10,58 @@ pub mod en { pub use super::encoder::*; } -pub fn encode(value: T) -> Result, String> +pub mod de { + pub use super::decode::*; + pub use super::decoder::*; +} + +pub trait Flat<'b>: en::Encode + de::Decode<'b> { + fn flat(&self) -> Result, String> { + encode(self) + } + + fn unflat(bytes: &'b [u8]) -> Result { + decode(bytes) + } +} + +pub fn encode(value: &T) -> Result, String> where T: en::Encode, { let mut e = en::Encoder::new(); - e.encode((value, filler::Filler::FillerEnd))?; + value.encode(&mut e)?; + e.encode(filler::Filler::FillerEnd)?; Ok(e.buffer) } +pub fn decode<'b, T>(bytes: &'b [u8]) -> Result +where + T: de::Decode<'b>, +{ + let mut d = de::Decoder::new(bytes); + + d.decode() +} + #[cfg(test)] mod test { #[test] fn encode_bool() { - let bytes = super::encode(true).unwrap(); + let bytes = super::encode(&true).unwrap(); assert_eq!(bytes, vec![0b10000001]); - let bytes = super::encode(false).unwrap(); + let bytes = super::encode(&false).unwrap(); assert_eq!(bytes, vec![0b00000001]); } #[test] fn encode_u8() { - let bytes = super::encode(3_u8).unwrap(); + let bytes = super::encode(&3_u8).unwrap(); assert_eq!(bytes, vec![0b00000011, 0b00000001]); } diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index 2b92854d..98140447 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -1,6 +1,10 @@ use anyhow::anyhow; -use flat::en::{Encode, Encoder}; +use flat::{ + de::{Decode, Decoder}, + en::{Encode, Encoder}, + Flat, +}; use crate::{ ast::{Constant, Program, Term}, @@ -11,15 +15,17 @@ const BUILTIN_TAG_WIDTH: u32 = 7; const CONST_TAG_WIDTH: u32 = 4; const TERM_TAG_WIDTH: u32 = 4; -impl Program { - pub fn flat(&self) -> anyhow::Result> { - let bytes = flat::encode(self.clone()).map_err(|err| anyhow!("{}", err))?; +impl<'b> Flat<'b> for Program {} - Ok(bytes) +impl Program { + // convenient so that people don't need to depend on the flat crate + // directly to call programs flat function + pub fn to_flat(&self) -> anyhow::Result> { + self.flat().map_err(|err| anyhow!("{}", err)) } pub fn flat_hex(&self) -> anyhow::Result { - let bytes = self.flat()?; + let bytes = self.flat().map_err(|err| anyhow!("{}", err))?; let hex = hex::encode(&bytes); @@ -41,6 +47,12 @@ impl Encode for Program { } } +impl<'b> Decode<'b> for Program { + fn decode(_d: &mut Decoder<'b>) -> Result { + todo!() + } +} + impl Encode for Term { fn encode(&self, e: &mut Encoder) -> Result<(), String> { // still need annotation but here we have the term tags @@ -92,6 +104,12 @@ impl Encode for Term { } } +impl<'b> Decode<'b> for Term { + fn decode(_d: &mut Decoder<'b>) -> Result { + todo!() + } +} + impl Encode for &Constant { fn encode(&self, e: &mut Encoder) -> Result<(), String> { match self { @@ -128,6 +146,12 @@ impl Encode for &Constant { } } +impl<'b> Decode<'b> for Constant { + fn decode(_d: &mut Decoder<'b>) -> Result { + todo!() + } +} + impl Encode for DefaultFunction { fn encode(&self, e: &mut flat::en::Encoder) -> Result<(), String> { e.bits(BUILTIN_TAG_WIDTH as i64, self.clone() as u8); @@ -136,6 +160,12 @@ impl Encode for DefaultFunction { } } +impl<'b> Decode<'b> for DefaultFunction { + fn decode(_d: &mut Decoder<'b>) -> Result { + todo!() + } +} + fn encode_term_tag(tag: u8, e: &mut Encoder) -> Result<(), String> { safe_encode_bits(TERM_TAG_WIDTH, tag, e) } @@ -171,7 +201,7 @@ mod test { term: Term::Constant(Constant::Integer(11)), }; - let bytes = program.flat().unwrap(); + let bytes = program.to_flat().unwrap(); assert_eq!( bytes,