1pub trait Endianness: Clone {
13 fn i8_to_bytes(sample: i8) -> [u8; 1];
15
16 fn i16_to_bytes(sample: i16) -> [u8; 2];
18
19 fn i24_to_bytes(sample: i32) -> [u8; 3];
21
22 fn i32_to_bytes(sample: i32) -> [u8; 4];
24
25 fn bytes_to_i8(bytes: [u8; 1]) -> i8;
27
28 fn bytes_to_i16(bytes: [u8; 2]) -> i16;
30
31 fn bytes_to_i24(bytes: [u8; 3]) -> i32;
33
34 fn bytes_to_i32(bytes: [u8; 4]) -> i32;
36
37 fn bytes_to_be(buf: &mut [u8], bytes_per_sample: usize);
39
40 fn bytes_to_le(buf: &mut [u8], bytes_per_sample: usize);
42}
43
44#[derive(Copy, Clone)]
46pub struct LittleEndian;
47
48impl Endianness for LittleEndian {
49 #[inline]
50 fn i8_to_bytes(sample: i8) -> [u8; 1] {
51 sample.to_le_bytes()
52 }
53
54 #[inline]
55 fn i16_to_bytes(sample: i16) -> [u8; 2] {
56 sample.to_le_bytes()
57 }
58
59 #[inline]
60 fn i24_to_bytes(sample: i32) -> [u8; 3] {
61 let unsigned: u32 = if sample >= 0 {
62 sample as u32
63 } else {
64 0x800000 | ((sample - (-1 << 23)) as u32)
65 };
66
67 [
68 (unsigned & 0xFF) as u8,
69 ((unsigned & 0xFF00) >> 8) as u8,
70 (unsigned >> 16) as u8,
71 ]
72 }
73
74 #[inline]
75 fn i32_to_bytes(sample: i32) -> [u8; 4] {
76 sample.to_le_bytes()
77 }
78
79 #[inline]
80 fn bytes_to_i8(bytes: [u8; 1]) -> i8 {
81 i8::from_le_bytes(bytes)
82 }
83
84 #[inline]
85 fn bytes_to_i16(bytes: [u8; 2]) -> i16 {
86 i16::from_le_bytes(bytes)
87 }
88
89 #[inline]
90 fn bytes_to_i24(bytes: [u8; 3]) -> i32 {
91 let unsigned = ((bytes[2] as u32) << 16) | ((bytes[1] as u32) << 8) | bytes[0] as u32;
92
93 if unsigned & 0x800000 == 0 {
94 unsigned as i32
95 } else {
96 (unsigned & 0x7FFFFF) as i32 + (-1 << 23)
97 }
98 }
99
100 #[inline]
101 fn bytes_to_i32(bytes: [u8; 4]) -> i32 {
102 i32::from_le_bytes(bytes)
103 }
104
105 fn bytes_to_be(buf: &mut [u8], bytes_per_sample: usize) {
106 for chunk in buf.chunks_exact_mut(bytes_per_sample) {
107 chunk.reverse();
108 }
109 }
110
111 fn bytes_to_le(_buf: &mut [u8], _bytes_per_sample: usize) {
112 }
114}
115
116#[derive(Copy, Clone)]
118pub struct BigEndian;
119
120impl Endianness for BigEndian {
121 #[inline]
122 fn i8_to_bytes(sample: i8) -> [u8; 1] {
123 sample.to_be_bytes()
124 }
125
126 #[inline]
127 fn i16_to_bytes(sample: i16) -> [u8; 2] {
128 sample.to_be_bytes()
129 }
130
131 #[inline]
132 fn i24_to_bytes(sample: i32) -> [u8; 3] {
133 let unsigned: u32 = if sample >= 0 {
134 sample as u32
135 } else {
136 0x800000 | ((sample - (-1 << 23)) as u32)
137 };
138
139 [
140 (unsigned >> 16) as u8,
141 ((unsigned & 0xFF00) >> 8) as u8,
142 (unsigned & 0xFF) as u8,
143 ]
144 }
145
146 #[inline]
147 fn i32_to_bytes(sample: i32) -> [u8; 4] {
148 sample.to_be_bytes()
149 }
150
151 #[inline]
152 fn bytes_to_i8(bytes: [u8; 1]) -> i8 {
153 i8::from_be_bytes(bytes)
154 }
155
156 #[inline]
157 fn bytes_to_i16(bytes: [u8; 2]) -> i16 {
158 i16::from_be_bytes(bytes)
159 }
160
161 #[inline]
162 fn bytes_to_i24(bytes: [u8; 3]) -> i32 {
163 let unsigned = ((bytes[0] as u32) << 16) | ((bytes[1] as u32) << 8) | bytes[2] as u32;
164
165 if unsigned & 0x800000 == 0 {
166 unsigned as i32
167 } else {
168 (unsigned & 0x7FFFFF) as i32 + (-1 << 23)
169 }
170 }
171
172 #[inline]
173 fn bytes_to_i32(bytes: [u8; 4]) -> i32 {
174 i32::from_be_bytes(bytes)
175 }
176
177 fn bytes_to_be(_buf: &mut [u8], _bytes_per_sample: usize) {
178 }
180
181 fn bytes_to_le(buf: &mut [u8], bytes_per_sample: usize) {
182 for chunk in buf.chunks_exact_mut(bytes_per_sample) {
183 chunk.reverse();
184 }
185 }
186}
187
188#[allow(unused)]
189fn test_endianness<F: bitstream_io::Endianness, E: Endianness>() {
190 use bitstream_io::{BitWrite, BitWriter};
191
192 for i in i8::MIN..=i8::MAX {
194 let mut buf1 = [0; 1];
195 let mut w: BitWriter<_, F> = BitWriter::new(buf1.as_mut_slice());
196 w.write::<8, i8>(i).unwrap();
197
198 let buf2 = E::i8_to_bytes(i);
199
200 assert_eq!(buf1, buf2);
201
202 let j = E::bytes_to_i8(buf2);
203 assert_eq!(i, j);
204 }
205
206 for i in i16::MIN..=i16::MAX {
208 let mut buf1 = [0; 2];
209 let mut w: BitWriter<_, F> = BitWriter::new(buf1.as_mut_slice());
210 w.write::<16, i16>(i).unwrap();
211
212 let buf2 = E::i16_to_bytes(i);
213
214 assert_eq!(buf1, buf2);
215
216 let j = E::bytes_to_i16(buf2);
217 assert_eq!(i, j);
218 }
219
220 for i in (-1 << 23)..=((1 << 23) - 1) {
222 let mut buf1 = [0; 3];
223 let mut w: BitWriter<_, F> = BitWriter::new(buf1.as_mut_slice());
224 w.write::<24, i32>(i).unwrap();
225
226 let buf2 = E::i24_to_bytes(i);
227
228 assert_eq!(buf1, buf2);
229
230 let j = E::bytes_to_i24(buf2);
231 assert_eq!(i, j);
232 }
233}
234
235#[test]
236fn test_samples_le() {
237 test_endianness::<bitstream_io::LittleEndian, LittleEndian>()
238}
239
240#[test]
241fn test_samples_be() {
242 test_endianness::<bitstream_io::BigEndian, BigEndian>()
243}