1use std::{collections::HashMap, fmt::Display};
2
3#[derive(Debug, PartialEq, Clone)]
42pub enum Value<'s> {
43 None,
44 Str(&'s str),
45 Int(i64),
46 Float(f64),
47 Bool(bool),
48 List(Vec<Value<'s>>),
49 Dict(HashMap<&'s str, Value<'s>>),
50}
51
52impl<'s> Value<'s> {
53 pub fn as_str(&self) -> Option<&'s str> {
55 match self {
56 Value::Str(s) => Some(s),
57 _ => None,
58 }
59 }
60
61 pub fn as_int(&self) -> Option<i64> {
63 match self {
64 Value::Int(i) => Some(*i),
65 _ => None,
66 }
67 }
68
69 pub fn as_float(&self) -> Option<f64> {
71 match self {
72 Value::Float(f) => Some(*f),
73 _ => None,
74 }
75 }
76
77 pub fn as_bool(&self) -> Option<bool> {
79 match self {
80 Value::Bool(b) => Some(*b),
81 _ => None,
82 }
83 }
84
85 pub fn as_list(&self) -> Option<&Vec<Value<'s>>> {
87 match self {
88 Value::List(l) => Some(l),
89 _ => None,
90 }
91 }
92
93 pub fn as_dict(&self) -> Option<&HashMap<&'s str, Value<'s>>> {
95 match self {
96 Value::Dict(d) => Some(d),
97 _ => None,
98 }
99 }
100
101 pub fn is_none(&self) -> bool {
103 matches!(self, Value::None)
104 }
105
106 pub fn is_str(&self) -> bool {
108 matches!(self, Value::Str(_))
109 }
110
111 pub fn is_int(&self) -> bool {
113 matches!(self, Value::Int(_))
114 }
115
116 pub fn is_float(&self) -> bool {
118 matches!(self, Value::Float(_))
119 }
120
121 pub fn is_bool(&self) -> bool {
123 matches!(self, Value::Bool(_))
124 }
125
126 pub fn is_list(&self) -> bool {
128 matches!(self, Value::List(_))
129 }
130
131 pub fn is_dict(&self) -> bool {
133 matches!(self, Value::Dict(_))
134 }
135
136 pub fn len(&self) -> Option<usize> {
138 match self {
139 Value::List(l) => Some(l.len()),
140 Value::Dict(d) => Some(d.len()),
141 _ => None,
142 }
143 }
144
145 pub fn is_empty(&self) -> bool {
147 match self {
148 Value::List(l) => l.is_empty(),
149 Value::Dict(d) => d.is_empty(),
150 _ => false,
151 }
152 }
153}
154
155impl<'i, 's> std::ops::Index<&'i str> for Value<'s> {
156 type Output = Value<'s>;
157
158 fn index(&self, key: &'i str) -> &Self::Output {
159 match self {
160 Value::Dict(d) => d.get(key).unwrap_or(&Value::None),
161 _ => &Value::None,
162 }
163 }
164}
165
166impl<'s> std::ops::IndexMut<&'s str> for Value<'s> {
167 fn index_mut(&mut self, key: &'s str) -> &mut Self::Output {
168 match self {
169 Value::Dict(d) => d.entry(key).or_insert(Value::None),
170 _ => panic!("Cannot index non-dict value"),
171 }
172 }
173}
174
175impl<'s> std::ops::Index<usize> for Value<'s> {
176 type Output = Value<'s>;
177
178 fn index(&self, key: usize) -> &Self::Output {
179 match self {
180 Value::List(l) => l.get(key).unwrap_or(&Value::None),
181 _ => &Value::None,
182 }
183 }
184}
185
186impl<'s> std::ops::IndexMut<usize> for Value<'s> {
187 fn index_mut(&mut self, key: usize) -> &mut Self::Output {
188 match self {
189 Value::List(l) => match l.get_mut(key) {
190 Some(v) => v,
191 None => panic!("Index out of bounds"),
192 },
193 _ => panic!("Cannot index non-list value"),
194 }
195 }
196}
197
198impl<'s> Display for Value<'s> {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 match self {
201 Value::None => write!(f, "none"),
202 Value::Str(s) => write!(f, "{}", s),
203 Value::Int(i) => write!(f, "{}", i),
204 Value::Float(fl) => write!(f, "{}", fl),
205 Value::Bool(b) => write!(f, "{}", b),
206 Value::List(l) => {
207 write!(f, "[")?;
208 for v in l.iter() {
209 write!(f, " {}", v)?;
210 }
211 write!(f, " ]")
212 }
213 Value::Dict(d) => {
214 write!(f, "{{")?;
215 for (k, v) in d.iter() {
216 write!(f, " {}: {}", k, v)?;
217 }
218 write!(f, " }}")
219 }
220 }
221 }
222}