1use std::{self, collections::HashMap, fmt, ops::Index};
2
3use crate::{Parser, ParserErr, Val};
4
5#[derive(PartialEq, Clone)]
6pub struct Obj(HashMap<String, Val>);
7
8impl Index<&str> for Obj {
9 type Output = Val;
10
11 fn index(&self, key: &str) -> &Val {
12 let r = self.get(key);
13 if let Some(v) = r {
14 v
15 } else {
16 &Val::Undef
17 }
18 }
19}
20
21impl Obj {
34 pub fn new() -> Self {
35 Obj(HashMap::new())
36 }
37
38 pub fn parse(str: &str) -> Result<Val, ParserErr> {
39 let mut parser = Parser::new(str);
40 parser.parse(true)
41 }
42
43 pub fn from_map(v: HashMap<String, Val>) -> Self {
44 Self(v)
45 }
46}
47
48impl Obj {
49 pub fn len(&self) -> usize {
50 self.0.len()
51 }
52
53 pub fn get(&self, key: &str) -> Option<&Val> {
54 self.0.get(key.into())
55 }
56
57 pub fn get_mut(&mut self, key: &str) -> Option<&mut Val> {
58 self.0.get_mut(key.into())
59 }
60
61 pub fn set(&mut self, key: &str, val: Val) -> Option<Val> {
62 self.0.insert(key.into(), val)
63 }
64
65 pub fn remove(&mut self, key: &str) -> Option<Val> {
66 self.0.remove(key.into())
67 }
68}
69
70impl IntoIterator for Obj {
71 type Item = (String, Val);
72 type IntoIter = <HashMap<String, Val> as IntoIterator>::IntoIter;
73
74 #[inline]
75 fn into_iter(self) -> Self::IntoIter {
76 self.0.into_iter()
77 }
78}
79
80
81impl fmt::Display for Obj {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{:?}", self)
84 }
85}
86
87impl Extend<(String, Val)> for Obj {
88 fn extend<T: IntoIterator<Item = (String, Val)>>(&mut self, iter: T) {
89 self.0.extend(iter)
90 }
91}
92
93impl fmt::Debug for Obj {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 if self.0.len() == 0 {
96 write!(f, "{{}}")
97 } else {
98 let lines = self
104 .0
105 .iter()
106 .map(|(key, val)| format!("{:?}: {:?}", key, val))
107 .collect::<Vec<String>>()
108 .join(",\n")
109 .split("\n")
110 .map(|line| format!(" {}", line))
111 .collect::<Vec<String>>()
112 .join("\n");
113
114 write!(f, "{{\n{}\n}}", lines)
115 }
116 }
117}