11use crate :: error:: Result ;
22use crate :: macros:: err;
3- use std:: fmt:: UpperHex ;
43
4+ use std:: fmt:: { Debug , Display , UpperHex } ;
55use std:: io:: { Read , Write } ;
66use std:: ops:: { Add , Sub } ;
77
@@ -19,6 +19,10 @@ macro_rules! impl_vint {
1919 pub const MIN : $t = <$t>:: MIN ;
2020 /// A `VInt` with a value of 0
2121 pub const ZERO : Self = Self ( 0 ) ;
22+ /// An unknown-sized `VInt`
23+ ///
24+ /// See [`Self::is_unknown()`]
25+ pub const UNKNOWN : Self = Self ( Self :: ZERO . 0 | 1 << ( <$t>:: BITS as u64 ) - 1 ) ;
2226
2327 /// Gets the inner value of the `VInt`
2428 ///
@@ -32,10 +36,20 @@ macro_rules! impl_vint {
3236 /// assert_eq!(vint.value(), 2);
3337 /// # Ok(()) }
3438 /// ```
35- pub fn value( & self ) -> $t {
39+ #[ inline]
40+ pub fn value( self ) -> $t {
3641 self . 0
3742 }
3843
44+ /// Whether this `VInt` represents an unknown size
45+ ///
46+ /// Since EBML is built for streaming, elements can specify that their data length
47+ /// is unknown.
48+ #[ inline]
49+ pub fn is_unknown( self ) -> bool {
50+ self == Self :: UNKNOWN
51+ }
52+
3953 /// Parse a `VInt` from a reader
4054 ///
4155 /// `max_length` can be used to specify the maximum number of octets the number should
@@ -94,7 +108,8 @@ macro_rules! impl_vint {
94108 /// assert_eq!(vint.octet_length(), 3);
95109 /// # Ok(()) }
96110 /// ```
97- pub fn octet_length( & self ) -> u8 {
111+ #[ inline]
112+ pub fn octet_length( self ) -> u8 {
98113 octet_length( self . 0 as u64 )
99114 }
100115
@@ -123,15 +138,19 @@ macro_rules! impl_vint {
123138 /// assert_eq!(bytes, &[0b1000_1010]);
124139 /// # Ok(()) }
125140 /// ```
126- pub fn as_bytes( & self , min_length: Option <u8 >, max_length: Option <u8 >) -> Result <Vec <u8 >> {
141+ pub fn as_bytes( self , min_length: Option <u8 >, max_length: Option <u8 >) -> Result <Vec <u8 >> {
127142 let mut ret = Vec :: with_capacity( 8 ) ;
128- VInt :: <$t>:: write_to( self . 0 as u64 , min_length, max_length, & mut ret) ?;
143+ VInt :: <$t>:: write_to( self . 0 as u64 , min_length, max_length, self . is_unknown ( ) , & mut ret) ?;
129144 Ok ( ret)
130145 }
131146
132147 #[ inline]
133148 #[ allow( dead_code) ]
134149 pub ( crate ) fn saturating_sub( self , other: $t) -> Self {
150+ if self . is_unknown( ) {
151+ return self ;
152+ }
153+
135154 let v = self . 0 . saturating_sub( other) ;
136155 if v < Self :: MIN {
137156 return Self ( Self :: MIN ) ;
@@ -145,6 +164,10 @@ macro_rules! impl_vint {
145164 type Output = Self ;
146165
147166 fn add( self , other: Self ) -> Self :: Output {
167+ if self . is_unknown( ) {
168+ return self ;
169+ }
170+
148171 let val = self . 0 + other. 0 ;
149172 assert!( val <= Self :: MAX , "VInt overflow" ) ;
150173
@@ -156,6 +179,10 @@ macro_rules! impl_vint {
156179 type Output = Self ;
157180
158181 fn sub( self , other: Self ) -> Self :: Output {
182+ if self . is_unknown( ) {
183+ return self ;
184+ }
185+
159186 Self ( self . 0 - other. 0 )
160187 }
161188 }
@@ -177,6 +204,18 @@ macro_rules! impl_vint {
177204 Ok ( Self ( value) )
178205 }
179206 }
207+
208+ impl Debug for VInt <$t> {
209+ fn fmt( & self , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
210+ let mut debug = f. debug_tuple( "VInt" ) ;
211+ if self . is_unknown( ) {
212+ debug. field( & "<unknown>" ) ;
213+ } else {
214+ debug. field( & self . 0 ) ;
215+ }
216+ debug. finish( )
217+ }
218+ }
180219 }
181220 ) *
182221 } ;
@@ -188,7 +227,7 @@ macro_rules! impl_vint {
188227///
189228/// To ensure safe construction of `VInt`s, users must create them through the `TryFrom` implementations or [`VInt::parse`].
190229#[ repr( transparent) ]
191- #[ derive( Copy , Clone , Eq , PartialEq , Ord , PartialOrd , Hash , Debug , Default ) ]
230+ #[ derive( Copy , Clone , Eq , PartialEq , Ord , PartialOrd , Hash , Default ) ]
192231pub struct VInt < T > ( pub ( crate ) T ) ;
193232
194233impl < T > VInt < T > {
@@ -201,6 +240,7 @@ impl<T> VInt<T> {
201240 mut value : u64 ,
202241 min_length : Option < u8 > ,
203242 max_length : Option < u8 > ,
243+ unknown : bool ,
204244 writer : & mut W ,
205245 ) -> Result < ( ) >
206246 where
@@ -214,6 +254,15 @@ impl<T> VInt<T> {
214254 // Add the octet length
215255 value |= 1 << ( octets * ( Self :: USABLE_BITS_PER_BYTE as u8 ) ) ;
216256
257+ // All VINT_DATA bits set to one
258+ if unknown {
259+ for _ in 0 ..octets {
260+ writer. write_u8 ( u8:: MAX ) ?;
261+ }
262+
263+ return Ok ( ( ) ) ;
264+ }
265+
217266 let mut byte_shift = ( octets - 1 ) as i8 ;
218267 while byte_shift >= 0 {
219268 writer. write_u8 ( ( value >> ( byte_shift * 8 ) ) as u8 ) ?;
@@ -224,6 +273,15 @@ impl<T> VInt<T> {
224273 }
225274}
226275
276+ impl < T > Display for VInt < T >
277+ where
278+ T : Display ,
279+ {
280+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
281+ write ! ( f, "{}" , self . 0 )
282+ }
283+ }
284+
227285impl_vint ! ( u64 , i64 ) ;
228286
229287fn parse_vint < R > ( reader : & mut R , max_length : u8 , retain_marker : bool ) -> Result < ( u64 , u8 ) >
@@ -245,6 +303,11 @@ where
245303 val = ( val << 8 ) | u64:: from ( reader. read_u8 ( ) ?) ;
246304 }
247305
306+ // Special case for unknown VInts (all data bits set to one)
307+ if val + 1 == 1 << ( 7 * bytes_read) {
308+ return Ok ( ( VInt :: < u64 > :: UNKNOWN . 0 , bytes_read) ) ;
309+ }
310+
248311 Ok ( ( val, bytes_read) )
249312}
250313
@@ -283,7 +346,7 @@ fn octet_length(mut value: u64) -> u8 {
283346///
284347/// * The `VINT_MARKER` is retained after parsing
285348/// * When encoding, the minimum number of octets must be used
286- #[ derive( Copy , Clone , Eq , PartialEq , Ord , PartialOrd , Hash , Debug , Default ) ]
349+ #[ derive( Copy , Clone , Eq , PartialEq , Ord , PartialOrd , Hash , Default ) ]
287350pub struct ElementId ( pub ( crate ) u64 ) ;
288351
289352impl ElementId {
@@ -364,7 +427,7 @@ impl ElementId {
364427 pub ( crate ) fn write_to < W : Write > ( self , max_length : Option < u8 > , writer : & mut W ) -> Result < ( ) > {
365428 let mut val = self . 0 ;
366429 val ^= 1 << val. ilog2 ( ) ;
367- VInt :: < ( ) > :: write_to ( val, None , max_length, writer) ?;
430+ VInt :: < ( ) > :: write_to ( val, None , max_length, false , writer) ?;
368431 Ok ( ( ) )
369432 }
370433}
@@ -381,6 +444,12 @@ impl UpperHex for ElementId {
381444 }
382445}
383446
447+ impl Debug for ElementId {
448+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
449+ write ! ( f, "ElementId({:#X})" , self . 0 )
450+ }
451+ }
452+
384453#[ cfg( test) ]
385454mod tests {
386455 use crate :: ebml:: VInt ;
0 commit comments