Skip to content

Commit 34e1243

Browse files
committed
feat: Decode value from compact / padded encoding
Decode a Simplicity value as an associated method of the Value struct. Differentiate between compact and padded encoding.
1 parent 70aefd1 commit 34e1243

File tree

6 files changed

+144
-61
lines changed

6 files changed

+144
-61
lines changed

jets-bench/src/data_structures.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn var_len_buf_from_slice(v: &[u8], mut n: usize) -> Result<Value, Error> {
6363
while n > 0 {
6464
let ty = Final::two_two_n(n);
6565
let v = if v.len() >= (1 << (n + 1)) {
66-
let val = iter.read_value(&ty)?;
66+
let val = Value::from_compact_bits(&mut iter, &ty)?;
6767
Value::some(val)
6868
} else {
6969
Value::none(ty)

src/bit_encoding/bititer.rs

+2-53
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@
99
//! `Iterator<Item=bool>`.
1010
//!
1111
12-
use crate::types::Final;
13-
use crate::{decode, types};
14-
use crate::{Cmr, FailEntropy, Value};
15-
use std::sync::Arc;
12+
use crate::decode;
13+
use crate::{Cmr, FailEntropy};
1614
use std::{error, fmt};
1715

1816
/// Attempted to read from a bit iterator, but there was no more data
@@ -221,55 +219,6 @@ impl<I: Iterator<Item = u8>> BitIter<I> {
221219
Ok(FailEntropy::from_byte_array(ret))
222220
}
223221

224-
/// Decode a value from bits, based on the given type.
225-
pub fn read_value(&mut self, ty: &Final) -> Result<Value, EarlyEndOfStreamError> {
226-
enum State<'a> {
227-
ProcessType(&'a Final),
228-
DoSumL(Arc<Final>),
229-
DoSumR(Arc<Final>),
230-
DoProduct,
231-
}
232-
233-
let mut stack = vec![State::ProcessType(ty)];
234-
let mut result_stack = vec![];
235-
while let Some(state) = stack.pop() {
236-
match state {
237-
State::ProcessType(ty) => match ty.bound() {
238-
types::CompleteBound::Unit => result_stack.push(Value::unit()),
239-
types::CompleteBound::Sum(ref l, ref r) => {
240-
if self.read_bit()? {
241-
stack.push(State::DoSumR(Arc::clone(l)));
242-
stack.push(State::ProcessType(r));
243-
} else {
244-
stack.push(State::DoSumL(Arc::clone(r)));
245-
stack.push(State::ProcessType(l));
246-
}
247-
}
248-
types::CompleteBound::Product(ref l, ref r) => {
249-
stack.push(State::DoProduct);
250-
stack.push(State::ProcessType(r));
251-
stack.push(State::ProcessType(l));
252-
}
253-
},
254-
State::DoSumL(r) => {
255-
let val = result_stack.pop().unwrap();
256-
result_stack.push(Value::left(val, r));
257-
}
258-
State::DoSumR(l) => {
259-
let val = result_stack.pop().unwrap();
260-
result_stack.push(Value::right(l, val));
261-
}
262-
State::DoProduct => {
263-
let val_r = result_stack.pop().unwrap();
264-
let val_l = result_stack.pop().unwrap();
265-
result_stack.push(Value::product(val_l, val_r));
266-
}
267-
}
268-
}
269-
debug_assert_eq!(result_stack.len(), 1);
270-
Ok(result_stack.pop().unwrap())
271-
}
272-
273222
/// Decode a natural number from bits.
274223
///
275224
/// If a bound is specified, then the decoding terminates before trying to

src/bit_machine/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,11 @@ impl BitMachine {
358358
if output_width > 0 {
359359
let out_frame = self.write.last_mut().unwrap();
360360
out_frame.reset_cursor();
361-
let value = out_frame
362-
.as_bit_iter(&self.data)
363-
.read_value(&program.arrow().target)
364-
.expect("Decode value of output frame");
361+
let value = Value::from_padded_bits(
362+
&mut out_frame.as_bit_iter(&self.data),
363+
&program.arrow().target,
364+
)
365+
.expect("Decode value of output frame");
365366

366367
Ok(value)
367368
} else {

src/human_encoding/parse/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::sync::Arc;
77

88
use crate::human_encoding::{Error, ErrorSet, Position, WitnessOrHole};
99
use crate::jet::Jet;
10-
use crate::{node, types};
10+
use crate::{node, types, Value};
1111
use crate::{BitIter, Cmr, FailEntropy};
1212
use santiago::grammar::{Associativity, Grammar};
1313
use santiago::lexer::{Lexeme, LexerRules};
@@ -647,7 +647,7 @@ fn grammar<J: Jet + 'static>() -> Grammar<Ast<J>> {
647647
let ty = types::Final::two_two_n(bit_length.trailing_zeros() as usize);
648648
// unwrap ok here since literally every sequence of bits is a valid
649649
// value for the given type
650-
let value = iter.read_value(&ty).unwrap();
650+
let value = Value::from_compact_bits(&mut iter, &ty).unwrap();
651651
Ast::Expression(Expression {
652652
inner: ExprInner::Inline(node::Inner::Word(value)),
653653
position,

src/node/redeem.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl<J: Jet> RedeemNode<J> {
299299
) -> Result<Value, Self::Error> {
300300
let arrow = data.node.data.arrow();
301301
let target_ty = arrow.target.finalize()?;
302-
self.bits.read_value(&target_ty).map_err(Error::from)
302+
Value::from_compact_bits(self.bits, &target_ty).map_err(Error::from)
303303
}
304304

305305
fn convert_disconnect(

src/value.rs

+133
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use crate::dag::{Dag, DagLike, NoSharing};
99
use crate::types::Final;
1010

11+
use crate::{types, EarlyEndOfStreamError};
1112
use std::collections::VecDeque;
1213
use std::fmt;
1314
use std::hash::Hash;
@@ -388,6 +389,138 @@ impl<'a> Iterator for PaddedBitsIter<'a> {
388389
}
389390
}
390391

392+
trait Padding {
393+
fn read_left_padding<I: Iterator<Item = bool>>(
394+
bits: &mut I,
395+
ty_l: &Final,
396+
ty_r: &Final,
397+
) -> Result<(), EarlyEndOfStreamError>;
398+
399+
fn read_right_padding<I: Iterator<Item = bool>>(
400+
bits: &mut I,
401+
ty_l: &Final,
402+
ty_r: &Final,
403+
) -> Result<(), EarlyEndOfStreamError>;
404+
}
405+
406+
struct CompactEncoding;
407+
struct PaddedEncoding;
408+
409+
impl Padding for CompactEncoding {
410+
fn read_left_padding<I: Iterator<Item = bool>>(
411+
_: &mut I,
412+
_: &Final,
413+
_: &Final,
414+
) -> Result<(), EarlyEndOfStreamError> {
415+
// no padding
416+
Ok(())
417+
}
418+
419+
fn read_right_padding<I: Iterator<Item = bool>>(
420+
_: &mut I,
421+
_: &Final,
422+
_: &Final,
423+
) -> Result<(), EarlyEndOfStreamError> {
424+
// no padding
425+
Ok(())
426+
}
427+
}
428+
429+
impl Padding for PaddedEncoding {
430+
fn read_left_padding<I: Iterator<Item = bool>>(
431+
bits: &mut I,
432+
ty_l: &Final,
433+
ty_r: &Final,
434+
) -> Result<(), EarlyEndOfStreamError> {
435+
for _ in 0..ty_l.pad_left(ty_r) {
436+
let _padding = bits.next().ok_or(EarlyEndOfStreamError)?;
437+
}
438+
Ok(())
439+
}
440+
441+
fn read_right_padding<I: Iterator<Item = bool>>(
442+
bits: &mut I,
443+
ty_l: &Final,
444+
ty_r: &Final,
445+
) -> Result<(), EarlyEndOfStreamError> {
446+
for _ in 0..ty_l.pad_left(ty_r) {
447+
let _padding = bits.next().ok_or(EarlyEndOfStreamError)?;
448+
}
449+
Ok(())
450+
}
451+
}
452+
453+
impl Value {
454+
fn from_bits<I: Iterator<Item = bool>, P: Padding>(
455+
bits: &mut I,
456+
ty: &Final,
457+
) -> Result<Self, EarlyEndOfStreamError> {
458+
enum State<'a> {
459+
ProcessType(&'a Final),
460+
DoSumL(Arc<Final>),
461+
DoSumR(Arc<Final>),
462+
DoProduct,
463+
}
464+
465+
let mut stack = vec![State::ProcessType(ty)];
466+
let mut result_stack = vec![];
467+
while let Some(state) = stack.pop() {
468+
match state {
469+
State::ProcessType(ty) => match ty.bound() {
470+
types::CompleteBound::Unit => result_stack.push(Value::unit()),
471+
types::CompleteBound::Sum(ref l, ref r) => {
472+
if !bits.next().ok_or(EarlyEndOfStreamError)? {
473+
P::read_left_padding(bits, l, r)?;
474+
stack.push(State::DoSumL(Arc::clone(r)));
475+
stack.push(State::ProcessType(l));
476+
} else {
477+
P::read_right_padding(bits, l, r)?;
478+
stack.push(State::DoSumR(Arc::clone(l)));
479+
stack.push(State::ProcessType(r));
480+
}
481+
}
482+
types::CompleteBound::Product(ref l, ref r) => {
483+
stack.push(State::DoProduct);
484+
stack.push(State::ProcessType(r));
485+
stack.push(State::ProcessType(l));
486+
}
487+
},
488+
State::DoSumL(r) => {
489+
let val = result_stack.pop().unwrap();
490+
result_stack.push(Value::left(val, r));
491+
}
492+
State::DoSumR(l) => {
493+
let val = result_stack.pop().unwrap();
494+
result_stack.push(Value::right(l, val));
495+
}
496+
State::DoProduct => {
497+
let val_r = result_stack.pop().unwrap();
498+
let val_l = result_stack.pop().unwrap();
499+
result_stack.push(Value::product(val_l, val_r));
500+
}
501+
}
502+
}
503+
debug_assert_eq!(result_stack.len(), 1);
504+
Ok(result_stack.pop().unwrap())
505+
}
506+
507+
/// Decode a value of the given type from its compact bit encoding.
508+
pub fn from_compact_bits<I: Iterator<Item = bool>>(
509+
bits: &mut I,
510+
ty: &Final,
511+
) -> Result<Self, EarlyEndOfStreamError> {
512+
Self::from_bits::<_, CompactEncoding>(bits, ty)
513+
}
514+
515+
/// Decode a value of the given type from its padded bit encoding.
516+
pub fn from_padded_bits<I: Iterator<Item = bool>>(
517+
bits: &mut I,
518+
ty: &Final,
519+
) -> Result<Self, EarlyEndOfStreamError> {
520+
Self::from_bits::<_, PaddedEncoding>(bits, ty)
521+
}
522+
}
523+
391524
#[cfg(test)]
392525
mod tests {
393526
use super::*;

0 commit comments

Comments
 (0)