Merge pull request #1095 from zyansheep/dev

improve rkyv support
This commit is contained in:
Sébastien Crozet 2022-04-30 10:56:49 +02:00 committed by GitHub
commit a195e3547b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 80 additions and 352 deletions

View File

@ -53,7 +53,7 @@ convert-glam020 = [ "glam020" ]
serde-serialize-no-std = [ "serde", "num-complex/serde" ]
serde-serialize = [ "serde-serialize-no-std", "serde/std" ]
rkyv-serialize-no-std = [ "rkyv" ]
rkyv-serialize = [ "rkyv-serialize-no-std", "rkyv/std" ]
rkyv-serialize = [ "rkyv-serialize-no-std", "rkyv/std", "bytecheck" ]
# Randomness
## To use rand in a #[no-std] environment, enable the
@ -79,7 +79,8 @@ alga = { version = "0.9", default-features = false, optional = true }
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 }
rkyv = { version = "~0.6.4", default-features = false, features = ["const_generics"], optional = true }
rkyv = { version = "~0.7.1", optional = true }
bytecheck = { version = "~0.6.1", optional = true }
mint = { version = "0.5", optional = true }
quickcheck = { version = "1", optional = true }
pest = { version = "2", optional = true }

View File

@ -27,6 +27,11 @@ use std::mem;
/// A array-based statically sized matrix data storage.
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct ArrayStorage<T, const R: usize, const C: usize>(pub [[T; R]; C]);
@ -273,45 +278,3 @@ unsafe impl<T: Scalar + Copy + bytemuck::Pod, const R: usize, const C: usize> by
for ArrayStorage<T, R, C>
{
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::ArrayStorage;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive, const R: usize, const C: usize> Archive for ArrayStorage<T, R, C> {
type Archived = ArrayStorage<T::Archived, R, C>;
type Resolver = <[[T; R]; C] as Archive>::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.0.resolve(
pos + offset_of!(Self::Archived, 0),
resolver,
project_struct!(out: Self::Archived => 0),
);
}
}
impl<T: Serialize<S>, S: Fallible + ?Sized, const R: usize, const C: usize> Serialize<S>
for ArrayStorage<T, R, C>
{
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
self.0.serialize(serializer)
}
}
impl<T: Archive, D: Fallible + ?Sized, const R: usize, const C: usize>
Deserialize<ArrayStorage<T, R, C>, D> for ArrayStorage<T::Archived, R, C>
where
T::Archived: Deserialize<T, D>,
{
fn deserialize(&self, deserializer: &mut D) -> Result<ArrayStorage<T, R, C>, D::Error> {
Ok(ArrayStorage(self.0.deserialize(deserializer)?))
}
}
}

View File

@ -13,6 +13,11 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// Dim of dynamically-sized algebraic entities.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct Dynamic {
value: usize,
@ -198,6 +203,11 @@ dim_ops!(
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct Const<const R: usize>;
@ -233,37 +243,6 @@ impl<'de, const D: usize> Deserialize<'de> for Const<D> {
}
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Const;
use rkyv::{Archive, Deserialize, Fallible, Serialize};
impl<const R: usize> Archive for Const<R> {
type Archived = Self;
type Resolver = ();
fn resolve(
&self,
_: usize,
_: Self::Resolver,
_: &mut core::mem::MaybeUninit<Self::Archived>,
) {
}
}
impl<S: Fallible + ?Sized, const R: usize> Serialize<S> for Const<R> {
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
Ok(())
}
}
impl<D: Fallible + ?Sized, const R: usize> Deserialize<Self, D> for Const<R> {
fn deserialize(&self, _: &mut D) -> Result<Self, D::Error> {
Ok(Const)
}
}
}
pub trait ToConst {
type Const: DimName;
}

View File

