Repository: ron-rs/ron (rust)

Issue:
Serialization of Control Characters
Currently ASCII control characters like  `'\x07'` are directly serialized. I expect them to be escaped like in Rust Code.

Pull request:
Add support for \x?? and improve escapes
~~**This PR seems to contain a regression.**~~

Fixes #82 

Patch:
diff --git a/examples/encode.rs b/examples/encode.rs
index 389ac507..e8427b0f 100644
--- a/examples/encode.rs
+++ b/examples/encode.rs
@@ -4,6 +4,7 @@ extern crate serde;
 
 use std::collections::HashMap;
 use std::default::Default;
+use std::fs::File;
 
 use ron::ser::{to_string_pretty, PrettyConfig};
 
@@ -14,7 +15,6 @@ struct Config {
     map: HashMap<u8, char>,
     nested: Nested,
     var: Variant,
-    array: Vec<()>,
 }
 
 #[derive(Serialize)]
@@ -32,8 +32,11 @@ struct Nested {
 }
 
 fn main() {
+    use std::io::Write;
     use std::iter::FromIterator;
 
+    let mut file = File::create("config.ron").expect("Failed to create file");
+
     let data = Config {
         float: (2.18, -1.1),
         tuple: TupleStruct((), false),
@@ -43,16 +46,14 @@ fn main() {
             b: 'b',
         },
         var: Variant::A(!0, ""),
-        array: vec![(); 3],
     };
 
     let pretty = PrettyConfig {
-        depth_limit: 2,
         separate_tuple_members: true,
-        enumerate_arrays: true,
         ..PrettyConfig::default()
     };
     let s = to_string_pretty(&data, pretty).expect("Serialization failed");
 
-    println!("{}", s);
+    file.write(s.as_bytes())
+        .expect("Failed to write data to file");
 }
