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(crate) fn as_str(&self) -> &str {
39 self.inner.as_ref()
40 }
41}
42
43impl Default for DeInteger<'_> {
44 fn default() -> Self {
45 Self {
46 inner: DeString::Borrowed("0"),
47 radix: 10,
48 }
49 }
50}
51
52impl core::fmt::Display for DeInteger<'_> {
53 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 match self.radix {
55 2 => "0b".fmt(formatter)?,
56 8 => "0o".fmt(formatter)?,
57 10 => {}
58 16 => "0x".fmt(formatter)?,
59 _ => {
60 unreachable!(
61 "we should only ever have 2, 8, 10, and 16 radix, not {}",
62 self.radix
63 )
64 }
65 }
66 self.as_str().fmt(formatter)?;
67 Ok(())
68 }
69}
70
71#[derive(Clone, Debug)]
73pub struct DeFloat<'i> {
74 pub(crate) inner: DeString<'i>,
75}
76
77impl DeFloat<'_> {
78 pub(crate) fn to_f64(&self) -> Option<f64> {
79 let f: f64 = self.inner.as_ref().parse().ok()?;
80 if f.is_infinite() && !self.as_str().contains("inf") {
81 None
82 } else {
83 Some(f)
84 }
85 }
86
87 pub(crate) fn as_str(&self) -> &str {
88 self.inner.as_ref()
89 }
90}
91
92impl Default for DeFloat<'_> {
93 fn default() -> Self {
94 Self {
95 inner: DeString::Borrowed("0.0"),
96 }
97 }
98}
99
100impl core::fmt::Display for DeFloat<'_> {
101 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102 self.as_str().fmt(formatter)?;
103 Ok(())
104 }
105}
106
107#[derive(Clone, Debug)]
109pub enum DeValue<'i> {
110 String(DeString<'i>),
112 Integer(DeInteger<'i>),
114 Float(DeFloat<'i>),
116 Boolean(bool),
118 Datetime(Datetime),
120 Array(DeArray<'i>),
122 Table(DeTable<'i>),
124}
125
126impl<'i> DeValue<'i> {
127 pub fn parse(input: &'i str) -> Result<Spanned<Self>, crate::de::Error> {
129 let source = toml_parser::Source::new(input);
130 let mut errors = crate::de::error::TomlSink::<Option<_>>::new(source);
131 let value = crate::de::parser::parse_value(source, &mut errors);
132 if let Some(err) = errors.into_inner() {
133 Err(err)
134 } else {
135 Ok(value)
136 }
137 }
138
139 pub fn parse_recoverable(input: &'i str) -> (Spanned<Self>, Vec<crate::de::Error>) {
141 let source = toml_parser::Source::new(input);
142 let mut errors = crate::de::error::TomlSink::<Vec<_>>::new(source);
143 let value = crate::de::parser::parse_value(source, &mut errors);
144 (value, errors.into_inner())
145 }
146
147 pub fn make_owned(&mut self) {
149 match self {
150 DeValue::String(v) => {
151 let owned = core::mem::take(v);
152 *v = Cow::Owned(owned.into_owned());
153 }
154 DeValue::Integer(..)
155 | DeValue::Float(..)
156 | DeValue::Boolean(..)
157 | DeValue::Datetime(..) => {}
158 DeValue::Array(v) => {
159 for e in v.iter_mut() {
160 e.get_mut().make_owned();
161 }
162 }
163 DeValue::Table(v) => v.make_owned(),
164 }
165 }
166
167 pub fn get<I: Index>(&self, index: I) -> Option<&Spanned<Self>> {
176 index.index(self)
177 }
178
179 pub fn as_integer(&self) -> Option<&DeInteger<'i>> {
181 match self {
182 DeValue::Integer(i) => Some(i),
183 _ => None,
184 }
185 }
186
187 pub fn is_integer(&self) -> bool {
189 self.as_integer().is_some()
190 }
191
192 pub fn as_float(&self) -> Option<&DeFloat<'i>> {
194 match self {
195 DeValue::Float(f) => Some(f),
196 _ => None,
197 }
198 }
199
200 pub fn is_float(&self) -> bool {
202 self.as_float().is_some()
203 }
204
205 pub fn as_bool(&self) -> Option<bool> {
207 match *self {
208 DeValue::Boolean(b) => Some(b),
209 _ => None,
210 }
211 }
212
213 pub fn is_bool(&self) -> bool {
215 self.as_bool().is_some()
216 }
217
218 pub fn as_str(&self) -> Option<&str> {
220 match *self {
221 DeValue::String(ref s) => Some(&**s),
222 _ => None,
223 }
224 }
225
226 pub fn is_str(&self) -> bool {
228 self.as_str().is_some()
229 }
230
231 pub fn as_datetime(&self) -> Option<&Datetime> {
240 match *self {
241 DeValue::Datetime(ref s) => Some(s),
242 _ => None,
243 }
244 }
245
246 pub fn is_datetime(&self) -> bool {
248 self.as_datetime().is_some()
249 }
250
251 pub fn as_array(&self) -> Option<&DeArray<'i>> {
253 match *self {
254 DeValue::Array(ref s) => Some(s),
255 _ => None,
256 }
257 }
258
259 pub(crate) fn as_array_mut(&mut self) -> Option<&mut DeArray<'i>> {
260 match self {
261 DeValue::Array(s) => Some(s),
262 _ => None,
263 }
264 }
265
266 pub fn is_array(&self) -> bool {
268 self.as_array().is_some()
269 }
270
271 pub fn as_table(&self) -> Option<&DeTable<'i>> {
273 match *self {
274 DeValue::Table(ref s) => Some(s),
275 _ => None,
276 }
277 }
278
279 pub(crate) fn as_table_mut(&mut self) -> Option<&mut DeTable<'i>> {
280 match self {
281 DeValue::Table(s) => Some(s),
282 _ => None,
283 }
284 }
285
286 pub fn is_table(&self) -> bool {
288 self.as_table().is_some()
289 }
290
291 pub fn same_type(&self, other: &DeValue<'_>) -> bool {
293 discriminant(self) == discriminant(other)
294 }
295
296 pub fn type_str(&self) -> &'static str {
298 match *self {
299 DeValue::String(..) => "string",
300 DeValue::Integer(..) => "integer",
301 DeValue::Float(..) => "float",
302 DeValue::Boolean(..) => "boolean",
303 DeValue::Datetime(..) => "datetime",
304 DeValue::Array(..) => "array",
305 DeValue::Table(..) => "table",
306 }
307 }
308}
309
310impl<I> ops::Index<I> for DeValue<'_>
311where
312 I: Index,
313{
314 type Output = Spanned<Self>;
315
316 fn index(&self, index: I) -> &Spanned<Self> {
317 self.get(index).expect("index not found")
318 }
319}
320
321pub trait Index: Sealed {
329 #[doc(hidden)]
330 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>>;
331}
332
333#[doc(hidden)]
336pub trait Sealed {}
337impl Sealed for usize {}
338impl Sealed for str {}
339impl Sealed for String {}
340impl<T: Sealed + ?Sized> Sealed for &T {}
341
342impl Index for usize {
343 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
344 match *val {
345 DeValue::Array(ref a) => a.get(*self),
346 _ => None,
347 }
348 }
349}
350
351impl Index for str {
352 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
353 match *val {
354 DeValue::Table(ref a) => a.get(self),
355 _ => None,
356 }
357 }
358}
359
360impl Index for String {
361 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
362 self[..].index(val)
363 }
364}
365
366impl<T> Index for &T
367where
368 T: Index + ?Sized,
369{
370 fn index<'r, 'i>(&self, val: &'r DeValue<'i>) -> Option<&'r Spanned<DeValue<'i>>> {
371 (**self).index(val)
372 }
373}