surrealdb_sql/value/
put.rs

1use crate::part::Next;
2use crate::part::Part;
3use crate::value::Value;
4
5impl Value {
6	/// Synchronous method for setting a field on a `Value`
7	pub fn put(&mut self, path: &[Part], val: Value) {
8		match path.first() {
9			// Get the current value at path
10			Some(p) => match self {
11				// Current value at path is an object
12				Value::Object(v) => match p {
13					Part::Graph(g) => match v.get_mut(g.to_raw().as_str()) {
14						Some(v) if v.is_some() => v.put(path.next(), val),
15						_ => {
16							let mut obj = Value::base();
17							obj.put(path.next(), val);
18							v.insert(g.to_raw(), obj);
19						}
20					},
21					Part::Field(f) => match v.get_mut(f.to_raw().as_str()) {
22						Some(v) if v.is_some() => v.put(path.next(), val),
23						_ => {
24							let mut obj = Value::base();
25							obj.put(path.next(), val);
26							v.insert(f.to_raw(), obj);
27						}
28					},
29					Part::Index(i) => match v.get_mut(&i.to_string()) {
30						Some(v) if v.is_some() => v.put(path.next(), val),
31						_ => {
32							let mut obj = Value::base();
33							obj.put(path.next(), val);
34							v.insert(i.to_string(), obj);
35						}
36					},
37					_ => (),
38				},
39				// Current value at path is an array
40				Value::Array(v) => match p {
41					Part::All => {
42						let path = path.next();
43						v.iter_mut().for_each(|v| v.put(path, val.clone()));
44					}
45					Part::First => {
46						if let Some(v) = v.first_mut() {
47							v.put(path.next(), val)
48						}
49					}
50					Part::Last => {
51						if let Some(v) = v.last_mut() {
52							v.put(path.next(), val)
53						}
54					}
55					Part::Index(i) => {
56						if let Some(v) = v.get_mut(i.to_usize()) {
57							v.put(path.next(), val)
58						}
59					}
60					_ => {
61						v.iter_mut().for_each(|v| v.put(path, val.clone()));
62					}
63				},
64				// Current value at path is empty
65				Value::Null => {
66					*self = Value::base();
67					self.put(path, val)
68				}
69				// Current value at path is empty
70				Value::None => {
71					*self = Value::base();
72					self.put(path, val)
73				}
74				// Ignore everything else
75				_ => (),
76			},
77			// No more parts so put the value
78			None => {
79				*self = val;
80			}
81		}
82	}
83}
84
85#[cfg(test)]
86mod tests {
87
88	use super::*;
89	use crate::idiom::Idiom;
90	use crate::syn::test::Parse;
91
92	#[tokio::test]
93	async fn put_none() {
94		let idi = Idiom::default();
95		let mut val = Value::parse("{ test: { other: null, something: 123 } }");
96		let res = Value::parse("999");
97		val.put(&idi, Value::from(999));
98		assert_eq!(res, val);
99	}
100
101	#[tokio::test]
102	async fn put_empty() {
103		let idi = Idiom::parse("test");
104		let mut val = Value::None;
105		let res = Value::parse("{ test: 999 }");
106		val.put(&idi, Value::from(999));
107		assert_eq!(res, val);
108	}
109
110	#[tokio::test]
111	async fn put_blank() {
112		let idi = Idiom::parse("test.something");
113		let mut val = Value::None;
114		let res = Value::parse("{ test: { something: 999 } }");
115		val.put(&idi, Value::from(999));
116		assert_eq!(res, val);
117	}
118
119	#[tokio::test]
120	async fn put_reput() {
121		let idi = Idiom::parse("test");
122		let mut val = Value::parse("{ test: { other: null, something: 123 } }");
123		let res = Value::parse("{ test: 999 }");
124		val.put(&idi, Value::from(999));
125		assert_eq!(res, val);
126	}
127
128	#[tokio::test]
129	async fn put_basic() {
130		let idi = Idiom::parse("test.something");
131		let mut val = Value::parse("{ test: { other: null, something: 123 } }");
132		let res = Value::parse("{ test: { other: null, something: 999 } }");
133		val.put(&idi, Value::from(999));
134		assert_eq!(res, val);
135	}
136
137	#[tokio::test]
138	async fn put_allow() {
139		let idi = Idiom::parse("test.something.allow");
140		let mut val = Value::parse("{ test: { other: null } }");
141		let res = Value::parse("{ test: { other: null, something: { allow: 999 } } }");
142		val.put(&idi, Value::from(999));
143		assert_eq!(res, val);
144	}
145
146	#[tokio::test]
147	async fn put_wrong() {
148		let idi = Idiom::parse("test.something.wrong");
149		let mut val = Value::parse("{ test: { other: null, something: 123 } }");
150		let res = Value::parse("{ test: { other: null, something: 123 } }");
151		val.put(&idi, Value::from(999));
152		assert_eq!(res, val);
153	}
154
155	#[tokio::test]
156	async fn put_other() {
157		let idi = Idiom::parse("test.other.something");
158		let mut val = Value::parse("{ test: { other: null, something: 123 } }");
159		let res = Value::parse("{ test: { other: { something: 999 }, something: 123 } }");
160		val.put(&idi, Value::from(999));
161		assert_eq!(res, val);
162	}
163
164	#[tokio::test]
165	async fn put_array() {
166		let idi = Idiom::parse("test.something[1]");
167		let mut val = Value::parse("{ test: { something: [123, 456, 789] } }");
168		let res = Value::parse("{ test: { something: [123, 999, 789] } }");
169		val.put(&idi, Value::from(999));
170		assert_eq!(res, val);
171	}
172
173	#[tokio::test]
174	async fn put_array_field() {
175		let idi = Idiom::parse("test.something[1].age");
176		let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
177		let res = Value::parse("{ test: { something: [{ age: 34 }, { age: 21 }] } }");
178		val.put(&idi, Value::from(21));
179		assert_eq!(res, val);
180	}
181
182	#[tokio::test]
183	async fn put_array_fields() {
184		let idi = Idiom::parse("test.something[*].age");
185		let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
186		let res = Value::parse("{ test: { something: [{ age: 21 }, { age: 21 }] } }");
187		val.put(&idi, Value::from(21));
188		assert_eq!(res, val);
189	}
190
191	#[tokio::test]
192	async fn put_array_fields_flat() {
193		let idi = Idiom::parse("test.something.age");
194		let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
195		let res = Value::parse("{ test: { something: [{ age: 21 }, { age: 21 }] } }");
196		val.put(&idi, Value::from(21));
197		assert_eq!(res, val);
198	}
199}