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