@ -150,6 +150,11 @@ pub type MatrixCross<T, R1, C1, R2, C2> =
/// some concrete types for `T` and a compatible data storage type `S`).
#[repr(C)]
#[derive(Clone, Copy)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct Matrix<T, R, C, S> {
/// The data storage that contains all the matrix components. Disappointed?
@ -288,53 +293,6 @@ where
{
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Matrix;
use core::marker::PhantomData;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive, R: Archive, C: Archive, S: Archive> Archive for Matrix<T, R, C, S> {
type Archived = Matrix<T::Archived, R::Archived, C::Archived, S::Archived>;
type Resolver = S::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.data.resolve(
pos + offset_of!(Self::Archived, data),
resolver,
project_struct!(out: Self::Archived => data),
);
}
}
impl<T: Archive, R: Archive, C: Archive, S: Serialize<_S>, _S: Fallible + ?Sized> Serialize<_S>
for Matrix<T, R, C, S>
{
fn serialize(&self, serializer: &mut _S) -> Result<Self::Resolver, _S::Error> {
self.data.serialize(serializer)
}
}
impl<T: Archive, R: Archive, C: Archive, S: Archive, D: Fallible + ?Sized>
Deserialize<Matrix<T, R, C, S>, D>
for Matrix<T::Archived, R::Archived, C::Archived, S::Archived>
where
S::Archived: Deserialize<S, D>,
{
fn deserialize(&self, deserializer: &mut D) -> Result<Matrix<T, R, C, S>, D::Error> {
Ok(Matrix {
data: self.data.deserialize(deserializer)?,
_phantoms: PhantomData,
})
}
}
}
impl<T, R, C, S> Matrix<T, R, C, S> {
/// Creates a new matrix with the given data without statically checking that the matrix
/// dimension matches the storage dimension.

View File

@ -21,6 +21,11 @@ use crate::{Dim, Matrix, OMatrix, RealField, Scalar, SimdComplexField, SimdRealF
/// in their documentation, read their dedicated pages directly.
#[repr(transparent)]
#[derive(Clone, Hash, Copy)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
// #[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct Unit<T> {
pub(crate) value: T,
@ -58,47 +63,6 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for Unit<T> {
}
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Unit;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive> Archive for Unit<T> {
type Archived = Unit<T::Archived>;
type Resolver = T::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut ::core::mem::MaybeUninit<Self::Archived>,
) {
self.value.resolve(
pos + offset_of!(Self::Archived, value),
resolver,
project_struct!(out: Self::Archived => value),
);
}
}
impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for Unit<T> {
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
self.value.serialize(serializer)
}
}
impl<T: Archive, D: Fallible + ?Sized> Deserialize<Unit<T>, D> for Unit<T::Archived>
where
T::Archived: Deserialize<T, D>,
{
fn deserialize(&self, deserializer: &mut D) -> Result<Unit<T>, D::Error> {
Ok(Unit {
value: self.value.deserialize(deserializer)?,
})
}
}
}
#[cfg(feature = "cuda")]
unsafe impl<T: cust_core::DeviceCopy, R, C, S> cust_core::DeviceCopy for Unit<Matrix<T, R, C, S>>
where

View File

