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