darkfi_sdk/monotree/
bits.rs1use std::ops::Range;
21
22use super::{
23 utils::{bit, bytes_to_int, len_lcp, nbytes_across},
24 BitsLen,
25};
26use crate::GenericResult;
27
28#[derive(Debug, Clone, PartialEq)]
32pub struct BitsOwned {
33 path: Vec<u8>,
35 len: BitsLen,
37 offset: BitsLen,
39}
40
41impl BitsOwned {
42 #[inline]
44 pub fn new(len: BitsLen, offset: BitsLen) -> Self {
45 let num_bytes = len.div_ceil(8) as usize;
46 Self { path: vec![0u8; num_bytes], len, offset }
47 }
48
49 #[inline]
51 fn from_raw(path: Vec<u8>, len: BitsLen, offset: BitsLen) -> Self {
52 Self { path, len, offset }
53 }
54
55 #[inline]
56 pub fn len(&self) -> BitsLen {
57 self.len
58 }
59
60 #[inline]
61 pub fn is_empty(&self) -> bool {
62 self.len == 0
63 }
64
65 #[inline]
66 pub fn first(&self) -> bool {
67 debug_assert!(self.is_empty(), "cannot get first bit of empty BitsOwned");
68 self.path[0] & 0x80 != 0
69 }
70
71 pub fn to_bytes(&self) -> GenericResult<Vec<u8>> {
74 let start = self.offset;
75 let end = self.offset + self.len;
76
77 let byte_start = (start / 8) as usize;
78 let byte_end = end.div_ceil(8) as usize;
79 let num_path_bytes = byte_end - byte_start;
80
81 let mut result = Vec::with_capacity(4 + num_path_bytes);
82 result.extend_from_slice(&start.to_be_bytes());
83 result.extend_from_slice(&end.to_be_bytes());
84
85 if num_path_bytes == 0 {
86 return Ok(result)
87 }
88
89 let bit_shift = (start % 8) as usize;
90
91 if bit_shift == 0 {
92 result.extend_from_slice(&self.path[..num_path_bytes]);
94 } else {
95 for i in 0..num_path_bytes {
97 let hi = if i == 0 { 0 } else { self.path.get(i - 1).copied().unwrap_or(0) };
98 let lo = self.path.get(i).copied().unwrap_or(0);
99 let byte = (hi << (8 - bit_shift)) | (lo >> bit_shift);
100 result.push(byte);
101 }
102 }
103
104 let lead_mask = 0xFFu8 >> (start % 8) as u8;
106 result[4] &= lead_mask;
107
108 let trail = (end % 8) as u8;
110 if trail != 0 {
111 let trail_mask = 0xFFu8 << (8 - trail);
112 let last_idx = result.len() - 1;
113 result[last_idx] &= trail_mask;
114 }
115
116 Ok(result)
117 }
118}
119
120#[inline]
122fn extract_normalized(bits: &Bits) -> Vec<u8> {
123 let len = bits.len();
124 if len == 0 {
125 return Vec::new();
126 }
127
128 let num_bytes = len.div_ceil(8) as usize;
129 let bit_offset = (bits.range.start % 8) as usize;
130 let byte_start = (bits.range.start / 8) as usize;
131 let byte_end = bits.range.end.div_ceil(8) as usize;
132 let src = &bits.path[byte_start..byte_end];
133
134 let mut result = vec![0u8; num_bytes];
135
136 if bit_offset == 0 {
137 result[..num_bytes.min(src.len())].copy_from_slice(&src[..num_bytes.min(src.len())]);
139 } else {
140 for (i, bit) in result.iter_mut().enumerate().take(num_bytes) {
142 let hi = src.get(i).copied().unwrap_or(0);
143 let lo = src.get(i + 1).copied().unwrap_or(0);
144 *bit = (hi << bit_offset) | (lo >> (8 - bit_offset));
145 }
146 }
147
148 let trail = (len % 8) as usize;
150 if trail != 0 && !result.is_empty() {
151 let last = result.len() - 1;
152 result[last] &= 0xFF << (8 - trail);
153 }
154
155 result
156}
157
158#[inline]
160fn append_normalized(dst: &mut Vec<u8>, dst_len: BitsLen, src: &[u8], src_len: BitsLen) {
161 if src_len == 0 {
162 return
163 }
164
165 let total_len = dst_len + src_len;
166 let new_bytes = total_len.div_ceil(8) as usize;
167 dst.resize(new_bytes, 0);
168
169 let bit_offset = (dst_len % 8) as usize;
170 let byte_offset = (dst_len / 8) as usize;
171
172 if bit_offset == 0 {
173 let copy_len = src.len().min(new_bytes - byte_offset);
175 dst[byte_offset..byte_offset + copy_len].copy_from_slice(&src[..copy_len]);
176 } else {
177 for i in 0..src.len() {
179 let shifted_hi = src[i] >> bit_offset;
180 let shifted_lo = src[i] << (8 - bit_offset);
181
182 dst[byte_offset + i] |= shifted_hi;
183 if byte_offset + i + 1 < dst.len() {
184 dst[byte_offset + i + 1] |= shifted_lo;
185 }
186 }
187 }
188}
189
190#[inline]
192pub fn merge_owned_and_bits(a: &BitsOwned, b: &Bits) -> BitsOwned {
193 let a_len = a.len();
194 let b_len = b.len();
195 let total_len = a_len + b_len;
196
197 if total_len == 0 {
198 return BitsOwned::from_raw(Vec::new(), 0, a.offset);
199 }
200
201 let mut path = a.path.clone();
203
204 let b_norm = extract_normalized(b);
206 append_normalized(&mut path, a_len, &b_norm, b_len);
207
208 BitsOwned::from_raw(path, total_len, a.offset)
209}
210
211#[derive(Debug, Clone, PartialEq)]
212pub struct Bits<'a> {
214 pub path: &'a [u8],
215 pub range: Range<BitsLen>,
216}
217
218impl<'a> Bits<'a> {
219 pub fn new(bytes: &'a [u8]) -> Self {
220 Bits { path: bytes, range: 0..(bytes.len() as BitsLen * 8) }
221 }
222
223 pub fn from_bytes(bytes: &'a [u8]) -> Self {
225 let u = std::mem::size_of::<BitsLen>();
226 let start: BitsLen = bytes_to_int(&bytes[..u]);
227 let end: BitsLen = bytes_to_int(&bytes[u..2 * u]);
228 Self { path: &bytes[2 * u..], range: start..end }
229 }
230
231 pub fn to_bytes(&self) -> GenericResult<Vec<u8>> {
233 let start = (self.range.start / 8) as usize;
234 let end = self.range.end.div_ceil(8) as usize;
235 let mut path = self.path[start..end].to_owned();
236 let r = (self.range.start % 8) as u8;
237 if r != 0 {
238 let mask = 0xffu8 >> r;
239 path[0] &= mask;
240 }
241 let r = (self.range.end % 8) as u8;
242 if r != 0 {
243 let mask = 0xffu8 << (8 - r);
244 let last = path.len() - 1;
245 path[last] &= mask;
246 }
247 Ok([&self.range.start.to_be_bytes(), &self.range.end.to_be_bytes(), &path[..]].concat())
248 }
249
250 pub fn first(&self) -> bool {
252 bit(self.path, self.range.start)
253 }
254
255 pub fn len(&self) -> BitsLen {
256 self.range.end - self.range.start
257 }
258
259 pub fn is_empty(&self) -> bool {
260 self.len() == 0 || self.path.len() == 0
261 }
262
263 pub fn take(&self, n: BitsLen) -> Self {
265 let x = self.range.start + n;
266 let q = nbytes_across(self.range.start, x);
267 let range = self.range.start..x;
268 Self { path: &self.path[..q as usize], range }
269 }
270
271 pub fn drop(&self, n: BitsLen) -> Self {
273 let x = self.range.start + n;
274 let q = x / 8;
275 let range = x % 8..self.range.end - 8 * (x / 8);
276 Self { path: &self.path[q as usize..], range }
277 }
278
279 pub fn len_common_bits(a: &Self, b: &Self) -> BitsLen {
281 len_lcp(a.path, &a.range, b.path, &b.range)
282 }
283
284 #[inline]
286 pub fn to_bits_owned(&self) -> BitsOwned {
287 let path = extract_normalized(self);
288 BitsOwned::from_raw(path, self.len(), self.range.start)
289 }
290
291 #[inline]
293 pub fn merge(a: &Self, b: &Self) -> BitsOwned {
294 let a_len = a.len();
295 let b_len = b.len();
296 let total_len = a_len + b_len;
297
298 if total_len == 0 {
299 return BitsOwned::from_raw(Vec::new(), 0, a.range.start);
300 }
301
302 let mut path = extract_normalized(a);
304 let b_norm = extract_normalized(b);
305
306 append_normalized(&mut path, a_len, &b_norm, b_len);
308
309 BitsOwned::from_raw(path, total_len, a.range.start)
310 }
311}