diff --git a/src/boc/ser.rs b/src/boc/ser.rs index ec0d6d62..a6c30712 100644 --- a/src/boc/ser.rs +++ b/src/boc/ser.rs @@ -117,6 +117,49 @@ where ); } + /// Writes cell trees into the writer. + /// + /// NOTE: Use [`BocHeader::encode`] when possible since it's faster. + pub fn encode_to_writer(&self, mut writer: W) -> std::io::Result<()> { + const CELLS_CHUNK_SIZE: usize = 1000; + const P95_CELL_SIZE: usize = 128; + + let mut crc = self.include_crc.then_some(0u32); + let mut total_size = 0; + + let mut reset_chunk = |chunk: &mut Vec| { + if let Some(crc) = &mut crc { + *crc = crc32c::crc32c_append(*crc, chunk); + } + total_size += chunk.len() as u64; + chunk.clear(); + }; + + let mut chunk = Vec::new(); + + // Write header + let header = self.encode_header(&mut chunk); + ok!(writer.write_all(&chunk)); + reset_chunk(&mut chunk); + + // Write cells + for cells in self.rev_cells.rchunks(CELLS_CHUNK_SIZE) { + chunk.reserve(cells.len() * P95_CELL_SIZE); + self.encode_cells_chunk(cells, header.ref_size, &mut chunk); + ok!(writer.write_all(&chunk)); + reset_chunk(&mut chunk); + } + + debug_assert!(chunk.is_empty()); + + if let Some(crc) = crc { + ok!(writer.write_all(&crc.to_le_bytes())); + } + + debug_assert_eq!(total_size, header.total_size); + Ok(()) + } + /// Encodes cell trees into bytes. /// Uses `rayon` under the hood. #[cfg(feature = "rayon")]