tonlib_core/cell/
util.rs

1use std::io;
2
3use bitstream_io::{BitRead, BitReader, Endianness};
4
5use crate::cell::{MapTonCellError, TonCellError};
6
7pub trait BitReadExt {
8    fn read_bits(&mut self, num_bits: usize, slice: &mut [u8]) -> Result<(), TonCellError>;
9}
10
11impl<R: io::Read, E: Endianness> BitReadExt for BitReader<R, E> {
12    fn read_bits(&mut self, num_bits: usize, slice: &mut [u8]) -> Result<(), TonCellError> {
13        let total_bytes = num_bits.div_ceil(8);
14        if total_bytes > slice.len() {
15            let msg = format!(
16                "Attempt to read {} bits into buffer {} bytes",
17                num_bits,
18                slice.len()
19            );
20            return Err(TonCellError::CellParserError(msg));
21        }
22        let full_bytes = (num_bits) / 8;
23        self.read_bytes(&mut slice[0..full_bytes])
24            .map_cell_parser_error()?;
25        let last_byte_len = num_bits % 8;
26        if last_byte_len != 0 {
27            let last_byte = self
28                .read_var::<u8>(last_byte_len as u32)
29                .map_cell_parser_error()?;
30            slice[full_bytes] = last_byte << (8 - last_byte_len);
31        }
32        Ok(())
33    }
34}
35
36// return false if preconditions are not met
37pub fn rewrite_bits(
38    src: &[u8],
39    src_offset_bits: usize,
40    dst: &mut [u8],
41    dst_offset_bits: usize,
42    len: usize,
43) -> bool {
44    // Calculate total bits available in source and destination
45    let src_total_bits = src.len() * 8;
46    let dst_total_bits = dst.len() * 8;
47
48    // Check preconditions
49    if src_offset_bits + len > src_total_bits || dst_offset_bits + len > dst_total_bits {
50        return false;
51    }
52
53    for i in 0..len {
54        // Calculate the source bit position and extract the bit
55        let src_bit_pos = src_offset_bits + i;
56        let src_byte_index = src_bit_pos / 8;
57        let src_bit_offset = 7 - (src_bit_pos % 8); // MSB is bit 7
58        let src_bit = (src[src_byte_index] >> src_bit_offset) & 1;
59
60        // Calculate the destination bit position and write the bit
61        let dst_bit_pos = dst_offset_bits + i;
62        let dst_byte_index = dst_bit_pos / 8;
63        let dst_bit_offset = 7 - (dst_bit_pos % 8); // MSB is bit 7
64
65        // Clear the target bit and set it to the source bit value
66        dst[dst_byte_index] &= !(1 << dst_bit_offset); // Clear the bit
67        dst[dst_byte_index] |= src_bit << dst_bit_offset; // Set the bit
68    }
69
70    true
71}
72
73#[cfg(test)]
74mod tests {
75    use crate::cell::rewrite_bits;
76
77    #[test]
78    fn test_rewrite_bits() {
79        let src = vec![0b11001100, 0b10101010]; // Source bits
80        let mut dst = vec![0b00000000, 0b00000000]; // Destination bits
81        assert!(rewrite_bits(&src, 4, &mut dst, 8, 8));
82        assert_eq!(dst, vec![0b00000000, 0b11001010]);
83
84        let src = vec![0b11001100, 0b10101010]; // Source bits
85        let mut dst = vec![0b00000000, 0b00000000]; // Destination bits
86        assert!(rewrite_bits(&src, 0, &mut dst, 0, 16));
87        assert_eq!(dst, src);
88
89        let src = vec![0b11001100, 0b10101010]; // Source bits
90        let mut dst = vec![0b00000000, 0b00000000]; // Destination bits
91        assert!(rewrite_bits(&src, 0, &mut dst, 0, 8));
92        assert_eq!(dst[0], src[0]);
93        assert_eq!(dst[1], 0b00000000);
94
95        assert!(!rewrite_bits(&src, 14, &mut dst, 6, 10));
96    }
97}