tonlib_core/cell/
bag_of_cells.rs1use std::sync::Arc;
2
3use base64::engine::general_purpose::STANDARD;
4
5use crate::cell::raw_boc_from_boc::convert_to_raw_boc;
6use crate::cell::*;
7
8#[derive(PartialEq, Eq, Debug, Clone, Hash)]
9pub struct BagOfCells {
10 pub roots: Vec<ArcCell>,
11}
12
13impl BagOfCells {
14 pub fn new(roots: &[ArcCell]) -> BagOfCells {
15 BagOfCells {
16 roots: roots.to_vec(),
17 }
18 }
19
20 pub fn from_root(root: Cell) -> BagOfCells {
21 let arc = Arc::new(root);
22 BagOfCells { roots: vec![arc] }
23 }
24
25 pub fn add_root(&mut self, root: Cell) {
26 let arc = Arc::new(root);
27 self.roots.push(arc)
28 }
29
30 pub fn num_roots(&self) -> usize {
31 self.roots.len()
32 }
33
34 pub fn root(&self, idx: usize) -> Result<&ArcCell, TonCellError> {
35 self.roots.get(idx).ok_or_else(|| {
36 TonCellError::boc_deserialization_error(format!(
37 "Invalid root index: {}, BoC contains {} roots",
38 idx,
39 self.roots.len()
40 ))
41 })
42 }
43
44 pub fn single_root(mut self) -> Result<ArcCell, TonCellError> {
45 let roots_count = self.roots.len();
46 if roots_count == 1 {
47 Ok(self.roots.pop().unwrap()) } else {
49 let err_msg = format!("Single root expected, got {roots_count}");
50 Err(TonCellError::CellParserError(err_msg))
51 }
52 }
53
54 pub fn parse(serial: &[u8]) -> Result<BagOfCells, TonCellError> {
55 if serial.is_empty() {
56 return Err(TonCellError::boc_deserialization_error("Empty BoC"));
57 }
58 let raw = RawBagOfCells::parse(serial)?;
59 let num_cells = raw.cells.len();
60 let mut cells: Vec<ArcCell> = Vec::with_capacity(num_cells);
61
62 for (cell_index, raw_cell) in raw.cells.into_iter().enumerate().rev() {
63 let mut references = Vec::with_capacity(raw_cell.references.len());
64 for ref_index in &raw_cell.references {
65 if *ref_index <= cell_index {
66 return Err(TonCellError::boc_deserialization_error(
67 "References to previous cells are not supported",
68 ));
69 }
70 references.push(cells[num_cells - 1 - ref_index].clone());
71 }
72
73 let cell = Cell::new(
74 raw_cell.data,
75 raw_cell.bit_len,
76 references,
77 raw_cell.is_exotic,
78 )
79 .map_boc_deserialization_error()?;
80 cells.push(cell.to_arc());
81 }
82
83 let roots = raw
84 .roots
85 .into_iter()
86 .map(|r| &cells[num_cells - 1 - r])
87 .map(Arc::clone)
88 .collect();
89
90 Ok(BagOfCells { roots })
91 }
92
93 pub fn parse_hex(hex: &str) -> Result<BagOfCells, TonCellError> {
94 let str: String = hex.chars().filter(|c| !c.is_whitespace()).collect();
95 let bin = hex::decode(str.as_str()).map_boc_deserialization_error()?;
96 Self::parse(&bin)
97 }
98
99 pub fn parse_base64(base64: &str) -> Result<BagOfCells, TonCellError> {
100 let bin = STANDARD.decode(base64).map_boc_deserialization_error()?;
101 Self::parse(&bin)
102 }
103
104 pub fn serialize(&self, has_crc32: bool) -> Result<Vec<u8>, TonCellError> {
105 let raw = convert_to_raw_boc(self)?;
106 raw.serialize(has_crc32)
107 }
108}