1use core::{
2 error::Error,
3 fmt,
4 marker::PhantomData,
5 mem::MaybeUninit,
6 ops::{Deref, DerefMut},
7 ptr::{copy_nonoverlapping, NonNull},
8 slice,
9};
10
11use rancor::{fail, Source};
12
13use crate::ser::{Positional, Writer};
14
15#[derive(Debug)]
16struct BufferOverflow {
17 write_len: usize,
18 cap: usize,
19 len: usize,
20}
21
22impl fmt::Display for BufferOverflow {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 write!(
25 f,
26 "overflowed buffer while writing {} bytes into buffer of length \
27 {} (capacity is {})",
28 self.write_len, self.len, self.cap,
29 )
30 }
31}
32
33impl Error for BufferOverflow {}
34
35#[derive(Debug)]
73pub struct Buffer<'a> {
74 ptr: NonNull<u8>,
75 cap: usize,
76 len: usize,
77 _phantom: PhantomData<&'a mut [u8]>,
78}
79
80impl<'a, const N: usize> From<&'a mut [u8; N]> for Buffer<'a> {
81 fn from(bytes: &'a mut [u8; N]) -> Self {
82 Self {
83 ptr: NonNull::from(bytes).cast(),
84 cap: N,
85 len: 0,
86 _phantom: PhantomData,
87 }
88 }
89}
90
91impl<'a> From<&'a mut [u8]> for Buffer<'a> {
92 fn from(bytes: &'a mut [u8]) -> Self {
93 let size = bytes.len();
94 Self {
95 ptr: NonNull::from(bytes).cast(),
96 cap: size,
97 len: 0,
98 _phantom: PhantomData,
99 }
100 }
101}
102
103impl<'a, const N: usize> From<&'a mut [MaybeUninit<u8>; N]> for Buffer<'a> {
104 fn from(bytes: &'a mut [MaybeUninit<u8>; N]) -> Self {
105 Self {
106 ptr: NonNull::from(bytes).cast(),
107 cap: N,
108 len: 0,
109 _phantom: PhantomData,
110 }
111 }
112}
113
114impl<'a> From<&'a mut [MaybeUninit<u8>]> for Buffer<'a> {
115 fn from(bytes: &'a mut [MaybeUninit<u8>]) -> Self {
116 let size = bytes.len();
117 Self {
118 ptr: NonNull::from(bytes).cast(),
119 cap: size,
120 len: 0,
121 _phantom: PhantomData,
122 }
123 }
124}
125
126impl Deref for Buffer<'_> {
127 type Target = [u8];
128
129 fn deref(&self) -> &Self::Target {
130 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
131 }
132}
133
134impl DerefMut for Buffer<'_> {
135 fn deref_mut(&mut self) -> &mut Self::Target {
136 unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
137 }
138}
139
140impl Positional for Buffer<'_> {
141 #[inline]
142 fn pos(&self) -> usize {
143 self.len
144 }
145}
146
147impl<E: Source> Writer<E> for Buffer<'_> {
148 fn write(&mut self, bytes: &[u8]) -> Result<(), E> {
149 if bytes.len() > self.cap - self.len {
150 fail!(BufferOverflow {
151 write_len: bytes.len(),
152 cap: self.cap,
153 len: self.len,
154 });
155 } else {
156 unsafe {
157 copy_nonoverlapping(
158 bytes.as_ptr(),
159 self.ptr.as_ptr().add(self.len),
160 bytes.len(),
161 );
162 }
163 self.len += bytes.len();
164 Ok(())
165 }
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use core::mem::MaybeUninit;
172
173 use rancor::Panic;
174
175 use crate::{
176 api::serialize_using,
177 ser::{writer::Buffer, Serializer},
178 };
179
180 #[test]
181 fn zeros_padding() {
182 use core::mem::size_of;
183
184 use crate::{Archive, Serialize};
185
186 #[derive(Archive, Serialize)]
187 #[rkyv(crate)]
188 pub struct PaddedExample {
189 a: u8,
190 b: u64,
191 }
192
193 let mut bytes = [MaybeUninit::<u8>::new(0xcc); 256];
194 let mut serializer = Serializer::new(Buffer::from(&mut bytes), (), ());
195 serialize_using::<_, Panic>(
196 &PaddedExample { a: 0u8, b: 0u64 },
197 &mut serializer,
198 )
199 .unwrap();
200 let buffer = serializer.into_writer();
201 assert!(&buffer[0..size_of::<ArchivedPaddedExample>()]
202 .iter()
203 .all(|&b| b == 0));
204 }
205}