Skip to main content

mp4/mp4box/
data.rs

1use std::{
2    convert::TryFrom,
3    io::{Read, Seek},
4};
5
6use serde::Serialize;
7
8use crate::mp4box::*;
9
10#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
11pub struct DataBox {
12    pub data: Vec<u8>,
13    pub data_type: DataType,
14}
15
16impl DataBox {
17    pub fn get_type(&self) -> BoxType {
18        BoxType::DataBox
19    }
20
21    pub fn get_size(&self) -> u64 {
22        let mut size = HEADER_SIZE;
23        size += 4; // data_type
24        size += 4; // reserved
25        size += self.data.len() as u64;
26        size
27    }
28}
29
30impl Mp4Box for DataBox {
31    fn box_type(&self) -> BoxType {
32        self.get_type()
33    }
34
35    fn box_size(&self) -> u64 {
36        self.get_size()
37    }
38
39    fn to_json(&self) -> Result<String> {
40        Ok(serde_json::to_string(&self).unwrap())
41    }
42
43    fn summary(&self) -> Result<String> {
44        let s = format!("type={:?} len={}", self.data_type, self.data.len());
45        Ok(s)
46    }
47}
48
49impl<R: Read + Seek> ReadBox<&mut R> for DataBox {
50    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
51        let start = box_start(reader)?;
52
53        let data_type = DataType::try_from(reader.read_u32::<BigEndian>()?)?;
54
55        reader.read_u32::<BigEndian>()?; // reserved = 0
56
57        let current = reader.stream_position()?;
58        let mut data = vec![0u8; (start + size - current) as usize];
59        reader.read_exact(&mut data)?;
60
61        Ok(DataBox { data, data_type })
62    }
63}
64
65impl<W: Write> WriteBox<&mut W> for DataBox {
66    fn write_box(&self, writer: &mut W) -> Result<u64> {
67        let size = self.box_size();
68        BoxHeader::new(self.box_type(), size).write(writer)?;
69
70        writer.write_u32::<BigEndian>(self.data_type.clone() as u32)?;
71        writer.write_u32::<BigEndian>(0)?; // reserved = 0
72        writer.write_all(&self.data)?;
73
74        Ok(size)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use crate::mp4box::BoxHeader;
82    use std::io::Cursor;
83
84    #[test]
85    fn test_data() {
86        let src_box = DataBox {
87            data_type: DataType::Text,
88            data: b"test_data".to_vec(),
89        };
90        let mut buf = Vec::new();
91        src_box.write_box(&mut buf).unwrap();
92        assert_eq!(buf.len(), src_box.box_size() as usize);
93
94        let mut reader = Cursor::new(&buf);
95        let header = BoxHeader::read(&mut reader).unwrap();
96        assert_eq!(header.name, BoxType::DataBox);
97        assert_eq!(src_box.box_size(), header.size);
98
99        let dst_box = DataBox::read_box(&mut reader, header.size).unwrap();
100        assert_eq!(src_box, dst_box);
101    }
102
103    #[test]
104    fn test_data_empty() {
105        let src_box = DataBox::default();
106        let mut buf = Vec::new();
107        src_box.write_box(&mut buf).unwrap();
108        assert_eq!(buf.len(), src_box.box_size() as usize);
109
110        let mut reader = Cursor::new(&buf);
111        let header = BoxHeader::read(&mut reader).unwrap();
112        assert_eq!(header.name, BoxType::DataBox);
113        assert_eq!(src_box.box_size(), header.size);
114
115        let dst_box = DataBox::read_box(&mut reader, header.size).unwrap();
116        assert_eq!(src_box, dst_box);
117    }
118}