@@ -101,19 +101,48 @@ impl VInt {
101
101
where
102
102
R : Read ,
103
103
{
104
- // A value of 0b0000_0000 indicates either an invalid VInt, or one with an octet length > 8
105
104
let start = reader. read_u8 ( ) ?;
106
- if start == 0b0000_0000 {
107
- err ! ( BadVintSize ) ;
108
- }
105
+ let octet_length = Self :: verify_length ( start, max_length) ?;
109
106
110
- let octet_length = ( Self :: MAX_OCTET_LENGTH as u32 ) - start. ilog2 ( ) ;
111
- if octet_length > 8 || octet_length as u8 > max_length {
112
- err ! ( BadVintSize ) ;
107
+ let mut bytes_read = 1 ;
108
+ let mut val = u64:: from ( start) ^ ( 1 << start. ilog2 ( ) ) as u64 ;
109
+ while bytes_read < octet_length {
110
+ bytes_read += 1 ;
111
+ val = ( val << 8 ) | u64:: from ( reader. read_u8 ( ) ?) ;
113
112
}
114
113
114
+ Ok ( Self ( val) )
115
+ }
116
+
117
+ /// Parse a `VInt` from a reader, given the element ID
118
+ ///
119
+ /// An element ID is parsed similarly to a normal `VInt`, but the `VINT_MARKER` is not
120
+ /// removed.
121
+ ///
122
+ /// # Errors
123
+ ///
124
+ /// * `uint` cannot fit within the maximum width
125
+ ///
126
+ /// # Examples
127
+ ///
128
+ /// ```rust
129
+ /// use lofty::ebml::VInt;
130
+ ///
131
+ /// # fn main() -> lofty::Result<()> {
132
+ /// // Parse the EBML header element ID
133
+ /// let mut reader = &[0x1A, 0x45, 0xDF, 0xA3];
134
+ /// let vint = VInt::parse_from_element_id(&mut reader, 8)?;
135
+ /// assert_eq!(vint.value(), 0x1A45DFA3);
136
+ /// # Ok(()) }
137
+ pub fn parse_from_element_id < R > ( reader : & mut R , max_id_length : u8 ) -> Result < Self >
138
+ where
139
+ R : Read ,
140
+ {
141
+ let start = reader. read_u8 ( ) ?;
142
+ let octet_length = Self :: verify_length ( start, max_id_length) ?;
143
+
115
144
let mut bytes_read = 1 ;
116
- let mut val = u64:: from ( start) ^ ( 1 << start . ilog2 ( ) ) as u64 ;
145
+ let mut val = u64:: from ( start) ;
117
146
while bytes_read < octet_length {
118
147
bytes_read += 1 ;
119
148
val = ( val << 8 ) | u64:: from ( reader. read_u8 ( ) ?) ;
@@ -122,6 +151,21 @@ impl VInt {
122
151
Ok ( Self ( val) )
123
152
}
124
153
154
+ // Verify that the octet length is nonzero and <= 8
155
+ fn verify_length ( first_byte : u8 , max_length : u8 ) -> Result < u32 > {
156
+ // A value of 0b0000_0000 indicates either an invalid VInt, or one with an octet length > 8
157
+ if first_byte == 0b0000_0000 {
158
+ err ! ( BadVintSize ) ;
159
+ }
160
+
161
+ let octet_length = ( Self :: MAX_OCTET_LENGTH as u32 ) - first_byte. ilog2 ( ) ;
162
+ if octet_length > 8 || octet_length as u8 > max_length {
163
+ err ! ( BadVintSize ) ;
164
+ }
165
+
166
+ Ok ( octet_length)
167
+ }
168
+
125
169
/// Represents the length of the `VInt` in octets
126
170
///
127
171
/// NOTE: The value returned will always be <= 8
0 commit comments