Skip to content

Commit

Permalink
Implement serde traits for Variant types
Browse files Browse the repository at this point in the history
Fix Variant serialization
  • Loading branch information
Waridley committed Jun 3, 2021
1 parent c219871 commit f2b0d34
Show file tree
Hide file tree
Showing 21 changed files with 885 additions and 1 deletion.
1 change: 1 addition & 0 deletions gdnative-core/Cargo.toml
Expand Up @@ -24,6 +24,7 @@ glam = "0.15.1"
indexmap = "1.6.0"
ahash = "0.7.0"
once_cell = "1.7.2"
serde = { version = "1", default_features = false, features = ["derive"], optional = true }

gdnative-impl-proc-macros = { path = "../impl/proc_macros", version = "=0.9.3" }

Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/color.rs
Expand Up @@ -6,6 +6,7 @@ use crate::core_types::GodotString;
/// RGBA color with 32 bits floating point components.
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Color {
pub r: f32,
pub g: f32,
Expand Down
76 changes: 76 additions & 0 deletions gdnative-core/src/core_types/dictionary.rs
Expand Up @@ -544,6 +544,82 @@ where
}
}

#[cfg(feature = "serde")]
pub(super) mod serde {
use super::*;
use ::serde::{
de::{MapAccess, Visitor},
ser::SerializeMap,
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt::Formatter;

impl Serialize for Dictionary {
#[inline]
fn serialize<S>(&self, ser: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
let mut ser = ser.serialize_map(Some(self.len() as usize))?;
for (key, value) in self.iter() {
ser.serialize_entry(&key, &value)?
}
ser.end()
}
}

pub(in super::super) struct DictionaryVisitor;

impl<'de> Visitor<'de> for DictionaryVisitor {
type Value = Dictionary<Unique>;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a Dictionary")
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, <A as MapAccess<'de>>::Error>
where
A: MapAccess<'de>,
{
let dict = Dictionary::new();
while let Some((key, value)) = map.next_entry::<Variant, Variant>()? {
dict.insert(key, value)
}
Ok(dict)
}
}

impl<'de> Deserialize<'de> for Dictionary<Unique> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(DictionaryVisitor)
}
}

impl<'de> Deserialize<'de> for Dictionary<Shared> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Dictionary::<Unique>::deserialize(deserializer).map(Dictionary::into_shared)
}
}

impl<'de> Deserialize<'de> for Dictionary<ThreadLocal> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Dictionary::<Unique>::deserialize(deserializer).map(Dictionary::into_thread_local)
}
}
}

