bit_cursor/
byte_order.rs

1use nsw_types::*;
2use paste::paste;
3
4const U1_ONE: u1 = u1::new(1);
5
6// Helper macro to provide consistent syntax for initializing both nsw_types and standard integer types
7// TODO: better to just define a trait that implements ONE and ZERO for all types?
8macro_rules! init_integer {
9    (u16, $value:expr) => {
10        $value
11    };
12    (u32, $value:expr) => {
13        $value
14    };
15    ($type:ty, $value:expr) => {
16        <$type>::new($value)
17    };
18}
19
20/// Generate a LittleEndian read operation from a buffer for the nsw_types types
21macro_rules! impl_read_le {
22    ($type:ty, $size_bits:expr) => {
23        paste! {
24            fn [<read_ $type>](buf: &[u1; $size_bits]) -> $type {
25                let mut val = <$type>::default();
26                if $size_bits > 32 {
27                    unimplemented!("Only nsw_types types up to 32 bits supported");
28                }
29                if $size_bits > 24 {
30                    for i in 24..std::cmp::min($size_bits, 32) {
31                        val <<= 1;
32                        val |= <nsw_types::u1 as Into<$type>>::into(buf[i]);
33                    }
34                }
35                if $size_bits > 16 {
36                    for i in 16..std::cmp::min($size_bits, 24) {
37                        val <<= 1;
38                        val |= <nsw_types::u1 as Into<$type>>::into(buf[i]);
39                    }
40                }
41                if $size_bits > 8 {
42                    for i in 8..std::cmp::min($size_bits, 16) {
43                        val <<= 1;
44                        val |= <nsw_types::u1 as Into<$type>>::into(buf[i]);
45                    }
46                }
47                for i in 0..std::cmp::min($size_bits, 8) {
48                    val <<= 1;
49                    val |= <nsw_types::u1 as Into<$type>>::into(buf[i]);
50                }
51                val
52            }
53        }
54    };
55}
56
57macro_rules! impl_read_be {
58    ($type:ty, $size_bits:expr) => {
59        paste! {
60            fn [<read_ $type>](buf: &[u1; $size_bits]) -> $type {
61                let mut val = <$type>::default();
62                for bit in buf.iter() {
63                    val <<= 1;
64                    val |= <nsw_types::u1 as Into<$type>>::into(*bit);
65                }
66                val
67            }
68        }
69    };
70}
71
72macro_rules! impl_write_le {
73    ($type:ty, $size_bits:expr) => {
74        paste! {
75            fn [<write_ $type>](buf: &mut [u1; $size_bits], value: $type) {
76                const ZERO: $type = init_integer!($type, 0);
77                const ONE: $type = init_integer!($type, 1);
78                let mut mask = ONE << std::cmp::min($size_bits - 1, 7);
79                for i in 0..std::cmp::min($size_bits, 8) {
80                    if value & mask != ZERO {
81                        buf[i] = U1_ONE;
82                    }
83                    mask >>= 1;
84                }
85                if $size_bits > 8 {
86                    let mut mask = ONE << std::cmp::min($size_bits - 1, 15);
87                    for i in 8..std::cmp::min($size_bits, 16) {
88                        if value & mask != ZERO {
89                            buf[i] = U1_ONE;
90                        }
91                        mask >>= 1;
92                    }
93                }
94                if $size_bits > 16 {
95                    let mut mask = ONE << std::cmp::min($size_bits - 1, 23);
96                    for i in 16..std::cmp::min($size_bits, 24) {
97                        if value & mask != ZERO {
98                            buf[i] = U1_ONE;
99                        }
100                        mask >>= 1;
101                    }
102                }
103                if $size_bits > 24 {
104                    let mut mask = ONE << std::cmp::min($size_bits - 1, 31);
105                    for i in 24..std::cmp::min($size_bits, 32) {
106                        if value & mask != ZERO {
107                            buf[i] = U1_ONE;
108                        }
109                        mask >>= 1;
110                    }
111                }
112            }
113        }
114    };
115}
116
117macro_rules! impl_write_be {
118    ($type:ty, $size_bits:expr) => {
119        paste! {
120            fn [<write_ $type>](buf: &mut [u1; $size_bits], mut value: $type) {
121                const ONE: $type = init_integer!($type, 1);
122                for i in (0..$size_bits).rev() {
123                    if value & ONE == ONE {
124                        buf[i] = U1_ONE;
125                    }
126                    value >>= 1;
127                }
128            }
129        }
130    };
131}
132
133pub trait ByteOrder {
134    fn read_u9(buf: &[u1; 9]) -> u9;
135    fn read_u10(buf: &[u1; 10]) -> u10;
136    fn read_u11(buf: &[u1; 11]) -> u11;
137    fn read_u12(buf: &[u1; 12]) -> u12;
138    fn read_u13(buf: &[u1; 13]) -> u13;
139    fn read_u14(buf: &[u1; 14]) -> u14;
140    fn read_u15(buf: &[u1; 15]) -> u15;
141    fn read_u16(buf: &[u1; 16]) -> u16;
142    fn read_u17(buf: &[u1; 17]) -> u17;
143    fn read_u18(buf: &[u1; 18]) -> u18;
144    fn read_u19(buf: &[u1; 19]) -> u19;
145    fn read_u20(buf: &[u1; 20]) -> u20;
146    fn read_u21(buf: &[u1; 21]) -> u21;
147    fn read_u22(buf: &[u1; 22]) -> u22;
148    fn read_u23(buf: &[u1; 23]) -> u23;
149    fn read_u24(buf: &[u1; 24]) -> u24;
150    fn read_u25(buf: &[u1; 25]) -> u25;
151    fn read_u26(buf: &[u1; 26]) -> u26;
152    fn read_u27(buf: &[u1; 27]) -> u27;
153    fn read_u28(buf: &[u1; 28]) -> u28;
154    fn read_u29(buf: &[u1; 29]) -> u29;
155    fn read_u30(buf: &[u1; 30]) -> u30;
156    fn read_u31(buf: &[u1; 31]) -> u31;
157    fn read_u32(buf: &[u1; 32]) -> u32;
158
159    fn write_u9(buf: &mut [u1; 9], value: u9);
160    fn write_u10(buf: &mut [u1; 10], value: u10);
161    fn write_u11(buf: &mut [u1; 11], value: u11);
162    fn write_u12(buf: &mut [u1; 12], value: u12);
163    fn write_u13(buf: &mut [u1; 13], value: u13);
164    fn write_u14(buf: &mut [u1; 14], value: u14);
165    fn write_u15(buf: &mut [u1; 15], value: u15);
166    fn write_u16(buf: &mut [u1; 16], value: u16);
167    fn write_u17(buf: &mut [u1; 17], value: u17);
168    fn write_u18(buf: &mut [u1; 18], value: u18);
169    fn write_u19(buf: &mut [u1; 19], value: u19);
170    fn write_u20(buf: &mut [u1; 20], value: u20);
171    fn write_u21(buf: &mut [u1; 21], value: u21);
172    fn write_u22(buf: &mut [u1; 22], value: u22);
173    fn write_u23(buf: &mut [u1; 23], value: u23);
174    fn write_u24(buf: &mut [u1; 24], value: u24);
175    fn write_u25(buf: &mut [u1; 25], value: u25);
176    fn write_u26(buf: &mut [u1; 26], value: u26);
177    fn write_u27(buf: &mut [u1; 27], value: u27);
178    fn write_u28(buf: &mut [u1; 28], value: u28);
179    fn write_u29(buf: &mut [u1; 29], value: u29);
180    fn write_u30(buf: &mut [u1; 30], value: u30);
181    fn write_u31(buf: &mut [u1; 31], value: u31);
182    fn write_u32(buf: &mut [u1; 32], value: u32);
183}
184
185pub struct BigEndian {}
186
187pub struct LittleEndian {}
188
189pub type NetworkOrder = BigEndian;
190
191impl ByteOrder for LittleEndian {
192    impl_read_le!(u9, 9);
193    impl_read_le!(u10, 10);
194    impl_read_le!(u11, 11);
195    impl_read_le!(u12, 12);
196    impl_read_le!(u13, 13);
197    impl_read_le!(u14, 14);
198    impl_read_le!(u15, 15);
199    impl_read_le!(u16, 16);
200    impl_read_le!(u17, 17);
201    impl_read_le!(u18, 18);
202    impl_read_le!(u19, 19);
203    impl_read_le!(u20, 20);
204    impl_read_le!(u21, 21);
205    impl_read_le!(u22, 22);
206    impl_read_le!(u23, 23);
207    impl_read_le!(u24, 24);
208    impl_read_le!(u25, 25);
209    impl_read_le!(u26, 26);
210    impl_read_le!(u27, 27);
211    impl_read_le!(u28, 28);
212    impl_read_le!(u29, 29);
213    impl_read_le!(u30, 30);
214    impl_read_le!(u31, 31);
215    impl_read_le!(u32, 32);
216
217    impl_write_le!(u9, 9);
218    impl_write_le!(u10, 10);
219    impl_write_le!(u11, 11);
220    impl_write_le!(u12, 12);
221    impl_write_le!(u13, 13);
222    impl_write_le!(u14, 14);
223    impl_write_le!(u15, 15);
224    impl_write_le!(u16, 16);
225    impl_write_le!(u17, 17);
226    impl_write_le!(u18, 18);
227    impl_write_le!(u19, 19);
228    impl_write_le!(u20, 20);
229    impl_write_le!(u21, 21);
230    impl_write_le!(u22, 22);
231    impl_write_le!(u23, 23);
232    impl_write_le!(u24, 24);
233    impl_write_le!(u25, 25);
234    impl_write_le!(u26, 26);
235    impl_write_le!(u27, 27);
236    impl_write_le!(u28, 28);
237    impl_write_le!(u29, 29);
238    impl_write_le!(u30, 30);
239    impl_write_le!(u31, 31);
240    impl_write_le!(u32, 32);
241}
242
243impl ByteOrder for BigEndian {
244    impl_read_be!(u9, 9);
245    impl_read_be!(u10, 10);
246    impl_read_be!(u11, 11);
247    impl_read_be!(u12, 12);
248    impl_read_be!(u13, 13);
249    impl_read_be!(u14, 14);
250    impl_read_be!(u15, 15);
251    impl_read_be!(u16, 16);
252    impl_read_be!(u17, 17);
253    impl_read_be!(u18, 18);
254    impl_read_be!(u19, 19);
255    impl_read_be!(u20, 20);
256    impl_read_be!(u21, 21);
257    impl_read_be!(u22, 22);
258    impl_read_be!(u23, 23);
259    impl_read_be!(u24, 24);
260    impl_read_be!(u25, 25);
261    impl_read_be!(u26, 26);
262    impl_read_be!(u27, 27);
263    impl_read_be!(u28, 28);
264    impl_read_be!(u29, 29);
265    impl_read_be!(u30, 30);
266    impl_read_be!(u31, 31);
267    impl_read_be!(u32, 32);
268
269    impl_write_be!(u9, 9);
270    impl_write_be!(u10, 10);
271    impl_write_be!(u11, 11);
272    impl_write_be!(u12, 12);
273    impl_write_be!(u13, 13);
274    impl_write_be!(u14, 14);
275    impl_write_be!(u15, 15);
276    impl_write_be!(u16, 16);
277    impl_write_be!(u17, 17);
278    impl_write_be!(u18, 18);
279    impl_write_be!(u19, 19);
280    impl_write_be!(u20, 20);
281    impl_write_be!(u21, 21);
282    impl_write_be!(u22, 22);
283    impl_write_be!(u23, 23);
284    impl_write_be!(u24, 24);
285    impl_write_be!(u25, 25);
286    impl_write_be!(u26, 26);
287    impl_write_be!(u27, 27);
288    impl_write_be!(u28, 28);
289    impl_write_be!(u29, 29);
290    impl_write_be!(u30, 30);
291    impl_write_be!(u31, 31);
292    impl_write_be!(u32, 32);
293}