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    /// Returns `true` if this is [`JsonValue::Null`].
30    pub fn is_null(&self) -> bool {
31        matches!(self, JsonValue::Null)
32    }
33
34    /// Returns the boolean if this is a [`JsonValue::Bool`].
35    pub fn as_bool(&self) -> Option<bool> {
36        match self {
37            JsonValue::Bool(b) => Some(*b),
38            _ => None,
39        }
40    }
41
42    /// Returns the number if this is a [`JsonValue::Number`].
43    pub fn as_number(&self) -> Option<&JsonNumber> {
44        match self {
45            JsonValue::Number(n) => Some(n),
46            _ => None,
47        }
48    }
49
50    /// Returns the string if this is a [`JsonValue::String`].
51    pub fn as_str(&self) -> Option<&str> {
52        match self {
53            JsonValue::String(s) => Some(s),
54            _ => None,
55        }
56    }
57
58    /// Returns the array if this is a [`JsonValue::Array`].
59    pub fn as_array(&self) -> Option<&[JsonValue]> {
60        match self {
61            JsonValue::Array(a) => Some(a),
62            _ => None,
63        }
64    }
65
66    /// Returns the object if this is a [`JsonValue::Object`].
67    pub fn as_object(&self) -> Option<&JsonObject> {
68        match self {
69            JsonValue::Object(o) => Some(o),
70            _ => None,
71        }
72    }
73}
74
75/// A single object member (key/value pair).
76#[derive(Debug, Clone, PartialEq)]
77pub struct JsonMember {
78    key: String,
79    value: JsonValue,
80}
81
82impl JsonMember {
83    /// The member key.
84    pub fn key(&self) -> &str {
85        &self.key
86    }
87
88    /// The member value.
89    pub fn value(&self) -> &JsonValue {
90        &self.value
91    }
92}
93
94/// A JSON object: members in insertion order with unique keys.
95///
96/// Keys are guaranteed unique — the parser rejects duplicates, and
97/// [`insert`](Self::insert) replaces an existing key in place rather than
98/// adding a second entry. Lookup is linear; object size is bounded by
99/// [`JsonLimits`](crate::JsonLimits) when parsing untrusted input.
100#[derive(Debug, Clone, PartialEq, Default)]
101pub struct JsonObject {
102    entries: Vec<JsonMember>,
103}
104
105impl JsonObject {
106    /// Creates an empty object.
107    pub fn new() -> Self {
108        Self {
109            entries: Vec::new(),
110        }
111    }
112
113    pub(crate) fn push_unique(&mut self, key: String, value: JsonValue) {
114        self.entries.push(JsonMember { key, value });
115    }
116
117    /// Returns the value for `key`, if present.
118    pub fn get(&self, key: &str) -> Option<&JsonValue> {
119        self.entries.iter().find(|m| m.key == key).map(|m| &m.value)
120    }
121
122    /// Returns `true` if `key` is present.
123    pub fn contains_key(&self, key: &str) -> bool {
124        self.entries.iter().any(|m| m.key == key)
125    }
126
127    /// Inserts or replaces `key`. If the key already exists its value is
128    /// replaced in place (preserving position) and the old value is returned;
129    /// otherwise the member is appended.
130    pub fn insert(&mut self, key: String, value: JsonValue) -> Option<JsonValue> {
131        if let Some(member) = self.entries.iter_mut().find(|m| m.key == key) {
132            Some(core::mem::replace(&mut member.value, value))
133        } else {
134            self.entries.push(JsonMember { key, value });
135            None
136        }
137    }
138
139    /// The number of members.
140    pub fn len(&self) -> usize {
141        self.entries.len()
142    }
143
144    /// Returns `true` if the object has no members.
145    pub fn is_empty(&self) -> bool {
146        self.entries.is_empty()
147    }
148
149    /// Iterates over members in insertion order.
150    pub fn iter(&self) -> core::slice::Iter<'_, JsonMember> {
151        self.entries.iter()
152    }
153}