1use core::mem;
9
10use rkyv_0_8::{
11 rancor::Fallible,
12 traits::{CopyOptimization, NoUndef},
13 Archive, Deserialize, Place, Portable, Serialize,
14};
15
16use crate::{ArrayLength, GenericArray};
17
18unsafe impl<T: Portable, N: ArrayLength> Portable for GenericArray<T, N> {}
21unsafe impl<T: NoUndef, N: ArrayLength> NoUndef for GenericArray<T, N> {}
24
25#[inline]
33unsafe fn index_for_place_generic_array<T, N: ArrayLength>(
34 place: Place<GenericArray<T, N>>,
35 i: usize,
36) -> Place<T> {
37 let ptr = unsafe { place.ptr().cast::<T>().add(i) };
40 unsafe { Place::new_unchecked(place.pos() + i * mem::size_of::<T>(), ptr) }
43}
44
45impl<T: Archive, N: ArrayLength> Archive for GenericArray<T, N> {
46 const COPY_OPTIMIZATION: CopyOptimization<Self> =
47 unsafe { CopyOptimization::enable_if(T::COPY_OPTIMIZATION.is_enabled()) };
48
49 type Archived = GenericArray<T::Archived, N>;
53 type Resolver = GenericArray<T::Resolver, N>;
54
55 #[inline(always)]
56 fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
57 for (i, (value, resolver)) in self.iter().zip(resolver).enumerate() {
58 let out_i = unsafe { index_for_place_generic_array(out, i) };
59 value.resolve(resolver, out_i);
60 }
61 }
62}
63
64impl<T, S, N: ArrayLength> Serialize<S> for GenericArray<T, N>
65where
66 T: Serialize<S>,
67 S: Fallible + ?Sized,
68{
69 #[inline(always)]
70 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
71 let mut result = core::mem::MaybeUninit::<Self::Resolver>::uninit();
72 let result_ptr = result.as_mut_ptr().cast::<T::Resolver>();
73 for (i, value) in self.iter().enumerate() {
74 unsafe {
75 result_ptr.add(i).write(value.serialize(serializer)?);
76 }
77 }
78 unsafe { Ok(result.assume_init()) }
79 }
80}
81
82impl<T, D, N: ArrayLength> Deserialize<GenericArray<T, N>, D> for GenericArray<T::Archived, N>
83where
84 T: Archive,
85 T::Archived: Deserialize<T, D>,
86 D: Fallible + ?Sized,
87{
88 #[inline(always)]
89 fn deserialize(&self, deserializer: &mut D) -> Result<GenericArray<T, N>, D::Error> {
90 let mut result = core::mem::MaybeUninit::<GenericArray<T, N>>::uninit();
91 let result_ptr = result.as_mut_ptr().cast::<T>();
92 for (i, value) in self.iter().enumerate() {
93 unsafe {
94 result_ptr.add(i).write(value.deserialize(deserializer)?);
95 }
96 }
97 unsafe { Ok(result.assume_init()) }
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use rkyv_0_8 as rkyv;
104
105 use crate::typenum::{U0, U32, U6};
106 use crate::{arr, GenericArray};
107 use rkyv::rancor::Error;
108 use rkyv::traits::{NoUndef, Portable};
109
110 const fn assert_portable_noundef<T: Portable + NoUndef>() {}
111 const _: () = assert_portable_noundef::<GenericArray<u8, U32>>();
112 const _: () = assert_portable_noundef::<GenericArray<u8, U0>>();
113
114 #[test]
115 fn test_rkyv_roundtrip() {
116 let array: GenericArray<u32, U6> = arr![1, 2, 3, 4, 5, 6];
117 let bytes = rkyv::to_bytes::<Error>(&array).unwrap();
118 let archived =
119 unsafe { rkyv::access_unchecked::<rkyv::Archived<GenericArray<u32, U6>>>(&bytes) };
120 for (i, el) in archived.iter().enumerate() {
121 assert_eq!(el.to_native(), array[i]);
122 }
123 let deserialized: GenericArray<u32, U6> =
124 rkyv::deserialize::<GenericArray<u32, U6>, Error>(archived).unwrap();
125 assert_eq!(deserialized, array);
126 }
127
128 #[cfg(feature = "alloc")]
133 #[test]
134 fn test_rkyv_roundtrip_string() {
135 use alloc::string::String;
136 use typenum::U3;
137
138 let array: GenericArray<String, U3> = arr![
139 String::from("hello"),
140 String::from("rkyv"),
141 String::from("world")
142 ];
143 let bytes = rkyv::to_bytes::<Error>(&array).unwrap();
144 let archived =
145 unsafe { rkyv::access_unchecked::<rkyv::Archived<GenericArray<String, U3>>>(&bytes) };
146 for (i, el) in archived.iter().enumerate() {
147 assert_eq!(el.as_str(), array[i].as_str());
148 }
149 let deserialized: GenericArray<String, U3> =
150 rkyv::deserialize::<GenericArray<String, U3>, Error>(archived).unwrap();
151 assert_eq!(deserialized, array);
152 }
153}
154
155#[cfg(all(test, feature = "bytecheck-0_8"))]
156mod tests_full {
157 use rkyv_0_8 as rkyv;
158
159 use crate::typenum::U6;
160 use crate::{arr, GenericArray};
161 use rkyv::rancor::Error;
162
163 #[test]
164 fn test_validated_roundtrip() {
165 let array: GenericArray<u32, U6> = arr![10, 20, 30, 40, 50, 60];
166 let bytes = rkyv::to_bytes::<Error>(&array).unwrap();
167 let deserialized: GenericArray<u32, U6> =
168 rkyv::from_bytes::<GenericArray<u32, U6>, Error>(&bytes).unwrap();
169 assert_eq!(deserialized, array);
170 }
171
172 #[test]
173 fn test_validation_rejects_truncated() {
174 let array: GenericArray<u32, U6> = arr![1, 2, 3, 4, 5, 6];
175 let bytes = rkyv::to_bytes::<Error>(&array).unwrap();
176 let truncated = &bytes[..bytes.len() - 1];
177 let result = rkyv::access::<rkyv::Archived<GenericArray<u32, U6>>, Error>(truncated);
178 assert!(result.is_err());
179 }
180}