Skip to main content

reliakit_json/
value.rs

1//! The owned JSON value model.
2
3use alloc::string::String;
4use alloc::vec::Vec;
5
6use crate::number::JsonNumber;
7
8/// An owned JSON value.
9///
10/// JSON has exactly six value kinds, so this enum is intentionally exhaustive —
11/// you can `match` it without a wildcard arm.
12#[derive(Debug, Clone, PartialEq)]
13pub enum JsonValue {
14    /// `null`.
15    Null,
16    /// `true` or `false`.
17    Bool(bool),
18    /// A number, preserving its exact source text.
19    Number(JsonNumber),
20    /// A string (decoded Unicode scalar values).
21    String(String),
22    /// An array.
23    Array(Vec<JsonValue>),
24    /// An object with unique keys in insertion order.
25    Object(JsonObject),
26}
27
28impl JsonValue {
29    /// Builds a [`JsonValue::Array`] from an iterator of values.
30    pub fn array<I: IntoIterator<Item = JsonValue>>(items: I) -> Self {
31        JsonValue::Array(items.into_iter().collect())
32    }
33
34    /// Returns `true` if this is [`JsonValue::Null`].
35    pub fn is_null(&self) -> bool {
36        matches!(self, JsonValue::Null)
37    }
38
39    /// Returns the boolean if this is a [`JsonValue::Bool`].
40    pub fn as_bool(&self) -> Option<bool> {
41        match self {
42            JsonValue::Bool(b) => Some(*b),
43            _ => None,
44        }
45    }
46
47    /// Returns the number if this is a [`JsonValue::Number`].
48    pub fn as_number(&self) -> Option<&JsonNumber> {
49        match self {
50            JsonValue::Number(n) => Some(n),
51            _ => None,
52        }
53    }
54
55    /// Returns the string if this is a [`JsonValue::String`].
56    pub fn as_str(&self) -> Option<&str> {
57        match self {
58            JsonValue::String(s) => Some(s),
59            _ => None,
60        }
61    }
62
63    /// Returns the array if this is a [`JsonValue::Array`].
64    pub fn as_array(&self) -> Option<&[JsonValue]> {
65        match self {
66            JsonValue::Array(a) => Some(a),
67            _ => None,
68        }
69    }
70
71    /// Returns the object if this is a [`JsonValue::Object`].
72    pub fn as_object(&self) -> Option<&JsonObject> {
73        match self {
74            JsonValue::Object(o) => Some(o),
75            _ => None,
76        }
77    }
78}
79
80/// A single object member (key/value pair).
81#[derive(Debug, Clone, PartialEq)]
82pub struct JsonMember {
83    key: String,
84    value: JsonValue,
85}
86
87impl JsonMember {
88    /// The member key.
89    pub fn key(&self) -> &str {
90        &self.key
91    }
92
93    /// The member value.
94    pub fn value(&self) -> &JsonValue {
95        &self.value
96    }
97}
98
99/// A JSON object: members in insertion order with unique keys.
100///
101/// Keys are guaranteed unique — the parser rejects duplicates, and
102/// [`insert`](Self::insert) replaces an existing key in place rather than
103/// adding a second entry. Lookup is linear; object size is bounded by
104/// [`JsonLimits`](crate::JsonLimits) when parsing untrusted input.
105#[derive(Debug, Clone, PartialEq, Default)]
106pub struct JsonObject {
107    entries: Vec<JsonMember>,
108}
109
110impl JsonObject {
111    /// Creates an empty object.
112    pub fn new() -> Self {
113        Self {
114            entries: Vec::new(),
115        }
116    }
117
118    pub(crate) fn push_unique(&mut self, key: String, value: JsonValue) {
119        self.entries.push(JsonMember { key, value });
120    }
121
122    /// Returns the value for `key`, if present.
123    pub fn get(&self, key: &str) -> Option<&JsonValue> {
124        self.entries.iter().find(|m| m.key == key).map(|m| &m.value)
125    }
126
127    /// Returns `true` if `key` is present.
128    pub fn contains_key(&self, key: &str) -> bool {
129        self.entries.iter().any(|m| m.key == key)
130    }
131
132    /// Inserts or replaces `key`. If the key already exists its value is
133    /// replaced in place (preserving position) and the old value is returned;
134    /// otherwise the member is appended.
135    pub fn insert(&mut self, key: String, value: JsonValue) -> Option<JsonValue> {
136        if let Some(member) = self.entries.iter_mut().find(|m| m.key == key) {
137            Some(core::mem::replace(&mut member.value, value))
138        } else {
139            self.entries.push(JsonMember { key, value });
140            None
141        }
142    }
143
144    /// The number of members.
145    pub fn len(&self) -> usize {
146        self.entries.len()
147    }
148
149    /// Returns `true` if the object has no members.
150    pub fn is_empty(&self) -> bool {
151        self.entries.is_empty()
152    }
153
154    /// Iterates over members in insertion order.
155    pub fn iter(&self) -> core::slice::Iter<'_, JsonMember> {
156        self.entries.iter()
157    }
158}