async_mp4/types/
language.rs1use 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}