@ -40,6 +40,11 @@ use simba::scalar::{ClosedNeg, RealField};
/// See <https://github.com/dimforge/nalgebra/issues/487>
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct DualQuaternion<T> {
/// The real component of the quaternion

View File

@ -66,6 +66,11 @@ use crate::geometry::{AbstractRotation, Point, Translation};
Owned<T, Const<D>>: Deserialize<'de>,
T: Scalar"))
)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct Isometry<T, R, const D: usize> {
/// The pure rotational part of this isometry.
pub rotation: R,
@ -73,66 +78,6 @@ pub struct Isometry<T, R, const D: usize> {
pub translation: Translation<T, D>,
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Isometry;
use crate::{base::Scalar, geometry::Translation};
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Scalar + Archive, R: Archive, const D: usize> Archive for Isometry<T, R, D>
where
T::Archived: Scalar,
{
type Archived = Isometry<T::Archived, R::Archived, D>;
type Resolver = (R::Resolver, <Translation<T, D> as Archive>::Resolver);
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.rotation.resolve(
pos + offset_of!(Self::Archived, rotation),
resolver.0,
project_struct!(out: Self::Archived => rotation),
);
self.translation.resolve(
pos + offset_of!(Self::Archived, translation),
resolver.1,
project_struct!(out: Self::Archived => translation),
);
}
}
impl<T: Scalar + Serialize<S>, R: Serialize<S>, S: Fallible + ?Sized, const D: usize>
Serialize<S> for Isometry<T, R, D>
where
T::Archived: Scalar,
{
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
Ok((
self.rotation.serialize(serializer)?,
self.translation.serialize(serializer)?,
))
}
}
impl<T: Scalar + Archive, R: Archive, _D: Fallible + ?Sized, const D: usize>
Deserialize<Isometry<T, R, D>, _D> for Isometry<T::Archived, R::Archived, D>
where
T::Archived: Scalar + Deserialize<T, _D>,
R::Archived: Scalar + Deserialize<R, _D>,
{
fn deserialize(&self, deserializer: &mut _D) -> Result<Isometry<T, R, D>, _D::Error> {
Ok(Isometry {
rotation: self.rotation.deserialize(deserializer)?,
translation: self.translation.deserialize(deserializer)?,
})
}
}
}
impl<T: Scalar + hash::Hash, R: hash::Hash, const D: usize> hash::Hash for Isometry<T, R, D>
where
Owned<T, Const<D>>: hash::Hash,

View File

@ -19,6 +19,11 @@ use crate::geometry::{Point3, Projective3};
/// A 3D orthographic projection stored as a homogeneous 4x4 matrix.
#[repr(C)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[derive(Copy, Clone)]
pub struct Orthographic3<T> {

View File

@ -20,6 +20,11 @@ use crate::geometry::{Point3, Projective3};
/// A 3D perspective projection stored as a homogeneous 4x4 matrix.
#[repr(C)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[derive(Copy, Clone)]
pub struct Perspective3<T> {

View File

@ -36,6 +36,11 @@ use std::mem::MaybeUninit;
/// of said transformations for details.
#[repr(C)]
#[derive(Clone)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct OPoint<T: Scalar, D: DimName>
where
DefaultAllocator: Allocator<T, D>,

View File

@ -23,6 +23,11 @@ use crate::geometry::{Point3, Rotation};
/// that may be used as a rotation.
#[repr(C)]
#[derive(Copy, Clone)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct Quaternion<T> {
/// This quaternion as a 4D vector of coordinates in the `[ x, y, z, w ]` storage order.
@ -97,48 +102,6 @@ where
}
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Quaternion;
use crate::base::Vector4;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive> Archive for Quaternion<T> {
type Archived = Quaternion<T::Archived>;
type Resolver = <Vector4<T> as Archive>::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.coords.resolve(
pos + offset_of!(Self::Archived, coords),
resolver,
project_struct!(out: Self::Archived => coords),
);
}
}
impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for Quaternion<T> {
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
self.coords.serialize(serializer)
}
}
impl<T: Archive, D: Fallible + ?Sized> Deserialize<Quaternion<T>, D> for Quaternion<T::Archived>
where
T::Archived: Deserialize<T, D>,
{
fn deserialize(&self, deserializer: &mut D) -> Result<Quaternion<T>, D::Error> {
Ok(Quaternion {
coords: self.coords.deserialize(deserializer)?,
})
}
}
}
impl<T: SimdRealField> Quaternion<T>
where
T::Element: SimdRealField,

View File

