1 use std::time::Duration;
2
3 use consts::SAMPLES_PER_FRAME;
4 use enums::{Layer, Version};
5 use types::Url;
6
compute_duration(v: Version, l: Layer, sample_rate: u16) -> Option<Duration>7 pub fn compute_duration(v: Version, l: Layer, sample_rate: u16) -> Option<Duration> {
8 if sample_rate == 0 {
9 return None;
10 }
11 let mut big = match v {
12 Version::MPEG1 => SAMPLES_PER_FRAME[0][get_layer_value(l)] as u64 * 1_000_000_000,
13 Version::MPEG2 | Version::MPEG2_5 => {
14 SAMPLES_PER_FRAME[1][get_layer_value(l)] as u64 * 1_000_000_000
15 }
16 _ => return None,
17 };
18 big /= sample_rate as u64;
19 Some(Duration::new(big / 1_000_000_000, (big % 1_000_000_000) as u32))
20 }
21
get_line(v: Version, l: Layer) -> usize22 pub fn get_line(v: Version, l: Layer) -> usize {
23 match (v, l) {
24 (Version::MPEG1, Layer::Layer1) => 0,
25 (Version::MPEG1, Layer::Layer2) => 1,
26 (Version::MPEG1, Layer::Layer3) => 2,
27 (Version::MPEG2, Layer::Layer1) | (Version::MPEG2_5, Layer::Layer1) => 3,
28 _ => 4,
29 }
30 }
31
get_layer_value(l: Layer) -> usize32 pub fn get_layer_value(l: Layer) -> usize {
33 match l {
34 Layer::Layer1 => 0,
35 Layer::Layer2 => 1,
36 Layer::Layer3 => 2,
37 _ => 3,
38 }
39 }
40
get_samp_line(v: Version) -> usize41 pub fn get_samp_line(v: Version) -> usize {
42 match v {
43 Version::MPEG1 => 0,
44 Version::MPEG2 => 1,
45 Version::MPEG2_5 => 2,
46 _ => 1,
47 }
48 }
49
create_latin1_str(buf: &[u8]) -> String50 pub fn create_latin1_str(buf: &[u8]) -> String {
51 // interpret each byte as full codepoint. UTF-16 is big enough to
52 // represent those, surrogate pairs can't be created that way
53 let utf16 = buf.iter().map(|c| *c as u16).collect::<Vec<u16>>();
54 String::from_utf16_lossy(utf16.as_ref())
55 }
56
create_utf16_str(buf: &[u8]) -> String57 pub fn create_utf16_str(buf: &[u8]) -> String {
58 let mut v = Vec::<u16>::new();
59 if buf.len() >= 2 {
60 // BOM: \u{feff}
61 if buf[0] == 0xfe && buf[1] == 0xff {
62 // UTF-16BE
63 v.reserve(buf.len() / 2 - 1);
64 for i in 1..buf.len() / 2 {
65 v.push(
66 (buf[2*i+0] as u16) << 8
67 | (buf[2*i+1] as u16)
68 )
69 }
70 return String::from_utf16_lossy(v.as_ref());
71 } else if buf[0] == 0xff && buf[1] == 0xfe {
72 // UTF-16LE
73 v.reserve(buf.len() / 2 - 1);
74 for i in 1..buf.len() / 2 {
75 v.push(
76 (buf[2*i+1] as u16) << 8
77 | (buf[2*i+0] as u16)
78 )
79 }
80 return String::from_utf16_lossy(v.as_ref());
81 }
82 }
83 // try as UTF-16LE
84 v.reserve(buf.len() / 2);
85 for i in 0..buf.len() / 2 {
86 v.push(
87 (buf[2*i+1] as u16) << 8
88 | (buf[2*i+0] as u16)
89 )
90 }
91 return String::from_utf16_lossy(v.as_ref());
92 }
93
create_utf8_str(buf: &[u8]) -> String94 pub fn create_utf8_str(buf: &[u8]) -> String {
95 // String::from_utf8_lossy(buf).into_owned()
96 String::from_utf8(buf.to_owned()).unwrap_or(String::new())
97 }
98
get_url_field(buf: &[u8], pos: usize, size: u32, changes: &mut bool, value: &mut Option<Url>)99 pub fn get_url_field(buf: &[u8], pos: usize, size: u32, changes: &mut bool,
100 value: &mut Option<Url>) {
101 if value.is_some() || size < 2 {
102 return;
103 }
104 if *changes == false {
105 *changes = true;
106 }
107 let tmp_v = buf[pos..pos + size as usize].to_vec();
108 *value = Some(Url(String::from_utf8(tmp_v).unwrap_or(String::new())));
109 }
110
get_url_fields(buf: &[u8], pos: usize, size: u32, changes: &mut bool, value: &mut Vec<Url>)111 pub fn get_url_fields(buf: &[u8], pos: usize, size: u32, changes: &mut bool,
112 value: &mut Vec<Url>) {
113 let mut tmp = None;
114 get_url_field(buf, pos, size, changes, &mut tmp);
115 if let Some(tmp) = tmp {
116 value.push(tmp);
117 }
118 }
119
get_field(buf: &[u8], pos: usize, size: u32) -> String120 pub fn get_field(buf: &[u8], pos: usize, size: u32) -> String {
121 let buf = &buf[pos..][..size as usize];
122 if buf.len() < 1 {
123 String::new()
124 } else if buf[0] == 0 {
125 // ISO-8859-1
126 create_latin1_str(&buf[1..])
127 } else if buf[0] == 1 {
128 // UTF-16, requires a BOM
129 create_utf16_str(&buf[1..])
130 } else if buf[0] == 3 {
131 // UTF-8
132 create_utf8_str(&buf[1..])
133 } else {
134 String::new()
135 }
136 }
137
get_text_field(buf: &[u8], pos: usize, size: u32, changes: &mut bool, value: &mut Option<String>)138 pub fn get_text_field(buf: &[u8], pos: usize, size: u32, changes: &mut bool,
139 value: &mut Option<String>) {
140 if value.is_some() || size < 2 {
141 return;
142 }
143 if *changes == false {
144 *changes = true;
145 }
146 *value = Some(get_field(buf, pos, size));
147 }
148
get_text_fields(buf: &[u8], pos: usize, size: u32, changes: &mut bool, value: &mut Vec<String>)149 pub fn get_text_fields(buf: &[u8], pos: usize, size: u32, changes: &mut bool,
150 value: &mut Vec<String>) {
151 let tmp = get_field(buf, pos, size);
152 let tmp_v = tmp.split("/");
153 for entry in tmp_v {
154 if entry.len() > 0 {
155 value.push(entry.to_owned());
156 }
157 }
158 if *changes == false {
159 *changes = true;
160 }
161 }
162