rs_pixel/util/
generic_json.rs

1use serde_json::{Map, Value};
2
3pub trait Raw {
4    fn raw(&self) -> &Value;
5}
6
7pub trait Property {
8    fn get_property(&self, full_path: &str) -> Option<&Value>;
9    fn get_str_property(&self, full_path: &str) -> Option<&str>;
10    fn get_string_property(&self, full_path: &str) -> Option<String>;
11    fn get_int_property(&self, full_path: &str) -> Option<i64>;
12    fn get_float_property(&self, full_path: &str) -> Option<f64>;
13    fn get_array_property(&self, full_path: &str) -> Option<&Vec<Value>>;
14    fn get_object_property(&self, full_path: &str) -> Option<&Map<String, Value>>;
15}
16
17impl<T> Property for T
18where
19    T: Raw,
20{
21    fn get_property(&self, full_path: &str) -> Option<&Value> {
22        if full_path.is_empty() {
23            return Some(self.raw());
24        }
25
26        let paths = full_path.split('.');
27        let mut cur_raw = self.raw();
28
29        for path in paths {
30            if cur_raw.is_array() {
31                match path.parse::<usize>() {
32                    Ok(idx) => {
33                        match cur_raw.get(idx) {
34                            Some(new_raw) => cur_raw = new_raw,
35                            None => return None,
36                        };
37                        continue;
38                    }
39                    Err(_) => return None,
40                }
41            }
42
43            match cur_raw.get(path) {
44                Some(new_raw) => cur_raw = new_raw,
45                None => return None,
46            }
47        }
48
49        Some(cur_raw)
50    }
51
52    fn get_str_property(&self, full_path: &str) -> Option<&str> {
53        self.get_property(full_path)
54            .and_then(serde_json::Value::as_str)
55    }
56
57    fn get_string_property(&self, full_path: &str) -> Option<String> {
58        self.get_property(full_path)
59            .and_then(serde_json::Value::as_str)
60            .map(std::string::ToString::to_string)
61    }
62
63    fn get_int_property(&self, full_path: &str) -> Option<i64> {
64        self.get_property(full_path).and_then(|v| {
65            if v.is_i64() {
66                v.as_i64()
67            } else {
68                v.as_f64().map(|f| f as i64)
69            }
70        })
71    }
72
73    fn get_float_property(&self, full_path: &str) -> Option<f64> {
74        self.get_property(full_path).and_then(|v| {
75            if v.is_f64() {
76                v.as_f64()
77            } else {
78                v.as_i64().map(|f| f as f64)
79            }
80        })
81    }
82
83    fn get_array_property(&self, full_path: &str) -> Option<&Vec<Value>> {
84        self.get_property(full_path)
85            .and_then(serde_json::Value::as_array)
86    }
87
88    fn get_object_property(&self, full_path: &str) -> Option<&Map<String, Value>> {
89        self.get_property(full_path)
90            .and_then(serde_json::Value::as_object)
91    }
92}
93
94impl Raw for Value {
95    fn raw(&self) -> &Value {
96        self
97    }
98}