1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use crate::err::Error;
use crate::sql::value::Value;

impl Value {
	pub(crate) fn merge(&mut self, val: Value) -> Result<(), Error> {
		// If this value is not an object, then error
		if !val.is_object() {
			return Err(Error::InvalidMerge {
				value: val,
			});
		}
		// Otherwise loop through every object field
		for k in val.every(None, false, false).iter() {
			match val.pick(k) {
				Value::None => self.cut(k),
				v => self.put(k, v),
			}
		}
		Ok(())
	}
}

#[cfg(test)]
mod tests {

	use super::*;
	use crate::syn::test::Parse;

	#[tokio::test]
	async fn merge_none() {
		let mut res = Value::parse(
			"{
				name: {
					first: 'Tobie',
					last: 'Morgan Hitchcock',
					initials: 'TMH',
				},
			}",
		);
		let none = Value::None;
		match res.merge(none.clone()).unwrap_err() {
			Error::InvalidMerge {
				value,
			} => assert_eq!(value, none),
			error => panic!("unexpected error: {error:?}"),
		}
	}

	#[tokio::test]
	async fn merge_basic() {
		let mut res = Value::parse(
			"{
				name: {
					first: 'Tobie',
					last: 'Morgan Hitchcock',
					initials: 'TMH',
				},
			}",
		);
		let mrg = Value::parse(
			"{
				name: {
					title: 'Mr',
					initials: NONE,
				},
				tags: ['Rust', 'Golang', 'JavaScript'],
			}",
		);
		let val = Value::parse(
			"{
				name: {
					title: 'Mr',
					first: 'Tobie',
					last: 'Morgan Hitchcock',
				},
				tags: ['Rust', 'Golang', 'JavaScript'],
			}",
		);
		res.merge(mrg).unwrap();
		assert_eq!(res, val);
	}
}