//! Definition of a TOML value use std::collections::BTreeMap; use std::fmt; use std::ops; use std::str::FromStr; use std::vec; use serde::ser; use serde::de; pub use datetime::{Datetime, DatetimeParseError}; use datetime::{DatetimeFromString, SERDE_STRUCT_FIELD_NAME}; /// Representation of a TOML value. #[derive(PartialEq, Clone, Debug)] pub enum Value { /// Represents a TOML string String(String), /// Represents a TOML integer Integer(i64), /// Represents a TOML float Float(f64), /// Represents a TOML boolean Boolean(bool), /// Represents a TOML datetime Datetime(Datetime), /// Represents a TOML array Array(Array), /// Represents a TOML table Table(Table), } /// Type representing a TOML array, payload of the `Value::Array` variant pub type Array = Vec; /// Type representing a TOML table, payload of the `Value::Table` variant pub type Table = BTreeMap; impl Value { /// Convert a `T` into `toml::Value` which is an enum that can represent /// any valid TOML data. /// /// This conversion can fail if `T`'s implementation of `Serialize` decides to /// fail, or if `T` contains a map with non-string keys. pub fn try_from(value: T) -> Result where T: ser::Serialize, { value.serialize(Serializer) } /// Interpret a `toml::Value` as an instance of type `T`. /// /// This conversion can fail if the structure of the `Value` does not match the /// structure expected by `T`, for example if `T` is a struct type but the /// `Value` contains something other than a TOML table. It can also fail if the /// structure is correct but `T`'s implementation of `Deserialize` decides that /// something is wrong with the data, for example required struct fields are /// missing from the TOML map or some number is too big to fit in the expected /// primitive type. pub fn try_into<'de, T>(self) -> Result where T: de::Deserialize<'de>, { de::Deserialize::deserialize(self) } /// Index into a TOML array or map. A string index can be used to access a /// value in a map, and a usize index can be used to access an element of an /// array. /// /// Returns `None` if the type of `self` does not match the type of the /// index, for example if the index is a string and `self` is an array or a /// number. Also returns `None` if the given key does not exist in the map /// or the given index is not within the bounds of the array. pub fn get(&self, index: I) -> Option<&Value> { index.index(self) } /// Mutably index into a TOML array or map. A string index can be used to /// access a value in a map, and a usize index can be used to access an /// element of an array. /// /// Returns `None` if the type of `self` does not match the type of the /// index, for example if the index is a string and `self` is an array or a /// number. Also returns `None` if the given key does not exist in the map /// or the given index is not within the bounds of the array. pub fn get_mut(&mut self, index: I) -> Option<&mut Value> { index.index_mut(self) } /// Extracts the integer value if it is an integer. pub fn as_integer(&self) -> Option { match *self { Value::Integer(i) => Some(i), _ => None } } /// Tests whether this value is an integer pub fn is_integer(&self) -> bool { self.as_integer().is_some() } /// Extracts the float value if it is a float. pub fn as_float(&self) -> Option { match *self { Value::Float(f) => Some(f), _ => None } } /// Tests whether this value is a float pub fn is_float(&self) -> bool { self.as_float().is_some() } /// Extracts the boolean value if it is a boolean. pub fn as_bool(&self) -> Option { match *self { Value::Boolean(b) => Some(b), _ => None } } /// Tests whether this value is a boolean pub fn is_bool(&self) -> bool { self.as_bool().is_some() } /// Extracts the string of this value if it is a string. pub fn as_str(&self) -> Option<&str> { match *self { Value::String(ref s) => Some(&**s), _ => None } } /// Tests if this value is a string pub fn is_str(&self) -> bool { self.as_str().is_some() } /// Extracts the datetime value if it is a datetime. /// /// Note that a parsed TOML value will only contain ISO 8601 dates. An /// example date is: /// /// ```notrust /// 1979-05-27T07:32:00Z /// ``` pub fn as_datetime(&self) -> Option<&Datetime> { match *self { Value::Datetime(ref s) => Some(s), _ => None } } /// Tests whether this value is a datetime pub fn is_datetime(&self) -> bool { self.as_datetime().is_some() } /// Extracts the array value if it is an array. pub fn as_array(&self) -> Option<&Vec> { match *self { Value::Array(ref s) => Some(s), _ => None } } /// Extracts the array value if it is an array. pub fn as_array_mut(&mut self) -> Option<&mut Vec> { match *self { Value::Array(ref mut s) => Some(s), _ => None } } /// Tests whether this value is an array pub fn is_array(&self) -> bool { self.as_array().is_some() } /// Extracts the table value if it is a table. pub fn as_table(&self) -> Option<&Table> { match *self { Value::Table(ref s) => Some(s), _ => None } } /// Extracts the table value if it is a table. pub fn as_table_mut(&mut self) -> Option<&mut Table> { match *self { Value::Table(ref mut s) => Some(s), _ => None } } /// Extracts the table value if it is a table. pub fn is_table(&self) -> bool { self.as_table().is_some() } /// Tests whether this and another value have the same type. pub fn same_type(&self, other: &Value) -> bool { match (self, other) { (&Value::String(..), &Value::String(..)) | (&Value::Integer(..), &Value::Integer(..)) | (&Value::Float(..), &Value::Float(..)) | (&Value::Boolean(..), &Value::Boolean(..)) | (&Value::Datetime(..), &Value::Datetime(..)) | (&Value::Array(..), &Value::Array(..)) | (&Value::Table(..), &Value::Table(..)) => true, _ => false, } } /// Returns a human-readable representation of the type of this value. pub fn type_str(&self) -> &'static str { match *self { Value::String(..) => "string", Value::Integer(..) => "integer", Value::Float(..) => "float", Value::Boolean(..) => "boolean", Value::Datetime(..) => "datetime", Value::Array(..) => "array", Value::Table(..) => "table", } } } impl ops::Index for Value where I: Index { type Output = Value; fn index(&self, index: I) -> &Value { self.get(index).expect("index not found") } } impl ops::IndexMut for Value where I: Index { fn index_mut(&mut self, index: I) -> &mut Value { self.get_mut(index).expect("index not found") } } impl From for Value { fn from(val: String) -> Value { Value::String(val) } } impl From for Value { fn from(val: i64) -> Value { Value::Integer(val) } } impl From for Value { fn from(val: f64) -> Value { Value::Float(val) } } impl From for Value { fn from(val: bool) -> Value { Value::Boolean(val) } } impl From for Value { fn from(val: Array) -> Value { Value::Array(val) } } impl From for Value { fn from(val: Table) -> Value { Value::Table(val) } } impl From for Value { fn from(val: Datetime) -> Value { Value::Datetime(val) } } /// Types that can be used to index a `toml::Value` /// /// Currently this is implemented for `usize` to index arrays and `str` to index /// tables. /// /// This trait is sealed and not intended for implementation outside of the /// `toml` crate. pub trait Index: Sealed { #[doc(hidden)] fn index<'a>(&self, val: &'a Value) -> Option<&'a Value>; #[doc(hidden)] fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value>; } /// An implementation detail that should not be implemented, this will change in /// the future and break code otherwise. #[doc(hidden)] pub trait Sealed {} impl Sealed for usize {} impl Sealed for str {} impl Sealed for String {} impl<'a, T: Sealed + ?Sized> Sealed for &'a T {} impl Index for usize { fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { match *val { Value::Array(ref a) => a.get(*self), _ => None, } } fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { match *val { Value::Array(ref mut a) => a.get_mut(*self), _ => None, } } } impl Index for str { fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { match *val { Value::Table(ref a) => a.get(self), _ => None, } } fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { match *val { Value::Table(ref mut a) => a.get_mut(self), _ => None, } } } impl Index for String { fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { self[..].index(val) } fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { self[..].index_mut(val) } } impl<'s, T: ?Sized> Index for &'s T where T: Index { fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { (**self).index(val) } fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { (**self).index_mut(val) } } impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ::ser::to_string(self).expect("Unable to represent value as string").fmt(f) } } impl FromStr for Value { type Err = ::de::Error; fn from_str(s: &str) -> Result { ::from_str(s) } } impl ser::Serialize for Value { fn serialize(&self, serializer: S) -> Result where S: ser::Serializer { use serde::ser::SerializeMap; match *self { Value::String(ref s) => serializer.serialize_str(s), Value::Integer(i) => serializer.serialize_i64(i), Value::Float(f) => serializer.serialize_f64(f), Value::Boolean(b) => serializer.serialize_bool(b), Value::Datetime(ref s) => s.serialize(serializer), Value::Array(ref a) => a.serialize(serializer), Value::Table(ref t) => { let mut map = serializer.serialize_map(Some(t.len()))?; // Be sure to visit non-tables first (and also non // array-of-tables) as all keys must be emitted first. for (k, v) in t { if !v.is_table() && !v.is_array() || (v.as_array().map(|a| !a.iter().any(|v| v.is_table())).unwrap_or(false)) { map.serialize_entry(k, v)?; } } for (k, v) in t { if v.as_array().map(|a| a.iter().any(|v| v.is_table())).unwrap_or(false) { map.serialize_entry(k, v)?; } } for (k, v) in t { if v.is_table() { map.serialize_entry(k, v)?; } } map.end() } } } } impl<'de> de::Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { struct ValueVisitor; impl<'de> de::Visitor<'de> for ValueVisitor { type Value = Value; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("any valid TOML value") } fn visit_bool(self, value: bool) -> Result { Ok(Value::Boolean(value)) } fn visit_i64(self, value: i64) -> Result { Ok(Value::Integer(value)) } fn visit_f64(self, value: f64) -> Result { Ok(Value::Float(value)) } fn visit_str(self, value: &str) -> Result { Ok(Value::String(value.into())) } fn visit_string(self, value: String) -> Result { Ok(Value::String(value)) } fn visit_some(self, deserializer: D) -> Result where D: de::Deserializer<'de>, { de::Deserialize::deserialize(deserializer) } fn visit_seq(self, mut visitor: V) -> Result where V: de::SeqAccess<'de>, { let mut vec = Vec::new(); while let Some(elem) = try!(visitor.next_element()) { vec.push(elem); } Ok(Value::Array(vec)) } fn visit_map(self, mut visitor: V) -> Result where V: de::MapAccess<'de>, { let mut key = String::new(); let datetime = visitor.next_key_seed(DatetimeOrTable { key: &mut key, })?; match datetime { Some(true) => { let date: DatetimeFromString = visitor.next_value()?; return Ok(Value::Datetime(date.value)) } None => return Ok(Value::Table(BTreeMap::new())), Some(false) => {} } let mut map = BTreeMap::new(); map.insert(key, visitor.next_value()?); while let Some(key) = visitor.next_key()? { if map.contains_key(&key) { let msg = format!("duplicate key: `{}`", key); return Err(de::Error::custom(msg)) } map.insert(key, visitor.next_value()?); } Ok(Value::Table(map)) } } deserializer.deserialize_any(ValueVisitor) } } impl<'de> de::Deserializer<'de> for Value { type Error = ::de::Error; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self { Value::Boolean(v) => visitor.visit_bool(v), Value::Integer(n) => visitor.visit_i64(n), Value::Float(n) => visitor.visit_f64(n), Value::String(v) => visitor.visit_string(v), Value::Datetime(v) => visitor.visit_string(v.to_string()), Value::Array(v) => { let len = v.len(); let mut deserializer = SeqDeserializer::new(v); let seq = visitor.visit_seq(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(seq) } else { Err(de::Error::invalid_length(len, &"fewer elements in array")) } } Value::Table(v) => { let len = v.len(); let mut deserializer = MapDeserializer::new(v); let map = visitor.visit_map(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(map) } else { Err(de::Error::invalid_length(len, &"fewer elements in map")) } } } } // `None` is interpreted as a missing field so be sure to implement `Some` // as a present field. fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_some(self) } forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq bytes byte_buf map unit_struct tuple_struct struct tuple ignored_any enum newtype_struct identifier } } struct SeqDeserializer { iter: vec::IntoIter, } impl SeqDeserializer { fn new(vec: Vec) -> Self { SeqDeserializer { iter: vec.into_iter(), } } } impl<'de> de::SeqAccess<'de> for SeqDeserializer { type Error = ::de::Error; fn next_element_seed(&mut self, seed: T) -> Result, ::de::Error> where T: de::DeserializeSeed<'de>, { match self.iter.next() { Some(value) => seed.deserialize(value).map(Some), None => Ok(None), } } fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } struct MapDeserializer { iter: as IntoIterator>::IntoIter, value: Option<(String, Value)>, } impl MapDeserializer { fn new(map: BTreeMap) -> Self { MapDeserializer { iter: map.into_iter(), value: None, } } } impl<'de> de::MapAccess<'de> for MapDeserializer { type Error = ::de::Error; fn next_key_seed(&mut self, seed: T) -> Result, ::de::Error> where T: de::DeserializeSeed<'de>, { match self.iter.next() { Some((key, value)) => { self.value = Some((key.clone(), value)); seed.deserialize(Value::String(key)).map(Some) } None => Ok(None), } } fn next_value_seed(&mut self, seed: T) -> Result where T: de::DeserializeSeed<'de>, { let (key, res) = match self.value.take() { Some((key, value)) => (key, seed.deserialize(value)), None => return Err(de::Error::custom("value is missing")), }; res.map_err(|mut error| { error.add_key_context(&key); error }) } fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } struct Serializer; impl ser::Serializer for Serializer { type Ok = Value; type Error = ::ser::Error; type SerializeSeq = SerializeVec; type SerializeTuple = ser::Impossible; type SerializeTupleStruct = ser::Impossible; type SerializeTupleVariant = ser::Impossible; type SerializeMap = SerializeMap; type SerializeStruct = SerializeMap; type SerializeStructVariant = ser::Impossible; fn serialize_bool(self, value: bool) -> Result { Ok(Value::Boolean(value)) } fn serialize_i8(self, value: i8) -> Result { self.serialize_i64(value.into()) } fn serialize_i16(self, value: i16) -> Result { self.serialize_i64(value.into()) } fn serialize_i32(self, value: i32) -> Result { self.serialize_i64(value.into()) } fn serialize_i64(self, value: i64) -> Result { Ok(Value::Integer(value.into())) } fn serialize_u8(self, value: u8) -> Result { self.serialize_i64(value.into()) } fn serialize_u16(self, value: u16) -> Result { self.serialize_i64(value.into()) } fn serialize_u32(self, value: u32) -> Result { self.serialize_i64(value.into()) } fn serialize_u64(self, value: u64) -> Result { if value <= i64::max_value() as u64 { self.serialize_i64(value as i64) } else { Err(ser::Error::custom("u64 value was too large")) } } fn serialize_f32(self, value: f32) -> Result { self.serialize_f64(value.into()) } fn serialize_f64(self, value: f64) -> Result { Ok(Value::Float(value)) } fn serialize_char(self, value: char) -> Result { let mut s = String::new(); s.push(value); self.serialize_str(&s) } fn serialize_str(self, value: &str) -> Result { Ok(Value::String(value.to_owned())) } fn serialize_bytes(self, value: &[u8]) -> Result { let vec = value.iter().map(|&b| Value::Integer(b.into())).collect(); Ok(Value::Array(vec)) } fn serialize_unit(self) -> Result { Err(::ser::Error::UnsupportedType) } fn serialize_unit_struct(self, _name: &'static str) -> Result { Err(::ser::Error::UnsupportedType) } fn serialize_unit_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str) -> Result { self.serialize_str(_variant) } fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result where T: ser::Serialize, { value.serialize(self) } fn serialize_newtype_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _value: &T) -> Result where T: ser::Serialize, { Err(::ser::Error::UnsupportedType) } fn serialize_none(self) -> Result { Err(::ser::Error::UnsupportedNone) } fn serialize_some(self, value: &T) -> Result where T: ser::Serialize, { value.serialize(self) } fn serialize_seq(self, len: Option) -> Result { Ok(SerializeVec { vec: Vec::with_capacity(len.unwrap_or(0)) }) } fn serialize_tuple(self, _len: usize) -> Result { Err(::ser::Error::UnsupportedType) } fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result { Err(::ser::Error::UnsupportedType) } fn serialize_tuple_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize) -> Result { Err(::ser::Error::UnsupportedType) } fn serialize_map(self, _len: Option) -> Result { Ok(SerializeMap { map: BTreeMap::new(), next_key: None, }) } fn serialize_struct(self, _name: &'static str, len: usize) -> Result { self.serialize_map(Some(len)) } fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize) -> Result { Err(::ser::Error::UnsupportedType) } } struct SerializeVec { vec: Vec, } struct SerializeMap { map: BTreeMap, next_key: Option, } impl ser::SerializeSeq for SerializeVec { type Ok = Value; type Error = ::ser::Error; fn serialize_element(&mut self, value: &T) -> Result<(), ::ser::Error> where T: ser::Serialize { self.vec.push(Value::try_from(value)?); Ok(()) } fn end(self) -> Result { Ok(Value::Array(self.vec)) } } impl ser::SerializeMap for SerializeMap { type Ok = Value; type Error = ::ser::Error; fn serialize_key(&mut self, key: &T) -> Result<(), ::ser::Error> where T: ser::Serialize { match Value::try_from(key)? { Value::String(s) => self.next_key = Some(s), _ => return Err(::ser::Error::KeyNotString), }; Ok(()) } fn serialize_value(&mut self, value: &T) -> Result<(), ::ser::Error> where T: ser::Serialize { let key = self.next_key.take(); let key = key.expect("serialize_value called before serialize_key"); match Value::try_from(value) { Ok(value) => { self.map.insert(key, value); } Err(::ser::Error::UnsupportedNone) => {} Err(e) => return Err(e), } Ok(()) } fn end(self) -> Result { Ok(Value::Table(self.map)) } } impl ser::SerializeStruct for SerializeMap { type Ok = Value; type Error = ::ser::Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), ::ser::Error> where T: ser::Serialize { try!(ser::SerializeMap::serialize_key(self, key)); ser::SerializeMap::serialize_value(self, value) } fn end(self) -> Result { ser::SerializeMap::end(self) } } struct DatetimeOrTable<'a> { key: &'a mut String, } impl<'a, 'de> de::DeserializeSeed<'de> for DatetimeOrTable<'a> { type Value = bool; fn deserialize(self, deserializer: D) -> Result where D: de::Deserializer<'de> { deserializer.deserialize_any(self) } } impl<'a, 'de> de::Visitor<'de> for DatetimeOrTable<'a> { type Value = bool; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string key") } fn visit_str(self, s: &str) -> Result where E: de::Error, { if s == SERDE_STRUCT_FIELD_NAME { Ok(true) } else { self.key.push_str(s); Ok(false) } } fn visit_string(self, s: String) -> Result where E: de::Error, { if s == SERDE_STRUCT_FIELD_NAME { Ok(true) } else { *self.key = s; Ok(false) } } }