diff --git a/src/de/error.rs b/src/de/error.rs
index e21975b0..194e6feb 100644
--- a/src/de/error.rs
+++ b/src/de/error.rs
@@ -44,7 +44,7 @@ pub enum ParseError {
     ExpectedStringEnd,
     ExpectedIdentifier,
 
-    InvalidEscape,
+    InvalidEscape(&'static str),
 
     NoSuchExtension(String),
 
@@ -103,7 +103,7 @@ impl StdError for Error {
                 ParseError::ExpectedString => "Expected string",
                 ParseError::ExpectedIdentifier => "Expected identifier",
 
-                ParseError::InvalidEscape => "Invalid escape sequence",
+                ParseError::InvalidEscape(_) => "Invalid escape sequence",
 
                 ParseError::Utf8Error(ref e) => e.description(),
                 ParseError::TrailingCharacters => "Non-whitespace trailing characters",
diff --git a/src/parse.rs b/src/parse.rs
index 2b849cb3..9b774b19 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -1,3 +1,4 @@
+use std::char::from_u32 as char_from_u32;
 use std::fmt::{Display, Formatter, Result as FmtResult};
 use std::ops::Neg;
 use std::result::Result as StdResult;
@@ -91,13 +92,8 @@ impl<'a> Bytes<'a> {
 
         let c = if c == b'\\' {
             let _ = self.advance(1);
-            let c = self.eat_byte()?;
 
-            if c != b'\\' && c != b'\'' {
-                return self.err(ParseError::InvalidEscape);
-            }
-
-            c as char
+            self.parse_escape()?
         } else {
             // Check where the end of the char (') is and try to
             // interpret the rest as UTF-8
@@ -211,6 +207,13 @@ impl<'a> Bytes<'a> {
         )
     }
 
+    pub fn expect_byte(&mut self, byte: u8, error: ParseError) -> Result<()> {
+        self.eat_byte().and_then(|b| match b == byte {
+            true => Ok(()),
+            false => self.err(error),
+        })
+    }
+
     /// Returns the extensions bit mask.
     fn extensions(&mut self) -> Result<Extensions> {
         if self.peek() != Some(b'#') {
@@ -335,6 +338,8 @@ impl<'a> Bytes<'a> {
     }
 
     pub fn string(&mut self) -> Result<ParsedStr> {
+        use std::iter::repeat;
+
         if !self.consume("\"") {
             return self.err(ParseError::ExpectedString);
         }
@@ -359,7 +364,15 @@ impl<'a> Bytes<'a> {
 
             loop {
                 let _ = self.advance(i + 1);
-                self.parse_str_escape(&mut s)?;
+                let character = self.parse_escape()?;
+                match character.len_utf8() {
+                    1 => s.push(character as u8),
+                    len => {
+                        let start = s.len();
+                        s.extend(repeat(0).take(len));
+                        character.encode_utf8(&mut s[start..]);
+                    }
+                }
 
                 let (new_i, end_or_escape) = self.bytes
                     .iter()
@@ -421,86 +434,75 @@ impl<'a> Bytes<'a> {
         res
     }
 
-    fn decode_hex_escape(&mut self) -> Result<u16> {
+    fn decode_ascii_escape(&mut self) -> Result<u8> {
         let mut n = 0;
-        for _ in 0..4 {
-            n = match self.eat_byte()? {
-                c @ b'0'...b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
-                b'a' | b'A' => n * 16_u16 + 10_u16,
-                b'b' | b'B' => n * 16_u16 + 11_u16,
-                b'c' | b'C' => n * 16_u16 + 12_u16,
-                b'd' | b'D' => n * 16_u16 + 13_u16,
-                b'e' | b'E' => n * 16_u16 + 14_u16,
-                b'f' | b'F' => n * 16_u16 + 15_u16,
-                _ => {
-                    return self.err(ParseError::InvalidEscape);
-                }
-            };
+        for _ in 0..2 {
+            n = n << 4;
+            let byte = self.eat_byte()?;
+            let decoded = self.decode_hex(byte)?;
+            n |= decoded;
         }
 
         Ok(n)
     }
 
-    fn parse_str_escape(&mut self, store: &mut Vec<u8>) -> Result<()> {
-        use std::iter::repeat;
+    fn decode_hex(&self, c: u8) -> Result<u8> {
+        match c {
+            c @ b'0'...b'9' => Ok(c - b'0'),
+            c @ b'a'...b'f' => Ok(10 + c - b'a'),
+            c @ b'A'...b'F' => Ok(10 + c - b'A'),
+            _ => self.err(ParseError::InvalidEscape("Non-hex digit found")),
+        }
+    }
 
-        match self.eat_byte()? {
-            b'"' => store.push(b'"'),
-            b'\\' => store.push(b'\\'),
-            b'b' => store.push(b'\x08'),
-            b'f' => store.push(b'\x0c'),
-            b'n' => store.push(b'\n'),
-            b'r' => store.push(b'\r'),
-            b't' => store.push(b'\t'),
+    fn parse_escape(&mut self) -> Result<char> {
+        let c = match self.eat_byte()? {
+            b'\'' => '\'',
+            b'"' => '"',
+            b'\\' => '\\',
+            b'n' => '\n',
+            b'r' => '\r',
+            b't' => '\t',
+            b'x' => self.decode_ascii_escape()? as char,
             b'u' => {
-                let c: char = match self.decode_hex_escape()? {
-                    0xDC00...0xDFFF => {
-                        return self.err(ParseError::InvalidEscape);
-                    }
+                self.expect_byte(b'{', ParseError::InvalidEscape("Missing {"))?;
 
-                    n1 @ 0xD800...0xDBFF => {
-                        if self.eat_byte()? != b'\\' {
-                            return self.err(ParseError::InvalidEscape);
-                        }
+                let mut bytes: u32 = 0;
+                let mut num_digits = 0;
 
-                        if self.eat_byte()? != b'u' {
-                            return self.err(ParseError::InvalidEscape);
-                        }
+                while num_digits < 6 {
+                    let byte = self.peek_or_eof()?;
 
-                        let n2 = self.decode_hex_escape()?;
+                    if byte == b'}' {
+                        break;
+                    } else {
+                        self.advance_single()?;
+                    }
 
-                        if n2 < 0xDC00 || n2 > 0xDFFF {
-                            return self.err(ParseError::InvalidEscape);
-                        }
+                    let byte = self.decode_hex(byte)?;
+                    bytes = bytes << 4;
+                    bytes |= byte as u32;
 
-                        let n = (((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000;
+                    num_digits += 1;
+                }
 
-                        match ::std::char::from_u32(n as u32) {
-                            Some(c) => c,
-                            None => {
-                                return self.err(ParseError::InvalidEscape);
-                            }
-                        }
-                    }
+                if num_digits == 0 {
+                    return self.err(ParseError::InvalidEscape(
+                        "Expected 1-6 digits, got 0 digits",
+                    ));
+                }
 
-                    n => match ::std::char::from_u32(n as u32) {
-                        Some(c) => c,
-                        None => {
-                            return self.err(ParseError::InvalidEscape);
-                        }
-                    },
-                };
-
-                let char_start = store.len();
-                store.extend(repeat(0).take(c.len_utf8()));
-                c.encode_utf8(&mut store[char_start..]);
+                self.expect_byte(b'}', ParseError::InvalidEscape("No } at the end"))?;
+                let character = char_from_u32(bytes)
+                    .ok_or_else(|| self.error(ParseError::InvalidEscape("Not a valid char")))?;
+                character
             }
             _ => {
-                return self.err(ParseError::InvalidEscape);
+                return self.err(ParseError::InvalidEscape("Unknown escape character"));
             }
-        }
+        };
 
-        Ok(())
+        Ok(c)
     }
 
     fn skip_comment(&mut self) -> bool {
@@ -570,3 +572,14 @@ impl Display for Position {
         write!(f, "{}:{}", self.line, self.col)
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn decode_x10() {
+        let mut bytes = Bytes::new(b"10").unwrap();
+        assert_eq!(bytes.decode_ascii_escape(), Ok(0x10));
+    }
+}
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
index 7182eb6b..f3b89eab 100644
--- a/src/ser/mod.rs
+++ b/src/ser/mod.rs
@@ -1,9 +1,12 @@
 use std::error::Error as StdError;
-use std::fmt::{Display, Formatter, Write, Result as FmtResult};
+use std::fmt::{Display, Formatter, Result as FmtResult};
 use std::result::Result as StdResult;
 
 use serde::ser::{self, Serialize};
 
+#[deprecated(since = "0.1.4",
+             note = "please use `to_string_pretty` with `PrettyConfig::default()` instead")]
+pub mod pretty;
 mod value;
 
 /// Serializes `value` and returns it as string.
@@ -30,7 +33,7 @@ where
 {
     let mut s = Serializer {
         output: String::new(),
-        pretty: Some((config, Pretty { indent: 0, sequence_index: Vec::new() })),
+        pretty: Some((config, Pretty { indent: 0 })),
         struct_names: false,
     };
     value.serialize(&mut s)?;
@@ -72,35 +75,28 @@ impl StdError for Error {
 /// Pretty serializer state
 struct Pretty {
     indent: usize,
-    sequence_index: Vec<usize>,
 }
 
 /// Pretty serializer configuration
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct PrettyConfig {
-    /// Limit the pretty-ness up to the given depth.
-    pub depth_limit: usize,
     /// New line string
     pub new_line: String,
     /// Indentation string
     pub indentor: String,
     /// Separate tuple members with indentation
     pub separate_tuple_members: bool,
-    /// Enumerate array items in comments
-    pub enumerate_arrays: bool,
 }
 
 impl Default for PrettyConfig {
     fn default() -> Self {
         PrettyConfig {
-            depth_limit: !0,
             #[cfg(not(target_os = "windows"))]
             new_line: "\n".to_string(),
             #[cfg(target_os = "windows")]
             new_line: "\r\n".to_string(),
             indentor: "    ".to_string(),
             separate_tuple_members: false,
-            enumerate_arrays: false,
         }
     }
 }
@@ -122,7 +118,7 @@ impl Serializer {
     pub fn new(config: Option<PrettyConfig>, struct_names: bool) -> Self {
         Serializer {
             output: String::new(),
-            pretty: config.map(|conf| (conf, Pretty { indent: 0, sequence_index: Vec::new() })),
+            pretty: config.map(|conf| (conf, Pretty { indent: 0 })),
             struct_names,
         }
     }
@@ -132,13 +128,6 @@ impl Serializer {
         self.output
     }
 
-    fn is_pretty(&self) -> bool {
-        match self.pretty {
-            Some((ref config, ref pretty)) => pretty.indent < config.depth_limit,
-            None => false,
-        }
-    }
-
     fn separate_tuple_members(&self) -> bool {
         self.pretty
             .as_ref()
@@ -149,30 +138,30 @@ impl Serializer {
     fn start_indent(&mut self) {
         if let Some((ref config, ref mut pretty)) = self.pretty {
             pretty.indent += 1;
-            if pretty.indent < config.depth_limit {
-                self.output += &config.new_line;
-            }
+            self.output += &config.new_line;
         }
     }
 
     fn indent(&mut self) {
         if let Some((ref config, ref pretty)) = self.pretty {
-            if pretty.indent < config.depth_limit {
-                self.output
-                    .extend((0..pretty.indent).map(|_| config.indentor.as_str()));
-            }
+            self.output
+                .extend((0..pretty.indent).map(|_| config.indentor.as_str()));
         }
     }
 
     fn end_indent(&mut self) {
         if let Some((ref config, ref mut pretty)) = self.pretty {
-            if pretty.indent < config.depth_limit {
-                self.output
-                    .extend((1..pretty.indent).map(|_| config.indentor.as_str()));
-            }
             pretty.indent -= 1;
+            self.output
+                .extend((0..pretty.indent).map(|_| config.indentor.as_str()));
         }
     }
+
+    fn serialize_escaped_str(&mut self, value: &str) {
+        self.output += "\"";
+        self.output.extend(value.chars().flat_map(|c| c.escape_debug()));
+        self.output += "\"";
+    }
 }
 
 impl<'a> ser::Serializer for &'a mut Serializer {
@@ -248,20 +237,13 @@ impl<'a> ser::Serializer for &'a mut Serializer {
     }
 
     fn serialize_str(self, v: &str) -> Result<()> {
-        self.output += "\"";
-        for char in v.chars() {
-            if char == '\\' || char == '"' {
-                self.output.push('\\');
-            }
-            self.output.push(char);
-        }
-        self.output += "\"";
+        self.serialize_escaped_str(v);
+
         Ok(())
     }
 
     fn serialize_bytes(self, v: &[u8]) -> Result<()> {
         use serde::ser::SerializeSeq;
-        //TODO: shorter version? e.g. base64 encoding in a single line
         let mut seq = self.serialize_seq(Some(v.len()))?;
         for byte in v {
             seq.serialize_element(byte)?;
@@ -346,10 +328,6 @@ impl<'a> ser::Serializer for &'a mut Serializer {
 
         self.start_indent();
 
-        if let Some((_, ref mut pretty)) = self.pretty {
-            pretty.sequence_index.push(0);
-        }
-
         Ok(self)
     }
 
@@ -440,18 +418,8 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer {
         value.serialize(&mut **self)?;
         self.output += ",";
 
-        if let Some((ref config, ref mut pretty)) = self.pretty {
-            if pretty.indent < config.depth_limit {
-                if config.enumerate_arrays {
-                    assert!(config.new_line.contains('\n'));
-                    let index = pretty.sequence_index.last_mut().unwrap();
-                    //TODO: when /**/ comments are supported, prepend the index
-                    // to an element instead of appending it.
-                    write!(self.output, "// [{}]", index).unwrap();
-                    *index += 1;
-                }
-                self.output += &config.new_line;
-            }
+        if let Some((ref config, _)) = self.pretty {
+            self.output += &config.new_line;
         }
 
         Ok(())
@@ -460,10 +428,6 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer {
     fn end(self) -> Result<()> {
         self.end_indent();
 
-        if let Some((_, ref mut pretty)) = self.pretty {
-            pretty.sequence_index.pop();
-        }
-
         self.output += "]";
         Ok(())
     }
@@ -484,25 +448,25 @@ impl<'a> ser::SerializeTuple for &'a mut Serializer {
         value.serialize(&mut **self)?;
         self.output += ",";
 
-        if let Some((ref config, ref pretty)) = self.pretty {
-            if pretty.indent < config.depth_limit {
-                self.output += if self.separate_tuple_members() {
-                    &config.new_line
-                } else {
-                    " "
-                };
-            }
+        if let Some((ref config, _)) = self.pretty {
+            self.output += if self.separate_tuple_members() {
+                &config.new_line
+            } else {
+                " "
+            };
         }
 
         Ok(())
     }
 
     fn end(self) -> Result<()> {
-        if self.separate_tuple_members() {
-            self.end_indent();
-        } else if self.is_pretty() {
-            self.output.pop();
-            self.output.pop();
+        if self.pretty.is_some() {
+            if self.separate_tuple_members() {
+                self.end_indent();
+            } else {
+                self.output.pop();
+                self.output.pop();
+            }
         }
 
         self.output += ")";
@@ -563,17 +527,15 @@ impl<'a> ser::SerializeMap for &'a mut Serializer {
     {
         self.output += ":";
 
-        if self.is_pretty() {
+        if self.pretty.is_some() {
             self.output += " ";
         }
 
         value.serialize(&mut **self)?;
         self.output += ",";
 
-        if let Some((ref config, ref pretty)) = self.pretty {
-            if pretty.indent < config.depth_limit {
-                self.output += &config.new_line;
-            }
+        if let Some((ref config, _)) = self.pretty {
+            self.output += &config.new_line;
         }
 
         Ok(())
@@ -600,17 +562,15 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer {
         self.output += key;
         self.output += ":";
 
-        if self.is_pretty() {
+        if self.pretty.is_some() {
             self.output += " ";
         }
 
         value.serialize(&mut **self)?;
         self.output += ",";
 
-        if let Some((ref config, ref pretty)) = self.pretty {
-            if pretty.indent < config.depth_limit {
-                self.output += &config.new_line;
-            }
+        if let Some((ref config, _)) = self.pretty {
+            self.output += &config.new_line;
         }
 
         Ok(())
diff --git a/src/ser/pretty.rs b/src/ser/pretty.rs
new file mode 100644
index 00000000..145dd56a
--- /dev/null
+++ b/src/ser/pretty.rs
@@ -0,0 +1,15 @@
+//! Provides default pretty serialization with `to_string`.
+
+use super::{to_string_pretty, Result};
+
+use serde::ser::Serialize;
+use std::default::Default;
+
+/// Serializes `value` in the recommended RON layout with
+/// default pretty configuration.
+pub fn to_string<T>(value: &T) -> Result<String>
+where
+    T: Serialize,
+{
+    to_string_pretty(value, Default::default())
+}


Test patch:
diff --git a/src/de/tests.rs b/src/de/tests.rs
index 6d70c502..eac34a8e 100644
--- a/src/de/tests.rs
+++ b/src/de/tests.rs
@@ -68,7 +68,7 @@ fn test_array() {
     assert_eq!(Ok(empty_array), from_str("[]"));
 
     assert_eq!(Ok([2, 3, 4i32]), from_str("(2,3,4,)"));
-    assert_eq!(Ok(([2, 3, 4i32].to_vec())), from_str("[2,3,4,]"));
+    assert_eq!(Ok([2, 3, 4i32].to_vec()), from_str("[2,3,4,]"));
 }
 
 #[test]
diff --git a/tests/depth_limit.rs b/tests/depth_limit.rs
deleted file mode 100644
index 8dd157b1..00000000
--- a/tests/depth_limit.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-extern crate ron;
-#[macro_use]
-extern crate serde;
-
-use std::collections::HashMap;
-
-#[derive(Serialize)]
-struct Config {
-    float: (f32, f64),
-    tuple: TupleStruct,
-    map: HashMap<u8, char>,
-    nested: Nested,
-    var: Variant,
-    array: Vec<()>,
-}
-
-#[derive(Serialize)]
-struct TupleStruct((), bool);
-
-#[derive(Serialize)]
-enum Variant {
-    A(u8, &'static str),
-}
-
-#[derive(Serialize)]
-struct Nested {
-    a: String,
-    b: char,
-}
-
-const EXPECTED: &str = "(
-    float: (2.18,-1.1,),
-    tuple: ((),false,),
-    map: {8:'1',},
-    nested: (a:\"a\",b:'b',),
-    var: A(255,\"\",),
-    array: [(),(),(),],
-)";
-
-#[test]
-fn depth_limit() {
-    let data = Config {
-        float: (2.18, -1.1),
-        tuple: TupleStruct((), false),
-        map: vec![(8, '1')].into_iter().collect(),
-        nested: Nested {
-            a: "a".to_owned(),
-            b: 'b',
-        },
-        var: Variant::A(!0, ""),
-        array: vec![(); 3],
-    };
-
-    let pretty = ron::ser::PrettyConfig {
-        depth_limit: 2,
-        separate_tuple_members: true,
-        enumerate_arrays: true,
-        .. Default::default()
-    };
-    let s = ron::ser::to_string_pretty(&data, pretty);
-
-    assert_eq!(s, Ok(EXPECTED.to_string()));
-}
diff --git a/tests/escape.rs b/tests/escape.rs
new file mode 100644
index 00000000..d715e776
--- /dev/null
+++ b/tests/escape.rs
@@ -0,0 +1,70 @@
+extern crate ron;
+extern crate serde;
+
+use std::char::from_u32;
+use std::fmt::Debug;
+
+use ron::de::from_str;
+use ron::ser::to_string;
+use serde::{Deserialize, Serialize};
+
+#[test]
+fn test_escape_basic() {
+    assert_eq!(to_string(&"\x07").unwrap(), "\"\\u{7}\"");
+
+    assert_eq!(from_str::<String>("\"\\x07\"").unwrap(), "\x07");
+    assert_eq!(from_str::<String>("\"\\u{7}\"").unwrap(), "\x07");
+}
+
+fn check_same<T>(t: T)
+where
+    T: Debug + for<'a> Deserialize<'a> + PartialEq + Serialize,
+{
+    let s: String = to_string(&t).unwrap();
+
+    println!("Serialized: \n\n{}\n\n", s);
+
+    assert_eq!(from_str(&s), Ok(t));
+}
+
+#[test]
+fn test_ascii_10() {
+    check_same("\u{10}".to_owned());
+}
+
+#[test]
+fn test_ascii_chars() {
+    (1..128).into_iter().flat_map(from_u32).for_each(check_same)
+}
+
+#[test]
+fn test_ascii_string() {
+    let s: String = (1..128).into_iter().flat_map(from_u32).collect();
+
+    check_same(s);
+}
+
+#[test]
+fn test_non_ascii() {
+    assert_eq!(to_string(&"♠").unwrap(), "\"♠\"");
+    assert_eq!(to_string(&"ß").unwrap(), "\"ß\"");
+    assert_eq!(to_string(&"ä").unwrap(), "\"ä\"");
+    assert_eq!(to_string(&"ö").unwrap(), "\"ö\"");
+    assert_eq!(to_string(&"ü").unwrap(), "\"ü\"");
+}
+
+#[test]
+fn test_chars() {
+    assert_eq!(to_string(&'♠').unwrap(), "'♠'");
+    assert_eq!(to_string(&'ß').unwrap(), "'ß'");
+    assert_eq!(to_string(&'ä').unwrap(), "'ä'");
+    assert_eq!(to_string(&'ö').unwrap(), "'ö'");
+    assert_eq!(to_string(&'ü').unwrap(), "'ü'");
+    assert_eq!(to_string(&'\u{715}').unwrap(), "'\u{715}'");
+    assert_eq!(from_str::<char>("'\u{715}'").unwrap(), from_str("'\\u{715}'").unwrap());
+}
+
+#[test]
+fn test_nul_in_string() {
+    check_same("Hello\0World!".to_owned());
+}
diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs
index f3447b66..c08840a4 100644
--- a/tests/roundtrip.rs
+++ b/tests/roundtrip.rs
@@ -67,11 +67,7 @@ fn roundtrip_pretty() {
             .collect(),
     };
 
-    let pretty = ron::ser::PrettyConfig {
-        enumerate_arrays: true,
-        .. Default::default()
-    };
-    let serial = ron::ser::to_string_pretty(&value, pretty).unwrap();
+    let serial = ron::ser::to_string_pretty(&value, Default::default()).unwrap();
 
     println!("Serialized: {}", serial);