1use crate::{Error, ErrorKind, Span};
7use std::{borrow::Cow, fmt};
8
9pub struct Value<'de> {
12 pub value: ValueInner<'de>,
14 pub span: Span,
16}
17
18impl<'de> Value<'de> {
19 #[inline]
21 pub fn new(value: ValueInner<'de>) -> Self {
22 Self::with_span(value, Span::default())
23 }
24
25 #[inline]
27 pub fn with_span(value: ValueInner<'de>, span: Span) -> Self {
28 Self { value, span }
29 }
30
31 #[inline]
35 pub fn take(&mut self) -> ValueInner<'de> {
36 std::mem::replace(&mut self.value, ValueInner::Boolean(false))
37 }
38
39 #[inline]
44 pub fn set(&mut self, value: ValueInner<'de>) {
45 self.value = value;
46 }
47
48 #[inline]
50 pub fn has_keys(&self) -> bool {
51 if let ValueInner::Table(table) = &self.value {
52 !table.is_empty()
53 } else {
54 false
55 }
56 }
57
58 #[inline]
60 pub fn has_key(&self, key: &str) -> bool {
61 if let ValueInner::Table(table) = &self.value {
62 table.contains_key(key)
63 } else {
64 false
65 }
66 }
67
68 #[inline]
71 pub fn take_string(&mut self, msg: Option<&'static str>) -> Result<Cow<'de, str>, Error> {
72 match self.take() {
73 ValueInner::String(s) => Ok(s),
74 other => Err(Error {
75 kind: ErrorKind::Wanted {
76 expected: msg.unwrap_or("a string"),
77 found: other.type_str(),
78 },
79 span: self.span,
80 line_info: None,
81 }),
82 }
83 }
84
85 #[inline]
87 pub fn as_str(&self) -> Option<&str> {
88 self.value.as_str()
89 }
90
91 #[inline]
93 pub fn as_table(&self) -> Option<&Table<'de>> {
94 self.value.as_table()
95 }
96
97 #[inline]
99 pub fn as_array(&self) -> Option<&Array<'de>> {
100 self.value.as_array()
101 }
102
103 #[inline]
105 pub fn as_integer(&self) -> Option<i64> {
106 self.value.as_integer()
107 }
108
109 #[inline]
111 pub fn as_float(&self) -> Option<f64> {
112 self.value.as_float()
113 }
114
115 #[inline]
117 pub fn as_bool(&self) -> Option<bool> {
118 self.value.as_bool()
119 }
120
121 pub fn pointer(&self, pointer: &str) -> Option<&Self> {
140 if pointer.is_empty() {
141 return Some(self);
142 } else if !pointer.starts_with('/') {
143 return None;
144 }
145
146 pointer
147 .split('/')
148 .skip(1)
149 .try_fold(self, move |target, token| match &target.value {
153 ValueInner::Table(tab) => tab.get(token),
154 ValueInner::Array(list) => parse_index(token).and_then(|x| list.get(x)),
155 _ => None,
156 })
157 }
158
159 pub fn pointer_mut(&mut self, pointer: &'de str) -> Option<&mut Self> {
161 if pointer.is_empty() {
162 return Some(self);
163 } else if !pointer.starts_with('/') {
164 return None;
165 }
166
167 pointer
168 .split('/')
169 .skip(1)
170 .try_fold(self, |target, token| match &mut target.value {
174 ValueInner::Table(tab) => tab.get_mut(token),
175 ValueInner::Array(list) => parse_index(token).and_then(|x| list.get_mut(x)),
176 _ => None,
177 })
178 }
179}
180
181fn parse_index(s: &str) -> Option<usize> {
182 if s.starts_with('+') || (s.starts_with('0') && s.len() != 1) {
183 return None;
184 }
185 s.parse().ok()
186}
187
188impl<'de> AsRef<ValueInner<'de>> for Value<'de> {
189 fn as_ref(&self) -> &ValueInner<'de> {
190 &self.value
191 }
192}
193
194impl fmt::Debug for Value<'_> {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 write!(f, "{:?}", self.value)
197 }
198}
199
200#[derive(Clone)]
202pub struct Key<'de> {
203 pub name: Cow<'de, str>,
206 pub span: Span,
208}
209
210impl std::borrow::Borrow<str> for Key<'_> {
211 fn borrow(&self) -> &str {
212 self.name.as_ref()
213 }
214}
215
216impl fmt::Debug for Key<'_> {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 f.write_str(&self.name)
219 }
220}
221
222impl fmt::Display for Key<'_> {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 f.write_str(&self.name)
225 }
226}
227
228impl Ord for Key<'_> {
229 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
230 self.name.cmp(&other.name)
231 }
232}
233
234impl PartialOrd for Key<'_> {
235 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
236 Some(self.cmp(other))
237 }
238}
239
240impl PartialEq for Key<'_> {
241 fn eq(&self, other: &Self) -> bool {
242 self.name.eq(&other.name)
243 }
244}
245
246impl Eq for Key<'_> {}
247
248pub type Table<'de> = std::collections::BTreeMap<Key<'de>, Value<'de>>;
252pub type Array<'de> = Vec<Value<'de>>;
254
255#[derive(Debug)]
260pub enum ValueInner<'de> {
261 String(Cow<'de, str>),
266 Integer(i64),
268 Float(f64),
270 Boolean(bool),
272 Array(Array<'de>),
274 Table(Table<'de>),
276}
277
278impl<'de> ValueInner<'de> {
279 pub fn type_str(&self) -> &'static str {
281 match self {
282 Self::String(..) => "string",
283 Self::Integer(..) => "integer",
284 Self::Float(..) => "float",
285 Self::Boolean(..) => "boolean",
286 Self::Array(..) => "array",
287 Self::Table(..) => "table",
288 }
289 }
290
291 #[inline]
293 pub fn as_str(&self) -> Option<&str> {
294 if let Self::String(s) = self {
295 Some(s.as_ref())
296 } else {
297 None
298 }
299 }
300
301 #[inline]
303 pub fn as_table(&self) -> Option<&Table<'de>> {
304 if let ValueInner::Table(t) = self {
305 Some(t)
306 } else {
307 None
308 }
309 }
310
311 #[inline]
313 pub fn as_array(&self) -> Option<&Array<'de>> {
314 if let ValueInner::Array(a) = self {
315 Some(a)
316 } else {
317 None
318 }
319 }
320
321 #[inline]
323 pub fn as_integer(&self) -> Option<i64> {
324 if let ValueInner::Integer(i) = self {
325 Some(*i)
326 } else {
327 None
328 }
329 }
330
331 #[inline]
333 pub fn as_float(&self) -> Option<f64> {
334 if let ValueInner::Float(f) = self {
335 Some(*f)
336 } else {
337 None
338 }
339 }
340
341 #[inline]
343 pub fn as_bool(&self) -> Option<bool> {
344 if let ValueInner::Boolean(b) = self {
345 Some(*b)
346 } else {
347 None
348 }
349 }
350}