1use crate::Rule;
2use indexmap::IndexMap;
3use log::trace;
4use pest::iterators::{Pair, Pairs};
5use std::fmt;
6use std::fmt::{Display, Formatter};
7
8#[derive(Debug, Default, Clone, PartialEq)]
10pub enum Value {
11 Number(i64),
12 Bool(bool),
13 Float(f64),
14 #[default]
15 Nil,
16 String(String),
17 Array(Vec<Value>),
18 Map(IndexMap<String, Value>),
19}
20
21impl Value {
22 pub fn as_bool(&self) -> Option<bool> {
23 match self {
24 Value::Bool(b) => Some(*b),
25 _ => None,
26 }
27 }
28
29 pub fn as_number(&self) -> Option<i64> {
30 match self {
31 Value::Number(n) => Some(*n),
32 _ => None,
33 }
34 }
35
36 pub fn as_float(&self) -> Option<f64> {
37 match self {
38 Value::Float(f) => Some(*f),
39 _ => None,
40 }
41 }
42
43 pub fn as_string(&self) -> Option<&str> {
44 match self {
45 Value::String(s) => Some(s),
46 _ => None,
47 }
48 }
49
50 pub fn as_array(&self) -> Option<&[Value]> {
51 match self {
52 Value::Array(a) => Some(a),
53 _ => None,
54 }
55 }
56
57 pub fn as_map(&self) -> Option<&IndexMap<String, Value>> {
58 match self {
59 Value::Map(m) => Some(m),
60 _ => None,
61 }
62 }
63
64 pub fn is_nil(&self) -> bool {
65 matches!(self, Value::Nil)
66 }
67}
68
69impl AsRef<Value> for Value {
70 fn as_ref(&self) -> &Value {
71 self
72 }
73}
74
75impl From<i64> for Value {
76 fn from(n: i64) -> Self {
77 Value::Number(n)
78 }
79}
80
81impl From<i32> for Value {
82 fn from(n: i32) -> Self {
83 Value::Number(n as i64)
84 }
85}
86
87impl From<usize> for Value {
88 fn from(n: usize) -> Self {
89 Value::Number(n as i64)
90 }
91}
92
93impl From<f64> for Value {
94 fn from(f: f64) -> Self {
95 Value::Float(f)
96 }
97}
98
99impl From<bool> for Value {
100 fn from(b: bool) -> Self {
101 Value::Bool(b)
102 }
103}
104
105impl From<String> for Value {
106 fn from(s: String) -> Self {
107 Value::String(s)
108 }
109}
110
111impl From<&String> for Value {
112 fn from(s: &String) -> Self {
113 s.to_string().into()
114 }
115}
116
117impl From<&str> for Value {
118 fn from(s: &str) -> Self {
119 s.to_string().into()
120 }
121}
122
123impl<V: Into<Value>> From<Vec<V>> for Value {
124 fn from(a: Vec<V>) -> Self {
125 Value::Array(a.into_iter().map(|v| v.into()).collect())
126 }
127}
128
129impl From<IndexMap<String, Value>> for Value {
130 fn from(m: IndexMap<String, Value>) -> Self {
131 Value::Map(m)
132 }
133}
134
135impl Display for Value {
136 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
137 match self {
138 Value::Number(n) => write!(f, "{n}"),
139 Value::Float(n) => write!(f, "{n}"),
140 Value::Bool(b) => write!(f, "{b}"),
141 Value::Nil => write!(f, "nil"),
142 Value::String(s) => write!(
143 f,
144 r#""{}""#,
145 s.replace("\\", "\\\\")
146 .replace("\n", "\\n")
147 .replace("\r", "\\r")
148 .replace("\t", "\\t")
149 .replace("\"", "\\\"")
150 ),
151 Value::Array(a) => write!(
152 f,
153 "[{}]",
154 a.iter()
155 .map(|v| v.to_string())
156 .collect::<Vec<String>>()
157 .join(", ")
158 ),
159 Value::Map(m) => write!(
160 f,
161 "{{{}}}",
162 m.iter()
163 .map(|(k, v)| format!("{}: {}", k, v))
164 .collect::<Vec<String>>()
165 .join(", ")
166 ),
167 }
168 }
169}
170
171impl From<Pairs<'_, Rule>> for Value {
172 fn from(mut pairs: Pairs<Rule>) -> Self {
173 pairs.next().unwrap().into()
174 }
175}
176
177impl From<Pair<'_, Rule>> for Value {
178 fn from(pair: Pair<Rule>) -> Self {
179 trace!("{:?} = {}", &pair.as_rule(), pair.as_str());
180 match pair.as_rule() {
181 Rule::value => pair.into_inner().into(),
182 Rule::nil => Value::Nil,
183 Rule::bool => Value::Bool(pair.as_str().parse().unwrap()),
184 Rule::int => Value::Number(pair.as_str().parse().unwrap()),
185 Rule::decimal => Value::Float(pair.as_str().parse().unwrap()),
186 Rule::string_multiline => pair.into_inner().as_str().into(),
187 Rule::string => pair
188 .into_inner()
189 .as_str()
190 .replace("\\\\", "\\")
191 .replace("\\n", "\n")
192 .replace("\\r", "\r")
193 .replace("\\t", "\t")
194 .replace("\\\"", "\"")
195 .into(),
196 rule => unreachable!("Unexpected rule: {rule:?} {}", pair.as_str()),
208 }
209 }
210}