From f3673a1d4c900f3832ba0210d560a31b618333a2 Mon Sep 17 00:00:00 2001 From: Romain Vaillant Date: Sun, 15 May 2016 14:48:57 +0200 Subject: [PATCH 1/5] makes rustc-serialize optional --- Cargo.toml | 3 ++- src/angle.rs | 6 ++++-- src/euler.rs | 2 +- src/lib.rs | 4 +++- src/matrix.rs | 9 ++++++--- src/point.rs | 9 ++++++--- src/projection.rs | 9 ++++++--- src/quaternion.rs | 3 ++- src/rotation.rs | 6 ++++-- src/transform.rs | 3 ++- src/vector.rs | 12 ++++++++---- 11 files changed, 44 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f02dbf..6f1e237 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,12 @@ name = "cgmath" [features] unstable = [] +default = ["rustc-serialize"] [dependencies] num-traits = "0.1" rand = "0.3" -rustc-serialize = "0.3" +rustc-serialize = { version = "0.3", optional = true } [dev-dependencies] glium = "0.14.0" diff --git a/src/angle.rs b/src/angle.rs index 7ee16b7..f42cd1b 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -32,14 +32,16 @@ use num::BaseFloat; /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(Copy, Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, PartialOrd)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Rad { pub s: S } /// An angle, in degrees. /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(Copy, Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, PartialOrd)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Deg { pub s: S } /// Create a new angle, in radians diff --git a/src/euler.rs b/src/euler.rs index ec28b45..808cac7 100644 --- a/src/euler.rs +++ b/src/euler.rs @@ -64,7 +64,7 @@ use num::BaseFloat; #[repr(C, packed)] #[derive(Copy, Clone, Debug)] #[derive(PartialEq, Eq)] -#[derive(RustcEncodable, RustcDecodable)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Euler { /// The angle to apply around the _x_ axis. Also known at the _pitch_. pub x: A, diff --git a/src/lib.rs b/src/lib.rs index 58ee237..1e4ec98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,9 +51,11 @@ //! ``` pub extern crate num_traits; -extern crate rustc_serialize; extern crate rand; +#[cfg(feature = "rustc-serialize")] +extern crate rustc_serialize; + // Re-exports pub use approx::*; diff --git a/src/matrix.rs b/src/matrix.rs index 8b98632..bdddeb0 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -35,7 +35,8 @@ use vector::{Vector2, Vector3, Vector4}; /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Matrix2 { /// The first column of the matrix. pub x: Vector2, @@ -47,7 +48,8 @@ pub struct Matrix2 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Matrix3 { /// The first column of the matrix. pub x: Vector3, @@ -61,7 +63,8 @@ pub struct Matrix3 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Matrix4 { /// The first column of the matrix. pub x: Vector4, diff --git a/src/point.rs b/src/point.rs index 4a808a2..19c2e0b 100644 --- a/src/point.rs +++ b/src/point.rs @@ -31,7 +31,8 @@ use vector::{Vector1, Vector2, Vector3, Vector4}; /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Point1 { pub x: S, } @@ -40,7 +41,8 @@ pub struct Point1 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Point2 { pub x: S, pub y: S, @@ -50,7 +52,8 @@ pub struct Point2 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Point3 { pub x: S, pub y: S, diff --git a/src/projection.rs b/src/projection.rs index 5bbac10..525073b 100644 --- a/src/projection.rs +++ b/src/projection.rs @@ -66,7 +66,8 @@ pub fn ortho(left: S, right: S, bottom: S, top: S, near: S, far: S } /// A perspective projection based on a vertical field-of-view angle. -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct PerspectiveFov { pub fovy: Rad, pub aspect: S, @@ -132,7 +133,8 @@ impl From> for Matrix4 { } /// A perspective projection with arbitrary left/right/bottom/top distances -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Perspective { pub left: S, pub right: S, @@ -178,7 +180,8 @@ impl From> for Matrix4 { } /// An orthographic projection with arbitrary left/right/bottom/top distances -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Ortho { pub left: S, pub right: S, diff --git a/src/quaternion.rs b/src/quaternion.rs index 1b5a1ff..da9fe6a 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -36,7 +36,8 @@ use vector::Vector3; /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Quaternion { /// The scalar part of the quaternion. pub s: S, diff --git a/src/rotation.rs b/src/rotation.rs index d819de0..3108af7 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -137,7 +137,8 @@ pub trait Rotation3: Rotation> /// let unit_y3 = (rot_half * rot_half).rotate_vector(unit_x); /// assert!(unit_y3.approx_eq(&unit_y2)); /// ``` -#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Copy, Clone)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Basis2 { mat: Matrix2 } @@ -209,7 +210,8 @@ impl fmt::Debug for Basis2 { /// inversion, can be implemented more efficiently than the implementations for /// `math::Matrix3`. To ensure orthogonality is maintained, the operations have /// been restricted to a subeset of those implemented on `Matrix3`. -#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Copy, Clone)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Basis3 { mat: Matrix3 } diff --git a/src/transform.rs b/src/transform.rs index 9ad25e8..b033ab6 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -56,7 +56,8 @@ pub trait Transform: Sized { /// A generic transformation consisting of a rotation, /// displacement vector and scale amount. -#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Decomposed { pub scale: V::Scalar, pub rot: R, diff --git a/src/vector.rs b/src/vector.rs index b5ecf03..a0f5a82 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -29,7 +29,8 @@ use num::{BaseNum, BaseFloat, PartialOrd}; /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Vector1 { /// The x component of the vector. pub x: S, @@ -39,7 +40,8 @@ pub struct Vector1 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Vector2 { /// The x component of the vector. pub x: S, @@ -51,7 +53,8 @@ pub struct Vector2 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Vector3 { /// The x component of the vector. pub x: S, @@ -65,7 +68,8 @@ pub struct Vector3 { /// /// This type is marked as `#[repr(C, packed)]`. #[repr(C, packed)] -#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)] +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct Vector4 { /// The x component of the vector. pub x: S, From cdbb9294e07b2814ab07f731383397652fd1e60f Mon Sep 17 00:00:00 2001 From: Romain Vaillant Date: Mon, 16 May 2016 14:16:59 +0200 Subject: [PATCH 2/5] Adds serde support --- Cargo.toml | 3 + src/angle.rs | 2 + src/euler.rs | 1 + src/lib.rs | 6 ++ src/matrix.rs | 3 + src/point.rs | 3 + src/projection.rs | 3 + src/quaternion.rs | 1 + src/rotation.rs | 2 + src/transform.rs | 147 ++++++++++++++++++++++++++++++++++++++++++++++ src/vector.rs | 4 ++ 11 files changed, 175 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 6f1e237..b126b45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,11 +29,14 @@ name = "cgmath" [features] unstable = [] default = ["rustc-serialize"] +eders = ["serde", "serde_macros"] [dependencies] num-traits = "0.1" rand = "0.3" rustc-serialize = { version = "0.3", optional = true } +serde = { version = "0.7", optional = true } +serde_macros = { version = "0.7", optional = true } [dev-dependencies] glium = "0.14.0" diff --git a/src/angle.rs b/src/angle.rs index f42cd1b..c434129 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -34,6 +34,7 @@ use num::BaseFloat; #[repr(C, packed)] #[derive(Copy, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Rad { pub s: S } /// An angle, in degrees. @@ -42,6 +43,7 @@ pub struct Rad { pub s: S } #[repr(C, packed)] #[derive(Copy, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Deg { pub s: S } /// Create a new angle, in radians diff --git a/src/euler.rs b/src/euler.rs index 808cac7..df72875 100644 --- a/src/euler.rs +++ b/src/euler.rs @@ -65,6 +65,7 @@ use num::BaseFloat; #[derive(Copy, Clone, Debug)] #[derive(PartialEq, Eq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Euler { /// The angle to apply around the _x_ axis. Also known at the _pitch_. pub x: A, diff --git a/src/lib.rs b/src/lib.rs index 1e4ec98..2efb293 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,12 +50,18 @@ //! use cgmath::prelude::*; //! ``` +#![cfg_attr(feature = "eders", feature(plugin, custom_derive))] +#![cfg_attr(feature = "eders", plugin(serde_macros))] + pub extern crate num_traits; extern crate rand; #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; +#[cfg(feature = "eders")] +extern crate serde; + // Re-exports pub use approx::*; diff --git a/src/matrix.rs b/src/matrix.rs index bdddeb0..7336783 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -37,6 +37,7 @@ use vector::{Vector2, Vector3, Vector4}; #[repr(C, packed)] #[derive(Copy, Clone, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Matrix2 { /// The first column of the matrix. pub x: Vector2, @@ -50,6 +51,7 @@ pub struct Matrix2 { #[repr(C, packed)] #[derive(Copy, Clone, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Matrix3 { /// The first column of the matrix. pub x: Vector3, @@ -65,6 +67,7 @@ pub struct Matrix3 { #[repr(C, packed)] #[derive(Copy, Clone, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Matrix4 { /// The first column of the matrix. pub x: Vector4, diff --git a/src/point.rs b/src/point.rs index 19c2e0b..8ee8393 100644 --- a/src/point.rs +++ b/src/point.rs @@ -33,6 +33,7 @@ use vector::{Vector1, Vector2, Vector3, Vector4}; #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Point1 { pub x: S, } @@ -43,6 +44,7 @@ pub struct Point1 { #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Point2 { pub x: S, pub y: S, @@ -54,6 +56,7 @@ pub struct Point2 { #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Point3 { pub x: S, pub y: S, diff --git a/src/projection.rs b/src/projection.rs index 525073b..d650aa6 100644 --- a/src/projection.rs +++ b/src/projection.rs @@ -68,6 +68,7 @@ pub fn ortho(left: S, right: S, bottom: S, top: S, near: S, far: S /// A perspective projection based on a vertical field-of-view angle. #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct PerspectiveFov { pub fovy: Rad, pub aspect: S, @@ -135,6 +136,7 @@ impl From> for Matrix4 { /// A perspective projection with arbitrary left/right/bottom/top distances #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Perspective { pub left: S, pub right: S, @@ -182,6 +184,7 @@ impl From> for Matrix4 { /// An orthographic projection with arbitrary left/right/bottom/top distances #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Ortho { pub left: S, pub right: S, diff --git a/src/quaternion.rs b/src/quaternion.rs index da9fe6a..7556330 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -38,6 +38,7 @@ use vector::Vector3; #[repr(C, packed)] #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Quaternion { /// The scalar part of the quaternion. pub s: S, diff --git a/src/rotation.rs b/src/rotation.rs index 3108af7..5b570c4 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -139,6 +139,7 @@ pub trait Rotation3: Rotation> /// ``` #[derive(PartialEq, Copy, Clone)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Basis2 { mat: Matrix2 } @@ -212,6 +213,7 @@ impl fmt::Debug for Basis2 { /// been restricted to a subeset of those implemented on `Matrix3`. #[derive(PartialEq, Copy, Clone)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Basis3 { mat: Matrix3 } diff --git a/src/transform.rs b/src/transform.rs index b033ab6..54a25a0 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -148,3 +148,150 @@ impl> From, R>> for Matrix4< impl> Transform2 for Decomposed, R> {} impl> Transform3 for Decomposed, R> {} + +#[cfg(feature = "eders")] +#[doc(hidden)] +mod eders_ser { + use structure::VectorSpace; + use super::Decomposed; + use serde::{self, Serialize}; + + impl Serialize for Decomposed + where V: Serialize, V::Scalar: Serialize, R: Serialize + { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + serializer.serialize_struct("Decomposed", DecomposedVisitor { + value: self, + state: 0, + }) + } + } + + struct DecomposedVisitor<'a, V: 'a + VectorSpace, R: 'a> { + value: &'a Decomposed, + state: u8, + } + + impl<'a, V: 'a + VectorSpace, R> serde::ser::MapVisitor for DecomposedVisitor<'a, V, R> + where V: Serialize, V::Scalar: Serialize, R: Serialize + { + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> + where S: serde::Serializer + { + match self.state { + 0 => { + self.state += 1; + Ok(Some(try!(serializer.serialize_struct_elt("scale", &self.value.scale)))) + }, + 1 => { + self.state += 1; + Ok(Some(try!(serializer.serialize_struct_elt("rot", &self.value.rot)))) + }, + 2 => { + self.state += 1; + Ok(Some(try!(serializer.serialize_struct_elt("disp", &self.value.disp)))) + }, + _ => { + Ok(None) + }, + } + } + } +} + +#[cfg(feature = "eders")] +#[doc(hidden)] +mod eders_de { + use structure::VectorSpace; + use super::Decomposed; + use serde::{self, Deserialize}; + use std::marker::PhantomData; + + enum DecomposedField { + Scale, + Rot, + Disp, + } + + impl Deserialize for DecomposedField { + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + struct DecomposedFieldVisitor; + + impl serde::de::Visitor for DecomposedFieldVisitor { + type Value = DecomposedField; + + fn visit_str(&mut self, value: &str) -> Result + where E: serde::de::Error + { + match value { + "scale" => Ok(DecomposedField::Scale), + "rot" => Ok(DecomposedField::Rot), + "disp" => Ok(DecomposedField::Disp), + _ => Err(serde::de::Error::custom("expected scale, rot or disp")), + } + } + } + + deserializer.deserialize(DecomposedFieldVisitor) + } + } + + impl Deserialize for Decomposed + where S: Deserialize, S::Scalar: Deserialize, R: Deserialize + { + fn deserialize(deserializer: &mut D) -> Result, D::Error> + where D: serde::de::Deserializer + { + const FIELDS: &'static [&'static str] = &["scale", "rot", "disp"]; + deserializer.deserialize_struct("Decomposed", FIELDS, DecomposedVisitor(PhantomData)) + } + } + + struct DecomposedVisitor(PhantomData<(S, R)>); + + impl serde::de::Visitor for DecomposedVisitor + where S: Deserialize, S::Scalar: Deserialize, R: Deserialize + { + type Value = Decomposed; + + fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> + where V: serde::de::MapVisitor + { + let mut scale = None; + let mut rot = None; + let mut disp = None; + + loop { + match try!(visitor.visit_key()) { + Some(DecomposedField::Scale) => { scale = Some(try!(visitor.visit_value())); }, + Some(DecomposedField::Rot) => { rot = Some(try!(visitor.visit_value())); }, + Some(DecomposedField::Disp) => { disp = Some(try!(visitor.visit_value())); }, + _ => { break; }, + } + } + + let scale = match scale { + Some(scale) => scale, + None => try!(visitor.missing_field("scale")), + }; + + let rot = match rot { + Some(rot) => rot, + None => try!(visitor.missing_field("rot")), + }; + + let disp = match disp { + Some(disp) => disp, + None => try!(visitor.missing_field("disp")), + }; + + try!(visitor.end()); + + Ok(Decomposed { scale: scale, rot: rot, disp: disp }) + } + } +} \ No newline at end of file diff --git a/src/vector.rs b/src/vector.rs index a0f5a82..d3c7997 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -31,6 +31,7 @@ use num::{BaseNum, BaseFloat, PartialOrd}; #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Vector1 { /// The x component of the vector. pub x: S, @@ -42,6 +43,7 @@ pub struct Vector1 { #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Vector2 { /// The x component of the vector. pub x: S, @@ -55,6 +57,7 @@ pub struct Vector2 { #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Vector3 { /// The x component of the vector. pub x: S, @@ -70,6 +73,7 @@ pub struct Vector3 { #[repr(C, packed)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] +#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))] pub struct Vector4 { /// The x component of the vector. pub x: S, From bfbbbe8445b997aff868b7df8385fcd4c0b84dc8 Mon Sep 17 00:00:00 2001 From: Romain Vaillant Date: Mon, 16 May 2016 14:22:18 +0200 Subject: [PATCH 3/5] Updates travis to support eders feature in nightly builds --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7033ead..0b377b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,8 @@ rust: env: global: - secure: afYeHpC8BJeyajd3vd84xRBYJKxQorKfh4lGvesu/hqh0bHc6lxrqGt0Pthb2m2YDODZiGSbx9yr9UetelZIJUSA3LoiG5PdDrtH/Kwdn5xGcBWSZl3v/sH+oB3AeR7Eji6mj0mrydQxn8PQbEACvR6lpGCYE2R48KrftYmD6Js= + - TRAVIS_CARGO_NIGHTLY_FEATURE="eders" + - secure: afYeHpC8BJeyajd3vd84xRBYJKxQorKfh4lGvesu/hqh0bHc6lxrqGt0Pthb2m2YDODZiGSbx9yr9UetelZIJUSA3LoiG5PdDrtH/Kwdn5xGcBWSZl3v/sH+oB3AeR7Eji6mj0mrydQxn8PQbEACvR6lpGCYE2R48KrftYmD6Js= before_script: - | From 118ec262fdf5e2ad7bd3efce4440a4d8cec176d0 Mon Sep 17 00:00:00 2001 From: Romain Vaillant Date: Mon, 16 May 2016 15:22:37 +0200 Subject: [PATCH 4/5] Adds ApproxEq for Decomposed --- src/transform.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/transform.rs b/src/transform.rs index 54a25a0..284d647 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -149,6 +149,18 @@ impl> Transform2 for Decomposed, R> impl> Transform3 for Decomposed, R> {} +impl ApproxEq for Decomposed + where S: ApproxEq, S::Scalar: ApproxEq, R: ApproxEq +{ + type Epsilon = E; + + fn approx_eq_eps(&self, other: &Self, epsilon: &Self::Epsilon) -> bool { + self.scale.approx_eq_eps(&other.scale, epsilon) && + self.rot.approx_eq_eps(&other.rot, epsilon) && + self.disp.approx_eq_eps(&other.disp, epsilon) + } +} + #[cfg(feature = "eders")] #[doc(hidden)] mod eders_ser { @@ -294,4 +306,4 @@ mod eders_de { Ok(Decomposed { scale: scale, rot: rot, disp: disp }) } } -} \ No newline at end of file +} From bb5eed1af6dae1bf45a51be5fe6235bc4c73ce54 Mon Sep 17 00:00:00 2001 From: Romain Vaillant Date: Mon, 16 May 2016 15:24:11 +0200 Subject: [PATCH 5/5] Add serde serialization test --- Cargo.toml | 1 + tests/transform.rs | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b126b45..41ab5e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,4 @@ serde_macros = { version = "0.7", optional = true } [dev-dependencies] glium = "0.14.0" +serde_json = "0.7" diff --git a/tests/transform.rs b/tests/transform.rs index e83372f..1688c69 100644 --- a/tests/transform.rs +++ b/tests/transform.rs @@ -16,28 +16,46 @@ extern crate cgmath; +#[cfg(feature = "eders")] +extern crate serde_json; + use cgmath::*; #[test] fn test_invert() { - let v = Vector3::new(1.0f64, 2.0, 3.0); - let t = Decomposed { + let v = Vector3::new(1.0f64, 2.0, 3.0); + let t = Decomposed { scale: 1.5f64, - rot: Quaternion::new(0.5f64,0.5,0.5,0.5), - disp: Vector3::new(6.0f64,-7.0,8.0) + rot: Quaternion::new(0.5f64, 0.5, 0.5, 0.5), + disp: Vector3::new(6.0f64, -7.0, 8.0), }; - let ti = t.inverse_transform().expect("Expected successful inversion"); - let vt = t.transform_vector(v); + let ti = t.inverse_transform().expect("Expected successful inversion"); + let vt = t.transform_vector(v); assert!(v.approx_eq(&ti.transform_vector(vt))); } #[test] fn test_look_at() { - let eye = Point3::new(0.0f64, 0.0, -5.0); - let center = Point3::new(0.0f64, 0.0, 0.0); - let up = Vector3::new(1.0f64, 0.0, 0.0); - let t: Decomposed, Quaternion> = Transform::look_at(eye, center, up); - let point = Point3::new(1.0f64, 0.0, 0.0); - let view_point = Point3::new(0.0f64, 1.0, 5.0); - assert!(t.transform_point(point).approx_eq(&view_point)); + let eye = Point3::new(0.0f64, 0.0, -5.0); + let center = Point3::new(0.0f64, 0.0, 0.0); + let up = Vector3::new(1.0f64, 0.0, 0.0); + let t: Decomposed, Quaternion> = Transform::look_at(eye, center, up); + let point = Point3::new(1.0f64, 0.0, 0.0); + let view_point = Point3::new(0.0f64, 1.0, 5.0); + assert!(t.transform_point(point).approx_eq(&view_point)); +} + +#[cfg(feature = "eders")] +#[test] +fn test_serialize() { + let t = Decomposed { + scale: 1.5f64, + rot: Quaternion::new(0.5f64, 0.5, 0.5, 0.5), + disp: Vector3::new(6.0f64, -7.0, 8.0), + }; + + let serialized = serde_json::to_string(&t).unwrap(); + let deserialized: Decomposed, Quaternion> = serde_json::from_str(&serialized).unwrap(); + + assert!(t.approx_eq(&deserialized)); }