tonlib_core/cell/
bag_of_cells.rs

1use 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()) // unwrap is safe: we have checked that roots has exactly one element above
48        } 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}