Skip to main content

bitstream/
error.rs

1//! Error types for bitstream operations.
2
3use std::fmt;
4
5/// Result type for bitstream operations.
6pub type BitResult<T> = Result<T, BitError>;
7
8/// Errors that can occur during bit-level encoding/decoding.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum BitError {
11    /// Attempted to read past the end of the buffer.
12    UnexpectedEof {
13        /// Number of bits requested.
14        requested: usize,
15        /// Number of bits available.
16        available: usize,
17    },
18
19    /// Attempted to write more bits than the buffer can hold.
20    WriteOverflow {
21        /// Number of bits attempted to write.
22        attempted: usize,
23        /// Number of bits available.
24        available: usize,
25    },
26
27    /// Invalid bit count for the operation.
28    InvalidBitCount {
29        /// The invalid bit count provided.
30        bits: u8,
31        /// Maximum allowed bits for this operation.
32        max_bits: u8,
33    },
34
35    /// Value exceeds the range representable by the specified number of bits.
36    ValueOutOfRange {
37        /// The value that was out of range.
38        value: u64,
39        /// Number of bits available.
40        bits: u8,
41    },
42
43    /// Invalid varint encoding (too many bytes or overflow).
44    InvalidVarint,
45
46    /// Attempted to read or write a byte-aligned value when not aligned.
47    MisalignedAccess {
48        /// Current bit position.
49        bit_position: usize,
50    },
51}
52
53impl fmt::Display for BitError {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        match self {
56            Self::UnexpectedEof {
57                requested,
58                available,
59            } => {
60                write!(
61                    f,
62                    "unexpected EOF: requested {requested} bits, {available} available"
63                )
64            }
65            Self::WriteOverflow {
66                attempted,
67                available,
68            } => {
69                write!(
70                    f,
71                    "write overflow: attempted {attempted} bits, {available} available"
72                )
73            }
74            Self::InvalidBitCount { bits, max_bits } => {
75                write!(f, "invalid bit count {bits}, maximum allowed is {max_bits}")
76            }
77            Self::ValueOutOfRange { value, bits } => {
78                write!(f, "value {value} cannot be represented in {bits} bits")
79            }
80            Self::InvalidVarint => {
81                write!(f, "invalid varint encoding")
82            }
83            Self::MisalignedAccess { bit_position } => {
84                write!(f, "misaligned access at bit position {bit_position}")
85            }
86        }
87    }
88}
89
90impl std::error::Error for BitError {}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn error_display_unexpected_eof() {
98        let err = BitError::UnexpectedEof {
99            requested: 8,
100            available: 3,
101        };
102        let msg = err.to_string();
103        assert!(msg.contains("8"), "should mention requested bits");
104        assert!(msg.contains("3"), "should mention available bits");
105        assert!(msg.contains("EOF"), "should mention EOF");
106    }
107
108    #[test]
109    fn error_display_write_overflow() {
110        let err = BitError::WriteOverflow {
111            attempted: 100,
112            available: 64,
113        };
114        let msg = err.to_string();
115        assert!(msg.contains("100"), "should mention attempted bits");
116        assert!(msg.contains("64"), "should mention available bits");
117        assert!(msg.contains("overflow"), "should mention overflow");
118    }
119
120    #[test]
121    fn error_display_invalid_bit_count() {
122        let err = BitError::InvalidBitCount {
123            bits: 128,
124            max_bits: 64,
125        };
126        let msg = err.to_string();
127        assert!(msg.contains("128"), "should mention invalid count");
128        assert!(msg.contains("64"), "should mention maximum");
129    }
130
131    #[test]
132    fn error_display_value_out_of_range() {
133        let err = BitError::ValueOutOfRange {
134            value: 256,
135            bits: 8,
136        };
137        let msg = err.to_string();
138        assert!(msg.contains("256"), "should mention the value");
139        assert!(msg.contains("8"), "should mention bit count");
140    }
141
142    #[test]
143    fn error_display_invalid_varint() {
144        let err = BitError::InvalidVarint;
145        assert!(err.to_string().contains("varint"));
146    }
147
148    #[test]
149    fn error_display_misaligned_access() {
150        let err = BitError::MisalignedAccess { bit_position: 3 };
151        let msg = err.to_string();
152        assert!(msg.contains("3"), "should mention bit position");
153        assert!(msg.contains("misaligned"));
154    }
155
156    #[test]
157    fn error_equality() {
158        let err1 = BitError::UnexpectedEof {
159            requested: 8,
160            available: 3,
161        };
162        let err2 = BitError::UnexpectedEof {
163            requested: 8,
164            available: 3,
165        };
166        let err3 = BitError::UnexpectedEof {
167            requested: 8,
168            available: 4,
169        };
170        assert_eq!(err1, err2);
171        assert_ne!(err1, err3);
172    }
173
174    #[test]
175    fn error_clone() {
176        let err = BitError::InvalidBitCount {
177            bits: 65,
178            max_bits: 64,
179        };
180        let cloned = err.clone();
181        assert_eq!(err, cloned);
182    }
183
184    #[test]
185    fn error_debug() {
186        let err = BitError::UnexpectedEof {
187            requested: 1,
188            available: 0,
189        };
190        let debug = format!("{err:?}");
191        assert!(debug.contains("UnexpectedEof"));
192    }
193
194    #[test]
195    fn error_is_std_error() {
196        fn assert_error<E: std::error::Error>() {}
197        assert_error::<BitError>();
198    }
199}