ser_raw/serializer_traits/
pos_tracking.rs

1use std::slice;
2
3use crate::{pos::PosMapping, storage::Storage, Serialize, Serializer};
4
5/// Trait for serializers which track position in output.
6///
7/// Used by `CompleteSerializer` and `PtrOffsetSerializer`, provided by this
8/// crate.
9pub trait PosTracking: Serializer {
10	// NB: Position tracking serializers can use `NoopAddr` as `Addr` associated
11	// type, unless they are also recording pointers.
12
13	/// Get current position mapping
14	fn pos_mapping(&self) -> &PosMapping;
15
16	/// Set current position mapping
17	fn set_pos_mapping(&mut self, pos_mapping: PosMapping) -> ();
18
19	/// Get position for a value
20	#[inline]
21	fn pos_for<T>(&self, value: &T) -> usize {
22		self.pos_mapping().pos_for(value)
23	}
24
25	fn do_serialize_value<T: Serialize<Self>>(&mut self, value: &T) {
26		// Align storage, ready to write value
27		self.storage_mut().align_for::<T>();
28
29		// Record position mapping for this value
30		self.set_pos_mapping(PosMapping::new(value as *const T as usize, self.pos()));
31
32		// Push value to storage.
33		// `push_slice_unaligned`'s requirements are satisfied by `align_for::<T>()` and
34		// `align_after::<T>()`.
35		let slice = slice::from_ref(value);
36		unsafe { self.storage_mut().push_slice_unaligned(slice) };
37		self.storage_mut().align_after::<T>();
38
39		// Serialize value (which may use the pos mapping we set)
40		value.serialize_data(self);
41	}
42
43	// Skip recording position when no further processing for a slice
44	#[inline]
45	fn do_push_slice<T>(&mut self, slice: &[T], _ptr_addr: Self::Addr) {
46		self.push_raw_slice(slice);
47	}
48
49	#[inline]
50	fn do_push_and_process_slice<T, P: FnOnce(&mut Self)>(
51		&mut self,
52		slice: &[T],
53		_ptr_addr: Self::Addr,
54		process: P,
55	) {
56		// Get position mapping before processing this
57		let pos_mapping_before = *self.pos_mapping();
58
59		// Align storage, ready to write slice
60		self.storage_mut().align_for::<T>();
61
62		// Record position mapping for this slice
63		self.set_pos_mapping(PosMapping::new(slice.as_ptr() as usize, self.pos()));
64
65		// Push slice to storage.
66		// `push_slice_unaligned`'s requirements are satisfied by `align_for::<T>()` and
67		// `align_after::<T>()`.
68		unsafe { self.storage_mut().push_slice_unaligned(slice) };
69		self.storage_mut().align_after::<T>();
70
71		// Call `process` function (which may use the pos mapping we set)
72		process(self);
73
74		// Reset position mapping back to as it was
75		self.set_pos_mapping(pos_mapping_before);
76	}
77}