Skip to main content

simplicity/
value.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! # Simplicity values
4//!
5//! Simplicity processes data in terms of [`Value`]s,
6//! i.e., inputs, intermediate results and outputs.
7
8use crate::dag::{Dag, DagLike};
9use crate::types::{CompleteBound, Final};
10use crate::{BitIter, Tmr};
11
12use crate::{BitCollector, EarlyEndOfStreamError};
13use core::{cmp, fmt, iter};
14use std::collections::VecDeque;
15use std::hash::Hash;
16use std::sync::Arc;
17
18/// A Simplicity value.
19#[derive(Clone)]
20pub struct Value {
21    /// The underlying data, in "padded" bit-encoded form, with the leftmost
22    /// bits encoded in the most-significant bits. So e.g. right(unit) is 0x80.
23    ///
24    /// We use the padded form, even though it is space-inefficient (sometimes
25    /// significantly so), for a couple reasons: first, this is the representation
26    /// used by the bit machine, so we want encoding/decoding to be as fast as
27    /// possible. Secondly, when destructuring a value (which we need to do during
28    /// scribing and pruning, at least) it is quite difficult to destructure a
29    /// compact-encoded product, since we would need to determine the compact
30    /// bitlengths of the children, and these quantities are not readily available.
31    inner: Arc<[u8]>,
32    /// An offset, in bits, at which the actual data starts. This is useful
33    /// because it allows constructing sub-values of a value without needing
34    /// to construct a new `inner` with all the bits offset.
35    bit_offset: usize,
36    /// The Simplicity type of the value.
37    ty: Arc<Final>,
38}
39
40/// Reference to a value, or to a sub-value of a value.
41#[derive(Debug, Clone, Copy)]
42pub struct ValueRef<'v> {
43    inner: &'v Arc<[u8]>,
44    bit_offset: usize,
45    ty: &'v Arc<Final>,
46}
47
48// Because two equal values may have different bit offsets, we must manually
49// implement the comparison traits. We do so by first comparing types, which
50// is constant overhead (this just compares TMRs). If those match, we know
51// the lengths and structures match, so we then compare the underlying byte
52// iterators.
53impl PartialEq for Value {
54    fn eq(&self, other: &Self) -> bool {
55        self.ty == other.ty && self.raw_byte_iter().eq(other.raw_byte_iter())
56    }
57}
58impl Eq for Value {}
59
60impl PartialOrd for Value {
61    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
62        Some(self.cmp(other))
63    }
64}
65impl Ord for Value {
66    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
67        self.ty
68            .cmp(&other.ty)
69            .then_with(|| self.raw_byte_iter().cmp(other.raw_byte_iter()))
70    }
71}
72
73impl core::hash::Hash for Value {
74    fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
75        b"Simplicity\x1fValue".hash(h);
76        self.ty.hash(h);
77        for val in self.raw_byte_iter() {
78            val.hash(h);
79        }
80    }
81}
82
83impl DagLike for ValueRef<'_> {
84    type Node = Self;
85
86    fn data(&self) -> &Self {
87        self
88    }
89
90    fn as_dag_node(&self) -> Dag<Self> {
91        if let Some((left, right)) = self.as_product() {
92            Dag::Binary(left, right)
93        } else if let Some(left) = self.as_left() {
94            Dag::Unary(left)
95        } else if let Some(right) = self.as_right() {
96            Dag::Unary(right)
97        } else {
98            assert!(self.ty.is_unit());
99            Dag::Nullary
100        }
101    }
102}
103
104impl<'v> ValueRef<'v> {
105    /// Check if the value is a unit.
106    pub fn is_unit(&self) -> bool {
107        self.ty.is_unit()
108    }
109
110    /// Helper function to read the first bit of a value
111    ///
112    /// If the first bit is not available (e.g. if the value has zero size)
113    /// then returns None.
114    fn first_bit(&self) -> Option<bool> {
115        let mask = if self.bit_offset % 8 == 0 {
116            0x80
117        } else {
118            1 << (7 - self.bit_offset % 8)
119        };
120        let res = self
121            .inner
122            .get(self.bit_offset / 8)
123            .map(|x| x & mask == mask);
124        res
125    }
126
127    /// Access the inner value of a left sum value.
128    pub fn as_left(&self) -> Option<Self> {
129        if self.first_bit() == Some(false) {
130            if let Some((lty, rty)) = self.ty.as_sum() {
131                let sum_width = 1 + cmp::max(lty.bit_width(), rty.bit_width());
132                Some(Self {
133                    inner: self.inner,
134                    bit_offset: self.bit_offset + sum_width - lty.bit_width(),
135                    ty: lty,
136                })
137            } else {
138                None
139            }
140        } else {
141            None
142        }
143    }
144
145    /// Access the inner value of a right sum value.
146    pub fn as_right(&self) -> Option<Self> {
147        if self.first_bit() == Some(true) {
148            if let Some((lty, rty)) = self.ty.as_sum() {
149                let sum_width = 1 + cmp::max(lty.bit_width(), rty.bit_width());
150                Some(Self {
151                    inner: self.inner,
152                    bit_offset: self.bit_offset + sum_width - rty.bit_width(),
153                    ty: rty,
154                })
155            } else {
156                None
157            }
158        } else {
159            None
160        }
161    }
162
163    /// Access the inner values of a product value.
164    pub fn as_product(&self) -> Option<(Self, Self)> {
165        if let Some((lty, rty)) = self.ty.as_product() {
166            Some((
167                Self {
168                    inner: self.inner,
169                    bit_offset: self.bit_offset,
170                    ty: lty,
171                },
172                Self {
173                    inner: self.inner,
174                    bit_offset: self.bit_offset + lty.bit_width(),
175                    ty: rty,
176                },
177            ))
178        } else {
179            None
180        }
181    }
182
183    /// Convert the reference back to a value.
184    pub fn to_value(&self) -> Value {
185        Value {
186            inner: Arc::clone(self.inner),
187            bit_offset: self.bit_offset,
188            ty: Arc::clone(self.ty),
189        }
190    }
191
192    /// Try to convert the value into a word.
193    pub fn to_word(&self) -> Option<Word> {
194        self.ty.as_word().map(|n| Word {
195            value: self.to_value(),
196            n,
197        })
198    }
199
200    /// Yields an iterator over the "raw bytes" of the value.
201    ///
202    /// The returned bytes match the padded bit-encoding of the value. You
203    /// may wish to call [`Self::iter_padded`] instead to obtain the bits,
204    /// but this method is more efficient in some contexts.
205    pub fn raw_byte_iter(&self) -> RawByteIter<'v> {
206        RawByteIter {
207            value: *self,
208            yielded_bytes: 0,
209        }
210    }
211
212    /// Return an iterator over the compact bit encoding of the value.
213    ///
214    /// This encoding is used for writing witness data and for computing IHRs.
215    pub fn iter_compact(&self) -> CompactBitsIter<'v> {
216        CompactBitsIter::new(*self)
217    }
218
219    /// Return an iterator over the padded bit encoding of the value.
220    ///
221    /// This encoding is used to represent the value in the Bit Machine.
222    pub fn iter_padded(&self) -> PreOrderIter<'v> {
223        PreOrderIter {
224            inner: BitIter::new(self.raw_byte_iter()).take(self.ty.bit_width()),
225        }
226    }
227}
228
229pub struct RawByteIter<'v> {
230    value: ValueRef<'v>,
231    yielded_bytes: usize,
232}
233
234impl Iterator for RawByteIter<'_> {
235    type Item = u8;
236    fn next(&mut self) -> Option<Self::Item> {
237        if 8 * self.yielded_bytes >= self.value.ty.bit_width() {
238            None
239        } else if self.value.bit_offset % 8 == 0 {
240            self.yielded_bytes += 1;
241
242            Some(self.value.inner[self.value.bit_offset / 8 + self.yielded_bytes - 1])
243        } else {
244            self.yielded_bytes += 1;
245
246            let ret1 = self.value.inner[self.value.bit_offset / 8 + self.yielded_bytes - 1];
247            let ret2 = self
248                .value
249                .inner
250                .get(self.value.bit_offset / 8 + self.yielded_bytes)
251                .copied()
252                .unwrap_or(0);
253            let bit_offset = self.value.bit_offset % 8;
254            Some((ret1 << bit_offset) | (ret2 >> (8 - bit_offset)))
255        }
256    }
257}
258
259pub struct PreOrderIter<'v> {
260    inner: iter::Take<BitIter<RawByteIter<'v>>>,
261}
262
263impl Iterator for PreOrderIter<'_> {
264    type Item = bool;
265    fn next(&mut self) -> Option<Self::Item> {
266        self.inner.next()
267    }
268}
269
270/// Helper function to right-shift a value by one bit.
271///
272/// This is used for putting a value into a sum type. It takes the value's
273/// bit encoding and current bit offset, and returns a new bit-encoding with
274/// a new bit inserted upfront and a new bit offset.
275fn right_shift_1(inner: &Arc<[u8]>, bit_offset: usize, new_bit: bool) -> (Arc<[u8]>, usize) {
276    // If the current bit offset is nonzero this is super easy: we just
277    // lower the bit offset and call that a fix.
278    if bit_offset > 0 {
279        let new_bit_offset = bit_offset - 1;
280        let mask = 1u8 << (7 - new_bit_offset % 8);
281        let current_bit = inner[new_bit_offset / 8] & mask != 0;
282        if current_bit == new_bit {
283            (Arc::clone(inner), new_bit_offset)
284        } else if new_bit {
285            let mut bx: Box<[u8]> = inner.as_ref().into();
286            bx[new_bit_offset / 8] |= mask;
287            (bx.into(), new_bit_offset)
288        } else {
289            let mut bx: Box<[u8]> = inner.as_ref().into();
290            bx[new_bit_offset / 8] &= !mask;
291            (bx.into(), new_bit_offset)
292        }
293    } else {
294        // If the current bit offset is 0, we just shift everything right by 8
295        // and then do pretty-much the same thing as above. This sometimes will
296        // waste 7 bits, but it avoids needing to iterate through all of `inner`.
297        let mut new = Vec::with_capacity(inner.len() + 1);
298        new.push(u8::from(new_bit));
299        new.extend(inner.iter().copied());
300        (new.into(), 7)
301    }
302}
303
304/// Helper function to copy `nbits` bits from `src`, starting at bit-offset `src_offset`,
305/// into `dst`, starting at bit-offset `dst_offset`.
306///
307/// Thanks ChatGPT for suggesting we extract this function.
308fn copy_bits(src: &[u8], src_offset: usize, dst: &mut [u8], dst_offset: usize, nbits: usize) {
309    // For each bit i in 0..nbits, extract the bit from `src`
310    // and insert it into `dst`.
311    for i in 0..nbits {
312        let bit = (src[(src_offset + i) / 8] >> (7 - (src_offset + i) % 8)) & 1;
313        dst[(dst_offset + i) / 8] |= bit << (7 - (dst_offset + i) % 8);
314    }
315}
316
317/// Helper function to take the product of two values (i.e. their concatenation).
318///
319/// If either `left_inner` or `right_inner` is not provided, it is assumed to be
320/// padding and will be stored as all zeros.
321///
322/// Returns the new bit data and the offset (NOT the length) of the data.
323fn product(
324    left: Option<(&Arc<[u8]>, usize)>,
325    left_bit_length: usize,
326    right: Option<(&Arc<[u8]>, usize)>,
327    right_bit_length: usize,
328) -> (Arc<[u8]>, usize) {
329    if left_bit_length == 0 {
330        if let Some((right, right_bit_offset)) = right {
331            (Arc::clone(right), right_bit_offset)
332        } else if right_bit_length == 0 {
333            (Arc::new([]), 0)
334        } else {
335            (Arc::from(vec![0; right_bit_length.div_ceil(8)]), 0)
336        }
337    } else if right_bit_length == 0 {
338        if let Some((lt, left_bit_offset)) = left {
339            (Arc::clone(lt), left_bit_offset)
340        } else {
341            (Arc::from(vec![0; left_bit_length.div_ceil(8)]), 0)
342        }
343    } else {
344        // Both left and right have nonzero lengths. This is the only "real" case
345        // in which we have to do something beyond cloning Arcs or allocating
346        // zeroed vectors. In this case we left-shift both as much as possible.
347        let mut bx = Box::<[u8]>::from(vec![0; (left_bit_length + right_bit_length).div_ceil(8)]);
348        if let Some((left, left_bit_offset)) = left {
349            copy_bits(left, left_bit_offset, &mut bx, 0, left_bit_length);
350        }
351        if let Some((right, right_bit_offset)) = right {
352            copy_bits(
353                right,
354                right_bit_offset,
355                &mut bx,
356                left_bit_length,
357                right_bit_length,
358            );
359        }
360
361        (bx.into(), 0)
362    }
363}
364
365impl Value {
366    /// Make a cheap copy of the value.
367    pub fn shallow_clone(&self) -> Self {
368        Self {
369            inner: Arc::clone(&self.inner),
370            bit_offset: self.bit_offset,
371            ty: Arc::clone(&self.ty),
372        }
373    }
374
375    /// Access the type of the value.
376    pub fn ty(&self) -> &Final {
377        &self.ty
378    }
379
380    /// Create the unit value.
381    pub fn unit() -> Self {
382        Self {
383            inner: Arc::new([]),
384            bit_offset: 0,
385            ty: Final::unit(),
386        }
387    }
388
389    /// Create a left value that wraps the given `inner` value.
390    pub fn left(inner: Self, right: Arc<Final>) -> Self {
391        let total_width = cmp::max(inner.ty.bit_width(), right.bit_width());
392
393        let (concat, concat_offset) = product(
394            None,
395            total_width - inner.ty.bit_width(),
396            Some((&inner.inner, inner.bit_offset)),
397            inner.ty.bit_width(),
398        );
399        let (new_inner, new_bit_offset) = right_shift_1(&concat, concat_offset, false);
400        Self {
401            inner: new_inner,
402            bit_offset: new_bit_offset,
403            ty: Final::sum(Arc::clone(&inner.ty), right),
404        }
405    }
406
407    /// Create a right value that wraps the given `inner` value.
408    pub fn right(left: Arc<Final>, inner: Self) -> Self {
409        let total_width = cmp::max(left.bit_width(), inner.ty.bit_width());
410        let (concat, concat_offset) = product(
411            None,
412            total_width - inner.ty.bit_width(),
413            Some((&inner.inner, inner.bit_offset)),
414            inner.ty.bit_width(),
415        );
416        let (new_inner, new_bit_offset) = right_shift_1(&concat, concat_offset, true);
417        Self {
418            inner: new_inner,
419            bit_offset: new_bit_offset,
420            ty: Final::sum(left, Arc::clone(&inner.ty)),
421        }
422    }
423
424    /// Create a product value that wraps the given `left` and `right` values.
425    pub fn product(left: Self, right: Self) -> Self {
426        let (new_inner, new_bit_offset) = product(
427            Some((&left.inner, left.bit_offset)),
428            left.ty.bit_width(),
429            Some((&right.inner, right.bit_offset)),
430            right.ty.bit_width(),
431        );
432        Self {
433            inner: new_inner,
434            bit_offset: new_bit_offset,
435            ty: Final::product(Arc::clone(&left.ty), Arc::clone(&right.ty)),
436        }
437    }
438
439    /// Create a none value.
440    pub fn none(right: Arc<Final>) -> Self {
441        Self::left(Value::unit(), right)
442    }
443
444    /// Create a some value.
445    pub fn some(inner: Self) -> Self {
446        Self::right(Final::unit(), inner)
447    }
448
449    /// Return the bit length of the value in compact encoding.
450    pub fn compact_len(&self) -> usize {
451        self.iter_compact().count()
452    }
453
454    /// Return the bit length of the value in padded encoding.
455    pub fn padded_len(&self) -> usize {
456        self.ty.bit_width()
457    }
458
459    /// Check if the value is a nested product of units.
460    /// In this case, the value contains no information.
461    pub fn is_empty(&self) -> bool {
462        self.ty.bit_width() == 0
463    }
464
465    /// Check if the value is a unit.
466    pub fn is_unit(&self) -> bool {
467        self.ty.is_unit()
468    }
469
470    /// A reference to this value, which can be recursed over.
471    pub fn as_ref(&self) -> ValueRef<'_> {
472        ValueRef {
473            inner: &self.inner,
474            bit_offset: self.bit_offset,
475            ty: &self.ty,
476        }
477    }
478
479    /// Access the inner value of a left sum value.
480    pub fn as_left(&self) -> Option<ValueRef<'_>> {
481        self.as_ref().as_left()
482    }
483
484    /// Access the inner value of a right sum value.
485    pub fn as_right(&self) -> Option<ValueRef<'_>> {
486        self.as_ref().as_right()
487    }
488
489    /// Access the inner values of a product value.
490    pub fn as_product(&self) -> Option<(ValueRef<'_>, ValueRef<'_>)> {
491        self.as_ref().as_product()
492    }
493
494    /// Create a 1-bit integer.
495    ///
496    /// ## Panics
497    ///
498    /// The value is out of range.
499    pub fn u1(value: u8) -> Self {
500        assert!(value <= 1, "{} out of range for Value::u1", value);
501        Self {
502            inner: Arc::new([value]),
503            bit_offset: 7,
504            ty: Final::two_two_n(0),
505        }
506    }
507
508    /// Create a 2-bit integer.
509    ///
510    /// ## Panics
511    ///
512    /// The value is out of range.
513    pub fn u2(value: u8) -> Self {
514        assert!(value <= 3, "{} out of range for Value::u2", value);
515        Self {
516            inner: Arc::new([value]),
517            bit_offset: 6,
518            ty: Final::two_two_n(1),
519        }
520    }
521
522    /// Create a 4-bit integer.
523    ///
524    /// ## Panics
525    ///
526    /// The value is ouf of range.
527    pub fn u4(value: u8) -> Self {
528        assert!(value <= 15, "{} out of range for Value::u2", value);
529        Self {
530            inner: Arc::new([value]),
531            bit_offset: 4,
532            ty: Final::two_two_n(2),
533        }
534    }
535
536    /// Create an 8-bit integer.
537    pub fn u8(value: u8) -> Self {
538        Self {
539            inner: Arc::new([value]),
540            bit_offset: 0,
541            ty: Final::two_two_n(3),
542        }
543    }
544
545    /// Create a 16-bit integer.
546    pub fn u16(bytes: u16) -> Self {
547        Self {
548            inner: Arc::new(bytes.to_be_bytes()),
549            bit_offset: 0,
550            ty: Final::two_two_n(4),
551        }
552    }
553
554    /// Create a 32-bit integer.
555    pub fn u32(bytes: u32) -> Self {
556        Self {
557            inner: Arc::new(bytes.to_be_bytes()),
558            bit_offset: 0,
559            ty: Final::two_two_n(5),
560        }
561    }
562
563    /// Create a 64-bit integer.
564    pub fn u64(bytes: u64) -> Self {
565        Self {
566            inner: Arc::new(bytes.to_be_bytes()),
567            bit_offset: 0,
568            ty: Final::two_two_n(6),
569        }
570    }
571
572    /// Create a 128-bit integer.
573    pub fn u128(bytes: u128) -> Self {
574        Self {
575            inner: Arc::new(bytes.to_be_bytes()),
576            bit_offset: 0,
577            ty: Final::two_two_n(7),
578        }
579    }
580
581    /// Create a 256-bit integer.
582    pub fn u256(bytes: [u8; 32]) -> Self {
583        Self {
584            inner: Arc::new(bytes),
585            bit_offset: 0,
586            ty: Final::two_two_n(8),
587        }
588    }
589
590    /// Create a 512-bit integer.
591    pub fn u512(bytes: [u8; 64]) -> Self {
592        Self {
593            inner: Arc::new(bytes),
594            bit_offset: 0,
595            ty: Final::two_two_n(9),
596        }
597    }
598
599    /// Create a value from a byte array.
600    ///
601    /// ## Panics
602    ///
603    /// The array length is not a power of two.
604    pub fn from_byte_array<const N: usize>(bytes: [u8; N]) -> Self {
605        assert!(N.is_power_of_two(), "Array length must be a power of two");
606        let mut values: VecDeque<_> = bytes.into_iter().map(Value::u8).collect();
607
608        while values.len() > 1 {
609            let mut alt_values = VecDeque::with_capacity(values.len() / 2);
610
611            while let (Some(left), Some(right)) = (values.pop_front(), values.pop_front()) {
612                alt_values.push_back(Value::product(left, right));
613            }
614
615            values = alt_values;
616        }
617
618        values.into_iter().next().unwrap()
619    }
620
621    /// Yields an iterator over the "raw bytes" of the value.
622    ///
623    /// The returned bytes match the padded bit-encoding of the value. You
624    /// may wish to call [`Self::iter_padded`] instead to obtain the bits,
625    /// but this method is more efficient in some contexts.
626    pub fn raw_byte_iter(&self) -> RawByteIter<'_> {
627        self.as_ref().raw_byte_iter()
628    }
629
630    /// Return an iterator over the compact bit encoding of the value.
631    ///
632    /// This encoding is used for writing witness data and for computing IHRs.
633    pub fn iter_compact(&self) -> CompactBitsIter<'_> {
634        self.as_ref().iter_compact()
635    }
636
637    /// Return an iterator over the padded bit encoding of the value.
638    ///
639    /// This encoding is used to represent the value in the Bit Machine.
640    pub fn iter_padded(&self) -> PreOrderIter<'_> {
641        self.as_ref().iter_padded()
642    }
643
644    /// Check if the value is of the given type.
645    pub fn is_of_type(&self, ty: &Final) -> bool {
646        self.ty.as_ref() == ty
647    }
648
649    /// Get the zero value for the given type.
650    ///
651    /// The zero value serializes to a string of zeroes.
652    ///
653    /// ## Construction
654    ///
655    /// - `zero( 1 )` = `()`
656    /// - `zero( A + B )` = `zero(A)`
657    /// - `zero( A × B )` = `zero(A) × zero(B)`
658    pub fn zero(ty: &Final) -> Self {
659        Self {
660            inner: Arc::from(vec![0; ty.bit_width().div_ceil(8)]),
661            bit_offset: 0,
662            ty: Arc::new(ty.clone()),
663        }
664    }
665
666    /// Try to convert the value into a word.
667    ///
668    /// The value is cheaply cloned.
669    pub fn to_word(&self) -> Option<Word> {
670        self.ty.as_word().map(|n| Word {
671            value: self.shallow_clone(),
672            n,
673        })
674    }
675
676    /// Prune the value down to the given type.
677    ///
678    /// The pruned type must be _smaller than or equal to_ the current type of the value.
679    /// Otherwise, this method returns `None`.
680    ///
681    /// ## Smallness
682    ///
683    /// - `T` ≤ `T` for all types `T`
684    /// - `1` ≤ `T` for all types `T`
685    /// - `A1 + B1` ≤ `A2 + B2` if `A1` ≤ `A2` and `B1` ≤ `B2`
686    /// - `A1 × B1` ≤ `A2 × B2` if `A1` ≤ `A2` and `B1` ≤ `B2`
687    ///
688    /// ## Pruning
689    ///
690    /// - `prune( v: T, 1 )` = `(): 1`
691    /// - `prune( L(l): A1 + B1, A2 + B2 )` = `prune(l: A1, A2) : A2 + B2`
692    /// - `prune( R(r): A1 + B1, A2 + B2 )` = `prune(r: B1, B2) : A2 + B2`
693    /// - `prune( (l, r): A1 × B1, A2 × B2 )` = `( prune(l: A1, A2), prune(r: B1, B2): A2 × B2`
694    pub fn prune(&self, pruned_ty: &Final) -> Option<Self> {
695        enum Task<'v, 'ty> {
696            Prune(ValueRef<'v>, &'ty Final),
697            MakeLeft(Arc<Final>),
698            MakeRight(Arc<Final>),
699            MakeProduct,
700        }
701
702        let mut stack = vec![Task::Prune(self.as_ref(), pruned_ty)];
703        let mut output = vec![];
704
705        while let Some(task) = stack.pop() {
706            match task {
707                Task::Prune(value, pruned_ty) if value.ty.as_ref() == pruned_ty => {
708                    output.push(value.to_value())
709                }
710                Task::Prune(value, pruned_ty) => match pruned_ty.bound() {
711                    CompleteBound::Unit => output.push(Value::unit()),
712                    CompleteBound::Sum(l_ty, r_ty) => {
713                        if let Some(l_value) = value.as_left() {
714                            stack.push(Task::MakeLeft(Arc::clone(r_ty)));
715                            stack.push(Task::Prune(l_value, l_ty));
716                        } else {
717                            let r_value = value.as_right()?;
718                            stack.push(Task::MakeRight(Arc::clone(l_ty)));
719                            stack.push(Task::Prune(r_value, r_ty));
720                        }
721                    }
722                    CompleteBound::Product(l_ty, r_ty) => {
723                        let (l_value, r_value) = value.as_product()?;
724                        stack.push(Task::MakeProduct);
725                        stack.push(Task::Prune(r_value, r_ty));
726                        stack.push(Task::Prune(l_value, l_ty));
727                    }
728                },
729                Task::MakeLeft(r_ty) => {
730                    let l_value = output.pop().unwrap();
731                    output.push(Value::left(l_value, r_ty));
732                }
733                Task::MakeRight(l_ty) => {
734                    let r_value = output.pop().unwrap();
735                    output.push(Value::right(l_ty, r_value));
736                }
737                Task::MakeProduct => {
738                    let r_value = output.pop().unwrap();
739                    let l_value = output.pop().unwrap();
740                    output.push(Value::product(l_value, r_value));
741                }
742            }
743        }
744
745        debug_assert_eq!(output.len(), 1);
746        output.pop()
747    }
748}
749
750impl fmt::Debug for Value {
751    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
752        f.debug_struct("Value")
753            .field("value", &format_args!("{}", self))
754            .field("ty", &self.ty)
755            .field("raw_value", &self.inner)
756            .field("raw_bit_offset", &self.bit_offset)
757            .finish()
758    }
759}
760
761impl fmt::Display for Value {
762    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
763        // This is a copy of the logic inside `CompactBitsIter` except
764        // that we handle products more explicitly.
765        enum S<'v> {
766            Disp(ValueRef<'v>),
767            DispCh(char),
768        }
769
770        let mut stack = Vec::with_capacity(1024);
771        // Next node to visit.
772        stack.push(S::Disp(self.as_ref()));
773
774        'main_loop: while let Some(next) = stack.pop() {
775            let value = match next {
776                S::Disp(ref value) => value,
777                S::DispCh(ch) => {
778                    write!(f, "{}", ch)?;
779                    continue;
780                }
781            };
782
783            if value.is_unit() {
784                f.write_str("ε")?;
785            } else {
786                // First, write any bitstrings out
787                for tmr in &Tmr::TWO_TWO_N {
788                    if value.ty.tmr() == *tmr {
789                        if value.ty.bit_width() < 4 {
790                            f.write_str("0b")?;
791                            for bit in value.iter_padded() {
792                                f.write_str(if bit { "1" } else { "0" })?;
793                            }
794                        } else {
795                            f.write_str("0x")?;
796                            // Annoyingly `array_chunks` is unstable so we have to do it manually
797                            // https://github.com/rust-lang/rust/issues/100450
798                            let mut iter = value.iter_padded();
799                            while let (Some(a), Some(b), Some(c), Some(d)) =
800                                (iter.next(), iter.next(), iter.next(), iter.next())
801                            {
802                                let n = (u8::from(a) << 3)
803                                    + (u8::from(b) << 2)
804                                    + (u8::from(c) << 1)
805                                    + u8::from(d);
806                                write!(f, "{:x}", n)?;
807                            }
808                        }
809                        continue 'main_loop;
810                    }
811                }
812
813                // If we don't have a bitstring, then write out the explicit value.
814                if let Some(l_value) = value.as_left() {
815                    f.write_str("L(")?;
816                    stack.push(S::DispCh(')'));
817                    stack.push(S::Disp(l_value));
818                } else if let Some(r_value) = value.as_right() {
819                    f.write_str("R(")?;
820                    stack.push(S::DispCh(')'));
821                    stack.push(S::Disp(r_value));
822                } else if let Some((l_value, r_value)) = value.as_product() {
823                    stack.push(S::DispCh(')'));
824                    stack.push(S::Disp(r_value));
825                    stack.push(S::DispCh(','));
826                    stack.push(S::Disp(l_value));
827                    stack.push(S::DispCh('('));
828                } else {
829                    unreachable!()
830                }
831            }
832        }
833        Ok(())
834    }
835}
836
837/// An iterator over the bits of the compact encoding of a [`Value`].
838#[derive(Debug, Clone)]
839pub struct CompactBitsIter<'v> {
840    stack: Vec<ValueRef<'v>>,
841}
842
843impl<'v> CompactBitsIter<'v> {
844    /// Create an iterator over the bits of the compact encoding of the `value`.
845    fn new(value: ValueRef<'v>) -> Self {
846        Self { stack: vec![value] }
847    }
848}
849
850impl Iterator for CompactBitsIter<'_> {
851    type Item = bool;
852
853    fn next(&mut self) -> Option<Self::Item> {
854        while let Some(value) = self.stack.pop() {
855            if value.ty.bit_width() == 0 {
856                // NOP
857            } else if let Some(l_value) = value.as_left() {
858                self.stack.push(l_value);
859                return Some(false);
860            } else if let Some(r_value) = value.as_right() {
861                self.stack.push(r_value);
862                return Some(true);
863            } else if let Some((l_value, r_value)) = value.as_product() {
864                self.stack.push(r_value);
865                self.stack.push(l_value);
866            }
867        }
868
869        None
870    }
871}
872
873impl Value {
874    /// Decode a value of the given type from its compact bit encoding.
875    pub fn from_compact_bits<I: Iterator<Item = u8>>(
876        bits: &mut BitIter<I>,
877        ty: &Final,
878    ) -> Result<Self, EarlyEndOfStreamError> {
879        enum State<'a> {
880            ProcessType(&'a Final),
881            DoSumL(Arc<Final>),
882            DoSumR(Arc<Final>),
883            DoProduct,
884        }
885
886        let mut stack = vec![State::ProcessType(ty)];
887        let mut result_stack = vec![];
888        while let Some(state) = stack.pop() {
889            match state {
890                State::ProcessType(ty) if ty.has_padding() => match ty.bound() {
891                    CompleteBound::Unit => result_stack.push(Value::unit()),
892                    CompleteBound::Sum(ref l, ref r) => {
893                        if !bits.next().ok_or(EarlyEndOfStreamError)? {
894                            stack.push(State::DoSumL(Arc::clone(r)));
895                            stack.push(State::ProcessType(l));
896                        } else {
897                            stack.push(State::DoSumR(Arc::clone(l)));
898                            stack.push(State::ProcessType(r));
899                        }
900                    }
901                    CompleteBound::Product(ref l, ref r) => {
902                        stack.push(State::DoProduct);
903                        stack.push(State::ProcessType(r));
904                        stack.push(State::ProcessType(l));
905                    }
906                },
907                State::ProcessType(ty) => {
908                    // no padding no problem
909                    result_stack.push(Value::from_padded_bits(bits, ty)?);
910                }
911                State::DoSumL(r) => {
912                    let val = result_stack.pop().unwrap();
913                    result_stack.push(Value::left(val, r));
914                }
915                State::DoSumR(l) => {
916                    let val = result_stack.pop().unwrap();
917                    result_stack.push(Value::right(l, val));
918                }
919                State::DoProduct => {
920                    let val_r = result_stack.pop().unwrap();
921                    let val_l = result_stack.pop().unwrap();
922                    result_stack.push(Value::product(val_l, val_r));
923                }
924            }
925        }
926        debug_assert_eq!(result_stack.len(), 1);
927        Ok(result_stack.pop().unwrap())
928    }
929
930    /// Decode a value of the given type from its padded bit encoding.
931    pub fn from_padded_bits<I: Iterator<Item = u8>>(
932        bits: &mut BitIter<I>,
933        ty: &Final,
934    ) -> Result<Self, EarlyEndOfStreamError> {
935        const MAX_INITIAL_ALLOC: usize = 32 * 1024 * 1024; // 4 megabytes
936
937        let cap = cmp::min(MAX_INITIAL_ALLOC, ty.bit_width().div_ceil(8));
938        let mut blob = Vec::with_capacity(cap);
939        for _ in 0..ty.bit_width() / 8 {
940            blob.push(bits.read_u8()?);
941        }
942        let mut last = 0u8;
943        for i in 0..ty.bit_width() % 8 {
944            if bits.read_bit()? {
945                last |= 1 << (7 - i);
946            }
947        }
948        blob.push(last);
949
950        Ok(Value {
951            inner: blob.into(),
952            bit_offset: 0,
953            ty: Arc::new(ty.clone()),
954        })
955    }
956}
957
958/// A Simplicity word. A value of type `TWO^(2^n)` for some `0 ≤ n < 32`.
959#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
960pub struct Word {
961    /// Value of type `TWO^(2^n)`.
962    value: Value,
963    /// 0 ≤ n < 32.
964    n: u32,
965}
966
967macro_rules! construct_word_fallible {
968    ($name: ident, $n: expr, $text: expr) => {
969        #[doc = "Create"]
970        #[doc = $text]
971        #[doc = "word.\n\n"]
972        #[doc = "## Panics\n"]
973        #[doc = "The value is ouf of range."]
974        pub fn $name(bit: u8) -> Self {
975            Self {
976                value: Value::$name(bit),
977                n: $n,
978            }
979        }
980    };
981}
982
983macro_rules! construct_word {
984    ($name: ident, $ty: ty, $n: expr, $text: expr) => {
985        #[doc = "Create"]
986        #[doc = $text]
987        #[doc = "word."]
988        pub fn $name(bit: $ty) -> Self {
989            Self {
990                value: Value::$name(bit),
991                n: $n,
992            }
993        }
994    };
995}
996
997impl Word {
998    /// Concatenate two words into a larger word.
999    ///
1000    /// Both words have to have the same length, which is 2^n bits.
1001    /// The resulting word will be 2^(n + 1) bits long.
1002    ///
1003    /// Returns `None` if the words differ in length.
1004    ///
1005    /// Returns `None` if the words are already 2^31 bits long
1006    /// _(the resulting word would be longer than 2^31 bits, which is not supported)_.
1007    pub fn product(self, right: Self) -> Option<Self> {
1008        if self.n == right.n && self.n < 30 {
1009            Some(Self {
1010                value: Value::product(self.value, right.value),
1011                n: self.n + 1,
1012            })
1013        } else {
1014            None
1015        }
1016    }
1017
1018    construct_word_fallible!(u1, 0, "a 1-bit");
1019    construct_word_fallible!(u2, 1, "a 2-bit");
1020    construct_word_fallible!(u4, 2, "a 4-bit");
1021    construct_word!(u8, u8, 3, "an 8-bit");
1022    construct_word!(u16, u16, 4, "a 16-bit");
1023    construct_word!(u32, u32, 5, "a 32-bit");
1024    construct_word!(u64, u64, 6, "a 64-bit");
1025    construct_word!(u128, u128, 7, "a 128-bit");
1026    construct_word!(u256, [u8; 32], 8, "a 256-bit");
1027    construct_word!(u512, [u8; 64], 9, "a 512-bit");
1028
1029    /// Make a cheap copy of the word.
1030    pub fn shallow_clone(&self) -> Self {
1031        Self {
1032            value: self.value.shallow_clone(),
1033            n: self.n,
1034        }
1035    }
1036
1037    /// Access the value of the word.
1038    pub fn as_value(&self) -> &Value {
1039        &self.value
1040    }
1041
1042    /// The word is of type `TWO^(2^n)`. Return `n`.
1043    pub fn n(&self) -> u32 {
1044        self.n
1045    }
1046
1047    /// Return the bit length of the word.
1048    ///
1049    /// The word is of type `TWO^(2^n)`. Return `2^n`.
1050    #[allow(clippy::len_without_is_empty)]
1051    pub fn len(&self) -> usize {
1052        2usize.pow(self.n)
1053    }
1054
1055    /// Return an iterator over the bit encoding of the word.
1056    ///
1057    /// Words have no padding, so their compact encoding is the same as the padded encoding.
1058    /// The universal encoding can be used in all situations.
1059    pub fn iter(&self) -> impl Iterator<Item = bool> + '_ {
1060        self.value.iter_compact()
1061    }
1062
1063    /// Decode a word of type `TWO^(2^n)` from bits.
1064    ///
1065    /// ## Panics
1066    ///
1067    /// n is greater than 31.
1068    pub fn from_bits<I: Iterator<Item = u8>>(
1069        bits: &mut BitIter<I>,
1070        n: u32,
1071    ) -> Result<Self, EarlyEndOfStreamError> {
1072        assert!(n < 32, "TWO^(2^{n}) is not supported as a word type");
1073        let ty = Final::two_two_n(n as usize); // cast safety: 32-bit machine or higher
1074        let value = Value::from_compact_bits(bits, &ty)?;
1075        Ok(Self { value, n })
1076    }
1077}
1078
1079impl fmt::Debug for Word {
1080    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1081        fmt::Display::fmt(self, f)
1082    }
1083}
1084
1085impl fmt::Display for Word {
1086    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1087        use hex::DisplayHex;
1088
1089        if let Ok(hex) = self.iter().try_collect_bytes() {
1090            write!(f, "0x{}", hex.as_hex())
1091        } else {
1092            f.write_str("0b")?;
1093            for bit in self.iter() {
1094                match bit {
1095                    false => f.write_str("0")?,
1096                    true => f.write_str("1")?,
1097                }
1098            }
1099            Ok(())
1100        }
1101    }
1102}
1103
1104#[cfg(test)]
1105mod tests {
1106    use super::*;
1107    use crate::bit_encoding::{BitCollector as _, BitIter};
1108    use crate::jet::type_name::TypeName;
1109
1110    #[test]
1111    fn value_len() {
1112        let v = Value::u4(6);
1113        let s_v = Value::some(v.shallow_clone());
1114        let n_v = Value::none(Final::two_two_n(2));
1115
1116        assert_eq!(v.compact_len(), 4);
1117        assert_eq!(v.padded_len(), 4);
1118        assert_eq!(s_v.compact_len(), 5);
1119        assert_eq!(s_v.padded_len(), 5);
1120        assert_eq!(n_v.compact_len(), 1);
1121        assert_eq!(n_v.padded_len(), 5);
1122    }
1123
1124    #[test]
1125    fn value_display() {
1126        // Only test a couple values becasue we probably want to change this
1127        // at some point and will have to redo this test.
1128        assert_eq!(Value::u1(0).to_string(), "0b0",);
1129        assert_eq!(Value::u1(1).to_string(), "0b1",);
1130        assert_eq!(Value::u4(6).to_string(), "0x6",);
1131    }
1132
1133    #[test]
1134    fn is_of_type() {
1135        let value_typename = [
1136            (Value::unit(), TypeName(b"1")),
1137            (Value::left(Value::unit(), Final::unit()), TypeName(b"+11")),
1138            (Value::right(Final::unit(), Value::unit()), TypeName(b"+11")),
1139            (
1140                Value::left(Value::unit(), Final::two_two_n(8)),
1141                TypeName(b"+1h"),
1142            ),
1143            (
1144                Value::right(Final::two_two_n(8), Value::unit()),
1145                TypeName(b"+h1"),
1146            ),
1147            (
1148                Value::product(Value::unit(), Value::unit()),
1149                TypeName(b"*11"),
1150            ),
1151            (Value::u8(u8::MAX), TypeName(b"c")),
1152            (Value::u64(u64::MAX), TypeName(b"l")),
1153        ];
1154
1155        for (value, typename) in value_typename {
1156            let ty = typename.to_final();
1157            assert!(value.is_of_type(ty.as_ref()));
1158        }
1159    }
1160
1161    #[test]
1162    fn prune_regression_1() {
1163        // Found this when fuzzing Elements; unsure how to reduce it further.
1164        let nontrivial_sum = Value::product(
1165            Value::right(Final::two_two_n(4), Value::u16(0)),
1166            Value::u8(0),
1167        );
1168        // Formatting should succeed and have no effect.
1169        let _ = format!("{nontrivial_sum}");
1170        // Pruning should succeed and have no effect.
1171        assert_eq!(
1172            nontrivial_sum.prune(nontrivial_sum.ty()),
1173            Some(nontrivial_sum)
1174        );
1175    }
1176
1177    #[test]
1178    fn prune() {
1179        let test_vectors = [
1180            (Value::unit(), Value::unit()),
1181            (Value::u64(42), Value::unit()),
1182            (
1183                Value::left(Value::u64(42), Final::u64()),
1184                Value::left(Value::u64(42), Final::unit()),
1185            ),
1186            (
1187                Value::right(Final::u64(), Value::u64(1337)),
1188                Value::right(Final::unit(), Value::u64(1337)),
1189            ),
1190            (
1191                Value::product(Value::u64(42), Value::u64(1337)),
1192                Value::product(Value::u64(42), Value::unit()),
1193            ),
1194            (
1195                Value::product(Value::u64(42), Value::u64(1337)),
1196                Value::product(Value::unit(), Value::u64(1337)),
1197            ),
1198        ];
1199
1200        for (value, expected_pruned_value) in test_vectors {
1201            assert_eq!(
1202                value.prune(expected_pruned_value.ty()),
1203                Some(expected_pruned_value)
1204            );
1205        }
1206
1207        let bad_test_vectors = [
1208            (Value::unit(), Final::u1()),
1209            (
1210                Value::product(Value::unit(), Value::unit()),
1211                Final::sum(Final::unit(), Final::unit()),
1212            ),
1213            (
1214                Value::left(Value::unit(), Final::unit()),
1215                Final::product(Final::unit(), Final::unit()),
1216            ),
1217            (
1218                Value::right(Final::unit(), Value::unit()),
1219                Final::product(Final::unit(), Final::unit()),
1220            ),
1221        ];
1222
1223        for (value, pruned_ty) in bad_test_vectors {
1224            assert_eq!(value.prune(&pruned_ty), None);
1225        }
1226    }
1227
1228    #[test]
1229    fn zero_value() {
1230        let test_vectors = [
1231            (Final::unit(), Value::unit()),
1232            (Final::u8(), Value::u8(0)),
1233            (Final::u64(), Value::u64(0)),
1234            (
1235                Final::product(Final::u16(), Final::u32()),
1236                Value::product(Value::u16(0), Value::u32(0)),
1237            ),
1238            (
1239                Final::sum(Final::unit(), Final::u64()),
1240                Value::left(Value::unit(), Final::u64()),
1241            ),
1242            (
1243                Final::product(Final::unit(), Final::unit()),
1244                Value::product(Value::unit(), Value::unit()),
1245            ),
1246        ];
1247
1248        for (ty, expected_default_value) in test_vectors {
1249            assert_eq!(Value::zero(&ty), expected_default_value);
1250        }
1251    }
1252
1253    #[test]
1254    fn compact_round_trip() {
1255        let v = Value::u64(0xff00_00ff_ff00_00ff);
1256        let (bits, _) = v.iter_compact().collect_bits();
1257        let mut iter = BitIter::new(bits.into_iter());
1258        let new_v = Value::from_compact_bits(&mut iter, &v.ty).unwrap();
1259        assert_eq!(v, new_v);
1260    }
1261
1262    #[test]
1263    fn padded_round_trip() {
1264        let v = Value::u64(0xff00_00ff_ff00_00ff);
1265        let (bits, _) = v.iter_padded().collect_bits();
1266        let mut iter = BitIter::new(bits.into_iter());
1267        let new_v = Value::from_padded_bits(&mut iter, &v.ty).unwrap();
1268        assert_eq!(v, new_v);
1269    }
1270
1271    // --- Bug regression tests for right_shift_1 when new_bit=false ---
1272    //
1273    // right_shift_1(inner, bit_offset > 0, new_bit=false) is supposed to insert
1274    // a 0 (Left tag) at position bit_offset-1 by decrementing bit_offset.  The bug
1275    // is that it clones the Arc without clearing that position, so any pre-existing
1276    // 1-bit at bit_offset-1 corrupts the Left tag, causing the value to read as
1277    // Right instead of Left.
1278    //
1279    // The dirty bit originates from product sub-value extraction: as_product()
1280    // returns ValueRef children that share the parent buffer.  The right child has
1281    // bit_offset = parent.bit_offset + left_bit_width, so every 1-bit encoded by
1282    // the left component sits "before" the right child's logical start.  When that
1283    // right child is later wrapped in Left, right_shift_1 may see a stale 1-bit.
1284
1285    /// Simplest direct construction: extract the right sub-value of a product
1286    /// whose left component has 1-bits, then wrap the sub-value in Left.
1287    ///
1288    /// `product(Right(u1(1)), Right(u1(0)))` encodes as [0xE0] at bit_offset=0:
1289    ///   bits 0..=1  = Right(u1(1))  = 1, 1   ← left component
1290    ///   bits 2..=3  = Right(u1(0))  = 1, 0   ← right component (bit_offset=2)
1291    ///
1292    /// Wrapping the right sub-value (bit_offset=2 in [0xE0]) in Left calls
1293    /// right_shift_1(false) which should clear bit 1.  The bug leaves bit 1 = 1,
1294    /// so the result reads as Right instead of Left.
1295    #[test]
1296    fn left_tag_not_corrupted_by_dirty_buffer() {
1297        let product_val = Value::product(
1298            Value::right(Final::u1(), Value::u1(1)), // encodes bits 0,1 as 1,1
1299            Value::right(Final::u1(), Value::u1(0)), // starts at bit_offset=2
1300        );
1301
1302        let (_, right_sub) = product_val.as_product().unwrap();
1303        // right_sub shares [0xE0]; bit at position 1 (before its start) is 1.
1304        let right_sub_owned = right_sub.to_value();
1305
1306        let left_val = Value::left(right_sub_owned, Final::unit());
1307
1308        assert!(
1309            left_val.as_left().is_some(),
1310            "BUG: Left tag corrupted — right_shift_1(false) did not clear dirty bit; \
1311             value reads as Right instead of Left"
1312        );
1313        assert!(
1314            left_val.as_right().is_none(),
1315            "BUG: Left tag corrupted — as_right() should return None for a Left value"
1316        );
1317    }
1318
1319    /// Verify the dirty-buffer bug at the bit level: the first padded bit of a
1320    /// Left value must always be 0 (the Left discriminant).
1321    #[test]
1322    fn left_tag_first_padded_bit_is_zero() {
1323        let product_val = Value::product(
1324            Value::right(Final::u1(), Value::u1(1)),
1325            Value::right(Final::u1(), Value::u1(0)),
1326        );
1327
1328        let (_, right_sub) = product_val.as_product().unwrap();
1329        let left_val = Value::left(right_sub.to_value(), Final::unit());
1330
1331        let first_bit = left_val.iter_padded().next();
1332        assert_eq!(
1333            first_bit,
1334            Some(false),
1335            "BUG: first padded bit of Left value is {:?}, expected Some(false)",
1336            first_bit
1337        );
1338    }
1339
1340    /// End-to-end via prune: pruning can extract a sub-value via to_value() that
1341    /// shares the parent buffer and has 1-bits before its logical start.  When
1342    /// prune then calls Value::left() on it (Task::MakeLeft), the bug corrupts
1343    /// the Left tag.
1344    ///
1345    /// Original:  Left(product(Right(u1(1)), Right(u1(0))))
1346    ///            type: ((u1+u1) * (u1+u1)) + unit
1347    ///
1348    /// Pruned to: (unit * (u1+u1)) + unit
1349    ///
1350    /// The right component of the inner product keeps its type (u1+u1) unchanged,
1351    /// so prune returns it via to_value() — sharing the same dirty buffer.
1352    /// MakeLeft then wraps it, triggering the bug.
1353    #[test]
1354    fn prune_does_not_corrupt_left_tag_via_shared_buffer() {
1355        let original = Value::left(
1356            Value::product(
1357                Value::right(Final::u1(), Value::u1(1)),
1358                Value::right(Final::u1(), Value::u1(0)),
1359            ),
1360            Final::unit(),
1361        );
1362
1363        // Shrink the left component: (u1+u1)*(u1+u1)  →  unit*(u1+u1).
1364        // The right sub-value of the product keeps type u1+u1 (matches exactly),
1365        // so prune returns it via to_value() with the dirty shared buffer intact.
1366        let pruned_ty = Final::sum(
1367            Final::product(Final::unit(), Final::sum(Final::u1(), Final::u1())),
1368            Final::unit(),
1369        );
1370
1371        let pruned = original
1372            .prune(&pruned_ty)
1373            .expect("prune returned None; the target type is compatible");
1374
1375        assert!(
1376            pruned.as_left().is_some(),
1377            "BUG: prune corrupted the Left tag — right_shift_1(false) did not clear \
1378             a dirty bit from the shared product buffer; value reads as Right"
1379        );
1380    }
1381}
1382
1383#[cfg(bench)]
1384mod benches {
1385    use super::*;
1386
1387    use crate::bit_encoding::{BitCollector as _, BitIter};
1388
1389    use test::{black_box, Bencher};
1390
1391    // Create values directly
1392    #[bench]
1393    fn bench_value_create_u64(bh: &mut Bencher) {
1394        bh.iter(|| black_box(Value::u64(0xff00_00ff_ff00_00ff)))
1395    }
1396
1397    #[bench]
1398    fn bench_value_create_u2048(bh: &mut Bencher) {
1399        bh.iter(|| black_box(Value::from_byte_array([0xcd; 2048])));
1400    }
1401
1402    #[bench]
1403    fn bench_value_create_deep_some(bh: &mut Bencher) {
1404        bh.iter(|| {
1405            let mut kilo = Value::from_byte_array([0xab; 1024]);
1406            for _ in 0..1000 {
1407                kilo = Value::some(kilo.shallow_clone());
1408            }
1409            black_box(kilo)
1410        });
1411    }
1412
1413    #[bench]
1414    fn bench_value_create_64k(bh: &mut Bencher) {
1415        bh.iter(|| {
1416            let mut kilo = Value::from_byte_array([0xab; 1024]);
1417            for _ in 0..5 {
1418                kilo = Value::product(kilo.shallow_clone(), kilo.shallow_clone());
1419            }
1420            black_box(kilo)
1421        });
1422    }
1423
1424    #[bench]
1425    fn bench_value_create_512_256(bh: &mut Bencher) {
1426        bh.iter(|| {
1427            // This is a common "slow" pattern in my Elements fuzzer; it is a deeply
1428            // nested product of 2^512 x 2^256, which is not a "primitive numeric
1429            // type" and therefore cannot be quickly decoded from compact bits by
1430            // simply matching to pre-computed types.
1431            //
1432            // However, this type is a giant product of bits. Its compact encoding
1433            // is therefore equal to its padded encoding and we should be able to
1434            // quickly decode it.
1435            let mut s512_256 = Value::product(
1436                Value::from_byte_array([0x12; 64]),
1437                Value::from_byte_array([0x23; 32]),
1438            );
1439            for _ in 0..5 {
1440                s512_256 = Value::product(s512_256.shallow_clone(), s512_256.shallow_clone());
1441            }
1442            black_box(s512_256);
1443        });
1444    }
1445
1446    // Create values from padded bits
1447    fn padded_bits(v: &Value) -> (Vec<u8>, &Final) {
1448        let (bits, _) = v.iter_padded().collect_bits();
1449        (bits, v.ty.as_ref())
1450    }
1451
1452    #[bench]
1453    fn bench_value_create_u64_padded(bh: &mut Bencher) {
1454        let v = Value::u64(0xff00_00ff_ff00_00ff);
1455        let (bits, ty) = padded_bits(&v);
1456        bh.iter(|| {
1457            black_box(Value::from_padded_bits(
1458                &mut BitIter::new(bits.iter().copied()),
1459                ty,
1460            ))
1461        })
1462    }
1463
1464    #[bench]
1465    fn bench_value_create_u2048_padded(bh: &mut Bencher) {
1466        let v = Value::from_byte_array([0xcd; 2048]);
1467        let (bits, ty) = padded_bits(&v);
1468        bh.iter(|| {
1469            black_box(Value::from_padded_bits(
1470                &mut BitIter::new(bits.iter().copied()),
1471                ty,
1472            ))
1473        })
1474    }
1475
1476    #[bench]
1477    fn bench_value_create_deep_some_padded(bh: &mut Bencher) {
1478        let mut kilo = Value::from_byte_array([0xab; 1024]);
1479        for _ in 0..1000 {
1480            kilo = Value::some(kilo.shallow_clone());
1481        }
1482        let (bits, ty) = padded_bits(&kilo);
1483        bh.iter(|| {
1484            black_box(Value::from_padded_bits(
1485                &mut BitIter::new(bits.iter().copied()),
1486                ty,
1487            ))
1488        })
1489    }
1490
1491    #[bench]
1492    fn bench_value_create_64k_padded(bh: &mut Bencher) {
1493        let mut kilo = Value::from_byte_array([0xab; 1024]);
1494        for _ in 0..5 {
1495            kilo = Value::product(kilo.shallow_clone(), kilo.shallow_clone());
1496        }
1497        let (bits, ty) = padded_bits(&kilo);
1498        bh.iter(|| {
1499            black_box(Value::from_padded_bits(
1500                &mut BitIter::new(bits.iter().copied()),
1501                ty,
1502            ))
1503        })
1504    }
1505
1506    #[bench]
1507    fn bench_value_create_512_256_padded(bh: &mut Bencher) {
1508        // See comment in bench_value_create_512_256 about this value
1509        let mut s512_256 = Value::product(
1510            Value::from_byte_array([0x12; 64]),
1511            Value::from_byte_array([0x23; 32]),
1512        );
1513        for _ in 0..5 {
1514            s512_256 = Value::product(s512_256.shallow_clone(), s512_256.shallow_clone());
1515        }
1516        let (bits, ty) = padded_bits(&s512_256);
1517        bh.iter(|| {
1518            black_box(Value::from_padded_bits(
1519                &mut BitIter::new(bits.iter().copied()),
1520                ty,
1521            ))
1522        })
1523    }
1524
1525    // Create values from compact bits
1526    fn compact_bits(v: &Value) -> (Vec<u8>, &Final) {
1527        let (bits, _) = v.iter_compact().collect_bits();
1528        (bits, v.ty.as_ref())
1529    }
1530
1531    #[bench]
1532    fn bench_value_create_u64_compact(bh: &mut Bencher) {
1533        let v = Value::u64(0xff00_00ff_ff00_00ff);
1534        let (bits, ty) = compact_bits(&v);
1535        bh.iter(|| {
1536            black_box(Value::from_compact_bits(
1537                &mut BitIter::new(bits.iter().copied()),
1538                ty,
1539            ))
1540        })
1541    }
1542
1543    #[bench]
1544    fn bench_value_create_u2048_compact(bh: &mut Bencher) {
1545        let v = Value::from_byte_array([0xcd; 2048]);
1546        let (bits, ty) = compact_bits(&v);
1547        bh.iter(|| {
1548            black_box(Value::from_compact_bits(
1549                &mut BitIter::new(bits.iter().copied()),
1550                ty,
1551            ))
1552        })
1553    }
1554
1555    #[bench]
1556    fn bench_value_create_deep_some_compact(bh: &mut Bencher) {
1557        let mut kilo = Value::from_byte_array([0xab; 1024]);
1558        for _ in 0..1000 {
1559            kilo = Value::some(kilo.shallow_clone());
1560        }
1561        let (bits, ty) = compact_bits(&kilo);
1562        bh.iter(|| {
1563            black_box(Value::from_compact_bits(
1564                &mut BitIter::new(bits.iter().copied()),
1565                ty,
1566            ))
1567        })
1568    }
1569
1570    #[bench]
1571    fn bench_value_create_64k_compact(bh: &mut Bencher) {
1572        let mut kilo = Value::from_byte_array([0xab; 1024]);
1573        for _ in 0..5 {
1574            kilo = Value::product(kilo.shallow_clone(), kilo.shallow_clone());
1575        }
1576        let (bits, ty) = compact_bits(&kilo);
1577        bh.iter(|| {
1578            black_box(Value::from_compact_bits(
1579                &mut BitIter::new(bits.iter().copied()),
1580                ty,
1581            ))
1582        })
1583    }
1584
1585    #[bench]
1586    fn bench_value_create_512_256_compact(bh: &mut Bencher) {
1587        // See comment in bench_value_create_512_256 about this value
1588        let mut s512_256 = Value::product(
1589            Value::from_byte_array([0x12; 64]),
1590            Value::from_byte_array([0x23; 32]),
1591        );
1592        for _ in 0..5 {
1593            s512_256 = Value::product(s512_256.shallow_clone(), s512_256.shallow_clone());
1594        }
1595        let (bits, ty) = compact_bits(&s512_256);
1596        bh.iter(|| {
1597            black_box(Value::from_compact_bits(
1598                &mut BitIter::new(bits.iter().copied()),
1599                ty,
1600            ))
1601        })
1602    }
1603
1604    // Display values
1605    #[bench]
1606    fn bench_value_display_u64(bh: &mut Bencher) {
1607        let v = Value::u64(0xff00_00ff_ff00_00ff);
1608        bh.iter(|| black_box(format!("{}", v)))
1609    }
1610
1611    #[bench]
1612    fn bench_value_display_u2024(bh: &mut Bencher) {
1613        let v = Value::from_byte_array([0xcd; 2048]);
1614        bh.iter(|| black_box(format!("{}", v)))
1615    }
1616
1617    #[bench]
1618    fn bench_value_display_deep_some(bh: &mut Bencher) {
1619        let mut kilo = Value::from_byte_array([0xab; 1024]);
1620        for _ in 0..1000 {
1621            kilo = Value::some(kilo.shallow_clone());
1622        }
1623        bh.iter(|| black_box(format!("{}", kilo)))
1624    }
1625
1626    #[bench]
1627    fn bench_value_display_64k(bh: &mut Bencher) {
1628        let mut kilo = Value::from_byte_array([0xab; 1024]);
1629        for _ in 0..5 {
1630            kilo = Value::product(kilo.shallow_clone(), kilo.shallow_clone());
1631        }
1632        bh.iter(|| black_box(format!("{}", kilo)))
1633    }
1634
1635    #[bench]
1636    fn bench_value_display_512_256(bh: &mut Bencher) {
1637        // See comment in bench_value_create_512_256 about this value
1638        let mut s512_256 = Value::product(
1639            Value::from_byte_array([0x12; 64]),
1640            Value::from_byte_array([0x23; 32]),
1641        );
1642        for _ in 0..5 {
1643            s512_256 = Value::product(s512_256.shallow_clone(), s512_256.shallow_clone());
1644        }
1645        bh.iter(|| black_box(format!("{}", s512_256)))
1646    }
1647
1648    // Display values
1649}