Skip to content

Commit c13ba1d

Browse files
committed
deserialize struct variants from visit_seq
1 parent 4891955 commit c13ba1d

File tree

1 file changed

+126
-62
lines changed
  • gdnative-core/src/core_types/variant

1 file changed

+126
-62
lines changed

gdnative-core/src/core_types/variant/serde.rs

Lines changed: 126 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,7 @@ impl Serialize for VariantDispatch {
138138
Color(v) => newtype_variant!(VariantType::Color, v),
139139
NodePath(v) => newtype_variant!(VariantType::NodePath, v),
140140
Rid(v) => newtype_variant!(VariantType::Rid, v),
141-
Object(_) => {
142-
newtype_variant!(VariantType::Object, &Option::<()>::None)
143-
}
141+
Object(_) => newtype_variant!(VariantType::Object, &Option::<()>::None),
144142
Dictionary(v) => newtype_variant!(VariantType::Dictionary, v),
145143
VariantArray(v) => {
146144
//Allows serializing to non-self-describing formats by avoiding serializing `Variant`s
@@ -203,7 +201,7 @@ impl<'de> Visitor<'de> for VariantDispatchVisitor {
203201
v.newtype_variant::<Vec<VariantDispatch>>()?
204202
.iter()
205203
.map(Into::<Variant>::into)
206-
.collect::<VariantArray<Unique>>()
204+
.collect::<variant_array::VariantArray<Unique>>()
207205
.into_shared(),
208206
),
209207
ByteArray => VariantDispatch::ByteArray(v.newtype_variant()?),
@@ -318,13 +316,89 @@ impl<'de> Visitor<'de> for VariantVisitor {
318316
where
319317
A: SeqAccess<'de>,
320318
{
321-
//TODO: Should this support deserializing struct variants as sequences?
322-
VariantArrayVisitor
323-
.visit_seq(seq)
324-
.map(VariantArray::<Unique>::owned_to_variant)
319+
let arr = VariantArrayVisitor.visit_seq(seq)?;
320+
let len = arr.len();
321+
322+
if len == 1 {
323+
if let VariantDispatch::VariantArray(arr) = arr.get(0).dispatch() {
324+
if arr.len() == 3 {
325+
if let Some(v) = arr.get(0).try_to_vector3() {
326+
//assume format may have treated Basis as a sequence of one element
327+
if let Some(basis) = basis_seq(&arr, v) {
328+
return Ok(basis.to_variant());
329+
}
330+
}
331+
}
332+
}
333+
} else if len == 2 {
334+
let first = arr.get(0).dispatch();
335+
match first {
336+
VariantDispatch::F64(x) => {
337+
let x = x as f32;
338+
if let Some(y) = f32_field(&arr.get(1)) {
339+
return Ok(Vector2 { x, y }.to_variant());
340+
}
341+
}
342+
VariantDispatch::Vector2(position) => {
343+
if let Some(size) = arr.get(1).try_to_vector2() {
344+
return Ok(Rect2 { position, size }.to_variant());
345+
}
346+
}
347+
VariantDispatch::Vector3(pos_or_norm) => {
348+
let next = arr.get(1);
349+
if let Some(d) = f32_field(&next) {
350+
let normal = pos_or_norm;
351+
return Ok(Plane { normal, d }.to_variant());
352+
} else if let Some(size) = next.try_to_vector3() {
353+
let position = pos_or_norm;
354+
return Ok(Aabb { position, size }.to_variant());
355+
}
356+
}
357+
_ => {}
358+
}
359+
} else if len == 3 {
360+
let first = arr.get(0).dispatch();
361+
match first {
362+
VariantDispatch::F64(x) => {
363+
let x = x as f32;
364+
if let Some(y) = f32_field(&arr.get(1)) {
365+
if let Some(z) = f32_field(&arr.get(2)) {
366+
return Ok(Vector3 { x, y, z }.to_variant());
367+
}
368+
}
369+
}
370+
VariantDispatch::Vector2(x) => {
371+
if let Some(y) = arr.get(1).try_to_vector2() {
372+
if let Some(origin) = arr.get(2).try_to_vector2() {
373+
return Ok(Transform2D { x, y, origin }.to_variant());
374+
}
375+
}
376+
}
377+
VariantDispatch::Vector3(v) => {
378+
if let Some(basis) = basis_seq(&arr, v) {
379+
return Ok(basis.to_variant());
380+
}
381+
}
382+
_ => {}
383+
}
384+
} else if len == 4 {
385+
if let Some(r) = f32_field(&arr.get(0)) {
386+
if let Some(g) = f32_field(&arr.get(1)) {
387+
if let Some(b) = f32_field(&arr.get(2)) {
388+
if let Some(a) = f32_field(&arr.get(3)) {
389+
//Assume it's a Color rather than a Quat since Godot calls arrays of
390+
//4-float structs `ColorArray`s.
391+
return Ok(Color { r, g, b, a }.to_variant());
392+
}
393+
}
394+
}
395+
}
396+
}
397+
398+
Ok(arr.owned_to_variant())
325399
}
326400

327-
fn visit_map<A>(self, map: A) -> Result<Self::Value, <A as MapAccess<'de>>::Error>
401+
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
328402
where
329403
A: MapAccess<'de>,
330404
{
@@ -369,39 +443,26 @@ impl<'de> Deserialize<'de> for Variant {
369443
}
370444
}
371445

446+
fn basis_seq<Access: ThreadAccess>(arr: &VariantArray<Access>, first: Vector3) -> Option<Basis> {
447+
if let Some(second) = arr.get(1).try_to_vector3() {
448+
if let Some(third) = arr.get(2).try_to_vector3() {
449+
return Some(Basis {
450+
elements: [first, second, third],
451+
});
452+
}
453+
}
454+
None
455+
}
456+
372457
fn string_tagged(key: &str, value: Variant) -> Option<Variant> {
373458
let s = key;
374459
if s == value.get_type().name() {
375460
return Some(value);
376461
} else if s == "elements" {
377-
match value.dispatch() {
378-
VariantDispatch::Vector3Array(arr) => {
379-
if arr.len() == 3 {
380-
return Some(
381-
Basis {
382-
elements: [arr.get(0), arr.get(1), arr.get(2)],
383-
}
384-
.to_variant(),
385-
);
386-
}
387-
}
388-
VariantDispatch::VariantArray(arr) => {
389-
if arr.len() == 3 {
390-
if let Some(e0) = arr.get(0).try_to_vector3() {
391-
if let Some(e1) = arr.get(1).try_to_vector3() {
392-
if let Some(e2) = arr.get(2).try_to_vector3() {
393-
return Some(
394-
Basis {
395-
elements: [e0, e1, e2],
396-
}
397-
.to_variant(),
398-
);
399-
}
400-
}
401-
}
402-
}
403-
}
404-
_ => {}
462+
//maybe a Basis represented as a Map
463+
if let VariantType::Basis = value.get_type() {
464+
//visit_seq will have assumed [Vector3; 3] was a Basis
465+
return Some(value);
405466
}
406467
} else if value.get_type() == ().to_variant().get_type() {
407468
match &*s {
@@ -455,14 +516,14 @@ fn int_tagged(key: i64, value: Variant) -> Option<Variant> {
455516
}
456517

457518
fn vec2_plane_rect2_or_aabb(dict: &Dictionary<Unique>) -> Option<Variant> {
458-
if let Some(x) = get_f64(&dict, "x") {
459-
if let Some(y) = get_f64(&dict, "y") {
460-
return Some(Vector2::new(x as f32, y as f32).to_variant());
519+
if let Some(x) = get_f32(&dict, "x") {
520+
if let Some(y) = get_f32(&dict, "y") {
521+
return Some(Vector2 { x, y }.to_variant());
461522
}
462523
} else {
463524
if let Some(normal) = dict.get("normal").try_to_vector3() {
464-
if let Some(d) = get_f64(&dict, "d") {
465-
return Some(Plane::new(normal, d as f32).to_variant());
525+
if let Some(d) = get_f32(&dict, "d") {
526+
return Some(Plane { normal, d }.to_variant());
466527
}
467528
}
468529
match dict.get("position").dispatch() {
@@ -483,10 +544,10 @@ fn vec2_plane_rect2_or_aabb(dict: &Dictionary<Unique>) -> Option<Variant> {
483544
}
484545

485546
fn vec3_or_xform2d(dict: &Dictionary<Unique>) -> Option<Variant> {
486-
if let Some(x) = get_f64(&dict, "x") {
487-
if let Some(y) = get_f64(&dict, "y") {
488-
if let Some(z) = get_f64(&dict, "z") {
489-
return Some(Vector3::new(x as f32, y as f32, z as f32).to_variant());
547+
if let Some(x) = get_f32(&dict, "x") {
548+
if let Some(y) = get_f32(&dict, "y") {
549+
if let Some(z) = get_f32(&dict, "z") {
550+
return Some(Vector3 { x, y, z }.to_variant());
490551
}
491552
}
492553
} else if let Some(x) = dict.get("x").try_to_vector2() {
@@ -500,32 +561,35 @@ fn vec3_or_xform2d(dict: &Dictionary<Unique>) -> Option<Variant> {
500561
}
501562

502563
fn quat_or_color(dict: &Dictionary<Unique>) -> Option<Variant> {
503-
if let Some(x) = get_f64(&dict, "x") {
504-
if let Some(y) = get_f64(&dict, "y") {
505-
if let Some(z) = get_f64(&dict, "z") {
506-
if let Some(w) = get_f64(&dict, "w") {
507-
return Some(Quat::new(x as f32, y as f32, z as f32, w as f32).to_variant());
564+
if let Some(x) = get_f32(&dict, "x") {
565+
if let Some(y) = get_f32(&dict, "y") {
566+
if let Some(z) = get_f32(&dict, "z") {
567+
if let Some(w) = get_f32(&dict, "w") {
568+
return Some(Quat { x, y, z, w }.to_variant());
508569
}
509570
}
510571
}
511-
} else if let Some(r) = get_f64(&dict, "r") {
512-
if let Some(g) = get_f64(&dict, "g") {
513-
if let Some(b) = get_f64(&dict, "b") {
514-
if let Some(a) = get_f64(&dict, "a") {
515-
return Some(
516-
Color::from_rgba(r as f32, g as f32, b as f32, a as f32).to_variant(),
517-
);
572+
} else if let Some(r) = get_f32(&dict, "r") {
573+
if let Some(g) = get_f32(&dict, "g") {
574+
if let Some(b) = get_f32(&dict, "b") {
575+
if let Some(a) = get_f32(&dict, "a") {
576+
return Some(Color { r, g, b, a }.to_variant());
518577
}
519578
}
520579
}
521580
}
522581
None
523582
}
524583

525-
fn get_f64<Access: ThreadAccess>(
584+
fn get_f32<Access: ThreadAccess>(
526585
dict: &Dictionary<Access>,
527586
key: impl ToVariant + ToVariantEq,
528-
) -> Option<f64> {
529-
dict.get_or_none(key)
530-
.and_then(|v| v.try_to_f64().or_else(|| v.try_to_i64().map(|i| i as f64)))
587+
) -> Option<f32> {
588+
dict.get_or_none(key).as_ref().and_then(f32_field)
589+
}
590+
591+
fn f32_field(v: &Variant) -> Option<f32> {
592+
v.try_to_f64()
593+
.map(|f| f as f32)
594+
.or_else(|| v.try_to_i64().map(|i| i as f32))
531595
}

0 commit comments

Comments
 (0)