mkv_element/
element.rs

1use crate::base::*;
2use crate::error::Error;
3use crate::functional::*;
4use crate::io::ReadFrom;
5
6/// A Matroska element.
7pub trait Element: Sized {
8    const ID: VInt64;
9    fn decode_body(buf: &mut &[u8]) -> crate::Result<Self>;
10    fn encode_body<B: BufMut>(&self, buf: &mut B) -> crate::Result<()>;
11}
12
13impl<T: Element> Decode for T {
14    fn decode(buf: &mut &[u8]) -> crate::Result<Self> {
15        let header = Header::decode(buf)?;
16        let body_size = *header.size as usize;
17        if buf.remaining() < body_size {
18            return Err(crate::error::Error::OutOfBounds);
19        }
20        let mut body = buf.slice(body_size);
21        let element = match T::decode_body(&mut body) {
22            Ok(e) => e,
23            Err(Error::OutOfBounds) => return Err(Error::OverDecode(Self::ID)),
24            Err(Error::ShortRead) => return Err(Error::UnderDecode(Self::ID)),
25            Err(e) => return Err(e),
26        };
27
28        if body.has_remaining() {
29            return Err(Error::UnderDecode(Self::ID));
30        }
31
32        buf.advance(body_size);
33        Ok(element)
34    }
35}
36
37impl<T: Element> Encode for T {
38    fn encode<B: BufMut>(&self, buf: &mut B) -> crate::Result<()> {
39        let mut body_buf = Vec::new();
40        self.encode_body(&mut body_buf)?;
41        let header = Header {
42            id: T::ID,
43            size: VInt64(body_buf.len() as u64),
44        };
45        header.encode(buf)?;
46        buf.append_slice(&body_buf);
47        Ok(())
48    }
49}
50
51impl<T: Element> ReadFrom for T {
52    fn read_from<R: std::io::Read>(r: &mut R) -> crate::Result<Self> {
53        let header = Header::read_from(r)?;
54        let body = header.read_body(r)?;
55        let element = match T::decode_body(&mut &body[..]) {
56            Ok(e) => e,
57            Err(Error::OutOfBounds) => return Err(Error::OverDecode(Self::ID)),
58            Err(Error::ShortRead) => return Err(Error::UnderDecode(Self::ID)),
59            Err(e) => return Err(e),
60        };
61        Ok(element)
62    }
63}