/rust/registry/src/index.crates.io-6f17d22bba15001f/rkyv-0.7.44/src/ser/serializers/core.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::{ |
2 | | ser::{ScratchSpace, Serializer}, |
3 | | Fallible, |
4 | | }; |
5 | | use core::{ |
6 | | alloc::Layout, |
7 | | fmt, |
8 | | ops::DerefMut, |
9 | | ptr::{copy_nonoverlapping, NonNull}, |
10 | | }; |
11 | | |
12 | | /// The error type returned by an [`BufferSerializer`]. |
13 | | #[derive(Debug)] |
14 | | pub enum BufferSerializerError { |
15 | | /// Writing has overflowed the internal buffer. |
16 | | Overflow { |
17 | | /// The position of the serializer |
18 | | pos: usize, |
19 | | /// The number of bytes needed |
20 | | bytes_needed: usize, |
21 | | /// The total length of the archive |
22 | | archive_len: usize, |
23 | | }, |
24 | | } |
25 | | |
26 | | impl fmt::Display for BufferSerializerError { |
27 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
28 | 0 | match self { |
29 | 0 | Self::Overflow { |
30 | 0 | pos, |
31 | 0 | bytes_needed, |
32 | 0 | archive_len, |
33 | 0 | } => write!( |
34 | 0 | f, |
35 | 0 | "writing has overflowed the serializer buffer: pos {}, needed {}, total length {}", |
36 | 0 | pos, bytes_needed, archive_len |
37 | 0 | ), |
38 | 0 | } |
39 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializerError as core::fmt::Display>::fmt Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializerError as core::fmt::Display>::fmt |
40 | | } |
41 | | |
42 | | #[cfg(feature = "std")] |
43 | | const _: () = { |
44 | | use std::error::Error; |
45 | | |
46 | | impl Error for BufferSerializerError {} |
47 | | }; |
48 | | |
49 | | /// Wraps a byte buffer and equips it with [`Serializer`]. |
50 | | /// |
51 | | /// Common uses include archiving in `#![no_std]` environments and archiving small objects without |
52 | | /// allocating. |
53 | | /// |
54 | | /// # Examples |
55 | | /// ``` |
56 | | /// use rkyv::{ |
57 | | /// archived_value, |
58 | | /// ser::{Serializer, serializers::BufferSerializer}, |
59 | | /// AlignedBytes, |
60 | | /// AlignedVec, |
61 | | /// Archive, |
62 | | /// Archived, |
63 | | /// Serialize, |
64 | | /// }; |
65 | | /// |
66 | | /// #[derive(Archive, Serialize)] |
67 | | /// enum Event { |
68 | | /// Spawn, |
69 | | /// Speak(String), |
70 | | /// Die, |
71 | | /// } |
72 | | /// |
73 | | /// let mut serializer = BufferSerializer::new(AlignedBytes([0u8; 256])); |
74 | | /// let pos = serializer.serialize_value(&Event::Speak("Help me!".to_string())) |
75 | | /// .expect("failed to archive event"); |
76 | | /// let buf = serializer.into_inner(); |
77 | | /// let archived = unsafe { archived_value::<Event>(buf.as_ref(), pos) }; |
78 | | /// if let Archived::<Event>::Speak(message) = archived { |
79 | | /// assert_eq!(message.as_str(), "Help me!"); |
80 | | /// } else { |
81 | | /// panic!("archived event was of the wrong type"); |
82 | | /// } |
83 | | /// ``` |
84 | | #[derive(Debug)] |
85 | | pub struct BufferSerializer<T> { |
86 | | inner: T, |
87 | | pos: usize, |
88 | | } |
89 | | |
90 | | impl<T> BufferSerializer<T> { |
91 | | /// Creates a new archive buffer from a byte buffer. |
92 | | #[inline] |
93 | 0 | pub fn new(inner: T) -> Self { |
94 | 0 | Self::with_pos(inner, 0) |
95 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_>>::new Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_>>::new |
96 | | |
97 | | /// Creates a new archive buffer from a byte buffer. The buffer will start writing at the given |
98 | | /// position, but the buffer must contain all bytes (otherwise the alignments of types may not |
99 | | /// be correct). |
100 | | #[inline] |
101 | 0 | pub fn with_pos(inner: T, pos: usize) -> Self { |
102 | 0 | Self { inner, pos } |
103 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_>>::with_pos Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_>>::with_pos |
104 | | |
105 | | /// Consumes the serializer and returns the underlying type. |
106 | | #[inline] |
107 | 0 | pub fn into_inner(self) -> T { |
108 | 0 | self.inner |
109 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_>>::into_inner Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_>>::into_inner |
110 | | } |
111 | | |
112 | | impl<T: Default> Default for BufferSerializer<T> { |
113 | | #[inline] |
114 | 0 | fn default() -> Self { |
115 | 0 | Self::new(T::default()) |
116 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_> as core::default::Default>::default Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_> as core::default::Default>::default |
117 | | } |
118 | | |
119 | | impl<T> Fallible for BufferSerializer<T> { |
120 | | type Error = BufferSerializerError; |
121 | | } |
122 | | |
123 | | impl<T: AsMut<[u8]>> Serializer for BufferSerializer<T> { |
124 | | #[inline] |
125 | 0 | fn pos(&self) -> usize { |
126 | 0 | self.pos |
127 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_> as rkyv::ser::Serializer>::pos Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_> as rkyv::ser::Serializer>::pos |
128 | | |
129 | 0 | fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { |
130 | 0 | let end_pos = self.pos + bytes.len(); |
131 | 0 | let archive_len = self.inner.as_mut().len(); |
132 | 0 | if end_pos > archive_len { |
133 | 0 | Err(BufferSerializerError::Overflow { |
134 | 0 | pos: self.pos, |
135 | 0 | bytes_needed: bytes.len(), |
136 | 0 | archive_len, |
137 | 0 | }) |
138 | | } else { |
139 | 0 | unsafe { |
140 | 0 | copy_nonoverlapping( |
141 | 0 | bytes.as_ptr(), |
142 | 0 | self.inner.as_mut().as_mut_ptr().add(self.pos), |
143 | 0 | bytes.len(), |
144 | 0 | ); |
145 | 0 | } |
146 | 0 | self.pos = end_pos; |
147 | 0 | Ok(()) |
148 | | } |
149 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_> as rkyv::ser::Serializer>::write Unexecuted instantiation: <rkyv::ser::serializers::core::BufferSerializer<_> as rkyv::ser::Serializer>::write |
150 | | } |
151 | | |
152 | | /// Errors that can occur when using a fixed-size allocator. |
153 | | /// |
154 | | /// Pairing a fixed-size allocator with a fallback allocator can help prevent running out of scratch |
155 | | /// space unexpectedly. |
156 | | #[derive(Debug)] |
157 | | pub enum FixedSizeScratchError { |
158 | | /// The allocator ran out of scratch space. |
159 | | OutOfScratch(Layout), |
160 | | /// Scratch space was not popped in reverse order. |
161 | | NotPoppedInReverseOrder { |
162 | | /// The current position of the start of free memory |
163 | | pos: usize, |
164 | | /// The next position according to the erroneous pop |
165 | | next_pos: usize, |
166 | | /// The size of the memory according to the erroneous pop |
167 | | next_size: usize, |
168 | | }, |
169 | | /// The given allocation did not belong to the scratch allocator. |
170 | | UnownedAllocation, |
171 | | } |
172 | | |
173 | | impl fmt::Display for FixedSizeScratchError { |
174 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
175 | 0 | match self { |
176 | 0 | Self::OutOfScratch(layout) => write!( |
177 | 0 | f, |
178 | 0 | "out of scratch: requested scratch space with size {} and align {}", |
179 | 0 | layout.size(), |
180 | 0 | layout.align() |
181 | 0 | ), |
182 | | Self::NotPoppedInReverseOrder { |
183 | 0 | pos, |
184 | 0 | next_pos, |
185 | 0 | next_size, |
186 | 0 | } => write!( |
187 | 0 | f, |
188 | 0 | "scratch space was not popped in reverse order: pos {}, next pos {}, next size {}", |
189 | 0 | pos, next_pos, next_size |
190 | 0 | ), |
191 | 0 | Self::UnownedAllocation => write!(f, "unowned allocation"), |
192 | | } |
193 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::FixedSizeScratchError as core::fmt::Display>::fmt Unexecuted instantiation: <rkyv::ser::serializers::core::FixedSizeScratchError as core::fmt::Display>::fmt |
194 | | } |
195 | | |
196 | | #[cfg(feature = "std")] |
197 | | impl std::error::Error for FixedSizeScratchError {} |
198 | | |
199 | | /// Scratch space that allocates within a buffer. |
200 | | #[derive(Debug)] |
201 | | pub struct BufferScratch<T> { |
202 | | buffer: T, |
203 | | pos: usize, |
204 | | // TODO: Compute this pointer eagerly in a future version of rkyv. |
205 | | ptr: Option<NonNull<[u8]>>, |
206 | | } |
207 | | |
208 | | unsafe impl<T> Send for BufferScratch<T> where T: Send {} |
209 | | unsafe impl<T> Sync for BufferScratch<T> where T: Sync {} |
210 | | |
211 | | impl<T> BufferScratch<T> { |
212 | | /// Creates a new buffer scratch allocator. |
213 | 30.0k | pub fn new(buffer: T) -> Self { |
214 | 30.0k | Self { |
215 | 30.0k | buffer, |
216 | 30.0k | pos: 0, |
217 | 30.0k | ptr: None, |
218 | 30.0k | } |
219 | 30.0k | } <rkyv::ser::serializers::core::BufferScratch<alloc::boxed::Box<rkyv::util::AlignedBytes<4096>>>>::new Line | Count | Source | 213 | 30.0k | pub fn new(buffer: T) -> Self { | 214 | 30.0k | Self { | 215 | 30.0k | buffer, | 216 | 30.0k | pos: 0, | 217 | 30.0k | ptr: None, | 218 | 30.0k | } | 219 | 30.0k | } |
Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_>>::new Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<alloc::boxed::Box<rkyv::util::AlignedBytes<4096>>>>::new Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_>>::new |
220 | | |
221 | | /// Resets the scratch space to its initial state. |
222 | 0 | pub fn clear(&mut self) { |
223 | 0 | self.pos = 0; |
224 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_>>::clear Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_>>::clear |
225 | | |
226 | | /// Consumes the buffer scratch allocator, returning the underlying buffer. |
227 | 0 | pub fn into_inner(self) -> T { |
228 | 0 | self.buffer |
229 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_>>::into_inner Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_>>::into_inner |
230 | | } |
231 | | |
232 | | impl<T: Default> Default for BufferScratch<T> { |
233 | 0 | fn default() -> Self { |
234 | 0 | Self::new(T::default()) |
235 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_> as core::default::Default>::default Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_> as core::default::Default>::default |
236 | | } |
237 | | |
238 | | impl<T> Fallible for BufferScratch<T> { |
239 | | type Error = FixedSizeScratchError; |
240 | | } |
241 | | |
242 | | impl<T: DerefMut<Target = U>, U: AsMut<[u8]>> ScratchSpace for BufferScratch<T> { |
243 | | #[inline] |
244 | 798k | unsafe fn push_scratch(&mut self, layout: Layout) -> Result<NonNull<[u8]>, Self::Error> { |
245 | 798k | if self.ptr.is_none() { |
246 | 30.0k | self.ptr = Some(NonNull::from(self.buffer.as_mut())); |
247 | 768k | } |
248 | 798k | let bytes = self.ptr.unwrap().as_ptr(); |
249 | 798k | |
250 | 798k | let start = bytes.cast::<u8>().add(self.pos); |
251 | 798k | let pad = match (start as usize) & (layout.align() - 1) { |
252 | 779k | 0 => 0, |
253 | 18.8k | x => layout.align() - x, |
254 | | }; |
255 | 798k | if pad + layout.size() <= ptr_meta::metadata(bytes) - self.pos { |
256 | 797k | self.pos += pad; |
257 | 797k | let result_slice = ptr_meta::from_raw_parts_mut( |
258 | 797k | bytes.cast::<u8>().add(self.pos).cast(), |
259 | 797k | layout.size(), |
260 | 797k | ); |
261 | 797k | let result = NonNull::new_unchecked(result_slice); |
262 | 797k | self.pos += layout.size(); |
263 | 797k | Ok(result) |
264 | | } else { |
265 | 1.04k | Err(FixedSizeScratchError::OutOfScratch(layout)) |
266 | | } |
267 | 798k | } <rkyv::ser::serializers::core::BufferScratch<alloc::boxed::Box<rkyv::util::AlignedBytes<4096>>> as rkyv::ser::ScratchSpace>::push_scratch Line | Count | Source | 244 | 798k | unsafe fn push_scratch(&mut self, layout: Layout) -> Result<NonNull<[u8]>, Self::Error> { | 245 | 798k | if self.ptr.is_none() { | 246 | 30.0k | self.ptr = Some(NonNull::from(self.buffer.as_mut())); | 247 | 768k | } | 248 | 798k | let bytes = self.ptr.unwrap().as_ptr(); | 249 | 798k | | 250 | 798k | let start = bytes.cast::<u8>().add(self.pos); | 251 | 798k | let pad = match (start as usize) & (layout.align() - 1) { | 252 | 779k | 0 => 0, | 253 | 18.8k | x => layout.align() - x, | 254 | | }; | 255 | 798k | if pad + layout.size() <= ptr_meta::metadata(bytes) - self.pos { | 256 | 797k | self.pos += pad; | 257 | 797k | let result_slice = ptr_meta::from_raw_parts_mut( | 258 | 797k | bytes.cast::<u8>().add(self.pos).cast(), | 259 | 797k | layout.size(), | 260 | 797k | ); | 261 | 797k | let result = NonNull::new_unchecked(result_slice); | 262 | 797k | self.pos += layout.size(); | 263 | 797k | Ok(result) | 264 | | } else { | 265 | 1.04k | Err(FixedSizeScratchError::OutOfScratch(layout)) | 266 | | } | 267 | 798k | } |
Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_> as rkyv::ser::ScratchSpace>::push_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<alloc::boxed::Box<rkyv::util::AlignedBytes<4096>>> as rkyv::ser::ScratchSpace>::push_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_> as rkyv::ser::ScratchSpace>::push_scratch |
268 | | |
269 | | #[inline] |
270 | 798k | unsafe fn pop_scratch(&mut self, ptr: NonNull<u8>, layout: Layout) -> Result<(), Self::Error> { |
271 | 798k | let bytes = self.ptr.unwrap().as_ptr(); |
272 | 798k | |
273 | 798k | let ptr = ptr.as_ptr(); |
274 | 798k | if ptr >= bytes.cast::<u8>() && ptr < bytes.cast::<u8>().add(ptr_meta::metadata(bytes)) { |
275 | 797k | let next_pos = ptr.offset_from(bytes.cast::<u8>()) as usize; |
276 | 797k | if next_pos + layout.size() <= self.pos { |
277 | 797k | self.pos = next_pos; |
278 | 797k | Ok(()) |
279 | | } else { |
280 | 0 | Err(FixedSizeScratchError::NotPoppedInReverseOrder { |
281 | 0 | pos: self.pos, |
282 | 0 | next_pos, |
283 | 0 | next_size: layout.size(), |
284 | 0 | }) |
285 | | } |
286 | | } else { |
287 | 1.04k | Err(FixedSizeScratchError::UnownedAllocation) |
288 | | } |
289 | 798k | } <rkyv::ser::serializers::core::BufferScratch<alloc::boxed::Box<rkyv::util::AlignedBytes<4096>>> as rkyv::ser::ScratchSpace>::pop_scratch Line | Count | Source | 270 | 798k | unsafe fn pop_scratch(&mut self, ptr: NonNull<u8>, layout: Layout) -> Result<(), Self::Error> { | 271 | 798k | let bytes = self.ptr.unwrap().as_ptr(); | 272 | 798k | | 273 | 798k | let ptr = ptr.as_ptr(); | 274 | 798k | if ptr >= bytes.cast::<u8>() && ptr < bytes.cast::<u8>().add(ptr_meta::metadata(bytes)) { | 275 | 797k | let next_pos = ptr.offset_from(bytes.cast::<u8>()) as usize; | 276 | 797k | if next_pos + layout.size() <= self.pos { | 277 | 797k | self.pos = next_pos; | 278 | 797k | Ok(()) | 279 | | } else { | 280 | 0 | Err(FixedSizeScratchError::NotPoppedInReverseOrder { | 281 | 0 | pos: self.pos, | 282 | 0 | next_pos, | 283 | 0 | next_size: layout.size(), | 284 | 0 | }) | 285 | | } | 286 | | } else { | 287 | 1.04k | Err(FixedSizeScratchError::UnownedAllocation) | 288 | | } | 289 | 798k | } |
Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_> as rkyv::ser::ScratchSpace>::pop_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<alloc::boxed::Box<rkyv::util::AlignedBytes<4096>>> as rkyv::ser::ScratchSpace>::pop_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::BufferScratch<_> as rkyv::ser::ScratchSpace>::pop_scratch |
290 | | } |
291 | | |
292 | | /// Allocates scratch space with a main and backup scratch. |
293 | | #[derive(Debug)] |
294 | | pub struct FallbackScratch<M, F> { |
295 | | main: M, |
296 | | fallback: F, |
297 | | } |
298 | | |
299 | | impl<M, F> FallbackScratch<M, F> { |
300 | | /// Creates fallback scratch from a main and backup scratch. |
301 | 0 | pub fn new(main: M, fallback: F) -> Self { |
302 | 0 | Self { main, fallback } |
303 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _>>::new Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _>>::new |
304 | | } |
305 | | |
306 | | impl<M: Default, F: Default> Default for FallbackScratch<M, F> { |
307 | 30.0k | fn default() -> Self { |
308 | 30.0k | Self { |
309 | 30.0k | main: M::default(), |
310 | 30.0k | fallback: F::default(), |
311 | 30.0k | } |
312 | 30.0k | } <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as core::default::Default>::default Line | Count | Source | 307 | 30.0k | fn default() -> Self { | 308 | 30.0k | Self { | 309 | 30.0k | main: M::default(), | 310 | 30.0k | fallback: F::default(), | 311 | 30.0k | } | 312 | 30.0k | } |
Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as core::default::Default>::default Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as core::default::Default>::default Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as core::default::Default>::default |
313 | | } |
314 | | |
315 | | impl<M, F: Fallible> Fallible for FallbackScratch<M, F> { |
316 | | type Error = F::Error; |
317 | | } |
318 | | |
319 | | impl<M: ScratchSpace, F: ScratchSpace> ScratchSpace for FallbackScratch<M, F> { |
320 | | #[inline] |
321 | 798k | unsafe fn push_scratch(&mut self, layout: Layout) -> Result<NonNull<[u8]>, Self::Error> { |
322 | 798k | self.main |
323 | 798k | .push_scratch(layout) |
324 | 798k | .or_else(|_| self.fallback.push_scratch(layout)) <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::push_scratch::{closure#0}Line | Count | Source | 324 | 1.04k | .or_else(|_| self.fallback.push_scratch(layout)) |
Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::push_scratch::{closure#0}Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::push_scratch::{closure#0}Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::push_scratch::{closure#0} |
325 | 798k | } <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::push_scratch Line | Count | Source | 321 | 798k | unsafe fn push_scratch(&mut self, layout: Layout) -> Result<NonNull<[u8]>, Self::Error> { | 322 | 798k | self.main | 323 | 798k | .push_scratch(layout) | 324 | 798k | .or_else(|_| self.fallback.push_scratch(layout)) | 325 | 798k | } |
Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::push_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::push_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::push_scratch |
326 | | |
327 | | #[inline] |
328 | 798k | unsafe fn pop_scratch(&mut self, ptr: NonNull<u8>, layout: Layout) -> Result<(), Self::Error> { |
329 | 798k | self.main |
330 | 798k | .pop_scratch(ptr, layout) |
331 | 798k | .or_else(|_| self.fallback.pop_scratch(ptr, layout)) <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::pop_scratch::{closure#0}Line | Count | Source | 331 | 1.04k | .or_else(|_| self.fallback.pop_scratch(ptr, layout)) |
Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::pop_scratch::{closure#0}Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::pop_scratch::{closure#0}Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::pop_scratch::{closure#0} |
332 | 798k | } <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::pop_scratch Line | Count | Source | 328 | 798k | unsafe fn pop_scratch(&mut self, ptr: NonNull<u8>, layout: Layout) -> Result<(), Self::Error> { | 329 | 798k | self.main | 330 | 798k | .pop_scratch(ptr, layout) | 331 | 798k | .or_else(|_| self.fallback.pop_scratch(ptr, layout)) | 332 | 798k | } |
Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::pop_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<rkyv::ser::serializers::alloc::HeapScratch<4096>, rkyv::ser::serializers::alloc::AllocScratch> as rkyv::ser::ScratchSpace>::pop_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::FallbackScratch<_, _> as rkyv::ser::ScratchSpace>::pop_scratch |
333 | | } |
334 | | |
335 | | /// A passthrough scratch space allocator that tracks scratch space usage. |
336 | | #[derive(Debug)] |
337 | | pub struct ScratchTracker<T> { |
338 | | inner: T, |
339 | | bytes_allocated: usize, |
340 | | allocations: usize, |
341 | | max_bytes_allocated: usize, |
342 | | max_allocations: usize, |
343 | | max_alignment: usize, |
344 | | } |
345 | | |
346 | | impl<T> ScratchTracker<T> { |
347 | | /// Creates a new scratch tracker from the given inner scratch space. |
348 | 0 | pub fn new(inner: T) -> Self { |
349 | 0 | Self { |
350 | 0 | inner, |
351 | 0 | bytes_allocated: 0, |
352 | 0 | allocations: 0, |
353 | 0 | max_bytes_allocated: 0, |
354 | 0 | max_allocations: 0, |
355 | 0 | max_alignment: 1, |
356 | 0 | } |
357 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::new Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::new |
358 | | |
359 | | /// Returns the maximum number of bytes that were concurrently allocated during serialization. |
360 | 0 | pub fn max_bytes_allocated(&self) -> usize { |
361 | 0 | self.max_bytes_allocated |
362 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::max_bytes_allocated Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::max_bytes_allocated |
363 | | |
364 | | /// Returns the maximum number of concurrent allocations during serialization. |
365 | 0 | pub fn max_allocations(&self) -> usize { |
366 | 0 | self.max_allocations |
367 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::max_allocations Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::max_allocations |
368 | | |
369 | | /// Returns the maximum alignment of scratch space requested during serialization. |
370 | 0 | pub fn max_alignment(&self) -> usize { |
371 | 0 | self.max_alignment |
372 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::max_alignment Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::max_alignment |
373 | | |
374 | | /// Returns the minimum buffer size required to serialize the same data. |
375 | | /// |
376 | | /// This calculation takes into account packing efficiency for slab allocated scratch space. It |
377 | | /// is not exact, and has an error bound of `max_allocations * (max_alignment - 1)` bytes. This |
378 | | /// should be suitably small for most use cases. |
379 | 0 | pub fn min_buffer_size(&self) -> usize { |
380 | 0 | self.max_bytes_allocated + self.min_buffer_size_max_error() |
381 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::min_buffer_size Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::min_buffer_size |
382 | | |
383 | | /// Returns the maximum error term for the minimum buffer size calculation. |
384 | 0 | pub fn min_buffer_size_max_error(&self) -> usize { |
385 | 0 | self.max_allocations * (self.max_alignment - 1) |
386 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::min_buffer_size_max_error Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_>>::min_buffer_size_max_error |
387 | | } |
388 | | |
389 | | impl<T: Fallible> Fallible for ScratchTracker<T> { |
390 | | type Error = T::Error; |
391 | | } |
392 | | |
393 | | impl<T: ScratchSpace> ScratchSpace for ScratchTracker<T> { |
394 | | #[inline] |
395 | 0 | unsafe fn push_scratch(&mut self, layout: Layout) -> Result<NonNull<[u8]>, Self::Error> { |
396 | 0 | let result = self.inner.push_scratch(layout)?; |
397 | | |
398 | 0 | self.bytes_allocated += layout.size(); |
399 | 0 | self.allocations += 1; |
400 | 0 | self.max_bytes_allocated = usize::max(self.bytes_allocated, self.max_bytes_allocated); |
401 | 0 | self.max_allocations = usize::max(self.allocations, self.max_allocations); |
402 | 0 | self.max_alignment = usize::max(self.max_alignment, layout.align()); |
403 | 0 |
|
404 | 0 | Ok(result) |
405 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_> as rkyv::ser::ScratchSpace>::push_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_> as rkyv::ser::ScratchSpace>::push_scratch |
406 | | |
407 | | #[inline] |
408 | 0 | unsafe fn pop_scratch(&mut self, ptr: NonNull<u8>, layout: Layout) -> Result<(), Self::Error> { |
409 | 0 | self.inner.pop_scratch(ptr, layout)?; |
410 | | |
411 | 0 | self.bytes_allocated -= layout.size(); |
412 | 0 | self.allocations -= 1; |
413 | 0 |
|
414 | 0 | Ok(()) |
415 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_> as rkyv::ser::ScratchSpace>::pop_scratch Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_> as rkyv::ser::ScratchSpace>::pop_scratch |
416 | | } |
417 | | |
418 | | impl<T> From<T> for ScratchTracker<T> { |
419 | 0 | fn from(inner: T) -> Self { |
420 | 0 | Self::new(inner) |
421 | 0 | } Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_> as core::convert::From<_>>::from Unexecuted instantiation: <rkyv::ser::serializers::core::ScratchTracker<_> as core::convert::From<_>>::from |
422 | | } |