Skip to main content

rustdb/
util.rs

1use crate::{BTreeSet, Data, HashMap, Rc, RefCell};
2
3/// In debug mode or feature unsafe-optim not enabled, same as debug_assert! otherwise unsafe compiler hint.
4#[cfg(any(debug_assertions, not(feature = "unsafe-optim")))]
5macro_rules! unsafe_assert {
6    ( $cond: expr_2021 ) => {
7        debug_assert!($cond)
8    };
9}
10
11/// In debug mode or feature unsafe-optim not enabled, same as debug_assert! otherwise unsafe compiler hint.
12#[cfg(all(not(debug_assertions), feature = "unsafe-optim"))]
13macro_rules! unsafe_assert {
14    ( $cond: expr ) => {
15        if !$cond {
16            unsafe { std::hint::unreachable_unchecked() }
17        }
18    };
19}
20
21/// In debug mode or feature unsafe-optim not enabled, same as panic! otherwise unsafe compiler hint.
22#[cfg(any(debug_assertions, not(feature = "unsafe-optim")))]
23macro_rules! unsafe_panic {
24    () => {
25        panic!()
26    };
27}
28
29/// In debug mode or feature unsafe-optim not enabled, same as debug_assert! otherwise unsafe compiler hint.
30#[cfg(all(not(debug_assertions), feature = "unsafe-optim"))]
31macro_rules! unsafe_panic {
32    () => {{ unsafe { std::hint::unreachable_unchecked() } }};
33}
34
35/// Wrap a type in Rc + RefCell.
36pub fn new<T>(x: T) -> std::rc::Rc<std::cell::RefCell<T>> {
37    Rc::new(RefCell::new(x))
38}
39
40/// New Data ( `Arc::new(Vec::new())` ).
41pub fn nd() -> Data {
42    Data::default()
43}
44
45/// Construct a new map wrapped in a RefCell.
46pub fn newmap<K, T>() -> RefCell<HashMap<K, T>> {
47    RefCell::new(HashMap::default())
48}
49
50/// Extract u64 from byte data.
51pub fn getu64(data: &[u8], off: usize) -> u64 {
52    unsafe_assert!(off + 8 <= data.len());
53    let data = &data[off..off + 8];
54    u64::from_le_bytes(data.try_into().unwrap())
55}
56
57/// Store u64 to byte data.
58pub fn setu64(data: &mut [u8], val: u64) {
59    unsafe_assert!(data.len() >= 8);
60    data[0..8].copy_from_slice(&val.to_le_bytes());
61}
62
63/// Extract f64 from byte data.
64pub fn getf64(data: &[u8], off: usize) -> f64 {
65    let data = &data[off..off + 8];
66    f64::from_le_bytes(data.try_into().unwrap())
67}
68
69/// Extract f32 from byte data.
70pub fn getf32(data: &[u8], off: usize) -> f32 {
71    let data = &data[off..off + 4];
72    f32::from_le_bytes(data.try_into().unwrap())
73}
74
75/// Extract unsigned value of n bytes from data.
76pub fn get(data: &[u8], off: usize, n: usize) -> u64 {
77    let mut buf = [0_u8; 8];
78    unsafe_assert!(off + n <= data.len());
79    buf[0..n].copy_from_slice(&data[off..off + n]);
80    u64::from_le_bytes(buf)
81}
82
83/// Extract signed value of n bytes from data.
84pub fn iget(data: &[u8], off: usize, n: usize) -> i64 {
85    let mut x: u64 = get(data, off, n);
86    if n < 8 {
87        let sign_bit = 1 << (n * 8 - 1);
88        if (sign_bit & x) != 0 {
89            x += u64::MAX << (n * 8);
90        }
91    }
92    x as i64
93}
94
95/// Store signed value of n bytes to data ( with overflow check ).
96pub fn iset(data: &mut [u8], off: usize, val: i64, n: usize) {
97    if n < 8 {
98        let chk = val + (1 << ((n * 8) - 1));
99        if chk < 0 || chk >= (1 << (n * 8)) {
100            panic!("overflow storing value {} in {} bytes", val, n);
101        }
102    }
103    let bytes = val.to_le_bytes();
104    data[off..off + n].copy_from_slice(&bytes[0..n]);
105}
106
107/// Store unsigned value of n bytes to data.
108pub fn set(data: &mut [u8], off: usize, val: u64, n: usize) {
109    let bytes = val.to_le_bytes();
110    data[off..off + n].copy_from_slice(&bytes[0..n]);
111}
112
113// Bitfield  macros
114
115/// The mask to extract $len bits at bit offset $off.
116macro_rules! bitmask {
117    ( $off: expr_2021, $len: expr_2021 ) => {
118        ((1 << $len) - 1) << $off
119    };
120}
121
122/// Extract $len bits from $val at bit offset $off.
123macro_rules! getbits {
124    ( $val: expr_2021, $off: expr_2021, $len: expr_2021 ) => {
125        ($val & bitmask!($off, $len)) >> $off
126    };
127}
128
129/// Update $len bits in $var at bit offset $off to $val.
130macro_rules! setbits {
131    ( $var: expr_2021, $off: expr_2021, $len: expr_2021, $val: expr_2021 ) => {
132        $var = ($var & !bitmask!($off, $len)) | (($val << $off) & bitmask!($off, $len))
133    };
134}
135
136/// Convert a hex char byte to a byte in range 0..15.
137pub fn hex(c: u8) -> u8 //
138{
139    match c {
140        b'0'..=b'9' => c - b'0',
141        b'A'..=b'F' => c + 10 - b'A',
142        b'a'..=b'f' => c + 10 - b'a',
143        _ => {
144            panic!()
145        }
146    }
147}
148
149/// Convert hex literal to bytes.
150pub fn parse_hex(s: &[u8]) -> Vec<u8> {
151    let n = s.len() / 2;
152    let mut result = Vec::<u8>::with_capacity(n);
153    for i in 0..n {
154        result.push(hex(s[i * 2]) * 16 + hex(s[i * 2 + 1]));
155    }
156    result
157}
158
159/// Convert bytes to hex string.
160pub fn to_hex(bytes: &[u8]) -> String {
161    const HEX: &[u8; 16] = b"0123456789abcdef";
162    let mut s = vec![b'0', b'x'];
163    for b in bytes {
164        let b = *b as usize;
165        s.push(HEX[b / 16]);
166        s.push(HEX[b % 16]);
167    }
168    String::from_utf8(s).unwrap()
169}
170
171/// Set of usize, optimised for elements < 64. default() is empty set.
172#[derive(Default)]
173pub struct SmallSet {
174    /// Holds elements < 64 as a bitmap.
175    bitset: u64,
176    /// Holds elements >= 64.
177    overflow: BTreeSet<usize>,
178}
179
180impl SmallSet {
181    /*
182        /// The set is empty.
183        pub fn is_empty(&self) -> bool {
184            self.bitset == 0 && self.overflow.len() == 0
185        }
186    */
187
188    /// Insert x into set.
189    pub fn insert(&mut self, x: usize) {
190        if x < 64 {
191            self.bitset |= 1 << x;
192        } else {
193            self.overflow.insert(x);
194        }
195    }
196
197    /// Test whether set contains x.
198    pub fn contains(&self, x: usize) -> bool {
199        if x < 64 {
200            self.bitset & (1 << x) != 0
201        } else {
202            self.overflow.contains(&x)
203        }
204    }
205
206    /// Remove x from set, result is whether set contained x.
207    pub fn remove(&mut self, x: usize) -> bool {
208        if x < 64 {
209            let bit: u64 = 1 << x;
210            let result = self.bitset & bit != 0;
211            self.bitset &= u64::MAX - bit;
212            result
213        } else {
214            self.overflow.remove(&x)
215        }
216    }
217}
218
219/// Function to compare bytes. Length is taken from a. Calls d for each range that is different.
220/// Interior equal ranges less than min_eq are taken as different.
221pub fn _diff<F>(a: &[u8], b: &[u8], min_eq: usize, mut d: F)
222where
223    F: FnMut(usize, usize),
224{
225    let mut check = 0;
226    let mut i = 0;
227    let n = a.len();
228    while i < n && a[i] == b[i] {
229        i += 1;
230    }
231    while i < n {
232        let start = i;
233        let mut end;
234        loop {
235            loop {
236                i += 1;
237                if i == n || a[i] == b[i] {
238                    break;
239                }
240            }
241            end = i;
242            // Check that following equal range is at least min_eq.
243            while i < n && a[i] == b[i] {
244                i += 1;
245            }
246            if i - end >= min_eq || i == n {
247                break;
248            }
249        }
250        assert_eq!(a[check..start], b[check..start]);
251        check = end;
252        d(start, end - start);
253    }
254    assert_eq!(a[check..n], b[check..n]);
255}
256
257#[test]
258fn difftest() {
259    use rand::Rng;
260    let mut rng = rand::thread_rng();
261    for _ in 0..1000 {
262        let mut v = Vec::new();
263        for _i in 0..100 {
264            v.push(0);
265        }
266        let mut v2 = v.clone();
267        for _ in 0..rng.r#gen::<usize>() % 50 {
268            v2[rng.r#gen::<usize>() % 100] = 1;
269        }
270        let mut x = 0;
271        _diff(&v, &v2, 2, |off, len| {
272            //println!("off={off} len={len}");
273            assert_eq!(v[x..off], v2[x..off]);
274            x = off + len;
275        });
276        assert_eq!(v[x..], v2[x..]);
277        //println!("Done a test");
278    }
279}