Skip to content

Commit

Permalink
Merge pull request #80 from SlimeYummy/feat/serde
Browse files Browse the repository at this point in the history
Add serde support
  • Loading branch information
SlimeYummy authored Jun 11, 2024
2 parents 9a9db46 + 8a27811 commit 78c8317
Show file tree
Hide file tree
Showing 7 changed files with 577 additions and 351 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ resolver = "2"

[features]
default = ["rkyv"]
serde = ["dep:serde", "glam/serde", "bimap/serde" ]
rkyv = ["dep:rkyv", "dep:bytecheck", "glam/rkyv", "glam/bytecheck"]
wasm = []
nodejs = ["wasm", "dep:js-sys", "dep:wasm-bindgen"]
Expand All @@ -24,7 +25,8 @@ bimap = { version = "0.6" }
bytecheck = { version = "0.6", optional = true, default-features = false }
glam = { version = "0.25", features = [ "core-simd", "libm" ] }
js-sys = { version = "0.3", optional = true }
rkyv = { version = "0.7.43", optional = true, features = [ "validation" ] }
rkyv = { version = "0.7", optional = true, features = [ "validation" ] }
serde = { version= "1.0", optional = true, features = [ "serde_derive" ] }
static_assertions = "1.1"
thiserror = "1.0"
wasm-bindgen = { version = "0.2", optional = true }
Expand Down
7 changes: 5 additions & 2 deletions src/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::math::{f16_to_f32, fx4, ix4, simd_f16_to_f32, SoaQuat, SoaVec3};
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Float3Key {
pub ratio: f32,
pub track: u16,
Expand Down Expand Up @@ -53,6 +54,7 @@ impl ArchiveRead<Float3Key> for Float3Key {
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct QuaternionKey {
pub ratio: f32,
// track: 13 => The track this key frame belongs to.
Expand Down Expand Up @@ -203,6 +205,7 @@ impl ArchiveRead<QuaternionKey> for QuaternionKey {
///
#[derive(Debug, Default)]
#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Animation {
duration: f32,
num_tracks: usize,
Expand Down Expand Up @@ -271,7 +274,7 @@ impl Animation {
let translation_count: i32 = archive.read()?;
let rotation_count: i32 = archive.read()?;
let scale_count: i32 = archive.read()?;

let mut name = String::new();
if name_len != 0 {
let buf = archive.read_vec(name_len as usize)?;
Expand All @@ -292,7 +295,7 @@ impl Animation {
/// Reads an `Animation` from an `Archive`.
pub fn from_archive(archive: &mut Archive<impl Read>) -> Result<Animation, OzzError> {
let meta = Animation::read_meta(archive)?;

let translations: Vec<Float3Key> = archive.read_vec(meta.translation_count as usize)?;
let rotations: Vec<QuaternionKey> = archive.read_vec(meta.rotation_count as usize)?;
let scales: Vec<Float3Key> = archive.read_vec(meta.scale_count as usize)?;
Expand Down
238 changes: 143 additions & 95 deletions src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,47 +167,70 @@ impl SoaVec3 {
}

#[cfg(feature = "rkyv")]
impl rkyv::Archive for SoaVec3 {
type Archived = SoaVec3;
type Resolver = ();
const _: () = {
use bytecheck::CheckBytes;
use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
use std::io::{Error, ErrorKind};

impl Archive for SoaVec3 {
type Archived = SoaVec3;
type Resolver = ();

#[inline]
unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
out.write(to_archived!(*self as Self));
}
}

#[inline]
unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
out.write(rkyv::to_archived!(*self as Self));
impl<S: Fallible + ?Sized> Serialize<S> for SoaVec3 {
#[inline]
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
return Ok(());
}
}
}

#[cfg(feature = "rkyv")]
impl<S: rkyv::Fallible + ?Sized> rkyv::Serialize<S> for SoaVec3 {
#[inline]
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
return Ok(());
impl<D: Fallible + ?Sized> Deserialize<SoaVec3, D> for SoaVec3 {
#[inline]
fn deserialize(&self, _: &mut D) -> Result<SoaVec3, D::Error> {
return Ok(from_archived!(*self));
}
}
}

#[cfg(feature = "rkyv")]
impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<SoaVec3, D> for SoaVec3 {
#[inline]
fn deserialize(&self, _: &mut D) -> Result<SoaVec3, D::Error> {
return Ok(rkyv::from_archived!(*self));
impl<C: ?Sized> CheckBytes<C> for SoaVec3 {
type Error = Error;

#[inline]
unsafe fn check_bytes<'a>(value: *const Self, _: &mut C) -> Result<&'a Self, Self::Error> {
if value as usize % mem::align_of::<SoaVec3>() != 0 {
return Err(Error::new(ErrorKind::InvalidData, "must be aligned to 16 bytes"));
}
return Ok(&*value);
}
}
}
};

#[cfg(feature = "rkyv")]
impl<C: ?Sized> bytecheck::CheckBytes<C> for SoaVec3 {
type Error = std::io::Error;
#[cfg(feature = "serde")]
const _: () = {
use serde::ser::SerializeSeq;
use serde::{Deserialize, Serialize, Serializer};

#[inline]
unsafe fn check_bytes<'a>(value: *const Self, _: &mut C) -> Result<&'a Self, Self::Error> {
if value as usize % mem::align_of::<SoaVec3>() != 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"must be aligned to 16 bytes",
));
impl Serialize for SoaVec3 {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_seq(Some(3))?;
seq.serialize_element(&self.x.as_array())?;
seq.serialize_element(&self.y.as_array())?;
seq.serialize_element(&self.z.as_array())?;
return seq.end();
}
return Ok(&*value);
}
}

impl<'de> Deserialize<'de> for SoaVec3 {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let tmp: [[f32; 4]; 3] = Deserialize::deserialize(deserializer)?;
return Ok(SoaVec3::new(tmp[0], tmp[1], tmp[2]));
}
}
};

//
// SoaQuat
Expand Down Expand Up @@ -376,54 +399,79 @@ impl SoaQuat {
}

#[cfg(feature = "rkyv")]
impl rkyv::Archive for SoaQuat {
type Archived = SoaQuat;
type Resolver = ();

#[inline]
unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
out.write(rkyv::to_archived!(*self as Self));
const _: () = {
use bytecheck::CheckBytes;
use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
use std::io::{Error, ErrorKind};

impl Archive for SoaQuat {
type Archived = SoaQuat;
type Resolver = ();

#[inline]
unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
out.write(to_archived!(*self as Self));
}
}
}

#[cfg(feature = "rkyv")]
impl<S: rkyv::Fallible + ?Sized> rkyv::Serialize<S> for SoaQuat {
#[inline]
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
return Ok(());
impl<S: Fallible + ?Sized> Serialize<S> for SoaQuat {
#[inline]
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
return Ok(());
}
}
}

#[cfg(feature = "rkyv")]
impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<SoaQuat, D> for SoaQuat {
#[inline]
fn deserialize(&self, _: &mut D) -> Result<SoaQuat, D::Error> {
return Ok(rkyv::from_archived!(*self));
impl<D: Fallible + ?Sized> Deserialize<SoaQuat, D> for SoaQuat {
#[inline]
fn deserialize(&self, _: &mut D) -> Result<SoaQuat, D::Error> {
return Ok(from_archived!(*self));
}
}
}

#[cfg(feature = "rkyv")]
impl<C: ?Sized> bytecheck::CheckBytes<C> for SoaQuat {
type Error = std::io::Error;
impl<C: ?Sized> CheckBytes<C> for SoaQuat {
type Error = Error;

#[inline]
unsafe fn check_bytes<'a>(value: *const Self, _: &mut C) -> Result<&'a Self, Self::Error> {
if value as usize % mem::align_of::<SoaQuat>() != 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"must be aligned to 16 bytes",
));
#[inline]
unsafe fn check_bytes<'a>(value: *const Self, _: &mut C) -> Result<&'a Self, Self::Error> {
if value as usize % mem::align_of::<SoaQuat>() != 0 {
return Err(Error::new(ErrorKind::InvalidData, "must be aligned to 16 bytes"));
}
return Ok(&*value);
}
}
};

#[cfg(feature = "serde")]
const _: () = {
use serde::ser::SerializeSeq;
use serde::{Deserialize, Serialize, Serializer};

impl Serialize for SoaQuat {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_seq(Some(3))?;
seq.serialize_element(&self.x.as_array())?;
seq.serialize_element(&self.y.as_array())?;
seq.serialize_element(&self.z.as_array())?;
seq.serialize_element(&self.w.as_array())?;
return seq.end();
}
return Ok(&*value);
}
}

impl<'de> Deserialize<'de> for SoaQuat {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let tmp: [[f32; 4]; 4] = Deserialize::deserialize(deserializer)?;
return Ok(SoaQuat::new(tmp[0], tmp[1], tmp[2], tmp[3]));
}
}
};

