Skip to main content

rkyv/ser/writer/
core.rs

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/// Wraps a byte buffer and equips it with [`Writer`].
36///
37/// Common uses include archiving in `#![no_std]` environments and archiving
38/// small objects without allocating.
39///
40/// # Examples
41///
42/// ```
43/// use core::mem::MaybeUninit;
44///
45/// use rkyv::{
46///     access_unchecked,
47///     api::high::to_bytes_in,
48///     rancor::{Error, Strategy},
49///     ser::{writer::Buffer, Writer},
50///     util::Align,
51///     Archive, Archived, Serialize,
52/// };
53///
54/// #[derive(Archive, Serialize)]
55/// enum Event {
56///     Spawn,
57///     Speak(String),
58///     Die,
59/// }
60///
61/// let event = Event::Speak("Help me!".to_string());
62/// let mut bytes = Align([MaybeUninit::uninit(); 256]);
63/// let buffer = to_bytes_in::<_, Error>(&event, Buffer::from(&mut *bytes))
64///     .expect("failed to serialize event");
65/// let archived = unsafe { access_unchecked::<Archived<Event>>(&buffer) };
66/// if let Archived::<Event>::Speak(message) = archived {
67///     assert_eq!(message.as_str(), "Help me!");
68/// } else {
69///     panic!("archived event was of the wrong type");
70/// }
71/// ```
72#[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}