musli_binary_common/
fixed_bytes.rs1use core::fmt;
5use core::marker;
6use core::mem::MaybeUninit;
7use core::ptr;
8
9use musli::error::Error;
10
11use crate::writer::Writer;
12
13pub struct FixedBytes<const N: usize, E = FixedBytesWriterError> {
15 data: [MaybeUninit<u8>; N],
17 init: usize,
19 _marker: marker::PhantomData<E>,
21}
22
23impl<const N: usize, E> FixedBytes<N, E> {
24 pub const fn new() -> Self {
26 Self {
27 data: unsafe { MaybeUninit::<[MaybeUninit<u8>; N]>::uninit().assume_init() },
29 init: 0,
30 _marker: marker::PhantomData,
31 }
32 }
33
34 pub const fn len(&self) -> usize {
36 self.init
37 }
38
39 pub fn into_bytes(self) -> Option<[u8; N]> {
41 if self.init == N {
42 unsafe { Some((&self.data as *const _ as *const [u8; N]).read()) }
48 } else {
49 None
50 }
51 }
52
53 pub fn as_bytes(&self) -> &[u8] {
55 if self.init == 0 {
56 return &[];
57 }
58
59 unsafe { core::slice::from_raw_parts(self.data.as_ptr() as *const u8, self.init) }
62 }
63}
64
65decl_message_repr!(FixedBytesWriterErrorRepr, "failed to write to fixed bytes");
66
67#[derive(Debug)]
69pub struct FixedBytesWriterError(FixedBytesWriterErrorRepr);
70
71impl fmt::Display for FixedBytesWriterError {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 self.0.fmt(f)
74 }
75}
76
77impl Error for FixedBytesWriterError {
78 #[inline]
79 fn custom<T>(message: T) -> Self
80 where
81 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
82 {
83 Self(FixedBytesWriterErrorRepr::collect(message))
84 }
85
86 #[inline]
87 fn message<T>(message: T) -> Self
88 where
89 T: fmt::Display,
90 {
91 Self(FixedBytesWriterErrorRepr::collect(message))
92 }
93}
94
95#[cfg(feature = "std")]
96impl std::error::Error for FixedBytesWriterError {}
97
98impl<const N: usize, E> Writer for FixedBytes<N, E>
99where
100 E: Error,
101{
102 type Error = E;
103
104 #[inline]
105 fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
106 if bytes.len() > N.saturating_sub(self.init) {
107 return Err(E::message(BufferOverflow {
108 at: self.init,
109 additional: bytes.len(),
110 capacity: N,
111 }));
112 }
113
114 unsafe {
115 let dst = (self.data.as_mut_ptr() as *mut u8).add(self.init);
116 ptr::copy_nonoverlapping(bytes.as_ptr(), dst, bytes.len());
117 }
118
119 self.init += bytes.len();
120 Ok(())
121 }
122}
123
124struct BufferOverflow {
125 at: usize,
126 additional: usize,
127 capacity: usize,
128}
129
130impl fmt::Display for BufferOverflow {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 let Self {
133 at,
134 additional,
135 capacity,
136 } = *self;
137
138 write!(
139 f,
140 "Overflow when writing {additional} bytes at {at} with capacity {capacity}"
141 )
142 }
143}