1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use super::DescriptorError;
use encoding::all::ISO_8859_1;
use encoding::types::DecoderTrap;
use encoding::Encoding;
use std::borrow::Cow;
use std::fmt;
pub struct Iso639LanguageDescriptor<'buf> {
pub buf: &'buf [u8],
}
impl<'buf> Iso639LanguageDescriptor<'buf> {
pub const TAG: u8 = 10;
pub fn new(
_tag: u8,
buf: &'buf [u8],
) -> Result<Iso639LanguageDescriptor<'buf>, DescriptorError> {
Ok(Iso639LanguageDescriptor { buf })
}
pub fn languages(&self) -> LanguageIterator<'buf> {
LanguageIterator::new(self.buf)
}
}
pub struct LanguageIterator<'buf> {
remaining_data: &'buf [u8],
}
impl<'buf> LanguageIterator<'buf> {
pub fn new(data: &'buf [u8]) -> LanguageIterator<'buf> {
LanguageIterator {
remaining_data: data,
}
}
}
impl<'buf> Iterator for LanguageIterator<'buf> {
type Item = Language<'buf>;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_data.is_empty() {
None
} else {
let (head, tail) = self.remaining_data.split_at(4);
self.remaining_data = tail;
Some(Language::new(head))
}
}
}
#[derive(Debug, PartialEq)]
enum AudioType {
Undefined,
CleanEffects,
HearingImpaired,
VisualImpairedCommentary,
Reserved(u8),
}
impl From<u8> for AudioType {
fn from(v: u8) -> Self {
match v {
0 => AudioType::Undefined,
1 => AudioType::CleanEffects,
2 => AudioType::HearingImpaired,
3 => AudioType::VisualImpairedCommentary,
_ => AudioType::Reserved(v),
}
}
}
pub struct Language<'buf> {
buf: &'buf [u8],
}
impl<'buf> Language<'buf> {
fn new(buf: &'buf [u8]) -> Language<'buf> {
assert_eq!(buf.len(), 4);
Language { buf }
}
fn code(&self, trap: DecoderTrap) -> Result<String, Cow<'static, str>> {
ISO_8859_1.decode(&self.buf[0..3], trap)
}
fn audio_type(&self) -> AudioType {
AudioType::from(self.buf[3])
}
}
impl<'buf> fmt::Debug for Language<'buf> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Language")
.field("code", &self.code(DecoderTrap::Replace).unwrap())
.field("audio_type", &self.audio_type())
.finish()
}
}
struct LangsDebug<'buf>(&'buf Iso639LanguageDescriptor<'buf>);
impl<'buf> fmt::Debug for LangsDebug<'buf> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_list().entries(self.0.languages()).finish()
}
}
impl<'buf> fmt::Debug for Iso639LanguageDescriptor<'buf> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Iso639LanguageDescriptor")
.field("languages", &LangsDebug(self))
.finish()
}
}
#[cfg(test)]
mod test {
use super::super::{CoreDescriptors, Descriptor};
use super::*;
use encoding;
#[test]
fn descriptor() {
let data = hex!("0a04656e6700");
let desc = CoreDescriptors::from_bytes(&data).unwrap();
if let CoreDescriptors::ISO639Language(iso_639_language) = desc {
let mut langs = iso_639_language.languages();
let first = langs.next().unwrap();
assert_eq!("eng", first.code(encoding::DecoderTrap::Strict).unwrap());
assert_eq!(AudioType::Undefined, first.audio_type());
assert_matches!(langs.next(), None);
} else {
panic!("wrong descriptor type {:?}", desc);
}
}
}