slice_codec/buffer/
vec.rs1use super::*;
6use crate::{Error, ErrorKind, Result};
7use alloc::vec::Vec;
8use core::mem::MaybeUninit;
9use core::{debug_assert, debug_assert_eq};
10
11#[derive(Debug)]
15pub struct VecOutputTarget<'a> {
16 buffer: &'a mut Vec<u8>,
18}
19
20impl<'a> VecOutputTarget<'a> {
21 fn ensure_buffer_has_at_least(&mut self, requested: usize) -> Result<()> {
31 self.buffer.try_reserve(requested).map_err(|_err| {
33 let remaining = self.remaining();
35 let kind = ErrorKind::UnexpectedEob { requested, remaining };
36 Error::new_with_source(kind, _err)
37 })
38 }
39}
40
41impl OutputTarget for VecOutputTarget<'_> {
42 fn remaining(&self) -> usize {
43 self.buffer.capacity() - self.buffer.len()
44 }
45
46 fn write_byte(&mut self, byte: u8) -> Result<()> {
47 self.ensure_buffer_has_at_least(1)?;
48
49 unsafe {
51 debug_assert!(self.buffer.spare_capacity_mut().get_mut(0).is_some());
52 let target = self.buffer.spare_capacity_mut().get_unchecked_mut(0);
53 target.write(byte);
54
55 let old_length = self.buffer.len();
56 self.buffer.set_len(old_length + 1);
57 Ok(())
58 }
59 }
60
61 fn write_bytes_exact(&mut self, bytes: &[u8]) -> Result<()> {
62 let count = bytes.len();
63 self.ensure_buffer_has_at_least(count)?;
64
65 unsafe {
68 debug_assert!(self.buffer.spare_capacity_mut().get_mut(..count).is_some());
69 let target_slice = self.buffer.spare_capacity_mut().get_unchecked_mut(..count);
70
71 debug_assert_eq!(target_slice.len(), count);
72 let source: &[MaybeUninit<u8>] = core::mem::transmute(bytes);
74
75 core::ptr::copy_nonoverlapping(source.as_ptr(), target_slice.as_mut_ptr(), count);
76
77 let old_length = self.buffer.len();
78 self.buffer.set_len(old_length + count);
79 Ok(())
80 }
81 }
82
83 fn write_bytes_into_reserved_exact(&mut self, reservation: &mut Reservation, bytes: &[u8]) -> Result<()> {
84 let Some(reserved_slice) = self.buffer.get_mut(reservation.range()) else {
86 let error = ErrorKind::InvalidReservation {
87 buffer_len: self.buffer.len(),
88 reserved_range: reservation.range(),
89 };
90 return Err(error.into());
91 };
92
93 if reserved_slice.len() < bytes.len() {
95 let error = ErrorKind::UnexpectedEob {
96 requested: bytes.len(),
97 remaining: reserved_slice.len(),
98 };
99 return Err(error.into());
100 }
101
102 unsafe {
105 core::ptr::copy_nonoverlapping(bytes.as_ptr(), reserved_slice.as_mut_ptr(), bytes.len());
106 reservation.0.start += bytes.len();
107 Ok(())
108 }
109 }
110
111 fn reserve_space(&mut self, count: usize) -> Result<Reservation> {
112 self.ensure_buffer_has_at_least(count)?;
113
114 unsafe {
117 let pos = self.buffer.len();
118 let end = pos + count;
119 debug_assert!(self.buffer.spare_capacity_mut().get(..count).is_some());
120 let target_offset = self.buffer.as_mut_ptr().add(pos);
121
122 core::ptr::write_bytes(target_offset, 0, count);
125 self.buffer.set_len(end);
126
127 Ok(Reservation(pos..end))
128 }
129 }
130}
131
132impl<'a> From<&'a mut Vec<u8>> for VecOutputTarget<'a> {
133 fn from(value: &'a mut Vec<u8>) -> Self {
135 Self { buffer: value }
136 }
137}
138
139impl<'a, T> From<T> for crate::encoder::Encoder<VecOutputTarget<'a>>
142where
143 T: Into<VecOutputTarget<'a>>,
144{
145 fn from(value: T) -> Self {
146 crate::encoder::Encoder::new(value.into())
147 }
148}
149
150#[cfg(test)]
151#[cfg(feature = "alloc")]
152mod tests {
153 use super::*;
154 use alloc::vec;
155
156 #[test]
159 fn ensure_buffer_has_at_least_returns_ok() {
160 let mut buffer = vec![115, 108, 105, 99, 101];
162 let mut target = VecOutputTarget::from(&mut buffer);
163
164 let result = target.ensure_buffer_has_at_least(5);
166
167 assert!(result.is_ok());
169 }
170
171 #[test]
174 #[ignore = "TODO: See https://github.com/icerpc/slice-rust/issues/3"]
175 fn ensure_buffer_has_at_least_returns_error() {}
176
177 #[test]
179 fn write_byte_writes_correct_byte() {
180 let mut buffer = Vec::new();
182 let mut target = VecOutputTarget::from(&mut buffer);
183
184 let result = target.write_byte(115);
186
187 assert!(result.is_ok());
189 assert_eq!(target.buffer, &[115]);
190 assert_eq!(target.remaining(), buffer.capacity() - 1);
191 }
192
193 #[test]
195 fn write_bytes_exact_writes_correct_bytes() {
196 let mut buffer = Vec::new();
198 let mut target = VecOutputTarget::from(&mut buffer);
199
200 let result = target.write_bytes_exact(&[115, 108, 105, 99, 101]);
202
203 assert!(result.is_ok());
205 assert_eq!(target.buffer, &[115, 108, 105, 99, 101]);
206 assert_eq!(target.buffer.len(), 5);
207 assert_eq!(target.remaining(), target.buffer.capacity() - 5);
208 }
209
210 #[test]
214 fn reserve_space_reserves_correct_space() {
215 let mut buffer = Vec::new();
217 let mut target = VecOutputTarget::from(&mut buffer);
218
219 let reserve_result = target.reserve_space(3);
221 let write_result = target.write_byte(99);
222
223 assert!(reserve_result.is_ok());
225 assert!(write_result.is_ok());
226
227 assert_eq!(reserve_result.unwrap().range(), 0..3);
228 assert_eq!(target.buffer.len(), 4);
229 assert_eq!(target.remaining(), target.buffer.capacity() - 4);
230 assert_eq!(buffer, [0, 0, 0, 99]);
231 }
232
233 #[test]
236 fn write_bytes_into_reserved_exact_writes_correct_bytes() {
237 let mut buffer = Vec::new();
239 let mut target = VecOutputTarget::from(&mut buffer);
240
241 let mut reservation = target.reserve_space(3).unwrap();
243
244 let _ = target.write_bytes_exact(&[99]);
246
247 let result = target.write_bytes_into_reserved_exact(&mut reservation, &[115, 108, 105]);
249
250 let _ = target.write_byte(101);
252
253 assert!(result.is_ok());
255 assert_eq!(target.buffer, &[115, 108, 105, 99, 101]);
256 assert_eq!(target.buffer.len(), 5);
257 assert_eq!(target.remaining(), target.buffer.capacity() - 5);
258 }
259}