1use std::io::Cursor;
2
3use bitstream_io::{BigEndian, BitWrite, BitWriter, ByteRead, ByteReader};
4use crc::Crc;
5use lazy_static::lazy_static;
6
7use crate::cell::level_mask::LevelMask;
8use crate::cell::{MapTonCellError, TonCellError};
9
10lazy_static! {
11 pub static ref CRC_32_ISCSI: Crc<u32> = Crc::<u32>::new(&crc::CRC_32_ISCSI);
12}
13
14#[derive(PartialEq, Eq, Debug, Clone, Hash)]
18pub(crate) struct RawCell {
19 pub(crate) data: Vec<u8>,
20 pub(crate) bit_len: usize,
21 pub(crate) references: Vec<usize>,
22 pub(crate) is_exotic: bool,
23 level_mask: u32,
24}
25
26impl RawCell {
27 pub(crate) fn new(
28 data: Vec<u8>,
29 bit_len: usize,
30 references: Vec<usize>,
31 level_mask: u32,
32 is_exotic: bool,
33 ) -> Self {
34 Self {
35 data,
36 bit_len,
37 references,
38 level_mask: level_mask & 7,
39 is_exotic,
40 }
41 }
42}
43
44#[derive(PartialEq, Eq, Debug, Clone, Hash)]
48pub(crate) struct RawBagOfCells {
49 pub(crate) cells: Vec<RawCell>,
50 pub(crate) roots: Vec<usize>,
51}
52
53const GENERIC_BOC_MAGIC: u32 = 0xb5ee9c72;
54const _INDEXED_BOC_MAGIC: u32 = 0x68ff65f3;
55const _INDEXED_CRC32_MAGIC: u32 = 0xacc3a728;
56
57impl RawBagOfCells {
58 pub(crate) fn parse(serial: &[u8]) -> Result<RawBagOfCells, TonCellError> {
59 let cursor = Cursor::new(serial);
60
61 let mut reader: ByteReader<Cursor<&[u8]>, BigEndian> =
62 ByteReader::endian(cursor, BigEndian);
63 let magic = reader.read::<u32>().map_boc_deserialization_error()?;
65
66 let (has_idx, has_crc32c, _has_cache_bits, size) = match magic {
67 GENERIC_BOC_MAGIC => {
68 let header = reader.read::<u8>().map_boc_deserialization_error()?;
70 let has_idx = header & 0b1000_0000 != 0;
71 let has_crc32c = header & 0b0100_0000 != 0;
72 let has_cache_bits = header & 0b0010_0000 != 0;
73
74 let size = header & 0b0000_0111;
76 if size > 4 {
77 return Err(TonCellError::boc_deserialization_error(format!(
78 "Invalid size {size}. Size should be <= 4."
79 )));
80 }
81
82 (has_idx, has_crc32c, has_cache_bits, size)
83 }
84 magic => {
85 return Err(TonCellError::boc_deserialization_error(format!(
86 "Unsupported cell magic number: {:#}",
87 magic
88 )));
89 }
90 };
91 let off_bytes = reader.read::<u8>().map_boc_deserialization_error()?;
93 let cells = read_var_size(&mut reader, size)?;
95 let roots = read_var_size(&mut reader, size)?;
97 let _absent = read_var_size(&mut reader, size)?;
99 let _tot_cells_size = read_var_size(&mut reader, off_bytes)?;
101 let mut root_list = vec![];
103 for _ in 0..roots {
104 root_list.push(read_var_size(&mut reader, size)?)
105 }
106 let mut index = vec![];
108 if has_idx {
109 for _ in 0..cells {
110 index.push(read_var_size(&mut reader, off_bytes)?)
111 }
112 }
113 let mut cell_vec = Vec::with_capacity(cells);
115
116 for _ in 0..cells {
117 let cell = read_cell(&mut reader, size)?;
118 cell_vec.push(cell);
119 }
120 let _crc32c = if has_crc32c {
122 reader.read::<u32>().map_boc_deserialization_error()?
123 } else {
124 0
125 };
126 Ok(RawBagOfCells {
129 cells: cell_vec,
130 roots: root_list,
131 })
132 }
133
134 pub(crate) fn serialize(&self, has_crc32: bool) -> Result<Vec<u8>, TonCellError> {
135 let root_count = self.roots.len();
138 let num_ref_bits = 32 - (self.cells.len() as u32).leading_zeros();
139 let num_ref_bytes = num_ref_bits.div_ceil(8);
140 let has_idx = false;
141
142 let mut full_size = 0u32;
143
144 for cell in &self.cells {
145 full_size += raw_cell_size(cell, num_ref_bytes);
146 }
147
148 let num_offset_bits = 32 - full_size.leading_zeros();
149 let num_offset_bytes = num_offset_bits.div_ceil(8);
150
151 let total_size = 4 + 1 + 1 + 3 * num_ref_bytes + num_offset_bytes + num_ref_bytes + (if has_idx { self.cells.len() as u32 * num_offset_bytes } else { 0 }) +
158 full_size +
159 (if has_crc32 { 4 } else { 0 });
160
161 let mut writer = BitWriter::endian(Vec::with_capacity(total_size as usize), BigEndian);
162
163 writer
164 .write_var(32, GENERIC_BOC_MAGIC)
165 .map_boc_serialization_error()?;
166
167 let has_cache_bits = false;
169 let flags: u8 = 0;
170 writer.write_bit(has_idx).map_boc_serialization_error()?;
171 writer.write_bit(has_crc32).map_boc_serialization_error()?;
172 writer
173 .write_bit(has_cache_bits)
174 .map_boc_serialization_error()?;
175 writer.write_var(2, flags).map_boc_serialization_error()?;
176 writer
177 .write_var(3, num_ref_bytes)
178 .map_boc_serialization_error()?;
179 writer
180 .write_var(8, num_offset_bytes)
181 .map_boc_serialization_error()?;
182 writer
183 .write_var(8 * num_ref_bytes, self.cells.len() as u32)
184 .map_boc_serialization_error()?;
185 writer
186 .write_var(8 * num_ref_bytes, root_count as u32)
187 .map_boc_serialization_error()?;
188 writer
189 .write_var(8 * num_ref_bytes, 0)
190 .map_boc_serialization_error()?; writer
192 .write_var(8 * num_offset_bytes, full_size)
193 .map_boc_serialization_error()?;
194 for &root in &self.roots {
195 writer
196 .write_var(8 * num_ref_bytes, root as u32)
197 .map_boc_serialization_error()?;
198 }
199
200 for cell in &self.cells {
201 write_raw_cell(&mut writer, cell, num_ref_bytes)?;
202 }
203
204 if has_crc32 {
205 let bytes = writer.writer().ok_or_else(|| {
206 TonCellError::boc_serialization_error("Stream is not byte-aligned")
207 })?;
208 let cs = CRC_32_ISCSI.checksum(bytes.as_slice());
209 writer
210 .write_bytes(cs.to_le_bytes().as_slice())
211 .map_boc_serialization_error()?;
212 }
213 writer.byte_align().map_boc_serialization_error()?;
214 let res = writer
215 .writer()
216 .ok_or_else(|| TonCellError::boc_serialization_error("Stream is not byte-aligned"))?;
217 Ok(res.clone())
218 }
219}
220
221fn read_cell(
222 reader: &mut ByteReader<Cursor<&[u8]>, BigEndian>,
223 size: u8,
224) -> Result<RawCell, TonCellError> {
225 let d1 = reader.read::<u8>().map_boc_deserialization_error()?;
226 let d2 = reader.read::<u8>().map_boc_deserialization_error()?;
227
228 let ref_num = d1 & 0b111;
229 let is_exotic = (d1 & 0b1000) != 0;
230 let has_hashes = (d1 & 0b10000) != 0;
231 let level_mask = (d1 >> 5) as u32;
232 let data_size = ((d2 >> 1) + (d2 & 1)).into();
233 let full_bytes = (d2 & 0x01) == 0;
234
235 if has_hashes {
236 let hash_count = LevelMask::new(level_mask).hash_count();
237 let skip_size = hash_count * (32 + 2);
238
239 reader
241 .skip(skip_size as u32)
242 .map_boc_deserialization_error()?;
243 }
244
245 let mut data = reader
246 .read_to_vec(data_size)
247 .map_boc_deserialization_error()?;
248
249 let data_len = data.len();
250 let padding_len = if data_len > 0 && !full_bytes {
251 let num_zeros = data[data_len - 1].trailing_zeros();
254 if num_zeros >= 8 {
255 return Err(TonCellError::boc_deserialization_error(
256 "Last byte of binary must not be zero if full_byte flag is not set",
257 ));
258 }
259 data[data_len - 1] &= !(1 << num_zeros);
260 num_zeros + 1
261 } else {
262 0
263 };
264 let bit_len = data.len() * 8 - padding_len as usize;
265 let mut references: Vec<usize> = Vec::new();
266 for _ in 0..ref_num {
267 references.push(read_var_size(reader, size)?);
268 }
269 let cell = RawCell::new(data, bit_len, references, level_mask, is_exotic);
270 Ok(cell)
271}
272
273fn raw_cell_size(cell: &RawCell, ref_size_bytes: u32) -> u32 {
274 let data_len = cell.bit_len.div_ceil(8);
275 2 + data_len as u32 + cell.references.len() as u32 * ref_size_bytes
276}
277
278fn write_raw_cell(
279 writer: &mut BitWriter<Vec<u8>, BigEndian>,
280 cell: &RawCell,
281 ref_size_bytes: u32,
282) -> Result<(), TonCellError> {
283 let level = cell.level_mask;
284 let is_exotic = cell.is_exotic as u32;
285 let num_refs = cell.references.len() as u32;
286 let d1 = num_refs + is_exotic * 8 + level * 32;
287
288 let padding_bits = cell.bit_len % 8;
289 let full_bytes = padding_bits == 0;
290 let data = cell.data.as_slice();
291 let data_len_bytes = cell.bit_len.div_ceil(8);
292 let d2 = (data_len_bytes * 2 - if full_bytes { 0 } else { 1 }) as u8; writer.write_var(8, d1).map_boc_serialization_error()?;
296 writer.write_var(8, d2).map_boc_serialization_error()?;
297 if !full_bytes {
298 writer
299 .write_bytes(&data[..data_len_bytes - 1])
300 .map_boc_serialization_error()?;
301 let last_byte = data[data_len_bytes - 1];
302 let l = last_byte | (1 << (8 - padding_bits - 1));
303 writer.write_var(8, l).map_boc_serialization_error()?;
304 } else {
305 writer.write_bytes(data).map_boc_serialization_error()?;
306 }
307
308 for r in cell.references.as_slice() {
309 writer
310 .write_var(8 * ref_size_bytes, *r as u32)
311 .map_boc_serialization_error()?;
312 }
313
314 Ok(())
315}
316
317fn read_var_size(
318 reader: &mut ByteReader<Cursor<&[u8]>, BigEndian>,
319 n: u8,
320) -> Result<usize, TonCellError> {
321 let bytes = reader
322 .read_to_vec(n.into())
323 .map_boc_deserialization_error()?;
324
325 let mut result = 0;
326 for &byte in &bytes {
327 result <<= 8;
328 result |= usize::from(byte);
329 }
330 Ok(result)
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336
337 #[test]
338 fn test_raw_cell_serialize() {
339 let raw_cell = RawCell::new(vec![1; 128], 1023, vec![], 255, false);
340 let raw_bag = RawBagOfCells {
341 cells: vec![raw_cell],
342 roots: vec![0],
343 };
344 assert!(raw_bag.serialize(false).is_ok());
345 }
346}