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