symphonia_metadata/id3v2/
unsync.rs

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// Symphonia
// Copyright (c) 2019-2022 The Project Symphonia Developers.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use std::io;

use symphonia_core::errors::Result;
use symphonia_core::io::{FiniteStream, ReadBytes};

pub fn read_syncsafe_leq32<B: ReadBytes>(reader: &mut B, bit_width: u8) -> Result<u32> {
    debug_assert!(bit_width <= 32);

    let mut result = 0u32;
    let mut bits_read = 0;

    while bits_read < bit_width {
        // Ensure bits_read never exceeds the bit width which will cause an overflow
        let next_read = (bit_width - bits_read).min(7);
        bits_read += next_read;
        // The mask should have of the bits below 2 ^ nex_read set to 1
        let mask = (1 << next_read) - 1;
        result |= u32::from(reader.read_u8()? & mask) << (bit_width - bits_read);
    }

    Ok(result)
}

pub fn decode_unsynchronisation(buf: &mut [u8]) -> &mut [u8] {
    let len = buf.len();
    let mut src = 0;
    let mut dst = 0;

    // Decode the unsynchronisation scheme in-place.
    while src < len - 1 {
        buf[dst] = buf[src];
        dst += 1;
        src += 1;

        if buf[src - 1] == 0xff && buf[src] == 0x00 {
            src += 1;
        }
    }

    if src < len {
        buf[dst] = buf[src];
        dst += 1;
    }

    &mut buf[..dst]
}

pub struct UnsyncStream<B: ReadBytes + FiniteStream> {
    inner: B,
    byte: u8,
}

impl<B: ReadBytes + FiniteStream> UnsyncStream<B> {
    pub fn new(inner: B) -> Self {
        UnsyncStream { inner, byte: 0 }
    }

    /// Convert the `UnsyncStream` to the inner stream.
    pub fn into_inner(self) -> B {
        self.inner
    }
}

impl<B: ReadBytes + FiniteStream> FiniteStream for UnsyncStream<B> {
    #[inline(always)]
    fn byte_len(&self) -> u64 {
        self.inner.byte_len()
    }

    #[inline(always)]
    fn bytes_read(&self) -> u64 {
        self.inner.bytes_read()
    }

    #[inline(always)]
    fn bytes_available(&self) -> u64 {
        self.inner.bytes_available()
    }
}

impl<B: ReadBytes + FiniteStream> ReadBytes for UnsyncStream<B> {
    fn read_byte(&mut self) -> io::Result<u8> {
        let last = self.byte;

        self.byte = self.inner.read_byte()?;

        // If the last byte was 0xff, and the current byte is 0x00, the current byte should be
        // dropped and the next byte read instead.
        if last == 0xff && self.byte == 0x00 {
            self.byte = self.inner.read_byte()?;
        }

        Ok(self.byte)
    }

    fn read_double_bytes(&mut self) -> io::Result<[u8; 2]> {
        Ok([self.read_byte()?, self.read_byte()?])
    }

    fn read_triple_bytes(&mut self) -> io::Result<[u8; 3]> {
        Ok([self.read_byte()?, self.read_byte()?, self.read_byte()?])
    }

    fn read_quad_bytes(&mut self) -> io::Result<[u8; 4]> {
        Ok([self.read_byte()?, self.read_byte()?, self.read_byte()?, self.read_byte()?])
    }

    fn read_buf(&mut self, _: &mut [u8]) -> io::Result<usize> {
        // Not required.
        unimplemented!();
    }

    fn read_buf_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
        let len = buf.len();

        if len > 0 {
            // Fill the provided buffer directly from the underlying reader.
            self.inner.read_buf_exact(buf)?;

            // If the last seen byte was 0xff, and the first byte in buf is 0x00, skip the first
            // byte of buf.
            let mut src = usize::from(self.byte == 0xff && buf[0] == 0x00);
            let mut dst = 0;

            // Record the last byte in buf to continue unsychronisation streaming later.
            self.byte = buf[len - 1];

            // Decode the unsynchronisation scheme in-place.
            while src < len - 1 {
                buf[dst] = buf[src];
                dst += 1;
                src += 1;

                if buf[src - 1] == 0xff && buf[src] == 0x00 {
                    src += 1;
                }
            }

            // When the final two src bytes are [ 0xff, 0x00 ], src will always equal len.
            // Therefore, if src < len, then the final byte should always be copied to dst.
            if src < len {
                buf[dst] = buf[src];
                dst += 1;
            }

            // If dst < len, then buf is not full. Read the remaining bytes manually to completely
            // fill buf.
            while dst < len {
                buf[dst] = self.read_byte()?;
                dst += 1;
            }
        }

        Ok(())
    }

    fn scan_bytes_aligned<'a>(
        &mut self,
        _: &[u8],
        _: usize,
        _: &'a mut [u8],
    ) -> io::Result<&'a mut [u8]> {
        // Not required.
        unimplemented!();
    }

    fn ignore_bytes(&mut self, count: u64) -> io::Result<()> {
        for _ in 0..count {
            self.inner.read_byte()?;
        }
        Ok(())
    }

    fn pos(&self) -> u64 {
        // Not required.
        unimplemented!();
    }
}

#[cfg(test)]
mod tests {
    use super::read_syncsafe_leq32;
    use symphonia_core::io::BufReader;

    #[test]
    fn verify_read_syncsafe_leq32() {
        let mut stream = BufReader::new(&[3, 4, 80, 1, 15]);
        assert_eq!(101875743, read_syncsafe_leq32(&mut stream, 32).unwrap());

        // Special case: for a bit depth that is not a multiple of 7 such as 32
        // we need to ensure the mask is correct.
        // In this case, the final iteration should read 4 bits and have a mask of 0b0000_1111.
        // 0b0000_1111 has a 0 in 16's place so testing mask & 16 will ensure this is working.
        let mut stream = BufReader::new(&[16, 16, 16, 16, 16]);
        assert_eq!(541098240, read_syncsafe_leq32(&mut stream, 32).unwrap());

        let mut stream = BufReader::new(&[3, 4, 80, 1]);
        assert_eq!(6367233, read_syncsafe_leq32(&mut stream, 28).unwrap());

        let mut stream = BufReader::new(&[3, 4, 80, 1]);
        assert_eq!(0, read_syncsafe_leq32(&mut stream, 0).unwrap());
    }
}