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#[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 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 pub fn load_stack_value(slice: &mut CellSlice) -> Result<RcStackValue, Error> {
83 let ty = ok!(slice.load_u8());
84 Ok(match ty {
85 0 => Stack::make_null(),
87 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 ok!(slice.skip_first(8, 0));
97 Stack::make_nan()
98 } else if t / 2 == 0 {
99 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 3 => SafeRc::new_dyn_value(ok!(slice.load_reference_cloned())),
108 4 => SafeRc::new_dyn_value(ok!(load_slice_as_stack_value(slice))),
110 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 6 => ok!(load_cont(slice)).into_dyn_value(),
119 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 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 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
501impl 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
561pub 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 #[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
631pub 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
827pub 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
843impl 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 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#[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 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
914impl 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 ok!(builder.store_u8(0x01));
935 builder.store_bigint(self, 64, true)
936 } else {
937 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
985impl 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 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
1049impl 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 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
1113impl 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 b.set_exotic(false);
1134
1135 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
1182impl 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 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
1239pub type Tuple = Vec<RcStackValue>;
1243
1244pub 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 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 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
1383pub(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
1404pub(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
1438impl 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 check_value(SafeRc::new_dyn_value(()));
1535
1536 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 check_value(SafeRc::new_dyn_value(NaN));
1549
1550 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 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 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 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}