|
| 1 | +use crate::ebml::vint::VInt; |
| 2 | +use crate::error::Result; |
| 3 | +use crate::macros::decode_err; |
| 4 | + |
| 5 | +use std::io::Read; |
| 6 | + |
| 7 | +use byteorder::{BigEndian, ReadBytesExt}; |
| 8 | + |
| 9 | +pub struct ElementHeader { |
| 10 | + pub(crate) id: VInt, |
| 11 | + pub(crate) size: VInt, |
| 12 | +} |
| 13 | + |
| 14 | +impl ElementHeader { |
| 15 | + fn read<R>(reader: &mut R, max_vint_length: u8) -> Result<Self> |
| 16 | + where |
| 17 | + R: Read, |
| 18 | + { |
| 19 | + Ok(Self { |
| 20 | + id: VInt::parse(reader, max_vint_length)?, |
| 21 | + size: VInt::parse(reader, max_vint_length)?, |
| 22 | + }) |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +#[derive(Copy, Clone)] |
| 27 | +pub enum ElementDataType { |
| 28 | + SignedInt, |
| 29 | + UnsignedInt, |
| 30 | + Float, |
| 31 | + String, |
| 32 | + Utf8, |
| 33 | + Date, |
| 34 | + Master, |
| 35 | + Binary, |
| 36 | +} |
| 37 | + |
| 38 | +#[derive(Copy, Clone)] |
| 39 | +struct MasterElement { |
| 40 | + id: ElementIdent, |
| 41 | + children: &'static [(VInt, ChildElementDescriptor)], |
| 42 | +} |
| 43 | + |
| 44 | +#[derive(Copy, Clone)] |
| 45 | +pub(crate) struct ChildElementDescriptor { |
| 46 | + pub(crate) ident: ElementIdent, |
| 47 | + pub(crate) data_type: ElementDataType, |
| 48 | +} |
| 49 | + |
| 50 | +macro_rules! define_master_elements { |
| 51 | + ($( |
| 52 | + $_readable_ident:ident : { |
| 53 | + id: $vint_id:literal, |
| 54 | + children: [ |
| 55 | + $($_readable_child_ident:ident : { $child_id:literal, $data_ty:ident }),* $(,)? |
| 56 | + ] $(,)? |
| 57 | + } |
| 58 | + ),+ $(,)?) => { |
| 59 | + #[derive(Copy, Clone, Eq, PartialEq)] |
| 60 | + pub(crate) enum ElementIdent { |
| 61 | + $( |
| 62 | + $_readable_ident, |
| 63 | + $($_readable_child_ident,)* |
| 64 | + )+ |
| 65 | + } |
| 66 | + |
| 67 | + static MASTER_ELEMENTS: once_cell::sync::Lazy<std::collections::HashMap<VInt, MasterElement>> = once_cell::sync::Lazy::new(|| { |
| 68 | + let mut m = std::collections::HashMap::new(); |
| 69 | + $( |
| 70 | + m.insert( |
| 71 | + VInt($vint_id), |
| 72 | + MasterElement { |
| 73 | + id: ElementIdent::$_readable_ident, |
| 74 | + children: &[$((VInt($child_id), ChildElementDescriptor { |
| 75 | + ident: ElementIdent::$_readable_child_ident, |
| 76 | + data_type: ElementDataType::$data_ty, |
| 77 | + })),*][..] |
| 78 | + } |
| 79 | + ); |
| 80 | + )+ |
| 81 | + m |
| 82 | + }); |
| 83 | + } |
| 84 | +} |
| 85 | + |
| 86 | +define_master_elements! { |
| 87 | + EBML: { |
| 88 | + id: 0x1A45DFA3, |
| 89 | + children: [ |
| 90 | + EBMLVersion: { 0x4286, UnsignedInt }, |
| 91 | + EBMLReadVersion: { 0x42F7, UnsignedInt }, |
| 92 | + EBMLMaxIDLength: { 0x42F2, UnsignedInt }, |
| 93 | + EBMLMaxSizeLength: { 0x42F3, UnsignedInt }, |
| 94 | + DocType: { 0x4282, String }, |
| 95 | + DocTypeVersion: { 0x4287, UnsignedInt }, |
| 96 | + DocTypeReadVersion: { 0x4285, UnsignedInt }, |
| 97 | + ], |
| 98 | + }, |
| 99 | + DocTypeExtension: { |
| 100 | + id: 0x4281, |
| 101 | + children: [ |
| 102 | + DocTypeExtensionName: { 0x4283, String }, |
| 103 | + DocTypeExtensionVersion: { 0x4284, UnsignedInt }, |
| 104 | + ], |
| 105 | + }, |
| 106 | +} |
| 107 | + |
| 108 | +struct ElementReaderContext { |
| 109 | + /// Current master element |
| 110 | + current_master: Option<MasterElement>, |
| 111 | + /// Remaining length of the master element |
| 112 | + master_length: u64, |
| 113 | + /// Maximum size in octets of all element IDs |
| 114 | + max_id_length: u8, |
| 115 | + /// Maximum size in octets of all element data sizes |
| 116 | + max_size_length: u8, |
| 117 | +} |
| 118 | + |
| 119 | +impl Default for ElementReaderContext { |
| 120 | + fn default() -> Self { |
| 121 | + Self { |
| 122 | + current_master: None, |
| 123 | + master_length: 0, |
| 124 | + // https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxidlength-element |
| 125 | + max_id_length: 4, |
| 126 | + // https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxsizelength-element |
| 127 | + max_size_length: 8, |
| 128 | + } |
| 129 | + } |
| 130 | +} |
| 131 | + |
| 132 | +pub(crate) enum ElementReaderYield { |
| 133 | + Master((ElementIdent, u64)), |
| 134 | + Child((ChildElementDescriptor, u64)), |
| 135 | + Unknown(ElementHeader), |
| 136 | + Eof, |
| 137 | +} |
| 138 | + |
| 139 | +pub struct ElementReader<R> { |
| 140 | + reader: R, |
| 141 | + ctx: ElementReaderContext, |
| 142 | +} |
| 143 | + |
| 144 | +impl<R> ElementReader<R> |
| 145 | +where |
| 146 | + R: Read, |
| 147 | +{ |
| 148 | + pub(crate) fn new(reader: R) -> Self { |
| 149 | + Self { |
| 150 | + reader, |
| 151 | + ctx: ElementReaderContext::default(), |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + pub(crate) fn set_max_id_length(&mut self, len: u8) { |
| 156 | + self.ctx.max_id_length = len |
| 157 | + } |
| 158 | + |
| 159 | + pub(crate) fn set_max_size_length(&mut self, len: u8) { |
| 160 | + self.ctx.max_size_length = len |
| 161 | + } |
| 162 | + |
| 163 | + fn next_master(&mut self) -> Result<ElementReaderYield> { |
| 164 | + let header = ElementHeader::read(&mut self.reader, self.ctx.max_size_length)?; |
| 165 | + let Some(master) = MASTER_ELEMENTS.get(&header.id) else { |
| 166 | + // We encountered an unknown master element |
| 167 | + return Ok(ElementReaderYield::Unknown(header)); |
| 168 | + }; |
| 169 | + |
| 170 | + self.ctx.current_master = Some(*master); |
| 171 | + self.ctx.master_length = header.size.value(); |
| 172 | + Ok(ElementReaderYield::Master(( |
| 173 | + master.id, |
| 174 | + self.ctx.master_length, |
| 175 | + ))) |
| 176 | + } |
| 177 | + |
| 178 | + pub(crate) fn next(&mut self) -> Result<ElementReaderYield> { |
| 179 | + let Some(current_master) = self.ctx.current_master else { |
| 180 | + return self.next_master(); |
| 181 | + }; |
| 182 | + |
| 183 | + if self.ctx.master_length == 0 { |
| 184 | + return self.next_master(); |
| 185 | + } |
| 186 | + |
| 187 | + let header = ElementHeader::read(&mut self.reader, self.ctx.max_size_length)?; |
| 188 | + |
| 189 | + let Some((_, child)) = current_master |
| 190 | + .children |
| 191 | + .iter() |
| 192 | + .find(|(id, _)| *id == header.id) |
| 193 | + else { |
| 194 | + return Ok(ElementReaderYield::Unknown(header)); |
| 195 | + }; |
| 196 | + |
| 197 | + Ok(ElementReaderYield::Child((*child, header.size.value()))) |
| 198 | + } |
| 199 | + |
| 200 | + pub(crate) fn skip(&mut self, length: u64) -> Result<()> { |
| 201 | + std::io::copy(&mut self.reader.by_ref().take(length), &mut std::io::sink())?; |
| 202 | + Ok(()) |
| 203 | + } |
| 204 | + |
| 205 | + pub(crate) fn read_signed_int(&mut self) -> Result<i64> { |
| 206 | + todo!() |
| 207 | + } |
| 208 | + |
| 209 | + pub(crate) fn read_unsigned_int(&mut self) -> Result<u64> { |
| 210 | + todo!() |
| 211 | + } |
| 212 | + |
| 213 | + pub(crate) fn read_float(&mut self, element_length: u64) -> Result<f64> { |
| 214 | + Ok(match element_length { |
| 215 | + 0 => 0.0, |
| 216 | + 4 => self.reader.read_f32::<BigEndian>()? as f64, |
| 217 | + 8 => self.reader.read_f64::<BigEndian>()?, |
| 218 | + _ => decode_err!(@BAIL Ebml, "Invalid size for float element"), |
| 219 | + }) |
| 220 | + } |
| 221 | + |
| 222 | + pub(crate) fn read_string(&mut self) -> Result<String> { |
| 223 | + todo!() |
| 224 | + } |
| 225 | + |
| 226 | + pub(crate) fn read_utf8(&mut self) -> Result<String> { |
| 227 | + todo!() |
| 228 | + } |
| 229 | + |
| 230 | + pub(crate) fn read_date(&mut self) -> Result<String> { |
| 231 | + todo!() |
| 232 | + } |
| 233 | + |
| 234 | + pub(crate) fn read_binary(&mut self) -> Result<Vec<u8>> { |
| 235 | + todo!() |
| 236 | + } |
| 237 | +} |
0 commit comments