Skip to main content

oximedia_bitstream/
integer.rs

1// Copyright 2017 Brian Langenberger
2// Copyright 2024-2026 COOLJAPAN OU (Team Kitasan)
3//
4// Licensed under the Apache License, Version 2.0 or the MIT license,
5// at your option. See the LICENSE-APACHE / LICENSE-MIT files for details.
6
7//! Numeric and integer traits.
8//!
9//! Split out from `lib.rs` during the 0.1.4 refactor so that the crate's
10//! core trait surface (`Primitive`, `Integer`, `VBRInteger`, `Numeric`,
11//! `UnsignedInteger`, `SignedInteger`) and the macros that implement them
12//! for the built-in numeric types live in a single focused file.
13
14#![allow(clippy::unreadable_literal)]
15
16use core::num::NonZero;
17use core::ops::{
18    BitAnd, BitOr, BitOrAssign, BitXor, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
19};
20use core::{fmt::Debug, mem};
21use std::io;
22
23use crate::{BitCount, BitRead, BitWrite};
24
25/// A trait intended for simple fixed-length primitives (such as ints and floats)
26/// which allows them to be read and written to streams of
27/// different endiannesses verbatim.
28pub trait Primitive {
29    /// The raw byte representation of this numeric type
30    type Bytes: AsRef<[u8]> + AsMut<[u8]>;
31
32    /// An empty buffer of this type's size
33    fn buffer() -> Self::Bytes;
34
35    /// Our value in big-endian bytes
36    fn to_be_bytes(self) -> Self::Bytes;
37
38    /// Our value in little-endian bytes
39    fn to_le_bytes(self) -> Self::Bytes;
40
41    /// Convert big-endian bytes to our value
42    fn from_be_bytes(bytes: Self::Bytes) -> Self;
43
44    /// Convert little-endian bytes to our value
45    fn from_le_bytes(bytes: Self::Bytes) -> Self;
46}
47
48macro_rules! define_primitive_numeric {
49    ($t:ty) => {
50        impl Primitive for $t {
51            type Bytes = [u8; mem::size_of::<$t>()];
52
53            #[inline(always)]
54            fn buffer() -> Self::Bytes {
55                [0; mem::size_of::<$t>()]
56            }
57            #[inline(always)]
58            fn to_be_bytes(self) -> Self::Bytes {
59                self.to_be_bytes()
60            }
61            #[inline(always)]
62            fn to_le_bytes(self) -> Self::Bytes {
63                self.to_le_bytes()
64            }
65            #[inline(always)]
66            fn from_be_bytes(bytes: Self::Bytes) -> Self {
67                <$t>::from_be_bytes(bytes)
68            }
69            #[inline(always)]
70            fn from_le_bytes(bytes: Self::Bytes) -> Self {
71                <$t>::from_le_bytes(bytes)
72            }
73        }
74    };
75}
76
77impl<const N: usize> Primitive for [u8; N] {
78    type Bytes = [u8; N];
79
80    #[inline(always)]
81    fn buffer() -> Self::Bytes {
82        [0; N]
83    }
84
85    #[inline(always)]
86    fn to_be_bytes(self) -> Self::Bytes {
87        self
88    }
89
90    #[inline(always)]
91    fn to_le_bytes(self) -> Self::Bytes {
92        self
93    }
94
95    #[inline(always)]
96    fn from_be_bytes(bytes: Self::Bytes) -> Self {
97        bytes
98    }
99
100    #[inline(always)]
101    fn from_le_bytes(bytes: Self::Bytes) -> Self {
102        bytes
103    }
104}
105
106/// This trait is for integer types which can be read or written
107/// to a bit stream as a partial amount of bits.
108///
109/// It unifies signed and unsigned integer types by delegating
110/// reads and writes to the signed and unsigned reading
111/// and writing methods as appropriate.
112pub trait Integer {
113    /// Reads a value of ourself from the stream
114    /// with the given number of bits.
115    ///
116    /// # Errors
117    ///
118    /// Passes along any I/O error from the underlying stream.
119    /// A compile-time error occurs if the given number of bits
120    /// is larger than our type.
121    fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
122    where
123        Self: Sized;
124
125    /// Reads a value of ourself from the stream
126    /// with the given number of bits.
127    ///
128    /// # Errors
129    ///
130    /// Passes along any I/O error from the underlying stream.
131    /// Also returns an error if our type is too small
132    /// to hold the requested number of bits.
133    fn read_var<const MAX: u32, R>(reader: &mut R, bits: BitCount<MAX>) -> io::Result<Self>
134    where
135        R: BitRead + ?Sized,
136        Self: Sized;
137
138    /// Writes ourself to the stream using the given const number of bits.
139    ///
140    /// # Errors
141    ///
142    /// Passes along any I/O error from the underlying stream.
143    /// Returns an error if our value is too large
144    /// to fit the given number of bits.
145    /// A compile-time error occurs if the given number of bits
146    /// is larger than our type.
147    fn write<const BITS: u32, W: BitWrite + ?Sized>(self, writer: &mut W) -> io::Result<()>;
148
149    /// Writes ourself to the stream using the given number of bits.
150    ///
151    /// # Errors
152    ///
153    /// Passes along any I/O error from the underlying stream.
154    /// Returns an error if our value is too small
155    /// to hold the given number of bits.
156    /// Returns an error if our value is too large
157    /// to fit the given number of bits.
158    fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
159        self,
160        writer: &mut W,
161        bits: BitCount<MAX>,
162    ) -> io::Result<()>;
163}
164
165/// This trait is for integer types which can be read or written
166/// to a bit stream as variable-width integers.
167///
168/// It unifies signed and unsigned integer types by delegating
169/// reads and write to the signed and unsigned vbr reading and
170/// writing methods as appropriate.
171pub trait VBRInteger: Integer {
172    /// Reads a value of ourself from the stream using a variable width integer.
173    ///
174    /// # Errors
175    ///
176    /// Passes along any I/O error from the underlying stream.
177    fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
178    where
179        R: BitRead + ?Sized,
180        Self: Sized;
181
182    /// Writes ourself to the stream using a variable width integer.
183    ///
184    /// # Errors
185    ///
186    /// Passes along any I/O error from the underlying stream.
187    fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
188        self,
189        writer: &mut W,
190    ) -> io::Result<()>;
191}
192
193/// Reading and writing booleans as `Integer` requires the number of bits to be 1.
194///
195/// This is more useful when combined with the fixed array target
196/// for reading blocks of bit flags.
197///
198/// # Example
199/// ```
200/// use oximedia_bitstream::{BitReader, BitRead, BigEndian};
201///
202/// #[derive(Debug, PartialEq, Eq)]
203/// struct Flags {
204///     a: bool,
205///     b: bool,
206///     c: bool,
207///     d: bool,
208/// }
209///
210/// let data: &[u8] = &[0b1011_0000];
211/// let mut r = BitReader::endian(data, BigEndian);
212/// // note the number of bits must be 1 per read
213/// // while the quantity of flags is indicated by the array length
214/// let flags = r.read::<1, [bool; 4]>().map(|[a, b, c, d]| Flags { a, b, c, d }).unwrap();
215/// assert_eq!(flags, Flags { a: true, b: false, c: true, d: true });
216/// ```
217impl Integer for bool {
218    #[inline(always)]
219    fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
220    where
221        Self: Sized,
222    {
223        const {
224            assert!(BITS == 1, "booleans require exactly 1 bit");
225        }
226
227        reader.read_bit()
228    }
229
230    fn read_var<const MAX: u32, R>(
231        reader: &mut R,
232        BitCount { bits }: BitCount<MAX>,
233    ) -> io::Result<Self>
234    where
235        R: BitRead + ?Sized,
236        Self: Sized,
237    {
238        if bits == 1 {
239            reader.read_bit()
240        } else {
241            Err(io::Error::new(
242                io::ErrorKind::InvalidInput,
243                "booleans require exactly 1 bit",
244            ))
245        }
246    }
247
248    #[inline(always)]
249    fn write<const BITS: u32, W: BitWrite + ?Sized>(self, writer: &mut W) -> io::Result<()> {
250        const {
251            assert!(BITS == 1, "booleans require exactly 1 bit");
252        }
253
254        writer.write_bit(self)
255    }
256
257    fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
258        self,
259        writer: &mut W,
260        BitCount { bits }: BitCount<MAX>,
261    ) -> io::Result<()> {
262        if bits == 1 {
263            writer.write_bit(self)
264        } else {
265            Err(io::Error::new(
266                io::ErrorKind::InvalidInput,
267                "booleans require exactly 1 bit",
268            ))
269        }
270    }
271}
272
273impl<const SIZE: usize, I: Integer + Copy + Default> Integer for [I; SIZE] {
274    #[inline]
275    fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
276    where
277        Self: Sized,
278    {
279        let mut a = [I::default(); SIZE];
280
281        a.iter_mut().try_for_each(|v| {
282            *v = reader.read::<BITS, I>()?;
283            Ok::<(), io::Error>(())
284        })?;
285
286        Ok(a)
287    }
288
289    #[inline]
290    fn read_var<const MAX: u32, R>(reader: &mut R, count: BitCount<MAX>) -> io::Result<Self>
291    where
292        R: BitRead + ?Sized,
293        Self: Sized,
294    {
295        let mut a = [I::default(); SIZE];
296
297        a.iter_mut().try_for_each(|v| {
298            *v = reader.read_counted(count)?;
299            Ok::<(), io::Error>(())
300        })?;
301
302        Ok(a)
303    }
304
305    #[inline]
306    fn write<const BITS: u32, W: BitWrite + ?Sized>(self, writer: &mut W) -> io::Result<()> {
307        IntoIterator::into_iter(self).try_for_each(|v| writer.write::<BITS, I>(v))
308    }
309
310    #[inline]
311    fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
312        self,
313        writer: &mut W,
314        count: BitCount<MAX>,
315    ) -> io::Result<()> {
316        IntoIterator::into_iter(self).try_for_each(|v| writer.write_counted(count, v))
317    }
318}
319
320impl<const SIZE: usize, I: VBRInteger + Copy + Default> VBRInteger for [I; SIZE] {
321    fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
322    where
323        R: BitRead + ?Sized,
324        Self: Sized,
325    {
326        let mut a = [I::default(); SIZE];
327
328        a.iter_mut().try_for_each(|v| {
329            I::read_vbr::<FIELD_SIZE, R>(reader).map(|item| {
330                *v = item;
331            })
332        })?;
333
334        Ok(a)
335    }
336
337    fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
338        self,
339        writer: &mut W,
340    ) -> io::Result<()> {
341        IntoIterator::into_iter(self).try_for_each(|v| I::write_vbr::<FIELD_SIZE, W>(v, writer))
342    }
343}
344
345/// This trait extends many common integer types (both unsigned and signed)
346/// with a few trivial methods so that they can be used
347/// with the bitstream handling traits.
348pub trait Numeric:
349    Primitive
350    + Sized
351    + Copy
352    + Default
353    + Debug
354    + PartialOrd
355    + Shl<u32, Output = Self>
356    + ShlAssign<u32>
357    + Shr<u32, Output = Self>
358    + ShrAssign<u32>
359    + Rem<Self, Output = Self>
360    + RemAssign<Self>
361    + BitAnd<Self, Output = Self>
362    + BitOr<Self, Output = Self>
363    + BitOrAssign<Self>
364    + BitXor<Self, Output = Self>
365    + Not<Output = Self>
366    + Sub<Self, Output = Self>
367{
368    /// Size of type in bits
369    const BITS_SIZE: u32;
370
371    /// The value of 0 in this type
372    const ZERO: Self;
373
374    /// The value of 1 in this type
375    const ONE: Self;
376
377    /// Returns a `u8` value in this type
378    fn from_u8(u: u8) -> Self;
379
380    /// Assuming 0 <= value < 256, returns this value as a `u8` type
381    fn to_u8(self) -> u8;
382}
383
384macro_rules! define_numeric {
385    ($t:ty) => {
386        define_primitive_numeric!($t);
387
388        impl Numeric for $t {
389            const BITS_SIZE: u32 = mem::size_of::<$t>() as u32 * 8;
390
391            const ZERO: Self = 0;
392
393            const ONE: Self = 1;
394
395            #[inline(always)]
396            fn from_u8(u: u8) -> Self {
397                u as $t
398            }
399            #[inline(always)]
400            fn to_u8(self) -> u8 {
401                self as u8
402            }
403        }
404    };
405}
406
407/// This trait extends many common unsigned integer types
408/// so that they can be used with the bitstream handling traits.
409pub trait UnsignedInteger: Numeric {
410    /// This type's most-significant bit
411    const MSB_BIT: Self;
412
413    /// This type's least significant bit
414    const LSB_BIT: Self;
415
416    /// This type with all bits set
417    const ALL: Self;
418
419    /// The signed variant of ourself
420    type Signed: SignedInteger<Unsigned = Self>;
421
422    /// Given a twos-complement value,
423    /// return this value is a non-negative signed number.
424    /// The location of the sign bit depends on the stream's endianness
425    /// and is not stored in the result.
426    ///
427    /// # Example
428    /// ```
429    /// use oximedia_bitstream::UnsignedInteger;
430    /// assert_eq!(0b00000001u8.as_non_negative(), 1i8);
431    /// ```
432    fn as_non_negative(self) -> Self::Signed;
433
434    /// Given a two-complement positive value and certain number of bits,
435    /// returns this value as a negative signed number.
436    /// The location of the sign bit depends on the stream's endianness
437    /// and is not stored in the result.
438    ///
439    /// # Example
440    /// ```
441    /// use oximedia_bitstream::UnsignedInteger;
442    /// assert_eq!(0b01111111u8.as_negative(8), -1i8);
443    /// ```
444    fn as_negative(self, bits: u32) -> Self::Signed;
445
446    /// Given a two-complement positive value and certain number of bits,
447    /// returns this value as a negative number.
448    ///
449    /// # Example
450    /// ```
451    /// use oximedia_bitstream::UnsignedInteger;
452    /// assert_eq!(0b01111111u8.as_negative_fixed::<8>(), -1i8);
453    /// ```
454    fn as_negative_fixed<const BITS: u32>(self) -> Self::Signed;
455
456    /// Checked shift left
457    fn checked_shl(self, rhs: u32) -> Option<Self>;
458
459    /// Checked shift right
460    fn checked_shr(self, rhs: u32) -> Option<Self>;
461
462    /// Shift left up to our length in bits
463    ///
464    /// If rhs equals our length in bits, returns default
465    fn shl_default(self, rhs: u32) -> Self {
466        self.checked_shl(rhs).unwrap_or(Self::ZERO)
467    }
468
469    /// Shift left up to our length in bits
470    ///
471    /// If rhs equals our length in bits, returns zero
472    fn shr_default(self, rhs: u32) -> Self {
473        self.checked_shr(rhs).unwrap_or(Self::ZERO)
474    }
475}
476
477macro_rules! define_unsigned_integer {
478    ($t:ty, $s:ty) => {
479        define_numeric!($t);
480
481        impl UnsignedInteger for $t {
482            type Signed = $s;
483
484            const MSB_BIT: Self = 1 << (Self::BITS_SIZE - 1);
485
486            const LSB_BIT: Self = 1;
487
488            const ALL: Self = <$t>::MAX;
489
490            #[inline(always)]
491            fn as_non_negative(self) -> Self::Signed {
492                self as $s
493            }
494            #[inline(always)]
495            fn as_negative(self, bits: u32) -> Self::Signed {
496                (self as $s) + (-1 << (bits - 1))
497            }
498            #[inline(always)]
499            fn as_negative_fixed<const BITS: u32>(self) -> Self::Signed {
500                (self as $s) + (-1 << (BITS - 1))
501            }
502            #[inline(always)]
503            fn checked_shl(self, rhs: u32) -> Option<Self> {
504                self.checked_shl(rhs)
505            }
506            #[inline(always)]
507            fn checked_shr(self, rhs: u32) -> Option<Self> {
508                self.checked_shr(rhs)
509            }
510            // TODO - enable these in the future
511            // #[inline(always)]
512            // fn shl_default(self, rhs: u32) -> Self {
513            //     self.unbounded_shl(rhs)
514            // }
515            // #[inline(always)]
516            // fn shr_default(self, rhs: u32) -> Self {
517            //     self.unbounded_shr(rhs)
518            // }
519        }
520
521        impl Integer for $t {
522            #[inline(always)]
523            fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
524            where
525                Self: Sized,
526            {
527                reader.read_unsigned::<BITS, _>()
528            }
529
530            #[inline(always)]
531            fn read_var<const MAX: u32, R>(reader: &mut R, bits: BitCount<MAX>) -> io::Result<Self>
532            where
533                R: BitRead + ?Sized,
534                Self: Sized,
535            {
536                reader.read_unsigned_counted::<MAX, _>(bits)
537            }
538
539            #[inline(always)]
540            fn write<const BITS: u32, W: BitWrite + ?Sized>(
541                self,
542                writer: &mut W,
543            ) -> io::Result<()> {
544                writer.write_unsigned::<BITS, _>(self)
545            }
546
547            #[inline(always)]
548            fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
549                self,
550                writer: &mut W,
551                bits: BitCount<MAX>,
552            ) -> io::Result<()> {
553                writer.write_unsigned_counted(bits, self)
554            }
555        }
556
557        impl VBRInteger for $t {
558            #[inline(always)]
559            fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
560            where
561                R: BitRead + ?Sized,
562                Self: Sized,
563            {
564                reader.read_unsigned_vbr::<FIELD_SIZE, _>()
565            }
566
567            #[inline(always)]
568            fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
569                self,
570                writer: &mut W,
571            ) -> io::Result<()> {
572                writer.write_unsigned_vbr::<FIELD_SIZE, _>(self)
573            }
574        }
575
576        /// Unsigned NonZero types increment their value by 1
577        /// when being read and decrement it by 1
578        /// when being written.
579        ///
580        /// # Examples
581        /// ```
582        /// use oximedia_bitstream::{BitReader, BitRead, BigEndian};
583        /// use core::num::NonZero;
584        ///
585        /// let data: &[u8] = &[0b001_00000];
586        /// // reading a regular u8 in 3 bits yields 1
587        /// assert_eq!(BitReader::endian(data, BigEndian).read::<3, u8>().unwrap(), 1);
588        /// // reading a NonZero<u8> in 3 bits of the same data yields 2
589        /// assert_eq!(BitReader::endian(data, BigEndian).read::<3, NonZero<u8>>().unwrap().get(), 2);
590        /// ```
591        ///
592        /// ```
593        /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
594        /// use core::num::NonZero;
595        ///
596        /// let mut w = BitWriter::endian(vec![], BigEndian);
597        /// // writing 1 as a regular u8 in 3 bits
598        /// w.write::<3, u8>(1).unwrap();
599        /// w.byte_align();
600        /// assert_eq!(w.into_writer(), &[0b001_00000]);
601        ///
602        /// let mut w = BitWriter::endian(vec![], BigEndian);
603        /// // writing 1 as a NonZero<u8> in 3 bits
604        /// w.write::<3, NonZero<u8>>(NonZero::new(1).unwrap()).unwrap();
605        /// w.byte_align();
606        /// assert_eq!(w.into_writer(), &[0b000_00000]);
607        /// ```
608        impl Integer for NonZero<$t> {
609            #[inline]
610            fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
611            where
612                Self: Sized,
613            {
614                const {
615                    assert!(
616                        BITS < <$t>::BITS_SIZE,
617                        "BITS must be less than the type's size in bits"
618                    );
619                }
620
621                <$t as Integer>::read::<BITS, R>(reader).map(|u| {
622                    // `BITS < BITS_SIZE` (enforced by `const { assert! }` above),
623                    // so `u <= 2^BITS - 1 <= T::MAX - 1`, meaning `u + 1` never
624                    // overflows to zero.
625                    NonZero::new(u + 1)
626                        .expect("u + 1 is nonzero: BITS < BITS_SIZE guarantees no overflow")
627                })
628            }
629
630            #[inline]
631            fn read_var<const MAX: u32, R>(
632                reader: &mut R,
633                count @ BitCount { bits }: BitCount<MAX>,
634            ) -> io::Result<Self>
635            where
636                R: BitRead + ?Sized,
637                Self: Sized,
638            {
639                if MAX < <$t>::BITS_SIZE || bits < <$t>::BITS_SIZE {
640                    <$t as Integer>::read_var::<MAX, R>(reader, count).map(|u| {
641                        // `bits < BITS_SIZE` is enforced by the guard above, so
642                        // `u <= 2^bits - 1 <= T::MAX - 1`, meaning `u + 1` never
643                        // overflows to zero.
644                        NonZero::new(u + 1)
645                            .expect("u + 1 is nonzero: bits < BITS_SIZE guarantees no overflow")
646                    })
647                } else {
648                    Err(io::Error::new(
649                        io::ErrorKind::InvalidInput,
650                        "bit count must be less than the type's size in bits",
651                    ))
652                }
653            }
654
655            #[inline]
656            fn write<const BITS: u32, W: BitWrite + ?Sized>(
657                self,
658                writer: &mut W,
659            ) -> io::Result<()> {
660                const {
661                    assert!(
662                        BITS < <$t>::BITS_SIZE,
663                        "BITS must be less than the type's size in bits"
664                    );
665                }
666
667                <$t as Integer>::write::<BITS, W>(self.get() - 1, writer)
668            }
669
670            #[inline]
671            fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
672                self,
673                writer: &mut W,
674                count @ BitCount { bits }: BitCount<MAX>,
675            ) -> io::Result<()> {
676                if MAX < <$t>::BITS_SIZE || bits < <$t>::BITS_SIZE {
677                    <$t as Integer>::write_var::<MAX, W>(self.get() - 1, writer, count)
678                } else {
679                    Err(io::Error::new(
680                        io::ErrorKind::InvalidInput,
681                        "bit count must be less than the type's size in bits",
682                    ))
683                }
684            }
685        }
686
687        impl VBRInteger for NonZero<$t> {
688            #[inline]
689            fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
690            where
691                R: BitRead + ?Sized,
692                Self: Sized,
693            {
694                <$t as VBRInteger>::read_vbr::<FIELD_SIZE, R>(reader).map(|u| {
695                    // VBR groups encode at most `FIELD_SIZE - 1` data bits per chunk,
696                    // so the accumulated value fits within the type and `u + 1`
697                    // never overflows to zero.
698                    NonZero::new(u + 1)
699                        .expect("u + 1 is nonzero: VBR field size bounds prevent overflow")
700                })
701            }
702
703            #[inline]
704            fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
705                self,
706                writer: &mut W,
707            ) -> io::Result<()> {
708                <$t as VBRInteger>::write_vbr::<FIELD_SIZE, W>(self.get() - 1, writer)
709            }
710        }
711
712        impl Integer for Option<NonZero<$t>> {
713            #[inline]
714            fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
715            where
716                Self: Sized,
717            {
718                <$t as Integer>::read::<BITS, R>(reader).map(NonZero::new)
719            }
720
721            #[inline]
722            fn read_var<const MAX: u32, R>(reader: &mut R, count: BitCount<MAX>) -> io::Result<Self>
723            where
724                R: BitRead + ?Sized,
725                Self: Sized,
726            {
727                <$t as Integer>::read_var::<MAX, R>(reader, count).map(NonZero::new)
728            }
729
730            #[inline]
731            fn write<const BITS: u32, W: BitWrite + ?Sized>(
732                self,
733                writer: &mut W,
734            ) -> io::Result<()> {
735                <$t as Integer>::write::<BITS, W>(self.map(|n| n.get()).unwrap_or(0), writer)
736            }
737
738            #[inline]
739            fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
740                self,
741                writer: &mut W,
742                count: BitCount<MAX>,
743            ) -> io::Result<()> {
744                <$t as Integer>::write_var::<MAX, W>(
745                    self.map(|n| n.get()).unwrap_or(0),
746                    writer,
747                    count,
748                )
749            }
750        }
751
752        impl VBRInteger for Option<NonZero<$t>> {
753            #[inline(always)]
754            fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
755            where
756                R: BitRead + ?Sized,
757                Self: Sized,
758            {
759                <$t as VBRInteger>::read_vbr::<FIELD_SIZE, _>(reader).map(NonZero::new)
760            }
761
762            #[inline]
763            fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
764                self,
765                writer: &mut W,
766            ) -> io::Result<()> {
767                <$t as VBRInteger>::write_vbr::<FIELD_SIZE, W>(
768                    self.map(|n| n.get()).unwrap_or(0),
769                    writer,
770                )
771            }
772        }
773    };
774}
775
776/// This trait extends many common signed integer types
777/// so that they can be used with the bitstream handling traits.
778///
779/// This trait was formerly named `SignedNumeric` in 2.X.X code.
780/// If backwards-compatibility is needed one can
781/// import `SignedInteger` as `SignedNumeric`.
782pub trait SignedInteger: Numeric {
783    /// The unsigned variant of ourself
784    type Unsigned: UnsignedInteger<Signed = Self>;
785
786    /// Returns true if this value is negative
787    ///
788    /// # Example
789    /// ```
790    /// use oximedia_bitstream::SignedInteger;
791    /// assert!(!1i8.is_negative());
792    /// assert!((-1i8).is_negative());
793    /// ```
794    fn is_negative(self) -> bool;
795
796    /// Returns ourself as a non-negative value.
797    /// The location of the sign bit depends on the stream's endianness
798    /// and is not stored in the result.
799    ///
800    /// # Example
801    /// ```
802    /// use oximedia_bitstream::SignedInteger;
803    /// assert_eq!(1i8.as_non_negative(), 0b00000001u8);
804    /// ```
805    fn as_non_negative(self) -> Self::Unsigned;
806
807    /// Given a negative value and a certain number of bits,
808    /// returns this value as a twos-complement positive number.
809    /// The location of the sign bit depends on the stream's endianness
810    /// and is not stored in the result.
811    ///
812    /// # Example
813    /// ```
814    /// use oximedia_bitstream::SignedInteger;
815    /// assert_eq!((-1i8).as_negative(8), 0b01111111u8);
816    /// ```
817    fn as_negative(self, bits: u32) -> Self::Unsigned;
818
819    /// Given a negative value and a certain number of bits,
820    /// returns this value as a twos-complement positive number.
821    ///
822    /// # Example
823    /// ```
824    /// use oximedia_bitstream::SignedInteger;
825    /// assert_eq!((-1i8).as_negative_fixed::<8>(), 0b01111111u8);
826    /// ```
827    fn as_negative_fixed<const BITS: u32>(self) -> Self::Unsigned;
828}
829
830macro_rules! define_signed_integer {
831    ($t:ty, $u:ty) => {
832        define_numeric!($t);
833
834        impl SignedInteger for $t {
835            type Unsigned = $u;
836
837            #[inline(always)]
838            fn is_negative(self) -> bool {
839                self.is_negative()
840            }
841            fn as_non_negative(self) -> Self::Unsigned {
842                self as $u
843            }
844            fn as_negative(self, bits: u32) -> Self::Unsigned {
845                (self - (-1 << (bits - 1))) as $u
846            }
847            fn as_negative_fixed<const BITS: u32>(self) -> Self::Unsigned {
848                (self - (-1 << (BITS - 1))) as $u
849            }
850        }
851
852        impl Integer for $t {
853            #[inline(always)]
854            fn read<const BITS: u32, R: BitRead + ?Sized>(reader: &mut R) -> io::Result<Self>
855            where
856                Self: Sized,
857            {
858                reader.read_signed::<BITS, _>()
859            }
860
861            #[inline(always)]
862            fn read_var<const MAX: u32, R>(reader: &mut R, bits: BitCount<MAX>) -> io::Result<Self>
863            where
864                R: BitRead + ?Sized,
865                Self: Sized,
866            {
867                reader.read_signed_counted::<MAX, _>(bits)
868            }
869
870            #[inline(always)]
871            fn write<const BITS: u32, W: BitWrite + ?Sized>(
872                self,
873                writer: &mut W,
874            ) -> io::Result<()> {
875                writer.write_signed::<BITS, _>(self)
876            }
877
878            #[inline(always)]
879            fn write_var<const MAX: u32, W: BitWrite + ?Sized>(
880                self,
881                writer: &mut W,
882                bits: BitCount<MAX>,
883            ) -> io::Result<()> {
884                writer.write_signed_counted::<MAX, _>(bits, self)
885            }
886        }
887
888        impl VBRInteger for $t {
889            #[inline(always)]
890            fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
891            where
892                R: BitRead + ?Sized,
893                Self: Sized,
894            {
895                reader.read_signed_vbr::<FIELD_SIZE, _>()
896            }
897
898            #[inline(always)]
899            fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
900                self,
901                writer: &mut W,
902            ) -> io::Result<()> {
903                writer.write_signed_vbr::<FIELD_SIZE, _>(self)
904            }
905        }
906    };
907}
908
909define_unsigned_integer!(u8, i8);
910define_unsigned_integer!(u16, i16);
911define_unsigned_integer!(u32, i32);
912define_unsigned_integer!(u64, i64);
913define_unsigned_integer!(u128, i128);
914
915define_signed_integer!(i8, u8);
916define_signed_integer!(i16, u16);
917define_signed_integer!(i32, u32);
918define_signed_integer!(i64, u64);
919define_signed_integer!(i128, u128);
920
921define_primitive_numeric!(f32);
922define_primitive_numeric!(f64);