bits_io/buf/
byte_order.rs1use bitvec::field::BitField;
2use funty::Integral;
3
4use crate::prelude::*;
5
6pub trait ByteOrder {
10 fn load<O: BitStore, U: Integral>(src: &BitSlice<O>) -> U;
11 fn load_u16(src: &[u8]) -> u16;
12 fn load_u24(src: &[u8]) -> u24;
13 fn load_u32(src: &[u8]) -> u32;
14
15 fn store<O: BitStore, U: Integral>(dest: &mut BitSlice<O>, value: U);
16 fn store_u16(dest: &mut [u8], value: u16);
17 fn store_u24(dest: &mut [u8], value: u24);
18 fn store_u32(dest: &mut [u8], value: u32);
19}
20
21pub struct BigEndian {}
22
23pub struct LittleEndian {}
24
25pub type NetworkOrder = BigEndian;
26
27impl ByteOrder for BigEndian {
28 fn load<O: BitStore, U: Integral>(src: &BitSlice<O>) -> U {
29 src.load_be()
30 }
31
32 fn load_u16(src: &[u8]) -> u16 {
33 u16::from_be_bytes(src.try_into().unwrap())
34 }
35
36 fn load_u24(src: &[u8]) -> u24 {
37 let mut value = 0u32;
38 value |= src[0] as u32;
39 value <<= 8;
40 value |= src[1] as u32;
41 value <<= 8;
42 value |= src[2] as u32;
43
44 u24::new(value)
45 }
46
47 fn load_u32(src: &[u8]) -> u32 {
48 u32::from_be_bytes(src.try_into().unwrap())
49 }
50
51 fn store<O: BitStore, U: Integral>(dest: &mut BitSlice<O>, value: U) {
52 dest.store_be(value);
53 }
54
55 fn store_u16(dest: &mut [u8], value: u16) {
56 dest[0] = (value >> 8) as u8;
57 dest[1] = value as u8;
58 }
59
60 fn store_u24(dest: &mut [u8], value: u24) {
61 let value: u32 = value.into();
62 dest[0] = (value >> 16) as u8;
63 dest[1] = (value >> 8) as u8;
64 dest[2] = value as u8;
65 }
66
67 fn store_u32(dest: &mut [u8], value: u32) {
68 dest[0] = (value >> 24) as u8;
69 dest[1] = (value >> 16) as u8;
70 dest[2] = (value >> 8) as u8;
71 dest[3] = value as u8;
72 }
73}
74
75impl ByteOrder for LittleEndian {
76 fn load<O: BitStore, U: Integral>(src: &BitSlice<O>) -> U {
77 src.load_le()
78 }
79
80 fn load_u16(src: &[u8]) -> u16 {
81 u16::from_le_bytes(src.try_into().unwrap())
82 }
83
84 fn load_u24(src: &[u8]) -> u24 {
85 let mut value = 0u32;
86 value |= src[2] as u32;
87 value <<= 8;
88 value |= src[1] as u32;
89 value <<= 8;
90 value |= src[0] as u32;
91 u24::new(value)
92 }
93
94 fn load_u32(src: &[u8]) -> u32 {
95 u32::from_le_bytes(src.try_into().unwrap())
96 }
97
98 fn store<O: BitStore, U: Integral>(dest: &mut BitSlice<O>, value: U) {
99 dest.store_le(value)
100 }
101
102 fn store_u16(dest: &mut [u8], value: u16) {
103 dest[0] = value as u8;
104 dest[1] = (value >> 8) as u8;
105 }
106
107 fn store_u24(dest: &mut [u8], value: u24) {
108 let value: u32 = value.into();
109 dest[0] = value as u8;
110 dest[1] = (value >> 8) as u8;
111 dest[2] = (value >> 16) as u8;
112 }
113
114 fn store_u32(dest: &mut [u8], value: u32) {
115 dest[0] = value as u8;
116 dest[1] = (value >> 8) as u8;
117 dest[2] = (value >> 16) as u8;
118 dest[3] = (value >> 24) as u8;
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
129 fn test_big_endian_write() {
130 let mut buf = [0u8; 2];
131 {
132 let dest = &mut BitSlice::from_slice_mut(&mut buf);
134 BigEndian::store(&mut dest[..16], 0xABCDu16);
135 let value = u16::from_be_bytes(buf);
136 assert_eq!(value, 0xABCD);
137 }
138
139 {
141 let dest = BitSlice::from_slice_mut(&mut buf);
142 let (_, dest) = unsafe { dest.split_at_unchecked_mut(0) };
143 BigEndian::store(&mut dest[..16], 0xABCDu16);
144 let value = u16::from_be_bytes(buf);
145 assert_eq!(value, 0xABCD);
146 }
147 }
148
149 #[test]
150 fn test_big_endian_read() {
151 let value = 0xABCDu16;
152 let value_bytes = value.to_be_bytes();
153 let src = BitSlice::from_slice(&value_bytes);
154 let read_value: u16 = BigEndian::load(src);
155 assert_eq!(value, read_value);
156 }
157
158 #[test]
159 fn test_little_endian_write() {
160 let mut buf = [0u8; 2];
161 {
162 let dest = &mut BitSlice::from_slice_mut(&mut buf);
164 LittleEndian::store(&mut dest[..16], 0xABCDu16);
165 let value = u16::from_le_bytes(buf);
166 assert_eq!(value, 0xABCD);
167 }
168
169 {
171 let dest = BitSlice::from_slice_mut(&mut buf);
172 let (_, dest) = unsafe { dest.split_at_unchecked_mut(0) };
173 LittleEndian::store(&mut dest[..16], 0xABCDu16);
174 let value = u16::from_le_bytes(buf);
175 assert_eq!(value, 0xABCD);
176 }
177 }
178
179 #[test]
180 fn test_little_endian_read() {
181 let value = 0xABCDu16;
182 let value_bytes = value.to_le_bytes();
183 let src = BitSlice::from_slice(&value_bytes);
184 let read_value: u16 = LittleEndian::load(src);
185 assert_eq!(value, read_value);
186 }
187}