@ -49,6 +49,11 @@ use crate::geometry::Point;
/// * [Conversion to a matrix <span style="float:right;">`matrix`, `to_homogeneous`…</span>](#conversion-to-a-matrix)
///
#[repr(C)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[derive(Copy, Clone)]
pub struct Rotation<T, const D: usize> {

View File

@ -17,6 +17,11 @@ use crate::geometry::Point;
/// A scale which supports non-uniform scaling.
#[repr(C)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[derive(Copy, Clone)]
pub struct Scale<T, const D: usize> {
@ -84,49 +89,6 @@ where
}
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Scale;
use crate::base::SVector;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive, const D: usize> Archive for Scale<T, D> {
type Archived = Scale<T::Archived, D>;
type Resolver = <SVector<T, D> as Archive>::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.vector.resolve(
pos + offset_of!(Self::Archived, vector),
resolver,
project_struct!(out: Self::Archived => vector),
);
}
}
impl<T: Serialize<S>, S: Fallible + ?Sized, const D: usize> Serialize<S> for Scale<T, D> {
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
self.vector.serialize(serializer)
}
}
impl<T: Archive, _D: Fallible + ?Sized, const D: usize> Deserialize<Scale<T, D>, _D>
for Scale<T::Archived, D>
where
T::Archived: Deserialize<T, _D>,
{
fn deserialize(&self, deserializer: &mut _D) -> Result<Scale<T, D>, _D::Error> {
Ok(Scale {
vector: self.vector.deserialize(deserializer)?,
})
}
}
}
impl<T: Scalar, const D: usize> Scale<T, D> {
/// Inverts `self`.
///

View File

@ -34,6 +34,11 @@ use crate::geometry::{AbstractRotation, Isometry, Point, Translation};
DefaultAllocator: Allocator<T, Const<D>>,
Owned<T, Const<D>>: Deserialize<'de>"))
)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct Similarity<T, R, const D: usize> {
/// The part of this similarity that does not include the scaling factor.
pub isometry: Isometry<T, R, D>,

View File

@ -17,6 +17,11 @@ use crate::geometry::Point;
/// A translation.
#[repr(C)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[derive(Copy, Clone)]
pub struct Translation<T, const D: usize> {
@ -84,49 +89,6 @@ where
}
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Translation;
use crate::base::SVector;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive, const D: usize> Archive for Translation<T, D> {
type Archived = Translation<T::Archived, D>;
type Resolver = <SVector<T, D> as Archive>::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.vector.resolve(
pos + offset_of!(Self::Archived, vector),
resolver,
project_struct!(out: Self::Archived => vector),
);
}
}
impl<T: Serialize<S>, S: Fallible + ?Sized, const D: usize> Serialize<S> for Translation<T, D> {
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
self.vector.serialize(serializer)
}
}
impl<T: Archive, _D: Fallible + ?Sized, const D: usize> Deserialize<Translation<T, D>, _D>
for Translation<T::Archived, D>
where
T::Archived: Deserialize<T, _D>,
{
fn deserialize(&self, deserializer: &mut _D) -> Result<Translation<T, D>, _D::Error> {
Ok(Translation {
vector: self.vector.deserialize(deserializer)?,
})
}
}
}
impl<T: Scalar, const D: usize> Translation<T, D> {
/// Creates a new translation from the given vector.
#[inline]

View File

@ -78,12 +78,13 @@ an optimized set of tools for computer graphics and physics. Those features incl
unused_mut,
unused_parens,
unused_qualifications,
unused_results,
rust_2018_idioms,
rust_2018_compatibility,
future_incompatible,
missing_copy_implementations
)]
#![cfg_attr(feature = "rkyv-serialize-no-std", warn(unused_results))] // TODO: deny this once bytecheck stops generating warnings.
#![cfg_attr(not(feature = "rkyv-serialize-no-std"), deny(unused_results))]
#![doc(
html_favicon_url = "https://nalgebra.org/img/favicon.ico",
html_root_url = "https://docs.rs/nalgebra/0.25.0"