1use core::mem;
12use std::io;
13
14use crate::endian::{find_unary, read_byte, write_byte};
15use crate::{
16 private, BitCount, BitRead, BitWrite, Checked, CheckedSigned, CheckedUnsigned, Endianness,
17 Numeric, Primitive, SignedBitCount, SignedInteger, UnsignedInteger,
18};
19
20#[derive(Copy, Clone, Debug)]
22pub struct LittleEndian;
23
24pub type LE = LittleEndian;
26
27impl LittleEndian {
28 #[inline]
32 fn read_bits_checked<const MAX: u32, R, U>(
33 reader: &mut R,
34 queue: &mut u8,
35 queue_bits: &mut u32,
36 BitCount { bits }: BitCount<MAX>,
37 ) -> io::Result<U>
38 where
39 R: io::Read,
40 U: UnsignedInteger,
41 {
42 #[inline(always)]
46 fn read_bytes<R, U>(reader: &mut R, bytes: usize) -> io::Result<U>
47 where
48 R: io::Read,
49 U: UnsignedInteger,
50 {
51 let mut buf = U::buffer();
52 reader
53 .read_exact(&mut buf.as_mut()[0..bytes])
54 .map(|()| U::from_le_bytes(buf))
55 }
56
57 if bits <= *queue_bits {
58 let value = *queue & u8::ALL.shr_default(u8::BITS_SIZE - bits);
60 *queue = queue.shr_default(bits);
61 *queue_bits -= bits;
62 Ok(U::from_u8(value))
63 } else {
64 let needed_bits = bits - *queue_bits;
68
69 match (needed_bits / 8, needed_bits % 8) {
70 (0, needed) => {
71 let next_byte = read_byte(reader)?;
75
76 Ok(
77 U::from_u8(mem::replace(queue, next_byte.shr_default(needed)))
78 | (U::from_u8(next_byte & (u8::ALL >> (u8::BITS_SIZE - needed)))
79 << mem::replace(queue_bits, u8::BITS_SIZE - needed)),
80 )
81 }
82 (bytes, 0) => {
83 Ok(U::from_u8(mem::take(queue))
90 | (read_bytes::<R, U>(reader, bytes as usize)? << mem::take(queue_bits)))
91 }
92 (bytes, needed) => {
93 let whole: U = read_bytes(reader, bytes as usize)?;
99 let next_byte = read_byte(reader)?;
100
101 Ok(
102 U::from_u8(mem::replace(queue, next_byte.shr_default(needed)))
103 | (whole << *queue_bits)
104 | (U::from_u8(next_byte & (u8::ALL >> (u8::BITS_SIZE - needed)))
105 << (mem::replace(queue_bits, u8::BITS_SIZE - needed) + bytes * 8)),
106 )
107 }
108 }
109 }
110 }
111}
112
113impl Endianness for LittleEndian {}
114
115impl private::Endianness for LittleEndian {
116 #[inline]
117 fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option<u8> {
118 *queue_value |= u8::from(bit) << *queue_bits;
119 *queue_bits = (*queue_bits + 1) % 8;
120 (*queue_bits == 0).then(|| mem::take(queue_value))
121 }
122
123 #[inline]
124 fn read_bits<const MAX: u32, R, U>(
125 reader: &mut R,
126 queue_value: &mut u8,
127 queue_bits: &mut u32,
128 count @ BitCount { bits }: BitCount<MAX>,
129 ) -> io::Result<U>
130 where
131 R: io::Read,
132 U: UnsignedInteger,
133 {
134 if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE {
135 Self::read_bits_checked::<MAX, R, U>(reader, queue_value, queue_bits, count)
136 } else {
137 Err(io::Error::new(
138 io::ErrorKind::InvalidInput,
139 "excessive bits for type read",
140 ))
141 }
142 }
143
144 #[inline]
145 fn read_bits_fixed<const BITS: u32, R, U>(
146 reader: &mut R,
147 queue_value: &mut u8,
148 queue_bits: &mut u32,
149 ) -> io::Result<U>
150 where
151 R: io::Read,
152 U: UnsignedInteger,
153 {
154 const {
155 assert!(BITS <= U::BITS_SIZE, "excessive bits for type read");
156 }
157
158 Self::read_bits_checked::<BITS, R, U>(
159 reader,
160 queue_value,
161 queue_bits,
162 BitCount::new::<BITS>(),
163 )
164 }
165
166 #[inline]
171 fn write_bits_checked<const MAX: u32, W, U>(
172 writer: &mut W,
173 queue_value: &mut u8,
174 queue_bits: &mut u32,
175 CheckedUnsigned {
176 count: BitCount { bits },
177 value,
178 }: CheckedUnsigned<MAX, U>,
179 ) -> io::Result<()>
180 where
181 W: io::Write,
182 U: UnsignedInteger,
183 {
184 fn write_bytes<W, U>(writer: &mut W, bytes: usize, value: U) -> io::Result<()>
185 where
186 W: io::Write,
187 U: UnsignedInteger,
188 {
189 let buf = U::to_le_bytes(value);
190 writer.write_all(&buf.as_ref()[0..bytes])
191 }
192
193 let available_bits = u8::BITS_SIZE - *queue_bits;
195
196 if bits < available_bits {
197 *queue_value |= U::to_u8(value.shl_default(*queue_bits));
199 *queue_bits += bits;
200 Ok(())
201 } else {
202 let excess_bits = bits - available_bits;
206
207 match (excess_bits / 8, excess_bits % 8) {
208 (0, excess) => {
209 write_byte(
214 writer,
215 mem::replace(queue_value, U::to_u8(value.shr_default(available_bits)))
216 | U::to_u8(
217 (value << mem::replace(queue_bits, excess)) & U::from_u8(u8::ALL),
218 ),
219 )
220 }
221 (bytes, 0) => {
222 write_byte(
227 writer.by_ref(),
228 mem::take(queue_value)
229 | U::to_u8((value << mem::take(queue_bits)) & U::from_u8(u8::ALL)),
230 )?;
231
232 write_bytes(writer, bytes as usize, value >> available_bits)
233 }
234 (bytes, excess) => {
235 write_byte(
242 writer.by_ref(),
243 mem::replace(
244 queue_value,
245 U::to_u8(value.shr_default(available_bits + bytes * 8)),
246 ) | U::to_u8(
247 (value << mem::replace(queue_bits, excess)) & U::from_u8(u8::ALL),
248 ),
249 )?;
250
251 write_bytes(writer, bytes as usize, value >> available_bits)
252 }
253 }
254 }
255 }
256
257 fn write_signed_bits_checked<const MAX: u32, W, S>(
258 writer: &mut W,
259 queue_value: &mut u8,
260 queue_bits: &mut u32,
261 value: CheckedSigned<MAX, S>,
262 ) -> io::Result<()>
263 where
264 W: io::Write,
265 S: SignedInteger,
266 {
267 let (
269 SignedBitCount {
270 bits: BitCount { bits },
271 unsigned,
272 },
273 value,
274 ) = value.into_count_value();
275
276 Self::write_bits_checked(
277 writer.by_ref(),
278 queue_value,
279 queue_bits,
280 Checked {
281 value: if value.is_negative() {
282 value.as_negative(bits)
283 } else {
284 value.as_non_negative()
285 },
286 count: unsigned,
287 },
288 )?;
289 match Self::push_bit_flush(queue_value, queue_bits, value.is_negative()) {
290 Some(b) => write_byte(writer, b),
291 None => Ok(()),
292 }
293 }
294
295 #[inline]
296 fn pop_bit_refill<R>(
297 reader: &mut R,
298 queue_value: &mut u8,
299 queue_bits: &mut u32,
300 ) -> io::Result<bool>
301 where
302 R: io::Read,
303 {
304 Ok(if *queue_bits == 0 {
305 let value = read_byte(reader)?;
306 let lsb = value & u8::LSB_BIT;
307 *queue_value = value >> 1;
308 *queue_bits = u8::BITS_SIZE - 1;
309 lsb
310 } else {
311 let lsb = *queue_value & u8::LSB_BIT;
312 *queue_value >>= 1;
313 *queue_bits -= 1;
314 lsb
315 } != 0)
316 }
317
318 #[inline]
319 fn pop_unary<const STOP_BIT: u8, R>(
320 reader: &mut R,
321 queue_value: &mut u8,
322 queue_bits: &mut u32,
323 ) -> io::Result<u32>
324 where
325 R: io::Read,
326 {
327 const {
328 assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1");
329 }
330
331 match STOP_BIT {
332 0 => find_unary(
333 reader,
334 queue_value,
335 queue_bits,
336 |v| v.trailing_ones(),
337 |q| *q,
338 |v, b| v.checked_shr(b),
339 ),
340 1 => find_unary(
341 reader,
342 queue_value,
343 queue_bits,
344 |v| v.trailing_zeros(),
345 |_| u8::BITS_SIZE,
346 |v, b| v.checked_shr(b),
347 ),
348 _ => unreachable!(),
349 }
350 }
351
352 #[inline]
353 fn read_signed_counted<const MAX: u32, R, S>(
354 r: &mut R,
355 SignedBitCount {
356 bits: BitCount { bits },
357 unsigned,
358 }: SignedBitCount<MAX>,
359 ) -> io::Result<S>
360 where
361 R: BitRead,
362 S: SignedInteger,
363 {
364 if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE {
365 let unsigned = r.read_unsigned_counted::<MAX, S::Unsigned>(unsigned)?;
366 let is_negative = r.read_bit()?;
367 Ok(if is_negative {
368 unsigned.as_negative(bits)
369 } else {
370 unsigned.as_non_negative()
371 })
372 } else {
373 Err(io::Error::new(
374 io::ErrorKind::InvalidInput,
375 "excessive bits for type read",
376 ))
377 }
378 }
379
380 fn read_bytes<const CHUNK_SIZE: usize, R>(
381 reader: &mut R,
382 queue_value: &mut u8,
383 queue_bits: u32,
384 buf: &mut [u8],
385 ) -> io::Result<()>
386 where
387 R: io::Read,
388 {
389 if queue_bits == 0 {
390 reader.read_exact(buf)
391 } else {
392 let mut input_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE];
393
394 for output_chunk in buf.chunks_mut(CHUNK_SIZE) {
395 let input_chunk = &mut input_chunk[0..output_chunk.len()];
396 reader.read_exact(input_chunk)?;
397
398 output_chunk
399 .iter_mut()
400 .zip(input_chunk.iter())
401 .for_each(|(o, i)| {
402 *o = i << queue_bits;
403 });
404
405 output_chunk[1..]
406 .iter_mut()
407 .zip(input_chunk.iter())
408 .for_each(|(o, i)| {
409 *o |= i >> (u8::BITS_SIZE - queue_bits);
410 });
411
412 let last_byte = *input_chunk
415 .last()
416 .unwrap_or_else(|| unreachable!("chunks_mut never yields empty slices"));
417 output_chunk[0] |=
418 mem::replace(queue_value, last_byte >> (u8::BITS_SIZE - queue_bits));
419 }
420
421 Ok(())
422 }
423 }
424
425 fn write_bytes<const CHUNK_SIZE: usize, W>(
426 writer: &mut W,
427 queue_value: &mut u8,
428 queue_bits: u32,
429 buf: &[u8],
430 ) -> io::Result<()>
431 where
432 W: io::Write,
433 {
434 if queue_bits == 0 {
435 writer.write_all(buf)
436 } else {
437 let mut output_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE];
438
439 for input_chunk in buf.chunks(CHUNK_SIZE) {
440 let output_chunk = &mut output_chunk[0..input_chunk.len()];
441
442 output_chunk
443 .iter_mut()
444 .zip(input_chunk.iter())
445 .for_each(|(o, i)| {
446 *o = i << queue_bits;
447 });
448
449 output_chunk[1..]
450 .iter_mut()
451 .zip(input_chunk.iter())
452 .for_each(|(o, i)| {
453 *o |= i >> (u8::BITS_SIZE - queue_bits);
454 });
455
456 let last_byte = *input_chunk
459 .last()
460 .unwrap_or_else(|| unreachable!("chunks never yields empty slices"));
461 output_chunk[0] |=
462 mem::replace(queue_value, last_byte >> (u8::BITS_SIZE - queue_bits));
463
464 writer.write_all(output_chunk)?;
465 }
466
467 Ok(())
468 }
469 }
470
471 #[inline(always)]
472 fn bytes_to_primitive<P: Primitive>(buf: P::Bytes) -> P {
473 P::from_le_bytes(buf)
474 }
475
476 #[inline(always)]
477 fn primitive_to_bytes<P: Primitive>(p: P) -> P::Bytes {
478 p.to_le_bytes()
479 }
480
481 #[inline]
482 fn read_primitive<R, V>(r: &mut R) -> io::Result<V>
483 where
484 R: BitRead,
485 V: Primitive,
486 {
487 let mut buffer = V::buffer();
488 r.read_bytes(buffer.as_mut())?;
489 Ok(V::from_le_bytes(buffer))
490 }
491
492 #[inline]
493 fn write_primitive<W, V>(w: &mut W, value: V) -> io::Result<()>
494 where
495 W: BitWrite,
496 V: Primitive,
497 {
498 w.write_bytes(value.to_le_bytes().as_ref())
499 }
500}