diff --git a/Cargo.toml b/Cargo.toml index 1a356c3d..f1d65128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,7 +76,7 @@ rand_distr = { version = "0.4", default-features = false, optional = true } matrixmultiply = { version = "0.3", optional = true } serde = { version = "1.0", default-features = false, features = [ "derive" ], optional = true } abomonation = { version = "0.7", optional = true } -rkyv = { version = "~0.6.3", default-features = false, features = ["const_generics"], optional = true } +rkyv = { version = "~0.6.4", default-features = false, features = ["const_generics"], optional = true } mint = { version = "0.5", optional = true } glam = { version = "0.13", optional = true } quickcheck = { version = "1", optional = true } diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index e575229c..350240cd 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -37,7 +37,6 @@ use crate::base::Scalar; /// A array-based statically sized matrix data storage. #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Deserialize, Serialize))] pub struct ArrayStorage(pub [[T; R]; C]); // TODO: remove this once the stdlib implements Default for arrays. @@ -303,3 +302,34 @@ where self.as_slice().iter().fold(0, |acc, e| acc + e.extent()) } } + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for ArrayStorage { + type Archived = ArrayStorage; + type Resolver = <[[T; R]; C] as Archive>::Resolver; + + fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut core::mem::MaybeUninit) { + self.0.resolve( + pos + rkyv::offset_of!(Self::Archived, 0), + resolver, + rkyv::project_struct!(out: Self::Archived => 0) + ); + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl, S: rkyv::Fallible + ?Sized, const R: usize, const C: usize> Serialize for ArrayStorage { + fn serialize(&self, serializer: &mut S) -> Result { + Ok(self.0.serialize(serializer)?) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize, D> for ArrayStorage +where + T::Archived: Deserialize, +{ + fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { + Ok(ArrayStorage(self.0.deserialize(deserializer)?)) + } +} diff --git a/src/base/dimension.rs b/src/base/dimension.rs index 2c51b2f4..3ee762f1 100644 --- a/src/base/dimension.rs +++ b/src/base/dimension.rs @@ -200,7 +200,6 @@ dim_ops!( ); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Deserialize, Serialize))] pub struct Const; /// Trait implemented exclusively by type-level integers. @@ -235,6 +234,29 @@ impl<'de, const D: usize> Deserialize<'de> for Const { } } +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for Const { + type Archived = Self; + type Resolver = (); + + fn resolve(&self, _: usize, _: Self::Resolver, _: &mut core::mem::MaybeUninit) { + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Serialize for Const { + fn serialize(&self, _: &mut S) -> Result { + Ok(()) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize for Const { + fn deserialize(&self, _: &mut D) -> Result { + Ok(Const) + } +} + pub trait ToConst { type Const: DimName; } diff --git a/src/base/matrix.rs b/src/base/matrix.rs index c7e02e22..939e78b3 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -156,7 +156,6 @@ pub type MatrixCross = /// some concrete types for `T` and a compatible data storage type `S`). #[repr(C)] #[derive(Clone, Copy)] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Deserialize, Serialize))] pub struct Matrix { /// The data storage that contains all the matrix components. Disappointed? /// @@ -312,6 +311,40 @@ where { } +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for Matrix { + type Archived = Matrix; + type Resolver = S::Resolver; + + fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut core::mem::MaybeUninit) { + self.data.resolve( + pos + rkyv::offset_of!(Self::Archived, data), + resolver, + rkyv::project_struct!(out: Self::Archived => data) + ); + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl, _S: rkyv::Fallible + ?Sized> Serialize<_S> for Matrix { + fn serialize(&self, serializer: &mut _S) -> Result { + Ok(self.data.serialize(serializer)?) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize, D> for Matrix +where + S::Archived: Deserialize, +{ + fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { + Ok(Matrix { + data: self.data.deserialize(deserializer)?, + _phantoms: PhantomData, + }) + } +} + impl Matrix { /// Creates a new matrix with the given data without statically checking that the matrix /// dimension matches the storage dimension. diff --git a/src/base/unit.rs b/src/base/unit.rs index 4b1d1948..0c30f961 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -29,7 +29,6 @@ use crate::{Dim, Matrix, OMatrix, RealField, Scalar, SimdComplexField, SimdRealF /// in their documentation, read their dedicated pages directly. #[repr(transparent)] #[derive(Clone, Hash, Debug, Copy)] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Deserialize, Serialize))] pub struct Unit { pub(crate) value: T, } @@ -75,6 +74,39 @@ impl Abomonation for Unit { } } +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for Unit { + type Archived = Unit; + type Resolver = T::Resolver; + + fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut ::core::mem::MaybeUninit) { + self.value.resolve( + pos + rkyv::offset_of!(Self::Archived, value), + resolver, + rkyv::project_struct!(out: Self::Archived => value), + ); + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl, S: rkyv::Fallible + ?Sized> Serialize for Unit { + fn serialize(&self, serializer: &mut S) -> Result { + Ok(self.value.serialize(serializer)?) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize, D> for Unit +where + T::Archived: Deserialize, +{ + fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { + Ok(Unit { + value: self.value.deserialize(deserializer)?, + }) + } +} + impl PartialEq for Unit> where T: Scalar + PartialEq, diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 7c8686c0..dea1b1be 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -71,7 +71,6 @@ use crate::geometry::{AbstractRotation, Point, Translation}; DefaultAllocator: Allocator>, Owned>: Deserialize<'de>")) )] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Serialize, Deserialize))] pub struct Isometry { /// The pure rotational part of this isometry. pub rotation: R, @@ -102,6 +101,55 @@ where } } +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for Isometry +where + T::Archived: Scalar, +{ + type Archived = Isometry; + type Resolver = (R::Resolver, as Archive>::Resolver); + + fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut core::mem::MaybeUninit) { + self.rotation.resolve( + pos + rkyv::offset_of!(Self::Archived, rotation), + resolver.0, + rkyv::project_struct!(out: Self::Archived => rotation) + ); + self.translation.resolve( + pos + rkyv::offset_of!(Self::Archived, translation), + resolver.1, + rkyv::project_struct!(out: Self::Archived => translation) + ); + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl, R: Serialize, S: rkyv::Fallible + ?Sized, const D: usize> Serialize for Isometry +where + T::Archived: Scalar, +{ + fn serialize(&self, serializer: &mut S) -> Result { + Ok(( + self.rotation.serialize(serializer)?, + self.translation.serialize(serializer)?, + )) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize, _D> for Isometry +where + T::Archived: Scalar + Deserialize, + R::Archived: Scalar + Deserialize, +{ + fn deserialize(&self, deserializer: &mut _D) -> Result, _D::Error> { + Ok(Isometry { + rotation: self.rotation.deserialize(deserializer)?, + translation: self.translation.deserialize(deserializer)?, + }) + } +} + impl hash::Hash for Isometry where Owned>: hash::Hash, diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 9a920a8a..7c6a70ae 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -31,7 +31,6 @@ use crate::geometry::{Point3, Rotation}; /// that may be used as a rotation. #[repr(C)] #[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Deserialize, Serialize))] pub struct Quaternion { /// This quaternion as a 4D vector of coordinates in the `[ x, y, z, w ]` storage order. pub coords: Vector4, @@ -117,6 +116,39 @@ where } } +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for Quaternion { + type Archived = Quaternion; + type Resolver = as Archive>::Resolver; + + fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut core::mem::MaybeUninit) { + self.coords.resolve( + pos + rkyv::offset_of!(Self::Archived, coords), + resolver, + rkyv::project_struct!(out: Self::Archived => coords) + ); + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl, S: rkyv::Fallible + ?Sized> Serialize for Quaternion { + fn serialize(&self, serializer: &mut S) -> Result { + Ok(self.coords.serialize(serializer)?) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize, D> for Quaternion +where + T::Archived: Deserialize, +{ + fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { + Ok(Quaternion { + coords: self.coords.deserialize(deserializer)?, + }) + } +} + impl Quaternion where T::Element: SimdRealField, diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 92747dab..7f3665ae 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -26,7 +26,6 @@ use crate::geometry::Point; /// A translation. #[repr(C)] #[derive(Debug)] -#[cfg_attr(feature = "rkyv-serialize-no-std", derive(Archive, Deserialize, Serialize))] pub struct Translation { /// The translation coordinates, i.e., how much is added to a point's coordinates when it is /// translated. @@ -101,6 +100,39 @@ where } } +#[cfg(feature = "rkyv-serialize-no-std")] +impl Archive for Translation { + type Archived = Translation; + type Resolver = as Archive>::Resolver; + + fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut core::mem::MaybeUninit) { + self.vector.resolve( + pos + rkyv::offset_of!(Self::Archived, vector), + resolver, + rkyv::project_struct!(out: Self::Archived => vector) + ); + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl, S: rkyv::Fallible + ?Sized, const D: usize> Serialize for Translation { + fn serialize(&self, serializer: &mut S) -> Result { + Ok(self.vector.serialize(serializer)?) + } +} + +#[cfg(feature = "rkyv-serialize-no-std")] +impl Deserialize, _D> for Translation +where + T::Archived: Deserialize, +{ + fn deserialize(&self, deserializer: &mut _D) -> Result, _D::Error> { + Ok(Translation { + vector: self.vector.deserialize(deserializer)?, + }) + } +} + impl Translation { /// Creates a new translation from the given vector. #[inline]