feat: spec complaint program encoding

Co-authored-by: rvcas <x@rvcas.dev>
This commit is contained in:
Kasey White
2022-05-27 22:32:43 -04:00
parent 2e130ac5f0
commit c01469ea51
8 changed files with 99 additions and 22 deletions

View File

@@ -8,7 +8,7 @@ const CONST_TAG_WIDTH: u32 = 4;
#[derive(Debug, Clone)]
pub struct Program {
pub version: String,
pub version: (usize, usize, usize),
pub term: Term,
}
@@ -97,7 +97,12 @@ pub fn encode_constant_tag(tag: u8, e: &mut Encoder) -> Result<(), String> {
impl Encode for Program {
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
self.version.encode(e)?;
let (major, minor, patch) = self.version;
major.encode(e)?;
minor.encode(e)?;
patch.encode(e)?;
self.term.encode(e)?;
Ok(())
@@ -123,7 +128,6 @@ impl Encode for Term {
encode_term_tag(2, e)?;
// need to create encoding for Binder
todo!();
body.encode(e)?;
}
Term::Apply { function, argument } => {
encode_term_tag(3, e)?;
@@ -169,12 +173,17 @@ impl Encode for &Constant {
}
Constant::String(s) => {
encode_constant(2, e)?;
s.encode(e)?;
s.as_bytes().encode(e)?;
}
// there is no char constant tag
Constant::Char(c) => {
c.encode(e)?;
todo!()
let mut b = [0; 4];
let s = c.encode_utf8(&mut b);
s.as_bytes().encode(e)?;
}
Constant::Unit => encode_constant(3, e)?,
Constant::Bool(b) => {
@@ -186,3 +195,23 @@ impl Encode for &Constant {
Ok(())
}
}
#[cfg(test)]
mod test {
use super::{Constant, Program, Term};
#[test]
fn flat_encode_integer() {
let program = Program {
version: (11, 22, 33),
term: Term::Constant(Constant::Integer(11)),
};
let bytes = program.flat().unwrap();
assert_eq!(
bytes,
vec![0b00001011, 0b00010110, 0b00100001, 0b01001000, 0b00000101, 0b10000001]
)
}
}

View File

@@ -16,7 +16,7 @@ use crate::{
pub fn program(src: &str) -> anyhow::Result<Program> {
let mut parser = program_();
let result = parser.easy_parse(position::Stream::new(src));
let result = parser.easy_parse(position::Stream::new(src.trim()));
match result {
Ok((program, _)) => Ok(program),
@@ -37,7 +37,7 @@ where
between(token('('), token(')'), prog).skip(spaces())
}
fn version<Input>() -> impl Parser<Input, Output = String>
fn version<Input>() -> impl Parser<Input, Output = (usize, usize, usize)>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@@ -51,7 +51,11 @@ where
)
.map(
|(major, _, minor, _, patch): (String, char, String, char, String)| {
format!("{}.{}.{}", major, minor, patch)
(
major.parse::<usize>().unwrap(),
minor.parse::<usize>().unwrap(),
patch.parse::<usize>().unwrap(),
)
},
)
}
@@ -203,7 +207,7 @@ where
string("integer")
.with(skip_many1(space()))
.with(many1(digit()))
.map(|d: String| Constant::Integer(d.parse::<i64>().unwrap()))
.map(|d: String| Constant::Integer(d.parse::<isize>().unwrap()))
}
fn constant_bytestring<Input>() -> impl Parser<Input, Output = Constant>
@@ -253,18 +257,19 @@ where
#[cfg(test)]
mod test {
use combine::Parser;
const CODE: &str = include_str!("../example/plutus-core");
#[test]
fn parse_program() {
let result = super::program_().parse(CODE);
let code = r#"
(program 11.22.33
(con integer 11)
)
"#;
let result = super::program(code);
assert!(result.is_ok());
let program = result.unwrap().0;
let program = result.unwrap();
assert_eq!(program.version, "1.0.0");
assert_eq!(program.version, (11, 22, 33));
}
}