1use core::cell::RefCell;
7use std::time::{Duration, SystemTime, UNIX_EPOCH};
8
9use rkyv::{
10 ser::{
11 allocator::{Arena, ArenaHandle},
12 writer::Buffer as RkyvBuffer,
13 Positional, Serializer, Writer,
14 },
15 with::{ArchiveWith, DeserializeWith, SerializeWith},
16 Archive, Archived, Deserialize, Place, Portable, Serialize,
17};
18
19pub type XousDeserializer = rkyv::rancor::Strategy<(), rkyv::rancor::Error>;
20pub type XousValidator<'a> = rkyv::api::low::LowValidator<'a, rkyv::rancor::Error>;
21pub type XousSerializer<'a, 'b> = rkyv::rancor::Strategy<
22 rkyv::ser::Serializer<rkyv::ser::writer::Buffer<'b>, ArenaHandle<'a>, ()>,
23 rkyv::rancor::Error,
24>;
25pub(crate) type SizeOfSerializer<'a> =
26 rkyv::rancor::Strategy<rkyv::ser::Serializer<SizeOfWriter, ArenaHandle<'a>, ()>, rkyv::rancor::Error>;
27
28thread_local! {
29 static ALLOC_ARENA: RefCell<Arena> = RefCell::new(Arena::new());
30}
31
32fn with_arena<R>(f: impl FnOnce(ArenaHandle<'_>) -> R) -> R {
33 ALLOC_ARENA.with_borrow_mut(|alloc| f(alloc.acquire()))
34}
35
36pub(crate) fn serialized_size<T>(src: &T) -> core::result::Result<usize, rkyv::rancor::Error>
38where
39 T: for<'a> rkyv::Serialize<SizeOfSerializer<'a>>,
40{
41 with_arena(|arena| {
42 let mut serializer = Serializer::new(SizeOfWriter::new(), arena, ());
43 rkyv::api::serialize_using(src, &mut serializer)?;
44 Ok(serializer.pos())
45 })
46}
47
48pub(crate) fn serialize_into<T>(dst: &mut [u8], src: &T) -> core::result::Result<usize, rkyv::rancor::Error>
50where
51 T: for<'a, 'b> rkyv::Serialize<XousSerializer<'a, 'b>>,
52{
53 with_arena(|arena| {
54 let mut serializer = Serializer::new(RkyvBuffer::from(dst), arena, ());
55 rkyv::api::serialize_using(src, &mut serializer)?;
56 Ok(serializer.pos())
57 })
58}
59
60pub(crate) fn decode<T>(bytes: &[u8]) -> core::result::Result<T, rkyv::rancor::Error>
62where
63 T: rkyv::Archive,
64 T::Archived:
65 Portable + for<'a> rkyv::bytecheck::CheckBytes<XousValidator<'a>> + Deserialize<T, XousDeserializer>,
66{
67 let archived = rkyv::api::low::access::<T::Archived, rkyv::rancor::Error>(bytes)?;
68 rkyv::api::low::deserialize::<T, rkyv::rancor::Error>(archived)
69}
70
71#[derive(Debug, Default)]
74pub struct SizeOfWriter {
75 pos: usize,
76}
77
78impl SizeOfWriter {
79 pub(crate) fn new() -> Self { Self { pos: 0 } }
80}
81
82impl Positional for SizeOfWriter {
83 fn pos(&self) -> usize { self.pos }
84}
85
86impl rkyv::rancor::Fallible for SizeOfWriter {
87 type Error = rkyv::rancor::Error;
88}
89
90impl Writer<rkyv::rancor::Error> for SizeOfWriter {
91 fn write(&mut self, bytes: &[u8]) -> core::result::Result<(), rkyv::rancor::Error> {
92 self.pos += bytes.len();
93 Ok(())
94 }
95}
96
97pub struct WithUnixTimestamp;
100
101impl ArchiveWith<SystemTime> for WithUnixTimestamp {
102 type Archived = Archived<Duration>;
103 type Resolver = <Duration as Archive>::Resolver;
104
105 #[inline]
106 fn resolve_with(field: &SystemTime, resolver: Self::Resolver, out: Place<Self::Archived>) {
107 let duration = field.duration_since(UNIX_EPOCH).unwrap_or_default();
108 Archive::resolve(&duration, resolver, out);
109 }
110}
111
112impl<S> SerializeWith<SystemTime, S> for WithUnixTimestamp
113where
114 S: rkyv::rancor::Fallible + ?Sized,
115{
116 fn serialize_with(field: &SystemTime, s: &mut S) -> Result<Self::Resolver, S::Error> {
117 let duration = field.duration_since(UNIX_EPOCH).unwrap_or_default();
118 duration.serialize(s)
119 }
120}
121
122impl<D> DeserializeWith<Archived<Duration>, SystemTime, D> for WithUnixTimestamp
123where
124 D: rkyv::rancor::Fallible + ?Sized,
125{
126 fn deserialize_with(field: &Archived<Duration>, _: &mut D) -> Result<SystemTime, D::Error> {
127 Ok(UNIX_EPOCH + Duration::from(*field))
128 }
129}
130
131pub struct WithAppId;
132
133impl ArchiveWith<xous::AppId> for WithAppId {
134 type Archived = Archived<[u32; 4]>;
135 type Resolver = <[u32; 4] as Archive>::Resolver;
136
137 #[inline]
138 fn resolve_with(field: &xous::AppId, resolver: Self::Resolver, out: Place<Self::Archived>) {
139 let words: [u32; 4] = field.into();
140 Archive::resolve(&words, resolver, out);
141 }
142}
143
144impl<S> SerializeWith<xous::AppId, S> for WithAppId
145where
146 S: rkyv::rancor::Fallible + ?Sized,
147{
148 fn serialize_with(field: &xous::AppId, s: &mut S) -> Result<Self::Resolver, S::Error> {
149 let words: [u32; 4] = field.into();
150 words.serialize(s)
151 }
152}
153
154impl<D> DeserializeWith<Archived<[u32; 4]>, xous::AppId, D> for WithAppId
155where
156 D: rkyv::rancor::Fallible + ?Sized,
157{
158 fn deserialize_with(field: &Archived<[u32; 4]>, d: &mut D) -> Result<xous::AppId, D::Error> {
159 let words = field.deserialize(d)?;
160 Ok(words.into())
161 }
162}