Repository: not-fl3/nanoserde
Pull request #115 (2024-10-05 22:03:40)

nanoserde: fix compile error when using `proxy` as a struct annotation
It looks like proxying structs was originally intended to be implemented, but when I tried it out, it produced code that failed to compile with the following warning:

```
error[E0308]: mismatched types
   --> crates/nanoserde/tests/json.rs:960:14
    |
960 |     #[derive(DeJson, SerJson, PartialEq, Debug)]
    |              ^^^^^^
    |              |
    |              expected `&str`, found `&mut Chars<'_>`
    |              arguments to this function are incorrect
    |
    = note:      expected reference `&str`
            found mutable reference `&mut Chars<'_>`
note: associated function defined here
   --> /workspaces/macroquad-test/crates/nanoserde/src/serde_json.rs:82:8
    |
82  |     fn deserialize_json(input: &str) -> Result<Self, DeJsonErr> {
    |        ^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `DeJson` (in Nightly builds, run with -Z macro-backtrace for more info)
```

This change fixes the issue, and adds a test to defend it against future breaks.


Patch:
diff --git a/derive/src/serde_json.rs b/derive/src/serde_json.rs
index ba2ad83..51aa91c 100644
--- a/derive/src/serde_json.rs
+++ b/derive/src/serde_json.rs
@@ -249,8 +249,8 @@ pub fn derive_de_json_proxy(proxy_type: &str, type_: &str) -> TokenStream {
     format!(
         "impl DeJson for {} {{
             #[allow(clippy::ignored_unit_patterns)]
-            fn de_json(_s: &mut nanoserde::DeJsonState, i: &mut core::str::Chars) -> ::core::result::Result<Self, nanoserde::DeJsonErr> {{
-                let proxy: {} = DeJson::deserialize_json(i)?;
+            fn de_json(s: &mut nanoserde::DeJsonState, i: &mut core::str::Chars) -> ::core::result::Result<Self, nanoserde::DeJsonErr> {{
+                let proxy: {} = DeJson::de_json(s, i)?;
                 ::core::result::Result::Ok(Into::into(&proxy))
             }}
         }}",
diff --git a/derive/src/serde_ron.rs b/derive/src/serde_ron.rs
index 01d87e0..0f0bc60 100644
--- a/derive/src/serde_ron.rs
+++ b/derive/src/serde_ron.rs
@@ -200,23 +200,34 @@ pub fn derive_de_ron_named(
                 ));
             }
         } else {
-            unwraps.push(default_val.unwrap_or_else(|| String::from("Default::default()")));
+            unwraps.push(format!(
+                "{{ {} }}",
+                default_val
+                    .as_ref()
+                    .map(|x| x.as_str())
+                    .unwrap_or_else(|| "Default::default()")
+            ));
         }
 
         struct_field_names.push(struct_fieldname);
         ron_field_names.push(ron_fieldname);
-        local_vars.push(localvar);
+        local_vars.push((localvar, field.ty.full()));
     }
 
     let mut local_lets = String::new();
 
-    for local in &local_vars {
-        l!(local_lets, "let mut {} = None;", local)
+    for (local, local_type) in &local_vars {
+        l!(
+            local_lets,
+            "let mut {}: Option<{}> = None;",
+            local,
+            local_type
+        )
     }
 
     let match_names = if ron_field_names.len() != 0 {
         let mut inner = String::new();
-        for (ron_field_name, local_var) in ron_field_names.iter().zip(local_vars.iter()) {
+        for (ron_field_name, (local_var, _)) in ron_field_names.iter().zip(local_vars.iter()) {
             l!(
                 inner,
                 "\"{}\" => {{


Test patch:
diff --git a/tests/json.rs b/tests/json.rs
index 0f11100..d143727 100644
--- a/tests/json.rs
+++ b/tests/json.rs
@@ -908,6 +908,42 @@ fn field_proxy() {
     assert!(test == test_deserialized);
 }
 
+#[test]
+fn object_proxy() {
+    #[derive(DeJson, SerJson, PartialEq, Debug)]
+    #[nserde(proxy = "Serializable")]
+    pub struct NonSerializable {
+        foo: i32,
+    }
+
+    #[derive(DeJson, SerJson, PartialEq, Debug)]
+    pub struct Serializable {
+        x: i32,
+    }
+
+    impl From<&NonSerializable> for Serializable {
+        fn from(non_serializable: &NonSerializable) -> Serializable {
+            Serializable {
+                x: non_serializable.foo,
+            }
+        }
+    }
+    impl From<&Serializable> for NonSerializable {
+        fn from(serializable: &Serializable) -> NonSerializable {
+            NonSerializable {
+                foo: serializable.x,
+            }
+        }
+    }
+
+    let test = NonSerializable { foo: 6 };
+
+    let bytes = SerJson::serialize_json(&test);
+    let test_deserialized = DeJson::deserialize_json(&bytes).unwrap();
+
+    assert!(test == test_deserialized);
+}
+
 #[test]
 fn field_option_proxy() {
     #[derive(PartialEq, Clone, Debug)]