Repository: not-fl3/nanoserde (rust)

Issue:
Feature request: Support `&str` in `SerJson`
Hi,

For now, we can use `SerJson` with `&String` but not `&str`. Could you please add support for it?

Thanks

Pull request description:
Implement `SerJson` for `str`
Close #62 

Patch:
diff --git a/src/serde_json.rs b/src/serde_json.rs
index 7e69d8d..bdd7b2d 100644
--- a/src/serde_json.rs
+++ b/src/serde_json.rs
@@ -778,29 +778,36 @@ impl DeJson for bool {
     }
 }
 
-impl SerJson for String {
-    fn ser_json(&self, _d: usize, s: &mut SerJsonState) {
-        s.out.push('"');
-        for c in self.chars() {
-            match c {
-                '\x08' => s.out += "\\b",
-                '\x0C' => s.out += "\\f",
-                '\n' => s.out += "\\n",
-                '\r' => s.out += "\\r",
-                '\t' => s.out += "\\t",
-                _ if c.is_ascii_control() => {
-                    use core::fmt::Write as _;
-                    let _ = write!(s.out, "\\u{:04x}", c as u32);
+macro_rules! impl_ser_json_string {
+    ($ty: ident) => {
+        impl SerJson for $ty {
+            fn ser_json(&self, _d: usize, s: &mut SerJsonState) {
+                s.out.push('"');
+                for c in self.chars() {
+                    match c {
+                        '\x08' => s.out += "\\b",
+                        '\x0C' => s.out += "\\f",
+                        '\n' => s.out += "\\n",
+                        '\r' => s.out += "\\r",
+                        '\t' => s.out += "\\t",
+                        _ if c.is_ascii_control() => {
+                            use core::fmt::Write as _;
+                            let _ = write!(s.out, "\\u{:04x}", c as u32);
+                        }
+                        '\\' => s.out += "\\\\",
+                        '"' => s.out += "\\\"",
+                        _ => s.out.push(c),
+                    }
                 }
-                '\\' => s.out += "\\\\",
-                '"' => s.out += "\\\"",
-                _ => s.out.push(c),
+                s.out.push('"');
             }
         }
-        s.out.push('"');
-    }
+    };
 }
 
+impl_ser_json_string!(String);
+impl_ser_json_string!(str);
+
 impl DeJson for String {
     fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<String, DeJsonErr> {
         let val = s.as_string()?;


Test patch:
diff --git a/tests/json.rs b/tests/json.rs
index 8ba3bec..ae821c7 100644
--- a/tests/json.rs
+++ b/tests/json.rs
@@ -691,3 +691,41 @@ fn control_characters() {
 
     assert_eq!(SerJson::serialize_json(&string), escaped);
 }
+
+#[test]
+fn ser_str() {
+    #[derive(SerJson)]
+    struct AString {
+        s: String,
+    }
+
+    #[derive(SerJson)]
+    struct ABorrowedString<'a> {
+        s: &'a String,
+    }
+
+    #[derive(SerJson)]
+    struct AStr<'a> {
+        s: &'a str,
+    }
+
+    let a_string = AString {
+        s: "abc".to_string(),
+    };
+
+    let a_borrowed_string = ABorrowedString {
+        s: &"abc".to_string(),
+    };
+
+    let a_str = AStr { s: "abc" };
+
+    assert_eq!(
+        SerJson::serialize_json(&a_string),
+        SerJson::serialize_json(&a_borrowed_string)
+    );
+
+    assert_eq!(
+        SerJson::serialize_json(&a_string),
+        SerJson::serialize_json(&a_str)
+    );
+}