async_mp4/types/
language.rs

1use std::fmt::{Debug, Formatter};
2use isolanguage_1::LanguageCode;
3use std::str::FromStr;
4use crate::mp4_data;
5
6mp4_data! {
7    #[derive(Copy, Clone, Eq, PartialEq, Hash)]
8    pub struct Mp4LanguageCode(u16);
9}
10
11impl Debug for Mp4LanguageCode {
12    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
13        Debug::fmt(&self.to_language_code(), f)
14    }
15}
16
17impl Default for Mp4LanguageCode {
18    fn default() -> Self {
19        Self::from_language_code(None)
20    }
21}
22
23impl From<LanguageCode> for Mp4LanguageCode {
24    fn from(code: LanguageCode) -> Self {
25        Self::from_language_code(Some(code))
26    }
27}
28
29impl From<Option<LanguageCode>> for Mp4LanguageCode {
30    fn from(code: Option<LanguageCode>) -> Self {
31        Self::from_language_code(code)
32    }
33}
34
35impl From<Mp4LanguageCode> for Option<LanguageCode> {
36    fn from(code: Mp4LanguageCode) -> Self {
37        code.to_language_code()
38    }
39}
40
41
42impl Mp4LanguageCode {
43    fn to_language_code(&self) -> Option<LanguageCode> {
44        const MASK: u8 = 0b11111;
45        let value = self.0;
46        let data = [
47            ((value >> 10) as u8 & MASK) + 0x60,
48            ((value >> 05) as u8 & MASK) + 0x60,
49            ((value >> 00) as u8 & MASK) + 0x60
50        ];
51        LanguageCode::from_str(std::str::from_utf8(&data).ok()?).ok()
52    }
53
54    fn from_language_code(code: Option<LanguageCode>) -> Self {
55        const UND: u16 =
56            ((b'u' as u16 - 0x60) << 10) |
57            ((b'n' as u16 - 0x60) << 05) |
58            ((b'd' as u16 - 0x60) << 00);
59
60        Self(match code {
61            None => UND,
62            Some(code) => {
63                if let [a, b, c] = code.code_t().as_bytes() {
64                    ((*a as u16 - 0x60) << 10) | ((*b as u16 - 0x60) << 05) | ((*c as u16 - 0x60) << 00)
65                } else {
66                    UND
67                }
68            }
69        })
70    }
71}