1use core::fmt;
5use core::mem::{self, MaybeUninit};
6use core::ops::{Deref, DerefMut};
7use core::ptr;
8use core::slice;
9
10use musli::{Buf, Context};
11
12use crate::writer::Writer;
13
14pub struct FixedBytes<const N: usize> {
16 data: [MaybeUninit<u8>; N],
18 init: usize,
20}
21
22impl<const N: usize> FixedBytes<N> {
23 #[inline]
25 pub const fn new() -> Self {
26 Self {
27 data: unsafe { MaybeUninit::<[MaybeUninit<u8>; N]>::uninit().assume_init() },
29 init: 0,
30 }
31 }
32
33 pub fn with_capacity(capacity: usize) -> Self {
35 assert!(
36 capacity < N,
37 "Requested capacity {capacity} is larger than {N}"
38 );
39 Self::new()
40 }
41
42 #[inline]
44 pub const fn len(&self) -> usize {
45 self.init
46 }
47
48 #[inline]
50 pub const fn is_empty(&self) -> bool {
51 self.init == 0
52 }
53
54 #[inline]
56 pub fn clear(&mut self) {
57 self.init = 0;
58 }
59
60 #[inline]
62 pub const fn remaining(&self) -> usize {
63 N.saturating_sub(self.init)
64 }
65
66 #[inline]
68 pub fn into_bytes(self) -> Option<[u8; N]> {
69 if self.init == N {
70 unsafe { Some((&self.data as *const _ as *const [u8; N]).read()) }
76 } else {
77 None
78 }
79 }
80
81 #[inline]
83 pub fn as_slice(&self) -> &[u8] {
84 if self.init == 0 {
85 return &[];
86 }
87
88 unsafe { core::slice::from_raw_parts(self.data.as_ptr().cast(), self.init) }
91 }
92
93 #[inline]
95 pub fn as_mut_slice(&mut self) -> &mut [u8] {
96 if self.init == 0 {
97 return &mut [];
98 }
99
100 unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().cast(), self.init) }
103 }
104
105 #[inline]
107 pub fn push(&mut self, value: u8) -> bool {
108 if N.saturating_sub(self.init) == 0 {
109 return false;
110 }
111
112 unsafe {
113 self.data
114 .as_mut_ptr()
115 .cast::<u8>()
116 .add(self.init)
117 .write(value)
118 }
119
120 self.init += 1;
121 true
122 }
123
124 #[inline]
126 pub fn extend_from_slice(&mut self, source: &[u8]) -> bool {
127 if source.len() > N.saturating_sub(self.init) {
128 return false;
129 }
130
131 unsafe {
132 let dst = (self.data.as_mut_ptr() as *mut u8).add(self.init);
133 ptr::copy_nonoverlapping(source.as_ptr(), dst, source.len());
134 }
135
136 self.init = self.init.wrapping_add(source.len());
137 true
138 }
139
140 #[inline]
142 pub fn write_bytes<C>(&mut self, cx: &C, source: &[u8]) -> Result<(), C::Error>
143 where
144 C: ?Sized + Context,
145 {
146 if !self.extend_from_slice(source) {
147 return Err(cx.message(FixedBytesOverflow {
148 at: self.init,
149 additional: source.len(),
150 capacity: N,
151 }));
152 }
153
154 Ok(())
155 }
156}
157
158impl<const N: usize> Deref for FixedBytes<N> {
159 type Target = [u8];
160
161 #[inline]
162 fn deref(&self) -> &Self::Target {
163 self.as_slice()
164 }
165}
166
167impl<const N: usize> DerefMut for FixedBytes<N> {
168 #[inline]
169 fn deref_mut(&mut self) -> &mut Self::Target {
170 self.as_mut_slice()
171 }
172}
173
174impl<const N: usize> Default for FixedBytes<N> {
175 #[inline]
176 fn default() -> Self {
177 Self::new()
178 }
179}
180
181impl<const N: usize> Writer for FixedBytes<N> {
182 type Mut<'this> = &'this mut Self where Self: 'this;
183
184 #[inline]
185 fn borrow_mut(&mut self) -> Self::Mut<'_> {
186 self
187 }
188
189 #[inline]
190 fn write_buffer<C, B>(&mut self, cx: &C, buffer: B) -> Result<(), C::Error>
191 where
192 C: ?Sized + Context,
193 B: Buf,
194 {
195 self.write_bytes(cx, buffer.as_slice())
197 }
198
199 #[inline]
200 fn write_bytes<C>(&mut self, cx: &C, bytes: &[u8]) -> Result<(), C::Error>
201 where
202 C: ?Sized + Context,
203 {
204 FixedBytes::write_bytes(self, cx, bytes)?;
205 cx.advance(bytes.len());
206 Ok(())
207 }
208}
209
210#[derive(Debug)]
213#[allow(missing_docs)]
214#[non_exhaustive]
215pub(crate) struct FixedBytesOverflow {
216 at: usize,
217 additional: usize,
218 capacity: usize,
219}
220
221impl fmt::Display for FixedBytesOverflow {
222 #[inline]
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 let FixedBytesOverflow {
225 at,
226 additional,
227 capacity,
228 } = self;
229
230 write!(
231 f,
232 "Tried to write {additional} bytes at {at} with capacity {capacity}"
233 )
234 }
235}
236
237#[non_exhaustive]
239pub(crate) struct CapacityError;
240
241pub(crate) struct FixedVec<T, const N: usize> {
243 data: [MaybeUninit<T>; N],
244 len: usize,
245}
246
247impl<T, const N: usize> FixedVec<T, N> {
248 pub(crate) const fn new() -> FixedVec<T, N> {
250 unsafe {
251 FixedVec {
252 data: MaybeUninit::uninit().assume_init(),
253 len: 0,
254 }
255 }
256 }
257
258 #[inline]
259 pub(crate) fn as_ptr(&self) -> *const T {
260 self.data.as_ptr() as *const T
261 }
262
263 #[inline]
264 pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
265 self.data.as_mut_ptr() as *mut T
266 }
267
268 #[inline]
269 pub(crate) fn as_slice(&self) -> &[T] {
270 unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
271 }
272
273 #[inline]
274 pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
275 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
276 }
277
278 pub(crate) fn try_push(&mut self, element: T) -> Result<(), CapacityError> {
280 if self.len >= N {
281 return Err(CapacityError);
282 }
283
284 unsafe {
285 ptr::write(self.as_mut_ptr().wrapping_add(self.len), element);
286 self.len += 1;
287 }
288
289 Ok(())
290 }
291
292 pub(crate) fn pop(&mut self) -> Option<T> {
294 if self.len == 0 {
295 return None;
296 }
297
298 unsafe {
299 let new_len = self.len - 1;
300 self.len = new_len;
301 Some(ptr::read(self.as_ptr().wrapping_add(new_len)))
302 }
303 }
304
305 pub(crate) fn clear(&mut self) {
306 if self.len == 0 {
307 return;
308 }
309
310 let len = mem::take(&mut self.len);
311
312 if mem::needs_drop::<T>() {
313 unsafe {
314 let tail = slice::from_raw_parts_mut(self.as_mut_ptr(), len);
315 ptr::drop_in_place(tail);
316 }
317 }
318 }
319}
320
321impl<T, const N: usize> Deref for FixedVec<T, N> {
322 type Target = [T];
323
324 #[inline]
325 fn deref(&self) -> &Self::Target {
326 self.as_slice()
327 }
328}
329
330impl<T, const N: usize> DerefMut for FixedVec<T, N> {
331 #[inline]
332 fn deref_mut(&mut self) -> &mut Self::Target {
333 self.as_mut_slice()
334 }
335}
336
337impl<T, const N: usize> Drop for FixedVec<T, N> {
338 #[inline]
339 fn drop(&mut self) {
340 self.clear()
341 }
342}