id3/stream/
unsynch.rs

1//! The only purpose of unsynchronisation is to make the ID3v2 tag as compatible as possible with
2//! existing software and hardware. There is no use in 'unsynchronising' tags if the file is only
3//! to be processed only by ID3v2 aware software and hardware. Unsynchronisation is only useful
4//! with tags in MPEG 1/2 layer I, II and III, MPEG 2.5 and AAC files.
5use std::io;
6
7/// Returns the synchsafe variant of a `u32` value.
8pub fn encode_u32(n: u32) -> u32 {
9    assert!(n < 0x1000_0000);
10    let mut x: u32 = n & 0x7F | (n & 0xFFFF_FF80) << 1;
11    x = x & 0x7FFF | (x & 0xFFFF_8000) << 1;
12    x = x & 0x7F_FFFF | (x & 0xFF80_0000) << 1;
13    x
14}
15
16/// Returns the unsynchsafe varaiant of a `u32` value.
17pub fn decode_u32(n: u32) -> u32 {
18    n & 0xFF | (n & 0xFF00) >> 1 | (n & 0xFF_0000) >> 2 | (n & 0xFF00_0000) >> 3
19}
20
21/// Decoder for an unsynchronized stream of bytes.
22///
23/// The decoder has an internal buffer.
24pub struct Reader<R>
25where
26    R: io::Read,
27{
28    reader: R,
29    buf: [u8; 8192],
30    next: usize,
31    available: usize,
32    discard_next_null_byte: bool,
33}
34
35impl<R> Reader<R>
36where
37    R: io::Read,
38{
39    pub fn new(reader: R) -> Reader<R> {
40        Reader {
41            reader,
42            buf: [0; 8192],
43            next: 0,
44            available: 0,
45            discard_next_null_byte: false,
46        }
47    }
48}
49
50impl<R> io::Read for Reader<R>
51where
52    R: io::Read,
53{
54    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
55        let mut i = 0;
56
57        while i < buf.len() {
58            assert!(self.next <= self.available);
59            if self.next == self.available {
60                self.available = self.reader.read(&mut self.buf)?;
61                self.next = 0;
62                if self.available == 0 {
63                    break;
64                }
65            }
66
67            if self.discard_next_null_byte && self.buf[self.next] == 0x00 {
68                self.discard_next_null_byte = false;
69                self.next += 1;
70                continue;
71            }
72            self.discard_next_null_byte = false;
73
74            buf[i] = self.buf[self.next];
75            i += 1;
76
77            if self.buf[self.next] == 0xff {
78                self.discard_next_null_byte = true;
79            }
80            self.next += 1;
81        }
82
83        Ok(i)
84    }
85}
86
87/// Applies the unsynchronization scheme to a byte buffer.
88pub fn encode_vec(buffer: &mut Vec<u8>) {
89    let mut repeat_next_null_byte = false;
90    let mut i = 0;
91    while i < buffer.len() {
92        if buffer[i] == 0x00 && repeat_next_null_byte {
93            buffer.insert(i, 0);
94            i += 1;
95        }
96        repeat_next_null_byte = buffer[i] == 0xFF;
97        i += 1;
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use std::mem;
105
106    fn decode_vec(buffer: &mut Vec<u8>) {
107        let buf_len = buffer.len();
108        let from_buf = mem::replace(buffer, Vec::with_capacity(buf_len));
109        let mut reader = Reader::new(io::Cursor::new(from_buf));
110        io::copy(&mut reader, buffer).unwrap();
111    }
112
113    #[test]
114    fn synchsafe() {
115        for i in 0..1 << 26 {
116            assert_eq!(i, decode_u32(encode_u32(i)));
117        }
118        assert_eq!(0x7f7f7f7f, encode_u32(0x0fff_ffff));
119        assert_eq!(0x0fff_ffff, decode_u32(0x7f7f7f7f));
120    }
121
122    #[test]
123    fn synchronization() {
124        let mut v = vec![66, 0, 255, 0, 255, 0, 0, 255, 66];
125        encode_vec(&mut v);
126        assert_eq!(v, [66, 0, 255, 0, 0, 255, 0, 0, 0, 255, 66]);
127        decode_vec(&mut v);
128        assert_eq!(v, [66, 0, 255, 0, 255, 0, 0, 255, 66]);
129    }
130
131    #[test]
132    fn synchronization_jpeg() {
133        let orig = vec![
134            0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x02,
135            0x00, 0x76,
136        ];
137        let mut recoded = orig.clone();
138        encode_vec(&mut recoded);
139        decode_vec(&mut recoded);
140        assert_eq!(orig, recoded);
141    }
142
143    #[test]
144    fn synchronization_large() {
145        let mut orig = Vec::new();
146        for i in 0..1_000_000 {
147            orig.push(0xff);
148            orig.push(i as u8);
149        }
150
151        let mut recoded = orig.clone();
152        encode_vec(&mut recoded);
153        decode_vec(&mut recoded);
154        assert_eq!(orig, recoded);
155    }
156}