Skip to main content

mp4_atom/moov/udta/
rtng.rs

1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Rtng {
6    pub entity: FourCC,
7    pub criteria: FourCC,
8    pub language: String,
9    pub rating_info: String,
10}
11
12impl AtomExt for Rtng {
13    type Ext = ();
14
15    const KIND_EXT: FourCC = FourCC::new(b"rtng");
16
17    fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
18        let entity = FourCC::decode(buf)?;
19        let criteria = FourCC::decode(buf)?;
20        let language_code = u16::decode(buf)?;
21        let language = language_string(language_code);
22        let num_remaining_bytes = buf.remaining();
23        let remaining_bytes = &mut buf.slice(num_remaining_bytes);
24        let mut rating_info =
25            String::from_utf8(remaining_bytes.to_vec()).map_err(|_| Error::InvalidSize)?;
26        if rating_info.ends_with('\0') {
27            rating_info.truncate(rating_info.len() - 1);
28        }
29        buf.advance(num_remaining_bytes);
30        Ok(Rtng {
31            entity,
32            criteria,
33            language,
34            rating_info,
35        })
36    }
37
38    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
39        self.entity.encode(buf)?;
40        self.criteria.encode(buf)?;
41        let language_code = language_code(&self.language);
42        language_code.encode(buf)?;
43        self.rating_info.as_str().encode(buf)?;
44        Ok(())
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use crate::*;
51
52    const ENCODED_RTNG: &[u8] = &[
53        0x00, 0x00, 0x00, 0x1d, 0x72, 0x74, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x50, 0x41,
54        0x41, 0x00, 0x00, 0x00, 0x00, 0x15, 0xc7, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55    ];
56
57    #[test]
58    fn test_rtng_decode() {
59        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_RTNG);
60        let rtng = Rtng::decode(buf).expect("failed to decode rtng");
61        assert_eq!(
62            rtng,
63            Rtng {
64                entity: b"MPAA".into(),
65                criteria: b"\0\0\0\0".into(),
66                language: "eng".into(),
67                rating_info: "G\0\0\0\0\0".into(),
68            }
69        );
70    }
71
72    #[test]
73    fn test_rtng_encode() {
74        let rtng = Rtng {
75            entity: b"MPAA".into(),
76            criteria: b"\0\0\0\0".into(),
77            language: "eng".into(),
78            rating_info: "G\0\0\0\0\0".into(),
79        };
80
81        let mut buf = Vec::new();
82        rtng.encode(&mut buf).unwrap();
83        assert_eq!(buf, ENCODED_RTNG);
84    }
85}