Skip to main content

mp4_atom/
buf.rs

1use std::io::Cursor;
2
3/// A contiguous buffer of bytes.
4// We're not using bytes::Buf because of some strange bugs with take().
5pub trait Buf {
6    fn remaining(&self) -> usize;
7    fn has_remaining(&self) -> bool {
8        self.remaining() > 0
9    }
10
11    fn slice(&self, size: usize) -> &[u8];
12    fn advance(&mut self, n: usize);
13}
14
15impl Buf for &[u8] {
16    fn remaining(&self) -> usize {
17        self.len()
18    }
19
20    fn slice(&self, size: usize) -> &[u8] {
21        self[..size].as_ref()
22    }
23
24    fn advance(&mut self, n: usize) {
25        *self = &self[n..];
26    }
27}
28
29impl<T: AsRef<[u8]>> Buf for Cursor<T> {
30    fn remaining(&self) -> usize {
31        self.get_ref().as_ref().len() - self.position() as usize
32    }
33
34    fn slice(&self, size: usize) -> &[u8] {
35        let pos = self.position() as usize;
36        self.get_ref().as_ref()[pos..pos + size].as_ref()
37    }
38
39    fn advance(&mut self, n: usize) {
40        self.set_position(self.position() + n as u64);
41    }
42}
43
44impl<T: Buf + ?Sized> Buf for &mut T {
45    fn remaining(&self) -> usize {
46        (**self).remaining()
47    }
48
49    fn slice(&self, size: usize) -> &[u8] {
50        (**self).slice(size)
51    }
52
53    fn advance(&mut self, n: usize) {
54        (**self).advance(n);
55    }
56}
57
58/// Drain trailing padding left after an atom's child boxes.
59///
60/// Some muxers — QuickTime in particular — append a few bytes (commonly a
61/// 4-byte zero "terminator") after the last child box of a container atom or
62/// sample entry. Such a remainder is shorter than a box header (8 bytes), so it
63/// cannot be a box and can only be padding: drain it instead of failing the
64/// whole atom with [`Error::UnderDecode`](crate::Error::UnderDecode), matching
65/// ffmpeg, GPAC and other demuxers. A remainder of 8 or more bytes is left
66/// untouched so genuine trailing corruption is still reported.
67pub(crate) fn skip_trailing_padding<B: Buf>(buf: &mut B) {
68    let n = buf.remaining();
69    if n > 0 && n < 8 {
70        buf.advance(n);
71    }
72}
73
74#[cfg(feature = "bytes")]
75impl Buf for bytes::Bytes {
76    fn remaining(&self) -> usize {
77        self.len()
78    }
79
80    fn slice(&self, size: usize) -> &[u8] {
81        &self[..size]
82    }
83
84    fn advance(&mut self, n: usize) {
85        bytes::Buf::advance(self, n);
86    }
87}
88
89/// A mutable contiguous buffer of bytes.
90// We're not using bytes::BufMut because it doesn't allow seeking backwards (to set the size).
91pub trait BufMut {
92    // Returns the current length.
93    fn len(&self) -> usize;
94
95    fn is_empty(&self) -> bool {
96        self.len() == 0
97    }
98
99    // Append a slice to the buffer
100    fn append_slice(&mut self, val: &[u8]);
101
102    // Set a slice at a position in the buffer.
103    fn set_slice(&mut self, pos: usize, val: &[u8]);
104}
105
106impl BufMut for Vec<u8> {
107    fn len(&self) -> usize {
108        self.len()
109    }
110
111    fn append_slice(&mut self, v: &[u8]) {
112        self.extend_from_slice(v);
113    }
114
115    fn set_slice(&mut self, pos: usize, val: &[u8]) {
116        self[pos..pos + val.len()].copy_from_slice(val);
117    }
118}
119
120impl<T: BufMut + ?Sized> BufMut for &mut T {
121    fn len(&self) -> usize {
122        (**self).len()
123    }
124
125    fn append_slice(&mut self, v: &[u8]) {
126        (**self).append_slice(v);
127    }
128
129    fn set_slice(&mut self, pos: usize, val: &[u8]) {
130        (**self).set_slice(pos, val);
131    }
132}
133
134#[cfg(feature = "bytes")]
135impl BufMut for bytes::BytesMut {
136    fn len(&self) -> usize {
137        self.len()
138    }
139
140    fn append_slice(&mut self, v: &[u8]) {
141        self.extend_from_slice(v);
142    }
143
144    fn set_slice(&mut self, pos: usize, val: &[u8]) {
145        self[pos..pos + val.len()].copy_from_slice(val);
146    }
147}