1use crate::belt::based_check;
2use crate::crypto::cheetah::F6lt;
3#[cfg(feature = "wasm")]
4use alloc::format;
5#[cfg(feature = "wasm")]
6use alloc::string::ToString;
7use alloc::{
8 boxed::Box, collections::btree_map::BTreeMap, string::String, sync::Arc, vec, vec::Vec,
9};
10use bitvec::prelude::{BitSlice, Lsb0};
11use ibig::UBig;
12use num_traits::Zero;
13use serde::de::{Error as DeError, SeqAccess, Visitor};
14use serde::{ser::SerializeSeq, Serialize, Serializer};
15use serde::{Deserialize, Deserializer};
16
17use crate::{belt::Belt, crypto::cheetah::CheetahPoint, Digest};
18
19#[repr(transparent)]
21#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
22pub struct Zeroable<T>(pub Option<T>);
23
24impl<T> core::ops::Deref for Zeroable<T> {
25 type Target = Option<T>;
26
27 fn deref(&self) -> &Self::Target {
28 &self.0
29 }
30}
31
32impl<T> core::ops::DerefMut for Zeroable<T> {
33 fn deref_mut(&mut self) -> &mut Self::Target {
34 &mut self.0
35 }
36}
37
38pub fn noun_serialize<T: NounEncode, S>(v: &T, serializer: S) -> Result<S::Ok, S::Error>
39where
40 S: Serializer,
41{
42 v.to_noun().serialize(serializer)
43}
44
45pub fn noun_deserialize<'de, T: NounDecode, D>(deserializer: D) -> Result<T, D::Error>
46where
47 D: Deserializer<'de>,
48{
49 let r = Noun::deserialize(deserializer)?;
50 T::from_noun(&r).ok_or_else(|| DeError::custom("unable to parse noun"))
51}
52
53const fn mug(mut x: u64) -> u64 {
54 x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9u64);
55 x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111ebu64);
56 x ^ (x >> 31)
57}
58
59const fn mug_bytes(b: &[u8]) -> u64 {
60 let mut ret = 0u64;
61
62 let mut i = 0;
63
64 while i < b.len() {
65 ret = mug(ret.wrapping_add(b[i] as u64));
66 i += 1;
67 }
68
69 mug(ret)
70}
71
72fn mug_noun(noun: &Noun) -> u32 {
73 match noun {
74 Noun::Atom(atom) => mug(mug_bytes(&atom.to_le_bytes())) as u32,
75 Noun::Cell(left, right) => mug(left.0.mug as u64 | ((right.0.mug as u64) << 32)) as u32,
76 }
77}
78
79fn weight_noun(noun: &Noun) -> u32 {
80 match noun {
81 Noun::Atom(_) => 1,
82 Noun::Cell(left, right) => 1 + left.0.weight + right.0.weight,
83 }
84}
85
86#[derive(Clone, Debug)]
87struct HashNounContents {
88 noun: Noun,
89 mug: u32,
90 weight: u32,
91}
92
93impl From<Noun> for HashNounContents {
94 fn from(noun: Noun) -> Self {
95 Self {
96 mug: mug_noun(&noun),
97 weight: weight_noun(&noun),
98 noun,
99 }
100 }
101}
102
103#[derive(Clone, Debug)]
104pub struct HashNoun(Arc<HashNounContents>);
105
106impl From<Noun> for HashNoun {
107 fn from(noun: Noun) -> Self {
108 Self(Arc::new(noun.into()))
109 }
110}
111
112impl core::ops::Deref for HashNoun {
113 type Target = Noun;
114
115 fn deref(&self) -> &Self::Target {
116 &self.0.noun
117 }
118}
119
120#[derive(Clone, Debug)]
130#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
131#[cfg_attr(
132 feature = "wasm",
133 tsify(into_wasm_abi, from_wasm_abi, type = "string | [Noun]")
134)]
135pub enum Noun {
136 Atom(UBig),
137 Cell(HashNoun, HashNoun),
138}
139
140impl PartialEq for Noun {
141 fn eq(&self, other: &Self) -> bool {
142 match (self, other) {
143 (Noun::Atom(a), Noun::Atom(b)) => a == b,
144 (Noun::Cell(a1, b1), Noun::Cell(a2, b2)) => {
145 (Arc::as_ptr(&a1.0) == Arc::as_ptr(&a2.0)
146 && Arc::as_ptr(&b1.0) == Arc::as_ptr(&b2.0))
147 || (a1.0.mug == a2.0.mug
148 && b1.0.mug == b2.0.mug
149 && a1.0.weight == a2.0.weight
150 && b1.0.weight == b2.0.weight
151 && a1.0.noun == a2.0.noun
152 && b1.0.noun == b2.0.noun)
153 }
154 _ => false,
155 }
156 }
157}
158
159impl Eq for Noun {}
160
161impl core::fmt::Display for Noun {
162 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
163 struct AutoCons<'a>(&'a Noun);
164 impl<'a> core::fmt::Display for AutoCons<'a> {
165 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
166 match self.0 {
167 Noun::Atom(a) => write!(f, "{}", a),
168 Noun::Cell(head, tail) => match &**tail {
169 Noun::Cell(_, _) => write!(f, "{} {}", AutoCons(head), AutoCons(tail)),
170 Noun::Atom(a) if a.is_zero() => AutoCons(head).fmt(f),
171 Noun::Atom(_) => write!(f, "{} . {}", AutoCons(head), AutoCons(tail)),
172 },
173 }
174 }
175 }
176
177 match self {
178 Noun::Atom(a) => write!(f, "{}", a),
179 Noun::Cell(_, _) => write!(f, "[{}]", AutoCons(self)),
180 }
181 }
182}
183
184impl Serialize for Noun {
185 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
186 where
187 S: Serializer,
188 {
189 match self {
190 Self::Atom(v) => serializer.serialize_str(&alloc::format!("{v:x}")),
191 Self::Cell(a, b) => {
192 let mut seq = serializer.serialize_seq(None)?;
193
194 seq.serialize_element(&**a)?;
195
196 let mut b = b.clone();
197
198 while let Self::Cell(left, right) = &*b {
199 seq.serialize_element(&**left)?;
200 b = right.clone();
201 }
202
203 seq.serialize_element(&*b)?;
204
205 seq.end()
206 }
207 }
208 }
209}
210
211impl<'de> Deserialize<'de> for Noun {
212 fn deserialize<D>(de: D) -> Result<Self, D::Error>
213 where
214 D: Deserializer<'de>,
215 {
216 struct V;
217
218 impl<'de> Visitor<'de> for V {
219 type Value = Noun;
220
221 fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
222 f.write_str("atom or cell")
223 }
224
225 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
226 where
227 E: DeError,
228 {
229 let n = UBig::from_str_radix(s, 16).map_err(E::custom)?;
230 Ok(Noun::Atom(n))
231 }
232
233 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
234 where
235 A: SeqAccess<'de>,
236 {
237 let mut stack = Vec::new();
238
239 while let Some(noun) = seq.next_element::<Noun>()? {
240 stack.push(noun);
241 }
242
243 if stack.len() < 2 {
244 return Err(DeError::custom("expected at least 2 elements"));
245 }
246
247 let mut top = stack.pop().ok_or_else(|| DeError::custom("empty cell"))?;
248
249 while let Some(noun) = stack.pop() {
250 top = Noun::Cell(noun.into(), top.into());
251 }
252
253 Ok(top)
254 }
255 }
256
257 de.deserialize_any(V)
258 }
259}
260
261pub trait NounCode: NounEncode + NounDecode {}
262impl<T: NounEncode + NounDecode> NounCode for T {}
263
264pub trait NounEncode {
265 fn to_noun(&self) -> Noun;
266}
267
268pub trait NounDecode: Sized {
269 fn from_noun(noun: &Noun) -> Option<Self>;
270}
271
272fn atom(value: u64) -> Noun {
273 Noun::Atom(UBig::from(value))
274}
275
276fn cons(left: Noun, right: Noun) -> Noun {
277 Noun::Cell(left.into(), right.into())
278}
279
280impl<T: NounEncode + ?Sized> NounEncode for &T {
281 fn to_noun(&self) -> Noun {
282 (**self).to_noun()
283 }
284}
285
286impl<T: NounEncode + ?Sized> NounEncode for Arc<T> {
287 fn to_noun(&self) -> Noun {
288 (**self).to_noun()
289 }
290}
291
292impl<T: NounDecode> NounDecode for Arc<T> {
293 fn from_noun(noun: &Noun) -> Option<Self> {
294 Some(Arc::new(T::from_noun(noun)?))
295 }
296}
297
298impl<T: NounEncode + ?Sized> NounEncode for Box<T> {
299 fn to_noun(&self) -> Noun {
300 (**self).to_noun()
301 }
302}
303
304impl<T: NounDecode> NounDecode for Box<T> {
305 fn from_noun(noun: &Noun) -> Option<Self> {
306 Some(Box::new(T::from_noun(noun)?))
307 }
308}
309
310impl NounEncode for Noun {
311 fn to_noun(&self) -> Noun {
312 self.clone()
313 }
314}
315
316impl NounDecode for Noun {
317 fn from_noun(noun: &Noun) -> Option<Self> {
318 Some(noun.clone())
319 }
320}
321
322impl NounEncode for () {
323 fn to_noun(&self) -> Noun {
324 atom(0)
325 }
326}
327
328impl NounDecode for () {
329 fn from_noun(noun: &Noun) -> Option<Self> {
330 if *noun == atom(0) {
331 Some(())
332 } else {
333 None
334 }
335 }
336}
337
338impl NounEncode for Belt {
339 fn to_noun(&self) -> Noun {
340 atom(self.0)
341 }
342}
343
344impl NounDecode for Belt {
345 fn from_noun(noun: &Noun) -> Option<Self> {
346 let Noun::Atom(a) = noun else {
347 return None;
348 };
349 let v = u64::try_from(a).ok()?;
350 if based_check(v) {
351 Some(Belt(v))
352 } else {
353 None
354 }
355 }
356}
357
358impl NounEncode for Digest {
359 fn to_noun(&self) -> Noun {
360 self.0.to_noun()
361 }
362}
363
364impl NounDecode for Digest {
365 fn from_noun(noun: &Noun) -> Option<Self> {
366 Some(Digest(<[Belt; 5]>::from_noun(noun)?))
367 }
368}
369
370impl NounEncode for CheetahPoint {
371 fn to_noun(&self) -> Noun {
372 (self.x.0, self.y.0, self.inf).to_noun()
373 }
374}
375
376impl NounDecode for CheetahPoint {
377 fn from_noun(noun: &Noun) -> Option<Self> {
378 let (x, y, inf) = NounDecode::from_noun(noun)?;
379 Some(Self {
380 x: F6lt(x),
381 y: F6lt(y),
382 inf,
383 })
384 }
385}
386
387macro_rules! impl_nounable_for_int {
388 ($($ty:ty),* $(,)?) => {
389 $(
390 impl NounEncode for $ty {
391 fn to_noun(&self) -> Noun {
392 atom(*self as u64)
393 }
394 }
395
396 impl NounDecode for $ty {
397 fn from_noun(noun: &Noun) -> Option<$ty> {
398 let Noun::Atom(a) = noun else {
399 return None;
400 };
401 <$ty>::try_from(a).ok()
402 }
403 }
404 )*
405 };
406}
407
408impl_nounable_for_int!(i32, i64, isize, u32, u64, usize);
409
410impl NounEncode for bool {
411 fn to_noun(&self) -> Noun {
412 atom(if *self { 0 } else { 1 })
413 }
414}
415
416impl NounDecode for bool {
417 fn from_noun(noun: &Noun) -> Option<Self> {
418 let Noun::Atom(a) = noun else {
419 return None;
420 };
421 if a == &UBig::from(0u64) {
422 Some(true)
423 } else if a == &UBig::from(1u64) {
424 Some(false)
425 } else {
426 None
427 }
428 }
429}
430
431impl<T: NounEncode> NounEncode for Option<T> {
432 fn to_noun(&self) -> Noun {
433 match self {
434 None => atom(0),
435 Some(value) => (0, value.to_noun()).to_noun(),
436 }
437 }
438}
439
440impl<T: NounDecode> NounDecode for Option<T> {
441 fn from_noun(noun: &Noun) -> Option<Self> {
442 match noun {
443 Noun::Cell(x, v) if **x == atom(0) => Some(Some(T::from_noun(v)?)),
444 Noun::Atom(x) if x.is_zero() => Some(None),
445 _ => None,
446 }
447 }
448}
449
450impl<T: NounEncode> NounEncode for Zeroable<T> {
451 fn to_noun(&self) -> Noun {
452 match &self.0 {
453 None => atom(0),
454 Some(value) => value.to_noun(),
455 }
456 }
457}
458
459impl<T: NounDecode> NounDecode for Zeroable<T> {
460 fn from_noun(noun: &Noun) -> Option<Self> {
461 match noun {
462 Noun::Atom(x) if x.is_zero() => Some(Zeroable(None)),
463 Noun::Atom(_) => None,
464 v => Some(Zeroable(Some(T::from_noun(v)?))),
465 }
466 }
467}
468
469macro_rules! impl_nounable_for_tuple {
470 ($T0:ident => $i0:ident) => {};
471 ($T:ident => $t:ident $( $U:ident => $u:ident )+) => {
472 impl<$T: NounEncode, $($U: NounEncode),*> NounEncode for ($T, $($U),*) {
473 fn to_noun(&self) -> Noun {
474 let ($t, $($u),*) = self;
475 cons($t.to_noun(), ($($u),*).to_noun())
476 }
477 }
478
479 impl<$T: NounDecode, $($U: NounDecode),*> NounDecode for ($T, $($U),*) {
480 fn from_noun(noun: &Noun) -> Option<($T, $($U),*)> {
481 let Noun::Cell(a, b) = noun else {
482 return None;
483 };
484 let a = <$T>::from_noun(a)?;
485 #[allow(unused_parens)]
486 let ($($u),*) = <($($U),*)>::from_noun(b)?;
487 Some((a, $($u),*))
488 }
489 }
490
491 impl_nounable_for_tuple!($($U => $u)*);
492 };
493}
494
495impl_nounable_for_tuple!(
496 A => a
497 B => b
498 C => c
499 D => d
500 E => e
501 F => f
502 G => g
503 H => h
504 I => i
505 J => j
506 K => k
507 L => l
508 M => m
509 N => n
510 O => o
511 P => p
512 Q => q
513 R => r
514 S => s
515 T => t
516);
517
518impl<T: NounEncode, const N: usize> NounEncode for [T; N] {
519 fn to_noun(&self) -> Noun {
520 match self.split_last() {
521 None => self[0].to_noun(),
522 Some((last, rest)) => {
523 let mut acc = last.to_noun();
524 for item in rest.iter().rev() {
525 acc = cons(item.to_noun(), acc);
526 }
527 acc
528 }
529 }
530 }
531}
532
533impl<T: NounDecode, const N: usize> NounDecode for [T; N] {
534 fn from_noun(mut noun: &Noun) -> Option<Self> {
535 let mut ret: [Option<T>; N] = [(); N].map(|_| None);
536 for (i, item) in ret.iter_mut().enumerate() {
537 let decode = match noun {
538 Noun::Cell(a, b) => {
539 noun = b;
540 a
541 }
542 v if i == N - 1 => v,
543 _ => return None,
544 };
545 *item = Some(T::from_noun(decode)?);
546 }
547
548 Some(ret.map(|v| v.unwrap()))
549 }
550}
551
552impl<T: NounEncode> NounEncode for &[T] {
553 fn to_noun(&self) -> Noun {
554 match self.split_last() {
555 None => atom(0),
556 Some((last, rest)) => {
557 let mut acc = last.to_noun();
558 for item in rest.iter().rev() {
559 acc = cons(item.to_noun(), acc);
560 }
561 acc
562 }
563 }
564 }
565}
566
567impl<T: NounEncode> NounEncode for Vec<T> {
568 fn to_noun(&self) -> Noun {
569 let mut acc = atom(0);
570 for item in self.iter().rev() {
571 acc = cons(item.to_noun(), acc);
572 }
573 acc
574 }
575}
576
577impl<T: NounDecode> NounDecode for Vec<T> {
578 fn from_noun(mut noun: &Noun) -> Option<Self> {
579 let mut ret = vec![];
580 loop {
581 match noun {
582 Noun::Cell(a, b) => {
583 ret.push(T::from_noun(a)?);
584 noun = b;
585 }
586 Noun::Atom(v) => {
587 if v.is_zero() {
588 return Some(ret);
589 } else {
590 return None;
591 }
592 }
593 }
594 }
595 }
596}
597
598impl NounEncode for &str {
599 fn to_noun(&self) -> Noun {
600 Noun::Atom(UBig::from_le_bytes(self.as_bytes()))
601 }
602}
603
604impl NounEncode for String {
605 fn to_noun(&self) -> Noun {
606 self.as_str().to_noun()
607 }
608}
609
610impl NounDecode for String {
611 fn from_noun(noun: &Noun) -> Option<Self> {
612 let Noun::Atom(a) = noun else {
613 return None;
614 };
615 String::from_utf8(a.to_le_bytes()).ok()
616 }
617}
618
619pub fn jam(noun: Noun) -> Vec<u8> {
621 fn met0_u64_to_usize(value: u64) -> usize {
622 (u64::BITS - value.leading_zeros()) as usize
623 }
624
625 fn met0_atom(atom: &UBig) -> usize {
626 atom.bit_len()
627 }
628
629 fn mat_backref(writer: &mut BitWriter, backref: usize) {
630 if backref == 0 {
631 writer.write_bits_from_value(0b111, 3); return;
633 }
634 let backref_sz = met0_u64_to_usize(backref as u64);
635 let backref_sz_sz = met0_u64_to_usize(backref_sz as u64);
636 writer.write_bit(true);
638 writer.write_bit(true);
639 writer.write_zeros(backref_sz_sz);
641 writer.write_bit(true);
643 writer.write_bits_from_value(backref_sz, backref_sz_sz - 1);
645 writer.write_bits_from_value(backref, backref_sz);
647 }
648
649 fn mat_atom(writer: &mut BitWriter, atom: &UBig) {
650 if atom.is_zero() {
651 writer.write_bits_from_value(0b10, 2); return;
653 }
654 let atom_sz = met0_atom(atom);
655 let atom_sz_sz = met0_u64_to_usize(atom_sz as u64);
656 writer.write_bit(false); writer.write_zeros(atom_sz_sz); writer.write_bit(true); writer.write_bits_from_value(atom_sz, atom_sz_sz - 1);
661 writer.write_bits_from_le_bytes(&atom.to_le_bytes(), atom_sz);
663 }
664
665 fn find_backref(
666 backrefs: &BTreeMap<(u32, u32), Vec<(Noun, usize)>>,
667 weight: u32,
668 mug: u32,
669 target: &Noun,
670 ) -> Option<usize> {
671 backrefs
672 .get(&(weight, mug))
673 .and_then(|vec| vec.iter().find(|(n, _)| n == target))
674 .map(|(_, offset)| *offset)
675 }
676
677 let mut backrefs: BTreeMap<(u32, u32), Vec<(Noun, usize)>> = BTreeMap::new();
678 let mut stack = Vec::new();
679 stack.push((weight_noun(&noun), mug_noun(&noun), noun));
680 let mut buffer = BitWriter::new();
681
682 while let Some((weight, mug, current)) = stack.pop() {
683 if let Some(backref) = find_backref(&backrefs, weight, mug, ¤t) {
684 match ¤t {
685 Noun::Atom(atom) => {
686 if met0_u64_to_usize(backref as u64) < met0_atom(atom) {
687 mat_backref(&mut buffer, backref);
688 } else {
689 mat_atom(&mut buffer, atom);
690 }
691 }
692 Noun::Cell(_, _) => {
693 mat_backref(&mut buffer, backref);
694 }
695 }
696 } else {
697 let offset = buffer.bit_len();
698 backrefs
699 .entry((weight, mug))
700 .or_default()
701 .push((current.clone(), offset));
702 match current {
703 Noun::Atom(atom) => {
704 mat_atom(&mut buffer, &atom);
705 }
706 Noun::Cell(left, right) => {
707 buffer.write_bit(true);
708 buffer.write_bit(false);
709 stack.push((right.0.weight, right.0.mug, (*right).clone()));
710 stack.push((left.0.weight, left.0.mug, (*left).clone()));
711 }
712 }
713 }
714 }
715
716 buffer.into_vec()
717}
718
719pub fn cue(bytes: &[u8]) -> Option<Noun> {
721 cue_bitslice(BitSlice::from_slice(bytes))
722}
723
724pub fn cue_bitslice(buffer: &BitSlice<u8, Lsb0>) -> Option<Noun> {
725 #[derive(Copy, Clone)]
726 enum CueStackEntry {
727 DestinationPointer(*mut Noun),
728 BackRef(u64, *mut Noun),
729 }
730
731 pub fn next_up_to_n_bits<'a>(
732 cursor: &mut usize,
733 slice: &'a BitSlice<u8, Lsb0>,
734 n: usize,
735 ) -> &'a BitSlice<u8, Lsb0> {
736 let res = if (slice).len() >= *cursor + n {
737 &slice[*cursor..*cursor + n]
738 } else if slice.len() > *cursor {
739 &slice[*cursor..]
740 } else {
741 BitSlice::<u8, Lsb0>::empty()
742 };
743 *cursor += n;
744 res
745 }
746
747 pub fn rest_bits(cursor: usize, slice: &BitSlice<u8, Lsb0>) -> &BitSlice<u8, Lsb0> {
748 if slice.len() > cursor {
749 &slice[cursor..]
750 } else {
751 BitSlice::<u8, Lsb0>::empty()
752 }
753 }
754
755 fn get_size(cursor: &mut usize, buffer: &BitSlice<u8, Lsb0>) -> Option<usize> {
756 let buff_at_cursor = rest_bits(*cursor, buffer);
757 let bitsize = buff_at_cursor.first_one()?;
758 if bitsize == 0 {
759 *cursor += 1;
760 Some(0)
761 } else {
762 let mut size = [0u8; 8];
763 *cursor += bitsize + 1;
764 let size_bits = next_up_to_n_bits(cursor, buffer, bitsize - 1);
765 BitSlice::from_slice_mut(&mut size)[0..bitsize - 1].copy_from_bitslice(size_bits);
766 Some((u64::from_le_bytes(size) as usize) + (1 << (bitsize - 1)))
767 }
768 }
769
770 fn rub_backref(cursor: &mut usize, buffer: &BitSlice<u8, Lsb0>) -> Option<u64> {
771 let size = get_size(cursor, buffer)?;
773 if size == 0 {
774 Some(0)
775 } else if size <= 64 {
776 let mut backref = [0u8; 8];
778 BitSlice::from_slice_mut(&mut backref)[0..size]
779 .copy_from_bitslice(&buffer[*cursor..*cursor + size]);
780 *cursor += size;
781 Some(u64::from_le_bytes(backref))
782 } else {
783 None
784 }
785 }
786
787 fn rub_atom(cursor: &mut usize, buffer: &BitSlice<u8, Lsb0>) -> Option<UBig> {
788 let size = get_size(cursor, buffer)?;
789 let bits = next_up_to_n_bits(cursor, buffer, size);
790 if size == 0 {
791 Some(UBig::from(0u64))
792 } else if size < 64 {
793 let mut direct_raw = [0u8; 8];
795 BitSlice::from_slice_mut(&mut direct_raw)[0..bits.len()].copy_from_bitslice(bits);
796 Some(UBig::from(u64::from_le_bytes(direct_raw)))
797 } else {
798 let wordsize = (size + 63) >> 6;
800 let mut bytes = vec![0u8; wordsize * 8];
801 BitSlice::from_slice_mut(&mut bytes)[0..bits.len()].copy_from_bitslice(bits);
802 Some(UBig::from_le_bytes(&bytes))
803 }
804 }
805
806 pub fn next_bit(cursor: &mut usize, slice: &BitSlice<u8, Lsb0>) -> bool {
807 if (*slice).len() > *cursor {
808 let res = slice[*cursor];
809 *cursor += 1;
810 res
811 } else {
812 false
813 }
814 }
815
816 let mut backref_map = BTreeMap::<u64, *mut Noun>::new();
817 let mut result = atom(0);
818 let mut cursor = 0;
819
820 let mut cue_stack = vec![];
821
822 cue_stack.push(CueStackEntry::DestinationPointer(&mut result as *mut Noun));
823
824 while let Some(stack_entry) = cue_stack.pop() {
825 unsafe {
826 match stack_entry {
828 CueStackEntry::DestinationPointer(dest_ptr) => {
829 if next_bit(&mut cursor, buffer) {
831 if next_bit(&mut cursor, buffer) {
833 let backref = rub_backref(&mut cursor, buffer)?;
834 *dest_ptr = (**backref_map.get(&backref)?).clone();
835 } else {
836 let head = HashNoun::from(atom(0));
838 let head_ptr = Arc::as_ptr(&head.0) as *mut _;
839 let tail = HashNoun::from(atom(0));
840 let tail_ptr = Arc::as_ptr(&tail.0) as *mut _;
841 *dest_ptr = Noun::Cell(head, tail);
842 let backref = (cursor - 2) as u64;
843 backref_map.insert(backref, dest_ptr);
844 cue_stack.push(CueStackEntry::BackRef(cursor as u64 - 2, dest_ptr));
845 cue_stack.push(CueStackEntry::DestinationPointer(tail_ptr));
846 cue_stack.push(CueStackEntry::DestinationPointer(head_ptr));
847 }
848 } else {
849 let backref: u64 = (cursor - 1) as u64;
851 *dest_ptr = Noun::Atom(rub_atom(&mut cursor, buffer)?);
852 backref_map.insert(backref, dest_ptr);
853 }
854 }
855 CueStackEntry::BackRef(backref, noun_ptr) => {
856 backref_map.insert(backref, noun_ptr);
857 }
858 }
859 }
860 }
861
862 Some(result)
863}
864
865pub struct BitWriter {
867 buf: Vec<u8>, acc: u8, nbits: u8, bit_len: usize, }
872impl Default for BitWriter {
873 fn default() -> Self {
874 Self::new()
875 }
876}
877
878impl BitWriter {
879 #[inline]
880 pub fn new() -> Self {
881 BitWriter {
882 buf: Vec::with_capacity(1024),
883 acc: 0,
884 nbits: 0,
885 bit_len: 0,
886 }
887 }
888
889 #[inline]
890 pub fn bit_len(&self) -> usize {
891 self.bit_len
892 }
893
894 #[inline]
895 pub fn write_bit(&mut self, bit: bool) {
896 if bit {
897 self.acc |= 1 << self.nbits;
898 }
899 self.nbits += 1;
900 self.bit_len += 1;
901 if self.nbits == 8 {
902 self.flush_acc();
903 }
904 }
905
906 #[inline]
907 pub fn write_zeros(&mut self, count: usize) {
908 let mut remaining = count;
911 if self.nbits != 0 {
912 let space = 8 - self.nbits;
913 if remaining < space as usize {
914 let mask = (1u16 << self.nbits) - 1; self.acc &= mask as u8; self.nbits += remaining as u8;
924 self.bit_len += remaining;
925 return;
926 } else {
927 let mask = (1u16 << self.nbits) - 1; self.acc &= mask as u8; self.nbits = 8;
937 self.bit_len += space as usize;
938 remaining -= space as usize;
939 self.flush_acc();
940 }
941 }
942 let full_bytes = remaining / 8;
944 if full_bytes > 0 {
945 self.buf.extend(core::iter::repeat_n(0u8, full_bytes));
946 self.bit_len += full_bytes * 8;
947 remaining -= full_bytes * 8;
948 }
949 self.nbits = remaining as u8;
951 self.acc = 0; self.bit_len += remaining;
953 }
954
955 #[inline]
956 pub fn write_bits_from_value(&mut self, mut value: usize, count: usize) {
957 for _ in 0..count {
958 self.write_bit((value & 1) == 1);
959 value >>= 1;
960 }
961 }
962
963 #[inline]
964 pub fn write_bits_from_le_bytes(&mut self, bytes: &[u8], total_bits: usize) {
965 if total_bits == 0 {
966 return;
967 }
968
969 let full_bytes = total_bits / 8;
970 let rem_bits: usize = total_bits % 8;
971
972 if self.nbits == 0 {
973 if full_bytes > 0 {
975 self.buf.extend_from_slice(&bytes[..full_bytes]);
976 self.bit_len += full_bytes * 8;
977 }
978 } else if full_bytes > 0 {
979 let shift = self.nbits;
981 let mut carry = self.acc;
982 for &byte in &bytes[..full_bytes] {
983 let combined = carry | (byte << shift);
984 self.buf.push(combined);
985 self.bit_len += 8;
986 carry = byte >> (8 - shift);
987 }
988 self.acc = carry;
989 }
991
992 if rem_bits > 0 {
994 let src_byte = if full_bytes < bytes.len() {
995 bytes[full_bytes]
996 } else {
997 0
998 };
999 for i in 0..rem_bits {
1000 self.write_bit(((src_byte >> i) & 1) == 1);
1001 }
1002 }
1003 }
1007
1008 #[inline]
1009 pub fn flush_acc(&mut self) {
1010 if self.nbits == 0 {
1011 return;
1012 }
1013 self.buf.push(self.acc);
1014 self.acc = 0;
1015 self.nbits = 0;
1016 }
1017
1018 pub fn into_vec(mut self) -> Vec<u8> {
1019 if self.nbits > 0 {
1020 self.flush_acc();
1022 }
1023 self.buf
1024 }
1025}