Skip to main content

tjson/
value.rs

1use std::fmt;
2
3use crate::error::{Error, Result};
4use crate::number::Number;
5use crate::options::RenderOptions;
6use crate::parse::ParseOptions;
7use crate::render::Renderer;
8
9/// A single key-value entry in a TJSON object.
10///
11/// Used instead of a tuple so that code handling object entries can use named fields
12/// rather than `.0` / `.1`. Objects are represented as `Vec<Entry>` to preserve
13/// insertion order and allow duplicate keys.
14#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct Entry {
16    pub key: String,
17    pub value: Value,
18}
19
20/// A parsed TJSON value. Mirrors the JSON type system with the same six variants.
21///
22/// Numbers are stored as [`Number`] values, which preserve the exact string representation.
23/// Objects are stored as an ordered `Vec` of key-value pairs, which allows duplicate keys
24/// at the data structure level (though JSON and TJSON parsers typically deduplicate them).
25#[derive(Clone, Debug, PartialEq, Eq)]
26pub enum Value {
27    /// JSON `null`.
28    Null,
29    /// JSON boolean.
30    Bool(bool),
31    /// JSON number.
32    Number(Number),
33    /// JSON string.
34    String(String),
35    /// JSON array.
36    Array(Vec<Value>),
37    /// JSON object, as an ordered list of key-value pairs.
38    Object(Vec<Entry>),
39}
40
41#[cfg(feature = "serde_json")]
42impl From<serde_json::Value> for Value {
43    fn from(value: serde_json::Value) -> Self {
44        Self::from_serde_json(value)
45    }
46}
47
48#[cfg(feature = "serde_json")]
49impl From<Value> for serde_json::Value {
50    fn from(value: Value) -> Self {
51        value.to_serde_json()
52    }
53}
54
55impl Value {
56    /// Convert from a `serde_json::Value`. Used internally regardless of the `serde_json`
57    /// feature, since serde_json is a hard dependency.
58    pub(crate) fn from_serde_json(value: serde_json::Value) -> Self {
59        match value {
60            serde_json::Value::Null => Self::Null,
61            serde_json::Value::Bool(v) => Self::Bool(v),
62            serde_json::Value::Number(n) => Self::Number(Number(n.to_string())),
63            serde_json::Value::String(s) => Self::String(s),
64            serde_json::Value::Array(values) => {
65                Self::Array(values.into_iter().map(Self::from_serde_json).collect())
66            }
67            serde_json::Value::Object(map) => Self::Object(
68                map.into_iter()
69                    .map(|(key, value)| Entry { key, value: Self::from_serde_json(value) })
70                    .collect(),
71            ),
72        }
73    }
74
75    pub(crate) fn to_serde_json(&self) -> serde_json::Value {
76        match self {
77            Self::Null => serde_json::Value::Null,
78            Self::Bool(v) => serde_json::Value::Bool(*v),
79            Self::Number(n) => serde_json::Value::Number(n.to_serde_json_number()),
80            Self::String(s) => serde_json::Value::String(s.clone()),
81            Self::Array(values) => {
82                serde_json::Value::Array(values.iter().map(Value::to_serde_json).collect())
83            }
84            Self::Object(entries) => {
85                let mut map = serde_json::Map::new();
86                for Entry { key, value } in entries {
87                    map.insert(key.clone(), value.to_serde_json());
88                }
89                serde_json::Value::Object(map)
90            }
91        }
92    }
93
94    pub(crate) fn parse_with(input: &str, options: ParseOptions) -> Result<Self> {
95        crate::parse::Parser::parse_document(input, options.start_indent).map_err(Error::Parse)
96    }
97
98    /// Render this value as a TJSON string using the given options.
99    ///
100    /// ```
101    /// use tjson::{Value, RenderOptions};
102    ///
103    /// let v: Value = "  name: Alice  age:30".parse().unwrap();
104    /// let s = v.to_tjson_with(RenderOptions::canonical());
105    /// assert_eq!(s, "  name: Alice\n  age:30");
106    /// ```
107    pub fn to_tjson_with(&self, options: RenderOptions) -> String {
108        Renderer::render(self, &options).expect("render is infallible")
109    }
110
111    /// Serialize this value to a JSON string.
112    ///
113    /// ```
114    /// use tjson::Value;
115    ///
116    /// let v: Value = "  name: Alice".parse().unwrap();
117    /// assert_eq!(v.to_json(), r#"{"name":"Alice"}"#);
118    /// ```
119    pub fn to_json(&self) -> String {
120        let mut out = String::new();
121        write_json(self, &mut out);
122        out
123    }
124}
125
126fn write_json(value: &Value, out: &mut String) {
127    match value {
128        Value::Null => out.push_str("null"),
129        Value::Bool(b) => out.push_str(if *b { "true" } else { "false" }),
130        Value::Number(n) => out.push_str(&n.to_string()),
131        Value::String(s) => {
132            // serde_json handles all JSON string escaping correctly.
133            out.push_str(&serde_json::to_string(s).expect("string serialization is infallible"))
134        }
135        Value::Array(values) => {
136            out.push('[');
137            for (i, v) in values.iter().enumerate() {
138                if i > 0 { out.push(','); }
139                write_json(v, out);
140            }
141            out.push(']');
142        }
143        Value::Object(entries) => {
144            out.push('{');
145            for (i, Entry { key, value }) in entries.iter().enumerate() {
146                if i > 0 { out.push(','); }
147                out.push_str(&serde_json::to_string(key).expect("string serialization is infallible"));
148                out.push(':');
149                write_json(value, out);
150            }
151            out.push('}');
152        }
153    }
154}
155
156impl serde::Serialize for Value {
157    fn serialize<S: serde::Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
158        use serde::ser::{SerializeMap, SerializeSeq};
159        match self {
160            Self::Null => serializer.serialize_unit(),
161            Self::Bool(b) => serializer.serialize_bool(*b),
162            Self::Number(n) => serde::Serialize::serialize(n, serializer),
163            Self::String(s) => serializer.serialize_str(s),
164            Self::Array(values) => {
165                let mut seq = serializer.serialize_seq(Some(values.len()))?;
166                for v in values {
167                    seq.serialize_element(v)?;
168                }
169                seq.end()
170            }
171            Self::Object(entries) => {
172                let mut map = serializer.serialize_map(Some(entries.len()))?;
173                for Entry { key, value } in entries {
174                    map.serialize_entry(key, value)?;
175                }
176                map.end()
177            }
178        }
179    }
180}
181
182impl fmt::Display for Value {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        f.write_str(&self.to_tjson_with(RenderOptions::default()))
185    }
186}
187
188/// ```
189/// let v: tjson::Value = "  name: Alice".parse().unwrap();
190/// assert!(matches!(v, tjson::Value::Object(_)));
191/// ```
192impl std::str::FromStr for Value {
193    type Err = Error;
194
195    fn from_str(s: &str) -> Result<Self> {
196        Self::parse_with(s, ParseOptions::default())
197    }
198}