Repository: ron-rs/ron
Pull request #182 (2019-07-13 15:16:32)

Allow pretty ser to work with implicit-some extension
Additionally configure newline for tests to work on windows.


I was converting my yaml files to ron and needed this, so I figured I'd submit a PR.  Really enjoying RON as a data language, btw!


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 6ac572ad..ef1649e0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ron"
-version = "0.5.1"
+version = "0.5.2"
 license = "MIT/Apache-2.0"
 keywords = ["parser", "serde", "serialization"]
 authors = [
diff --git a/src/de/mod.rs b/src/de/mod.rs
index e80f17bb..94dce469 100644
--- a/src/de/mod.rs
+++ b/src/de/mod.rs
@@ -7,7 +7,8 @@ use std::{borrow::Cow, io, str};
 
 use self::id::IdDeserializer;
 use self::tag::TagDeserializer;
-use crate::parse::{AnyNum, Bytes, Extensions, ParsedStr};
+use crate::extensions::Extensions;
+use crate::parse::{AnyNum, Bytes, ParsedStr};
 
 mod error;
 mod id;
diff --git a/src/extensions.rs b/src/extensions.rs
new file mode 100644
index 00000000..0c12330a
--- /dev/null
+++ b/src/extensions.rs
@@ -0,0 +1,27 @@
+use bitflags::bitflags;
+use serde::{Deserialize, Serialize};
+
+bitflags! {
+    #[derive(Serialize, Deserialize)]
+    pub struct Extensions: usize {
+        const UNWRAP_NEWTYPES = 0x1;
+        const IMPLICIT_SOME = 0x2;
+    }
+}
+
+impl Extensions {
+    /// Creates an extension flag from an ident.
+    pub fn from_ident(ident: &[u8]) -> Option<Extensions> {
+        match ident {
+            b"unwrap_newtypes" => Some(Extensions::UNWRAP_NEWTYPES),
+            b"implicit_some" => Some(Extensions::IMPLICIT_SOME),
+            _ => None,
+        }
+    }
+}
+
+impl Default for Extensions {
+    fn default() -> Self {
+        Extensions::empty()
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index c6218017..81e0f544 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -60,6 +60,7 @@ Serializing / Deserializing is as simple as calling `to_string` / `from_str`.
 pub mod de;
 pub mod ser;
 pub mod value;
+pub mod extensions;
 pub use crate::value::Value;
 
 mod parse;
diff --git a/src/parse.rs b/src/parse.rs
index 11c44b21..15dd69f4 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -1,4 +1,3 @@
-use bitflags::bitflags;
 use std::{
     char::from_u32 as char_from_u32,
     fmt::{Display, Formatter, Result as FmtResult},
@@ -7,6 +6,7 @@ use std::{
 };
 
 use crate::de::{Error, ParseError, Result};
+use crate::extensions::Extensions;
 
 const DIGITS: &[u8] = b"0123456789ABCDEFabcdef_";
 const FLOAT_CHARS: &[u8] = b"0123456789.+-eE";
@@ -773,23 +773,6 @@ impl<'a> Bytes<'a> {
     }
 }
 
-bitflags! {
-    pub struct Extensions: usize {
-        const UNWRAP_NEWTYPES = 0x1;
-        const IMPLICIT_SOME = 0x2;
-    }
-}
-
-impl Extensions {
-    /// Creates an extension flag from an ident.
-    pub fn from_ident(ident: &[u8]) -> Option<Extensions> {
-        match ident {
-            b"unwrap_newtypes" => Some(Extensions::UNWRAP_NEWTYPES),
-            b"implicit_some" => Some(Extensions::IMPLICIT_SOME),
-            _ => None,
-        }
-    }
-}
 
 pub trait Num {
     fn from_u8(x: u8) -> Self;
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
index 941c520f..f0403a10 100644
--- a/src/ser/mod.rs
+++ b/src/ser/mod.rs
@@ -4,6 +4,8 @@ use std::{
     fmt::{Display, Formatter, Result as FmtResult, Write},
 };
 
+use crate::extensions::Extensions;
+
 mod value;
 
 /// Serializes `value` and returns it as string.
@@ -14,12 +16,7 @@ pub fn to_string<T>(value: &T) -> Result<String>
 where
     T: Serialize,
 {
-    let mut s = Serializer {
-        output: String::new(),
-        pretty: None,
-        struct_names: false,
-        is_empty: None,
-    };
+    let mut s = Serializer::new(None, false);
     value.serialize(&mut s)?;
     Ok(s.output)
 }
@@ -29,18 +26,7 @@ pub fn to_string_pretty<T>(value: &T, config: PrettyConfig) -> Result<String>
 where
     T: Serialize,
 {
-    let mut s = Serializer {
-        output: String::new(),
-        pretty: Some((
-            config,
-            Pretty {
-                indent: 0,
-                sequence_index: Vec::new(),
-            },
-        )),
-        struct_names: false,
-        is_empty: None,
-    };
+    let mut s = Serializer::new(Some(config), false);
     value.serialize(&mut s)?;
     Ok(s.output)
 }
@@ -112,6 +98,8 @@ pub struct PrettyConfig {
     /// Enumerate array items in comments
     #[serde(default = "default_enumerate_arrays")]
     pub enumerate_arrays: bool,
+    /// Enable extensions. Only configures 'implicit_some' for now.
+    pub extensions: Extensions,
     /// Private field to ensure adding a field is non-breaking.
     #[serde(skip)]
     _future_proof: (),
@@ -172,6 +160,15 @@ impl PrettyConfig {
 
         self
     }
+
+    /// Configures extensions
+    ///
+    /// Default: Extensions::empty()
+    pub fn with_extensions(mut self, extensions: Extensions) -> Self {
+        self.extensions = extensions;
+
+        self
+    }
 }
 
 fn default_depth_limit() -> usize {
@@ -207,6 +204,7 @@ impl Default for PrettyConfig {
             indentor: default_indentor(),
             separate_tuple_members: default_separate_tuple_members(),
             enumerate_arrays: default_enumerate_arrays(),
+            extensions: Extensions::default(),
             _future_proof: (),
         }
     }
@@ -228,8 +226,17 @@ impl Serializer {
     ///
     /// Most of the time you can just use `to_string` or `to_string_pretty`.
     pub fn new(config: Option<PrettyConfig>, struct_names: bool) -> Self {
+        let initial_output = if let Some(conf) = &config {
+            if conf.extensions.contains(Extensions::IMPLICIT_SOME) {
+                "#![enable(implicit_some)]".to_string() + &conf.new_line
+            } else {
+                String::new()
+            }
+        } else {
+            String::new()
+        };
         Serializer {
-            output: String::new(),
+            output: initial_output,
             pretty: config.map(|conf| {
                 (
                     conf,
@@ -262,6 +269,12 @@ impl Serializer {
             .map_or(false, |&(ref config, _)| config.separate_tuple_members)
     }
 
+    fn extensions(&self) -> Extensions {
+        self.pretty
+            .as_ref()
+            .map_or(Extensions::empty(), |&(ref config, _)| config.extensions)
+    }
+
     fn start_indent(&mut self) {
         if let Some((ref config, ref mut pretty)) = self.pretty {
             pretty.indent += 1;
@@ -399,9 +412,14 @@ impl<'a> ser::Serializer for &'a mut Serializer {
     where
         T: ?Sized + Serialize,
     {
-        self.output += "Some(";
+        let implicit_some = self.extensions().contains(Extensions::IMPLICIT_SOME);
+        if !implicit_some {
+            self.output += "Some(";
+        }
         value.serialize(&mut *self)?;
-        self.output += ")";
+        if !implicit_some {
+            self.output += ")";
+        }
 
         Ok(())
     }


Test patch:
diff --git a/tests/147_empty_sets_serialisation.rs b/tests/147_empty_sets_serialisation.rs
index dfebb677..827ed8e4 100644
--- a/tests/147_empty_sets_serialisation.rs
+++ b/tests/147_empty_sets_serialisation.rs
@@ -41,7 +41,9 @@ fn empty_sets_arrays() {
             .collect(),
     };
 
-    let pretty = ron::ser::PrettyConfig::new().with_enumerate_arrays(true);
+    let pretty = ron::ser::PrettyConfig::new()
+        .with_enumerate_arrays(true)
+        .with_new_line("\n".to_string());
     let serial = ron::ser::to_string_pretty(&value, pretty).unwrap();
 
     println!("Serialized: {}", serial);
diff --git a/tests/depth_limit.rs b/tests/depth_limit.rs
index 94fac067..41929a84 100644
--- a/tests/depth_limit.rs
+++ b/tests/depth_limit.rs
@@ -51,7 +51,8 @@ fn depth_limit() {
     let pretty = ron::ser::PrettyConfig::new()
         .with_depth_limit(2)
         .with_separate_tuple_members(true)
-        .with_enumerate_arrays(true);
+        .with_enumerate_arrays(true)
+        .with_new_line("\n".to_string());
     let s = ron::ser::to_string_pretty(&data, pretty);
 
     assert_eq!(s, Ok(EXPECTED.to_string()));
diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs
index 5b5a48a9..08022f0f 100644
--- a/tests/roundtrip.rs
+++ b/tests/roundtrip.rs
@@ -1,6 +1,8 @@
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 
+use ron::extensions::Extensions;
+
 #[derive(Debug, PartialEq, Deserialize, Serialize)]
 struct UnitStruct;
 
@@ -66,7 +68,9 @@ fn roundtrip_pretty() {
         .collect(),
     };
 
-    let pretty = ron::ser::PrettyConfig::new().with_enumerate_arrays(true);
+    let pretty = ron::ser::PrettyConfig::new()
+        .with_enumerate_arrays(true)
+        .with_extensions(Extensions::IMPLICIT_SOME);
     let serial = ron::ser::to_string_pretty(&value, pretty).unwrap();
 
     println!("Serialized: {}", serial);