bustools/busz/
utils.rs

1use bitvec::field::BitField;
2use itertools::Itertools;
3
4use super::BuszBitSlice;
5
6/// turn a bitslice into an array of bytes
7/// the first 8 bits (bits[..8]) will become the first byte in the result
8/// i.e. a sort of BigEndian encoding
9pub (crate) fn bitslice_to_bytes(bits: &BuszBitSlice) -> Vec<u8>{
10
11    assert_eq!(bits.len() % 8,  0, "cant covnert to bytes if Bitsclie is not a multiple of 8");
12
13    let nbytes = bits.len() / 8;
14    let mut bytes = Vec::with_capacity(nbytes);
15    for i in 0..nbytes {
16        let b = &bits[i*8.. (i+1)*8];
17        let a: u8 = b.load_be(); // doesnt matter if be/le here since its only 1byte anyway
18        bytes.push(a);
19    }
20    bytes
21}
22
23/// for debugging: display a BitVec as a string of bits
24pub (crate) fn bitstream_to_string(buffer: &BuszBitSlice) -> String{
25    let mut s = String::new();
26    let x = buffer.iter().map(|x| if *x{"1"} else {"0"});
27    for bit64 in &x.into_iter().chunks(64){
28        let concat = bit64.collect::<Vec<_>>().join("");
29        s.push_str(&concat);
30        s.push('\n');
31    }
32    s
33}
34
35// all the encoded parts (cb,umi,ec...) are padded with zeros until a mutiple of 64
36// which we need to remove
37pub(crate) fn calc_n_trailing_bits(bits_processed: usize) -> usize {
38    let padded_size = round_to_multiple(bits_processed, 64);
39    let zeros_toremoved = padded_size - bits_processed;
40    zeros_toremoved
41}
42
43// // // turn a bitvector (64 elements) into a u64
44// pub fn bits64_to_u64(x: bit_vec::BitVec) -> u64{
45//     assert_eq!(x.len(), 64);
46//     u64::from_le_bytes(x.to_bytes()[..8].try_into().unwrap())
47// }
48
49/// swaps endianness of the byte-vector
50/// assuming 8byte (u64) words
51/// simply grabs each 8byte section and reverses the order within
52/// # params
53/// * wordsize: 4 (bytes) for u32, 8(bytes) for u64
54pub (crate) fn swap_endian(bytes: &[u8], wordsize: usize) -> Vec<u8>{
55    let mut swapped_endian: Vec<u8> = Vec::with_capacity(bytes.len());
56    for bytes in bytes.chunks(wordsize){
57        swapped_endian.extend(bytes.iter().rev());
58    }
59    swapped_endian
60}
61
62/// shortcut for doing swap_endian(swap_endian(x, 8), 4)
63/// essentially does tihs:
64/// ...ABCD|EFGH...: ....EFGH|ABCD...
65pub (crate) fn swap_endian8_swap_endian4(bytes: &[u8], ) -> Vec<u8>{
66    let mut swapped_endian: Vec<u8> = Vec::with_capacity(bytes.len());
67    for bytes in bytes.chunks(8){
68        swapped_endian.extend(&bytes[4..]);
69        swapped_endian.extend(&bytes[..4]);
70    }
71    swapped_endian
72}
73
74/// does the endian8-endian4 swap, but without allocating anything
75/// just does it in the vec itself
76pub (crate) fn swap_endian8_swap_endian4_inplace(x: &mut [u8]) {
77    let n_chunks: usize = (x.len() / 8).try_into().expect("must be multiple of 8 (u64=8 bytes!)");
78    for i in 0..n_chunks {
79        let pos = i * 8;
80
81        x.swap(pos, pos+4);
82        x.swap(pos+1, pos+5);
83        x.swap(pos+2, pos+6);
84        x.swap(pos+3, pos+7);
85    }
86}
87
88
89
90
91// pub fn display_u64_in_bits(x: u64) -> String{
92//     let s: Vec<u64> = (0..64).rev().map (|n| (x >> n) & 1).collect();
93//     s.into_iter().map(|x| x.to_string()).collect::<Vec<_>>().join("")
94// }
95
96// pub fn display_u32_in_bits(x: u32) -> String{
97//     let s: Vec<u32> = (0..32).rev().map (|n| (x >> n) & 1).collect();
98//     s.into_iter().map(|x| x.to_string()).collect::<Vec<_>>().join("")
99// }
100
101/// round an integer to the next bigger multiple
102/// ```bash, no_run  // TODO STUPID, wont run on private modules
103///  use bustools::busz::utils::round_to_multiple;
104///  assert_eq!(round_to_multiple(10,10), 10);
105///  assert_eq!(round_to_multiple(11,10), 20);
106///  assert_eq!(round_to_multiple(6,5), 10);
107/// ```
108pub (crate) fn round_to_multiple(i: usize, multiple: usize) -> usize {
109    // ((i+multiple-1)/multiple)*multiple
110    i.next_multiple_of(multiple)  // rust 1.73
111}
112
113/// set the lowest x bits in a 32bit vecotr (represented as u32)
114pub (crate) fn setbits_u32(x: u8) -> u32 {
115    u32::MAX >> (32 - x)
116}
117
118/// set the lowest x bits in a 64bit vecotr (represented as u32)
119pub (crate) fn setbits_u64(x: u8) -> u64 {
120    u64::MAX >> (64 - x)
121}
122
123
124#[cfg(test)]
125mod test {
126    use std::io::Read;
127    use bitvec::{bits, order::Msb0};
128    use fastfibonacci::utils::create_bitvector;
129    use super::*;
130    use crate::busz::utils::{swap_endian, setbits_u32, setbits_u64};
131    #[test]
132    fn test_bitslice_to_bytes() {
133        let b = create_bitvector(vec![
134            0,0,0,0, 0, 0, 1, 1,
135            1,1,1,1, 1, 1, 1, 1,
136        ]);
137        
138        assert_eq!(
139            bitslice_to_bytes(&b),
140            vec![3, 255]
141        );
142
143        assert_eq!(
144            b.bytes().map(|x| x.unwrap()).collect::<Vec<_>>(),
145            vec![3, 255]
146        )
147    }
148
149    #[test]
150    fn test_swap_inmem() {
151        let b = bits![u64, Msb0; 
152            0,0,0,0, 0, 0, 0, 1,
153            0,0,0,0, 0, 0, 1, 1,
154            0,0,0,0, 0, 1, 1, 1,
155            0,0,0,0, 1, 1, 1, 1,
156            0,0,0,1, 1, 1, 1, 1,
157            0,0,1,1, 1, 1, 1, 1,
158            0,1,1,1, 1, 1, 1, 1,
159            1,1,1,1, 1, 1, 1, 1,
160        ];
161        let before = b.bytes().map(|x| x.unwrap()).collect::<Vec<_>>();
162
163        println!("{:?}", before);
164
165
166        let bytes_it = b.bytes().map(|x| x.unwrap());
167
168        let mut swapped_endian: Vec<u8> = Vec::new();
169        for bytes in bytes_it.chunks(8).into_iter(){
170            let b1: Vec<_> = bytes.collect();
171            swapped_endian.extend(&b1[4..]);
172            swapped_endian.extend(&b1[..4]);
173        }
174
175        println!("{:?}", swapped_endian)
176    }
177    #[test]
178    fn endian_swapping() {
179        let v = vec![0_u8,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
180        let a = swap_endian(&v, 8);
181        let b = swap_endian(&a, 4);
182        let c = swap_endian(&b, 4);
183        let d = swap_endian(&c, 8);
184        assert_eq!(v,d);
185    }
186
187    #[test]
188    fn test_setbits_u32() {
189        assert_eq!(setbits_u32(3), 7);
190        assert_eq!(setbits_u32(2), 3);
191        assert_eq!(setbits_u32(1), 1);
192    }
193    #[test]
194    fn test_setbits_u64() {
195        assert_eq!(setbits_u64(3), 7);
196        assert_eq!(setbits_u64(2), 3);
197        assert_eq!(setbits_u64(1), 1);
198
199    }
200    #[test]
201    fn test_swap_endian8_swap_endian4() {
202        let x = &[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24];
203        let y1 = swap_endian8_swap_endian4(x);
204    
205        let y2 = swap_endian(
206            &swap_endian(x, 8),
207            4
208        );
209        assert_eq!(y1, y2);
210    
211        let y3 = swap_endian(
212            &swap_endian(x, 4),
213            8
214        );
215        assert_eq!(y1, y3);
216    
217        // inplace swap
218        let mut a: Vec<u8> = x.to_vec();
219        // println!("before {:?}", a);
220        swap_endian8_swap_endian4_inplace(&mut a);
221        // println!("after {:?}", a);
222        assert_eq!(y1, a);
223    }
224
225}