Repository: ron-rs/ron
Pull request #173 (2019-06-06 15:31:26)

Make PrettyConfig future-proof!


Patch:
diff --git a/docs/grammar.md b/docs/grammar.md
index c4308d0b..0f40039d 100644
--- a/docs/grammar.md
+++ b/docs/grammar.md
@@ -71,10 +71,7 @@ string_raw = ("r#", string_raw, "#") | "\"", { unicode_non_greedy }, "\"";
 r##"This is a "raw string". It can contain quotations or
 backslashes (\)!"##
   ```
-Raw strings cannot be written in EBNF, as they are context-sensitive.
-Also see [the Rust document] about context-sensitivity of raw strings.
-
-[the Rust document]: https://github.com/rust-lang/rust/blob/HEAD@%7B2019-05-26T21:45:17Z%7D/src/grammar/raw-string-literal-ambiguity.md
+  I don't know any sane way to write this out in EBNF, if you do, let me know.
 
 ## Char
 
diff --git a/examples/encode.rs b/examples/encode.rs
index 101208bb..3d3dc253 100644
--- a/examples/encode.rs
+++ b/examples/encode.rs
@@ -39,12 +39,10 @@ fn main() {
         array: vec![(); 3],
     };
 
-    let pretty = PrettyConfig {
-        depth_limit: 2,
-        separate_tuple_members: true,
-        enumerate_arrays: true,
-        ..PrettyConfig::default()
-    };
+    let pretty = PrettyConfig::new()
+        .with_depth_limit(2)
+        .with_separate_tuple_members(true)
+        .with_enumerate_arrays(true);
     let s = to_string_pretty(&data, pretty).expect("Serialization failed");
 
     println!("{}", s);
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
index f2297350..941c520f 100644
--- a/src/ser/mod.rs
+++ b/src/ser/mod.rs
@@ -83,32 +83,131 @@ struct Pretty {
     sequence_index: Vec<usize>,
 }
 
-/// Pretty serializer configuration
+/// Pretty serializer configuration.
+///
+/// # Examples
+///
+/// ```
+/// use ron::ser::PrettyConfig;
+///
+/// let my_config = PrettyConfig::new()
+///     .with_depth_limit(4)
+///     // definitely superior (okay, just joking)
+///     .with_indentor("\t".to_owned());
+/// ```
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct PrettyConfig {
     /// Limit the pretty-ness up to the given depth.
+    #[serde(default = "default_depth_limit")]
     pub depth_limit: usize,
     /// New line string
+    #[serde(default = "default_new_line")]
     pub new_line: String,
     /// Indentation string
+    #[serde(default = "default_indentor")]
     pub indentor: String,
     /// Separate tuple members with indentation
+    #[serde(default = "default_separate_tuple_members")]
     pub separate_tuple_members: bool,
     /// Enumerate array items in comments
+    #[serde(default = "default_enumerate_arrays")]
     pub enumerate_arrays: bool,
+    /// Private field to ensure adding a field is non-breaking.
+    #[serde(skip)]
+    _future_proof: (),
+}
+
+impl PrettyConfig {
+    /// Creates a default `PrettyConfig`.
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Limits the pretty-formatting based on the number of indentations.
+    /// I.e., with a depth limit of 5, starting with an element of depth (indentation level) 6,
+    /// everything will be put into the same line, without pretty formatting.
+    ///
+    /// Default: [std::usize::MAX]
+    pub fn with_depth_limit(mut self, depth_limit: usize) -> Self {
+        self.depth_limit = depth_limit;
+
+        self
+    }
+
+    /// Configures the newlines used for serialization.
+    ///
+    /// Default: `\r\n` on Windows, `\n` otherwise
+    pub fn with_new_line(mut self, new_line: String) -> Self {
+        self.new_line = new_line;
+
+        self
+    }
+
+    /// Configures the string sequence used for indentation.
+    ///
+    /// Default: 4 spaces
+    pub fn with_indentor(mut self, indentor: String) -> Self {
+        self.indentor = indentor;
+
+        self
+    }
+
+    /// Configures whether tuples are single- or multi-line.
+    /// If set to `true`, tuples will have their fields indented and in new lines.
+    /// If set to `false`, tuples will be serialized without any newlines or indentations.
+    ///
+    /// Default: `false`
+    pub fn with_separate_tuple_members(mut self, separate_tuple_members: bool) -> Self {
+        self.separate_tuple_members = separate_tuple_members;
+
+        self
+    }
+
+    /// Configures whether a comment shall be added to every array element, indicating
+    /// the index.
+    ///
+    /// Default: `false`
+    pub fn with_enumerate_arrays(mut self, enumerate_arrays: bool) -> Self {
+        self.enumerate_arrays = enumerate_arrays;
+
+        self
+    }
+}
+
+fn default_depth_limit() -> usize {
+    !0
+}
+
+fn default_new_line() -> String {
+    #[cfg(not(target_os = "windows"))]
+    let new_line = "\n".to_string();
+    #[cfg(target_os = "windows")]
+    let new_line = "\r\n".to_string();
+
+    new_line
+}
+
+fn default_indentor() -> String {
+    "    ".to_string()
+}
+
+fn default_separate_tuple_members() -> bool {
+    false
+}
+
+fn default_enumerate_arrays() -> bool {
+    false
 }
 
 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,
