1 use std::iter::FromIterator;
2 use std::str::FromStr;
3 
4 use toml_datetime::*;
5 
6 use crate::key::Key;
7 use crate::repr::{Decor, Formatted};
8 use crate::{Array, InlineTable, InternalString, RawString};
9 
10 /// Representation of a TOML Value (as part of a Key/Value Pair).
11 #[derive(Debug, Clone)]
12 pub enum Value {
13     /// A string value.
14     String(Formatted<String>),
15     /// A 64-bit integer value.
16     Integer(Formatted<i64>),
17     /// A 64-bit float value.
18     Float(Formatted<f64>),
19     /// A boolean value.
20     Boolean(Formatted<bool>),
21     /// An RFC 3339 formatted date-time with offset.
22     Datetime(Formatted<Datetime>),
23     /// An inline array of values.
24     Array(Array),
25     /// An inline table of key/value pairs.
26     InlineTable(InlineTable),
27 }
28 
29 /// Downcasting
30 impl Value {
31     /// Text description of value type
type_name(&self) -> &'static str32     pub fn type_name(&self) -> &'static str {
33         match self {
34             Value::String(..) => "string",
35             Value::Integer(..) => "integer",
36             Value::Float(..) => "float",
37             Value::Boolean(..) => "boolean",
38             Value::Datetime(..) => "datetime",
39             Value::Array(..) => "array",
40             Value::InlineTable(..) => "inline table",
41         }
42     }
43 
44     /// Casts `self` to str.
as_str(&self) -> Option<&str>45     pub fn as_str(&self) -> Option<&str> {
46         match *self {
47             Value::String(ref value) => Some(value.value()),
48             _ => None,
49         }
50     }
51 
52     /// Returns true iff `self` is a string.
is_str(&self) -> bool53     pub fn is_str(&self) -> bool {
54         self.as_str().is_some()
55     }
56 
57     /// Casts `self` to integer.
as_integer(&self) -> Option<i64>58     pub fn as_integer(&self) -> Option<i64> {
59         match *self {
60             Value::Integer(ref value) => Some(*value.value()),
61             _ => None,
62         }
63     }
64 
65     /// Returns true iff `self` is an integer.
is_integer(&self) -> bool66     pub fn is_integer(&self) -> bool {
67         self.as_integer().is_some()
68     }
69 
70     /// Casts `self` to float.
as_float(&self) -> Option<f64>71     pub fn as_float(&self) -> Option<f64> {
72         match *self {
73             Value::Float(ref value) => Some(*value.value()),
74             _ => None,
75         }
76     }
77 
78     /// Returns true iff `self` is a float.
is_float(&self) -> bool79     pub fn is_float(&self) -> bool {
80         self.as_float().is_some()
81     }
82 
83     /// Casts `self` to boolean.
as_bool(&self) -> Option<bool>84     pub fn as_bool(&self) -> Option<bool> {
85         match *self {
86             Value::Boolean(ref value) => Some(*value.value()),
87             _ => None,
88         }
89     }
90 
91     /// Returns true iff `self` is a boolean.
is_bool(&self) -> bool92     pub fn is_bool(&self) -> bool {
93         self.as_bool().is_some()
94     }
95 
96     /// Casts `self` to date-time.
as_datetime(&self) -> Option<&Datetime>97     pub fn as_datetime(&self) -> Option<&Datetime> {
98         match *self {
99             Value::Datetime(ref value) => Some(value.value()),
100             _ => None,
101         }
102     }
103 
104     /// Returns true iff `self` is a date-time.
is_datetime(&self) -> bool105     pub fn is_datetime(&self) -> bool {
106         self.as_datetime().is_some()
107     }
108 
109     /// Casts `self` to array.
as_array(&self) -> Option<&Array>110     pub fn as_array(&self) -> Option<&Array> {
111         match *self {
112             Value::Array(ref value) => Some(value),
113             _ => None,
114         }
115     }
116 
117     /// Casts `self` to mutable array.
as_array_mut(&mut self) -> Option<&mut Array>118     pub fn as_array_mut(&mut self) -> Option<&mut Array> {
119         match *self {
120             Value::Array(ref mut value) => Some(value),
121             _ => None,
122         }
123     }
124 
125     /// Returns true iff `self` is an array.
is_array(&self) -> bool126     pub fn is_array(&self) -> bool {
127         self.as_array().is_some()
128     }
129 
130     /// Casts `self` to inline table.
as_inline_table(&self) -> Option<&InlineTable>131     pub fn as_inline_table(&self) -> Option<&InlineTable> {
132         match *self {
133             Value::InlineTable(ref value) => Some(value),
134             _ => None,
135         }
136     }
137 
138     /// Casts `self` to mutable inline table.
as_inline_table_mut(&mut self) -> Option<&mut InlineTable>139     pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
140         match *self {
141             Value::InlineTable(ref mut value) => Some(value),
142             _ => None,
143         }
144     }
145 
146     /// Returns true iff `self` is an inline table.
is_inline_table(&self) -> bool147     pub fn is_inline_table(&self) -> bool {
148         self.as_inline_table().is_some()
149     }
150 }
151 
152 impl Value {
153     /// Get the decoration of the value.
154     /// # Example
155     /// ```rust
156     /// let v = toml_edit::Value::from(true);
157     /// assert_eq!(v.decor().suffix(), None);
158     ///```
decor_mut(&mut self) -> &mut Decor159     pub fn decor_mut(&mut self) -> &mut Decor {
160         match self {
161             Value::String(f) => f.decor_mut(),
162             Value::Integer(f) => f.decor_mut(),
163             Value::Float(f) => f.decor_mut(),
164             Value::Boolean(f) => f.decor_mut(),
165             Value::Datetime(f) => f.decor_mut(),
166             Value::Array(a) => a.decor_mut(),
167             Value::InlineTable(t) => t.decor_mut(),
168         }
169     }
170 
171     /// Get the decoration of the value.
172     /// # Example
173     /// ```rust
174     /// let v = toml_edit::Value::from(true);
175     /// assert_eq!(v.decor().suffix(), None);
176     ///```
decor(&self) -> &Decor177     pub fn decor(&self) -> &Decor {
178         match *self {
179             Value::String(ref f) => f.decor(),
180             Value::Integer(ref f) => f.decor(),
181             Value::Float(ref f) => f.decor(),
182             Value::Boolean(ref f) => f.decor(),
183             Value::Datetime(ref f) => f.decor(),
184             Value::Array(ref a) => a.decor(),
185             Value::InlineTable(ref t) => t.decor(),
186         }
187     }
188 
189     /// Sets the prefix and the suffix for value.
190     /// # Example
191     /// ```rust
192     /// # #[cfg(feature = "display")] {
193     /// let mut v = toml_edit::Value::from(42);
194     /// assert_eq!(&v.to_string(), "42");
195     /// let d = v.decorated(" ", " ");
196     /// assert_eq!(&d.to_string(), " 42 ");
197     /// # }
198     /// ```
decorated(mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self199     pub fn decorated(mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self {
200         self.decorate(prefix, suffix);
201         self
202     }
203 
decorate(&mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>)204     pub(crate) fn decorate(&mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) {
205         let decor = self.decor_mut();
206         *decor = Decor::new(prefix, suffix);
207     }
208 
209     /// Returns the location within the original document
span(&self) -> Option<std::ops::Range<usize>>210     pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
211         match self {
212             Value::String(f) => f.span(),
213             Value::Integer(f) => f.span(),
214             Value::Float(f) => f.span(),
215             Value::Boolean(f) => f.span(),
216             Value::Datetime(f) => f.span(),
217             Value::Array(a) => a.span(),
218             Value::InlineTable(t) => t.span(),
219         }
220     }
221 
despan(&mut self, input: &str)222     pub(crate) fn despan(&mut self, input: &str) {
223         match self {
224             Value::String(f) => f.despan(input),
225             Value::Integer(f) => f.despan(input),
226             Value::Float(f) => f.despan(input),
227             Value::Boolean(f) => f.despan(input),
228             Value::Datetime(f) => f.despan(input),
229             Value::Array(a) => a.despan(input),
230             Value::InlineTable(t) => t.despan(input),
231         }
232     }
233 }
234 
235 #[cfg(feature = "parse")]
236 impl FromStr for Value {
237     type Err = crate::TomlError;
238 
239     /// Parses a value from a &str
from_str(s: &str) -> Result<Self, Self::Err>240     fn from_str(s: &str) -> Result<Self, Self::Err> {
241         crate::parser::parse_value(s)
242     }
243 }
244 
245 impl<'b> From<&'b Value> for Value {
from(s: &'b Value) -> Self246     fn from(s: &'b Value) -> Self {
247         s.clone()
248     }
249 }
250 
251 impl<'b> From<&'b str> for Value {
from(s: &'b str) -> Self252     fn from(s: &'b str) -> Self {
253         s.to_owned().into()
254     }
255 }
256 
257 impl<'b> From<&'b String> for Value {
from(s: &'b String) -> Self258     fn from(s: &'b String) -> Self {
259         s.to_owned().into()
260     }
261 }
262 
263 impl From<String> for Value {
from(s: String) -> Self264     fn from(s: String) -> Self {
265         Value::String(Formatted::new(s))
266     }
267 }
268 
269 impl<'b> From<&'b InternalString> for Value {
from(s: &'b InternalString) -> Self270     fn from(s: &'b InternalString) -> Self {
271         s.as_str().into()
272     }
273 }
274 
275 impl From<InternalString> for Value {
from(s: InternalString) -> Self276     fn from(s: InternalString) -> Self {
277         s.as_str().into()
278     }
279 }
280 
281 impl From<i64> for Value {
from(i: i64) -> Self282     fn from(i: i64) -> Self {
283         Value::Integer(Formatted::new(i))
284     }
285 }
286 
287 impl From<f64> for Value {
from(f: f64) -> Self288     fn from(f: f64) -> Self {
289         // Preserve sign of NaN. It may get written to TOML as `-nan`.
290         Value::Float(Formatted::new(f))
291     }
292 }
293 
294 impl From<bool> for Value {
from(b: bool) -> Self295     fn from(b: bool) -> Self {
296         Value::Boolean(Formatted::new(b))
297     }
298 }
299 
300 impl From<Datetime> for Value {
from(d: Datetime) -> Self301     fn from(d: Datetime) -> Self {
302         Value::Datetime(Formatted::new(d))
303     }
304 }
305 
306 impl From<Date> for Value {
from(d: Date) -> Self307     fn from(d: Date) -> Self {
308         let d: Datetime = d.into();
309         d.into()
310     }
311 }
312 
313 impl From<Time> for Value {
from(d: Time) -> Self314     fn from(d: Time) -> Self {
315         let d: Datetime = d.into();
316         d.into()
317     }
318 }
319 
320 impl From<Array> for Value {
from(array: Array) -> Self321     fn from(array: Array) -> Self {
322         Value::Array(array)
323     }
324 }
325 
326 impl From<InlineTable> for Value {
from(table: InlineTable) -> Self327     fn from(table: InlineTable) -> Self {
328         Value::InlineTable(table)
329     }
330 }
331 
332 impl<V: Into<Value>> FromIterator<V> for Value {
from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = V>,333     fn from_iter<I>(iter: I) -> Self
334     where
335         I: IntoIterator<Item = V>,
336     {
337         let array: Array = iter.into_iter().collect();
338         Value::Array(array)
339     }
340 }
341 
342 impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Value {
from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = (K, V)>,343     fn from_iter<I>(iter: I) -> Self
344     where
345         I: IntoIterator<Item = (K, V)>,
346     {
347         let table: InlineTable = iter.into_iter().collect();
348         Value::InlineTable(table)
349     }
350 }
351 
352 #[cfg(feature = "display")]
353 impl std::fmt::Display for Value {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result354     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355         crate::encode::encode_value(self, f, None, ("", ""))
356     }
357 }
358 
359 // `key1 = value1`
360 pub(crate) const DEFAULT_VALUE_DECOR: (&str, &str) = (" ", "");
361 // `{ key = value }`
362 pub(crate) const DEFAULT_TRAILING_VALUE_DECOR: (&str, &str) = (" ", " ");
363 // `[value1, value2]`
364 pub(crate) const DEFAULT_LEADING_VALUE_DECOR: (&str, &str) = ("", "");
365 
366 #[cfg(test)]
367 #[cfg(feature = "parse")]
368 #[cfg(feature = "display")]
369 mod tests {
370     use super::*;
371 
372     #[test]
from_iter_formatting()373     fn from_iter_formatting() {
374         let features = vec!["node".to_owned(), "mouth".to_owned()];
375         let features: Value = features.iter().cloned().collect();
376         assert_eq!(features.to_string(), r#"["node", "mouth"]"#);
377     }
378 }
379