Coverage Report

Created: 2026-03-20 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/avif-serialize-0.8.8/src/writer.rs
Line
Count
Source
1
use std::convert::TryFrom;
2
use std::io;
3
4
pub struct OOM;
5
6
pub trait WriterBackend {
7
    type Error;
8
    fn reserve(&mut self, size: usize) -> Result<(), Self::Error>;
9
    fn extend_from_slice_in_capacity(&mut self, data: &[u8]) -> Result<(), Self::Error>;
10
}
11
12
/// `io::Write` generates bloated code (with backtrace for every byte written),
13
/// so small boxes are written infallibly.
14
impl WriterBackend for Vec<u8> {
15
    type Error = OOM;
16
17
    #[inline]
18
0
    fn reserve(&mut self, size: usize) -> Result<(), Self::Error> {
19
0
        self.try_reserve(size).map_err(|_| OOM)
20
0
    }
21
22
    #[inline(always)]
23
0
    fn extend_from_slice_in_capacity(&mut self, data: &[u8]) -> Result<(), Self::Error> {
24
0
        let has_capacity = self.capacity() - self.len() >= data.len();
25
0
        debug_assert!(has_capacity);
26
0
        if has_capacity {
27
0
            self.extend_from_slice(data);
28
0
            Ok(())
29
        } else {
30
0
            Err(OOM)
31
        }
32
0
    }
33
}
34
35
pub struct IO<W>(pub W);
36
37
impl<W: io::Write> WriterBackend for IO<W> {
38
    type Error = io::Error;
39
40
    #[inline]
41
0
    fn reserve(&mut self, _size: usize) -> io::Result<()> {
42
0
        Ok(())
43
0
    }
44
45
    #[inline(always)]
46
0
    fn extend_from_slice_in_capacity(&mut self, data: &[u8]) -> io::Result<()> {
47
0
        self.0.write_all(data)
48
0
    }
49
}
50
51
pub struct Writer<'p, 'w, B> {
52
    out: &'w mut B,
53
    #[cfg(debug_assertions)]
54
    parent: Option<&'p mut usize>,
55
    #[cfg(not(debug_assertions))]
56
    parent: std::marker::PhantomData<&'p mut usize>,
57
    #[cfg(debug_assertions)]
58
    left: usize,
59
}
60
61
impl<'w, B> Writer<'static, 'w, B> {
62
    #[inline]
63
0
    pub fn new(out: &'w mut B) -> Self {
64
0
        Self {
65
0
            parent: Default::default(),
66
0
            #[cfg(debug_assertions)]
67
0
            left: 0,
68
0
            out,
69
0
        }
70
0
    }
71
}
72
73
impl<B: WriterBackend> Writer<'_, '_, B> {
74
    #[inline(always)]
75
0
    pub fn full_box(&mut self, len: usize, typ: [u8; 4], version: u8) -> Result<Writer<'_, '_, B>, B::Error> {
76
0
        let mut b = self.basic_box(len, typ)?;
77
0
        b.push(&[version, 0, 0, 0])?;
78
0
        Ok(b)
79
0
    }
80
81
    #[inline]
82
0
    pub fn basic_box(&mut self, len: usize, typ: [u8; 4]) -> Result<Writer<'_, '_, B>, B::Error> {
83
0
        let mut b = Writer {
84
0
            out: self.out,
85
0
            parent: Default::default(),
86
0
            #[cfg(debug_assertions)]
87
0
            left: len,
88
0
        };
89
        #[cfg(debug_assertions)]
90
        if self.left > 0 {
91
            self.left -= len;
92
            b.parent = Some(&mut self.left);
93
        } else {
94
            debug_assert!(self.parent.is_none());
95
        }
96
0
        b.out.reserve(len)?;
97
98
0
        if let Ok(len) = u32::try_from(len) {
99
0
            b.u32(len)?;
100
        } else {
101
0
            debug_assert!(false, "constants for box size don't include this");
102
0
            b.u32(1)?;
103
0
            b.u64(len as u64)?;
104
        }
105
0
        b.push(&typ)?;
106
0
        Ok(b)
107
0
    }
108
109
    #[inline(always)]
110
0
    pub fn push(&mut self, data: &[u8]) -> Result<(), B::Error> {
111
        #[cfg(debug_assertions)] {
112
            self.left -= data.len();
113
        }
114
0
        self.out.extend_from_slice_in_capacity(data)
115
0
    }
116
117
    #[inline(always)]
118
0
    pub fn u8(&mut self, val: u8) -> Result<(), B::Error> {
119
0
        self.push(std::slice::from_ref(&val))
120
0
    }
121
122
    #[inline(always)]
123
0
    pub fn u16(&mut self, val: u16) -> Result<(), B::Error> {
124
0
        self.push(&val.to_be_bytes())
125
0
    }
126
127
    #[inline(always)]
128
0
    pub fn u32(&mut self, val: u32) -> Result<(), B::Error> {
129
0
        self.push(&val.to_be_bytes())
130
0
    }
131
132
    #[inline(always)]
133
0
    pub fn u64(&mut self, val: u64) -> Result<(), B::Error> {
134
0
        self.push(&val.to_be_bytes())
135
0
    }
136
}
137
138
#[cfg(debug_assertions)]
139
impl<B> Drop for Writer<'_, '_, B> {
140
    fn drop(&mut self) {
141
        assert_eq!(self.left, 0);
142
    }
143
}