surrealdb_sql/value/
pick.rs1use crate::part::Next;
2use crate::part::Part;
3use crate::value::Value;
4
5impl Value {
6 pub fn pick(&self, path: &[Part]) -> Self {
8 match path.first() {
9 Some(p) => match self {
11 Value::Object(v) => match p {
13 Part::Field(f) => match v.get(f as &str) {
14 Some(v) => v.pick(path.next()),
15 None => Value::None,
16 },
17 Part::Index(i) => match v.get(&i.to_string()) {
18 Some(v) => v.pick(path.next()),
19 None => Value::None,
20 },
21 Part::All => self.pick(path.next()),
22 _ => Value::None,
23 },
24 Value::Array(v) => match p {
26 Part::All => v.iter().map(|v| v.pick(path.next())).collect::<Vec<_>>().into(),
27 Part::First => match v.first() {
28 Some(v) => v.pick(path.next()),
29 None => Value::None,
30 },
31 Part::Last => match v.last() {
32 Some(v) => v.pick(path.next()),
33 None => Value::None,
34 },
35 Part::Index(i) => match v.get(i.to_usize()) {
36 Some(v) => v.pick(path.next()),
37 None => Value::None,
38 },
39 _ => v.iter().map(|v| v.pick(path)).collect::<Vec<_>>().into(),
40 },
41 _ => Value::None,
43 },
44 None => self.clone(),
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52
53 use super::*;
54 use crate::id::Id;
55 use crate::idiom::Idiom;
56 use crate::syn::test::Parse;
57 use crate::thing::Thing;
58
59 #[test]
60 fn pick_none() {
61 let idi = Idiom::default();
62 let val = Value::parse("{ test: { other: null, something: 123 } }");
63 let res = val.pick(&idi);
64 assert_eq!(res, val);
65 }
66
67 #[test]
68 fn pick_basic() {
69 let idi = Idiom::parse("test.something");
70 let val = Value::parse("{ test: { other: null, something: 123 } }");
71 let res = val.pick(&idi);
72 assert_eq!(res, Value::from(123));
73 }
74
75 #[test]
76 fn pick_thing() {
77 let idi = Idiom::parse("test.other");
78 let val = Value::parse("{ test: { other: test:tobie, something: 123 } }");
79 let res = val.pick(&idi);
80 assert_eq!(
81 res,
82 Value::from(Thing {
83 tb: String::from("test"),
84 id: Id::from("tobie")
85 })
86 );
87 }
88
89 #[test]
90 fn pick_array() {
91 let idi = Idiom::parse("test.something[1]");
92 let val = Value::parse("{ test: { something: [123, 456, 789] } }");
93 let res = val.pick(&idi);
94 assert_eq!(res, Value::from(456));
95 }
96
97 #[test]
98 fn pick_array_thing() {
99 let idi = Idiom::parse("test.something[1]");
100 let val = Value::parse("{ test: { something: [test:tobie, test:jaime] } }");
101 let res = val.pick(&idi);
102 assert_eq!(
103 res,
104 Value::from(Thing {
105 tb: String::from("test"),
106 id: Id::from("jaime")
107 })
108 );
109 }
110
111 #[test]
112 fn pick_array_field() {
113 let idi = Idiom::parse("test.something[1].age");
114 let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
115 let res = val.pick(&idi);
116 assert_eq!(res, Value::from(36));
117 }
118
119 #[test]
120 fn pick_array_fields() {
121 let idi = Idiom::parse("test.something[*].age");
122 let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
123 let res = val.pick(&idi);
124 assert_eq!(res, Value::from(vec![34, 36]));
125 }
126
127 #[test]
128 fn pick_array_fields_flat() {
129 let idi = Idiom::parse("test.something.age");
130 let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
131 let res = val.pick(&idi);
132 assert_eq!(res, Value::from(vec![34, 36]));
133 }
134}