Skip to content

Commit 25ee3b4

Browse files
committed
EBML: Implement integer parsing
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
1 parent 6fab5de commit 25ee3b4

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

src/ebml/element_reader.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,41 @@ where
299299
Ok(())
300300
}
301301

302-
pub(crate) fn read_signed_int(&mut self) -> Result<i64> {
303-
todo!()
302+
pub(crate) fn read_signed_int(&mut self, element_length: u64) -> Result<i64> {
303+
// https://www.rfc-editor.org/rfc/rfc8794.html#section-7.1
304+
// A Signed Integer Element MUST declare a length from zero to eight octets
305+
if element_length > 8 {
306+
decode_err!(@BAIL Ebml, "Invalid size for signed int element")
307+
}
308+
309+
let mut buf = [0; 8];
310+
self.reader
311+
.read_exact(&mut buf[8 - element_length as usize..])?;
312+
let value = u64::from_be_bytes(buf);
313+
314+
// Signed Integers are stored with two's complement notation with the leftmost bit being the sign bit.
315+
let value_width = element_length * 8;
316+
let shift = (64 - value_width) as u32;
317+
Ok((value.wrapping_shl(shift) as i64).wrapping_shr(shift))
304318
}
305319

306-
pub(crate) fn read_unsigned_int(&mut self) -> Result<u64> {
307-
todo!()
320+
pub(crate) fn read_unsigned_int(&mut self, element_length: u64) -> Result<u64> {
321+
// https://www.rfc-editor.org/rfc/rfc8794.html#section-7.2
322+
// An Unsigned Integer Element MUST declare a length from zero to eight octets
323+
if element_length > 8 {
324+
decode_err!(@BAIL Ebml, "Invalid size for unsigned int element")
325+
}
326+
327+
let mut buf = [0; 8];
328+
self.reader
329+
.read_exact(&mut buf[8 - element_length as usize..])?;
330+
Ok(u64::from_be_bytes(buf))
308331
}
309332

310333
pub(crate) fn read_float(&mut self, element_length: u64) -> Result<f64> {
334+
// https://www.rfc-editor.org/rfc/rfc8794.html#section-7.3
335+
// A Float Element MUST declare a length of either zero octets (0 bit),
336+
// four octets (32 bit), or eight octets (64 bit)
311337
Ok(match element_length {
312338
0 => 0.0,
313339
4 => f64::from(self.reader.read_f32::<BigEndian>()?),

src/ebml/read.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,13 @@ where
9494
}
9595

9696
if ident == ElementIdent::EBMLMaxIDLength {
97-
properties.header.max_id_length = element_reader.read_unsigned_int()? as u8;
97+
properties.header.max_id_length = element_reader.read_unsigned_int(size)? as u8;
9898
element_reader.set_max_id_length(properties.header.max_id_length);
9999
continue;
100100
}
101101

102102
if ident == ElementIdent::EBMLMaxSizeLength {
103-
properties.header.max_size_length = element_reader.read_unsigned_int()? as u8;
103+
properties.header.max_size_length = element_reader.read_unsigned_int(size)? as u8;
104104
element_reader.set_max_size_length(properties.header.max_size_length);
105105
continue;
106106
}
@@ -114,14 +114,14 @@ where
114114

115115
match ident {
116116
ElementIdent::EBMLVersion => {
117-
properties.header.version = element_reader.read_unsigned_int()?
117+
properties.header.version = element_reader.read_unsigned_int(size)?
118118
},
119119
ElementIdent::EBMLReadVersion => {
120-
properties.header.read_version = element_reader.read_unsigned_int()?
120+
properties.header.read_version = element_reader.read_unsigned_int(size)?
121121
},
122122
ElementIdent::DocType => properties.header.doc_type = element_reader.read_string()?,
123123
ElementIdent::DocTypeVersion => {
124-
properties.header.doc_type_version = element_reader.read_unsigned_int()?
124+
properties.header.doc_type_version = element_reader.read_unsigned_int(size)?
125125
},
126126
_ => element_reader.skip(size)?,
127127
}

0 commit comments

Comments
 (0)