1use alloc::vec::Vec;
2#[cfg(feature = "std")]
3use std::{io, mem};
4
5use crate::pod::{bytes_of, bytes_of_slice, Pod};
6
7#[allow(clippy::len_without_is_empty)]
9pub trait WritableBuffer {
10 fn len(&self) -> usize;
14
15 fn reserve(&mut self, size: usize) -> Result<(), ()>;
20
21 fn resize(&mut self, new_len: usize);
24
25 fn write_bytes(&mut self, val: &[u8]);
27
28 fn write_pod<T: Pod>(&mut self, val: &T)
30 where
31 Self: Sized,
32 {
33 self.write_bytes(bytes_of(val))
34 }
35
36 fn write_pod_slice<T: Pod>(&mut self, val: &[T])
38 where
39 Self: Sized,
40 {
41 self.write_bytes(bytes_of_slice(val))
42 }
43}
44
45impl<'a> dyn WritableBuffer + 'a {
46 pub fn write<T: Pod>(&mut self, val: &T) {
48 self.write_bytes(bytes_of(val))
49 }
50
51 pub fn write_slice<T: Pod>(&mut self, val: &[T]) {
53 self.write_bytes(bytes_of_slice(val))
54 }
55}
56
57impl WritableBuffer for Vec<u8> {
58 #[inline]
59 fn len(&self) -> usize {
60 self.len()
61 }
62
63 #[inline]
64 fn reserve(&mut self, size: usize) -> Result<(), ()> {
65 debug_assert!(self.is_empty());
66 self.reserve(size);
67 Ok(())
68 }
69
70 #[inline]
71 fn resize(&mut self, new_len: usize) {
72 debug_assert!(new_len >= self.len());
73 self.resize(new_len, 0);
74 }
75
76 #[inline]
77 fn write_bytes(&mut self, val: &[u8]) {
78 debug_assert!(self.len() + val.len() <= self.capacity());
79 self.extend_from_slice(val)
80 }
81}
82
83#[cfg(feature = "std")]
91#[derive(Debug)]
92pub struct StreamingBuffer<W> {
93 writer: W,
94 len: usize,
95 result: Result<(), io::Error>,
96}
97
98#[cfg(feature = "std")]
99impl<W> StreamingBuffer<W> {
100 pub fn new(writer: W) -> Self {
102 StreamingBuffer {
103 writer,
104 len: 0,
105 result: Ok(()),
106 }
107 }
108
109 pub fn into_inner(self) -> W {
111 self.writer
112 }
113
114 pub fn result(&mut self) -> Result<(), io::Error> {
116 mem::replace(&mut self.result, Ok(()))
117 }
118}
119
120#[cfg(feature = "std")]
121impl<W: io::Write> StreamingBuffer<W> {
122 pub fn flush(&mut self) -> Result<(), io::Error> {
124 self.result()?;
125 self.writer.flush()
126 }
127}
128
129#[cfg(feature = "std")]
130impl<W: io::Write> WritableBuffer for StreamingBuffer<W> {
131 #[inline]
132 fn len(&self) -> usize {
133 self.len
134 }
135
136 #[inline]
137 fn reserve(&mut self, _size: usize) -> Result<(), ()> {
138 Ok(())
139 }
140
141 #[inline]
142 fn resize(&mut self, new_len: usize) {
143 debug_assert!(self.len <= new_len);
144 while self.len < new_len {
145 let write_amt = (new_len - self.len - 1) % 1024 + 1;
146 self.write_bytes(&[0; 1024][..write_amt]);
147 }
148 }
149
150 #[inline]
151 fn write_bytes(&mut self, val: &[u8]) {
152 if self.result.is_ok() {
153 self.result = self.writer.write_all(val);
154 }
155 self.len += val.len();
156 }
157}
158
159pub(crate) trait BytesMut {
163 fn write_at<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()>;
164}
165
166impl<'a> BytesMut for &'a mut [u8] {
167 #[inline]
168 fn write_at<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()> {
169 let src = bytes_of(val);
170 let dest = self.get_mut(offset..).ok_or(())?;
171 let dest = dest.get_mut(..src.len()).ok_or(())?;
172 dest.copy_from_slice(src);
173 Ok(())
174 }
175}
176
177#[allow(dead_code)]
181pub(crate) fn write_uleb128(buf: &mut Vec<u8>, mut val: u64) -> usize {
182 let mut len = 0;
183 loop {
184 let mut byte = (val & 0x7f) as u8;
185 val >>= 7;
186 let done = val == 0;
187 if !done {
188 byte |= 0x80;
189 }
190
191 buf.push(byte);
192 len += 1;
193
194 if done {
195 return len;
196 }
197 }
198}
199
200#[allow(dead_code)]
204pub(crate) fn write_sleb128(buf: &mut Vec<u8>, mut val: i64) -> usize {
205 let mut len = 0;
206 loop {
207 let mut byte = val as u8;
208 val >>= 6;
210 let done = val == 0 || val == -1;
211 if done {
212 byte &= !0x80;
213 } else {
214 val >>= 1;
216 byte |= 0x80;
217 }
218
219 buf.push(byte);
220 len += 1;
221
222 if done {
223 return len;
224 }
225 }
226}
227
228pub(crate) fn align(offset: usize, size: usize) -> usize {
229 (offset + (size - 1)) & !(size - 1)
230}
231
232#[allow(dead_code)]
233pub(crate) fn align_u32(offset: u32, size: u32) -> u32 {
234 (offset + (size - 1)) & !(size - 1)
235}
236
237#[allow(dead_code)]
238pub(crate) fn align_u64(offset: u64, size: u64) -> u64 {
239 (offset + (size - 1)) & !(size - 1)
240}
241
242pub(crate) fn write_align(buffer: &mut dyn WritableBuffer, size: usize) {
243 let new_len = align(buffer.len(), size);
244 buffer.resize(new_len);
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[test]
252 fn bytes_mut() {
253 let data = vec![0x01, 0x23, 0x45, 0x67];
254
255 let mut bytes = data.clone();
256 bytes.extend_from_slice(bytes_of(&u16::to_be(0x89ab)));
257 assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]);
258
259 let mut bytes = data.clone();
260 assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(()));
261 assert_eq!(bytes, [0x89, 0xab, 0x45, 0x67]);
262
263 let mut bytes = data.clone();
264 assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(()));
265 assert_eq!(bytes, [0x01, 0x23, 0x89, 0xab]);
266
267 assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(()));
268 assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(()));
269 assert_eq!([].write_at(0, &u32::to_be(0x89ab)), Err(()));
270 }
271}