//
// SoaTransform
//

#[repr(C)]
#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SoaTransform {
pub translation: SoaVec3,
pub rotation: SoaQuat,
Expand Down Expand Up @@ -452,47 +500,47 @@ impl SoaTransform {
}

#[cfg(feature = "rkyv")]
impl rkyv::Archive for SoaTransform {
type Archived = SoaTransform;
type Resolver = ();

#[inline]
unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
out.write(rkyv::to_archived!(*self as Self));
const _: () = {
use bytecheck::CheckBytes;
use rkyv::{from_archived, to_archived, Archive, Deserialize, Fallible, Serialize};
use std::io::{Error, ErrorKind};

impl Archive for SoaTransform {
type Archived = SoaTransform;
type Resolver = ();

#[inline]
unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
out.write(to_archived!(*self as Self));
}
}
}

#[cfg(feature = "rkyv")]
impl<S: rkyv::Fallible + ?Sized> rkyv::Serialize<S> for SoaTransform {
#[inline]
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
return Ok(());
impl<S: Fallible + ?Sized> Serialize<S> for SoaTransform {
#[inline]
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
return Ok(());
}
}
}

#[cfg(feature = "rkyv")]
impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<SoaTransform, D> for SoaTransform {
#[inline]
fn deserialize(&self, _: &mut D) -> Result<SoaTransform, D::Error> {
return Ok(rkyv::from_archived!(*self));
impl<D: Fallible + ?Sized> Deserialize<SoaTransform, D> for SoaTransform {
#[inline]
fn deserialize(&self, _: &mut D) -> Result<SoaTransform, D::Error> {
return Ok(from_archived!(*self));
}
}
}

#[cfg(feature = "rkyv")]
impl<C: ?Sized> bytecheck::CheckBytes<C> for SoaTransform {
type Error = std::io::Error;
impl<C: ?Sized> CheckBytes<C> for SoaTransform {
type Error = Error;

#[inline]
unsafe fn check_bytes<'a>(value: *const Self, _: &mut C) -> Result<&'a Self, Self::Error> {
if value as usize % mem::align_of::<SoaTransform>() != 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"must be aligned to 16 bytes",
));
#[inline]
unsafe fn check_bytes<'a>(value: *const Self, _: &mut C) -> Result<&'a Self, Self::Error> {
if value as usize % mem::align_of::<SoaTransform>() != 0 {
return Err(Error::new(ErrorKind::InvalidData, "must be aligned to 16 bytes"));
}
return Ok(&*value);
}
return Ok(&*value);
}
}
};

//
// AosMat4
Expand Down
Loading

0 comments on commit 78c8317

Please sign in to comment.