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 pub fn store_raw_address(&mut self, val: &TonAddress) -> Result<&mut Self, TonCellError> {
145 self.store_u8(2, 0b10u8)?; self.store_bit(false)?; 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 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 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 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 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 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 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 } 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 } 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 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); assert_eq!(written, value);
582
583 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 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}