Skip to main content

surrealdb_types/value/
object.rs

1use std::collections::{BTreeMap, HashMap};
2use std::ops::{Deref, DerefMut};
3
4use serde::{Deserialize, Serialize};
5
6use crate::sql::{SqlFormat, ToSql};
7use crate::{SurrealValue, Value};
8
9/// Represents an object with key-value pairs in SurrealDB
10///
11/// An object is a collection of key-value pairs where keys are strings and values can be of any
12/// type. The underlying storage is a `BTreeMap<String, Value>` which maintains sorted keys.
13
14#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
15#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
16pub struct Object(pub(crate) BTreeMap<String, Value>);
17
18impl Object {
19	/// Create a new empty object
20	pub fn new() -> Self {
21		Object(BTreeMap::new())
22	}
23
24	/// Insert a key-value pair into the object
25	pub fn insert(&mut self, key: impl Into<String>, value: impl SurrealValue) -> Option<Value> {
26		self.0.insert(key.into(), value.into_value())
27	}
28
29	/// Convert into the inner BTreeMap<String, Value>
30	pub fn into_inner(self) -> BTreeMap<String, Value> {
31		self.0
32	}
33}
34
35impl Deref for Object {
36	type Target = BTreeMap<String, Value>;
37
38	fn deref(&self) -> &Self::Target {
39		&self.0
40	}
41}
42
43impl DerefMut for Object {
44	fn deref_mut(&mut self) -> &mut Self::Target {
45		&mut self.0
46	}
47}
48
49impl ToSql for Object {
50	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
51		use crate::sql::fmt_sql_key_value;
52
53		if self.is_empty() {
54			return f.push_str("{  }");
55		}
56
57		if fmt.is_pretty() {
58			f.push('{');
59		} else {
60			f.push_str("{ ");
61		}
62
63		if !self.is_empty() {
64			let inner_fmt = fmt.increment();
65			fmt_sql_key_value(self.iter(), f, inner_fmt);
66		}
67
68		if fmt.is_pretty() {
69			f.push('}');
70		} else {
71			f.push_str(" }");
72		}
73	}
74}
75
76impl<T: SurrealValue> From<BTreeMap<&str, T>> for Object {
77	fn from(v: BTreeMap<&str, T>) -> Self {
78		Self(v.into_iter().map(|(key, val)| (key.to_string(), val.into_value())).collect())
79	}
80}
81
82impl<T: SurrealValue> From<BTreeMap<String, T>> for Object {
83	fn from(v: BTreeMap<String, T>) -> Self {
84		Self(v.into_iter().map(|(key, val)| (key, val.into_value())).collect())
85	}
86}
87
88impl<T: SurrealValue> FromIterator<(String, T)> for Object {
89	fn from_iter<I: IntoIterator<Item = (String, T)>>(iter: I) -> Self {
90		Self(BTreeMap::from_iter(iter.into_iter().map(|(k, v)| (k, v.into_value()))))
91	}
92}
93
94impl<T: SurrealValue> From<HashMap<&str, T>> for Object {
95	fn from(v: HashMap<&str, T>) -> Self {
96		Self(v.into_iter().map(|(key, val)| (key.to_string(), val.into_value())).collect())
97	}
98}
99
100impl<T: SurrealValue> From<HashMap<String, T>> for Object {
101	fn from(v: HashMap<String, T>) -> Self {
102		Self(v.into_iter().map(|(key, val)| (key, val.into_value())).collect())
103	}
104}
105
106impl IntoIterator for Object {
107	type Item = (String, Value);
108	type IntoIter = std::collections::btree_map::IntoIter<String, Value>;
109	fn into_iter(self) -> Self::IntoIter {
110		self.0.into_iter()
111	}
112}
113
114impl<'a> IntoIterator for &'a Object {
115	type Item = (&'a String, &'a Value);
116	type IntoIter = std::collections::btree_map::Iter<'a, String, Value>;
117	fn into_iter(self) -> Self::IntoIter {
118		self.0.iter()
119	}
120}
121
122impl<'a> IntoIterator for &'a mut Object {
123	type Item = (&'a String, &'a mut Value);
124	type IntoIter = std::collections::btree_map::IterMut<'a, String, Value>;
125	fn into_iter(self) -> Self::IntoIter {
126		self.0.iter_mut()
127	}
128}