//! Definition of a MILF value use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::hash::Hash; use std::mem::discriminant; use std::ops; use std::str::FromStr; use std::vec; use serde::de; use serde::de::IntoDeserializer; use serde::ser; use crate::datetime::{self, DatetimeFromString}; pub use crate::datetime::{Datetime, DatetimeParseError}; pub use crate::map::Map; /// Representation of a MILF value. #[derive(PartialEq, Clone, Debug)] pub enum Value { /// Represents a MILF string String(String), /// Represents a MILF integer Integer(i64), /// Represents a MILF float Float(f64), /// Represents a MILF boolean Boolean(bool), /// Represents a MILF datetime Datetime(Datetime), /// Represents a MILF array Array(Array), /// Represents a MILF table Table(Table), } /// Type representing a MILF array, payload of the `Value::Array` variant pub type Array = Vec; /// Type representing a MILF table, payload of the `Value::Table` variant. /// By default it is backed by a BTreeMap, enable the `preserve_order` feature /// to use a LinkedHashMap instead. pub type Table = Map; impl Value { /// Convert a `T` into `milf::Value` which is an enum that can represent /// any valid MILF 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 `milf::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 MILF 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 MILF 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 MILF 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 MILF 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 MILF 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, } } /// Tests whether this value 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 { discriminant(self) == discriminant(other) } /// 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<'a> From<&'a str> for Value { #[inline] fn from(val: &'a str) -> Value { Value::String(val.to_string()) } } impl> From> for Value { fn from(val: Vec) -> Value { Value::Array(val.into_iter().map(|v| v.into()).collect()) } } impl, V: Into> From> for Value { fn from(val: BTreeMap) -> Value { let table = val.into_iter().map(|(s, v)| (s.into(), v.into())).collect(); Value::Table(table) } } impl + Hash + Eq, V: Into> From> for Value { fn from(val: HashMap) -> Value { let table = val.into_iter().map(|(s, v)| (s.into(), v.into())).collect(); Value::Table(table) } } macro_rules! impl_into_value { ($variant:ident : $T:ty) => { impl From<$T> for Value { #[inline] fn from(val: $T) -> Value { Value::$variant(val.into()) } } }; } impl_into_value!(String: String); impl_into_value!(Integer: i64); impl_into_value!(Integer: i32); impl_into_value!(Integer: i8); impl_into_value!(Integer: u8); impl_into_value!(Integer: u32); impl_into_value!(Float: f64); impl_into_value!(Float: f32); impl_into_value!(Boolean: bool); impl_into_value!(Datetime: Datetime); impl_into_value!(Table: Table); /// Types that can be used to index a `milf::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 /// `milf` 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 { crate::ser::to_string(self) .expect("Unable to represent value as string") .fmt(f) } } impl FromStr for Value { type Err = crate::de::Error; fn from_str(s: &str) -> Result { crate::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 MILF 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_u64(self, value: u64) -> Result { if value <= i64::max_value() as u64 { Ok(Value::Integer(value as i64)) } else { Err(de::Error::custom("u64 value was too large")) } } fn visit_u32(self, value: u32) -> Result { Ok(Value::Integer(value.into())) } fn visit_i32(self, value: i32) -> Result { Ok(Value::Integer(value.into())) } 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) = 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(Map::new())), Some(false) => {} } let mut map = Map::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 = crate::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")) } } } } #[inline] fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { match self { Value::String(variant) => visitor.visit_enum(variant.into_deserializer()), _ => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"string only", )), } } // `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) } fn deserialize_newtype_struct( self, _name: &'static str, visitor: V, ) -> Result where V: de::Visitor<'de>, { visitor.visit_newtype_struct(self) } serde::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 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 = crate::de::Error; fn next_element_seed(&mut self, seed: T) -> Result, crate::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: Map) -> Self { MapDeserializer { iter: map.into_iter(), value: None, } } } impl<'de> de::MapAccess<'de> for MapDeserializer { type Error = crate::de::Error; fn next_key_seed(&mut self, seed: T) -> Result, crate::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, } } } impl<'de> de::IntoDeserializer<'de, crate::de::Error> for Value { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } struct Serializer; impl ser::Serializer for Serializer { type Ok = Value; type Error = crate::ser::Error; type SerializeSeq = SerializeVec; type SerializeTuple = SerializeVec; type SerializeTupleStruct = SerializeVec; type SerializeTupleVariant = SerializeVec; 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)) } 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(crate::ser::Error::UnsupportedType) } fn serialize_unit_struct(self, _name: &'static str) -> Result { Err(crate::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(crate::ser::Error::UnsupportedType) } fn serialize_none(self) -> Result { Err(crate::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 { self.serialize_seq(Some(len)) } fn serialize_tuple_struct( self, _name: &'static str, len: usize, ) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, len: usize, ) -> Result { self.serialize_seq(Some(len)) } fn serialize_map(self, _len: Option) -> Result { Ok(SerializeMap { map: Map::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(crate::ser::Error::UnsupportedType) } } struct SerializeVec { vec: Vec, } struct SerializeMap { map: Map, next_key: Option, } impl ser::SerializeSeq for SerializeVec { type Ok = Value; type Error = crate::ser::Error; fn serialize_element(&mut self, value: &T) -> Result<(), crate::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::SerializeTuple for SerializeVec { type Ok = Value; type Error = crate::ser::Error; fn serialize_element(&mut self, value: &T) -> Result<(), crate::ser::Error> where T: ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } impl ser::SerializeTupleStruct for SerializeVec { type Ok = Value; type Error = crate::ser::Error; fn serialize_field(&mut self, value: &T) -> Result<(), crate::ser::Error> where T: ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } impl ser::SerializeTupleVariant for SerializeVec { type Ok = Value; type Error = crate::ser::Error; fn serialize_field(&mut self, value: &T) -> Result<(), crate::ser::Error> where T: ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } impl ser::SerializeMap for SerializeMap { type Ok = Value; type Error = crate::ser::Error; fn serialize_key(&mut self, key: &T) -> Result<(), crate::ser::Error> where T: ser::Serialize, { match Value::try_from(key)? { Value::String(s) => self.next_key = Some(s), _ => return Err(crate::ser::Error::KeyNotString), }; Ok(()) } fn serialize_value(&mut self, value: &T) -> Result<(), crate::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(crate::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 = crate::ser::Error; fn serialize_field( &mut self, key: &'static str, value: &T, ) -> Result<(), crate::ser::Error> where T: ser::Serialize, { 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 == datetime::FIELD { Ok(true) } else { self.key.push_str(s); Ok(false) } } fn visit_string(self, s: String) -> Result where E: de::Error, { if s == datetime::FIELD { Ok(true) } else { *self.key = s; Ok(false) } } }