darkfi_sdk/monotree/
bits.rs1use std::{cmp::Ordering, ops::Range};
21
22use super::{
23 utils::{bit, bytes_to_int, len_lcp, offsets},
24 BitsLen,
25};
26use crate::GenericResult;
27
28#[derive(Debug, Clone)]
30pub struct Bits<'a> {
31 pub path: &'a [u8],
32 pub range: Range<BitsLen>,
33}
34
35impl<'a> Bits<'a> {
36 pub fn new(bytes: &'a [u8]) -> Self {
37 Self { path: bytes, range: 0..(bytes.len() as BitsLen * 8) }
38 }
39
40 pub fn from_bytes(bytes: &'a [u8]) -> Self {
42 let u = std::mem::size_of::<BitsLen>();
43 let start: BitsLen = bytes_to_int(&bytes[..u]);
44 let end: BitsLen = bytes_to_int(&bytes[u..2 * u]);
45 Self { path: &bytes[2 * u..], range: start..end }
46 }
47
48 pub fn to_bytes(&self) -> GenericResult<Vec<u8>> {
50 Ok([&self.range.start.to_be_bytes(), &self.range.end.to_be_bytes(), self.path].concat())
51 }
52
53 pub fn first(&self) -> bool {
55 bit(self.path, self.range.start)
56 }
57
58 pub fn len(&self) -> BitsLen {
59 self.range.end - self.range.start
60 }
61
62 pub fn is_empty(&self) -> bool {
63 self.len() == 0 || self.path.len() == 0
64 }
65
66 pub fn shift(&self, n: BitsLen, tail: bool) -> Self {
68 let (q, range) = offsets(&self.range, n, tail);
69 if tail {
70 Self { path: &self.path[..q as usize], range }
71 } else {
72 Self { path: &self.path[q as usize..], range }
73 }
74 }
75
76 pub fn len_common_bits(a: &Self, b: &Self) -> BitsLen {
78 len_lcp(a.path, &a.range, b.path, &b.range)
79 }
80
81 pub fn bit(&self, i: BitsLen) -> bool {
83 assert!(i < self.len(), "Bit index out of range");
84 bit(self.path, self.range.start + i)
85 }
86
87 pub fn lexical_cmp(&self, other: &Self) -> Ordering {
89 let min_len = std::cmp::min(self.len(), other.len());
90
91 for i in 0..min_len {
93 match (self.bit(i), other.bit(i)) {
94 (false, true) => return Ordering::Less,
95 (true, false) => return Ordering::Greater,
96 _ => continue,
97 }
98 }
99
100 self.len().cmp(&other.len())
102 }
103}
104
105impl PartialEq for Bits<'_> {
107 fn eq(&self, other: &Self) -> bool {
108 self.len() == other.len() && (0..self.len()).all(|i| self.bit(i) == other.bit(i))
109 }
110}
111
112impl Eq for Bits<'_> {}
113
114#[allow(clippy::non_canonical_partial_ord_impl)]
115impl PartialOrd for Bits<'_> {
116 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
117 Some(self.lexical_cmp(other))
118 }
119}
120
121impl Ord for Bits<'_> {
122 fn cmp(&self, other: &Self) -> Ordering {
123 self.lexical_cmp(other)
124 }
125}