feat: spec complaint program encoding
Co-authored-by: rvcas <x@rvcas.dev>
This commit is contained in:
parent
2e130ac5f0
commit
c01469ea51
|
@ -11,7 +11,13 @@ fn main() -> anyhow::Result<()> {
|
|||
|
||||
println!("{:#?}", program);
|
||||
|
||||
println!("{:?}", program.flat()?);
|
||||
let flat_bytes = program.flat()?;
|
||||
|
||||
for byte in flat_bytes {
|
||||
print!("{:08b} ", byte);
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
println!("{}", program.flat_hex()?);
|
||||
|
||||
|
|
|
@ -28,6 +28,14 @@ impl Encode for isize {
|
|||
}
|
||||
}
|
||||
|
||||
impl Encode for usize {
|
||||
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
|
||||
e.word(*self);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for char {
|
||||
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
|
||||
e.char(*self)?;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::encode::Encode;
|
||||
use crate::{encode::Encode, zigzag};
|
||||
|
||||
pub struct Encoder {
|
||||
pub buffer: Vec<u8>,
|
||||
|
@ -66,12 +66,13 @@ impl Encoder {
|
|||
}
|
||||
|
||||
pub fn integer(&mut self, i: isize) -> Result<&mut Self, String> {
|
||||
let i = zigzag::to_usize(i);
|
||||
self.word(i);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn char(&mut self, c: char) -> Result<&mut Self, String> {
|
||||
self.word(c as isize);
|
||||
self.word(c as usize);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
|
@ -132,7 +133,7 @@ impl Encoder {
|
|||
self.write_blk(arr, src_ptr);
|
||||
}
|
||||
|
||||
fn word(&mut self, c: isize) {
|
||||
pub fn word(&mut self, c: usize) {
|
||||
loop {
|
||||
let mut w = (c & 127) as u8;
|
||||
let c = c >> 7;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod encode;
|
||||
mod encoder;
|
||||
mod filler;
|
||||
mod zigzag;
|
||||
|
||||
pub mod en {
|
||||
pub use super::encode::*;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
pub fn to_usize(x: isize) -> usize {
|
||||
let double_x = x << 1;
|
||||
|
||||
if x >= 0 {
|
||||
double_x as usize
|
||||
} else {
|
||||
(-double_x - 1) as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_isize(u: usize) -> isize {
|
||||
let s = u as isize;
|
||||
|
||||
(s >> 1) ^ -(s & 1)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn convert() {
|
||||
let n = -12;
|
||||
let unsigned = super::to_usize(n);
|
||||
let signed = super::to_isize(unsigned);
|
||||
|
||||
assert_eq!(n, signed)
|
||||
}
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
(program 1.0.0
|
||||
(con bool False)
|
||||
(program 11.22.33
|
||||
(con integer 11)
|
||||
)
|
|
@ -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]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue