tonlib_core/cell/
builder.rs

1use std::cmp::min;
2use std::collections::HashMap;
3use std::ops::Deref;
4use std::sync::Arc;
5
6use bitstream_io::{BigEndian, BitWrite, BitWriter};
7use num_bigint::{BigInt, BigUint};
8use num_traits::Zero;
9
10use super::TonCellNum;
11use crate::cell::dict::{DictBuilder, ValWriter};
12use crate::cell::error::{MapTonCellError, TonCellError};
13use crate::cell::{ArcCell, Cell, CellParser};
14use crate::tlb_types::block::msg_address::MsgAddress;
15use crate::tlb_types::tlb::TLB;
16use crate::{TonAddress, TonHash};
17
18pub(crate) const MAX_CELL_BITS: usize = 1023;
19pub(crate) const MAX_CELL_REFERENCES: usize = 4;
20pub(crate) const MAX_LEVEL_MASK: u32 = 3;
21
22pub struct CellBuilder {
23    bit_writer: BitWriter<Vec<u8>, BigEndian>,
24    bits_to_write: usize,
25    references: Vec<ArcCell>,
26    is_cell_exotic: bool,
27}
28
29#[derive(Clone, Debug, PartialEq, Copy)]
30pub enum EitherCellLayout {
31    Native,
32    ToRef,
33    ToCell,
34}
35
36impl CellBuilder {
37    pub fn new() -> CellBuilder {
38        let bit_writer = BitWriter::endian(Vec::new(), BigEndian);
39        CellBuilder {
40            bit_writer,
41            bits_to_write: 0,
42            references: Vec::new(),
43            is_cell_exotic: false,
44        }
45    }
46
47    pub fn set_cell_is_exotic(&mut self, val: bool) {
48        self.is_cell_exotic = val;
49    }
50
51    pub fn store_bit(&mut self, val: bool) -> Result<&mut Self, TonCellError> {
52        self.bit_writer.write_bit(val).map_cell_builder_error()?;
53        self.bits_to_write += 1;
54        Ok(self)
55    }
56
57    pub fn store_number_optional<N: TonCellNum>(
58        &mut self,
59        bit_len: usize,
60        maybe_val: Option<N>,
61    ) -> Result<&mut Self, TonCellError> {
62        if let Some(val) = maybe_val {
63            self.store_bit(true)?;
64            self.store_number(bit_len, &val)?;
65        } else {
66            self.store_bit(false)?;
67        }
68        Ok(self)
69    }
70
71    pub fn store_u8(&mut self, bit_len: usize, val: u8) -> Result<&mut Self, TonCellError> {
72        self.store_number(bit_len, &val)
73    }
74
75    pub fn store_i8(&mut self, bit_len: usize, val: i8) -> Result<&mut Self, TonCellError> {
76        self.store_number(bit_len, &val)
77    }
78
79    pub fn store_u16(&mut self, bit_len: usize, val: u16) -> Result<&mut Self, TonCellError> {
80        self.store_number(bit_len, &val)
81    }
82
83    pub fn store_u32(&mut self, bit_len: usize, val: u32) -> Result<&mut Self, TonCellError> {
84        self.store_number(bit_len, &val)
85    }
86
87    pub fn store_i32(&mut self, bit_len: usize, val: i32) -> Result<&mut Self, TonCellError> {
88        self.store_number(bit_len, &val)
89    }
90
91    pub fn store_u64(&mut self, bit_len: usize, val: u64) -> Result<&mut Self, TonCellError> {
92        self.store_number(bit_len, &val)
93    }
94
95    pub fn store_i64(&mut self, bit_len: usize, val: i64) -> Result<&mut Self, TonCellError> {
96        self.store_number(bit_len, &val)
97    }
98
99    pub fn store_uint(&mut self, bit_len: usize, val: &BigUint) -> Result<&mut Self, TonCellError> {
100        self.store_number(bit_len, val)
101    }
102
103    pub fn store_int(&mut self, bit_len: usize, val: &BigInt) -> Result<&mut Self, TonCellError> {
104        self.store_number(bit_len, val)
105    }
106
107    pub fn store_byte(&mut self, val: u8) -> Result<&mut Self, TonCellError> {
108        self.store_number(8, &val)
109    }
110
111    pub fn store_slice(&mut self, slice: &[u8]) -> Result<&mut Self, TonCellError> {
112        for val in slice {
113            self.store_byte(*val)?;
114        }
115        Ok(self)
116    }
117
118    pub fn store_bits(&mut self, bit_len: usize, slice: &[u8]) -> Result<&mut Self, TonCellError> {
119        let full_bytes = bit_len / 8;
120        self.store_slice(&slice[0..full_bytes])?;
121        let last_byte_len = bit_len % 8;
122        if last_byte_len != 0 {
123            let last_byte = slice[full_bytes] >> (8 - last_byte_len);
124            self.store_u8(last_byte_len, last_byte)?;
125        }
126        Ok(self)
127    }
128
129    pub fn store_string(&mut self, val: &str) -> Result<&mut Self, TonCellError> {
130        self.store_slice(val.as_bytes())
131    }
132
133    pub fn store_coins(&mut self, val: &BigUint) -> Result<&mut Self, TonCellError> {
134        if val.is_zero() {
135            self.store_u8(4, 0)
136        } else {
137            let num_bytes = (val.bits() as usize).div_ceil(8);
138            self.store_u8(4, num_bytes as u8)?;
139            self.store_uint(num_bytes * 8, val)
140        }
141    }
142
143    /// Stores address without optimizing hole address
144    pub fn store_raw_address(&mut self, val: &TonAddress) -> Result<&mut Self, TonCellError> {
145        self.store_u8(2, 0b10u8)?; //store as MsgAddressInt
146        self.store_bit(false)?; // always no anycast
147        let wc = (val.workchain & 0xff) as u8;
148        self.store_u8(8, wc)?;
149        self.store_slice(val.hash_part.as_slice())?;
150        Ok(self)
151    }
152
153    /// Stores address optimizing hole address two to bits
154    pub fn store_address(&mut self, val: &TonAddress) -> Result<&mut Self, TonCellError> {
155        val.to_msg_address().write(self)?;
156        Ok(self)
157    }
158
159    pub fn store_msg_address(&mut self, val: &MsgAddress) -> Result<&mut Self, TonCellError> {
160        val.write(self)?;
161        Ok(self)
162    }
163
164    /// Adds reference to an existing `Cell`.
165    ///
166    /// The reference is passed as `ArcCell` so it might be references from other cells.
167    pub fn store_reference(&mut self, cell: &ArcCell) -> Result<&mut Self, TonCellError> {
168        if self.references.len() == 4 {
169            return Err(TonCellError::cell_builder_error("Cell already has 4 refs"));
170        }
171        self.references.push(cell.clone());
172        Ok(self)
173    }
174
175    pub fn store_references(&mut self, refs: &[ArcCell]) -> Result<&mut Self, TonCellError> {
176        for r in refs {
177            self.store_reference(r)?;
178        }
179        Ok(self)
180    }
181
182    /// Adds a newly constructed `Cell` as a reference.
183    ///
184    /// The cell is wrapped it the `Arc`.
185    pub fn store_child(&mut self, cell: Cell) -> Result<&mut Self, TonCellError> {
186        self.store_reference(&cell.to_arc())
187    }
188
189    pub fn store_remaining_bits(
190        &mut self,
191        parser: &mut CellParser,
192    ) -> Result<&mut Self, TonCellError> {
193        let num_full_bytes = parser.remaining_bits() / 8;
194        let bytes = parser.load_bytes(num_full_bytes)?;
195        self.store_slice(bytes.as_slice())?;
196        let num_bits = parser.remaining_bits() % 8;
197        let tail = parser.load_u8(num_bits)?;
198        self.store_u8(num_bits, tail)?;
199        Ok(self)
200    }
201
202    pub fn store_cell_data(&mut self, cell: &Cell) -> Result<&mut Self, TonCellError> {
203        let mut parser = cell.parser();
204        self.store_remaining_bits(&mut parser)?;
205        Ok(self)
206    }
207
208    pub fn store_cell(&mut self, cell: &Cell) -> Result<&mut Self, TonCellError> {
209        self.store_cell_data(cell)?;
210        self.store_references(cell.references.as_slice())?;
211        Ok(self)
212    }
213
214    // https://docs.ton.org/develop/data-formats/tl-b-types#either
215    pub fn store_either_cell_or_cell_ref(
216        &mut self,
217        cell: &ArcCell,
218        layout: EitherCellLayout,
219    ) -> Result<&mut Self, TonCellError> {
220        match layout {
221            EitherCellLayout::Native => {
222                if cell.bit_len() < self.remaining_bits() {
223                    self.store_bit(false)?;
224                    self.store_cell(cell)?;
225                } else {
226                    self.store_bit(true)?;
227                    self.store_reference(cell)?;
228                }
229            }
230            EitherCellLayout::ToRef => {
231                self.store_bit(true)?;
232                self.store_reference(cell)?;
233            }
234            EitherCellLayout::ToCell => {
235                self.store_bit(false)?;
236                self.store_cell(cell)?;
237            }
238        }
239
240        Ok(self)
241    }
242
243    // https://docs.ton.org/develop/data-formats/tl-b-types#maybe
244    pub fn store_ref_cell_optional(
245        &mut self,
246        maybe_cell: Option<&ArcCell>,
247    ) -> Result<&mut Self, TonCellError> {
248        if let Some(cell) = maybe_cell {
249            self.store_bit(true)?;
250            self.store_reference(cell)?;
251        } else {
252            self.store_bit(false)?;
253        }
254        Ok(self)
255    }
256
257    pub fn store_dict_data<K, V>(
258        &mut self,
259        key_len_bits: usize,
260        value_writer: ValWriter<V>,
261        data: HashMap<K, V>,
262    ) -> Result<&mut Self, TonCellError>
263    where
264        BigUint: From<K>,
265    {
266        if data.is_empty() {
267            return Err(TonCellError::CellBuilderError(
268                "can't save empty dict as dict_data".to_string(),
269            ));
270        }
271        let dict_builder = DictBuilder::new(key_len_bits, value_writer, data)?;
272        let dict_cell = dict_builder.build()?;
273        self.store_cell(&dict_cell)
274    }
275
276    pub fn store_dict<K, V>(
277        &mut self,
278        key_len_bits: usize,
279        value_writer: ValWriter<V>,
280        data: HashMap<K, V>,
281    ) -> Result<&mut Self, TonCellError>
282    where
283        BigUint: From<K>,
284    {
285        if data.is_empty() {
286            self.store_bit(false)
287        } else {
288            self.store_bit(true)?;
289
290            let dict_data = Arc::new(
291                CellBuilder::new()
292                    .store_dict_data(key_len_bits, value_writer, data)?
293                    .build()?,
294            );
295            self.store_reference(&dict_data)
296        }
297    }
298
299    pub fn store_tonhash(&mut self, ton_hash: &TonHash) -> Result<&mut Self, TonCellError> {
300        self.store_slice(ton_hash.as_slice())
301    }
302
303    pub fn remaining_bits(&self) -> usize {
304        MAX_CELL_BITS - self.bits_to_write
305    }
306
307    pub fn store_number<N, B>(&mut self, bit_len: usize, data: B) -> Result<&mut Self, TonCellError>
308    where
309        N: TonCellNum,
310        B: Deref<Target = N>,
311    {
312        let value = data.deref();
313
314        // data is zero
315        if bit_len == 0 {
316            if value.tcn_is_zero() {
317                Ok(self)
318            } else {
319                Err(TonCellError::CellBuilderError(format!(
320                    "Cannot write non-zero number {value} as 0 bits"
321                )))
322            }
323            //data is unsigned primitive
324        } else if let Some(unsigned) = value.tcn_to_unsigned_primitive() {
325            self.bit_writer.write_var(bit_len as u32, unsigned)?;
326            self.bits_to_write += bit_len;
327            Ok(self)
328            //data is signed or BigInt or BigUint
329        } else {
330            let min_bits = value.tcn_min_bits_len();
331            if min_bits > bit_len {
332                Err(TonCellError::CellBuilderError(format!(
333                    "Cannot write number {value} in {bit_len} bits (requires at least {min_bits} bits)"
334                )))
335            } else {
336                let bytes = value.tcn_to_bytes();
337                let padding_bits = bit_len - min_bits;
338
339                let first_padding_byte = if N::SIGNED && bytes[0] & 0x80 != 0 {
340                    0xFF
341                } else {
342                    0
343                };
344
345                if padding_bits > 0 {
346                    let pad_bytes = vec![first_padding_byte; padding_bits.div_ceil(8)];
347                    self.write_bits(pad_bytes, padding_bits)?;
348                }
349
350                let bit_offset = bytes.len() * 8 - min_bits;
351                self.write_bits_with_offset(bytes, bit_len - padding_bits, bit_offset)?;
352                Ok(self)
353            }
354        }
355    }
356
357    pub fn write_bits_with_offset<T: AsRef<[u8]>>(
358        &mut self,
359        data: T,
360        bit_len: usize,
361        bit_offset: usize,
362    ) -> Result<&mut Self, TonCellError> {
363        self.bits_to_write += bit_len;
364        let mut value = data.as_ref();
365
366        if (bit_len + bit_offset).div_ceil(8) > value.len() {
367            Err(TonCellError::CellBuilderError(format!(
368                "Can't extract {} bits from {} bytes",
369                bit_len + bit_offset,
370                value.len()
371            )))
372        } else if bit_len == 0 {
373            Ok(self)
374        } else {
375            // skip bytes_offset, adjust borders
376            value = &value[bit_offset / 8..];
377            let aligned_bit_offset = bit_offset % 8;
378
379            let first_byte_bits_len = min(bit_len, 8 - aligned_bit_offset);
380            let mut first_byte_val = value[0] << aligned_bit_offset >> aligned_bit_offset;
381            if first_byte_bits_len == bit_len {
382                first_byte_val >>= 8 - aligned_bit_offset - bit_len
383            }
384            self.bit_writer
385                .write_var(first_byte_bits_len as u32, first_byte_val)?;
386
387            value = &value[1..];
388            let aligned_bit_len = bit_len - first_byte_bits_len;
389
390            let full_bytes = aligned_bit_len / 8;
391            self.bit_writer.write_bytes(&value[0..full_bytes])?;
392            let rest_bits_len = aligned_bit_len % 8;
393            if rest_bits_len != 0 {
394                self.bit_writer.write_var(
395                    rest_bits_len as u32,
396                    value[full_bytes] >> (8 - rest_bits_len),
397                )?;
398            }
399
400            Ok(self)
401        }
402    }
403
404    pub fn write_bits<T: AsRef<[u8]>>(
405        &mut self,
406        data: T,
407        bit_len: usize,
408    ) -> Result<&mut Self, TonCellError> {
409        self.write_bits_with_offset(data, bit_len, 0)
410    }
411
412    pub fn build(&mut self) -> Result<Cell, TonCellError> {
413        let mut trailing_zeros = 0;
414        while !self.bit_writer.byte_aligned() {
415            self.bit_writer.write_bit(false).map_cell_builder_error()?;
416            trailing_zeros += 1;
417        }
418
419        if let Some(vec) = self.bit_writer.writer() {
420            let bit_len = vec.len() * 8 - trailing_zeros;
421            if bit_len > MAX_CELL_BITS {
422                return Err(TonCellError::cell_builder_error(format!(
423                    "Cell must contain at most {} bits, got {}",
424                    MAX_CELL_BITS, bit_len
425                )));
426            }
427            let ref_count = self.references.len();
428            if ref_count > MAX_CELL_REFERENCES {
429                return Err(TonCellError::cell_builder_error(format!(
430                    "Cell must contain at most 4 references, got {}",
431                    ref_count
432                )));
433            }
434
435            Cell::new(
436                vec.clone(),
437                self.bits_to_write,
438                self.references.clone(),
439                self.is_cell_exotic,
440            )
441        } else {
442            Err(TonCellError::CellBuilderError(
443                "Stream is not byte-aligned".to_string(),
444            ))
445        }
446    }
447}
448
449impl Default for CellBuilder {
450    fn default() -> Self {
451        Self::new()
452    }
453}
454
455#[cfg(test)]
456mod tests {
457    use std::collections::HashMap;
458    use std::ops::ShrAssign;
459    use std::str::FromStr;
460
461    use num_bigint::{BigInt, BigUint, Sign};
462    use num_traits::{FromPrimitive, Num, Zero};
463
464    use crate::cell::dict::predefined_readers::{key_reader_u8, val_reader_uint};
465    use crate::cell::{CellBuilder, TonCellError};
466    use crate::types::TonAddress;
467    use crate::TonHash;
468
469    #[test]
470    fn write_bit() -> Result<(), TonCellError> {
471        let mut writer = CellBuilder::new();
472        let cell = writer.store_bit(true)?.build()?;
473        assert_eq!(cell.data, [0b1000_0000]);
474        assert_eq!(cell.bit_len, 1);
475        let mut reader = cell.parser();
476        let result = reader.load_bit()?;
477        assert!(result);
478        Ok(())
479    }
480
481    #[test]
482    fn write_u8() -> Result<(), TonCellError> {
483        let value = 234u8;
484        let mut writer = CellBuilder::new();
485        let cell = writer.store_u8(8, value)?.build()?;
486        assert_eq!(cell.data, [0b1110_1010]);
487        assert_eq!(cell.bit_len, 8);
488        let mut reader = cell.parser();
489        let result = reader.load_u8(8)?;
490        assert_eq!(result, value);
491        Ok(())
492    }
493
494    #[test]
495    fn write_u32() -> Result<(), TonCellError> {
496        let value = 0xFAD45AADu32;
497        let mut writer = CellBuilder::new();
498        let cell = writer.store_u32(32, value)?.build()?;
499        assert_eq!(cell.data, [0xFA, 0xD4, 0x5A, 0xAD]);
500        assert_eq!(cell.bit_len, 32);
501        let mut reader = cell.parser();
502        let result = reader.load_u32(32)?;
503        assert_eq!(result, value);
504        Ok(())
505    }
506
507    #[test]
508    fn write_u64() -> Result<(), TonCellError> {
509        let value = 0xFAD45AADAA12FF45;
510        let mut writer = CellBuilder::new();
511        let cell = writer.store_u64(64, value)?.build()?;
512        assert_eq!(cell.data, [0xFA, 0xD4, 0x5A, 0xAD, 0xAA, 0x12, 0xFF, 0x45]);
513        assert_eq!(cell.bit_len, 64);
514        let mut reader = cell.parser();
515        let result = reader.load_u64(64)?;
516        assert_eq!(result, value);
517        Ok(())
518    }
519
520    #[test]
521    fn write_slice() -> Result<(), TonCellError> {
522        let value = [0xFA, 0xD4, 0x5A, 0xAD, 0xAA, 0x12, 0xFF, 0x45];
523        let mut writer = CellBuilder::new();
524        let cell = writer.store_slice(&value)?.build()?;
525        assert_eq!(cell.data, value);
526        assert_eq!(cell.bit_len, 64);
527        let mut reader = cell.parser();
528        let bytes = reader.load_bytes(8)?;
529        assert_eq!(bytes, value);
530        Ok(())
531    }
532
533    #[test]
534    fn write_str() -> Result<(), TonCellError> {
535        let texts = ["hello", "Русский текст", "中华人民共和国", "\u{263A}😃"];
536        for text in texts {
537            let mut writer = CellBuilder::new();
538            let cell = writer.store_string(text)?.build()?;
539            let text_bytes = text.as_bytes();
540            assert_eq!(cell.data, text_bytes);
541            assert_eq!(cell.bit_len, text_bytes.len() * 8);
542            let mut reader = cell.parser();
543            let remaining_bytes = reader.remaining_bytes();
544            let result = reader.load_utf8(remaining_bytes)?;
545            assert_eq!(result, text);
546        }
547        Ok(())
548    }
549
550    #[test]
551    fn write_address() -> Result<(), TonCellError> {
552        let addr = TonAddress::from_base64_url("EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR")
553            .unwrap();
554
555        let mut writer = CellBuilder::new();
556        let cell = writer.store_address(&addr)?.build()?;
557        assert_eq!(
558            cell.data,
559            [
560                128, 28, 155, 42, 157, 243, 233, 194, 74, 20, 77, 107, 119, 90, 237, 67, 155, 162,
561                249, 250, 17, 117, 117, 173, 233, 132, 124, 110, 68, 225, 93, 237, 238, 192
562            ]
563        );
564        assert_eq!(cell.bit_len, 2 + 1 + 8 + 32 * 8);
565        let mut reader = cell.parser();
566        let result = reader.load_address()?;
567        assert_eq!(result, addr);
568        Ok(())
569    }
570
571    #[test]
572    fn write_big_int() -> Result<(), TonCellError> {
573        let value = BigInt::from_str("3").unwrap();
574        let mut writer = CellBuilder::new();
575        writer.store_int(33, &value)?;
576        let cell = writer.build()?;
577        println!("cell: {:?}", cell);
578        let mut written = BigInt::from_bytes_be(Sign::Plus, &cell.data);
579        written.shr_assign(8 - cell.bit_len % 8); // should shift bigint here as cell builder writes unalinged bits
580
581        assert_eq!(written, value);
582
583        // 256 bits (+ sign)
584        let value = BigInt::from_str_radix(
585            "123456789ABCDEFAA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55",
586            16,
587        )
588        .unwrap();
589        let mut writer = CellBuilder::new();
590        writer.store_int(257, &value)?;
591        let cell = writer.build()?;
592        println!("cell: {:?}", cell);
593        let mut written = BigInt::from_bytes_be(Sign::Plus, &cell.data);
594        written.shr_assign(8 - cell.bit_len % 8);
595        assert_eq!(written, value);
596
597        let value = BigInt::from_str("-5").unwrap();
598        let mut writer = CellBuilder::new();
599        writer.store_int(5, &value)?;
600        let cell = writer.build()?;
601        println!("cell: {:?}", cell);
602        assert_eq!(5, cell.bit_len);
603        assert_eq!(0b1101_1000, cell.data[0]);
604
605        let value = BigInt::from_str("-5").unwrap();
606        let mut writer = CellBuilder::new();
607        writer.store_int(7, &value)?;
608        let cell = writer.build()?;
609        println!("cell: {:?}", cell);
610        assert_eq!(7, cell.bit_len);
611        assert_eq!(0b1111_0110, cell.data[0]);
612
613        assert!(CellBuilder::new()
614            .store_int(32, &BigInt::from(2401234567u32))
615            .is_err());
616        Ok(())
617    }
618
619    #[test]
620    fn write_load_big_uint() -> Result<(), TonCellError> {
621        let value = BigUint::from_str("3").unwrap();
622        let mut writer = CellBuilder::new();
623        assert!(writer.store_uint(1, &value).is_err());
624        let bits_for_tests = [256, 128, 64, 8];
625
626        for bits_num in bits_for_tests.iter() {
627            writer.store_uint(*bits_num, &value)?;
628        }
629        let cell = writer.build()?;
630        println!("cell: {:?}", cell);
631        let mut cell_parser = cell.parser();
632        for bits_num in bits_for_tests.iter() {
633            let written_value = cell_parser.load_uint(*bits_num)?;
634            assert_eq!(written_value, value);
635        }
636
637        // 256 bit
638        let value = BigUint::from_str(
639            "97887266651548624282413032824435501549503168134499591480902563623927645013201",
640        )
641        .unwrap();
642        let mut writer = CellBuilder::new();
643        assert!(writer.store_uint(255, &value).is_err());
644        let bits_for_tests = [496, 264, 256];
645        for bits_num in bits_for_tests.iter() {
646            writer.store_uint(*bits_num, &value)?;
647        }
648        let cell = writer.build()?;
649        let mut cell_parser = cell.parser();
650        println!("cell: {:?}", cell);
651        for bits_num in bits_for_tests.iter() {
652            let written_value = cell_parser.load_uint(*bits_num)?;
653            assert_eq!(written_value, value);
654        }
655
656        Ok(())
657    }
658
659    #[test]
660    fn test_padding() -> Result<(), TonCellError> {
661        let mut writer = CellBuilder::new();
662
663        let n = BigUint::from(0x55a5f0f0u32);
664
665        writer.store_uint(32, &BigUint::zero())?;
666        writer.store_uint(32, &n)?;
667        writer.store_uint(31, &BigUint::zero())?;
668        writer.store_uint(31, &n)?;
669        writer.store_uint(35, &BigUint::zero())?;
670        writer.store_uint(35, &n)?;
671        let cell = writer.build()?;
672
673        println!("{:?}", cell);
674        assert_eq!(cell.data.len(), 25);
675        assert_eq!(cell.bit_len, 196);
676
677        let mut parser = cell.parser();
678        let result_zero = parser.load_uint(32)?;
679        let result_test_num = parser.load_uint(32)?;
680
681        assert_eq!(result_zero, BigUint::zero());
682        assert_eq!(result_test_num, n);
683        let result_zero = parser.load_uint(31)?;
684        let result_test_num = parser.load_uint(31)?;
685
686        assert_eq!(result_zero, BigUint::zero());
687        assert_eq!(result_test_num, n);
688        let result_zero = parser.load_uint(35)?;
689        let result_test_num = parser.load_uint(35)?;
690
691        assert_eq!(result_zero, BigUint::zero());
692
693        assert_eq!(result_test_num, n);
694        parser.ensure_empty()?;
695
696        Ok(())
697    }
698
699    #[test]
700    fn test_zero_alone() -> Result<(), TonCellError> {
701        let bitlens_to_test = [
702            1, 7, 8, 9, 30, 31, 32, 33, 127, 128, 129, 255, 256, 257, 300,
703        ];
704        for bitlen in bitlens_to_test {
705            let mut writer = CellBuilder::new();
706            writer.store_uint(bitlen, &BigUint::zero())?;
707
708            let cell = writer.build()?;
709
710            println!("{:?}", cell);
711            let taeget_bytelen = bitlen.div_ceil(8);
712            assert_eq!(cell.data.len(), taeget_bytelen);
713
714            assert_eq!(cell.bit_len, bitlen);
715
716            let mut parser = cell.parser();
717            let result_zero = parser.load_uint(bitlen)?;
718
719            assert_eq!(result_zero, BigUint::zero());
720            parser.ensure_empty()?;
721        }
722        Ok(())
723    }
724
725    #[test]
726    fn test_store_dict() -> Result<(), TonCellError> {
727        let mut builder = CellBuilder::new();
728        let mut data = HashMap::new();
729        data.insert(1u8, BigUint::from(2u8));
730        data.insert(3u8, BigUint::from(4u8));
731
732        let value_writer = |writer: &mut CellBuilder, value: BigUint| {
733            writer.store_uint(8, &value)?;
734            Ok(())
735        };
736        builder.store_dict(8, value_writer, data.clone())?;
737        let cell = builder.build()?;
738        let mut parser = cell.parser();
739        let parsed = parser.load_dict(8, key_reader_u8, val_reader_uint)?;
740        assert_eq!(data, parsed);
741        Ok(())
742    }
743
744    #[test]
745    fn test_store_dict_data_empty() -> Result<(), TonCellError> {
746        let mut builder = CellBuilder::new();
747        let data: HashMap<BigUint, BigUint> = HashMap::new();
748        let value_writer = |writer: &mut CellBuilder, value: BigUint| {
749            writer.store_uint(8, &value)?;
750            Ok(())
751        };
752        assert!(builder.store_dict_data(8, value_writer, data).is_err());
753        Ok(())
754    }
755
756    #[test]
757    fn test_store_tonhash() -> Result<(), TonCellError> {
758        let mut writer = CellBuilder::new();
759        let ton_hash =
760            TonHash::from_hex("9f31f4f413a3accb706c88962ac69d59103b013a0addcfaeed5dd73c18fa98a8")?;
761
762        writer.store_tonhash(&ton_hash)?;
763        let cell = writer.build()?;
764        let mut parser = cell.parser();
765        let parsed = parser.load_tonhash()?;
766        assert_eq!(ton_hash, parsed);
767        parser.ensure_empty()?;
768        Ok(())
769    }
770
771    #[test]
772    fn test_store_load_signed_unaligned() -> Result<(), TonCellError> {
773        let mut builder = CellBuilder::new();
774        builder.store_bit(false)?;
775        builder.store_i8(8, -4)?;
776        builder.store_i32(32, -5)?;
777        builder.store_i64(64, -6)?;
778        builder.store_u32(9, 256)?;
779        let cell = builder.build()?;
780        let mut parser = cell.parser();
781        assert!(!parser.load_bit()?);
782        assert_eq!(parser.load_i8(8)?, -4);
783        assert_eq!(parser.load_i32(32)?, -5);
784        assert_eq!(parser.load_i64(64)?, -6);
785        assert_eq!(parser.load_u32(9)?, 256);
786        Ok(())
787    }
788
789    #[test]
790    fn test_store_load_117146891372() -> Result<(), TonCellError> {
791        let mut test = CellBuilder::new();
792        test.store_number(257, &BigUint::from_u64(117146891372).unwrap())
793            .unwrap();
794        Ok(())
795    }
796}