symphonia_metadata/id3v2/
unsync.rs

1// Symphonia
2// Copyright (c) 2019-2022 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8use std::io;
9
10use symphonia_core::errors::Result;
11use symphonia_core::io::{FiniteStream, ReadBytes};
12
13pub fn read_syncsafe_leq32<B: ReadBytes>(reader: &mut B, bit_width: u8) -> Result<u32> {
14    debug_assert!(bit_width <= 32);
15
16    let mut result = 0u32;
17    let mut bits_read = 0;
18
19    while bits_read < bit_width {
20        // Ensure bits_read never exceeds the bit width which will cause an overflow
21        let next_read = (bit_width - bits_read).min(7);
22        bits_read += next_read;
23        // The mask should have of the bits below 2 ^ nex_read set to 1
24        let mask = (1 << next_read) - 1;
25        result |= u32::from(reader.read_u8()? & mask) << (bit_width - bits_read);
26    }
27
28    Ok(result)
29}
30
31pub fn decode_unsynchronisation(buf: &mut [u8]) -> &mut [u8] {
32    let len = buf.len();
33    let mut src = 0;
34    let mut dst = 0;
35
36    // Decode the unsynchronisation scheme in-place.
37    while src < len - 1 {
38        buf[dst] = buf[src];
39        dst += 1;
40        src += 1;
41
42        if buf[src - 1] == 0xff && buf[src] == 0x00 {
43            src += 1;
44        }
45    }
46
47    if src < len {
48        buf[dst] = buf[src];
49        dst += 1;
50    }
51
52    &mut buf[..dst]
53}
54
55pub struct UnsyncStream<B: ReadBytes + FiniteStream> {
56    inner: B,
57    byte: u8,
58}
59
60impl<B: ReadBytes + FiniteStream> UnsyncStream<B> {
61    pub fn new(inner: B) -> Self {
62        UnsyncStream { inner, byte: 0 }
63    }
64
65    /// Convert the `UnsyncStream` to the inner stream.
66    pub fn into_inner(self) -> B {
67        self.inner
68    }
69}
70
71impl<B: ReadBytes + FiniteStream> FiniteStream for UnsyncStream<B> {
72    #[inline(always)]
73    fn byte_len(&self) -> u64 {
74        self.inner.byte_len()
75    }
76
77    #[inline(always)]
78    fn bytes_read(&self) -> u64 {
79        self.inner.bytes_read()
80    }
81
82    #[inline(always)]
83    fn bytes_available(&self) -> u64 {
84        self.inner.bytes_available()
85    }
86}
87
88impl<B: ReadBytes + FiniteStream> ReadBytes for UnsyncStream<B> {
89    fn read_byte(&mut self) -> io::Result<u8> {
90        let last = self.byte;
91
92        self.byte = self.inner.read_byte()?;
93
94        // If the last byte was 0xff, and the current byte is 0x00, the current byte should be
95        // dropped and the next byte read instead.
96        if last == 0xff && self.byte == 0x00 {
97            self.byte = self.inner.read_byte()?;
98        }
99
100        Ok(self.byte)
101    }
102
103    fn read_double_bytes(&mut self) -> io::Result<[u8; 2]> {
104        Ok([self.read_byte()?, self.read_byte()?])
105    }
106
107    fn read_triple_bytes(&mut self) -> io::Result<[u8; 3]> {
108        Ok([self.read_byte()?, self.read_byte()?, self.read_byte()?])
109    }
110
111    fn read_quad_bytes(&mut self) -> io::Result<[u8; 4]> {
112        Ok([self.read_byte()?, self.read_byte()?, self.read_byte()?, self.read_byte()?])
113    }
114
115    fn read_buf(&mut self, _: &mut [u8]) -> io::Result<usize> {
116        // Not required.
117        unimplemented!();
118    }
119
120    fn read_buf_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
121        let len = buf.len();
122
123        if len > 0 {
124            // Fill the provided buffer directly from the underlying reader.
125            self.inner.read_buf_exact(buf)?;
126
127            // If the last seen byte was 0xff, and the first byte in buf is 0x00, skip the first
128            // byte of buf.
129            let mut src = usize::from(self.byte == 0xff && buf[0] == 0x00);
130            let mut dst = 0;
131
132            // Record the last byte in buf to continue unsychronisation streaming later.
133            self.byte = buf[len - 1];
134
135            // Decode the unsynchronisation scheme in-place.
136            while src < len - 1 {
137                buf[dst] = buf[src];
138                dst += 1;
139                src += 1;
140
141                if buf[src - 1] == 0xff && buf[src] == 0x00 {
142                    src += 1;
143                }
144            }
145
146            // When the final two src bytes are [ 0xff, 0x00 ], src will always equal len.
147            // Therefore, if src < len, then the final byte should always be copied to dst.
148            if src < len {
149                buf[dst] = buf[src];
150                dst += 1;
151            }
152
153            // If dst < len, then buf is not full. Read the remaining bytes manually to completely
154            // fill buf.
155            while dst < len {
156                buf[dst] = self.read_byte()?;
157                dst += 1;
158            }
159        }
160
161        Ok(())
162    }
163
164    fn scan_bytes_aligned<'a>(
165        &mut self,
166        _: &[u8],
167        _: usize,
168        _: &'a mut [u8],
169    ) -> io::Result<&'a mut [u8]> {
170        // Not required.
171        unimplemented!();
172    }
173
174    fn ignore_bytes(&mut self, count: u64) -> io::Result<()> {
175        for _ in 0..count {
176            self.inner.read_byte()?;
177        }
178        Ok(())
179    }
180
181    fn pos(&self) -> u64 {
182        // Not required.
183        unimplemented!();
184    }
185}
186
187#[cfg(test)]
188mod tests {
189    use super::read_syncsafe_leq32;
190    use symphonia_core::io::BufReader;
191
192    #[test]
193    fn verify_read_syncsafe_leq32() {
194        let mut stream = BufReader::new(&[3, 4, 80, 1, 15]);
195        assert_eq!(101875743, read_syncsafe_leq32(&mut stream, 32).unwrap());
196
197        // Special case: for a bit depth that is not a multiple of 7 such as 32
198        // we need to ensure the mask is correct.
199        // In this case, the final iteration should read 4 bits and have a mask of 0b0000_1111.
200        // 0b0000_1111 has a 0 in 16's place so testing mask & 16 will ensure this is working.
201        let mut stream = BufReader::new(&[16, 16, 16, 16, 16]);
202        assert_eq!(541098240, read_syncsafe_leq32(&mut stream, 32).unwrap());
203
204        let mut stream = BufReader::new(&[3, 4, 80, 1]);
205        assert_eq!(6367233, read_syncsafe_leq32(&mut stream, 28).unwrap());
206
207        let mut stream = BufReader::new(&[3, 4, 80, 1]);
208        assert_eq!(0, read_syncsafe_leq32(&mut stream, 0).unwrap());
209    }
210}