Skip to main content

mp4_atom/
buf.rs

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