1use std::collections::BTreeMap;
2use std::num::NonZeroU8;
3
4use num_bigint::{BigUint, Sign};
5
6use crate::abi::{
7 AbiHeader, AbiHeaderType, AbiType, AbiValue, AbiVersion, NamedAbiValue, PlainAbiType,
8 PlainAbiValue,
9};
10use crate::cell::{
11 Cell, CellBuilder, CellContext, CellSlice, CellTreeStats, Size, Store, MAX_BIT_LEN,
12 MAX_REF_COUNT,
13};
14use crate::dict::{self, RawDict};
15use crate::error::Error;
16use crate::models::IntAddr;
17use crate::num::Tokens;
18use crate::prelude::CellFamily;
19
20impl NamedAbiValue {
21 pub fn tuple_to_builder(items: &[Self], version: AbiVersion) -> Result<CellBuilder, Error> {
23 let context = &mut Cell::empty_context();
24 let mut serializer = AbiSerializer::new(version);
25 for item in items {
26 serializer.reserve_value(&item.value);
27 }
28 for item in items {
29 ok!(serializer.write_value(&item.value, context));
30 }
31 serializer.finalize(context)
32 }
33
34 pub fn tuple_to_cell(items: &[Self], version: AbiVersion) -> Result<Cell, Error> {
36 Self::tuple_to_builder(items, version).and_then(CellBuilder::build)
37 }
38
39 pub fn make_builder(&self, version: AbiVersion) -> Result<CellBuilder, Error> {
41 self.value.make_builder(version)
42 }
43
44 pub fn make_cell(&self, version: AbiVersion) -> Result<Cell, Error> {
46 self.value.make_cell(version)
47 }
48}
49
50impl AbiValue {
51 pub fn tuple_to_builder(values: &[Self], version: AbiVersion) -> Result<CellBuilder, Error> {
53 let context = &mut Cell::empty_context();
54 let mut serializer = AbiSerializer::new(version);
55 for value in values {
56 serializer.reserve_value(value);
57 }
58 for value in values {
59 ok!(serializer.write_value(value, context));
60 }
61 serializer.finalize(context)
62 }
63
64 pub fn tuple_to_cell(values: &[Self], version: AbiVersion) -> Result<Cell, Error> {
66 Self::tuple_to_builder(values, version).and_then(CellBuilder::build)
67 }
68
69 pub fn make_builder(&self, version: AbiVersion) -> Result<CellBuilder, Error> {
71 let context = &mut Cell::empty_context();
72 let mut serializer = AbiSerializer::new(version);
73 serializer.reserve_value(self);
74 ok!(serializer.write_value(self, context));
75 serializer.finalize(context)
76 }
77
78 pub fn make_cell(&self, version: AbiVersion) -> Result<Cell, Error> {
80 self.make_builder(version).and_then(CellBuilder::build)
81 }
82
83 fn compute_size_full(&self, version: AbiVersion) -> CellTreeStats {
84 if version.use_max_size() {
85 self.compute_max_size_full()
86 } else {
87 self.compute_exact_size_full()
88 }
89 }
90
91 fn compute_max_size_full(&self) -> CellTreeStats {
92 if let Self::Tuple(items) = self {
93 items
94 .iter()
95 .map(|item| item.value.compute_max_size_full())
96 .sum()
97 } else {
98 self.compute_max_size_short().into()
99 }
100 }
101
102 fn compute_exact_size_full(&self) -> CellTreeStats {
103 if let Self::Tuple(items) = self {
104 items
105 .iter()
106 .map(|item| item.value.compute_exact_size_full())
107 .sum()
108 } else {
109 self.compute_exact_size_short().into()
110 }
111 }
112
113 fn compute_exact_size_short(&self) -> Size {
114 fn compute_varuint_size(n: &NonZeroU8, value: &BigUint) -> Size {
115 let value_bytes: u8 = n.get() - 1;
116 let len_bits = (8 - value_bytes.leading_zeros()) as u16;
117 let value_bits = std::cmp::max(8, 8 * ((value.bits() + 7) / 8) as u16);
118 Size {
119 bits: len_bits + value_bits,
120 refs: 0,
121 }
122 }
123
124 match self {
125 Self::Uint(n, _) | Self::Int(n, _) => Size { bits: *n, refs: 0 },
126 Self::VarUint(n, value) => compute_varuint_size(n, value),
127 Self::VarInt(n, value) => compute_varuint_size(n, value.magnitude()),
128 Self::Bool(_) => Size { bits: 1, refs: 0 },
129 Self::Cell(_)
130 | Self::Bytes(_)
131 | Self::FixedBytes(_)
132 | Self::String(_)
133 | Self::Ref(_) => Size { bits: 0, refs: 1 },
134 Self::Address(value) => Size {
135 bits: value.bit_len(),
136 refs: 0,
137 },
138 Self::Token(tokens) => Size {
139 bits: tokens.bit_len().unwrap_or(Tokens::MAX_BITS),
140 refs: 0,
141 },
142 Self::Array(_, values) => Size {
143 bits: 33,
144 refs: !values.is_empty() as u8,
145 },
146 Self::FixedArray(_, values) => Size {
147 bits: 1,
148 refs: !values.is_empty() as u8,
149 },
150 Self::Map(_, _, values) => Size {
151 bits: 1,
152 refs: !values.is_empty() as u8,
153 },
154 Self::Optional(ty, value) => {
155 if let Some(value) = value {
156 let ty_size = ty.max_size();
157 if ty_size.bit_count < MAX_BIT_LEN as u64
158 && ty_size.cell_count < MAX_REF_COUNT as u64
159 {
160 Size { bits: 1, refs: 0 } + value.compute_exact_size_short()
161 } else {
162 Size { bits: 1, refs: 1 }
163 }
164 } else {
165 Size { bits: 1, refs: 0 }
166 }
167 }
168 Self::Tuple(items) => {
169 let mut size = Size::ZERO;
170 for item in items {
171 size = size.saturating_add(item.value.compute_exact_size_short());
172 }
173 size
174 }
175 }
176 }
177
178 fn compute_max_size_short(&self) -> Size {
179 match self {
180 Self::Uint(n, _) | Self::Int(n, _) => Size { bits: *n, refs: 0 },
181 Self::VarUint(n, _) | Self::VarInt(n, _) => {
182 let value_bytes: u8 = n.get() - 1;
183 let bits = (8 - value_bytes.leading_zeros()) as u16 + (value_bytes as u16 * 8);
184 Size { bits, refs: 0 }
185 }
186 Self::Bool(_) => Size { bits: 1, refs: 0 },
187 Self::Cell(_)
188 | Self::Bytes(_)
189 | Self::FixedBytes(_)
190 | Self::String(_)
191 | Self::Ref(_) => Size { bits: 0, refs: 1 },
192 Self::Address(_) => Size {
193 bits: IntAddr::BITS_MAX,
194 refs: 0,
195 },
196 Self::Token(_) => Size {
197 bits: Tokens::MAX_BITS,
198 refs: 0,
199 },
200 Self::Array(..) => Size { bits: 33, refs: 1 },
201 Self::FixedArray(..) | Self::Map(..) => Size { bits: 1, refs: 1 },
202 Self::Optional(ty, _) => {
203 let ty_size = ty.max_size();
204 if ty_size.bit_count < MAX_BIT_LEN as u64
205 && ty_size.cell_count < MAX_REF_COUNT as u64
206 {
207 Size {
208 bits: 1 + ty_size.bit_count as u16,
209 refs: ty_size.cell_count as u8,
210 }
211 } else {
212 Size { bits: 1, refs: 1 }
213 }
214 }
215 Self::Tuple(items) => {
216 let mut size = Size::ZERO;
217 for item in items {
218 size = size.saturating_add(item.value.compute_max_size_short());
219 }
220 size
221 }
222 }
223 }
224}
225
226pub(crate) struct AbiSerializer {
227 version: AbiVersion,
228 current: Size,
229 remaining_total: CellTreeStats,
230 stack: Vec<CellBuilder>,
231}
232
233impl AbiSerializer {
234 pub fn new(version: AbiVersion) -> Self {
235 Self {
236 version,
237 current: Size::ZERO,
238 remaining_total: CellTreeStats::ZERO,
239 stack: Vec::new(),
240 }
241 }
242
243 pub fn add_offset(&mut self, offset: Size) {
244 self.current += offset;
245 }
246
247 pub fn reserve_value(&mut self, value: &AbiValue) {
248 self.remaining_total += value.compute_size_full(self.version);
249 }
250
251 pub fn reserve_headers(&mut self, headers: &[AbiHeaderType], has_public_key: bool) {
252 for header in headers {
253 self.remaining_total.bit_count += match header {
254 AbiHeaderType::Time => 64,
255 AbiHeaderType::Expire => 32,
256 AbiHeaderType::PublicKey => {
257 1 + if self.version.use_max_size() || has_public_key {
258 256
259 } else {
260 0
261 }
262 }
263 };
264 }
265 }
266
267 pub fn finalize(mut self, context: &mut dyn CellContext) -> Result<CellBuilder, Error> {
268 debug_assert_eq!(self.remaining_total, CellTreeStats::ZERO);
269
270 let mut result = self.stack.pop().unwrap_or_default();
271 while let Some(builder) = self.stack.pop() {
272 let child = ok!(std::mem::replace(&mut result, builder).build_ext(context));
273 ok!(result.store_reference(child));
274 }
275 Ok(result)
276 }
277
278 pub fn take_finalize(&mut self, context: &mut dyn CellContext) -> Result<CellBuilder, Error> {
279 debug_assert_eq!(self.remaining_total, CellTreeStats::ZERO);
280
281 self.current = Size::ZERO;
282 self.remaining_total = CellTreeStats::ZERO;
283
284 let mut result = self.stack.pop().unwrap_or_default();
285 while let Some(builder) = self.stack.pop() {
286 let child = ok!(std::mem::replace(&mut result, builder).build_ext(context));
287 ok!(result.store_reference(child));
288 }
289 Ok(result)
290 }
291
292 fn begin_child(&self) -> Self {
293 Self::new(self.version)
294 }
295
296 fn require_builder(&mut self, value_size: Size) -> &mut CellBuilder {
297 if self.stack.is_empty() {
298 self.stack.push(CellBuilder::new());
299 }
300
301 self.remaining_total -= value_size;
302
303 let remaining = Size::MAX - self.current;
304
305 let store_inline = if value_size.bits > remaining.bits || value_size.refs > remaining.refs {
306 false
307 } else if value_size.refs > 0 && value_size.refs == remaining.refs {
308 self.version.major != 1
309 && self.remaining_total.cell_count == 0
310 && self.remaining_total.bit_count + value_size.bits as u64 <= remaining.bits as u64
311 } else {
312 true
313 };
314
315 if !store_inline {
316 self.current = Size::ZERO;
317 self.stack.push(CellBuilder::new());
318 }
319
320 self.current += value_size;
321
322 unsafe { self.stack.last_mut().unwrap_unchecked() }
324 }
325
326 pub(crate) fn write_header_value(&mut self, value: &AbiHeader) -> Result<(), Error> {
327 match value {
328 AbiHeader::Time(value) => self
329 .require_builder(Size { bits: 64, refs: 0 })
330 .store_u64(*value),
331 AbiHeader::Expire(value) => self
332 .require_builder(Size { bits: 32, refs: 0 })
333 .store_u32(*value),
334 AbiHeader::PublicKey(value) => {
335 let target = self.require_builder(Size {
336 bits: 1 + if self.version.use_max_size() || value.is_some() {
337 256
338 } else {
339 0
340 },
341 refs: 0,
342 });
343 match value {
344 None => target.store_bit_zero(),
345 Some(value) => {
346 ok!(target.store_bit_one());
347 target.store_raw(value.as_bytes(), 256)
348 }
349 }
350 }
351 }
352 }
353
354 pub(crate) fn write_value(
355 &mut self,
356 value: &AbiValue,
357 c: &mut dyn CellContext,
358 ) -> Result<(), Error> {
359 match value {
360 AbiValue::Uint(n, value) => self.write_int(*n, Sign::Plus, value),
361 AbiValue::Int(n, value) => self.write_int(*n, value.sign(), value.magnitude()),
362 AbiValue::VarUint(n, value) => self.write_varint(*n, Sign::Plus, value),
363 AbiValue::VarInt(n, value) => self.write_varint(*n, value.sign(), value.magnitude()),
364 AbiValue::Bool(value) => self.write_bool(*value),
365 AbiValue::Cell(value) => self.write_cell(value),
366 AbiValue::Address(value) => self.write_address(value),
367 AbiValue::Bytes(value) | AbiValue::FixedBytes(value) => self.write_bytes(value, c),
368 AbiValue::String(value) => self.write_bytes(value.as_bytes(), c),
369 AbiValue::Token(value) => self.write_tokens(value),
370 AbiValue::Tuple(items) => self.write_tuple(items, c),
371 AbiValue::Array(ty, values) => self.write_array(ty, values, false, c),
372 AbiValue::FixedArray(ty, values) => self.write_array(ty, values, true, c),
373 AbiValue::Map(k, v, values) => self.write_map(k, v, values, c),
374 AbiValue::Optional(ty, value) => self.write_optional(ty, value.as_deref(), c),
375 AbiValue::Ref(value) => self.write_ref(value, c),
376 }
377 }
378
379 pub(crate) fn write_tuple(
380 &mut self,
381 items: &[NamedAbiValue],
382 context: &mut dyn CellContext,
383 ) -> Result<(), Error> {
384 for item in items {
385 ok!(self.write_value(&item.value, context));
386 }
387 Ok(())
388 }
389
390 fn write_int(&mut self, bits: u16, sign: Sign, value: &BigUint) -> Result<(), Error> {
391 let target = self.require_builder(Size { bits, refs: 0 });
392 write_int(bits, sign, value, target)
393 }
394
395 fn write_varint(&mut self, size: NonZeroU8, sign: Sign, value: &BigUint) -> Result<(), Error> {
396 let is_negative = sign == Sign::Minus;
397 let bytes = to_signed_bytes_be(is_negative, value);
398
399 let max_value_size = size.get() - 1;
400 if bytes.len() > max_value_size as usize {
401 return Err(Error::IntOverflow);
402 }
403
404 let len_bits = (8 - max_value_size.leading_zeros()) as u16;
405 let value_bits = (bytes.len() * 8) as u16;
406
407 let target = self.require_builder(Size {
408 bits: if self.version.use_max_size() {
409 len_bits + (max_value_size as u16) * 8
410 } else {
411 len_bits + value_bits
412 },
413 refs: 0,
414 });
415
416 ok!(target.store_small_uint(bytes.len() as u8, len_bits));
417 target.store_raw(&bytes, value_bits)
418 }
419
420 fn write_bool(&mut self, value: bool) -> Result<(), Error> {
421 let target = self.require_builder(Size { bits: 1, refs: 0 });
422 target.store_bit(value)
423 }
424
425 fn write_cell(&mut self, cell: &Cell) -> Result<(), Error> {
426 let target = self.require_builder(Size { bits: 0, refs: 1 });
427 target.store_reference(cell.clone())
428 }
429
430 fn write_address(&mut self, address: &IntAddr) -> Result<(), Error> {
431 let target = self.require_builder(Size {
432 bits: if self.version.use_max_size() {
433 IntAddr::BITS_MAX
434 } else {
435 address.bit_len()
436 },
437 refs: 0,
438 });
439 address.store_into(target, &mut Cell::empty_context())
440 }
441
442 fn write_tokens(&mut self, tokens: &Tokens) -> Result<(), Error> {
443 let target = self.require_builder(Size {
444 bits: if self.version.use_max_size() {
445 Tokens::MAX_BITS
446 } else {
447 tokens.bit_len().unwrap_or(Tokens::MAX_BITS)
448 },
449 refs: 0,
450 });
451 tokens.store_into(target, &mut Cell::empty_context())
452 }
453
454 fn write_bytes(&mut self, mut data: &[u8], context: &mut dyn CellContext) -> Result<(), Error> {
455 const MAX_BYTES_PER_BUILDER: usize = (MAX_BIT_LEN / 8) as usize;
456 let mut len = data.len();
457
458 let mut bytes_per_builder = if self.version.major > 1 {
459 match len % MAX_BYTES_PER_BUILDER {
460 0 => MAX_BYTES_PER_BUILDER,
461 x => x,
462 }
463 } else {
464 std::cmp::min(MAX_BYTES_PER_BUILDER, len)
465 };
466
467 let mut result = CellBuilder::new();
468 while len > 0 {
469 len -= bytes_per_builder;
470 let (head, tail) = data.split_at(len);
471 data = head;
472
473 if result.size_bits() > 0 {
474 let child = ok!(std::mem::take(&mut result).build_ext(context));
475 ok!(result.store_reference(child));
476 }
477
478 ok!(result.store_raw(tail, (bytes_per_builder * 8) as u16));
479
480 bytes_per_builder = std::cmp::min(MAX_BYTES_PER_BUILDER, len);
481 }
482
483 let target = self.require_builder(Size { bits: 0, refs: 1 });
484 target.store_reference(ok!(result.build()))
485 }
486
487 fn write_array(
488 &mut self,
489 value_ty: &AbiType,
490 values: &[AbiValue],
491 fixed_len: bool,
492 context: &mut dyn CellContext,
493 ) -> Result<(), Error> {
494 let inline_value = fits_into_dict_leaf(32, value_ty.max_bits());
495
496 let mut dict = RawDict::<32>::new();
497 let mut key_builder = CellBuilder::new();
498 let mut serializer = self.begin_child();
499 for (i, value) in values.iter().enumerate() {
500 ok!(key_builder.store_u32(i as u32));
501
502 let value = {
503 serializer.reserve_value(value);
504 ok!(serializer.write_value(value, context));
505 ok!(serializer.take_finalize(context))
506 };
507 let value = if inline_value {
508 InlineOrRef::Inline(value.as_full_slice())
509 } else {
510 InlineOrRef::Ref(ok!(value.build_ext(context)))
511 };
512
513 ok!(dict.set(key_builder.as_data_slice(), value));
514
515 ok!(key_builder.rewind(32));
516 }
517
518 let bits = 1 + if fixed_len { 1 } else { 32 };
519 let refs = if self.version.use_max_size() {
520 1
521 } else {
522 !values.is_empty() as u8
523 };
524
525 let target = self.require_builder(Size { bits, refs });
526
527 if !fixed_len {
528 ok!(target.store_u32(values.len() as u32));
529 }
530 dict.store_into(target, context)
531 }
532
533 fn write_map(
534 &mut self,
535 key_ty: &PlainAbiType,
536 value_ty: &AbiType,
537 value: &BTreeMap<PlainAbiValue, AbiValue>,
538 context: &mut dyn CellContext,
539 ) -> Result<(), Error> {
540 let key_bits = key_ty.key_bits();
541 let inline_value = fits_into_dict_leaf(key_bits, value_ty.max_bits());
542
543 let mut dict = None::<Cell>;
544 let mut key_builder = CellBuilder::new();
545 let mut serializer = self.begin_child();
546 for (key, value) in value {
547 ok!(key.store_into(&mut key_builder, context));
548
549 let value = {
550 serializer.reserve_value(value);
551 ok!(serializer.write_value(value, context));
552 ok!(serializer.take_finalize(context))
553 };
554 let value = if inline_value {
555 InlineOrRef::Inline(value.as_full_slice())
556 } else {
557 InlineOrRef::Ref(ok!(value.build_ext(context)))
558 };
559
560 ok!(dict::dict_insert(
561 &mut dict,
562 &mut key_builder.as_data_slice(),
563 key_bits,
564 &value,
565 dict::SetMode::Set,
566 context,
567 ));
568
569 ok!(key_builder.rewind(key_builder.size_bits()));
570 }
571
572 let target = self.require_builder(Size { bits: 1, refs: 1 });
573 dict.store_into(target, context)
574 }
575
576 fn write_optional(
577 &mut self,
578 ty: &AbiType,
579 value: Option<&AbiValue>,
580 context: &mut dyn CellContext,
581 ) -> Result<(), Error> {
582 let (max_size, inline) = {
583 let ty_size = ty.max_size();
584 if ty_size.bit_count < MAX_BIT_LEN as _ && ty_size.cell_count < MAX_REF_COUNT as _ {
585 let size = Size {
586 bits: 1 + ty_size.bit_count as u16,
587 refs: ty_size.cell_count as u8,
588 };
589 (size, true)
590 } else {
591 (Size { bits: 1, refs: 1 }, false)
592 }
593 };
594
595 match value {
596 Some(value) => {
597 let value = {
598 let mut serializer = self.begin_child();
599 serializer.reserve_value(value);
600 ok!(serializer.write_value(value, context));
601 ok!(serializer.finalize(context))
602 };
603
604 let target = self.require_builder(if self.version.use_max_size() {
605 max_size
606 } else if inline {
607 Size {
608 bits: 1 + value.size_bits(),
609 refs: value.size_refs(),
610 }
611 } else {
612 Size { bits: 1, refs: 1 }
613 });
614
615 ok!(target.store_bit(true));
616 if inline {
617 target.store_builder(&value)
618 } else {
619 target.store_reference(ok!(value.build_ext(context)))
620 }
621 }
622 None => {
623 let target = self.require_builder(if self.version.use_max_size() {
624 max_size
625 } else {
626 Size { bits: 1, refs: 0 }
627 });
628 target.store_bit(false)
629 }
630 }
631 }
632
633 fn write_ref(&mut self, value: &AbiValue, context: &mut dyn CellContext) -> Result<(), Error> {
634 let cell = {
635 let mut serializer = self.begin_child();
636 serializer.reserve_value(value);
637 ok!(serializer.write_value(value, context));
638 let builder = ok!(serializer.finalize(context));
639 ok!(builder.build_ext(context))
640 };
641 let target = self.require_builder(Size { bits: 0, refs: 1 });
642 target.store_reference(cell)
643 }
644}
645
646fn to_signed_bytes_be(is_negative: bool, value: &BigUint) -> Vec<u8> {
647 #[inline]
648 fn is_zero(value: &u8) -> bool {
649 *value == 0
650 }
651
652 #[inline]
653 pub fn twos_complement_le(digits: &mut [u8]) {
654 let mut carry = true;
655 for digit in digits {
656 *digit = !*digit;
657 if carry {
658 let (d, c) = digit.overflowing_add(1);
659 *digit = d;
660 carry = c;
661 }
662 }
663 }
664
665 fn negative_to_signed_bytes_be(value: &BigUint) -> Vec<u8> {
666 let mut bytes = value.to_bytes_le();
667 let last_byte = bytes.last().cloned().unwrap_or(0);
668 if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(is_zero)) {
669 bytes.push(0);
671 }
672 twos_complement_le(&mut bytes);
673 bytes.reverse();
674 bytes
675 }
676
677 if is_negative {
678 negative_to_signed_bytes_be(value)
679 } else {
680 value.to_bytes_be()
681 }
682}
683
684const fn fits_into_dict_leaf(key_bits: u16, value_bits: usize) -> bool {
685 const LABEL_OFFSET: usize = 12;
688
689 LABEL_OFFSET + key_bits as usize + value_bits <= MAX_BIT_LEN as usize
690}
691
692enum InlineOrRef<'a> {
693 Inline(CellSlice<'a>),
694 Ref(Cell),
695}
696
697impl Store for InlineOrRef<'_> {
698 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
699 match self {
700 Self::Inline(slice) => builder.store_slice(slice),
701 Self::Ref(cell) => builder.store_reference(cell.clone()),
702 }
703 }
704}
705
706impl Store for PlainAbiValue {
707 fn store_into(&self, builder: &mut CellBuilder, f: &mut dyn CellContext) -> Result<(), Error> {
708 match self {
709 Self::Uint(bits, value) => write_int(*bits, Sign::Plus, value, builder),
710 Self::Int(bits, value) => write_int(*bits, value.sign(), value.magnitude(), builder),
711 Self::Bool(bit) => builder.store_bit(*bit),
712 Self::Address(address) => address.store_into(builder, f),
713 }
714 }
715}
716
717impl AbiVersion {
718 fn use_max_size(&self) -> bool {
719 self >= &Self::V2_2
720 }
721}
722
723fn write_int(
724 bits: u16,
725 sign: Sign,
726 value: &BigUint,
727 target: &mut CellBuilder,
728) -> Result<(), Error> {
729 if value.bits() > bits as u64 {
730 return Err(Error::IntOverflow);
731 }
732
733 let is_negative = sign == Sign::Minus;
734 let bytes = to_signed_bytes_be(is_negative, value);
735 let value_bits = (bytes.len() * 8) as u16;
736
737 if bytes.is_empty() {
738 target.store_zeros(bits)
739 } else if bits > value_bits {
740 let diff = bits - value_bits;
741 ok!(if is_negative {
742 target.store_ones(diff)
743 } else {
744 target.store_zeros(diff)
745 });
746 target.store_raw(&bytes, value_bits)
747 } else {
748 let bits_offset = value_bits - bits;
749 let bytes_offset = (bits_offset / 8) as usize;
750 let rem = bits_offset % 8;
751
752 let (left, right) = bytes.split_at(bytes_offset + 1);
753 if let Some(left) = left.last() {
754 ok!(target.store_small_uint(*left << rem, 8 - rem));
755 }
756 if !right.is_empty() {
757 ok!(target.store_raw(right, (right.len() * 8) as u16));
758 }
759 Ok(())
760 }
761}
762
763#[cfg(test)]
764mod tests {
765 use std::sync::Arc;
766
767 use bytes::Bytes;
768
769 use crate::dict::Dict;
770 use crate::models::{StdAddr, VarAddr};
771 use crate::num::Uint9;
772 use crate::prelude::{CellFamily, HashBytes};
773
774 use super::*;
775
776 const VX_X: [AbiVersion; 5] = [
777 AbiVersion::V1_0,
778 AbiVersion::V2_0,
779 AbiVersion::V2_1,
780 AbiVersion::V2_2,
781 AbiVersion::V2_3,
782 ];
783 const V2_X: [AbiVersion; 4] = [
784 AbiVersion::V2_0,
785 AbiVersion::V2_1,
786 AbiVersion::V2_2,
787 AbiVersion::V2_3,
788 ];
789
790 fn check_encoding(version: AbiVersion, value: AbiValue) {
791 let cell = value.make_cell(version).unwrap();
792 let parsed =
793 AbiValue::load(&value.get_type(), version, &mut cell.as_slice().unwrap()).unwrap();
794 assert_eq!(value, parsed);
795 }
796
797 #[test]
798 fn int_overflow() {
799 assert_eq!(
800 AbiValue::Uint(16, BigUint::from(u32::MAX)).make_cell(AbiVersion::V2_2),
801 Err(Error::IntOverflow)
802 );
803
804 assert_eq!(
805 AbiValue::Uint(16, BigUint::from(u16::MAX as u32 + 1)).make_cell(AbiVersion::V2_2),
806 Err(Error::IntOverflow)
807 );
808 }
809
810 #[test]
811 fn encode_int() {
812 macro_rules! define_tests {
813 ($v:ident, { $($abi:ident($bits:literal) => [$($expr:expr),*$(,)?]),*$(,)? }) => {$(
814 $(check_encoding($v, AbiValue::$abi($bits, $expr));)*
815 )*};
816 }
817
818 for v in VX_X {
819 println!("ABIv{v}");
820 define_tests!(v, {
821 uint(8) => [0u8, 123u8, u8::MAX],
822 uint(16) => [0u16, 1234u16, u16::MAX],
823 uint(32) => [0u32, 123456u32, u32::MAX],
824 uint(64) => [0u64, 123456789u64, u64::MAX],
825 uint(128) => [0u128, 123456789123123123123u128, u128::MAX],
826
827 int(8) => [0i8, 123i8, i8::MIN, i8::MAX],
828 int(16) => [0i16, 1234i16, i16::MIN, i16::MAX],
829 int(32) => [0i32, 123456i32, i32::MIN, i32::MAX],
830 int(64) => [0i64, 123456789i64, i64::MIN, i64::MAX],
831 int(128) => [0i128, 123456789123123123123i128, i128::MIN, i128::MAX],
832 });
833 }
834 }
835
836 #[test]
837 fn encode_varint() {
838 for v in V2_X {
839 println!("ABIv{v}");
840 check_encoding(v, AbiValue::varuint(4, 0u32));
841 check_encoding(v, AbiValue::varuint(4, u32::MAX >> 8));
842 check_encoding(v, AbiValue::varuint(4, 123321u32));
843
844 check_encoding(v, AbiValue::varuint(8, 0u32));
845 check_encoding(v, AbiValue::varuint(8, u64::MAX >> 8));
846 check_encoding(v, AbiValue::varuint(8, 1233213213123123u64));
847
848 check_encoding(v, AbiValue::varuint(16, 0u8));
849 check_encoding(v, AbiValue::Token(Tokens::ZERO));
850
851 let mut prev_value = 0;
852 for byte in 0..15 {
853 let value = (0xffu128 << (byte * 8)) | prev_value;
854 prev_value = value;
855 check_encoding(v, AbiValue::varuint(16, value));
856 check_encoding(v, AbiValue::Token(Tokens::new(value)));
857 }
858
859 check_encoding(v, AbiValue::varuint(128, 0u8));
860 check_encoding(v, AbiValue::varuint(128, BigUint::from(1u8) << (126 * 8)));
861 }
862 }
863
864 #[test]
865 fn encode_bool() {
866 for v in VX_X {
867 println!("ABIv{v}");
868 check_encoding(v, AbiValue::Bool(false));
869 check_encoding(v, AbiValue::Bool(true));
870 }
871 }
872
873 #[test]
874 fn encode_cell() {
875 for v in VX_X {
877 check_encoding(v, AbiValue::Cell(Cell::empty_cell()));
878 }
879
880 let value = AbiValue::unnamed_tuple([
882 AbiValue::Cell(Cell::empty_cell()),
883 AbiValue::Cell(Cell::empty_cell()),
884 AbiValue::Cell(Cell::empty_cell()),
885 AbiValue::Cell(Cell::empty_cell()),
886 ]);
887
888 let cell_v1 = {
890 let mut builder = CellBuilder::new();
891 builder.store_reference(Cell::empty_cell()).unwrap();
892 builder.store_reference(Cell::empty_cell()).unwrap();
893 builder.store_reference(Cell::empty_cell()).unwrap();
894 builder
895 .store_reference(CellBuilder::build_from(Cell::empty_cell()).unwrap())
896 .unwrap();
897 builder.build().unwrap()
898 };
899
900 assert_eq!(value.make_cell(AbiVersion::V1_0).unwrap(), cell_v1);
901
902 let cell_v2 = CellBuilder::build_from((
904 Cell::empty_cell(),
905 Cell::empty_cell(),
906 Cell::empty_cell(),
907 Cell::empty_cell(),
908 ))
909 .unwrap();
910
911 for v in V2_X {
912 println!("ABIv{v}");
913 assert_eq!(value.make_cell(v).unwrap(), cell_v2);
914 }
915 }
916
917 #[test]
918 fn encode_address() {
919 for v in VX_X {
920 check_encoding(v, AbiValue::address(StdAddr::new(0, HashBytes([0xff; 32]))));
921 check_encoding(
922 v,
923 AbiValue::address(VarAddr {
924 address_len: Uint9::new(10 * 8),
925 anycast: None,
926 workchain: 123456,
927 address: vec![0xffu8; 10],
928 }),
929 );
930 }
931 }
932
933 #[test]
934 fn encode_bytes() {
935 let mut bytes = vec![0xffu8; 256];
936 bytes[0] = 0xff; let bytes = Bytes::from(bytes);
938
939 let empty_bytes_cell = {
940 let mut builder = CellBuilder::new();
941 builder.store_reference(Cell::empty_cell()).unwrap();
942 builder.build().unwrap()
943 };
944
945 for v in VX_X {
947 println!("ABIv{v}");
948
949 check_encoding(v, AbiValue::Bytes(bytes.clone()));
950
951 assert_eq!(
953 AbiValue::Bytes(bytes.clone()).make_cell(v),
954 AbiValue::FixedBytes(bytes.clone()).make_cell(v)
955 );
956
957 assert_eq!(
958 AbiValue::Bytes(Bytes::new()).make_cell(v).unwrap(),
959 empty_bytes_cell
960 );
961 }
962
963 let cell_v1 = CellBuilder::build_from({
965 let mut builder = CellBuilder::new();
966 builder.store_raw(&[0xff; 2], 2 * 8).unwrap();
967
968 builder
969 .store_reference({
970 let mut builder = CellBuilder::new();
971 builder.store_raw(&[0xff; 127], 127 * 8).unwrap();
972
973 builder
974 .store_reference({
975 let mut builder = CellBuilder::new();
976 builder.store_raw(&[0xff; 127], 127 * 8).unwrap();
977 builder.build().unwrap()
978 })
979 .unwrap();
980
981 builder.build().unwrap()
982 })
983 .unwrap();
984
985 builder.build().unwrap()
986 })
987 .unwrap();
988
989 let cell_v2 = CellBuilder::build_from({
991 let mut builder = CellBuilder::new();
992 builder.store_raw(&[0xff; 127], 127 * 8).unwrap();
993
994 builder
995 .store_reference({
996 let mut builder = CellBuilder::new();
997 builder.store_raw(&[0xff; 127], 127 * 8).unwrap();
998
999 builder
1000 .store_reference({
1001 let mut builder = CellBuilder::new();
1002 builder.store_raw(&[0xff; 2], 2 * 8).unwrap();
1003 builder.build().unwrap()
1004 })
1005 .unwrap();
1006
1007 builder.build().unwrap()
1008 })
1009 .unwrap();
1010
1011 builder.build().unwrap()
1012 })
1013 .unwrap();
1014
1015 assert_eq!(
1018 AbiValue::Bytes(bytes.clone())
1019 .make_cell(AbiVersion::V1_0)
1020 .unwrap(),
1021 cell_v1
1022 );
1023
1024 for v in V2_X {
1025 println!("ABIv{v}");
1026
1027 assert_eq!(
1028 AbiValue::Bytes(bytes.clone()).make_cell(v).unwrap(),
1029 cell_v2
1030 );
1031 }
1032 }
1033
1034 #[test]
1035 fn encode_string() {
1036 for v in VX_X {
1037 println!("ABIv{v}");
1038 check_encoding(v, AbiValue::String(String::new()));
1039 check_encoding(v, AbiValue::String("Hello".to_owned()));
1040 check_encoding(
1041 v,
1042 AbiValue::String(
1043 std::iter::repeat_with(|| "HELLO".to_owned())
1044 .take(200)
1045 .collect::<Vec<String>>()
1046 .join(" "),
1047 ),
1048 );
1049 }
1050 }
1051
1052 #[test]
1053 fn encode_nested_simple_tuple() {
1054 let value = AbiValue::unnamed_tuple([
1055 AbiValue::uint(32, 0u32),
1056 AbiValue::Cell(Cell::empty_cell()),
1057 AbiValue::Bool(false),
1058 AbiValue::unnamed_tuple([
1059 AbiValue::int(8, -15),
1060 AbiValue::int(16, -9845),
1061 AbiValue::unnamed_tuple([
1062 AbiValue::int(32, -1),
1063 AbiValue::int(64, 12345678),
1064 AbiValue::int(128, -12345678),
1065 ]),
1066 ]),
1067 AbiValue::unnamed_tuple([
1068 AbiValue::uint(8, 255_u8),
1069 AbiValue::uint(16, 0_u16),
1070 AbiValue::unnamed_tuple([
1071 AbiValue::uint(32, 256_u32),
1072 AbiValue::uint(64, 123_u64),
1073 AbiValue::uint(128, 1234567890_u128),
1074 ]),
1075 ]),
1076 ]);
1077
1078 for v in VX_X {
1079 println!("ABIv{v}");
1080
1081 let cell = value.make_cell(v).unwrap();
1082 assert_eq!(
1083 cell.bit_len(),
1084 32 + 1 + 8 + 16 + 32 + 64 + 128 + 8 + 16 + 32 + 64 + 128
1085 );
1086 assert_eq!(cell.reference_count(), 1);
1087
1088 check_encoding(v, value.clone());
1089 }
1090 }
1091
1092 #[test]
1093 fn encode_tuple_four_refs_and_four_uint256() {
1094 let bytes = HashBytes([0xff; 32]);
1095 let bytes_cell = CellBuilder::build_from(bytes).unwrap();
1096
1097 let cell = {
1098 let mut builder = CellBuilder::new();
1099 builder.store_u32(0).unwrap();
1100 builder.store_reference(Cell::empty_cell()).unwrap();
1101
1102 builder.store_reference(bytes_cell.clone()).unwrap();
1103 builder.store_reference(bytes_cell.clone()).unwrap();
1104
1105 let mut second_builder = CellBuilder::new();
1106 second_builder.store_reference(bytes_cell.clone()).unwrap();
1107 second_builder.store_u256(&bytes).unwrap();
1108 second_builder.store_u256(&bytes).unwrap();
1109 second_builder.store_u256(&bytes).unwrap();
1110
1111 let mut third_builder = CellBuilder::new();
1112 third_builder.store_u256(&bytes).unwrap();
1113
1114 second_builder
1115 .store_reference(third_builder.build().unwrap())
1116 .unwrap();
1117 builder
1118 .store_reference(second_builder.build().unwrap())
1119 .unwrap();
1120
1121 builder.build().unwrap()
1122 };
1123
1124 let value = AbiValue::unnamed_tuple([
1125 AbiValue::uint(32, 0_u32),
1126 AbiValue::Cell(Cell::empty_cell()),
1127 AbiValue::Cell(bytes_cell.clone()),
1128 AbiValue::Bytes(Bytes::copy_from_slice(bytes.as_slice())),
1129 AbiValue::Cell(bytes_cell),
1130 AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1131 AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1132 AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1133 AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1134 ]);
1135
1136 for v in VX_X {
1137 println!("ABIv{v}");
1138
1139 assert_eq!(value.make_cell(v).unwrap(), cell);
1140 check_encoding(v, value.clone());
1141 }
1142 }
1143
1144 #[test]
1145 fn encode_tuple_four_refs_and_one_uint256() {
1146 let bytes = HashBytes([0x55; 32]);
1147 let bytes_cell = CellBuilder::build_from(bytes).unwrap();
1148
1149 let mut builder = CellBuilder::new();
1150 builder.store_u32(0).unwrap();
1151 builder.store_reference(Cell::empty_cell()).unwrap();
1152
1153 builder.store_reference(bytes_cell.clone()).unwrap();
1154 builder.store_reference(bytes_cell.clone()).unwrap();
1155
1156 let cell_v2 = {
1157 let mut builder = builder.clone();
1158 builder.store_reference(bytes_cell.clone()).unwrap();
1159 builder.store_u256(&bytes).unwrap();
1160 builder.build().unwrap()
1161 };
1162
1163 let cell_v1 = {
1164 let mut child_builder = CellBuilder::new();
1165 child_builder.store_reference(bytes_cell.clone()).unwrap();
1166 child_builder.store_u256(&bytes).unwrap();
1167
1168 builder
1169 .store_reference(child_builder.build().unwrap())
1170 .unwrap();
1171 builder.build().unwrap()
1172 };
1173
1174 let value = AbiValue::unnamed_tuple([
1175 AbiValue::uint(32, 0_u32),
1176 AbiValue::Cell(Cell::empty_cell()),
1177 AbiValue::Cell(bytes_cell.clone()),
1178 AbiValue::Bytes(Bytes::copy_from_slice(bytes.as_slice())),
1179 AbiValue::Cell(bytes_cell.clone()),
1180 AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1181 ]);
1182
1183 for v in VX_X {
1184 println!("ABIv{v}");
1185 check_encoding(v, value.clone());
1186 }
1187
1188 assert_eq!(value.make_cell(AbiVersion::V1_0).unwrap(), cell_v1);
1189
1190 for v in V2_X {
1191 println!("ABIv{v}");
1192 assert_eq!(value.make_cell(v).unwrap(), cell_v2);
1193 }
1194 }
1195
1196 #[test]
1197 fn encode_map_simple() {
1198 let bytes = HashBytes([0x55; 32]);
1199 let bytes_cell = CellBuilder::build_from(bytes).unwrap();
1200
1201 let mut bytes_map = Dict::<u8, Cell>::new();
1202 for i in 1..=3 {
1203 bytes_map.set(i, bytes_cell.clone()).unwrap();
1204 }
1205 let bytes_map_cell = CellBuilder::build_from(bytes_map).unwrap();
1206 let bytes_map_value = AbiValue::map([
1207 (1u8, Bytes::copy_from_slice(bytes.as_slice())),
1208 (2, Bytes::copy_from_slice(bytes.as_slice())),
1209 (3, Bytes::copy_from_slice(bytes.as_slice())),
1210 ]);
1211
1212 for v in VX_X {
1213 println!("ABIv{v}");
1214
1215 assert_eq!(bytes_map_value.make_cell(v).unwrap(), bytes_map_cell);
1216 check_encoding(v, bytes_map_value.clone());
1217 }
1218
1219 let mut int_map = Dict::<i16, i128>::new();
1221 for i in -1..=1 {
1222 int_map.set(i, i as i128).unwrap();
1223 }
1224 let int_map_cell = CellBuilder::build_from(int_map).unwrap();
1225 let int_map_value = AbiValue::map([(-1i16, -1i128), (0, 0), (1, 1)]);
1226
1227 for v in VX_X {
1228 println!("ABIv{v}");
1229
1230 assert_eq!(int_map_value.make_cell(v).unwrap(), int_map_cell);
1231 check_encoding(v, int_map_value.clone());
1232 }
1233
1234 let mut tuples_map = Dict::<u128, (u32, bool)>::new();
1236 for i in 1..=5 {
1237 tuples_map.set(i as u128, (i, i % 2 != 0)).unwrap();
1238 }
1239 let tuples_map_cell = CellBuilder::build_from(tuples_map).unwrap();
1240 let tuples_map_value = AbiValue::map([
1241 (1u128, (1u32, true)),
1242 (2, (2, false)),
1243 (3, (3, true)),
1244 (4, (4, false)),
1245 (5, (5, true)),
1246 ]);
1247
1248 for v in VX_X {
1249 println!("ABIv{v}");
1250
1251 assert_eq!(tuples_map_value.make_cell(v).unwrap(), tuples_map_cell);
1252 check_encoding(v, tuples_map_value.clone());
1253 }
1254
1255 let addr1 = StdAddr::new(0, HashBytes([0x11; 32]));
1257 let addr2 = StdAddr::new(0, HashBytes([0x22; 32]));
1258
1259 let mut addr_map = Dict::<StdAddr, u32>::new();
1260 addr_map.set(&addr1, 123).unwrap();
1261 addr_map.set(&addr2, 456).unwrap();
1262 let addr_map_cell = CellBuilder::build_from(addr_map).unwrap();
1263 let addr_map_value = AbiValue::map([(addr1, 123u32), (addr2, 456)]);
1264
1265 for v in VX_X {
1266 println!("ABIv{v}");
1267
1268 assert_eq!(addr_map_value.make_cell(v).unwrap(), addr_map_cell);
1269 check_encoding(v, addr_map_value.clone());
1270 }
1271 }
1272
1273 #[test]
1274 fn encode_map_big_value() {
1275 let tuple_value = AbiValue::unnamed_tuple([
1277 AbiValue::uint(256, 1_u32),
1278 AbiValue::uint(256, 2_u32),
1279 AbiValue::uint(256, 3_u32),
1280 AbiValue::uint(256, 4_u32),
1281 ]);
1282
1283 let mut map_value = CellBuilder::new();
1285 map_value.store_u128(0).unwrap();
1286 map_value.store_u128(1).unwrap();
1287 map_value.store_u128(0).unwrap();
1288 map_value.store_u128(2).unwrap();
1289 map_value.store_u128(0).unwrap();
1290 map_value.store_u128(3).unwrap();
1291 map_value
1292 .store_reference(CellBuilder::build_from((0u128, 4u128)).unwrap())
1293 .unwrap();
1294 let map_value = map_value.build().unwrap();
1295
1296 let mut key = CellBuilder::new();
1297 key.store_u128(0).unwrap();
1298 key.store_u128(123).unwrap();
1299
1300 let mut map = RawDict::<256>::new();
1301 map.set(key.as_data_slice(), &map_value).unwrap();
1302 let map_cell = CellBuilder::build_from(map).unwrap();
1303 let map = AbiValue::Map(
1304 PlainAbiType::Uint(256),
1305 Arc::new(tuple_value.get_type()),
1306 BTreeMap::from([(
1307 PlainAbiValue::Uint(256, BigUint::from(123u32)),
1308 tuple_value.clone(),
1309 )]),
1310 );
1311
1312 for v in VX_X {
1313 println!("ABIv{v}");
1314 assert_eq!(map.make_cell(v).unwrap(), map_cell);
1315 check_encoding(v, map.clone());
1316 }
1317
1318 let mut key = CellBuilder::new();
1320 key.store_u32(0).unwrap();
1321
1322 let mut array = RawDict::<32>::new();
1323 array.set(key.as_data_slice(), &map_value).unwrap();
1324 let array_cell = CellBuilder::build_from((1u32, array)).unwrap();
1325 let array = AbiValue::Array(Arc::new(tuple_value.get_type()), vec![tuple_value]);
1326
1327 for v in V2_X {
1328 println!("ABIv{v}");
1329 assert_eq!(array.make_cell(v).unwrap(), array_cell);
1330 check_encoding(v, array.clone());
1331 }
1332 }
1333
1334 #[test]
1335 fn encode_optional() {
1336 const STR: &str = "Some string";
1337
1338 let string_cell = {
1339 let mut builder = CellBuilder::new();
1340 builder
1341 .store_raw(STR.as_bytes(), (STR.len() * 8) as u16)
1342 .unwrap();
1343 builder.build().unwrap()
1344 };
1345 let string_value = AbiValue::String(STR.to_owned());
1346
1347 let tuple_value = AbiValue::unnamed_tuple([
1348 string_value.clone(),
1349 string_value.clone(),
1350 string_value.clone(),
1351 string_value.clone(),
1352 ]);
1353
1354 let value = AbiValue::unnamed_tuple([
1355 AbiValue::uint(32, 0u32),
1356 AbiValue::Cell(Cell::empty_cell()),
1357 AbiValue::varint(16, -123),
1358 AbiValue::varuint(32, 456u32),
1359 AbiValue::optional(None::<bool>),
1360 AbiValue::Optional(
1361 Arc::new(AbiType::Uint(1022)),
1362 Some(Box::new(AbiValue::uint(1022, 1u32))),
1363 ),
1364 AbiValue::Optional(
1365 Arc::new(AbiType::varuint(128)),
1366 Some(Box::new(AbiValue::varuint(128, 123u32))),
1367 ),
1368 AbiValue::Optional(
1369 Arc::new(tuple_value.get_type()),
1370 Some(Box::new(tuple_value)),
1371 ),
1372 ]);
1373
1374 let cell = {
1375 let mut builder = CellBuilder::new();
1376 builder.store_u32(0).unwrap();
1377 builder.store_reference(Cell::empty_cell()).unwrap();
1378
1379 builder.store_small_uint(1, 4).unwrap();
1380 builder.store_u8(-123i8 as _).unwrap();
1381
1382 builder.store_small_uint(2, 5).unwrap();
1383 builder.store_u16(456).unwrap();
1384
1385 builder.store_bit_zero().unwrap();
1386
1387 builder
1388 .store_reference({
1389 let mut builder = CellBuilder::new();
1390 builder.store_bit_one().unwrap();
1391 builder.store_zeros(127 * 8).unwrap();
1392 builder.store_small_uint(1, 6).unwrap();
1393
1394 builder
1395 .store_reference({
1396 let mut builder = CellBuilder::new();
1397 builder.store_bit_one().unwrap();
1398 builder
1399 .store_reference({
1400 let mut builder = CellBuilder::new();
1401 builder.store_small_uint(1, 7).unwrap();
1402 builder.store_u8(123).unwrap();
1403 builder.build().unwrap()
1404 })
1405 .unwrap();
1406
1407 builder.store_bit_one().unwrap();
1408 builder
1409 .store_reference(
1410 CellBuilder::build_from((
1411 string_cell.clone(),
1412 string_cell.clone(),
1413 string_cell.clone(),
1414 string_cell.clone(),
1415 ))
1416 .unwrap(),
1417 )
1418 .unwrap();
1419
1420 builder.build().unwrap()
1421 })
1422 .unwrap();
1423
1424 builder.build().unwrap()
1425 })
1426 .unwrap();
1427
1428 builder.build().unwrap()
1429 };
1430
1431 for v in V2_X {
1432 println!("ABIv{v}");
1433
1434 assert_eq!(value.make_cell(v).unwrap(), cell);
1435 check_encoding(v, value.clone());
1436 }
1437 }
1438
1439 #[test]
1440 fn encode_ref() {
1441 let cell = CellBuilder::build_from((
1442 CellBuilder::build_from(123u64).unwrap(),
1443 CellBuilder::build_from((true, Cell::empty_cell())).unwrap(),
1444 ))
1445 .unwrap();
1446
1447 let value = AbiValue::unnamed_tuple([
1448 AbiValue::reference(123u64),
1449 AbiValue::reference((true, Cell::empty_cell())),
1450 ]);
1451
1452 for v in V2_X {
1453 println!("ABIv{v}");
1454 assert_eq!(value.make_cell(v).unwrap(), cell);
1455 check_encoding(v, value.clone());
1456 }
1457 }
1458}