jaml/formatter/
options.rs

1/// Formatting options for JAML output.
2#[derive(Debug, Clone)]
3pub struct Options {
4    /// Quote style for strings.
5    pub quote_style: QuoteStyle,
6
7    /// Binary data encoding preference.
8    pub binary_encoding: BinaryEncoding,
9
10    /// Use unquoted keys in maps when possible.
11    pub unquoted_keys: bool,
12
13    /// Add leading plus sign to positive numbers (+42, +3.14, +inf).
14    pub leading_plus: bool,
15
16    /// Sort map keys alphabetically for consistent output.
17    pub sort_keys: bool,
18
19    /// Escape all non-ASCII characters as \uXXXX sequences.
20    pub escape_unicode: bool,
21
22    /// Use 'Z' for UTC timestamps instead of '+00:00'.
23    pub use_zulu: bool,
24
25    /// Precision for timestamp fractional seconds.
26    pub timestamp_precision: TimestampPrecision,
27}
28
29impl Default for Options {
30    fn default() -> Self {
31        Self {
32            quote_style: QuoteStyle::Double,
33            binary_encoding: BinaryEncoding::Base64,
34            unquoted_keys: true,
35            leading_plus: false,
36            sort_keys: true,
37            escape_unicode: false,
38            use_zulu: true,
39            timestamp_precision: TimestampPrecision::Auto,
40        }
41    }
42}
43
44impl Options {
45    /// Creates default formatting options.
46    pub fn new() -> Self {
47        Self::default()
48    }
49
50    /// Sets the quote style.
51    pub fn with_quote_style(mut self, style: QuoteStyle) -> Self {
52        self.quote_style = style;
53        self
54    }
55
56    /// Sets the binary encoding preference.
57    pub fn with_binary_encoding(mut self, encoding: BinaryEncoding) -> Self {
58        self.binary_encoding = encoding;
59        self
60    }
61
62    /// Sets whether to use unquoted keys.
63    pub fn with_unquoted_keys(mut self, enable: bool) -> Self {
64        self.unquoted_keys = enable;
65        self
66    }
67
68    /// Sets whether to add leading plus sign to positive numbers.
69    pub fn with_leading_plus(mut self, enable: bool) -> Self {
70        self.leading_plus = enable;
71        self
72    }
73
74    /// Sets whether to sort map keys alphabetically.
75    pub fn with_sort_keys(mut self, enable: bool) -> Self {
76        self.sort_keys = enable;
77        self
78    }
79
80    /// Sets whether to escape non-ASCII characters as \uXXXX.
81    pub fn with_escape_unicode(mut self, enable: bool) -> Self {
82        self.escape_unicode = enable;
83        self
84    }
85
86    /// Sets whether to use 'Z' for UTC timestamps instead of '+00:00'.
87    pub fn with_use_zulu(mut self, enable: bool) -> Self {
88        self.use_zulu = enable;
89        self
90    }
91
92    /// Sets the precision for timestamp fractional seconds.
93    pub fn with_timestamp_precision(mut self, precision: TimestampPrecision) -> Self {
94        self.timestamp_precision = precision;
95        self
96    }
97}
98
99/// Quote style for strings and map keys.
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum QuoteStyle {
102    /// Always use double quotes: "string"
103    Double,
104
105    /// Always use single quotes: 'string'
106    Single,
107
108    /// Prefer double quotes, but use single if string contains "
109    PreferDouble,
110}
111
112/// Binary data encoding preference.
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum BinaryEncoding {
115    /// Always use base64: b64"..."
116    Base64,
117
118    /// Always use hex: hex"..."
119    Hex,
120}
121
122/// Precision for timestamp fractional seconds.
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124pub enum TimestampPrecision {
125    /// Automatically use minimum necessary digits (default).
126    Auto,
127
128    /// No fractional seconds (whole seconds only).
129    Seconds,
130
131    /// Milliseconds (3 decimal places).
132    Milliseconds,
133
134    /// Microseconds (6 decimal places).
135    Microseconds,
136
137    /// Nanoseconds (9 decimal places).
138    Nanoseconds,
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn test_default_options() {
147        let opts = Options::default();
148        assert_eq!(opts.quote_style, QuoteStyle::Double);
149        assert_eq!(opts.binary_encoding, BinaryEncoding::Base64);
150        assert!(opts.unquoted_keys);
151        assert!(!opts.leading_plus);
152        assert!(opts.sort_keys);
153        assert!(!opts.escape_unicode);
154        assert!(opts.use_zulu);
155        assert_eq!(opts.timestamp_precision, TimestampPrecision::Auto);
156    }
157
158    #[test]
159    fn test_builder_pattern() {
160        let opts = Options::new()
161            .with_quote_style(QuoteStyle::Single)
162            .with_binary_encoding(BinaryEncoding::Hex)
163            .with_unquoted_keys(false)
164            .with_sort_keys(false);
165
166        assert_eq!(opts.quote_style, QuoteStyle::Single);
167        assert_eq!(opts.binary_encoding, BinaryEncoding::Hex);
168        assert!(!opts.unquoted_keys);
169        assert!(!opts.sort_keys);
170    }
171}