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