1use ahash::{HashMap, HashMapExt};
2use serde::de::{Error, MapAccess, SeqAccess, Visitor};
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::Number;
5use std::collections::BTreeMap;
6use std::collections::hash_map::Entry;
7use std::fmt::{self, Display, Formatter};
8
9use crate::{join, join_format};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum Value {
13 Object(HashMap<String, Value>),
14 Array(Vec<Value>),
15 Boolean(bool),
16 Null,
17 String(String),
18 Number(Number),
19}
20
21impl Value {
22 pub fn object(obj: HashMap<String, Value>) -> Value {
23 Value::Object(obj)
24 }
25
26 pub fn object_from_iter<I>(iter: I) -> Value
27 where
28 I: IntoIterator<Item = (String, Value)>,
29 {
30 Value::Object(HashMap::from_iter(iter))
31 }
32
33 pub fn array(values: Vec<Value>) -> Value {
34 Value::Array(values)
35 }
36
37 pub fn array_from_iter<I>(iter: I) -> Value
38 where
39 I: IntoIterator<Item = Value>,
40 {
41 Value::Array(iter.into_iter().collect())
42 }
43
44 pub fn boolean(boolean: bool) -> Value {
45 Value::Boolean(boolean)
46 }
47
48 pub fn null() -> Value {
49 Value::Null
50 }
51
52 pub fn new_string(string: impl Into<String>) -> Value {
53 Value::String(string.into())
54 }
55}
56
57impl Value {
58 pub fn as_object(&self) -> Option<&HashMap<String, Value>> {
59 match self {
60 Value::Object(object) => Some(object),
61 _ => None,
62 }
63 }
64
65 pub fn as_object_mut(&mut self) -> Option<&mut HashMap<String, Value>> {
66 match self {
67 Value::Object(object) => Some(object),
68 _ => None,
69 }
70 }
71
72 pub fn as_array(&self) -> Option<&Vec<Value>> {
73 match self {
74 Value::Array(array) => Some(array),
75 _ => None,
76 }
77 }
78
79 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
80 match self {
81 Value::Array(array) => Some(array),
82 _ => None,
83 }
84 }
85
86 pub fn as_boolean(&self) -> Option<bool> {
87 match self {
88 Value::Boolean(boolean) => Some(*boolean),
89 _ => None,
90 }
91 }
92
93 pub fn as_boolean_mut(&mut self) -> Option<&mut bool> {
94 match self {
95 Value::Boolean(boolean) => Some(boolean),
96 _ => None,
97 }
98 }
99
100 pub fn as_str(&self) -> Option<&str> {
101 match self {
102 Value::String(string) => Some(string),
103 _ => None,
104 }
105 }
106
107 pub fn as_str_mut(&mut self) -> Option<&mut String> {
108 match self {
109 Value::String(string) => Some(string),
110 _ => None,
111 }
112 }
113
114 pub fn as_f64(&mut self) -> Option<f64> {
115 match self {
116 Value::Number(number) => number.as_f64(),
117 _ => None,
118 }
119 }
120
121 pub fn as_i64(&self) -> Option<i64> {
122 match self {
123 Value::Number(number) => number.as_i64(),
124 _ => None,
125 }
126 }
127
128 pub fn is_null(&self) -> bool {
129 matches!(self, Value::Null)
130 }
131
132 pub fn ty(&self) -> &'static str {
133 match self {
134 Value::Object(_) => "Object",
135 Value::Array(_) => "Array",
136 Value::Boolean(_) => "Boolean",
137 Value::Null => "Null",
138 Value::String(_) => "String",
139 Value::Number(_) => "Number",
140 }
141 }
142
143 pub fn into_object(self) -> Option<HashMap<String, Value>> {
144 match self {
145 Value::Object(object) => Some(object),
146 _ => None,
147 }
148 }
149
150 pub fn into_array(self) -> Option<Vec<Value>> {
151 match self {
152 Value::Array(array) => Some(array),
153 _ => None,
154 }
155 }
156
157 pub fn into_boolean(self) -> Option<bool> {
158 match self {
159 Value::Boolean(boolean) => Some(boolean),
160 _ => None,
161 }
162 }
163
164 pub fn into_string(self) -> Option<String> {
165 match self {
166 Value::String(string) => Some(string),
167 _ => None,
168 }
169 }
170
171 pub fn get_by_path<'a>(&self, paths: impl AsRef<[&'a str]>) -> Option<&Value> {
177 let paths = paths.as_ref();
178 if paths.is_empty() {
179 return None;
180 }
181 let mut current = self;
182 for &path in paths {
183 if let Value::Object(obj) = current {
184 if let Some(val) = obj.get(path) {
185 current = val;
186 } else {
187 return None;
188 }
189 }
190 }
191 Some(current)
192 }
193
194 pub fn get_by_path_mut<'a>(&mut self, paths: impl AsRef<[&'a str]>) -> Option<&mut Value> {
195 let paths = paths.as_ref();
196 if paths.is_empty() {
197 return None;
198 }
199 let mut current = self;
200 for &path in paths {
201 if let Value::Object(obj) = current {
202 if let Some(val) = obj.get_mut(path) {
203 current = val;
204 } else {
205 return None;
206 }
207 }
208 }
209 Some(current)
210 }
211
212 pub fn with_fallback(self, fallback: Value) -> Value {
222 match (self, fallback) {
223 (Value::Object(mut obj), Value::Object(fb_obj)) => {
225 for (k, fb_val) in fb_obj {
226 match obj.entry(k) {
227 Entry::Occupied(mut occupied_entry) => {
229 let existing_val = occupied_entry.get_mut();
230
231 if let (Value::Object(_), Value::Object(_)) = (&existing_val, &fb_val) {
233 let mut temp = Value::Null;
235 std::mem::swap(&mut temp, existing_val);
236
237 *existing_val = temp.with_fallback(fb_val);
239 }
240 }
242
243 Entry::Vacant(vacant_entry) => {
245 vacant_entry.insert(fb_val);
246 }
247 }
248 }
249 Value::Object(obj)
250 }
251
252 (other, _) => other,
254 }
255 }
256}
257
258impl Value {}
259
260impl Display for Value {
261 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
262 match self {
263 Value::Object(object) => {
264 write!(f, "{{")?;
265 join_format(
266 object.iter(),
267 f,
268 |f| write!(f, ", "),
269 |f, (k, v)| write!(f, "{k}: {v}"),
270 )?;
271 write!(f, "}}")?;
272 Ok(())
273 }
274 Value::Array(array) => {
275 write!(f, "[")?;
276 join(array.iter(), ", ", f)?;
277 write!(f, "]")?;
278 Ok(())
279 }
280 Value::Boolean(boolean) => {
281 write!(f, "{}", boolean)
282 }
283 Value::Null => {
284 write!(f, "null")
285 }
286 Value::String(string) => {
287 write!(f, "{}", string)
288 }
289 Value::Number(number) => {
290 write!(f, "{}", number)
291 }
292 }
293 }
294}
295
296impl TryFrom<crate::merge::value::Value> for Value {
297 type Error = crate::error::Error;
298
299 fn try_from(value: crate::merge::value::Value) -> Result<Self, Self::Error> {
300 fn from_object(object: crate::merge::object::Object) -> crate::Result<Value> {
301 let inner: BTreeMap<_, _> = object.into();
302 let mut object = HashMap::with_capacity(inner.len());
303 for (k, v) in inner.into_iter() {
304 let v = v.into_inner();
305 if !matches!(v, crate::merge::value::Value::None) {
306 let v: Value = v.try_into()?;
307 object.insert(k, v);
308 }
309 }
310 Ok(Value::Object(object))
311 }
312
313 fn from_array(array: crate::merge::array::Array) -> crate::Result<Value> {
314 let mut result = Vec::with_capacity(array.len());
315 for ele in array.into_inner().into_iter() {
316 let v = ele.into_inner();
317 let v: Value = v.try_into()?;
318 result.push(v);
319 }
320 Ok(Value::Array(result))
321 }
322 let value = match value {
323 crate::merge::value::Value::Object(object) => {
324 if object.is_unmerged() {
325 return Err(crate::error::Error::ResolveIncomplete);
326 }
327 from_object(object)?
328 }
329 crate::merge::value::Value::Array(array) => from_array(array)?,
330 crate::merge::value::Value::Boolean(boolean) => Value::Boolean(boolean),
331 crate::merge::value::Value::Null | crate::merge::value::Value::None => Value::Null,
332 crate::merge::value::Value::String(string) => Value::String(string),
333 crate::merge::value::Value::Number(number) => Value::Number(number),
334 crate::merge::value::Value::Substitution(_)
335 | crate::merge::value::Value::Concat(_)
336 | crate::merge::value::Value::AddAssign(_)
337 | crate::merge::value::Value::DelayReplacement(_) => {
338 return Err(crate::error::Error::ResolveIncomplete);
339 }
340 };
341 Ok(value)
342 }
343}
344
345impl Serialize for Value {
346 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
347 where
348 S: Serializer,
349 {
350 match self {
351 Value::Object(map) => map.serialize(serializer),
352 Value::Array(arr) => arr.serialize(serializer),
353 Value::Boolean(b) => b.serialize(serializer),
354 Value::Null => serializer.serialize_none(),
355 Value::String(s) => s.serialize(serializer),
356 Value::Number(num) => num.serialize(serializer),
357 }
358 }
359}
360
361impl<'de> Deserialize<'de> for Value {
362 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
363 where
364 D: Deserializer<'de>,
365 {
366 struct ValueVisitor;
367
368 impl<'de> Visitor<'de> for ValueVisitor {
369 type Value = Value;
370
371 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
372 formatter.write_str("any valid HOCON value")
373 }
374
375 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> {
376 Ok(Value::Boolean(v))
377 }
378
379 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> {
380 Ok(Value::Number(Number::from(v)))
381 }
382
383 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
384 Ok(Value::Number(Number::from(v)))
385 }
386
387 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
388 where
389 E: Error,
390 {
391 Number::from_f64(v)
392 .map(Value::Number)
393 .ok_or_else(|| Error::custom("invalid f64 value"))
394 }
395
396 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
397 Ok(Value::String(v.to_owned()))
398 }
399
400 fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
401 Ok(Value::String(v))
402 }
403
404 fn visit_none<E>(self) -> Result<Self::Value, E> {
405 Ok(Value::Null)
406 }
407
408 fn visit_unit<E>(self) -> Result<Self::Value, E> {
409 Ok(Value::Null)
410 }
411
412 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
413 where
414 A: SeqAccess<'de>,
415 {
416 let mut vec = Vec::new();
417 while let Some(elem) = seq.next_element()? {
418 vec.push(elem);
419 }
420 Ok(Value::Array(vec))
421 }
422
423 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
424 where
425 M: MapAccess<'de>,
426 {
427 let mut values = HashMap::new();
428 while let Some((k, v)) = map.next_entry()? {
429 values.insert(k, v);
430 }
431 Ok(Value::Object(values))
432 }
433 }
434
435 deserializer.deserialize_any(ValueVisitor)
436 }
437}