+            depth_limit: default_depth_limit(),
+            new_line: default_new_line(),
+            indentor: default_indentor(),
+            separate_tuple_members: default_separate_tuple_members(),
+            enumerate_arrays: default_enumerate_arrays(),
+            _future_proof: (),
         }
     }
 }


Test patch:
diff --git a/tests/147_empty_sets_serialisation.rs b/tests/147_empty_sets_serialisation.rs
index bf679e56..dfebb677 100644
--- a/tests/147_empty_sets_serialisation.rs
+++ b/tests/147_empty_sets_serialisation.rs
@@ -41,10 +41,7 @@ fn empty_sets_arrays() {
             .collect(),
     };
 
-    let pretty = ron::ser::PrettyConfig {
-        enumerate_arrays: true,
-        ..Default::default()
-    };
+    let pretty = ron::ser::PrettyConfig::new().with_enumerate_arrays(true);
     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 beacc02e..94fac067 100644
--- a/tests/depth_limit.rs
+++ b/tests/depth_limit.rs
@@ -48,12 +48,10 @@ fn depth_limit() {
         array: vec![(); 3],
     };
 
-    let pretty = ron::ser::PrettyConfig {
-        depth_limit: 2,
-        separate_tuple_members: true,
-        enumerate_arrays: true,
-        ..Default::default()
-    };
+    let pretty = ron::ser::PrettyConfig::new()
+        .with_depth_limit(2)
+        .with_separate_tuple_members(true)
+        .with_enumerate_arrays(true);
     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 de12a5b2..5b5a48a9 100644
--- a/tests/roundtrip.rs
+++ b/tests/roundtrip.rs
@@ -66,10 +66,7 @@ fn roundtrip_pretty() {
         .collect(),
     };
 
-    let pretty = ron::ser::PrettyConfig {
-        enumerate_arrays: true,
-        ..Default::default()
-    };
+    let pretty = ron::ser::PrettyConfig::new().with_enumerate_arrays(true);
     let serial = ron::ser::to_string_pretty(&value, pretty).unwrap();
 
     println!("Serialized: {}", serial);
@@ -109,13 +106,7 @@ fn roundtrip_sep_tuple_members() {
 
     let value = Both { a, b };
 
-    let pretty = ron::ser::PrettyConfig {
-        depth_limit: !0,
-        new_line: "\n".to_owned(),
-        indentor: "    ".to_owned(),
-        separate_tuple_members: true,
-        enumerate_arrays: false,
-    };
+    let pretty = ron::ser::PrettyConfig::new().with_separate_tuple_members(true);
     let serial = ron::ser::to_string_pretty(&value, pretty).unwrap();
 
     println!("Serialized: {}", serial);