1use anyhow::Result;
2use std::collections::HashMap;
3use std::fmt::Display;
4
5#[derive(Debug, Clone)]
6pub enum ValueType {
7 STRING(String),
8 LIST(HashMap<String, ValueType>),
9}
10
11impl PartialEq for ValueType {
12 fn eq(&self, other: &Self) -> bool {
13 match self {
14 ValueType::STRING(str1) => {
15 if let ValueType::STRING(str2) = other {
16 str2 == str1
17 } else {
18 false
19 }
20 }
21 ValueType::LIST(map1) => {
22 if let ValueType::LIST(map2) = other {
23 map1 == map2
24 } else {
25 false
26 }
27 }
28 }
29 }
30}
31
32impl ValueType {
33 pub fn get_str(&self, path: &str) -> Result<String> {
34 if path.is_empty() {
35 return if let ValueType::STRING(val) = self {
36 Ok(val.to_owned())
37 } else {
38 Err(anyhow::anyhow!(
39 "error: query doesn't match the graph structure"
40 ))
41 };
42 }
43 let parts = path.split_once('.').unwrap_or((path, ""));
44
45 if let ValueType::LIST(map) = self {
46 let value = map.get(parts.0).ok_or(anyhow::anyhow!("error"))?;
47 value.get_str(parts.1)
48 } else {
49 Err(anyhow::anyhow!(
50 "error: query doesn't match the graph structure"
51 ))
52 }
53 }
54
55 pub fn get_node(&self, path: &str) -> Result<ValueType> {
57 if path.is_empty() {
58 return if let ValueType::LIST(_) = self {
59 Ok(self.clone())
60 } else {
61 Err(anyhow::anyhow!(
62 "error: query doesn't match the graph structure"
63 ))
64 };
65 }
66 let parts = path.split_once('.').unwrap_or((path, ""));
67
68 if let ValueType::LIST(map) = self {
69 let value = map.get(parts.0).ok_or(anyhow::anyhow!("error"))?;
70 value.get_node(parts.1)
71 } else {
72 Err(anyhow::anyhow!(
73 "error: query doesn't match the graph structure"
74 ))
75 }
76 }
77}
78
79pub fn from_byte_vec(data: Vec<u8>) -> Result<ValueType> {
80 let data = String::from_utf8(data)?;
81 let data: Vec<String> = split_string(data);
82 let (_, map) = parse_list(data.get(1..).unwrap())?;
83
84 Ok(ValueType::LIST(map))
85}
86
87fn split_string(mut val: String) -> Vec<String> {
88 let mut parts: Vec<String> = Vec::new();
89 while !val.is_empty() {
90 let (part, rest) = val.split_once(' ').unwrap_or((val.as_str(), ""));
91 if part == "[" || part == "]" {
92 parts.push(part.to_owned());
93 val = rest.to_owned();
94 continue;
95 }
96 let str_len = part.parse::<usize>().unwrap();
97 let (part, rest) = rest.split_at(str_len);
98 parts.push(part.to_owned());
99 val = rest.trim().to_owned();
100 }
101
102 parts
103}
104
105fn parse_list(data: &[String]) -> Result<(usize, HashMap<String, ValueType>)> {
106 let mut map = HashMap::new();
107 let mut index = 0;
108 while index < data.len() {
109 let key = data.get(index).unwrap().clone();
110 if key == "]" {
111 return Ok((index, map));
112 }
113 index += 1;
114 let value = data.get(index).unwrap().clone();
115 if value == "[" {
116 let (i, val) = parse_list(data.get(index + 1..).unwrap())?;
117 map.insert(key.to_owned(), ValueType::LIST(val));
118 index += 1 + i;
119 } else {
120 map.insert(key.to_owned(), ValueType::STRING(value.to_owned()));
121 }
122 index += 1;
123 }
124
125 Ok((index, map))
126}
127
128pub fn to_byte_vec(data: ValueType) -> Vec<u8> {
129 if let ValueType::LIST(map) = data {
130 let string = write_list(map);
131 string.into_bytes()
132 } else {
133 panic!("Root ValueType must be a LIST variant")
134 }
135}
136
137fn write_list(map: HashMap<String, ValueType>) -> String {
138 let mut string = "[".to_owned();
139 for element in map {
140 string.push_str(&format!(" {} {} ", element.0.len(), element.0));
141 match element.1 {
142 ValueType::STRING(value) => {
143 string.push_str(&format!("{} {}", value.len(), value));
144 }
145 ValueType::LIST(map) => string.push_str(&write_list(map)),
146 }
147 }
148 string.push_str(" ]");
149 string
150}
151
152fn write_tree(node: ValueType, f: &mut std::fmt::Formatter<'_>, depth: usize) -> std::fmt::Result {
153 match node {
154 ValueType::STRING(val) => writeln!(f, "{}", val),
155 ValueType::LIST(map) => {
156 writeln!(f, "[")?;
157 for (key, value) in map {
158 for _ in 0..depth {
159 write!(f, " ")?;
160 }
161 write!(f, " {} ", key)?;
162 write_tree(value, f, depth + 1)?;
163 }
164 for _ in 0..depth {
165 write!(f, " ")?;
166 }
167 writeln!(f, "]")
168 }
169 }
170}
171
172impl Display for ValueType {
173 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 write_tree(self.clone(), f, 0)
176 }
177}