godot_test!(test_dictionary {
use std::collections::HashSet;

Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/error.rs
Expand Up @@ -2,6 +2,7 @@ use crate::sys;

/// Error codes used in various Godot APIs.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u32)]
pub enum GodotError {
Failed = sys::godot_error_GODOT_FAILED as u32,
Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/geom/aabb.rs
Expand Up @@ -3,6 +3,7 @@ use crate::core_types::Vector3;
/// Axis-aligned bounding box.
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Aabb {
pub position: Vector3,
pub size: Vector3,
Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/geom/basis.rs
Expand Up @@ -4,6 +4,7 @@ use core::ops::Mul;
/// A 3x3 matrix.
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Basis {
pub elements: [Vector3; 3],
}
Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/geom/plane.rs
Expand Up @@ -3,6 +3,7 @@ use crate::core_types::{IsEqualApprox, Vector3};
/// Plane in hessian form.
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Plane {
pub normal: Vector3,
pub d: f32,
Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/geom/transform.rs
Expand Up @@ -3,6 +3,7 @@ use crate::core_types::{Basis, Vector3};
/// 3D Transformation (3x4 matrix) Using basis + origin representation.
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Transform {
/// The basis is a matrix containing 3 Vector3 as its columns: X axis, Y axis, and Z axis.
/// These vectors can be interpreted as the basis vectors of local coordinate system
Expand Down
2 changes: 1 addition & 1 deletion gdnative-core/src/core_types/mod.rs
Expand Up @@ -43,7 +43,7 @@ pub use rid::*;
pub use string::*;
pub use string_array::*;
pub use transform2d::*;
pub use typed_array::TypedArray;
pub use typed_array::{Element, TypedArray};
pub use variant::*;
pub use variant_array::*;
pub use vector2::*;
Expand Down
64 changes: 64 additions & 0 deletions gdnative-core/src/core_types/node_path.rs
Expand Up @@ -176,3 +176,67 @@ impl fmt::Debug for NodePath {
write!(f, "NodePath({})", self.to_string())
}
}

#[cfg(feature = "serde")]
mod serde {
use super::*;
use ::serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt::Formatter;

impl Serialize for NodePath {
#[inline]
fn serialize<S>(&self, ser: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
ser.serialize_newtype_struct("NodePath", &*self.to_string())
}
}

impl<'de> Deserialize<'de> for NodePath {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct NodePathVisitor;

impl<'de> Visitor<'de> for NodePathVisitor {
type Value = NodePath;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a NodePath")
}

fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(NodePath::from_str(s))
}

fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
where
E: Error,
{
Ok(NodePath::from_str(&*s))
}

fn visit_newtype_struct<D>(
self,
deserializer: D,
) -> Result<Self::Value, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
}

deserializer.deserialize_newtype_struct("NodePath", NodePathVisitor)
}
}
}
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/quat.rs
@@ -1,6 +1,7 @@
use super::IsEqualApprox;

#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Quat {
pub x: f32,
Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/rect2.rs
@@ -1,5 +1,6 @@
use super::Vector2;

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Rect2 {
pub position: Vector2,
Expand Down
36 changes: 36 additions & 0 deletions gdnative-core/src/core_types/rid.rs
Expand Up @@ -84,3 +84,39 @@ impl PartialOrd for Rid {
}
}
}

#[cfg(feature = "serde")]
mod serde {
use super::*;
use ::serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::Formatter;

impl Serialize for Rid {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_unit()
}
}

impl<'de> Deserialize<'de> for Rid {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct RidVisitor;
impl<'de> Visitor<'de> for RidVisitor {
type Value = Rid;

fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("Unit as an RID placeholder")
}
}
deserializer.deserialize_unit(RidVisitor)?;
Ok(Rid::new())
}
}
}
49 changes: 49 additions & 0 deletions gdnative-core/src/core_types/string.rs
Expand Up @@ -612,6 +612,55 @@ where
}
}

#[cfg(feature = "serde")]
mod serde {
use super::*;
use ::serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt::Formatter;

impl Serialize for GodotString {
#[inline]
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
serializer.serialize_str(&*self.to_string())
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for GodotString {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
struct GodotStringVisitor;
impl<'de> Visitor<'de> for GodotStringVisitor {
type Value = GodotString;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a GodotString")
}

fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(GodotString::from(s))
}
}

deserializer.deserialize_str(GodotStringVisitor)
}
}
}
godot_test!(test_string {
use crate::core_types::{GodotString, Variant, VariantType, ToVariant};

Expand Down
1 change: 1 addition & 0 deletions gdnative-core/src/core_types/transform2d.rs
@@ -1,5 +1,6 @@
use super::Vector2;

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Transform2D {
pub x: Vector2,
Expand Down
60 changes: 60 additions & 0 deletions gdnative-core/src/core_types/typed_array.rs
Expand Up @@ -483,3 +483,63 @@ macros::impl_typed_array_element! {
mod private {
pub trait Sealed {}
}

#[cfg(feature = "serde")]
mod serde {
use super::*;
use ::serde::{
de::{SeqAccess, Visitor},
ser::SerializeSeq,
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt::Formatter;
use std::marker::PhantomData;

impl<T: Serialize + Element> Serialize for TypedArray<T> {
#[inline]
fn serialize<S>(&self, ser: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
let read = self.read();
let mut ser = ser.serialize_seq(Some(read.len()))?;
for e in read.iter() {
ser.serialize_element(e)?
}
ser.end()
}
}

impl<'de, T: Deserialize<'de> + Element> Deserialize<'de> for TypedArray<T> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
struct TypedArrayVisitor<T>(PhantomData<T>);
impl<'de, T: Deserialize<'de> + Element> Visitor<'de> for TypedArrayVisitor<T> {
type Value = TypedArray<T>;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str(std::any::type_name::<Self::Value>())
}

fn visit_seq<A>(
self,
mut seq: A,
) -> Result<Self::Value, <A as SeqAccess<'de>>::Error>
where
A: SeqAccess<'de>,
{
let mut vec = seq.size_hint().map_or_else(Vec::new, Vec::with_capacity);
while let Some(val) = seq.next_element::<T>()? {
vec.push(val);
}
Ok(Self::Value::from_vec(vec))
}
}

deserializer.deserialize_seq(TypedArrayVisitor::<T>(PhantomData))
}
}
}

0 comments on commit f2b0d34

Please sign in to comment.