Skip to content

Commit a62bccc

Browse files
committed
serde support for core types & VariantDispatch
1 parent 831958c commit a62bccc

22 files changed

+822
-2
lines changed

gdnative-core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ glam = "0.18.0"
2424
indexmap = "1.7.0"
2525
ahash = "0.7.4"
2626
once_cell = "1.8.0"
27+
serde = { version = "1", features = ["derive"], optional = true }
2728

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

gdnative-core/src/core_types/color.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::core_types::GodotString;
66
/// RGBA color with 32 bits floating point components.
77
#[repr(C)]
88
#[derive(Copy, Clone, Debug, PartialEq)]
9+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
910
pub struct Color {
1011
pub r: f32,
1112
pub g: f32,

gdnative-core/src/core_types/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::sys;
22

33
/// Error codes used in various Godot APIs.
44
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56
#[repr(u32)]
67
pub enum GodotError {
78
Failed = sys::godot_error_GODOT_FAILED as u32,

gdnative-core/src/core_types/geom/aabb.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::core_types::Vector3;
33
/// Axis-aligned bounding box.
44
#[repr(C)]
55
#[derive(Copy, Clone, Debug, PartialEq)]
6+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67
pub struct Aabb {
78
pub position: Vector3,
89
pub size: Vector3,

gdnative-core/src/core_types/geom/basis.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use glam::Mat3;
55
/// A 3x3 matrix.
66
#[repr(C)]
77
#[derive(Copy, Clone, Debug, PartialEq)]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub struct Basis {
910
pub elements: [Vector3; 3],
1011
}

gdnative-core/src/core_types/geom/plane.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::core_types::{IsEqualApprox, Vector3};
33
/// Plane in hessian form.
44
#[repr(C)]
55
#[derive(Copy, Clone, Debug, PartialEq)]
6+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67
pub struct Plane {
78
pub normal: Vector3,
89
pub d: f32,

gdnative-core/src/core_types/geom/transform.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::core_types::{Basis, Vector3};
33
/// 3D Transformation (3x4 matrix) Using basis + origin representation.
44
#[repr(C)]
55
#[derive(Copy, Clone, Debug, PartialEq)]
6+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67
pub struct Transform {
78
/// The basis is a matrix containing 3 Vector3 as its columns: X axis, Y axis, and Z axis.
89
/// These vectors can be interpreted as the basis vectors of local coordinate system

gdnative-core/src/core_types/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub use rid::*;
4343
pub use string::*;
4444
pub use string_array::*;
4545
pub use transform2d::*;
46-
pub use typed_array::TypedArray;
46+
pub use typed_array::{Element, TypedArray};
4747
pub use variant::*;
4848
pub use variant_array::*;
4949
pub use vector2::*;

gdnative-core/src/core_types/node_path.rs

+57
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,60 @@ impl fmt::Debug for NodePath {
176176
write!(f, "NodePath({})", self.to_string())
177177
}
178178
}
179+
180+
#[cfg(feature = "serde")]
181+
mod serialize {
182+
use super::*;
183+
use serde::{
184+
de::{Error, Visitor},
185+
Deserialize, Deserializer, Serialize, Serializer,
186+
};
187+
use std::fmt::Formatter;
188+
189+
impl Serialize for NodePath {
190+
#[inline]
191+
fn serialize<S>(&self, ser: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
192+
where
193+
S: Serializer,
194+
{
195+
ser.serialize_newtype_struct("NodePath", &*self.to_string())
196+
}
197+
}
198+
199+
impl<'de> Deserialize<'de> for NodePath {
200+
#[inline]
201+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
202+
where
203+
D: Deserializer<'de>,
204+
{
205+
struct NodePathVisitor;
206+
207+
impl<'de> Visitor<'de> for NodePathVisitor {
208+
type Value = NodePath;
209+
210+
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
211+
formatter.write_str("a NodePath")
212+
}
213+
214+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
215+
where
216+
E: Error,
217+
{
218+
Ok(NodePath::from_str(s))
219+
}
220+
221+
fn visit_newtype_struct<D>(
222+
self,
223+
deserializer: D,
224+
) -> Result<Self::Value, <D as Deserializer<'de>>::Error>
225+
where
226+
D: Deserializer<'de>,
227+
{
228+
deserializer.deserialize_str(self)
229+
}
230+
}
231+
232+
deserializer.deserialize_newtype_struct("NodePath", NodePathVisitor)
233+
}
234+
}
235+
}

gdnative-core/src/core_types/quat.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use glam::EulerRot;
33
use std::ops::{Mul, Neg};
44

55
#[derive(Copy, Clone, Debug, PartialEq)]
6+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67
#[repr(C)]
78
pub struct Quat {
89
pub x: f32,

gdnative-core/src/core_types/rect2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::Vector2;
22

3+
#[derive(Copy, Clone, Debug, PartialEq)]
4+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35
#[repr(C)]
46
pub struct Rect2 {
57
pub position: Vector2,

gdnative-core/src/core_types/string.rs

+50
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,56 @@ where
612612
}
613613
}
614614

615+
#[cfg(feature = "serde")]
616+
mod serialize {
617+
use super::*;
618+
use serde::{
619+
de::{Error, Visitor},
620+
Deserialize, Deserializer, Serialize, Serializer,
621+
};
622+
use std::fmt::Formatter;
623+
624+
impl Serialize for GodotString {
625+
#[inline]
626+
fn serialize<S>(
627+
&self,
628+
serializer: S,
629+
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
630+
where
631+
S: Serializer,
632+
{
633+
serializer.serialize_str(&*self.to_string())
634+
}
635+
}
636+
637+
#[cfg(feature = "serde")]
638+
impl<'de> serialize::Deserialize<'de> for GodotString {
639+
#[inline]
640+
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
641+
where
642+
D: Deserializer<'de>,
643+
{
644+
struct GodotStringVisitor;
645+
impl<'de> Visitor<'de> for GodotStringVisitor {
646+
type Value = GodotString;
647+
648+
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
649+
formatter.write_str("a GodotString")
650+
}
651+
652+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
653+
where
654+
E: Error,
655+
{
656+
Ok(GodotString::from(s))
657+
}
658+
}
659+
660+
deserializer.deserialize_str(GodotStringVisitor)
661+
}
662+
}
663+
}
664+
615665
godot_test!(test_string {
616666
use crate::core_types::{GodotString, Variant, VariantType, ToVariant};
617667

gdnative-core/src/core_types/transform2d.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::Vector2;
22

3+
#[derive(Copy, Clone, Debug, PartialEq)]
4+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35
#[repr(C)]
46
pub struct Transform2D {
57
pub x: Vector2,

gdnative-core/src/core_types/typed_array.rs

+60
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,63 @@ macros::impl_typed_array_element! {
483483
mod private {
484484
pub trait Sealed {}
485485
}
486+
487+
#[cfg(feature = "serde")]
488+
mod serialize {
489+
use super::*;
490+
use serde::{
491+
de::{SeqAccess, Visitor},
492+
ser::SerializeSeq,
493+
Deserialize, Deserializer, Serialize, Serializer,
494+
};
495+
use std::fmt::Formatter;
496+
use std::marker::PhantomData;
497+
498+
impl<T: Serialize + Element> Serialize for TypedArray<T> {
499+
#[inline]
500+
fn serialize<S>(&self, ser: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
501+
where
502+
S: Serializer,
503+
{
504+
let read = self.read();
505+
let mut ser = ser.serialize_seq(Some(read.len()))?;
506+
for e in read.iter() {
507+
ser.serialize_element(e)?
508+
}
509+
ser.end()
510+
}
511+
}
512+
513+
impl<'de, T: Deserialize<'de> + Element> Deserialize<'de> for TypedArray<T> {
514+
#[inline]
515+
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
516+
where
517+
D: Deserializer<'de>,
518+
{
519+
struct TypedArrayVisitor<T>(PhantomData<T>);
520+
impl<'de, T: Deserialize<'de> + Element> Visitor<'de> for TypedArrayVisitor<T> {
521+
type Value = TypedArray<T>;
522+
523+
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
524+
formatter.write_str(std::any::type_name::<Self::Value>())
525+
}
526+
527+
fn visit_seq<A>(
528+
self,
529+
mut seq: A,
530+
) -> Result<Self::Value, <A as SeqAccess<'de>>::Error>
531+
where
532+
A: SeqAccess<'de>,
533+
{
534+
let mut vec = seq.size_hint().map_or_else(Vec::new, Vec::with_capacity);
535+
while let Some(val) = seq.next_element::<T>()? {
536+
vec.push(val);
537+
}
538+
Ok(Self::Value::from_vec(vec))
539+
}
540+
}
541+
542+
deserializer.deserialize_seq(TypedArrayVisitor::<T>(PhantomData))
543+
}
544+
}
545+
}

gdnative-core/src/core_types/variant.rs

+32
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use crate::object::*;
99
use crate::private::{get_api, ManuallyManagedClassPlaceholder};
1010
use crate::thread_access::*;
1111

12+
#[cfg(feature = "serde")]
13+
mod serialize;
14+
1215
// TODO: implement Debug, PartialEq, etc.
1316

1417
/// A `Variant` can represent many of godot's core types.
@@ -109,6 +112,13 @@ macro_rules! decl_variant_type {
109112
)*
110113
}
111114

115+
impl VariantType {
116+
/// The potential names of VariantTypes. Mostly used for serialization.
117+
pub const NAMES: &'static [&'static str] = &[
118+
$(stringify!($variant),)*
119+
];
120+
}
121+
112122
/// Rust enum associating each primitive variant type to its value.
113123
///
114124
/// For `Variant`s containing objects, the original `Variant` is returned unchanged, due to
@@ -132,6 +142,19 @@ macro_rules! decl_variant_type {
132142
}
133143
}
134144
}
145+
146+
impl<'a> From<&'a VariantDispatch> for Variant {
147+
#[inline]
148+
fn from(v: &'a VariantDispatch) -> Self {
149+
match v {
150+
$($(VariantDispatch::$variant(v) => {
151+
let v: &$inner = v;
152+
v.to_variant()
153+
})?)*
154+
_ => Variant::new()
155+
}
156+
}
157+
}
135158
}
136159
}
137160

@@ -173,6 +196,15 @@ impl VariantType {
173196
pub fn from_sys(v: sys::godot_variant_type) -> VariantType {
174197
unsafe { transmute(v as u32) }
175198
}
199+
200+
/// The `stringify!` representation of this variant. Mostly used for serialization.
201+
#[inline]
202+
pub const fn name(&self) -> &'static str {
203+
// NOTE: this assumes that the discriminants remain sequential, since any additions to the
204+
// VariantType enum would require a breaking change anyway since it is not marked as non-exhaustive.
205+
// See also the Deserialize implementation in the serde submodule.
206+
Self::NAMES[*self as usize]
207+
}
176208
}
177209

178210
#[repr(u32)]

0 commit comments

Comments
 (0)