1use crate::core::JsonbItemType;
7use std::borrow::Cow;
8use std::cmp::Ordering;
9use std::collections::BTreeMap;
10use std::fmt::Debug;
11use std::fmt::Display;
12use std::fmt::Formatter;
13
14use crate::extension::ExtensionValue;
15
16use crate::Date;
17use crate::Interval;
18use crate::Number;
19use crate::Timestamp;
20use crate::TimestampTz;
21use crate::core::Encoder;
22
23pub type Object<'a> = BTreeMap<String, Value<'a>>;
24
25#[derive(Clone, Default)]
33pub enum Value<'a> {
34 #[default]
36 Null,
37 Bool(bool),
39 String(Cow<'a, str>),
41 Number(Number),
43 Binary(&'a [u8]),
46 Date(Date),
49 Timestamp(Timestamp),
52 TimestampTz(TimestampTz),
55 Interval(Interval),
58 Array(Vec<Self>),
60 Object(Object<'a>),
62}
63
64impl Eq for Value<'_> {}
65
66impl PartialEq for Value<'_> {
67 fn eq(&self, other: &Self) -> bool {
68 let result = self.cmp(other);
69 result == Ordering::Equal
70 }
71}
72
73impl PartialOrd for Value<'_> {
74 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
75 Some(self.cmp(other))
76 }
77}
78
79impl Ord for Value<'_> {
80 fn cmp(&self, other: &Self) -> Ordering {
81 let self_type = self.jsonb_item_type();
82 let other_type = other.jsonb_item_type();
83
84 if let Some(ord) = self_type.partial_cmp(&other_type) {
85 return ord;
86 }
87
88 match (self, other) {
89 (Value::Null, Value::Null) => Ordering::Equal,
90 (Value::Bool(v1), Value::Bool(v2)) => v1.cmp(v2),
91 (Value::Number(v1), Value::Number(v2)) => v1.cmp(v2),
92 (Value::String(v1), Value::String(v2)) => v1.cmp(v2),
93 (Value::Array(arr1), Value::Array(arr2)) => {
94 for (v1, v2) in arr1.iter().zip(arr2.iter()) {
95 let ord = v1.cmp(v2);
96 if ord != Ordering::Equal {
97 return ord;
98 }
99 }
100 arr1.len().cmp(&arr2.len())
101 }
102 (Value::Object(obj1), Value::Object(obj2)) => {
103 for ((k1, v1), (k2, v2)) in obj1.iter().zip(obj2.iter()) {
104 let ord = k1.cmp(k2);
105 if ord != Ordering::Equal {
106 return ord;
107 }
108 let ord = v1.cmp(v2);
109 if ord != Ordering::Equal {
110 return ord;
111 }
112 }
113 obj1.len().cmp(&obj2.len())
114 }
115 (_, _) => match (self.as_extension_value(), other.as_extension_value()) {
116 (Some(self_ext), Some(other_ext)) => {
117 if let Some(ord) = self_ext.partial_cmp(&other_ext) {
118 return ord;
119 }
120 Ordering::Equal
121 }
122 (_, _) => Ordering::Equal,
123 },
124 }
125 }
126}
127
128impl Debug for Value<'_> {
129 fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
130 match *self {
131 Value::Null => formatter.debug_tuple("Null").finish(),
132 Value::Bool(v) => formatter.debug_tuple("Bool").field(&v).finish(),
133 Value::Number(ref v) => Debug::fmt(v, formatter),
134 Value::String(ref v) => formatter.debug_tuple("String").field(v).finish(),
135 Value::Binary(ref v) => formatter.debug_tuple("Binary").field(v).finish(),
136 Value::Date(ref v) => formatter.debug_tuple("Date").field(v).finish(),
137 Value::Timestamp(ref v) => formatter.debug_tuple("Timestamp").field(v).finish(),
138 Value::TimestampTz(ref v) => formatter.debug_tuple("TimestampTz").field(v).finish(),
139 Value::Interval(ref v) => formatter.debug_tuple("Interval").field(v).finish(),
140 Value::Array(ref v) => {
141 formatter.write_str("Array(")?;
142 Debug::fmt(v, formatter)?;
143 formatter.write_str(")")
144 }
145 Value::Object(ref v) => {
146 formatter.write_str("Object(")?;
147 Debug::fmt(v, formatter)?;
148 formatter.write_str(")")
149 }
150 }
151 }
152}
153
154fn write_json_string(f: &mut Formatter<'_>, s: &str) -> std::fmt::Result {
163 let escaped = serde_json::to_string(s).map_err(|_| std::fmt::Error)?;
164 write!(f, "{escaped}")
165}
166
167impl Display for Value<'_> {
168 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
169 match self {
170 Value::Null => write!(f, "null"),
171 Value::Bool(v) => {
172 if *v {
173 write!(f, "true")
174 } else {
175 write!(f, "false")
176 }
177 }
178 Value::Number(v) => write!(f, "{}", v),
179 Value::String(v) => write_json_string(f, v),
180 Value::Binary(v) => {
181 write!(f, "\"")?;
182 for c in *v {
183 write!(f, "{c:02X}")?;
184 }
185 write!(f, "\"")?;
186 Ok(())
187 }
188 Value::Date(v) => {
189 write!(f, "\"{}\"", v)
190 }
191 Value::Timestamp(v) => {
192 write!(f, "\"{}\"", v)
193 }
194 Value::TimestampTz(v) => {
195 write!(f, "\"{}\"", v)
196 }
197 Value::Interval(v) => {
198 write!(f, "\"{}\"", v)
199 }
200 Value::Array(vs) => {
201 write!(f, "[")?;
202 for (i, v) in vs.iter().enumerate() {
203 if i > 0 {
204 write!(f, ",")?;
205 }
206 write!(f, "{v}")?;
207 }
208 write!(f, "]")
209 }
210 Value::Object(vs) => {
211 write!(f, "{{")?;
212 for (i, (k, v)) in vs.iter().enumerate() {
213 if i > 0 {
214 write!(f, ",")?;
215 }
216 write_json_string(f, k)?;
217 write!(f, ":")?;
218 write!(f, "{v}")?;
219 }
220 write!(f, "}}")
221 }
222 }
223 }
224}
225
226impl<'a> Value<'a> {
227 pub(crate) fn write_to_vec(&self, buf: &mut Vec<u8>) {
229 let mut encoder = Encoder::new(buf);
230 encoder.encode(self);
231 }
232
233 pub fn to_vec(&self) -> Vec<u8> {
235 let mut buf = Vec::new();
236 self.write_to_vec(&mut buf);
237 buf
238 }
239
240 fn jsonb_item_type(&self) -> JsonbItemType {
241 match self {
242 Value::Null => JsonbItemType::Null,
243 Value::Bool(_) => JsonbItemType::Boolean,
244 Value::Number(_) => JsonbItemType::Number,
245 Value::String(_) => JsonbItemType::String,
246 Value::Binary(_) => JsonbItemType::Extension,
247 Value::Date(_) => JsonbItemType::Extension,
248 Value::Timestamp(_) => JsonbItemType::Extension,
249 Value::TimestampTz(_) => JsonbItemType::Extension,
250 Value::Interval(_) => JsonbItemType::Extension,
251 Value::Array(arr) => JsonbItemType::Array(arr.len()),
252 Value::Object(obj) => JsonbItemType::Object(obj.len()),
253 }
254 }
255
256 fn as_extension_value(&self) -> Option<ExtensionValue<'_>> {
257 match self {
258 Value::Binary(v) => Some(ExtensionValue::Binary(v)),
259 Value::Date(v) => Some(ExtensionValue::Date(v.clone())),
260 Value::Timestamp(v) => Some(ExtensionValue::Timestamp(v.clone())),
261 Value::TimestampTz(v) => Some(ExtensionValue::TimestampTz(v.clone())),
262 Value::Interval(v) => Some(ExtensionValue::Interval(v.clone())),
263 _ => None,
264 }
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_display_escapes_object_keys() {
274 let mut obj = Object::new();
275 obj.insert("line\nbreak".to_string(), Value::Bool(false));
276 let value = Value::Object(obj);
277
278 let displayed = format!("{value}");
279 assert_eq!(displayed, "{\"line\\nbreak\":false}");
280
281 let reparsed: serde_json::Value = serde_json::from_str(&displayed).unwrap();
283 assert_eq!(reparsed, serde_json::json!({"line\nbreak": false}));
284 }
285
286 #[test]
292 fn test_display_string_control_char_is_valid_json() {
293 let value = Value::String(Cow::Borrowed("\u{1}"));
294 let displayed = format!("{value}");
295 assert!(
296 serde_json::from_str::<serde_json::Value>(&displayed).is_ok(),
297 "{displayed:?} is not valid JSON"
298 );
299 }
300
301 #[test]
302 fn test_display_string_nul_is_valid_json() {
303 let value = Value::String(Cow::Borrowed("\0"));
304 let displayed = format!("{value}");
305 assert!(
306 serde_json::from_str::<serde_json::Value>(&displayed).is_ok(),
307 "{displayed:?} is not valid JSON"
308 );
309 }
310
311 #[test]
312 fn test_display_object_key_control_char_is_valid_json() {
313 let mut obj = Object::new();
314 obj.insert("\u{1}".to_string(), Value::Null);
315 let value = Value::Object(obj);
316
317 let displayed = format!("{value}");
318 let reparsed: Result<serde_json::Value, _> = serde_json::from_str(&displayed);
319 assert!(reparsed.is_ok(), "{displayed:?} is not valid JSON");
320 assert_eq!(reparsed.unwrap(), serde_json::json!({"\u{1}": null}),);
321 }
322}