isobmff/
common_types.rs

1use std::io;
2use std::ops::Deref;
3
4use base64::Engine;
5use scuffle_bytes_util::BitWriter;
6use scuffle_bytes_util::zero_copy::{Deserialize, Serialize, ZeroCopyReader};
7
8use crate::IsoSized;
9
10/// UTF-8 string as defined in IETF RFC 3629, null-terminated.
11///
12/// ISO/IEC 14496-12 - 4.2.1
13#[derive(Debug, PartialEq, Eq)]
14pub struct Utf8String(pub String);
15
16impl From<String> for Utf8String {
17    fn from(string: String) -> Self {
18        Utf8String(string)
19    }
20}
21
22impl From<Utf8String> for String {
23    fn from(utf8_string: Utf8String) -> Self {
24        utf8_string.0
25    }
26}
27
28impl Deref for Utf8String {
29    type Target = str;
30
31    fn deref(&self) -> &Self::Target {
32        &self.0
33    }
34}
35
36impl<'a> Deserialize<'a> for Utf8String {
37    fn deserialize<R>(mut reader: R) -> io::Result<Self>
38    where
39        R: ZeroCopyReader<'a>,
40    {
41        let mut bytes = Vec::new();
42
43        loop {
44            let byte = u8::deserialize(&mut reader)?;
45            if byte == 0 {
46                break;
47            }
48            bytes.push(byte);
49        }
50
51        let string =
52            String::from_utf8(bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 sequence"))?;
53        Ok(Utf8String(string))
54    }
55}
56
57impl Serialize for Utf8String {
58    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
59    where
60        W: std::io::Write,
61    {
62        writer.write_all(self.0.as_bytes())?;
63        writer.write_all(&[0])?;
64        Ok(())
65    }
66}
67
68impl IsoSized for Utf8String {
69    fn size(&self) -> usize {
70        self.0.len() + 1
71    }
72}
73
74/// Null-terminated base64 encoded data.
75///
76/// ISO/IEC 14496-12 - 4.2.1
77#[derive(Debug, PartialEq, Eq)]
78pub struct Base64String(pub Vec<u8>);
79
80impl Deref for Base64String {
81    type Target = [u8];
82
83    fn deref(&self) -> &Self::Target {
84        &self.0
85    }
86}
87
88impl<'a> Deserialize<'a> for Base64String {
89    fn deserialize<R>(mut reader: R) -> io::Result<Self>
90    where
91        R: ZeroCopyReader<'a>,
92    {
93        let mut bytes = Vec::new();
94
95        loop {
96            let byte = u8::deserialize(&mut reader)?;
97            if byte == 0 {
98                break;
99            }
100            bytes.push(byte);
101        }
102
103        let data = base64::prelude::BASE64_STANDARD
104            .decode(bytes)
105            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("Base64 decode error: {e}")))?;
106        Ok(Base64String(data))
107    }
108}
109
110impl Serialize for Base64String {
111    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
112    where
113        W: std::io::Write,
114    {
115        let encoded = base64::prelude::BASE64_STANDARD.encode(&self.0);
116        writer.write_all(encoded.as_bytes())?;
117        writer.write_all(&[0])?;
118        Ok(())
119    }
120}
121
122impl IsoSized for Base64String {
123    fn size(&self) -> usize {
124        base64::prelude::BASE64_STANDARD.encode(&self.0).len() + 1
125    }
126}
127
128/// Null-terminated list of space-separated UTF-8 strings.
129///
130/// ISO/IEC 14496-12 - 4.2.1
131#[derive(Debug, PartialEq, Eq)]
132pub struct Utf8List(pub Vec<String>);
133
134impl<'a> Deserialize<'a> for Utf8List {
135    fn deserialize<R>(mut reader: R) -> io::Result<Self>
136    where
137        R: ZeroCopyReader<'a>,
138    {
139        let mut strings = Vec::new();
140
141        'list: loop {
142            let mut bytes = Vec::new();
143
144            'string: loop {
145                let byte = u8::deserialize(&mut reader)?;
146                if byte == b' ' {
147                    break 'string;
148                } else if byte == 0 {
149                    break 'list;
150                }
151                bytes.push(byte);
152            }
153
154            let string = String::from_utf8(bytes)
155                .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 sequence"))?;
156
157            strings.push(string);
158        }
159
160        Ok(Self(strings))
161    }
162}
163
164impl Serialize for Utf8List {
165    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
166    where
167        W: std::io::Write,
168    {
169        for string in &self.0 {
170            writer.write_all(string.as_bytes())?;
171            writer.write_all(b" ")?;
172        }
173        writer.write_all(&[0])?;
174
175        Ok(())
176    }
177}
178
179impl IsoSized for Utf8List {
180    fn size(&self) -> usize {
181        self.0.iter().map(|s| s.len() + 1).sum::<usize>() + 1
182    }
183}
184
185/// ISO-639-2 three-letter language code.
186///
187/// <https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes>
188#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189pub struct Langauge(pub [u8; 3]);
190
191impl Langauge {
192    /// Undetermined language code.
193    pub const UNDETERMINED: Self = Self([0x15, 0x0E, 0x04]); // und
194}
195
196impl<'a> Deserialize<'a> for Langauge {
197    fn deserialize<R>(reader: R) -> std::io::Result<Self>
198    where
199        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
200    {
201        // 0 xxxxx xxxxx xxxxx
202        let language = u16::deserialize(reader)?;
203        let language = [
204            ((language >> 10) & 0b11111) as u8,
205            ((language >> 5) & 0b11111) as u8,
206            (language & 0b11111) as u8,
207        ];
208
209        Ok(Langauge(language))
210    }
211}
212
213impl Serialize for Langauge {
214    fn serialize<W>(&self, writer: W) -> std::io::Result<()>
215    where
216        W: std::io::Write,
217    {
218        let mut bit_writer = BitWriter::new(writer);
219        bit_writer.write_bit(false)?;
220        bit_writer.write_bits(self.0[0] as u64, 5)?;
221        bit_writer.write_bits(self.0[1] as u64, 5)?;
222        bit_writer.write_bits(self.0[2] as u64, 5)?;
223        Ok(())
224    }
225}
226
227impl IsoSized for Langauge {
228    fn size(&self) -> usize {
229        2
230    }
231}
232
233impl Langauge {
234    /// Returns the language code as a three-character array.
235    pub fn code(&self) -> [char; 3] {
236        [
237            (self.0[0] + 0x60) as char,
238            (self.0[1] + 0x60) as char,
239            (self.0[2] + 0x60) as char,
240        ]
241    }
242}