Skip to main content

tycho_vm/
stack.rs

1use std::mem::ManuallyDrop;
2use std::rc::Rc;
3
4use num_bigint::BigInt;
5use num_traits::{One, ToPrimitive, Zero};
6use tycho_types::error::Error;
7use tycho_types::prelude::*;
8
9use crate::cont::{Cont, RcCont, load_cont};
10use crate::error::{VmError, VmResult};
11use crate::saferc::{SafeDelete, SafeRc, SafeRcMakeMut};
12use crate::util::{OwnedCellSlice, ensure_empty_slice};
13
14/// A stack of values.
15#[derive(Debug, Default, Clone)]
16pub struct Stack {
17    pub items: Vec<RcStackValue>,
18}
19
20impl Stack {
21    pub const MAX_DEPTH: usize = 0xffffff;
22
23    pub fn make_null() -> RcStackValue {
24        thread_local! {
25            static NULL: RcStackValue = SafeRc::new_dyn_value(());
26        }
27        NULL.with(SafeRc::clone)
28    }
29
30    pub fn make_nan() -> RcStackValue {
31        thread_local! {
32            static NAN: RcStackValue = SafeRc::new_dyn_value(NaN);
33        }
34        NAN.with(SafeRc::clone)
35    }
36
37    pub fn make_empty_tuple() -> RcStackValue {
38        thread_local! {
39            static EMPTY_TUPLE: RcStackValue = SafeRc::new_dyn_value(Vec::new());
40        }
41        EMPTY_TUPLE.with(SafeRc::clone)
42    }
43
44    pub fn make_zero() -> RcStackValue {
45        thread_local! {
46            static ONE: RcStackValue = SafeRc::new_dyn_value(BigInt::zero());
47        }
48        ONE.with(SafeRc::clone)
49    }
50
51    pub fn make_minus_one() -> RcStackValue {
52        thread_local! {
53            static MINUS_ONE: RcStackValue = SafeRc::new_dyn_value(-BigInt::one());
54        }
55        MINUS_ONE.with(SafeRc::clone)
56    }
57
58    pub fn make_one() -> RcStackValue {
59        thread_local! {
60            static ONE: RcStackValue = SafeRc::new_dyn_value(BigInt::one());
61        }
62        ONE.with(SafeRc::clone)
63    }
64
65    pub fn make_bool(value: bool) -> RcStackValue {
66        if value {
67            Self::make_minus_one()
68        } else {
69            Self::make_zero()
70        }
71    }
72
73    /// Loads stack value from the cell. Returns an error if data was not fully used.
74    pub fn load_stack_value_from_cell(cell: &DynCell) -> Result<RcStackValue, Error> {
75        let slice = &mut ok!(cell.as_slice());
76        let res = ok!(Self::load_stack_value(slice));
77        ok!(ensure_empty_slice(slice));
78        Ok(res)
79    }
80
81    /// Loads stack value from the slice advancing its cursors.
82    pub fn load_stack_value(slice: &mut CellSlice) -> Result<RcStackValue, Error> {
83        let ty = ok!(slice.load_u8());
84        Ok(match ty {
85            // vm_stk_null#00 = VmStackValue;
86            0 => Stack::make_null(),
87            // vm_stk_tinyint#01 value:int64 = VmStackValue;
88            1 => {
89                let value = ok!(slice.load_u64()) as i64;
90                SafeRc::new_dyn_value(BigInt::from(value))
91            }
92            2 => {
93                let t = ok!(slice.get_u8(0));
94                if t == 0xff {
95                    // vm_stk_nan#02ff = VmStackValue;
96                    ok!(slice.skip_first(8, 0));
97                    Stack::make_nan()
98                } else if t / 2 == 0 {
99                    // vm_stk_int#0201_ value:int257 = VmStackValue;
100                    ok!(slice.skip_first(7, 0));
101                    SafeRc::new_dyn_value(ok!(slice.load_bigint(257, true)))
102                } else {
103                    return Err(Error::InvalidData);
104                }
105            }
106            // vm_stk_cell#03 cell:^Cell = VmStackValue;
107            3 => SafeRc::new_dyn_value(ok!(slice.load_reference_cloned())),
108            // vm_stk_slice#04 _:VmCellSlice = VmStackValue;
109            4 => SafeRc::new_dyn_value(ok!(load_slice_as_stack_value(slice))),
110            // vm_stk_builder#05 cell:^Cell = VmStackValue;
111            5 => {
112                let cell = ok!(slice.load_reference());
113                let mut builder = CellBuilder::new();
114                ok!(builder.store_slice(cell.as_slice_allow_exotic()));
115                SafeRc::new_dyn_value(builder)
116            }
117            // vm_stk_cont#06 cont:VmCont = VmStackValue;
118            6 => ok!(load_cont(slice)).into_dyn_value(),
119            // vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue;
120            7 => {
121                let len = ok!(slice.load_u16()) as usize;
122                let mut tuple = Vec::with_capacity(std::cmp::min(len, 128));
123
124                match len {
125                    0 => {}
126                    1 => {
127                        let value = ok!(slice.load_reference());
128                        tuple.push(ok!(Self::load_stack_value_from_cell(value)));
129                    }
130                    _ => {
131                        let mut head = ok!(slice.load_reference());
132                        let mut tail = ok!(slice.load_reference());
133                        tuple.push(ok!(Self::load_stack_value_from_cell(tail)));
134
135                        for _ in 0..len - 2 {
136                            let slice = &mut ok!(head.as_slice());
137                            head = ok!(slice.load_reference());
138                            tail = ok!(slice.load_reference());
139                            ok!(ensure_empty_slice(slice));
140                            tuple.push(ok!(Self::load_stack_value_from_cell(tail)));
141                        }
142
143                        tuple.push(ok!(Self::load_stack_value_from_cell(head)));
144                        tuple.reverse();
145                    }
146                }
147
148                SafeRc::new_dyn_value(tuple)
149            }
150            _ => return Err(Error::InvalidTag),
151        })
152    }
153
154    pub fn with_items(items: Vec<RcStackValue>) -> Self {
155        Self { items }
156    }
157
158    pub fn depth(&self) -> usize {
159        self.items.len()
160    }
161
162    pub fn display_dump(&self, verbose: bool) -> impl std::fmt::Display + '_ {
163        struct DisplayStack<'a> {
164            items: &'a Vec<RcStackValue>,
165            #[allow(unused)]
166            verbose: bool,
167        }
168
169        impl std::fmt::Display for DisplayStack<'_> {
170            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171                (self.items as &dyn StackValue).display_list().fmt(f)
172            }
173        }
174
175        DisplayStack {
176            items: &self.items,
177            verbose,
178        }
179    }
180
181    /// Reserves capacity for at least `additional` more elements to be inserted.
182    pub fn reserve(&mut self, additional: usize) {
183        self.items.reserve(additional);
184    }
185
186    pub fn push<T: StackValue + 'static>(&mut self, item: T) -> VmResult<()> {
187        self.push_raw(SafeRc::new_dyn_value(item))
188    }
189
190    pub fn push_raw<T: StackValue + ?Sized + 'static>(&mut self, item: SafeRc<T>) -> VmResult<()> {
191        vm_ensure!(
192            self.depth() < Self::MAX_DEPTH,
193            StackUnderflow(Self::MAX_DEPTH)
194        );
195
196        self.items.push(item.into_dyn_value());
197        Ok(())
198    }
199
200    pub fn push_opt<T: StackValue + 'static>(&mut self, value: Option<T>) -> VmResult<()> {
201        match value {
202            None => self.push_null(),
203            Some(value) => self.push(value),
204        }
205    }
206
207    pub fn push_opt_raw<T: StackValue + ?Sized + 'static>(
208        &mut self,
209        item: Option<SafeRc<T>>,
210    ) -> VmResult<()> {
211        match item {
212            None => self.push_null(),
213            Some(item) => self.push_raw(item),
214        }
215    }
216
217    pub fn push_nth(&mut self, idx: usize) -> VmResult<()> {
218        let depth = self.depth();
219        vm_ensure!(idx < depth, StackUnderflow(idx));
220        vm_ensure!(depth + 1 < Self::MAX_DEPTH, StackUnderflow(Self::MAX_DEPTH));
221        self.items.push(self.items[depth - idx - 1].clone());
222        Ok(())
223    }
224
225    pub fn push_null(&mut self) -> VmResult<()> {
226        self.push_raw(Self::make_null())
227    }
228
229    pub fn push_nan(&mut self) -> VmResult<()> {
230        self.push_raw(Self::make_nan())
231    }
232
233    pub fn push_bool(&mut self, value: bool) -> VmResult<()> {
234        self.push_raw(Self::make_bool(value))
235    }
236
237    pub fn push_zero(&mut self) -> VmResult<()> {
238        self.push_raw(Self::make_zero())
239    }
240
241    pub fn push_int<T: Into<BigInt>>(&mut self, value: T) -> VmResult<()> {
242        // TODO: Inline some numbers as thread-local constants to avoid some allocations
243        self.push(value.into())
244    }
245
246    pub fn push_raw_int(&mut self, value: SafeRc<BigInt>, quiet: bool) -> VmResult<()> {
247        if value.bitsize(true) <= 257 {
248            self.push_raw(value)
249        } else if quiet {
250            self.push_nan()
251        } else {
252            vm_bail!(IntegerOverflow)
253        }
254    }
255
256    pub fn move_from_stack(&mut self, other: &mut Self, n: usize) -> VmResult<()> {
257        let Some(new_other_len) = other.depth().checked_sub(n) else {
258            vm_bail!(StackUnderflow(n));
259        };
260        self.items.extend(other.items.drain(new_other_len..));
261        Ok(())
262    }
263
264    pub fn split_top(&mut self, n: usize) -> VmResult<SafeRc<Self>> {
265        let Some(new_depth) = self.depth().checked_sub(n) else {
266            vm_bail!(StackUnderflow(n));
267        };
268        Ok(SafeRc::new(Self {
269            items: self.items.drain(new_depth..).collect(),
270        }))
271    }
272
273    pub fn split_top_ext(&mut self, n: usize, drop: usize) -> VmResult<SafeRc<Self>> {
274        let Some(new_depth) = self.depth().checked_sub(n + drop) else {
275            vm_bail!(StackUnderflow(n + drop));
276        };
277        let res = SafeRc::new(Self {
278            items: self.items.drain(new_depth + drop..).collect(),
279        });
280        self.items.truncate(new_depth);
281        Ok(res)
282    }
283
284    pub fn pop(&mut self) -> VmResult<RcStackValue> {
285        let Some(item) = self.items.pop() else {
286            vm_bail!(StackUnderflow(0));
287        };
288        Ok(item)
289    }
290
291    pub fn pop_bool(&mut self) -> VmResult<bool> {
292        Ok(!ok!(self.pop_int()).is_zero())
293    }
294
295    pub fn pop_int(&mut self) -> VmResult<SafeRc<BigInt>> {
296        ok!(self.pop()).into_int()
297    }
298
299    pub fn pop_int_or_nan(&mut self) -> VmResult<Option<SafeRc<BigInt>>> {
300        let value = ok!(self.pop());
301        if value.raw_ty() == StackValueType::Int as u8 && value.as_int().is_none() {
302            Ok(None)
303        } else {
304            value.into_int().map(Some)
305        }
306    }
307
308    pub fn pop_smallint_range(&mut self, min: u32, max: u32) -> VmResult<u32> {
309        let item = self.pop_int()?;
310        if let Some(item) = item.to_u32()
311            && item >= min
312            && item <= max
313        {
314            return Ok(item);
315        }
316        vm_bail!(IntegerOutOfRange {
317            min: min as isize,
318            max: max as isize,
319            actual: item.to_string(),
320        })
321    }
322
323    pub fn pop_long_range(&mut self, min: u64, max: u64) -> VmResult<u64> {
324        let item = self.pop_int()?;
325        if let Some(item) = item.to_u64()
326            && item >= min
327            && item <= max
328        {
329            return Ok(item);
330        }
331        vm_bail!(IntegerOutOfRange {
332            min: min as isize,
333            max: max as isize,
334            actual: item.to_string(),
335        })
336    }
337
338    pub fn pop_smallint_signed_range(&mut self, min: i32, max: i32) -> VmResult<i32> {
339        let item = self.pop_int()?;
340        into_signed_range(item, min, max)
341    }
342
343    pub fn pop_smallint_signed_range_or_null(
344        &mut self,
345        min: i32,
346        max: i32,
347    ) -> VmResult<Option<i32>> {
348        let item = ok!(self.pop());
349        if item.raw_ty() == StackValueType::Null as u8 {
350            return Ok(None);
351        }
352        into_signed_range(item.into_int()?, min, max).map(Some)
353    }
354
355    pub fn pop_tuple(&mut self) -> VmResult<SafeRc<Tuple>> {
356        self.pop()?.into_tuple()
357    }
358
359    pub fn pop_tuple_range(&mut self, min_len: u32, max_len: u32) -> VmResult<SafeRc<Tuple>> {
360        let tuple = self.pop()?.into_tuple()?;
361        vm_ensure!(
362            (min_len as usize..=max_len as usize).contains(&tuple.len()),
363            InvalidType {
364                expected: StackValueType::Tuple as _,
365                actual: StackValueType::Tuple as _,
366            }
367        );
368        Ok(tuple)
369    }
370
371    pub fn pop_opt_tuple_range(
372        &mut self,
373        min_len: u32,
374        max_len: u32,
375    ) -> VmResult<Option<SafeRc<Tuple>>> {
376        let tuple = {
377            let value = self.pop()?;
378            if value.is_null() {
379                return Ok(None);
380            }
381            value.into_tuple()?
382        };
383
384        vm_ensure!(
385            (min_len as usize..=max_len as usize).contains(&tuple.len()),
386            InvalidType {
387                expected: StackValueType::Tuple as _,
388                actual: StackValueType::Tuple as _,
389            }
390        );
391        Ok(Some(tuple))
392    }
393
394    pub fn pop_cont(&mut self) -> VmResult<RcCont> {
395        self.pop()?.into_cont()
396    }
397
398    pub fn pop_cs(&mut self) -> VmResult<SafeRc<OwnedCellSlice>> {
399        self.pop()?.into_cell_slice()
400    }
401
402    pub fn pop_cs_opt(&mut self) -> VmResult<Option<SafeRc<OwnedCellSlice>>> {
403        let sv = self.pop()?;
404        if sv.is_null() {
405            Ok(None)
406        } else {
407            sv.into_cell_slice().map(Some)
408        }
409    }
410
411    pub fn pop_builder(&mut self) -> VmResult<SafeRc<CellBuilder>> {
412        self.pop()?.into_cell_builder()
413    }
414
415    pub fn pop_cell(&mut self) -> VmResult<SafeRc<Cell>> {
416        self.pop()?.into_cell()
417    }
418
419    pub fn pop_cell_opt(&mut self) -> VmResult<Option<SafeRc<Cell>>> {
420        let sv = self.pop()?;
421        if sv.is_null() {
422            Ok(None)
423        } else {
424            sv.into_cell().map(Some)
425        }
426    }
427
428    pub fn pop_many(&mut self, n: usize) -> VmResult<()> {
429        let Some(new_len) = self.depth().checked_sub(n) else {
430            vm_bail!(StackUnderflow(n));
431        };
432        self.items.truncate(new_len);
433        Ok(())
434    }
435
436    pub fn drop_bottom(&mut self, n: usize) -> VmResult<()> {
437        vm_ensure!(n <= self.depth(), StackUnderflow(n));
438        self.items.drain(..n);
439        Ok(())
440    }
441
442    pub fn swap(&mut self, lhs: usize, rhs: usize) -> VmResult<()> {
443        let depth = self.depth();
444        vm_ensure!(lhs < depth, StackUnderflow(lhs));
445        vm_ensure!(rhs < depth, StackUnderflow(rhs));
446        self.items.swap(depth - lhs - 1, depth - rhs - 1);
447        Ok(())
448    }
449
450    pub fn reverse_range(&mut self, offset: usize, n: usize) -> VmResult<()> {
451        let depth = self.depth();
452        vm_ensure!(offset < depth, StackUnderflow(offset));
453        vm_ensure!(offset + n <= depth, StackUnderflow(offset + n));
454        self.items[depth - offset - n..depth - offset].reverse();
455        Ok(())
456    }
457
458    pub fn fetch(&self, idx: usize) -> VmResult<&RcStackValue> {
459        let depth = self.depth();
460        vm_ensure!(idx < depth, StackUnderflow(idx));
461        Ok(&self.items[depth - idx - 1])
462    }
463
464    pub fn get_exit_arg(&self) -> Option<i32> {
465        let last = self.items.last()?;
466        let last = last.as_int()?;
467        last.to_i32()
468    }
469}
470
471fn into_signed_range(item: SafeRc<BigInt>, min: i32, max: i32) -> VmResult<i32> {
472    if let Some(item) = item.to_i32()
473        && item >= min
474        && item <= max
475    {
476        return Ok(item);
477    }
478    vm_bail!(IntegerOutOfRange {
479        min: min as isize,
480        max: max as isize,
481        actual: item.to_string(),
482    })
483}
484
485impl SafeRcMakeMut for Stack {
486    #[inline]
487    fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
488        Rc::make_mut(rc)
489    }
490}
491
492impl FromIterator<RcStackValue> for Stack {
493    #[inline]
494    fn from_iter<T: IntoIterator<Item = RcStackValue>>(iter: T) -> Self {
495        Self {
496            items: Vec::<RcStackValue>::from_iter(iter),
497        }
498    }
499}
500
501// TODO: impl store with limit
502impl Store for Stack {
503    fn store_into(
504        &self,
505        builder: &mut CellBuilder,
506        context: &dyn CellContext,
507    ) -> Result<(), Error> {
508        let depth = self.depth();
509        if depth > Self::MAX_DEPTH {
510            return Err(Error::IntOverflow);
511        }
512        ok!(builder.store_uint(depth as _, 24));
513
514        if let Some((last, items)) = self.items.split_last() {
515            let mut rest = Cell::empty_cell();
516            for item in items {
517                let mut builder = CellBuilder::new();
518                ok!(builder.store_reference(rest));
519                ok!(item.store_as_stack_value(&mut builder, context));
520                rest = ok!(builder.build_ext(context));
521            }
522
523            ok!(builder.store_reference(rest));
524            ok!(last.store_as_stack_value(builder, context));
525        }
526        Ok(())
527    }
528}
529
530impl<'a> Load<'a> for Stack {
531    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
532        let depth = ok!(slice.load_uint(24)) as usize;
533        if depth == 0 {
534            return Ok(Stack::default());
535        }
536
537        let mut result = Stack {
538            items: Vec::with_capacity(std::cmp::min(depth, 128)),
539        };
540
541        let mut rest = ok!(slice.load_reference());
542        result.items.push(ok!(Self::load_stack_value(slice)));
543
544        if depth > 1 {
545            for _ in 0..depth - 1 {
546                let slice = &mut ok!(rest.as_slice());
547                rest = ok!(slice.load_reference());
548                result.items.push(ok!(Self::load_stack_value(slice)));
549                ok!(ensure_empty_slice(slice));
550            }
551
552            ok!(ensure_empty_slice(&ok!(rest.as_slice())));
553
554            result.items.reverse();
555        }
556
557        Ok(result)
558    }
559}
560
561// === StackValue trait ===
562
563/// [`Stack`] item.
564pub type RcStackValue = SafeRc<dyn StackValue>;
565
566macro_rules! define_stack_value_type {
567    (
568        $(#[$($meta:tt)*])*
569        $vis:vis enum $ident:ident {
570            $($name:ident = $n:literal),*$(,)?
571        }
572    ) => {
573        $(#[$($meta)*])*
574        $vis enum $ident {
575            $($name = $n,)*
576        }
577
578        impl $ident {
579            pub fn from_raw(value: u8) -> Option<Self> {
580                Some(match value {
581                    $($n => Self::$name,)*
582                    _ => return None,
583                })
584            }
585        }
586    };
587}
588
589define_stack_value_type! {
590    /// A value type of [`StackValue`].
591    #[derive(Debug, Clone, Copy, Eq, PartialEq)]
592    #[repr(u8)]
593    #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
594    pub enum StackValueType {
595        Null = 0,
596        Int = 1,
597        Cell = 2,
598        Slice = 3,
599        Builder = 4,
600        Cont = 5,
601        Tuple = 6,
602    }
603}
604
605impl StackValueType {
606    pub fn display_raw(value: u8) -> impl std::fmt::Display + Copy {
607        #[derive(Clone, Copy)]
608        #[repr(transparent)]
609        struct DisplayRaw(u8);
610
611        impl std::fmt::Display for DisplayRaw {
612            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
613                match StackValueType::from_raw(self.0) {
614                    Some(ty) => std::fmt::Debug::fmt(&ty, f),
615                    None => write!(f, "Type#{}", self.0),
616                }
617            }
618        }
619
620        DisplayRaw(value)
621    }
622}
623
624impl From<StackValueType> for u8 {
625    #[inline]
626    fn from(value: StackValueType) -> Self {
627        value as u8
628    }
629}
630
631/// Interface of a [`Stack`] item.
632pub trait StackValue: SafeDelete + std::fmt::Debug {
633    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue>;
634
635    fn raw_ty(&self) -> u8;
636
637    fn store_as_stack_value(
638        &self,
639        builder: &mut CellBuilder,
640        context: &dyn CellContext,
641    ) -> Result<(), Error>;
642
643    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
644
645    fn as_int(&self) -> Option<&BigInt> {
646        None
647    }
648
649    fn try_as_int(&self) -> VmResult<&BigInt> {
650        match self.as_int() {
651            Some(value) => Ok(value),
652            None => Err(invalid_type(self.raw_ty(), StackValueType::Int)),
653        }
654    }
655
656    fn rc_into_int(self: Rc<Self>) -> VmResult<Rc<BigInt>> {
657        Err(invalid_type(self.raw_ty(), StackValueType::Int))
658    }
659
660    fn as_cell(&self) -> Option<&Cell> {
661        None
662    }
663
664    fn try_as_cell(&self) -> VmResult<&Cell> {
665        match self.as_cell() {
666            Some(value) => Ok(value),
667            None => Err(invalid_type(self.raw_ty(), StackValueType::Cell)),
668        }
669    }
670
671    fn rc_into_cell(self: Rc<Self>) -> VmResult<Rc<Cell>> {
672        Err(invalid_type(self.raw_ty(), StackValueType::Cell))
673    }
674
675    fn as_cell_slice(&self) -> Option<&OwnedCellSlice> {
676        None
677    }
678
679    fn try_as_cell_slice(&self) -> VmResult<&OwnedCellSlice> {
680        match self.as_cell_slice() {
681            Some(value) => Ok(value),
682            None => Err(invalid_type(self.raw_ty(), StackValueType::Slice)),
683        }
684    }
685
686    fn rc_into_cell_slice(self: Rc<Self>) -> VmResult<Rc<OwnedCellSlice>> {
687        Err(invalid_type(self.raw_ty(), StackValueType::Slice))
688    }
689
690    fn as_cell_builder(&self) -> Option<&CellBuilder> {
691        None
692    }
693
694    fn try_as_cell_builder(&self) -> VmResult<&CellBuilder> {
695        match self.as_cell_builder() {
696            Some(value) => Ok(value),
697            None => Err(invalid_type(self.raw_ty(), StackValueType::Builder)),
698        }
699    }
700
701    fn rc_into_cell_builder(self: Rc<Self>) -> VmResult<Rc<CellBuilder>> {
702        Err(invalid_type(self.raw_ty(), StackValueType::Builder))
703    }
704
705    fn as_cont(&self) -> Option<&dyn Cont> {
706        None
707    }
708
709    fn try_as_cont(&self) -> VmResult<&dyn Cont> {
710        match self.as_cont() {
711            Some(value) => Ok(value),
712            None => Err(invalid_type(self.raw_ty(), StackValueType::Cont)),
713        }
714    }
715
716    fn rc_into_cont(self: Rc<Self>) -> VmResult<Rc<dyn Cont>> {
717        Err(invalid_type(self.raw_ty(), StackValueType::Cont))
718    }
719
720    fn as_tuple(&self) -> Option<&[RcStackValue]> {
721        None
722    }
723
724    fn try_as_tuple(&self) -> VmResult<&[RcStackValue]> {
725        match self.as_tuple() {
726            Some(value) => Ok(value),
727            None => Err(invalid_type(self.raw_ty(), StackValueType::Tuple)),
728        }
729    }
730
731    fn rc_into_tuple(self: Rc<Self>) -> VmResult<Rc<Tuple>> {
732        Err(invalid_type(self.raw_ty(), StackValueType::Tuple))
733    }
734}
735
736impl dyn StackValue + '_ {
737    pub fn is_null(&self) -> bool {
738        self.raw_ty() == StackValueType::Null as u8
739    }
740
741    pub fn is_tuple(&self) -> bool {
742        self.raw_ty() == StackValueType::Tuple as u8
743    }
744
745    pub fn as_tuple_range(&self, min_len: u32, max_len: u32) -> Option<&[RcStackValue]> {
746        let tuple = self.as_tuple()?;
747        (min_len as usize..=max_len as usize)
748            .contains(&tuple.len())
749            .then_some(tuple)
750    }
751
752    pub fn as_pair(&self) -> Option<(&dyn StackValue, &dyn StackValue)> {
753        match self.as_tuple()? {
754            [first, second] => Some((first.as_ref(), second.as_ref())),
755            _ => None,
756        }
757    }
758
759    pub fn as_list(&self) -> Option<(&dyn StackValue, &dyn StackValue)> {
760        let (head, tail) = self.as_pair()?;
761
762        let mut next = tail;
763        while !next.is_null() {
764            let (_, tail) = next.as_pair()?;
765            next = tail;
766        }
767
768        Some((head, tail))
769    }
770
771    pub fn display_list(&self) -> impl std::fmt::Display + '_ {
772        pub struct DisplayList<'a>(&'a dyn StackValue);
773
774        impl std::fmt::Display for DisplayList<'_> {
775            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
776                self.0.fmt_list(f)
777            }
778        }
779
780        DisplayList(self)
781    }
782
783    fn fmt_list(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
784        if self.is_null() {
785            f.write_str("()")
786        } else if let Some(tuple) = self.as_tuple() {
787            if let Some((head, tail)) = self.as_list() {
788                f.write_str("(")?;
789                head.fmt_list(f)?;
790                tail.fmt_list_tail(f)?;
791                return Ok(());
792            }
793
794            f.write_str("[")?;
795            let mut first = true;
796            for item in tuple {
797                if !std::mem::take(&mut first) {
798                    f.write_str(" ")?;
799                }
800                item.as_ref().fmt_list(f)?;
801            }
802            f.write_str("]")?;
803
804            Ok(())
805        } else {
806            self.fmt_dump(f)
807        }
808    }
809
810    fn fmt_list_tail(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
811        let mut item = self;
812        while !item.is_null() {
813            let Some((head, tail)) = item.as_pair() else {
814                f.write_str(" . ")?;
815                item.fmt_list(f)?;
816                break;
817            };
818
819            f.write_str(" ")?;
820            head.fmt_list(f)?;
821            item = tail;
822        }
823        f.write_str(")")
824    }
825}
826
827/// Static-dispatch type extension for [`StackValue`].
828pub trait StaticStackValue: StackValue {
829    type DynRef<'a>;
830
831    fn known_ty() -> StackValueType;
832    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>>;
833    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>>;
834}
835
836fn invalid_type(actual: u8, expected: StackValueType) -> Box<VmError> {
837    Box::new(VmError::InvalidType {
838        expected: expected as _,
839        actual,
840    })
841}
842
843// === Null ===
844
845impl StackValue for () {
846    #[inline]
847    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
848        self
849    }
850
851    fn raw_ty(&self) -> u8 {
852        StackValueType::Null as _
853    }
854
855    fn store_as_stack_value(
856        &self,
857        builder: &mut CellBuilder,
858        _: &dyn CellContext,
859    ) -> Result<(), Error> {
860        // vm_stk_null#00 = VmStackValue;
861        builder.store_zeros(8)
862    }
863
864    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
865        f.write_str("(null)")
866    }
867}
868
869// === Int (NaN) ===
870
871/// Invalid integer stack value.
872#[derive(Debug, Clone, Copy)]
873pub struct NaN;
874
875impl StackValue for NaN {
876    #[inline]
877    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
878        self
879    }
880
881    fn raw_ty(&self) -> u8 {
882        StackValueType::Int as _
883    }
884
885    fn store_as_stack_value(
886        &self,
887        builder: &mut CellBuilder,
888        _: &dyn CellContext,
889    ) -> Result<(), Error> {
890        // vm_stk_nan#02ff = VmStackValue;
891        builder.store_u16(0x02ff)
892    }
893
894    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
895        f.write_str("NaN")
896    }
897
898    fn try_as_int(&self) -> VmResult<&BigInt> {
899        vm_bail!(IntegerOverflow);
900    }
901
902    fn rc_into_int(self: Rc<Self>) -> VmResult<Rc<BigInt>> {
903        vm_bail!(IntegerOverflow);
904    }
905}
906
907impl SafeRcMakeMut for NaN {
908    #[inline]
909    fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
910        Rc::make_mut(rc)
911    }
912}
913
914// === Int ===
915
916impl StackValue for BigInt {
917    #[inline]
918    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
919        self
920    }
921
922    fn raw_ty(&self) -> u8 {
923        StackValueType::Int as _
924    }
925
926    fn store_as_stack_value(
927        &self,
928        builder: &mut CellBuilder,
929        _: &dyn CellContext,
930    ) -> Result<(), Error> {
931        let bitsize = self.bitsize(true);
932        if bitsize <= 64 {
933            // vm_stk_tinyint#01 value:int64 = VmStackValue;
934            ok!(builder.store_u8(0x01));
935            builder.store_bigint(self, 64, true)
936        } else {
937            // vm_stk_int#0201_ value:int257 = VmStackValue;
938            ok!(builder.store_uint(0x0200 >> 1, 15));
939            builder.store_bigint(self, 257, true)
940        }
941    }
942
943    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
944        std::fmt::Display::fmt(self, f)
945    }
946
947    fn as_int(&self) -> Option<&BigInt> {
948        Some(self)
949    }
950
951    fn rc_into_int(self: Rc<Self>) -> VmResult<Rc<BigInt>> {
952        Ok(self)
953    }
954}
955
956impl StaticStackValue for BigInt {
957    type DynRef<'a> = &'a BigInt;
958
959    fn known_ty() -> StackValueType {
960        StackValueType::Int
961    }
962
963    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>> {
964        value.rc_into_int()
965    }
966
967    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>> {
968        match value.as_int() {
969            Some(value) => Ok(value),
970            None => vm_bail!(InvalidType {
971                expected: StackValueType::Int as _,
972                actual: value.raw_ty(),
973            }),
974        }
975    }
976}
977
978impl SafeRcMakeMut for BigInt {
979    #[inline]
980    fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
981        Rc::make_mut(rc)
982    }
983}
984
985// === Cell ===
986
987impl StackValue for Cell {
988    #[inline]
989    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
990        self
991    }
992
993    fn raw_ty(&self) -> u8 {
994        StackValueType::Cell as _
995    }
996
997    fn store_as_stack_value(
998        &self,
999        builder: &mut CellBuilder,
1000        _: &dyn CellContext,
1001    ) -> Result<(), Error> {
1002        // vm_stk_cell#03 cell:^Cell = VmStackValue;
1003        ok!(builder.store_u8(0x03));
1004        builder.store_reference(self.clone())
1005    }
1006
1007    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1008        write!(f, "C{{{:X}}}", self.repr_hash())
1009    }
1010
1011    fn as_cell(&self) -> Option<&Cell> {
1012        Some(self)
1013    }
1014
1015    fn rc_into_cell(self: Rc<Self>) -> VmResult<Rc<Cell>> {
1016        Ok(self)
1017    }
1018}
1019
1020impl StaticStackValue for Cell {
1021    type DynRef<'a> = &'a Cell;
1022
1023    fn known_ty() -> StackValueType {
1024        StackValueType::Cell
1025    }
1026
1027    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>> {
1028        value.rc_into_cell()
1029    }
1030
1031    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>> {
1032        match value.as_cell() {
1033            Some(value) => Ok(value),
1034            None => vm_bail!(InvalidType {
1035                expected: StackValueType::Cell as _,
1036                actual: value.raw_ty(),
1037            }),
1038        }
1039    }
1040}
1041
1042impl SafeRcMakeMut for Cell {
1043    #[inline]
1044    fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
1045        Rc::make_mut(rc)
1046    }
1047}
1048
1049// === CellSlice ===
1050
1051impl StackValue for OwnedCellSlice {
1052    #[inline]
1053    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
1054        self
1055    }
1056
1057    fn raw_ty(&self) -> u8 {
1058        StackValueType::Slice as _
1059    }
1060
1061    fn store_as_stack_value(
1062        &self,
1063        builder: &mut CellBuilder,
1064        _: &dyn CellContext,
1065    ) -> Result<(), Error> {
1066        // vm_stk_slice#04 _:VmCellSlice = VmStackValue;
1067        ok!(builder.store_u8(0x04));
1068        store_slice_as_stack_value(self, builder)
1069    }
1070
1071    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1072        std::fmt::Display::fmt(self, f)
1073    }
1074
1075    fn as_cell_slice(&self) -> Option<&OwnedCellSlice> {
1076        Some(self)
1077    }
1078
1079    fn rc_into_cell_slice(self: Rc<Self>) -> VmResult<Rc<OwnedCellSlice>> {
1080        Ok(self)
1081    }
1082}
1083
1084impl StaticStackValue for OwnedCellSlice {
1085    type DynRef<'a> = &'a OwnedCellSlice;
1086
1087    fn known_ty() -> StackValueType {
1088        StackValueType::Slice
1089    }
1090
1091    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>> {
1092        value.rc_into_cell_slice()
1093    }
1094
1095    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>> {
1096        match value.as_cell_slice() {
1097            Some(value) => Ok(value),
1098            None => vm_bail!(InvalidType {
1099                expected: StackValueType::Slice as _,
1100                actual: value.raw_ty(),
1101            }),
1102        }
1103    }
1104}
1105
1106impl SafeRcMakeMut for OwnedCellSlice {
1107    #[inline]
1108    fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
1109        Rc::make_mut(rc)
1110    }
1111}
1112
1113// === CellBuilder ===
1114
1115impl StackValue for CellBuilder {
1116    #[inline]
1117    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
1118        self
1119    }
1120
1121    fn raw_ty(&self) -> u8 {
1122        StackValueType::Builder as _
1123    }
1124
1125    fn store_as_stack_value(
1126        &self,
1127        builder: &mut CellBuilder,
1128        context: &dyn CellContext,
1129    ) -> Result<(), Error> {
1130        let mut b = self.clone();
1131        // NOTE: We cannot serialize builders with partially built
1132        // exotic cells because it will fail.
1133        b.set_exotic(false);
1134
1135        // vm_stk_builder#05 cell:^Cell = VmStackValue;
1136        ok!(builder.store_u8(0x05));
1137        builder.store_reference(ok!(b.build_ext(context)))
1138    }
1139
1140    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1141        write!(f, "BC{{{}}}", self.display_data())
1142    }
1143
1144    fn as_cell_builder(&self) -> Option<&CellBuilder> {
1145        Some(self)
1146    }
1147
1148    fn rc_into_cell_builder(self: Rc<Self>) -> VmResult<Rc<CellBuilder>> {
1149        Ok(self)
1150    }
1151}
1152
1153impl StaticStackValue for CellBuilder {
1154    type DynRef<'a> = &'a CellBuilder;
1155
1156    fn known_ty() -> StackValueType {
1157        StackValueType::Builder
1158    }
1159
1160    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>> {
1161        value.rc_into_cell_builder()
1162    }
1163
1164    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>> {
1165        match value.as_cell_builder() {
1166            Some(value) => Ok(value),
1167            None => vm_bail!(InvalidType {
1168                expected: StackValueType::Builder as _,
1169                actual: value.raw_ty(),
1170            }),
1171        }
1172    }
1173}
1174
1175impl SafeRcMakeMut for CellBuilder {
1176    #[inline]
1177    fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
1178        Rc::make_mut(rc)
1179    }
1180}
1181
1182// === Continuation ===
1183
1184impl StackValue for dyn Cont {
1185    #[inline]
1186    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
1187        Cont::rc_into_dyn(self)
1188    }
1189
1190    fn raw_ty(&self) -> u8 {
1191        StackValueType::Cont as _
1192    }
1193
1194    fn store_as_stack_value(
1195        &self,
1196        builder: &mut CellBuilder,
1197        context: &dyn CellContext,
1198    ) -> Result<(), Error> {
1199        // vm_stk_cont#06 cont:VmCont = VmStackValue;
1200        ok!(builder.store_u8(0x06));
1201        self.store_into(builder, context)
1202    }
1203
1204    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1205        write!(f, "Cont{{{:?}}}", self as *const _ as *const ())
1206    }
1207
1208    fn as_cont(&self) -> Option<&dyn Cont> {
1209        Some(self)
1210    }
1211
1212    fn rc_into_cont(self: Rc<Self>) -> VmResult<Rc<dyn Cont>> {
1213        Ok(self)
1214    }
1215}
1216
1217impl StaticStackValue for dyn Cont {
1218    type DynRef<'a> = &'a dyn Cont;
1219
1220    fn known_ty() -> StackValueType {
1221        StackValueType::Cont
1222    }
1223
1224    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>> {
1225        value.rc_into_cont()
1226    }
1227
1228    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>> {
1229        match value.as_cont() {
1230            Some(value) => Ok(value),
1231            None => vm_bail!(InvalidType {
1232                expected: StackValueType::Cont as _,
1233                actual: value.raw_ty(),
1234            }),
1235        }
1236    }
1237}
1238
1239// === Tuple ===
1240
1241/// Multiple [`RcStackValue`]s.
1242pub type Tuple = Vec<RcStackValue>;
1243
1244/// Tuple utilities.
1245pub trait TupleExt {
1246    fn try_get(&self, index: usize) -> VmResult<&RcStackValue>;
1247
1248    fn try_get_owned<V: StaticStackValue>(&self, index: usize) -> VmResult<SafeRc<V>> {
1249        let value = ok!(self.try_get(index));
1250        V::from_dyn(Rc::clone(&*value.0)).map(SafeRc::from)
1251    }
1252
1253    fn try_get_ref<V: StaticStackValue>(&self, index: usize) -> VmResult<V::DynRef<'_>> {
1254        let value = ok!(self.try_get(index));
1255        V::from_dyn_ref(value.as_ref())
1256    }
1257
1258    fn try_get_tuple_range<R>(&self, index: usize, range: R) -> VmResult<&[RcStackValue]>
1259    where
1260        R: std::ops::RangeBounds<usize>,
1261    {
1262        let value = ok!(self.try_get_ref::<Tuple>(index));
1263        if range.contains(&value.len()) {
1264            Ok(value)
1265        } else {
1266            // NOTE: This error is logically incorrect, but it is the desired behaviour.
1267            vm_bail!(InvalidType {
1268                expected: StackValueType::Tuple as _,
1269                actual: StackValueType::Null as _
1270            })
1271        }
1272    }
1273}
1274
1275impl TupleExt for [RcStackValue] {
1276    fn try_get(&self, index: usize) -> VmResult<&RcStackValue> {
1277        let Some(value) = self.get(index) else {
1278            vm_bail!(IntegerOutOfRange {
1279                min: 0,
1280                max: self.len() as _,
1281                actual: index.to_string(),
1282            });
1283        };
1284        Ok(value)
1285    }
1286}
1287
1288impl StackValue for Tuple {
1289    #[inline]
1290    fn rc_into_dyn(self: Rc<Self>) -> Rc<dyn StackValue> {
1291        self
1292    }
1293
1294    fn raw_ty(&self) -> u8 {
1295        StackValueType::Tuple as _
1296    }
1297
1298    fn store_as_stack_value(
1299        &self,
1300        builder: &mut CellBuilder,
1301        context: &dyn CellContext,
1302    ) -> Result<(), Error> {
1303        if self.len() > u16::MAX as usize {
1304            return Err(Error::IntOverflow);
1305        }
1306
1307        let mut head = None::<Cell>;
1308        let mut tail = None::<Cell>;
1309
1310        for item in self {
1311            std::mem::swap(&mut head, &mut tail);
1312
1313            if tail.is_some()
1314                && head.is_some()
1315                && let (Some(t), Some(h)) = (tail.take(), head.take())
1316            {
1317                head = Some(ok!(CellBuilder::build_from_ext((t, h), context)));
1318            }
1319
1320            let mut builder = CellBuilder::new();
1321            ok!(item.store_as_stack_value(&mut builder, context));
1322            tail = Some(ok!(builder.build_ext(context)));
1323        }
1324
1325        // vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue;
1326        ok!(builder.store_u8(0x07));
1327        ok!(builder.store_u16(self.len() as _));
1328        if let Some(head) = head {
1329            ok!(builder.store_reference(head));
1330        }
1331        if let Some(tail) = tail {
1332            ok!(builder.store_reference(tail));
1333        }
1334        Ok(())
1335    }
1336
1337    fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1338        if self.is_empty() {
1339            return f.write_str("[]");
1340        }
1341        f.write_str("[ ")?;
1342        let mut first = true;
1343        for item in self {
1344            if !std::mem::take(&mut first) {
1345                f.write_str(" ")?;
1346            }
1347            StackValue::fmt_dump(item.as_ref(), f)?;
1348        }
1349        f.write_str(" ]")
1350    }
1351
1352    fn as_tuple(&self) -> Option<&[RcStackValue]> {
1353        Some(self)
1354    }
1355
1356    fn rc_into_tuple(self: Rc<Self>) -> VmResult<Rc<Tuple>> {
1357        Ok(self)
1358    }
1359}
1360
1361impl StaticStackValue for Tuple {
1362    type DynRef<'a> = &'a [RcStackValue];
1363
1364    fn known_ty() -> StackValueType {
1365        StackValueType::Tuple
1366    }
1367
1368    fn from_dyn(value: Rc<dyn StackValue>) -> VmResult<Rc<Self>> {
1369        value.rc_into_tuple()
1370    }
1371
1372    fn from_dyn_ref(value: &dyn StackValue) -> VmResult<Self::DynRef<'_>> {
1373        match value.as_tuple() {
1374            Some(value) => Ok(value),
1375            None => vm_bail!(InvalidType {
1376                expected: StackValueType::Tuple as _,
1377                actual: value.raw_ty(),
1378            }),
1379        }
1380    }
1381}
1382
1383// === Store/Load ===
1384
1385/// ```text
1386/// _ cell:^Cell
1387///   st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits }
1388///   st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice;
1389/// ```
1390pub(crate) fn store_slice_as_stack_value(
1391    slice: &OwnedCellSlice,
1392    builder: &mut CellBuilder,
1393) -> Result<(), Error> {
1394    ok!(builder.store_reference(slice.cell().clone()));
1395
1396    let range = slice.range();
1397    let value = ((range.offset_bits() as u64) << 16)
1398        | (((range.offset_bits() + range.size_bits()) as u64) << 6)
1399        | ((range.offset_refs() as u64) << 3)
1400        | (range.offset_refs() + range.size_refs()) as u64;
1401    builder.store_uint(value, 26)
1402}
1403
1404/// ```text
1405/// _ cell:^Cell
1406///   st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits }
1407///   st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice;
1408/// ```
1409pub(crate) fn load_slice_as_stack_value(slice: &mut CellSlice) -> Result<OwnedCellSlice, Error> {
1410    let cell = ok!(slice.load_reference_cloned());
1411    let range = ok!(slice.load_uint(26));
1412
1413    let bits_start = (range >> 16) as u16 & 0x3ff;
1414    let bits_end = (range >> 6) as u16 & 0x3ff;
1415    let refs_start = (range >> 3) as u8 & 0b111;
1416    let refs_end = range as u8 & 0b111;
1417
1418    if bits_start > bits_end || refs_start > refs_end || refs_end > 4 {
1419        return Err(Error::InvalidData);
1420    }
1421
1422    if bits_end > cell.bit_len() || refs_end > cell.reference_count() {
1423        return Err(Error::InvalidData);
1424    }
1425
1426    let mut range = CellSliceRange::full(cell.as_ref());
1427    let ok = range.skip_first(bits_start, refs_start).is_ok();
1428    debug_assert!(ok);
1429
1430    let bits = bits_end - bits_start;
1431    let refs = refs_end - refs_start;
1432    let ok = range.only_first(bits, refs).is_ok();
1433    debug_assert!(ok);
1434
1435    Ok(OwnedCellSlice::from((range, cell)))
1436}
1437
1438// === SafeRc ===
1439
1440impl RcStackValue {
1441    #[inline]
1442    pub fn new_dyn_value<T: StackValue + 'static>(value: T) -> Self {
1443        Self(ManuallyDrop::new(Rc::new(value)))
1444    }
1445
1446    #[inline]
1447    pub fn into_int(self) -> VmResult<SafeRc<BigInt>> {
1448        Self::into_inner(self).rc_into_int().map(SafeRc::from)
1449    }
1450
1451    #[inline]
1452    pub fn into_cell(self) -> VmResult<SafeRc<Cell>> {
1453        Self::into_inner(self).rc_into_cell().map(SafeRc::from)
1454    }
1455
1456    #[inline]
1457    pub fn into_cell_slice(self) -> VmResult<SafeRc<OwnedCellSlice>> {
1458        Self::into_inner(self)
1459            .rc_into_cell_slice()
1460            .map(SafeRc::from)
1461    }
1462
1463    #[inline]
1464    pub fn into_cell_builder(self) -> VmResult<SafeRc<CellBuilder>> {
1465        Self::into_inner(self)
1466            .rc_into_cell_builder()
1467            .map(SafeRc::from)
1468    }
1469
1470    #[inline]
1471    pub fn into_cont(self) -> VmResult<SafeRc<dyn Cont>> {
1472        Self::into_inner(self).rc_into_cont().map(SafeRc::from)
1473    }
1474
1475    #[inline]
1476    pub fn into_tuple(self) -> VmResult<SafeRc<Tuple>> {
1477        Self::into_inner(self).rc_into_tuple().map(SafeRc::from)
1478    }
1479}
1480
1481impl<T: StackValue + ?Sized> SafeRc<T> {
1482    #[inline]
1483    pub fn into_dyn_value(self) -> RcStackValue {
1484        let value = SafeRc::into_inner(self);
1485        SafeRc(ManuallyDrop::new(value.rc_into_dyn()))
1486    }
1487}
1488
1489impl<T: StackValue + 'static> From<T> for RcStackValue {
1490    #[inline]
1491    fn from(value: T) -> Self {
1492        Self(ManuallyDrop::new(Rc::new(value)))
1493    }
1494}
1495
1496impl<T: StackValue + 'static> From<Rc<T>> for RcStackValue {
1497    #[inline]
1498    fn from(value: Rc<T>) -> Self {
1499        Self(ManuallyDrop::new(value))
1500    }
1501}
1502
1503#[cfg(test)]
1504mod tests {
1505    use super::*;
1506
1507    #[test]
1508    fn parse_stack_tuple() {
1509        let cell =
1510            Boc::decode_base64("te6cckEBAwEAHQABGAAAAgEAAAAAAAAAAgEBEgEAAAAAAAAAAQIAAHap0w8=")
1511                .unwrap();
1512
1513        let stack = cell.parse::<Stack>().unwrap();
1514        println!("{:#?}", stack.items);
1515    }
1516
1517    #[test]
1518    fn stack_store_load_works() {
1519        #[track_caller]
1520        fn check_value(value: RcStackValue) {
1521            let mut b = CellBuilder::new();
1522            value
1523                .store_as_stack_value(&mut b, Cell::empty_context())
1524                .unwrap();
1525            let parsed = Stack::load_stack_value(&mut b.as_full_slice()).unwrap();
1526
1527            let value = format!("{}", value.display_list());
1528            let parsed = format!("{}", parsed.display_list());
1529            println!("VALUE: {value}, PARSED: {parsed}");
1530            assert_eq!(value, parsed);
1531        }
1532
1533        // Null
1534        check_value(SafeRc::new_dyn_value(()));
1535
1536        // Int
1537        for negate in [false, true] {
1538            for pow in 0..=256 {
1539                let mut value: BigInt = (BigInt::from(1) << pow) - 1;
1540                if negate {
1541                    value = -value;
1542                }
1543                check_value(SafeRc::new_dyn_value(value));
1544            }
1545        }
1546
1547        // NaN
1548        check_value(SafeRc::new_dyn_value(NaN));
1549
1550        // Cell
1551        check_value(SafeRc::new_dyn_value(
1552            CellBuilder::build_from((
1553                0x123123u32,
1554                HashBytes::wrap(&[0xff; 32]),
1555                Cell::default(),
1556                Cell::default(),
1557            ))
1558            .unwrap(),
1559        ));
1560
1561        // CellSlice
1562        check_value(SafeRc::new_dyn_value({
1563            let cell = CellBuilder::build_from((
1564                0x123123u32,
1565                HashBytes::wrap(&[0xff; 32]),
1566                Cell::default(),
1567                Cell::default(),
1568            ))
1569            .unwrap();
1570            let mut cs = OwnedCellSlice::new_allow_exotic(cell);
1571
1572            {
1573                let mut slice = cs.apply();
1574                slice.skip_first(16, 1).unwrap();
1575                slice.skip_last(8, 0).unwrap();
1576                cs.set_range(slice.range());
1577            }
1578
1579            cs
1580        }));
1581
1582        // CellBuilder
1583        check_value(SafeRc::new_dyn_value({
1584            let mut b = CellBuilder::new();
1585            b.set_exotic(true);
1586            b.store_u32(0x123123).unwrap();
1587            b.store_u256(HashBytes::wrap(&[0xff; 32])).unwrap();
1588            b.store_reference(Cell::default()).unwrap();
1589            b
1590        }));
1591
1592        // Tuple
1593        check_value(SafeRc::new_dyn_value(tuple![]));
1594        check_value(SafeRc::new_dyn_value(tuple![int 0, int 1, int 2]));
1595        check_value(SafeRc::new_dyn_value(
1596            tuple![int 0, int 1, int 2, [int 1, [int 2, [int 3, int 4]]]],
1597        ));
1598        check_value(SafeRc::new_dyn_value(tuple![
1599            raw SafeRc::new_dyn_value(Cell::default()),
1600            raw SafeRc::new_dyn_value(CellBuilder::new()),
1601            null,
1602            nan,
1603        ]));
1604    }
1605}