diff --git a/Cargo.lock b/Cargo.lock index b12c063e..60dfd553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,10 @@ dependencies = [ [[package]] name = "flat" version = "0.0.0" +dependencies = [ + "anyhow", + "thiserror", +] [[package]] name = "hashbrown" @@ -289,7 +293,6 @@ checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" name = "uplc" version = "0.1.0" dependencies = [ - "anyhow", "combine", "flat", "hex", diff --git a/crates/flat/Cargo.toml b/crates/flat/Cargo.toml index e69e2d8a..1720ee99 100644 --- a/crates/flat/Cargo.toml +++ b/crates/flat/Cargo.toml @@ -5,4 +5,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] \ No newline at end of file +[dependencies] +anyhow = "1.0.57" +thiserror = "1.0.31" diff --git a/crates/flat/src/decode.rs b/crates/flat/src/decode.rs index ac9d641c..0cd2e4ab 100644 --- a/crates/flat/src/decode.rs +++ b/crates/flat/src/decode.rs @@ -1,11 +1,17 @@ -use crate::{decoder::Decoder, filler::Filler}; +mod decoder; +mod error; + +use crate::filler::Filler; + +pub use decoder::Decoder; +pub use error::Error; pub trait Decode<'b>: Sized { - fn decode(d: &mut Decoder) -> Result; + fn decode(d: &mut Decoder) -> Result; } impl Decode<'_> for Filler { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.filler()?; Ok(Filler::FillerEnd) @@ -13,43 +19,43 @@ impl Decode<'_> for Filler { } impl Decode<'_> for Vec { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.bytes() } } impl Decode<'_> for u8 { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.u8() } } impl Decode<'_> for isize { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.integer() } } impl Decode<'_> for usize { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.word() } } impl Decode<'_> for char { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.char() } } impl Decode<'_> for String { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.utf8() } } impl Decode<'_> for bool { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { d.bool() } } diff --git a/crates/flat/src/decoder.rs b/crates/flat/src/decode/decoder.rs similarity index 67% rename from crates/flat/src/decoder.rs rename to crates/flat/src/decode/decoder.rs index cc30197d..1fb02b73 100644 --- a/crates/flat/src/decoder.rs +++ b/crates/flat/src/decode/decoder.rs @@ -1,5 +1,7 @@ use crate::{decode::Decode, zigzag}; +use super::Error; + pub struct Decoder<'b> { buffer: &'b [u8], used_bits: i64, @@ -15,35 +17,38 @@ impl<'b> Decoder<'b> { } } - pub fn decode>(&mut self) -> Result { + /// Encode any type that implements [`Decode`]. + pub fn decode>(&mut self) -> Result { T::decode(self) } - pub fn integer(&mut self) -> Result { + pub fn integer(&mut self) -> Result { Ok(zigzag::to_isize(self.word()?)) } - pub fn bool(&mut self) -> Result { + pub fn bool(&mut self) -> Result { let current_byte = self.buffer[self.pos]; let b = 0 != (current_byte & (128 >> self.used_bits)); self.increment_buffer_by_bit(); Ok(b) } - pub fn u8(&mut self) -> Result { + pub fn u8(&mut self) -> Result { self.bits8(8) } - pub fn bytes(&mut self) -> Result, String> { + pub fn bytes(&mut self) -> Result, Error> { self.filler()?; self.byte_array() } - pub fn char(&mut self) -> Result { - Ok(char::from_u32(self.word()? as u32).unwrap()) + pub fn char(&mut self) -> Result { + let character = self.word()? as u32; + + char::from_u32(character).ok_or(Error::DecodeChar(character)) } - pub fn string(&mut self) -> Result { + pub fn string(&mut self) -> Result { let mut s = String::new(); while self.bit()? { s += &self.char()?.to_string(); @@ -51,17 +56,17 @@ impl<'b> Decoder<'b> { Ok(s) } - pub fn utf8(&mut self) -> Result { + pub fn utf8(&mut self) -> Result { // TODO: Better Error Handling - Ok(String::from_utf8(Vec::::decode(self)?).unwrap()) + String::from_utf8(Vec::::decode(self)?).map_err(Error::from) } - pub fn filler(&mut self) -> Result<(), String> { + pub fn filler(&mut self) -> Result<(), Error> { while self.zero()? {} Ok(()) } - pub fn word(&mut self) -> Result { + pub fn word(&mut self) -> Result { let mut leading_bit = 1; let mut final_word: usize = 0; let mut shl: usize = 0; @@ -78,8 +83,8 @@ impl<'b> Decoder<'b> { pub fn decode_list_with>( &mut self, - decoder_func: for<'r> fn(&'r mut Decoder) -> Result, - ) -> Result, String> { + decoder_func: for<'r> fn(&'r mut Decoder) -> Result, + ) -> Result, Error> { let mut vec_array: Vec = Vec::new(); while self.bit()? { vec_array.push(decoder_func(self)?) @@ -87,46 +92,60 @@ impl<'b> Decoder<'b> { Ok(vec_array) } - fn zero(&mut self) -> Result { + fn zero(&mut self) -> Result { let current_bit = self.bit()?; + Ok(!current_bit) } - fn bit(&mut self) -> Result { + fn bit(&mut self) -> Result { if self.pos >= self.buffer.len() { - return Err("DecoderState: Reached end of buffer".to_string()); + return Err(Error::EndOfBuffer); } + let b = self.buffer[self.pos] & (128 >> self.used_bits) > 0; + self.increment_buffer_by_bit(); + Ok(b) } - fn byte_array(&mut self) -> Result, String> { + fn byte_array(&mut self) -> Result, Error> { if self.used_bits != 0 { - return Err("DecoderState.byteArray: Buffer is not byte aligned".to_string()); + return Err(Error::BufferNotByteAligned); } + self.ensure_bytes(1)?; + let mut blk_len = self.buffer[self.pos]; + self.pos += 1; + let mut blk_array: Vec = Vec::new(); + while blk_len != 0 { self.ensure_bytes(blk_len as usize + 1)?; + let decoded_array = &self.buffer[self.pos..self.pos + blk_len as usize]; + blk_array.extend(decoded_array); + self.pos += blk_len as usize; + blk_len = self.buffer[self.pos]; } + Ok(blk_array) } // can decode up to a max of 8 bits - pub fn bits8(&mut self, num_bits: usize) -> Result { + pub fn bits8(&mut self, num_bits: usize) -> Result { if num_bits > 8 { - return Err( - "Decoder.bits8: incorrect value of num_bits - must be less than 9".to_string(), - ); + return Err(Error::IncorrectNumBits); } + self.ensure_bits(num_bits)?; + let unused_bits = 8 - self.used_bits as usize; let leading_zeroes = 8 - num_bits; let r = (self.buffer[self.pos] << self.used_bits as usize) >> leading_zeroes; @@ -136,30 +155,28 @@ impl<'b> Decoder<'b> { } else { r }; + self.drop_bits(num_bits); + Ok(x) } - fn ensure_bytes(&mut self, required_bytes: usize) -> Result<(), String> { + fn ensure_bytes(&mut self, required_bytes: usize) -> Result<(), Error> { if required_bytes as isize > self.buffer.len() as isize - self.pos as isize { - return Err(format!( - "DecoderState: Not enough data available: {:#?} - required bytes {}", - self.buffer, required_bytes - )); + Err(Error::NotEnoughBytes(required_bytes)) + } else { + Ok(()) } - Ok(()) } - fn ensure_bits(&mut self, required_bits: usize) -> Result<(), String> { + fn ensure_bits(&mut self, required_bits: usize) -> Result<(), Error> { if required_bits as isize > (self.buffer.len() as isize - self.pos as isize) * 8 - self.used_bits as isize { - return Err(format!( - "DecoderState: Not enough data available: {:#?} - required bits {}", - self.buffer, required_bits - )); + Err(Error::NotEnoughBits(required_bits)) + } else { + Ok(()) } - Ok(()) } fn drop_bits(&mut self, num_bits: usize) { diff --git a/crates/flat/src/decode/error.rs b/crates/flat/src/decode/error.rs new file mode 100644 index 00000000..fcf90b97 --- /dev/null +++ b/crates/flat/src/decode/error.rs @@ -0,0 +1,23 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Reached end of buffer")] + EndOfBuffer, + #[error("Buffer is not byte aligned")] + BufferNotByteAligned, + #[error("Incorrect value of num_bits, must be less than 9")] + IncorrectNumBits, + #[error("Not enough data available, required {0} bytes")] + NotEnoughBytes(usize), + #[error("Not enough data available, required {0} bits")] + NotEnoughBits(usize), + #[error(transparent)] + DecodeUtf8(#[from] std::string::FromUtf8Error), + #[error("Decoding u32 to char {0}")] + DecodeChar(u32), + #[error("{0}")] + Message(String), + #[error(transparent)] + Custom(#[from] anyhow::Error), +} diff --git a/crates/flat/src/encode.rs b/crates/flat/src/encode.rs index a2ae05bb..4d1706dc 100644 --- a/crates/flat/src/encode.rs +++ b/crates/flat/src/encode.rs @@ -1,11 +1,17 @@ -use crate::{encoder::Encoder, filler::Filler}; +mod encoder; +mod error; + +use crate::filler::Filler; + +pub use encoder::Encoder; +pub use error::Error; pub trait Encode { - fn encode(&self, e: &mut Encoder) -> Result<(), String>; + fn encode(&self, e: &mut Encoder) -> Result<(), Error>; } impl Encode for bool { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.bool(*self); Ok(()) @@ -13,7 +19,7 @@ impl Encode for bool { } impl Encode for u8 { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.u8(*self)?; Ok(()) @@ -21,15 +27,15 @@ impl Encode for u8 { } impl Encode for isize { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { - e.integer(*self)?; + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { + e.integer(*self); Ok(()) } } impl Encode for usize { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.word(*self); Ok(()) @@ -37,15 +43,15 @@ impl Encode for usize { } impl Encode for char { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { - e.char(*self)?; + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { + e.char(*self); Ok(()) } } impl Encode for &str { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.utf8(self)?; Ok(()) @@ -53,7 +59,7 @@ impl Encode for &str { } impl Encode for String { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.utf8(self)?; Ok(()) @@ -61,7 +67,7 @@ impl Encode for String { } impl Encode for Vec { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.bytes(self)?; Ok(()) @@ -69,7 +75,7 @@ impl Encode for Vec { } impl Encode for &[u8] { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.bytes(self)?; Ok(()) @@ -77,7 +83,7 @@ impl Encode for &[u8] { } impl Encode for Box { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { self.as_ref().encode(e)?; Ok(()) @@ -85,7 +91,7 @@ impl Encode for Box { } impl Encode for Filler { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), Error> { e.filler(); Ok(()) diff --git a/crates/flat/src/encoder.rs b/crates/flat/src/encode/encoder.rs similarity index 85% rename from crates/flat/src/encoder.rs rename to crates/flat/src/encode/encoder.rs index 099e7f25..4f372d63 100644 --- a/crates/flat/src/encoder.rs +++ b/crates/flat/src/encode/encoder.rs @@ -1,5 +1,7 @@ use crate::{encode::Encode, zigzag}; +use super::Error; + pub struct Encoder { pub buffer: Vec, // Int @@ -24,12 +26,13 @@ impl Encoder { } /// Encode any type that implements [`Encode`]. - pub fn encode(&mut self, x: T) -> Result<&mut Self, String> { + pub fn encode(&mut self, x: T) -> Result<&mut Self, Error> { x.encode(self)?; + Ok(self) } - pub fn u8(&mut self, x: u8) -> Result<&mut Self, String> { + pub fn u8(&mut self, x: u8) -> Result<&mut Self, Error> { if self.used_bits == 0 { self.current_byte = x; self.next_word(); @@ -51,93 +54,54 @@ impl Encoder { self } - pub fn bytes(&mut self, x: &[u8]) -> Result<&mut Self, String> { + pub fn bytes(&mut self, x: &[u8]) -> Result<&mut Self, Error> { // use filler to write current buffer so bits used gets reset self.filler(); + self.byte_array(x) } - pub fn byte_array(&mut self, arr: &[u8]) -> Result<&mut Self, String> { + pub fn byte_array(&mut self, arr: &[u8]) -> Result<&mut Self, Error> { if self.used_bits != 0 { - return Err("Buffer is not byte aligned".to_string()); + return Err(Error::BufferNotByteAligned); } + self.write_blk(arr, &mut 0); + Ok(self) } - pub fn integer(&mut self, i: isize) -> Result<&mut Self, String> { + pub fn integer(&mut self, i: isize) -> &mut Self { let i = zigzag::to_usize(i); + self.word(i); - Ok(self) + + self } - pub fn char(&mut self, c: char) -> Result<&mut Self, String> { + pub fn char(&mut self, c: char) -> &mut Self { self.word(c as usize); - Ok(self) + + self } + // TODO: Do we need this? - pub fn string(&mut self, s: &str) -> Result<&mut Self, String> { + pub fn string(&mut self, s: &str) -> &mut Self { for i in s.chars() { self.one(); - self.char(i)?; + self.char(i); } self.zero(); - Ok(self) + self } - pub fn utf8(&mut self, s: &str) -> Result<&mut Self, String> { + pub fn utf8(&mut self, s: &str) -> Result<&mut Self, Error> { self.bytes(s.as_bytes()) } - fn zero(&mut self) { - if self.used_bits == 7 { - self.next_word(); - } else { - self.used_bits += 1; - } - } - - fn one(&mut self) { - if self.used_bits == 7 { - self.current_byte |= 1; - self.next_word(); - } else { - self.current_byte |= 128 >> self.used_bits; - self.used_bits += 1; - } - } - - fn byte_unaligned(&mut self, x: u8) { - let x_shift = self.current_byte | (x >> self.used_bits); - self.buffer.push(x_shift); - - self.current_byte = x << (8 - self.used_bits); - } - - fn next_word(&mut self) { - self.buffer.push(self.current_byte); - - self.current_byte = 0; - self.used_bits = 0; - } - - fn write_blk(&mut self, arr: &[u8], src_ptr: &mut usize) { - let src_len = arr.len() - *src_ptr; - let blk_len = src_len.min(255); - self.buffer.push(blk_len as u8); - if blk_len == 0 { - return; - } - - self.buffer.extend(&arr[*src_ptr..blk_len]); - - *src_ptr += blk_len; - self.write_blk(arr, src_ptr); - } - - pub fn word(&mut self, c: usize) { + pub fn word(&mut self, c: usize) -> &mut Self { loop { let mut w = (c & 127) as u8; let c = c >> 7; @@ -151,22 +115,26 @@ impl Encoder { break; } } + + self } pub fn encode_list_with( &mut self, - encoder_func: for<'r> fn(u8, &'r mut Encoder) -> Result<(), String>, list: Vec, - ) -> Result<(), String> { + encoder_func: for<'r> fn(u8, &'r mut Encoder) -> Result<(), Error>, + ) -> Result<&mut Self, Error> { for item in list { self.one(); encoder_func(item, self)?; } + self.zero(); - Ok(()) + + Ok(self) } - pub fn bits(&mut self, num_bits: i64, val: u8) { + pub fn bits(&mut self, num_bits: i64, val: u8) -> &mut Self { match (num_bits, val) { (1, 0) => self.zero(), (1, 1) => self.one(), @@ -207,10 +175,63 @@ impl Encoder { } } } + + self } - pub(crate) fn filler(&mut self) { + pub(crate) fn filler(&mut self) -> &mut Self { self.current_byte |= 1; self.next_word(); + + self + } + + fn zero(&mut self) { + if self.used_bits == 7 { + self.next_word(); + } else { + self.used_bits += 1; + } + } + + fn one(&mut self) { + if self.used_bits == 7 { + self.current_byte |= 1; + self.next_word(); + } else { + self.current_byte |= 128 >> self.used_bits; + self.used_bits += 1; + } + } + + fn byte_unaligned(&mut self, x: u8) { + let x_shift = self.current_byte | (x >> self.used_bits); + self.buffer.push(x_shift); + + self.current_byte = x << (8 - self.used_bits); + } + + fn next_word(&mut self) { + self.buffer.push(self.current_byte); + + self.current_byte = 0; + self.used_bits = 0; + } + + fn write_blk(&mut self, arr: &[u8], src_ptr: &mut usize) { + let src_len = arr.len() - *src_ptr; + let blk_len = src_len.min(255); + + self.buffer.push(blk_len as u8); + + if blk_len == 0 { + return; + } + + self.buffer.extend(&arr[*src_ptr..blk_len]); + + *src_ptr += blk_len; + + self.write_blk(arr, src_ptr); } } diff --git a/crates/flat/src/encode/error.rs b/crates/flat/src/encode/error.rs new file mode 100644 index 00000000..988dfda7 --- /dev/null +++ b/crates/flat/src/encode/error.rs @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Buffer is not byte aligned")] + BufferNotByteAligned, + #[error("{0}")] + Message(String), + #[error(transparent)] + Custom(#[from] anyhow::Error), +} diff --git a/crates/flat/src/filler.rs b/crates/flat/src/filler.rs index 7e33d2c1..0efe8db9 100644 --- a/crates/flat/src/filler.rs +++ b/crates/flat/src/filler.rs @@ -1,13 +1,13 @@ pub enum Filler { - // FillerStart(Box), + FillerStart(Box), FillerEnd, } -// impl Filler { -// pub fn len(&self) -> usize { -// match self { -// Filler::FillerStart(f) => f.len() + 1, -// Filler::FillerEnd => 1, -// } -// } -// } +impl Filler { + pub fn length(&self) -> usize { + match self { + Filler::FillerStart(f) => f.length() + 1, + Filler::FillerEnd => 1, + } + } +} diff --git a/crates/flat/src/lib.rs b/crates/flat/src/lib.rs index 8a11995b..1a44fe46 100644 --- a/crates/flat/src/lib.rs +++ b/crates/flat/src/lib.rs @@ -1,31 +1,27 @@ mod decode; -mod decoder; mod encode; -mod encoder; -mod filler; +pub mod filler; pub mod zigzag; pub mod en { pub use super::encode::*; - pub use super::encoder::*; } 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> { + fn flat(&self) -> Result, en::Error> { encode(self) } - fn unflat(bytes: &'b [u8]) -> Result { + fn unflat(bytes: &'b [u8]) -> Result { decode(bytes) } } -pub fn encode(value: &T) -> Result, String> +pub fn encode(value: &T) -> Result, en::Error> where T: en::Encode, { @@ -37,7 +33,7 @@ where Ok(e.buffer) } -pub fn decode<'b, T>(bytes: &'b [u8]) -> Result +pub fn decode<'b, T>(bytes: &'b [u8]) -> Result where T: de::Decode<'b>, { diff --git a/crates/uplc/Cargo.toml b/crates/uplc/Cargo.toml index eccca392..ef1dcbc6 100644 --- a/crates/uplc/Cargo.toml +++ b/crates/uplc/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.57" combine = "4.6.4" flat = { path = "../flat" } hex = "0.4.3" diff --git a/crates/uplc/src/builtins.rs b/crates/uplc/src/builtins.rs index fbcebfa6..00c9d723 100644 --- a/crates/uplc/src/builtins.rs +++ b/crates/uplc/src/builtins.rs @@ -1,3 +1,4 @@ +use flat::de; use strum_macros::EnumString; #[repr(u8)] @@ -80,6 +81,8 @@ pub enum DefaultFunction { } impl TryFrom for DefaultFunction { + type Error = de::Error; + fn try_from(v: u8) -> Result { match v { v if v == DefaultFunction::AddInteger as u8 => Ok(DefaultFunction::AddInteger), @@ -184,9 +187,7 @@ impl TryFrom for DefaultFunction { v if v == DefaultFunction::MkPairData as u8 => Ok(DefaultFunction::MkPairData), v if v == DefaultFunction::MkNilData as u8 => Ok(DefaultFunction::MkNilData), v if v == DefaultFunction::MkNilPairData as u8 => Ok(DefaultFunction::MkNilPairData), - _ => Err("Default Function not found".to_string()), + _ => Err(de::Error::Message("Default Function not found".to_string())), } } - - type Error = String; } diff --git a/crates/uplc/src/debruijn.rs b/crates/uplc/src/debruijn.rs index 294b184a..f37a6a6b 100644 --- a/crates/uplc/src/debruijn.rs +++ b/crates/uplc/src/debruijn.rs @@ -9,7 +9,7 @@ struct Level(usize); #[derive(Error, Debug)] pub enum Error { - #[error("Free Unique: `{0}`")] + #[error("Free Unique `{0}`")] FreeUnique(Unique), } diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index 846a8b0a..d4e16abf 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -1,8 +1,6 @@ -use anyhow::anyhow; - use flat::{ - de::{Decode, Decoder}, - en::{Encode, Encoder}, + de::{self, Decode, Decoder}, + en::{self, Encode, Encoder}, Flat, }; @@ -16,8 +14,8 @@ const CONST_TAG_WIDTH: u32 = 4; const TERM_TAG_WIDTH: u32 = 4; pub trait Binder<'b>: Encode + Decode<'b> { - fn binder_encode(&self, e: &mut Encoder) -> Result<(), String>; - fn binder_decode(d: &mut Decoder) -> Result; + fn binder_encode(&self, e: &mut Encoder) -> Result<(), en::Error>; + fn binder_decode(d: &mut Decoder) -> Result; } impl<'b, T> Flat<'b> for Program where T: Binder<'b> {} @@ -28,12 +26,12 @@ where { // 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 to_flat(&self) -> Result, en::Error> { + self.flat() } - pub fn flat_hex(&self) -> anyhow::Result { - let bytes = self.flat().map_err(|err| anyhow!("{}", err))?; + pub fn flat_hex(&self) -> Result { + let bytes = self.flat()?; let hex = hex::encode(&bytes); @@ -45,7 +43,7 @@ impl<'b, T> Encode for Program where T: Binder<'b>, { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { let (major, minor, patch) = self.version; major.encode(e)?; @@ -62,7 +60,7 @@ impl<'b, T> Decode<'b> for Program where T: Binder<'b>, { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { let version = (usize::decode(d)?, usize::decode(d)?, usize::decode(d)?); let term = Term::decode(d)?; Ok(Program { version, term }) @@ -73,7 +71,7 @@ impl<'b, T> Encode for Term where T: Binder<'b>, { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { match self { Term::Var(name) => { encode_term_tag(0, e)?; @@ -125,7 +123,7 @@ impl<'b, T> Decode<'b> for Term where T: Binder<'b>, { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { match decode_term_tag(d)? { 0 => Ok(Term::Var(T::decode(d)?)), 1 => Ok(Term::Delay(Box::new(Term::decode(d)?))), @@ -142,13 +140,16 @@ where 5 => Ok(Term::Force(Box::new(Term::decode(d)?))), 6 => Ok(Term::Error), 7 => Ok(Term::Builtin(DefaultFunction::decode(d)?)), - x => Err(format!("Unknown term constructor tag: {}", x)), + x => Err(de::Error::Message(format!( + "Unknown term constructor tag: {}", + x + ))), } } } impl Encode for &Constant { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { match self { Constant::Integer(i) => { encode_constant(0, e)?; @@ -182,20 +183,23 @@ impl Encode for &Constant { } impl<'b> Decode<'b> for Constant { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { match decode_constant(d)? { 0 => Ok(Constant::Integer(isize::decode(d)?)), 1 => Ok(Constant::ByteString(Vec::::decode(d)?)), 2 => Ok(Constant::String(String::decode(d)?)), 3 => Ok(Constant::Unit), 4 => Ok(Constant::Bool(bool::decode(d)?)), - x => Err(format!("Unknown constant constructor tag: {}", x)), + x => Err(de::Error::Message(format!( + "Unknown constant constructor tag: {}", + x + ))), } } } impl Encode for Unique { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { isize::from(*self).encode(e)?; Ok(()) @@ -203,13 +207,13 @@ impl Encode for Unique { } impl<'b> Decode<'b> for Unique { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { Ok(isize::decode(d)?.into()) } } impl Encode for Name { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { self.text.encode(e)?; self.unique.encode(e)?; @@ -218,7 +222,7 @@ impl Encode for Name { } impl<'b> Decode<'b> for Name { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { Ok(Name { text: String::decode(d)?, unique: Unique::decode(d)?, @@ -227,19 +231,19 @@ impl<'b> Decode<'b> for Name { } impl<'b> Binder<'b> for Name { - fn binder_encode(&self, e: &mut Encoder) -> Result<(), String> { + fn binder_encode(&self, e: &mut Encoder) -> Result<(), en::Error> { self.encode(e)?; Ok(()) } - fn binder_decode(d: &mut Decoder) -> Result { + fn binder_decode(d: &mut Decoder) -> Result { Name::decode(d) } } impl Encode for NamedDeBruijn { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { self.text.encode(e)?; self.index.encode(e)?; @@ -248,7 +252,7 @@ impl Encode for NamedDeBruijn { } impl<'b> Decode<'b> for NamedDeBruijn { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { Ok(NamedDeBruijn { text: String::decode(d)?, index: DeBruijn::decode(d)?, @@ -257,13 +261,13 @@ impl<'b> Decode<'b> for NamedDeBruijn { } impl<'b> Binder<'b> for NamedDeBruijn { - fn binder_encode(&self, e: &mut Encoder) -> Result<(), String> { + fn binder_encode(&self, e: &mut Encoder) -> Result<(), en::Error> { self.text.encode(e)?; Ok(()) } - fn binder_decode(d: &mut Decoder) -> Result { + fn binder_decode(d: &mut Decoder) -> Result { Ok(NamedDeBruijn { text: String::decode(d)?, index: DeBruijn::new(0), @@ -272,7 +276,7 @@ impl<'b> Binder<'b> for NamedDeBruijn { } impl Encode for DeBruijn { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { usize::from(*self).encode(e)?; Ok(()) @@ -280,23 +284,23 @@ impl Encode for DeBruijn { } impl<'b> Decode<'b> for DeBruijn { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { Ok(usize::decode(d)?.into()) } } impl<'b> Binder<'b> for DeBruijn { - fn binder_encode(&self, _: &mut Encoder) -> Result<(), String> { + fn binder_encode(&self, _: &mut Encoder) -> Result<(), en::Error> { Ok(()) } - fn binder_decode(_d: &mut Decoder) -> Result { + fn binder_decode(_d: &mut Decoder) -> Result { Ok(DeBruijn::new(0)) } } impl Encode for DefaultFunction { - fn encode(&self, e: &mut Encoder) -> Result<(), String> { + fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { e.bits(BUILTIN_TAG_WIDTH as i64, self.clone() as u8); Ok(()) @@ -304,53 +308,55 @@ impl Encode for DefaultFunction { } impl<'b> Decode<'b> for DefaultFunction { - fn decode(d: &mut Decoder) -> Result { + fn decode(d: &mut Decoder) -> Result { let builtin_tag = d.bits8(BUILTIN_TAG_WIDTH as usize)?; builtin_tag.try_into() } } -fn encode_term_tag(tag: u8, e: &mut Encoder) -> Result<(), String> { +fn encode_term_tag(tag: u8, e: &mut Encoder) -> Result<(), en::Error> { safe_encode_bits(TERM_TAG_WIDTH, tag, e) } -fn decode_term_tag(d: &mut Decoder) -> Result { +fn decode_term_tag(d: &mut Decoder) -> Result { d.bits8(TERM_TAG_WIDTH as usize) } -fn safe_encode_bits(num_bits: u32, byte: u8, e: &mut Encoder) -> Result<(), String> { +fn safe_encode_bits(num_bits: u32, byte: u8, e: &mut Encoder) -> Result<(), en::Error> { if 2_u8.pow(num_bits) < byte { - Err(format!( + Err(en::Error::Message(format!( "Overflow detected, cannot fit {} in {} bits.", byte, num_bits - )) + ))) } else { e.bits(num_bits as i64, byte); Ok(()) } } -pub fn encode_constant(tag: u8, e: &mut Encoder) -> Result<(), String> { - e.encode_list_with(encode_constant_tag, [tag].to_vec()) +pub fn encode_constant(tag: u8, e: &mut Encoder) -> Result<(), en::Error> { + e.encode_list_with([tag].to_vec(), encode_constant_tag)?; + + Ok(()) } -pub fn decode_constant(d: &mut Decoder) -> Result { +pub fn decode_constant(d: &mut Decoder) -> Result { let u8_list = d.decode_list_with(decode_constant_tag)?; if u8_list.len() > 1 { - Err( + Err(de::Error::Message( "Improper encoding on constant tag. Should be list of one item encoded in 4 bits" .to_string(), - ) + )) } else { Ok(u8_list[0]) } } -pub fn encode_constant_tag(tag: u8, e: &mut Encoder) -> Result<(), String> { +pub fn encode_constant_tag(tag: u8, e: &mut Encoder) -> Result<(), en::Error> { safe_encode_bits(CONST_TAG_WIDTH, tag, e) } -pub fn decode_constant_tag(d: &mut Decoder) -> Result { +pub fn decode_constant_tag(d: &mut Decoder) -> Result { d.bits8(CONST_TAG_WIDTH as usize) } diff --git a/crates/uplc/src/parser.rs b/crates/uplc/src/parser.rs index 5e58f90b..c7371175 100644 --- a/crates/uplc/src/parser.rs +++ b/crates/uplc/src/parser.rs @@ -1,7 +1,9 @@ use std::{collections::HashMap, str::FromStr}; use combine::{ - attempt, between, choice, many1, + attempt, between, choice, + error::StringStreamError, + many1, parser::{ char::{alpha_num, digit, hex_digit, space, spaces, string}, combinator::no_partial, @@ -46,18 +48,15 @@ impl ParserState { } } -pub fn program(src: &str) -> anyhow::Result> { +pub fn program(src: &str) -> Result, StringStreamError> { let mut parser = program_(); - let result = parser.parse(state::Stream { + let (program, _) = parser.parse(state::Stream { stream: position::Stream::new(src.trim()), state: ParserState::new(), - }); + })?; - match result { - Ok((program, _)) => Ok(program), - Err(err) => Err(anyhow::anyhow!("{}", err)), - } + Ok(program) } fn program_() -> impl Parser, Output = Program>