toml/de/parser/
devalue.rs1use alloc::borrow::Cow;
4use core::mem::discriminant;
5use core::ops;
6
7use serde_spanned::Spanned;
8use toml_datetime::Datetime;
9
10use crate::alloc_prelude::*;
11use crate::de::DeArray;
12use crate::de::DeTable;
13
14pub type DeString<'i> = Cow<'i, str>;
16
17#[derive(Clone, Debug)]
19pub struct DeInteger<'i> {
20 pub(crate) inner: DeString<'i>,
21 pub(crate) radix: u32,
22}
23
24impl DeInteger<'_> {
25 pub(crate) fn to_u64(&self) -> Option<u64> {
26 u64::from_str_radix(self.inner.as_ref(), self.radix).ok()
27 }
28 pub(crate) fn to_i64(&self) -> Option<i64> {
29 i64::from_str_radix(self.inner.as_ref(), self.radix).ok()
30 }
31 pub(crate) fn to_u128(&self) -> Option<u128> {
32 u128::from_str_radix(self.inner.as_ref(), self.radix).ok()
33 }
34 pub(crate) fn to_i128(&self) -> Option<i128> {
35 i128::from_str_radix(self.inner.as_ref(), self.radix).ok()
36 }
37
38 pub fn as_str(&self) -> &str {
44 self.inner.as_ref()
45 }
46
47 pub fn radix(&self) -> u32 {
49 self.radix
50 }
51}
52
53impl Default for DeInteger<'_> {
54 fn default() -> Self {
55 Self {
56 inner: DeString::Borrowed("0"),
57 radix: 10,
58 }
59 }
60}
61
62impl core::fmt::Display for DeInteger<'_> {
63 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64 match self.radix {
65 2 => "0b".fmt(formatter)?,
66 8 => "0o".fmt(formatter)?,
67 10 => {}
68 16 => "0x".fmt(formatter)?,
69 _ => {
70 unreachable!(
71 "we should only ever have 2, 8, 10, and 16 radix, not {}",
72 self.radix
73 )
74 }
75 }
76 self.as_str().fmt(formatter)?;
77 Ok(())
78 }
79}
80
81#[derive(Clone, Debug)]
83pub struct DeFloat<'i> {
84 pub(crate) inner: DeString<'i>,
85}
86
87impl DeFloat<'_> {
88 pub(crate) fn to_f64(&self) -> Option<f64> {
89 let f: f64 = self.inner.as_ref().parse().ok()?;
90 if f.is_infinite() && !self.as_str().contains("inf") {
91 None
92 } else {
93 Some(f)
94 }
95 }
96
97 pub fn as_str(&self) -> &str {
99 self.inner.as_ref()
100 }
101}
102
103impl Default for DeFloat<'_> {
104 fn default() -> Self {
105 Self {
106 inner: DeString::Borrowed("0.0"),
107 }
108 }
109}
110
111impl core::fmt::Display for DeFloat<'_> {
112 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
113 self.as_str().fmt(formatter)?;
114 Ok(())
115 }
116}
117
118#[derive(Clone, Debug)]
120pub enum DeValue<'i> {
121 String(DeString<'i>),
123 Integer(DeInteger<'i>),
125 Float(DeFloat<'i>),
127 Boolean(bool),
129 Datetime(Datetime),
131 Array(DeArray<'i>),
133 Table(DeTable<'i>),
135}
136
137impl<'i> DeValue<'i> {
138 pub fn parse(input: &'i str) -> Result<Spanned<Self>, crate::de::Error> {
140 let source = toml_parser::Source::new(input);
141 let mut errors = crate::de::error::TomlSink::<Option<_>>::new(source);
142 let value = crate::de::parser::parse_value(source, &mut errors);
143 if let Some(err) = errors.into_inner() {
144 Err(err)
145 } else {
146 Ok(value)
147 }
148 }
149
150 pub fn parse_recoverable(input: &'i str) -> (Spanned<Self>, Vec<crate::de::Error>) {
152 let source = toml_parser::Source::new(input);
153 let mut errors = crate::de::error::TomlSink::<Vec<_>>::new(source);
154 let value = crate::de::parser::parse_value(source, &mut errors);
155 (value, errors.into_inner())
156 }
157
158 pub fn make_owned(&mut self) {
160 match self {
161 DeValue::String(v) => {
162 let owned = core::mem::take(v);
163 *v = Cow::Owned(owned.into_owned());
164 }
165 DeValue::Integer(..)
166 | DeValue::Float(..)
167 | DeValue::Boolean(..)
168 | DeValue::Datetime(..) => {}
169 DeValue::Array(v) => {
170 for e in v.iter_mut() {
171 e.get_mut().make_owned();
172 }
173 }
174 DeValue::Table(v) => v.make_owned(),
175 }
176 }
177
178 pub fn get<I: Index>(&self, index: I) -> Option<&Spanned<Self>> {
187 index.index(self)
188 }
189
190 pub fn as_integer(&self) -> Option<&DeInteger<'i>> {
192 match self {
193 DeValue::Integer(i) => Some(i),
194 _ => None,
195 }
196 }
197
198 pub fn is_integer(&self) -> bool {
200 self.as_integer().is_some()
201 }
202
203 pub fn as_float(&self) -> Option<&DeFloat<'i>> {
205 match self {
206 DeValue::Float(f) => Some(f),
207 _ => None,
208 }
209 }
210
211 pub fn is_float(&self) -> bool {
213 self.as_float().is_some()
214 }
215
216 pub fn as_bool(&self) -> Option<bool> {
218 match *self {
219 DeValue::Boolean(b) => Some(b),
220 _ => None,
221 }
222 }
223
224 pub fn is_bool(&self) -> bool {
226 self.as_bool().is_some()
227 }
228
229 pub fn as_str(&self) -> Option<&str> {
231 match *self {
232 DeValue::String(ref s) => Some(&**s),
233 _ => None,
234 }
235 }
236
237 pub fn is_str(&self) -> bool {
239 self.as_str().is_some()
240 }
241
242 pub fn as_datetime(&self) -> Option<&Datetime> {
251 match *self {
252 DeValue::Datetime(ref s) => Some(s),
253 _ => None,
254 }
255 }
256
257 pub fn is_datetime(&self) -> bool {
259 self.as_datetime().is_some()
260 }
261
262 pub fn as_array(&self) -> Option<&DeArray<'i>> {
264 match *self {
265 DeValue::Array(ref s) => Some(s),
266 _ => None,
267 }
268 }
269
270 pub(crate) fn as_array_mut(&mut self) -> Option<&mut DeArray<'i>> {
271 match self {
272 DeValue::Array(s) => Some(s),
273 _ => None,
274 }
275 }
276
277 pub fn is_array(&self) -> bool {
279 self.as_array().is_some()
280 }
281
282 pub fn as_table(&self) -> Option<&DeTable<'i>> {
284 match *self {
285 DeValue::Table(ref s) => Some(s),
286 _ => None,
287 }
288 }
289
290 pub(crate) fn as_table_mut(&mut self) -> Option<&mut DeTable<'i>> {
291 match self {
292 DeValue::Table(s) => Some(s),
293 _ => None,
294 }
295 }
296
297 pub fn is_table(&self) -> bool {
299 self.as_table().is_some()
300 }
301
302 pub fn same_type(&self, other: &DeValue<'_>) -> bool {
304 discriminant(self) == discriminant(other)
305 }
306
307 pub fn type_str(&self) -> &'static str {
309 match *self {
310 DeValue::String(..) => "string",
311 DeValue::Integer(..) => "integer",
312 DeValue::Float(..) => "float",
313 DeValue::Boolean(..) => "boolean",
314 DeValue::Datetime(..) => "datetime",
315 DeValue::Array(..) => "array",
316 DeValue::Table(..) => "table",
317 }
318 }
319}
320
321impl<I> ops::Index<I> for DeValue<'_>
322where
323 I: Index,
324{
325 type Output = Spanned<Self>;
326
327 fn index(&self, index: I) -> &Spanned<Self> {
328 self.get(index).expect("index not found")
329 }
330}
331
332pub trait Index: Sealed {
340 #[doc(hidden)]
341 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>>;
342}
343
344#[doc(hidden)]
347pub trait Sealed {}
348impl Sealed for usize {}
349impl Sealed for str {}
350impl Sealed for String {}
351impl<T: Sealed + ?Sized> Sealed for &T {}
352
353impl Index for usize {
354 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
355 match *val {
356 DeValue::Array(ref a) => a.get(*self),
357 _ => None,
358 }
359 }
360}
361
362impl Index for str {
363 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
364 match *val {
365 DeValue::Table(ref a) => a.get(self),
366 _ => None,
367 }
368 }
369}
370
371impl Index for String {
372 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
373 self[..].index(val)
374 }
375}
376
377impl<T> Index for &T
378where
379 T: Index + ?Sized,
380{
381 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
382 (**self).index(val)
383 }
384}