summaryrefslogtreecommitdiffstats
path: root/third_party/rust/toml/src
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/toml/src')
-rw-r--r--third_party/rust/toml/src/datetime.rs425
-rw-r--r--third_party/rust/toml/src/de.rs1327
-rw-r--r--third_party/rust/toml/src/lib.rs168
-rw-r--r--third_party/rust/toml/src/ser.rs1714
-rw-r--r--third_party/rust/toml/src/tokens.rs620
-rw-r--r--third_party/rust/toml/src/value.rs946
6 files changed, 5200 insertions, 0 deletions
diff --git a/third_party/rust/toml/src/datetime.rs b/third_party/rust/toml/src/datetime.rs
new file mode 100644
index 0000000000..83b5c0bb9c
--- /dev/null
+++ b/third_party/rust/toml/src/datetime.rs
@@ -0,0 +1,425 @@
+use std::fmt;
+use std::str::{self, FromStr};
+use std::error;
+
+use serde::{de, ser};
+
+/// A parsed TOML datetime value
+///
+/// This structure is intended to represent the datetime primitive type that can
+/// be encoded into TOML documents. This type is a parsed version that contains
+/// all metadata internally.
+///
+/// Currently this type is intentionally conservative and only supports
+/// `to_string` as an accessor. Over time though it's intended that it'll grow
+/// more support!
+///
+/// Note that if you're using `Deserialize` to deserialize a TOML document, you
+/// can use this as a placeholder for where you're expecting a datetime to be
+/// specified.
+///
+/// Also note though that while this type implements `Serialize` and
+/// `Deserialize` it's only recommended to use this type with the TOML format,
+/// otherwise encoded in other formats it may look a little odd.
+#[derive(PartialEq, Clone)]
+pub struct Datetime {
+ date: Option<Date>,
+ time: Option<Time>,
+ offset: Option<Offset>,
+}
+
+/// Error returned from parsing a `Datetime` in the `FromStr` implementation.
+#[derive(Debug, Clone)]
+pub struct DatetimeParseError {
+ _private: (),
+}
+
+// Currently serde itself doesn't have a datetime type, so we map our `Datetime`
+// to a special valid in the serde data model. Namely one with thiese special
+// fields/struct names.
+//
+// In general the TOML encoder/decoder will catch this and not literally emit
+// these strings but rather emit datetimes as they're intended.
+pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$__toml_private_datetime";
+pub const SERDE_STRUCT_NAME: &'static str = "$__toml_private_Datetime";
+
+#[derive(PartialEq, Clone)]
+struct Date {
+ year: u16,
+ month: u8,
+ day: u8,
+}
+
+#[derive(PartialEq, Clone)]
+struct Time {
+ hour: u8,
+ minute: u8,
+ second: u8,
+ nanosecond: u32,
+}
+
+#[derive(PartialEq, Clone)]
+enum Offset {
+ Z,
+ Custom { hours: i8, minutes: u8 },
+}
+
+impl fmt::Debug for Datetime {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, f)
+ }
+}
+
+impl fmt::Display for Datetime {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if let Some(ref date) = self.date {
+ write!(f, "{}", date)?;
+ }
+ if let Some(ref time) = self.time {
+ if self.date.is_some() {
+ write!(f, "T")?;
+ }
+ write!(f, "{}", time)?;
+ }
+ if let Some(ref offset) = self.offset {
+ write!(f, "{}", offset)?;
+ }
+ Ok(())
+ }
+}
+
+impl fmt::Display for Date {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:04}-{:02}-{:02}", self.year, self.month, self.day)
+ }
+}
+
+impl fmt::Display for Time {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)?;
+ if self.nanosecond != 0 {
+ let s = format!("{:09}", self.nanosecond);
+ write!(f, ".{}", s.trim_right_matches('0'))?;
+ }
+ Ok(())
+ }
+}
+
+impl fmt::Display for Offset {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Offset::Z => write!(f, "Z"),
+ Offset::Custom { hours, minutes } => {
+ write!(f, "{:+03}:{:02}", hours, minutes)
+ }
+ }
+ }
+}
+
+impl FromStr for Datetime {
+ type Err = DatetimeParseError;
+
+ fn from_str(date: &str) -> Result<Datetime, DatetimeParseError> {
+ // Accepted formats:
+ //
+ // 0000-00-00T00:00:00.00Z
+ // 0000-00-00T00:00:00.00
+ // 0000-00-00
+ // 00:00:00.00
+ if date.len() < 3 {
+ return Err(DatetimeParseError { _private: () })
+ }
+ let mut offset_allowed = true;
+ let mut chars = date.chars();
+
+ // First up, parse the full date if we can
+ let full_date = if chars.clone().nth(2) == Some(':') {
+ offset_allowed = false;
+ None
+ } else {
+ let y1 = digit(&mut chars)? as u16;
+ let y2 = digit(&mut chars)? as u16;
+ let y3 = digit(&mut chars)? as u16;
+ let y4 = digit(&mut chars)? as u16;
+
+ match chars.next() {
+ Some('-') => {}
+ _ => return Err(DatetimeParseError { _private: () }),
+ }
+
+ let m1 = digit(&mut chars)?;
+ let m2 = digit(&mut chars)?;
+
+ match chars.next() {
+ Some('-') => {}
+ _ => return Err(DatetimeParseError { _private: () }),
+ }
+
+ let d1 = digit(&mut chars)?;
+ let d2 = digit(&mut chars)?;
+
+ let date = Date {
+ year: y1 * 1000 + y2 * 100 + y3 * 10 + y4,
+ month: m1 * 10 + m2,
+ day: d1 * 10 + d2,
+ };
+
+ if date.month < 1 || date.month > 12 {
+ return Err(DatetimeParseError { _private: () })
+ }
+ if date.day < 1 || date.day > 31 {
+ return Err(DatetimeParseError { _private: () })
+ }
+
+ Some(date)
+ };
+
+ // Next parse the "partial-time" if available
+ let partial_time = if full_date.is_some() &&
+ chars.clone().next() == Some('T') {
+ chars.next();
+ true
+ } else {
+ full_date.is_none()
+ };
+
+ let time = if partial_time {
+ let h1 = digit(&mut chars)?;
+ let h2 = digit(&mut chars)?;
+ match chars.next() {
+ Some(':') => {}
+ _ => return Err(DatetimeParseError { _private: () }),
+ }
+ let m1 = digit(&mut chars)?;
+ let m2 = digit(&mut chars)?;
+ match chars.next() {
+ Some(':') => {}
+ _ => return Err(DatetimeParseError { _private: () }),
+ }
+ let s1 = digit(&mut chars)?;
+ let s2 = digit(&mut chars)?;
+
+ let mut nanosecond = 0;
+ if chars.clone().next() == Some('.') {
+ chars.next();
+ let whole = chars.as_str();
+
+ let mut end = whole.len();
+ for (i, byte) in whole.bytes().enumerate() {
+ match byte {
+ b'0' ... b'9' => {
+ if i < 9 {
+ let p = 10_u32.pow(8 - i as u32);
+ nanosecond += p * (byte - b'0') as u32;
+ }
+ }
+ _ => {
+ end = i;
+ break;
+ }
+ }
+ }
+ if end == 0 {
+ return Err(DatetimeParseError { _private: () })
+ }
+ chars = whole[end..].chars();
+ }
+
+ let time = Time {
+ hour: h1 * 10 + h2,
+ minute: m1 * 10 + m2,
+ second: s1 * 10 + s2,
+ nanosecond: nanosecond,
+ };
+
+ if time.hour > 24 {
+ return Err(DatetimeParseError { _private: () })
+ }
+ if time.minute > 59 {
+ return Err(DatetimeParseError { _private: () })
+ }
+ if time.second > 59 {
+ return Err(DatetimeParseError { _private: () })
+ }
+ if time.nanosecond > 999_999_999 {
+ return Err(DatetimeParseError { _private: () })
+ }
+
+ Some(time)
+ } else {
+ offset_allowed = false;
+ None
+ };
+
+ // And finally, parse the offset
+ let offset = if offset_allowed {
+ let next = chars.clone().next();
+ if next == Some('Z') {
+ chars.next();
+ Some(Offset::Z)
+ } else if next.is_none() {
+ None
+ } else {
+ let sign = match next {
+ Some('+') => 1,
+ Some('-') => -1,
+ _ => return Err(DatetimeParseError { _private: () }),
+ };
+ chars.next();
+ let h1 = digit(&mut chars)? as i8;
+ let h2 = digit(&mut chars)? as i8;
+ match chars.next() {
+ Some(':') => {}
+ _ => return Err(DatetimeParseError { _private: () }),
+ }
+ let m1 = digit(&mut chars)?;
+ let m2 = digit(&mut chars)?;
+
+ Some(Offset::Custom {
+ hours: sign * (h1 * 10 + h2),
+ minutes: m1 * 10 + m2,
+ })
+ }
+ } else {
+ None
+ };
+
+ // Return an error if we didn't hit eof, otherwise return our parsed
+ // date
+ if chars.next().is_some() {
+ return Err(DatetimeParseError { _private: () })
+ }
+
+ Ok(Datetime {
+ date: full_date,
+ time: time,
+ offset: offset,
+ })
+ }
+}
+
+fn digit(chars: &mut str::Chars) -> Result<u8, DatetimeParseError> {
+ match chars.next() {
+ Some(c) if '0' <= c && c <= '9' => Ok(c as u8 - b'0'),
+ _ => Err(DatetimeParseError { _private: () }),
+ }
+}
+
+impl ser::Serialize for Datetime {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where S: ser::Serializer
+ {
+ use serde::ser::SerializeStruct;
+
+ let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?;
+ s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.to_string())?;
+ s.end()
+ }
+}
+
+impl<'de> de::Deserialize<'de> for Datetime {
+ fn deserialize<D>(deserializer: D) -> Result<Datetime, D::Error>
+ where D: de::Deserializer<'de>
+ {
+ struct DatetimeVisitor;
+
+ impl<'de> de::Visitor<'de> for DatetimeVisitor {
+ type Value = Datetime;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("a TOML datetime")
+ }
+
+ fn visit_map<V>(self, mut visitor: V) -> Result<Datetime, V::Error>
+ where V: de::MapAccess<'de>
+ {
+ let value = visitor.next_key::<DatetimeKey>()?;
+ if value.is_none() {
+ return Err(de::Error::custom("datetime key not found"))
+ }
+ let v: DatetimeFromString = visitor.next_value()?;
+ Ok(v.value)
+
+ }
+ }
+
+ static FIELDS: [&'static str; 1] = [SERDE_STRUCT_FIELD_NAME];
+ deserializer.deserialize_struct(SERDE_STRUCT_NAME,
+ &FIELDS,
+ DatetimeVisitor)
+ }
+}
+
+struct DatetimeKey;
+
+impl<'de> de::Deserialize<'de> for DatetimeKey {
+ fn deserialize<D>(deserializer: D) -> Result<DatetimeKey, D::Error>
+ where D: de::Deserializer<'de>
+ {
+ struct FieldVisitor;
+
+ impl<'de> de::Visitor<'de> for FieldVisitor {
+ type Value = ();
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("a valid datetime field")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<(), E>
+ where E: de::Error
+ {
+ if s == SERDE_STRUCT_FIELD_NAME {
+ Ok(())
+ } else {
+ Err(de::Error::custom("expected field with custom name"))
+ }
+ }
+ }
+
+ deserializer.deserialize_identifier(FieldVisitor)?;
+ Ok(DatetimeKey)
+ }
+}
+
+pub struct DatetimeFromString {
+ pub value: Datetime,
+}
+
+impl<'de> de::Deserialize<'de> for DatetimeFromString {
+ fn deserialize<D>(deserializer: D) -> Result<DatetimeFromString, D::Error>
+ where D: de::Deserializer<'de>
+ {
+ struct Visitor;
+
+ impl<'de> de::Visitor<'de> for Visitor {
+ type Value = DatetimeFromString;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("string containing a datetime")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<DatetimeFromString, E>
+ where E: de::Error,
+ {
+ match s.parse() {
+ Ok(date) => Ok(DatetimeFromString { value: date }),
+ Err(e) => Err(de::Error::custom(e)),
+ }
+ }
+ }
+
+ deserializer.deserialize_str(Visitor)
+ }
+}
+
+impl fmt::Display for DatetimeParseError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ "failed to parse datetime".fmt(f)
+ }
+}
+
+impl error::Error for DatetimeParseError {
+ fn description(&self) -> &str {
+ "failed to parse datetime"
+ }
+}
diff --git a/third_party/rust/toml/src/de.rs b/third_party/rust/toml/src/de.rs
new file mode 100644
index 0000000000..9ff09f7b51
--- /dev/null
+++ b/third_party/rust/toml/src/de.rs
@@ -0,0 +1,1327 @@
+//! Deserializing TOML into Rust structures.
+//!
+//! This module contains all the Serde support for deserializing TOML documents
+//! into Rust structures. Note that some top-level functions here are also
+//! provided at the top of the crate.
+
+use std::borrow::Cow;
+use std::error;
+use std::fmt;
+use std::str;
+use std::vec;
+
+use serde::de;
+use serde::de::IntoDeserializer;
+
+use tokens::{Tokenizer, Token, Error as TokenError};
+use datetime::{SERDE_STRUCT_FIELD_NAME, SERDE_STRUCT_NAME};
+
+/// Deserializes a byte slice into a type.
+///
+/// This function will attempt to interpret `bytes` as UTF-8 data and then
+/// deserialize `T` from the TOML document provided.
+pub fn from_slice<'de, T>(bytes: &'de [u8]) -> Result<T, Error>
+ where T: de::Deserialize<'de>,
+{
+ match str::from_utf8(bytes) {
+ Ok(s) => from_str(s),
+ Err(e) => Err(Error::custom(e.to_string())),
+ }
+}
+
+/// Deserializes a string into a type.
+///
+/// This function will attempt to interpret `s` as a TOML document and
+/// deserialize `T` from the document.
+///
+/// # Examples
+///
+/// ```
+/// #[macro_use]
+/// extern crate serde_derive;
+/// extern crate toml;
+///
+/// #[derive(Deserialize)]
+/// struct Config {
+/// title: String,
+/// owner: Owner,
+/// }
+///
+/// #[derive(Deserialize)]
+/// struct Owner {
+/// name: String,
+/// }
+///
+/// fn main() {
+/// let config: Config = toml::from_str(r#"
+/// title = 'TOML Example'
+///
+/// [owner]
+/// name = 'Lisa'
+/// "#).unwrap();
+///
+/// assert_eq!(config.title, "TOML Example");
+/// assert_eq!(config.owner.name, "Lisa");
+/// }
+/// ```
+pub fn from_str<'de, T>(s: &'de str) -> Result<T, Error>
+ where T: de::Deserialize<'de>,
+{
+ let mut d = Deserializer::new(s);
+ let ret = T::deserialize(&mut d)?;
+ d.end()?;
+ Ok(ret)
+}
+
+/// Errors that can occur when deserializing a type.
+#[derive(Debug, Clone)]
+pub struct Error {
+ inner: Box<ErrorInner>,
+}
+
+#[derive(Debug, Clone)]
+struct ErrorInner {
+ kind: ErrorKind,
+ line: Option<usize>,
+ col: usize,
+ message: String,
+ key: Vec<String>,
+}
+
+/// Errors that can occur when deserializing a type.
+#[derive(Debug, Clone)]
+enum ErrorKind {
+ /// EOF was reached when looking for a value
+ UnexpectedEof,
+
+ /// An invalid character not allowed in a string was found
+ InvalidCharInString(char),
+
+ /// An invalid character was found as an escape
+ InvalidEscape(char),
+
+ /// An invalid character was found in a hex escape
+ InvalidHexEscape(char),
+
+ /// An invalid escape value was specified in a hex escape in a string.
+ ///
+ /// Valid values are in the plane of unicode codepoints.
+ InvalidEscapeValue(u32),
+
+ /// A newline in a string was encountered when one was not allowed.
+ NewlineInString,
+
+ /// An unexpected character was encountered, typically when looking for a
+ /// value.
+ Unexpected(char),
+
+ /// An unterminated string was found where EOF was found before the ending
+ /// EOF mark.
+ UnterminatedString,
+
+ /// A newline was found in a table key.
+ NewlineInTableKey,
+
+ /// A number failed to parse
+ NumberInvalid,
+
+ /// A date or datetime was invalid
+ DateInvalid,
+
+ /// Wanted one sort of token, but found another.
+ Wanted {
+ /// Expected token type
+ expected: &'static str,
+ /// Actually found token type
+ found: &'static str,
+ },
+
+ /// An array was decoded but the types inside of it were mixed, which is
+ /// disallowed by TOML.
+ MixedArrayType,
+
+ /// A duplicate table definition was found.
+ DuplicateTable(String),
+
+ /// A previously defined table was redefined as an array.
+ RedefineAsArray,
+
+ /// An empty table key was found.
+ EmptyTableKey,
+
+ /// A custom error which could be generated when deserializing a particular
+ /// type.
+ Custom,
+
+ /// A struct was expected but something else was found
+ ExpectedString,
+
+ #[doc(hidden)]
+ __Nonexhaustive,
+}
+
+/// Deserialization implementation for TOML.
+pub struct Deserializer<'a> {
+ require_newline_after_table: bool,
+ input: &'a str,
+ tokens: Tokenizer<'a>,
+}
+
+impl<'de, 'b> de::Deserializer<'de> for &'b mut Deserializer<'de> {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ let mut tables = Vec::new();
+ let mut cur_table = Table {
+ at: 0,
+ header: Vec::new(),
+ values: None,
+ array: false,
+ };
+
+ while let Some(line) = self.line()? {
+ match line {
+ Line::Table { at, mut header, array } => {
+ if !cur_table.header.is_empty() || cur_table.values.is_some() {
+ tables.push(cur_table);
+ }
+ cur_table = Table {
+ at: at,
+ header: Vec::new(),
+ values: Some(Vec::new()),
+ array: array,
+ };
+ loop {
+ let part = header.next().map_err(|e| {
+ self.token_error(e)
+ });
+ match part? {
+ Some(part) => cur_table.header.push(part),
+ None => break,
+ }
+ }
+ }
+ Line::KeyValue(key, value) => {
+ if cur_table.values.is_none() {
+ cur_table.values = Some(Vec::new());
+ }
+ cur_table.values.as_mut().unwrap().push((key, value));
+ }
+ }
+ }
+ if !cur_table.header.is_empty() || cur_table.values.is_some() {
+ tables.push(cur_table);
+ }
+
+ visitor.visit_map(MapVisitor {
+ values: Vec::new().into_iter(),
+ next_value: None,
+ depth: 0,
+ cur: 0,
+ cur_parent: 0,
+ max: tables.len(),
+ tables: &mut tables,
+ array: false,
+ de: self,
+ })
+ }
+
+ fn deserialize_enum<V>(
+ self,
+ _name: &'static str,
+ _variants: &'static [&'static str],
+ visitor: V
+ ) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>
+ {
+ if let Some(next) = self.next()? {
+ match next {
+ Token::String { val, .. } => {
+ visitor.visit_enum(val.into_deserializer())
+ },
+ _ => Err(Error::from_kind(ErrorKind::ExpectedString))
+ }
+ } else {
+ Err(Error::from_kind(ErrorKind::UnexpectedEof))
+ }
+ }
+
+ forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map struct unit newtype_struct
+ ignored_any unit_struct tuple_struct tuple option identifier
+ }
+}
+
+struct Table<'a> {
+ at: usize,
+ header: Vec<Cow<'a, str>>,
+ values: Option<Vec<(Cow<'a, str>, Value<'a>)>>,
+ array: bool,
+}
+
+#[doc(hidden)]
+pub struct MapVisitor<'de: 'b, 'b> {
+ values: vec::IntoIter<(Cow<'de, str>, Value<'de>)>,
+ next_value: Option<(Cow<'de, str>, Value<'de>)>,
+ depth: usize,
+ cur: usize,
+ cur_parent: usize,
+ max: usize,
+ tables: &'b mut [Table<'de>],
+ array: bool,
+ de: &'b mut Deserializer<'de>,
+}
+
+impl<'de, 'b> de::MapAccess<'de> for MapVisitor<'de, 'b> {
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
+ where K: de::DeserializeSeed<'de>,
+ {
+ if self.cur_parent == self.max || self.cur == self.max {
+ return Ok(None)
+ }
+
+ loop {
+ assert!(self.next_value.is_none());
+ if let Some((key, value)) = self.values.next() {
+ let ret = seed.deserialize(StrDeserializer::new(key.clone()))?;
+ self.next_value = Some((key, value));
+ return Ok(Some(ret))
+ }
+
+ let next_table = {
+ let prefix = &self.tables[self.cur_parent].header[..self.depth];
+ self.tables[self.cur..self.max].iter().enumerate().find(|&(_, t)| {
+ if t.values.is_none() {
+ return false
+ }
+ match t.header.get(..self.depth) {
+ Some(header) => header == prefix,
+ None => false,
+ }
+ }).map(|(i, _)| i + self.cur)
+ };
+
+ let pos = match next_table {
+ Some(pos) => pos,
+ None => return Ok(None),
+ };
+ self.cur = pos;
+
+ // Test to see if we're duplicating our parent's table, and if so
+ // then this is an error in the toml format
+ if self.cur_parent != pos &&
+ self.tables[self.cur_parent].header == self.tables[pos].header {
+ let at = self.tables[pos].at;
+ let name = self.tables[pos].header.join(".");
+ return Err(self.de.error(at, ErrorKind::DuplicateTable(name)))
+ }
+
+ let table = &mut self.tables[pos];
+
+ // If we're not yet at the appropriate depth for this table then we
+ // just next the next portion of its header and then continue
+ // decoding.
+ if self.depth != table.header.len() {
+ let key = &table.header[self.depth];
+ let key = seed.deserialize(StrDeserializer::new(key.clone()))?;
+ return Ok(Some(key))
+ }
+
+ // Rule out cases like:
+ //
+ // [[foo.bar]]
+ // [[foo]]
+ if table.array {
+ let kind = ErrorKind::RedefineAsArray;
+ return Err(self.de.error(table.at, kind))
+ }
+
+ self.values = table.values.take().expect("Unable to read table values").into_iter();
+ }
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
+ where V: de::DeserializeSeed<'de>,
+ {
+ if let Some((k, v)) = self.next_value.take() {
+ match seed.deserialize(ValueDeserializer::new(v)) {
+ Ok(v) => return Ok(v),
+ Err(mut e) => {
+ e.add_key_context(&k);
+ return Err(e)
+ }
+ }
+ }
+
+ let array = self.tables[self.cur].array &&
+ self.depth == self.tables[self.cur].header.len() - 1;
+ self.cur += 1;
+ let res = seed.deserialize(MapVisitor {
+ values: Vec::new().into_iter(),
+ next_value: None,
+ depth: self.depth + if array {0} else {1},
+ cur_parent: self.cur - 1,
+ cur: 0,
+ max: self.max,
+ array: array,
+ tables: &mut *self.tables,
+ de: &mut *self.de,
+ });
+ res.map_err(|mut e| {
+ e.add_key_context(&self.tables[self.cur - 1].header[self.depth]);
+ e
+ })
+ }
+}
+
+impl<'de, 'b> de::SeqAccess<'de> for MapVisitor<'de, 'b> {
+ type Error = Error;
+
+ fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
+ where K: de::DeserializeSeed<'de>,
+ {
+ assert!(self.next_value.is_none());
+ assert!(self.values.next().is_none());
+
+ if self.cur_parent == self.max {
+ return Ok(None)
+ }
+
+ let next = self.tables[..self.max]
+ .iter()
+ .enumerate()
+ .skip(self.cur_parent + 1)
+ .find(|&(_, table)| {
+ table.array && table.header == self.tables[self.cur_parent].header
+ }).map(|p| p.0)
+ .unwrap_or(self.max);
+
+ let ret = seed.deserialize(MapVisitor {
+ values: self.tables[self.cur_parent].values.take().expect("Unable to read table values").into_iter(),
+ next_value: None,
+ depth: self.depth + 1,
+ cur_parent: self.cur_parent,
+ max: next,
+ cur: 0,
+ array: false,
+ tables: &mut self.tables,
+ de: &mut self.de,
+ })?;
+ self.cur_parent = next;
+ Ok(Some(ret))
+ }
+}
+
+impl<'de, 'b> de::Deserializer<'de> for MapVisitor<'de, 'b> {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ if self.array {
+ visitor.visit_seq(self)
+ } else {
+ visitor.visit_map(self)
+ }
+ }
+
+ // `None` is interpreted as a missing field so be sure to implement `Some`
+ // as a present field.
+ fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ visitor.visit_some(self)
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ _name: &'static str,
+ visitor: V
+ ) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>
+ {
+ visitor.visit_newtype_struct(self)
+ }
+
+ forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map struct unit identifier
+ ignored_any unit_struct tuple_struct tuple enum
+ }
+}
+
+struct StrDeserializer<'a> {
+ key: Cow<'a, str>,
+}
+
+impl<'a> StrDeserializer<'a> {
+ fn new(key: Cow<'a, str>) -> StrDeserializer<'a> {
+ StrDeserializer {
+ key: key,
+ }
+ }
+}
+
+impl<'de> de::Deserializer<'de> for StrDeserializer<'de> {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ match self.key {
+ Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
+ Cow::Owned(s) => visitor.visit_string(s),
+ }
+ }
+
+ forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map struct option unit newtype_struct
+ ignored_any unit_struct tuple_struct tuple enum identifier
+ }
+}
+
+struct ValueDeserializer<'a> {
+ value: Value<'a>,
+}
+
+impl<'a> ValueDeserializer<'a> {
+ fn new(value: Value<'a>) -> ValueDeserializer<'a> {
+ ValueDeserializer {
+ value: value,
+ }
+ }
+}
+
+impl<'de> de::Deserializer<'de> for ValueDeserializer<'de> {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ match self.value {
+ Value::Integer(i) => visitor.visit_i64(i),
+ Value::Boolean(b) => visitor.visit_bool(b),
+ Value::Float(f) => visitor.visit_f64(f),
+ Value::String(Cow::Borrowed(s)) => visitor.visit_borrowed_str(s),
+ Value::String(Cow::Owned(s)) => visitor.visit_string(s),
+ Value::Datetime(s) => visitor.visit_map(DatetimeDeserializer {
+ date: s,
+ visited: false,
+ }),
+ Value::Array(values) => {
+ let mut s = de::value::SeqDeserializer::new(values.into_iter());
+ let ret = visitor.visit_seq(&mut s)?;
+ s.end()?;
+ Ok(ret)
+ }
+ Value::InlineTable(values) => {
+ visitor.visit_map(InlineTableDeserializer {
+ values: values.into_iter(),
+ next_value: None,
+ })
+ }
+ }
+ }
+
+ fn deserialize_struct<V>(self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ if name == SERDE_STRUCT_NAME && fields == &[SERDE_STRUCT_FIELD_NAME] {
+ if let Value::Datetime(s) = self.value {
+ return visitor.visit_map(DatetimeDeserializer {
+ date: s,
+ visited: false,
+ })
+ }
+ }
+
+ self.deserialize_any(visitor)
+ }
+
+ // `None` is interpreted as a missing field so be sure to implement `Some`
+ // as a present field.
+ fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ visitor.visit_some(self)
+ }
+
+ fn deserialize_enum<V>(
+ self,
+ _name: &'static str,
+ _variants: &'static [&'static str],
+ visitor: V
+ ) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>
+ {
+ match self.value {
+ Value::String(val) => visitor.visit_enum(val.into_deserializer()),
+ _ => Err(Error::from_kind(ErrorKind::ExpectedString))
+ }
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ _name: &'static str,
+ visitor: V
+ ) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>
+ {
+ visitor.visit_newtype_struct(self)
+ }
+
+ forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map unit identifier
+ ignored_any unit_struct tuple_struct tuple
+ }
+}
+
+impl<'de> de::IntoDeserializer<'de, Error> for Value<'de> {
+ type Deserializer = ValueDeserializer<'de>;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ ValueDeserializer::new(self)
+ }
+}
+
+struct DatetimeDeserializer<'a> {
+ visited: bool,
+ date: &'a str,
+}
+
+impl<'de> de::MapAccess<'de> for DatetimeDeserializer<'de> {
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
+ where K: de::DeserializeSeed<'de>,
+ {
+ if self.visited {
+ return Ok(None)
+ }
+ self.visited = true;
+ seed.deserialize(DatetimeFieldDeserializer).map(Some)
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
+ where V: de::DeserializeSeed<'de>,
+ {
+ seed.deserialize(StrDeserializer::new(self.date.into()))
+ }
+}
+
+struct DatetimeFieldDeserializer;
+
+impl<'de> de::Deserializer<'de> for DatetimeFieldDeserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where V: de::Visitor<'de>,
+ {
+ visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME)
+ }
+
+ forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map struct option unit newtype_struct
+ ignored_any unit_struct tuple_struct tuple enum identifier
+ }
+}
+
+struct InlineTableDeserializer<'a> {
+ values: vec::IntoIter<(Cow<'a, str>, Value<'a>)>,
+ next_value: Option<Value<'a>>,
+}
+
+impl<'de> de::MapAccess<'de> for InlineTableDeserializer<'de> {
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
+ where K: de::DeserializeSeed<'de>,
+ {
+ let (key, value) = match self.values.next() {
+ Some(pair) => pair,
+ None => return Ok(None),
+ };
+ self.next_value = Some(value);
+ seed.deserialize(StrDeserializer::new(key)).map(Some)
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
+ where V: de::DeserializeSeed<'de>,
+ {
+ let value = self.next_value.take().expect("Unable to read table values");
+ seed.deserialize(ValueDeserializer::new(value))
+ }
+}
+
+
+impl<'a> Deserializer<'a> {
+ /// Creates a new deserializer which will be deserializing the string
+ /// provided.
+ pub fn new(input: &'a str) -> Deserializer<'a> {
+ Deserializer {
+ tokens: Tokenizer::new(input),
+ input: input,
+ require_newline_after_table: true,
+ }
+ }
+
+ /// The `Deserializer::end` method should be called after a value has been
+ /// fully deserialized. This allows the `Deserializer` to validate that the
+ /// input stream is at the end or that it only has trailing
+ /// whitespace/comments.
+ pub fn end(&mut self) -> Result<(), Error> {
+ Ok(())
+ }
+
+ /// Historical versions of toml-rs accidentally allowed a newline after a
+ /// table definition, but the TOML spec requires a newline after a table
+ /// definition header.
+ ///
+ /// This option can be set to `false` (the default is `true`) to emulate
+ /// this behavior for backwards compatibility with older toml-rs versions.
+ pub fn set_require_newline_after_table(&mut self, require: bool) {
+ self.require_newline_after_table = require;
+ }
+
+ fn line(&mut self) -> Result<Option<Line<'a>>, Error> {
+ loop {
+ self.eat_whitespace()?;
+ if self.eat_comment()? {
+ continue
+ }
+ if self.eat(Token::Newline)? {
+ continue
+ }
+ break
+ }
+
+ match self.peek()? {
+ Some(Token::LeftBracket) => self.table_header().map(Some),
+ Some(_) => self.key_value().map(Some),
+ None => Ok(None),
+ }
+ }
+
+ fn table_header(&mut self) -> Result<Line<'a>, Error> {
+ let start = self.tokens.current();
+ self.expect(Token::LeftBracket)?;
+ let array = self.eat(Token::LeftBracket)?;
+ let ret = Header::new(self.tokens.clone(),
+ array,
+ self.require_newline_after_table);
+ if self.require_newline_after_table {
+ self.tokens.skip_to_newline();
+ } else {
+ loop {
+ match self.next()? {
+ Some(Token::RightBracket) => {
+ if array {
+ self.eat(Token::RightBracket)?;
+ }
+ break
+ }
+ Some(Token::Newline) |
+ None => break,
+ _ => {}
+ }
+ }
+ self.eat_whitespace()?;
+ }
+ Ok(Line::Table { at: start, header: ret, array: array })
+ }
+
+ fn key_value(&mut self) -> Result<Line<'a>, Error> {
+ let key = self.table_key()?;
+ self.eat_whitespace()?;
+ self.expect(Token::Equals)?;
+ self.eat_whitespace()?;
+
+ let value = self.value()?;
+ self.eat_whitespace()?;
+ if !self.eat_comment()? {
+ self.eat_newline_or_eof()?;
+ }
+
+ Ok(Line::KeyValue(key, value))
+ }
+
+ fn value(&mut self) -> Result<Value<'a>, Error> {
+ let at = self.tokens.current();
+ let value = match self.next()? {
+ Some(Token::String { val, .. }) => Value::String(val),
+ Some(Token::Keylike("true")) => Value::Boolean(true),
+ Some(Token::Keylike("false")) => Value::Boolean(false),
+ Some(Token::Keylike(key)) => self.number_or_date(key)?,
+ Some(Token::Plus) => self.number_leading_plus()?,
+ Some(Token::LeftBrace) => self.inline_table().map(Value::InlineTable)?,
+ Some(Token::LeftBracket) => self.array().map(Value::Array)?,
+ Some(token) => {
+ return Err(self.error(at, ErrorKind::Wanted {
+ expected: "a value",
+ found: token.describe(),
+ }))
+ }
+ None => return Err(self.eof()),
+ };
+ Ok(value)
+ }
+
+ fn number_or_date(&mut self, s: &'a str) -> Result<Value<'a>, Error> {
+ if s.contains('T') || (s.len() > 1 && s[1..].contains('-')) &&
+ !s.contains("e-") {
+ self.datetime(s, false).map(Value::Datetime)
+ } else if self.eat(Token::Colon)? {
+ self.datetime(s, true).map(Value::Datetime)
+ } else {
+ self.number(s)
+ }
+ }
+
+ fn number(&mut self, s: &'a str) -> Result<Value<'a>, Error> {
+ if s.contains('e') || s.contains('E') {
+ self.float(s, None).map(Value::Float)
+ } else if self.eat(Token::Period)? {
+ let at = self.tokens.current();
+ match self.next()? {
+ Some(Token::Keylike(after)) => {
+ self.float(s, Some(after)).map(Value::Float)
+ }
+ _ => Err(self.error(at, ErrorKind::NumberInvalid)),
+ }
+ } else {
+ self.integer(s).map(Value::Integer)
+ }
+ }
+
+ fn number_leading_plus(&mut self) -> Result<Value<'a>, Error> {
+ let start = self.tokens.current();
+ match self.next()? {
+ Some(Token::Keylike(s)) => self.number(s),
+ _ => Err(self.error(start, ErrorKind::NumberInvalid)),
+ }
+ }
+
+ fn integer(&self, s: &'a str) -> Result<i64, Error> {
+ let (prefix, suffix) = self.parse_integer(s, true, false)?;
+ let start = self.tokens.substr_offset(s);
+ if suffix != "" {
+ return Err(self.error(start, ErrorKind::NumberInvalid))
+ }
+ prefix.replace("_", "").trim_left_matches('+').parse().map_err(|_e| {
+ self.error(start, ErrorKind::NumberInvalid)
+ })
+ }
+
+ fn parse_integer(&self,
+ s: &'a str,
+ allow_sign: bool,
+ allow_leading_zeros: bool)
+ -> Result<(&'a str, &'a str), Error> {
+ let start = self.tokens.substr_offset(s);
+
+ let mut first = true;
+ let mut first_zero = false;
+ let mut underscore = false;
+ let mut end = s.len();
+ for (i, c) in s.char_indices() {
+ let at = i + start;
+ if i == 0 && (c == '+' || c == '-') && allow_sign {
+ continue
+ }
+
+ match c {
+ '0' if first => first_zero = true,
+ '0' ... '9' if !first && first_zero && !allow_leading_zeros => {
+ return Err(self.error(at, ErrorKind::NumberInvalid))
+ }
+ '0' ... '9' => underscore = false,
+ '_' if first => {
+ return Err(self.error(at, ErrorKind::NumberInvalid))
+ }
+ '_' if !underscore => underscore = true,
+ _ => {
+ end = i;
+ break
+ }
+
+ }
+ first = false;
+ }
+ if first || underscore {
+ return Err(self.error(start, ErrorKind::NumberInvalid))
+ }
+ Ok((&s[..end], &s[end..]))
+ }
+
+ fn float(&mut self, s: &'a str, after_decimal: Option<&'a str>)
+ -> Result<f64, Error> {
+ let (integral, mut suffix) = self.parse_integer(s, true, false)?;
+ let start = self.tokens.substr_offset(integral);
+
+ let mut fraction = None;
+ if let Some(after) = after_decimal {
+ if suffix != "" {
+ return Err(self.error(start, ErrorKind::NumberInvalid))
+ }
+ let (a, b) = self.parse_integer(after, false, true)?;
+ fraction = Some(a);
+ suffix = b;
+ }
+
+ let mut exponent = None;
+ if suffix.starts_with('e') || suffix.starts_with('E') {
+ let (a, b) = if suffix.len() == 1 {
+ self.eat(Token::Plus)?;
+ match self.next()? {
+ Some(Token::Keylike(s)) => {
+ self.parse_integer(s, false, false)?
+ }
+ _ => return Err(self.error(start, ErrorKind::NumberInvalid)),
+ }
+ } else {
+ self.parse_integer(&suffix[1..], true, false)?
+ };
+ if b != "" {
+ return Err(self.error(start, ErrorKind::NumberInvalid))
+ }
+ exponent = Some(a);
+ }
+
+ let mut number = integral.trim_left_matches('+')
+ .chars()
+ .filter(|c| *c != '_')
+ .collect::<String>();
+ if let Some(fraction) = fraction {
+ number.push_str(".");
+ number.extend(fraction.chars().filter(|c| *c != '_'));
+ }
+ if let Some(exponent) = exponent {
+ number.push_str("E");
+ number.extend(exponent.chars().filter(|c| *c != '_'));
+ }
+ number.parse().map_err(|_e| {
+ self.error(start, ErrorKind::NumberInvalid)
+ }).and_then(|n: f64| {
+ if n.is_finite() {
+ Ok(n)
+ } else {
+ Err(self.error(start, ErrorKind::NumberInvalid))
+ }
+ })
+ }
+
+ fn datetime(&mut self, date: &'a str, colon_eaten: bool)
+ -> Result<&'a str, Error> {
+ let start = self.tokens.substr_offset(date);
+ if colon_eaten || self.eat(Token::Colon)? {
+ // minutes
+ match self.next()? {
+ Some(Token::Keylike(_)) => {}
+ _ => return Err(self.error(start, ErrorKind::DateInvalid)),
+ }
+ // Seconds
+ self.expect(Token::Colon)?;
+ match self.next()? {
+ Some(Token::Keylike(_)) => {}
+ _ => return Err(self.error(start, ErrorKind::DateInvalid)),
+ }
+ // Fractional seconds
+ if self.eat(Token::Period)? {
+ match self.next()? {
+ Some(Token::Keylike(_)) => {}
+ _ => return Err(self.error(start, ErrorKind::DateInvalid)),
+ }
+ }
+
+ // offset
+ if self.eat(Token::Plus)? {
+ match self.next()? {
+ Some(Token::Keylike(_)) => {}
+ _ => return Err(self.error(start, ErrorKind::DateInvalid)),
+ }
+ }
+ if self.eat(Token::Colon)? {
+ match self.next()? {
+ Some(Token::Keylike(_)) => {}
+ _ => return Err(self.error(start, ErrorKind::DateInvalid)),
+ }
+ }
+ }
+ let end = self.tokens.current();
+ Ok(&self.tokens.input()[start..end])
+ }
+
+ // TODO(#140): shouldn't buffer up this entire table in memory, it'd be
+ // great to defer parsing everything until later.
+ fn inline_table(&mut self) -> Result<Vec<(Cow<'a, str>, Value<'a>)>, Error> {
+ let mut ret = Vec::new();
+ self.eat_whitespace()?;
+ if self.eat(Token::RightBrace)? {
+ return Ok(ret)
+ }
+ loop {
+ let key = self.table_key()?;
+ self.eat_whitespace()?;
+ self.expect(Token::Equals)?;
+ self.eat_whitespace()?;
+ ret.push((key, self.value()?));
+
+ self.eat_whitespace()?;
+ if self.eat(Token::RightBrace)? {
+ return Ok(ret)
+ }
+ self.expect(Token::Comma)?;
+ self.eat_whitespace()?;
+ }
+ }
+
+ // TODO(#140): shouldn't buffer up this entire array in memory, it'd be
+ // great to defer parsing everything until later.
+ fn array(&mut self) -> Result<Vec<Value<'a>>, Error> {
+ let mut ret = Vec::new();
+
+ let intermediate = |me: &mut Deserializer| {
+ loop {
+ me.eat_whitespace()?;
+ if !me.eat(Token::Newline)? && !me.eat_comment()? {
+ break
+ }
+ }
+ Ok(())
+ };
+
+ loop {
+ intermediate(self)?;
+ if self.eat(Token::RightBracket)? {
+ return Ok(ret)
+ }
+ let at = self.tokens.current();
+ let value = self.value()?;
+ if let Some(last) = ret.last() {
+ if !value.same_type(last) {
+ return Err(self.error(at, ErrorKind::MixedArrayType))
+ }
+ }
+ ret.push(value);
+ intermediate(self)?;
+ if !self.eat(Token::Comma)? {
+ break
+ }
+ }
+ intermediate(self)?;
+ self.expect(Token::RightBracket)?;
+ Ok(ret)
+ }
+
+ fn table_key(&mut self) -> Result<Cow<'a, str>, Error> {
+ self.tokens.table_key().map_err(|e| self.token_error(e))
+ }
+
+ fn eat_whitespace(&mut self) -> Result<(), Error> {
+ self.tokens.eat_whitespace().map_err(|e| self.token_error(e))
+ }
+
+ fn eat_comment(&mut self) -> Result<bool, Error> {
+ self.tokens.eat_comment().map_err(|e| self.token_error(e))
+ }
+
+ fn eat_newline_or_eof(&mut self) -> Result<(), Error> {
+ self.tokens.eat_newline_or_eof().map_err(|e| self.token_error(e))
+ }
+
+ fn eat(&mut self, expected: Token<'a>) -> Result<bool, Error> {
+ self.tokens.eat(expected).map_err(|e| self.token_error(e))
+ }
+
+ fn expect(&mut self, expected: Token<'a>) -> Result<(), Error> {
+ self.tokens.expect(expected).map_err(|e| self.token_error(e))
+ }
+
+ fn next(&mut self) -> Result<Option<Token<'a>>, Error> {
+ self.tokens.next().map_err(|e| self.token_error(e))
+ }
+
+ fn peek(&mut self) -> Result<Option<Token<'a>>, Error> {
+ self.tokens.peek().map_err(|e| self.token_error(e))
+ }
+
+ fn eof(&self) -> Error {
+ self.error(self.input.len(), ErrorKind::UnexpectedEof)
+ }
+
+ fn token_error(&self, error: TokenError) -> Error {
+ match error {
+ TokenError::InvalidCharInString(at, ch) => {
+ self.error(at, ErrorKind::InvalidCharInString(ch))
+ }
+ TokenError::InvalidEscape(at, ch) => {
+ self.error(at, ErrorKind::InvalidEscape(ch))
+ }
+ TokenError::InvalidEscapeValue(at, v) => {
+ self.error(at, ErrorKind::InvalidEscapeValue(v))
+ }
+ TokenError::InvalidHexEscape(at, ch) => {
+ self.error(at, ErrorKind::InvalidHexEscape(ch))
+ }
+ TokenError::NewlineInString(at) => {
+ self.error(at, ErrorKind::NewlineInString)
+ }
+ TokenError::Unexpected(at, ch) => {
+ self.error(at, ErrorKind::Unexpected(ch))
+ }
+ TokenError::UnterminatedString(at) => {
+ self.error(at, ErrorKind::UnterminatedString)
+ }
+ TokenError::NewlineInTableKey(at) => {
+ self.error(at, ErrorKind::NewlineInTableKey)
+ }
+ TokenError::Wanted { at, expected, found } => {
+ self.error(at, ErrorKind::Wanted { expected: expected, found: found })
+ }
+ TokenError::EmptyTableKey(at) => {
+ self.error(at, ErrorKind::EmptyTableKey)
+ }
+ }
+ }
+
+ fn error(&self, at: usize, kind: ErrorKind) -> Error {
+ let mut err = Error::from_kind(kind);
+ let (line, col) = self.to_linecol(at);
+ err.inner.line = Some(line);
+ err.inner.col = col;
+ err
+ }
+
+ /// Converts a byte offset from an error message to a (line, column) pair
+ ///
+ /// All indexes are 0-based.
+ fn to_linecol(&self, offset: usize) -> (usize, usize) {
+ let mut cur = 0;
+ for (i, line) in self.input.lines().enumerate() {
+ if cur + line.len() + 1 > offset {
+ return (i, offset - cur)
+ }
+ cur += line.len() + 1;
+ }
+ (self.input.lines().count(), 0)
+ }
+}
+
+impl Error {
+ /// Produces a (line, column) pair of the position of the error if available
+ ///
+ /// All indexes are 0-based.
+ pub fn line_col(&self) -> Option<(usize, usize)> {
+ self.inner.line.map(|line| (line, self.inner.col))
+ }
+
+ fn from_kind(kind: ErrorKind) -> Error {
+ Error {
+ inner: Box::new(ErrorInner {
+ kind: kind,
+ line: None,
+ col: 0,
+ message: String::new(),
+ key: Vec::new(),
+ }),
+ }
+ }
+
+ fn custom(s: String) -> Error {
+ Error {
+ inner: Box::new(ErrorInner {
+ kind: ErrorKind::Custom,
+ line: None,
+ col: 0,
+ message: s,
+ key: Vec::new(),
+ }),
+ }
+ }
+
+ /// Do not call this method, it may be removed at any time, it's just an
+ /// internal implementation detail.
+ #[doc(hidden)]
+ pub fn add_key_context(&mut self, key: &str) {
+ self.inner.key.insert(0, key.to_string());
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.inner.kind {
+ ErrorKind::UnexpectedEof => "unexpected eof encountered".fmt(f)?,
+ ErrorKind::InvalidCharInString(c) => {
+ write!(f, "invalid character in string: `{}`",
+ c.escape_default().collect::<String>())?
+ }
+ ErrorKind::InvalidEscape(c) => {
+ write!(f, "invalid escape character in string: `{}`",
+ c.escape_default().collect::<String>())?
+ }
+ ErrorKind::InvalidHexEscape(c) => {
+ write!(f, "invalid hex escape character in string: `{}`",
+ c.escape_default().collect::<String>())?
+ }
+ ErrorKind::InvalidEscapeValue(c) => {
+ write!(f, "invalid escape value: `{}`", c)?
+ }
+ ErrorKind::NewlineInString => "newline in string found".fmt(f)?,
+ ErrorKind::Unexpected(ch) => {
+ write!(f, "unexpected character found: `{}`",
+ ch.escape_default().collect::<String>())?
+ }
+ ErrorKind::UnterminatedString => "unterminated string".fmt(f)?,
+ ErrorKind::NewlineInTableKey => "found newline in table key".fmt(f)?,
+ ErrorKind::Wanted { expected, found } => {
+ write!(f, "expected {}, found {}", expected, found)?
+ }
+ ErrorKind::NumberInvalid => "invalid number".fmt(f)?,
+ ErrorKind::DateInvalid => "invalid date".fmt(f)?,
+ ErrorKind::MixedArrayType => "mixed types in an array".fmt(f)?,
+ ErrorKind::DuplicateTable(ref s) => {
+ write!(f, "redefinition of table `{}`", s)?;
+ }
+ ErrorKind::RedefineAsArray => "table redefined as array".fmt(f)?,
+ ErrorKind::EmptyTableKey => "empty table key found".fmt(f)?,
+ ErrorKind::Custom => self.inner.message.fmt(f)?,
+ ErrorKind::ExpectedString => "expected string".fmt(f)?,
+ ErrorKind::__Nonexhaustive => panic!(),
+ }
+
+ if !self.inner.key.is_empty() {
+ write!(f, " for key `")?;
+ for (i, k) in self.inner.key.iter().enumerate() {
+ if i > 0 {
+ write!(f, ".")?;
+ }
+ write!(f, "{}", k)?;
+ }
+ write!(f, "`")?;
+ }
+
+ if let Some(line) = self.inner.line {
+ write!(f, " at line {}", line + 1)?;
+ }
+
+ Ok(())
+ }
+}
+
+impl error::Error for Error {
+ fn description(&self) -> &str {
+ match self.inner.kind {
+ ErrorKind::UnexpectedEof => "unexpected eof encountered",
+ ErrorKind::InvalidCharInString(_) => "invalid char in string",
+ ErrorKind::InvalidEscape(_) => "invalid escape in string",
+ ErrorKind::InvalidHexEscape(_) => "invalid hex escape in string",
+ ErrorKind::InvalidEscapeValue(_) => "invalid escape value in string",
+ ErrorKind::NewlineInString => "newline in string found",
+ ErrorKind::Unexpected(_) => "unexpected or invalid character",
+ ErrorKind::UnterminatedString => "unterminated string",
+ ErrorKind::NewlineInTableKey => "found newline in table key",
+ ErrorKind::Wanted { .. } => "expected a token but found another",
+ ErrorKind::NumberInvalid => "invalid number",
+ ErrorKind::DateInvalid => "invalid date",
+ ErrorKind::MixedArrayType => "mixed types in an array",
+ ErrorKind::DuplicateTable(_) => "duplicate table",
+ ErrorKind::RedefineAsArray => "table redefined as array",
+ ErrorKind::EmptyTableKey => "empty table key found",
+ ErrorKind::Custom => "a custom error",
+ ErrorKind::ExpectedString => "expected string",
+ ErrorKind::__Nonexhaustive => panic!(),
+ }
+ }
+}
+
+impl de::Error for Error {
+ fn custom<T: fmt::Display>(msg: T) -> Error {
+ Error::custom(msg.to_string())
+ }
+}
+
+enum Line<'a> {
+ Table { at: usize, header: Header<'a>, array: bool },
+ KeyValue(Cow<'a, str>, Value<'a>),
+}
+
+struct Header<'a> {
+ first: bool,
+ array: bool,
+ require_newline_after_table: bool,
+ tokens: Tokenizer<'a>,
+}
+
+impl<'a> Header<'a> {
+ fn new(tokens: Tokenizer<'a>,
+ array: bool,
+ require_newline_after_table: bool) -> Header<'a> {
+ Header {
+ first: true,
+ array: array,
+ tokens: tokens,
+ require_newline_after_table: require_newline_after_table,
+ }
+ }
+
+ fn next(&mut self) -> Result<Option<Cow<'a, str>>, TokenError> {
+ self.tokens.eat_whitespace()?;
+
+ if self.first || self.tokens.eat(Token::Period)? {
+ self.first = false;
+ self.tokens.eat_whitespace()?;
+ self.tokens.table_key().map(Some)
+ } else {
+ self.tokens.expect(Token::RightBracket)?;
+ if self.array {
+ self.tokens.expect(Token::RightBracket)?;
+ }
+
+ self.tokens.eat_whitespace()?;
+ if self.require_newline_after_table {
+ if !self.tokens.eat_comment()? {
+ self.tokens.eat_newline_or_eof()?;
+ }
+ }
+ Ok(None)
+ }
+ }
+}
+
+#[derive(Debug)]
+enum Value<'a> {
+ Integer(i64),
+ Float(f64),
+ Boolean(bool),
+ String(Cow<'a, str>),
+ Datetime(&'a str),
+ Array(Vec<Value<'a>>),
+ InlineTable(Vec<(Cow<'a, str>, Value<'a>)>),
+}
+
+impl<'a> Value<'a> {
+ fn same_type(&self, other: &Value<'a>) -> 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::InlineTable(..), &Value::InlineTable(..)) => true,
+
+ _ => false,
+ }
+ }
+}
diff --git a/third_party/rust/toml/src/lib.rs b/third_party/rust/toml/src/lib.rs
new file mode 100644
index 0000000000..c4a7e9dfa6
--- /dev/null
+++ b/third_party/rust/toml/src/lib.rs
@@ -0,0 +1,168 @@
+//! A [TOML]-parsing library
+//!
+//! This library implements a [TOML] v0.4.0 compatible parser,
+//! primarily supporting the [`serde`] library for encoding/decoding
+//! various types in Rust.
+//!
+//! TOML itself is a simple, ergonomic, and readable configuration format:
+//!
+//! ```toml
+//! [package]
+//! name = "toml"
+//! version = "0.4.2"
+//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
+//!
+//! [dependencies]
+//! serde = "1.0"
+//! ```
+//!
+//! The TOML format tends to be relatively common throughout the Rust community
+//! for configuration, notably being used by [Cargo], Rust's package manager.
+//!
+//! ## TOML values
+//!
+//! A value in TOML is represented with the `Value` enum in this crate:
+//!
+//! ```rust,ignore
+//! pub enum Value {
+//! String(String),
+//! Integer(i64),
+//! Float(f64),
+//! Boolean(bool),
+//! Datetime(Datetime),
+//! Array(Array),
+//! Table(Table),
+//! }
+//! ```
+//!
+//! TOML is similar to JSON with the notable addition of a `Datetime`
+//! type. In general, TOML and JSON are interchangeable in terms of
+//! formats.
+//!
+//! ## Parsing TOML
+//!
+//! The easiest way to parse a TOML document is via the `Value` type:
+//!
+//! ```rust
+//! use toml::Value;
+//!
+//! let value = "foo = 'bar'".parse::<Value>().unwrap();
+//!
+//! assert_eq!(value["foo"].as_str(), Some("bar"));
+//! ```
+//!
+//! The `Value` type implements a number of convenience methods and
+//! traits; the example above uses `FromStr` to parse a `str` into a
+//! `Value`.
+//!
+//! ## Deserialization and Serialization
+//!
+//! This crate supports [`serde`] 1.0 with a number of
+//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
+//! `Serializer` traits. Namely, you'll find:
+//!
+//! * `Deserialize for Value`
+//! * `Serialize for Value`
+//! * `Deserialize for Datetime`
+//! * `Serialize for Datetime`
+//! * `Deserializer for de::Deserializer`
+//! * `Serializer for ser::Serializer`
+//! * `Deserializer for Value`
+//!
+//! This means that you can use Serde to deserialize/serialize the
+//! `Value` type as well as the `Datetime` type in this crate. You can also
+//! use the `Deserializer`, `Serializer`, or `Value` type itself to act as
+//! a deserializer/serializer for arbitrary types.
+//!
+//! An example of deserializing with TOML is:
+//!
+//! ```rust
+//! #[macro_use]
+//! extern crate serde_derive;
+//! extern crate toml;
+//!
+//! #[derive(Deserialize)]
+//! struct Config {
+//! ip: String,
+//! port: Option<u16>,
+//! keys: Keys,
+//! }
+//!
+//! #[derive(Deserialize)]
+//! struct Keys {
+//! github: String,
+//! travis: Option<String>,
+//! }
+//!
+//! fn main() {
+//! let config: Config = toml::from_str(r#"
+//! ip = '127.0.0.1'
+//!
+//! [keys]
+//! github = 'xxxxxxxxxxxxxxxxx'
+//! travis = 'yyyyyyyyyyyyyyyyy'
+//! "#).unwrap();
+//!
+//! assert_eq!(config.ip, "127.0.0.1");
+//! assert_eq!(config.port, None);
+//! assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
+//! assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
+//! }
+//! ```
+//!
+//! You can serialize types in a similar fashion:
+//!
+//! ```rust
+//! #[macro_use]
+//! extern crate serde_derive;
+//! extern crate toml;
+//!
+//! #[derive(Serialize)]
+//! struct Config {
+//! ip: String,
+//! port: Option<u16>,
+//! keys: Keys,
+//! }
+//!
+//! #[derive(Serialize)]
+//! struct Keys {
+//! github: String,
+//! travis: Option<String>,
+//! }
+//!
+//! fn main() {
+//! let config = Config {
+//! ip: "127.0.0.1".to_string(),
+//! port: None,
+//! keys: Keys {
+//! github: "xxxxxxxxxxxxxxxxx".to_string(),
+//! travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
+//! },
+//! };
+//!
+//! let toml = toml::to_string(&config).unwrap();
+//! }
+//! ```
+//!
+//! [TOML]: https://github.com/toml-lang/toml
+//! [Cargo]: https://crates.io/
+//! [`serde`]: https://serde.rs/
+
+#![doc(html_root_url = "https://docs.rs/toml/0.4")]
+#![deny(missing_docs)]
+
+#[macro_use]
+extern crate serde;
+
+pub mod value;
+#[doc(no_inline)]
+pub use value::Value;
+mod datetime;
+
+pub mod ser;
+#[doc(no_inline)]
+pub use ser::{to_string, to_string_pretty, to_vec, Serializer};
+pub mod de;
+#[doc(no_inline)]
+pub use de::{from_slice, from_str, Deserializer};
+mod tokens;
diff --git a/third_party/rust/toml/src/ser.rs b/third_party/rust/toml/src/ser.rs
new file mode 100644
index 0000000000..ef037ed177
--- /dev/null
+++ b/third_party/rust/toml/src/ser.rs
@@ -0,0 +1,1714 @@
+//! Serializing Rust structures into TOML.
+//!
+//! This module contains all the Serde support for serializing Rust structures
+//! into TOML documents (as strings). Note that some top-level functions here
+//! are also provided at the top of the crate.
+//!
+//! Note that the TOML format has a restriction that if a table itself contains
+//! tables, all keys with non-table values must be emitted first. This is
+//! typically easy to ensure happens when you're defining a `struct` as you can
+//! reorder the fields manually, but when working with maps (such as `BTreeMap`
+//! or `HashMap`) this can lead to serialization errors. In those situations you
+//! may use the `tables_last` function in this module like so:
+//!
+//! ```rust
+//! # #[macro_use] extern crate serde_derive;
+//! # extern crate toml;
+//! # use std::collections::HashMap;
+//! #[derive(Serialize)]
+//! struct Manifest {
+//! package: Package,
+//! #[serde(serialize_with = "toml::ser::tables_last")]
+//! dependencies: HashMap<String, Dependency>,
+//! }
+//! # type Package = String;
+//! # type Dependency = String;
+//! # fn main() {}
+//! ```
+
+use std::cell::Cell;
+use std::error;
+use std::fmt::{self, Write};
+use std::marker;
+use std::rc::Rc;
+
+use serde::ser;
+use datetime::{SERDE_STRUCT_FIELD_NAME, SERDE_STRUCT_NAME};
+
+/// Serialize the given data structure as a TOML byte vector.
+///
+/// Serialization can fail if `T`'s implementation of `Serialize` decides to
+/// fail, if `T` contains a map with non-string keys, or if `T` attempts to
+/// serialize an unsupported datatype such as an enum, tuple, or tuple struct.
+pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>, Error>
+ where T: ser::Serialize,
+{
+ to_string(value).map(|e| e.into_bytes())
+}
+
+/// Serialize the given data structure as a String of TOML.
+///
+/// Serialization can fail if `T`'s implementation of `Serialize` decides to
+/// fail, if `T` contains a map with non-string keys, or if `T` attempts to
+/// serialize an unsupported datatype such as an enum, tuple, or tuple struct.
+///
+/// # Examples
+///
+/// ```
+/// #[macro_use]
+/// extern crate serde_derive;
+/// extern crate toml;
+///
+/// #[derive(Serialize)]
+/// struct Config {
+/// database: Database,
+/// }
+///
+/// #[derive(Serialize)]
+/// struct Database {
+/// ip: String,
+/// port: Vec<u16>,
+/// connection_max: u32,
+/// enabled: bool,
+/// }
+///
+/// fn main() {
+/// let config = Config {
+/// database: Database {
+/// ip: "192.168.1.1".to_string(),
+/// port: vec![8001, 8002, 8003],
+/// connection_max: 5000,
+/// enabled: false,
+/// },
+/// };
+///
+/// let toml = toml::to_string(&config).unwrap();
+/// println!("{}", toml)
+/// }
+/// ```
+pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error>
+ where T: ser::Serialize,
+{
+ let mut dst = String::with_capacity(128);
+ value.serialize(&mut Serializer::new(&mut dst))?;
+ Ok(dst)
+}
+
+/// Serialize the given data structure as a "pretty" String of TOML.
+///
+/// This is identical to `to_string` except the output string has a more
+/// "pretty" output. See `Serializer::pretty` for more details.
+pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error>
+ where T: ser::Serialize,
+{
+ let mut dst = String::with_capacity(128);
+ value.serialize(&mut Serializer::pretty(&mut dst))?;
+ Ok(dst)
+}
+
+/// Errors that can occur when serializing a type.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum Error {
+ /// Indicates that a Rust type was requested to be serialized but it was not
+ /// supported.
+ ///
+ /// Currently the TOML format does not support serializing types such as
+ /// enums, tuples and tuple structs.
+ UnsupportedType,
+
+ /// The key of all TOML maps must be strings, but serialization was
+ /// attempted where the key of a map was not a string.
+ KeyNotString,
+
+ /// An error that we never omit but keep for backwards compatibility
+ #[doc(hidden)]
+ KeyNewline,
+
+ /// Arrays in TOML must have a homogenous type, but a heterogeneous array
+ /// was emitted.
+ ArrayMixedType,
+
+ /// All values in a TOML table must be emitted before further tables are
+ /// emitted. If a value is emitted *after* a table then this error is
+ /// generated.
+ ValueAfterTable,
+
+ /// A serialized date was invalid.
+ DateInvalid,
+
+ /// A serialized number was invalid.
+ NumberInvalid,
+
+ /// None was attempted to be serialized, but it's not supported.
+ UnsupportedNone,
+
+ /// A custom error which could be generated when serializing a particular
+ /// type.
+ Custom(String),
+
+ #[doc(hidden)]
+ __Nonexhaustive,
+}
+
+#[derive(Debug, Default, Clone)]
+#[doc(hidden)]
+/// Internal place for holding array setings
+struct ArraySettings {
+ indent: usize,
+ trailing_comma: bool,
+}
+
+impl ArraySettings {
+ fn pretty() -> ArraySettings {
+ ArraySettings {
+ indent: 4,
+ trailing_comma: true,
+ }
+ }
+}
+
+#[doc(hidden)]
+#[derive(Debug, Default, Clone)]
+/// String settings
+struct StringSettings {
+ /// Whether to use literal strings when possible
+ literal: bool,
+}
+
+impl StringSettings {
+ fn pretty() -> StringSettings {
+ StringSettings {
+ literal: true,
+ }
+ }
+}
+
+#[derive(Debug, Default, Clone)]
+#[doc(hidden)]
+/// Internal struct for holding serialization settings
+struct Settings {
+ array: Option<ArraySettings>,
+ string: Option<StringSettings>,
+}
+
+/// Serialization implementation for TOML.
+///
+/// This structure implements serialization support for TOML to serialize an
+/// arbitrary type to TOML. Note that the TOML format does not support all
+/// datatypes in Rust, such as enums, tuples, and tuple structs. These types
+/// will generate an error when serialized.
+///
+/// Currently a serializer always writes its output to an in-memory `String`,
+/// which is passed in when creating the serializer itself.
+pub struct Serializer<'a> {
+ dst: &'a mut String,
+ state: State<'a>,
+ settings: Rc<Settings>,
+}
+
+#[derive(Debug, Clone)]
+enum State<'a> {
+ Table {
+ key: &'a str,
+ parent: &'a State<'a>,
+ first: &'a Cell<bool>,
+ table_emitted: &'a Cell<bool>,
+ },
+ Array {
+ parent: &'a State<'a>,
+ first: &'a Cell<bool>,
+ type_: &'a Cell<Option<&'static str>>,
+ len: Option<usize>,
+ },
+ End,
+}
+
+#[doc(hidden)]
+pub struct SerializeSeq<'a: 'b, 'b> {
+ ser: &'b mut Serializer<'a>,
+ first: Cell<bool>,
+ type_: Cell<Option<&'static str>>,
+ len: Option<usize>,
+}
+
+#[doc(hidden)]
+pub enum SerializeTable<'a: 'b, 'b> {
+ Datetime(&'b mut Serializer<'a>),
+ Table {
+ ser: &'b mut Serializer<'a>,
+ key: String,
+ first: Cell<bool>,
+ table_emitted: Cell<bool>,
+ }
+}
+
+impl<'a> Serializer<'a> {
+ /// Creates a new serializer which will emit TOML into the buffer provided.
+ ///
+ /// The serializer can then be used to serialize a type after which the data
+ /// will be present in `dst`.
+ pub fn new(dst: &'a mut String) -> Serializer<'a> {
+ Serializer {
+ dst: dst,
+ state: State::End,
+ settings: Rc::new(Settings::default()),
+ }
+ }
+
+ /// Instantiate a "pretty" formatter
+ ///
+ /// By default this will use:
+ ///
+ /// - pretty strings: strings with newlines will use the `'''` syntax. See
+ /// `Serializer::pretty_string`
+ /// - pretty arrays: each item in arrays will be on a newline, have an indentation of 4 and
+ /// have a trailing comma. See `Serializer::pretty_array`
+ pub fn pretty(dst: &'a mut String) -> Serializer<'a> {
+ Serializer {
+ dst: dst,
+ state: State::End,
+ settings: Rc::new(Settings {
+ array: Some(ArraySettings::pretty()),
+ string: Some(StringSettings::pretty()),
+ }),
+ }
+ }
+
+ /// Enable or Disable pretty strings
+ ///
+ /// If enabled, literal strings will be used when possible and strings with
+ /// one or more newlines will use triple quotes (i.e.: `'''` or `"""`)
+ ///
+ /// # Examples
+ ///
+ /// Instead of:
+ ///
+ /// ```toml,ignore
+ /// single = "no newlines"
+ /// text = "\nfoo\nbar\n"
+ /// ```
+ ///
+ /// You will have:
+ ///
+ /// ```toml,ignore
+ /// single = 'no newlines'
+ /// text = '''
+ /// foo
+ /// bar
+ /// '''
+ /// ```
+ pub fn pretty_string(&mut self, value: bool) -> &mut Self {
+ Rc::get_mut(&mut self.settings).unwrap().string = if value {
+ Some(StringSettings::pretty())
+ } else {
+ None
+ };
+ self
+ }
+
+ /// Enable or Disable Literal strings for pretty strings
+ ///
+ /// If enabled, literal strings will be used when possible and strings with
+ /// one or more newlines will use triple quotes (i.e.: `'''` or `"""`)
+ ///
+ /// If disabled, literal strings will NEVER be used and strings with one or
+ /// more newlines will use `"""`
+ ///
+ /// # Examples
+ ///
+ /// Instead of:
+ ///
+ /// ```toml,ignore
+ /// single = "no newlines"
+ /// text = "\nfoo\nbar\n"
+ /// ```
+ ///
+ /// You will have:
+ ///
+ /// ```toml,ignore
+ /// single = "no newlines"
+ /// text = """
+ /// foo
+ /// bar
+ /// """
+ /// ```
+ pub fn pretty_string_literal(&mut self, value: bool) -> &mut Self {
+ let use_default = if let &mut Some(ref mut s) = &mut Rc::get_mut(&mut self.settings)
+ .unwrap().string {
+ s.literal = value;
+ false
+ } else {
+ true
+ };
+
+ if use_default {
+ let mut string = StringSettings::pretty();
+ string.literal = value;
+ Rc::get_mut(&mut self.settings).unwrap().string = Some(string);
+ }
+ self
+ }
+
+ /// Enable or Disable pretty arrays
+ ///
+ /// If enabled, arrays will always have each item on their own line.
+ ///
+ /// Some specific features can be controlled via other builder methods:
+ ///
+ /// - `Serializer::pretty_array_indent`: set the indent to a value other
+ /// than 4.
+ /// - `Serializer::pretty_array_trailing_comma`: enable/disable the trailing
+ /// comma on the last item.
+ ///
+ /// # Examples
+ ///
+ /// Instead of:
+ ///
+ /// ```toml,ignore
+ /// array = ["foo", "bar"]
+ /// ```
+ ///
+ /// You will have:
+ ///
+ /// ```toml,ignore
+ /// array = [
+ /// "foo",
+ /// "bar",
+ /// ]
+ /// ```
+ pub fn pretty_array(&mut self, value: bool) -> &mut Self {
+ Rc::get_mut(&mut self.settings).unwrap().array = if value {
+ Some(ArraySettings::pretty())
+ } else {
+ None
+ };
+ self
+ }
+
+ /// Set the indent for pretty arrays
+ ///
+ /// See `Serializer::pretty_array` for more details.
+ pub fn pretty_array_indent(&mut self, value: usize) -> &mut Self {
+ let use_default = if let &mut Some(ref mut a) = &mut Rc::get_mut(&mut self.settings)
+ .unwrap().array {
+ a.indent = value;
+ false
+ } else {
+ true
+ };
+
+ if use_default {
+ let mut array = ArraySettings::pretty();
+ array.indent = value;
+ Rc::get_mut(&mut self.settings).unwrap().array = Some(array);
+ }
+ self
+ }
+
+ /// Specify whether to use a trailing comma when serializing pretty arrays
+ ///
+ /// See `Serializer::pretty_array` for more details.
+ pub fn pretty_array_trailing_comma(&mut self, value: bool) -> &mut Self {
+ let use_default = if let &mut Some(ref mut a) = &mut Rc::get_mut(&mut self.settings)
+ .unwrap().array {
+ a.trailing_comma = value;
+ false
+ } else {
+ true
+ };
+
+ if use_default {
+ let mut array = ArraySettings::pretty();
+ array.trailing_comma = value;
+ Rc::get_mut(&mut self.settings).unwrap().array = Some(array);
+ }
+ self
+ }
+
+ fn display<T: fmt::Display>(&mut self,
+ t: T,
+ type_: &'static str) -> Result<(), Error> {
+ self.emit_key(type_)?;
+ drop(write!(self.dst, "{}", t));
+ if let State::Table { .. } = self.state {
+ self.dst.push_str("\n");
+ }
+ Ok(())
+ }
+
+ fn emit_key(&mut self, type_: &'static str) -> Result<(), Error> {
+ self.array_type(type_)?;
+ let state = self.state.clone();
+ self._emit_key(&state)
+ }
+
+ // recursive implementation of `emit_key` above
+ fn _emit_key(&mut self, state: &State) -> Result<(), Error> {
+ match *state {
+ State::End => Ok(()),
+ State::Array { parent, first, type_, len } => {
+ assert!(type_.get().is_some());
+ if first.get() {
+ self._emit_key(parent)?;
+ }
+ self.emit_array(first, len)
+ }
+ State::Table { parent, first, table_emitted, key } => {
+ if table_emitted.get() {
+ return Err(Error::ValueAfterTable)
+ }
+ if first.get() {
+ self.emit_table_header(parent)?;
+ first.set(false);
+ }
+ self.escape_key(key)?;
+ self.dst.push_str(" = ");
+ Ok(())
+ }
+ }
+ }
+
+ fn emit_array(&mut self, first: &Cell<bool>, len: Option<usize>) -> Result<(), Error> {
+ match (len, &self.settings.array) {
+ (Some(0...1), _) | (_, &None) => {
+ if first.get() {
+ self.dst.push_str("[")
+ } else {
+ self.dst.push_str(", ")
+ }
+ },
+ (_, &Some(ref a)) => {
+ if first.get() {
+ self.dst.push_str("[\n")
+ } else {
+ self.dst.push_str(",\n")
+ }
+ for _ in 0..a.indent {
+ self.dst.push_str(" ");
+ }
+ },
+ }
+ Ok(())
+ }
+
+ fn array_type(&mut self, type_: &'static str) -> Result<(), Error> {
+ let prev = match self.state {
+ State::Array { type_, .. } => type_,
+ _ => return Ok(()),
+ };
+ if let Some(prev) = prev.get() {
+ if prev != type_ {
+ return Err(Error::ArrayMixedType)
+ }
+ } else {
+ prev.set(Some(type_));
+ }
+ Ok(())
+ }
+
+ fn escape_key(&mut self, key: &str) -> Result<(), Error> {
+ let ok = key.chars().all(|c| {
+ match c {
+ 'a' ... 'z' |
+ 'A' ... 'Z' |
+ '0' ... '9' |
+ '-' | '_' => true,
+ _ => false,
+ }
+ });
+ if ok {
+ drop(write!(self.dst, "{}", key));
+ } else {
+ self.emit_str(key, true)?;
+ }
+ Ok(())
+ }
+
+ fn emit_str(&mut self, value: &str, is_key: bool) -> Result<(), Error> {
+ #[derive(PartialEq)]
+ enum Type {
+ NewlineTripple,
+ OnelineTripple,
+ OnelineSingle,
+ }
+
+ enum Repr {
+ /// represent as a literal string (using '')
+ Literal(String, Type),
+ /// represent the std way (using "")
+ Std(Type),
+ }
+
+ fn do_pretty(value: &str) -> Repr {
+ // For doing pretty prints we store in a new String
+ // because there are too many cases where pretty cannot
+ // work. We need to determine:
+ // - if we are a "multi-line" pretty (if there are \n)
+ // - if ['''] appears if multi or ['] if single
+ // - if there are any invalid control characters
+ //
+ // Doing it any other way would require multiple passes
+ // to determine if a pretty string works or not.
+ let mut out = String::with_capacity(value.len() * 2);
+ let mut ty = Type::OnelineSingle;
+ // found consecutive single quotes
+ let mut max_found_singles = 0;
+ let mut found_singles = 0;
+ let mut can_be_pretty = true;
+
+ for ch in value.chars() {
+ if can_be_pretty {
+ if ch == '\'' {
+ found_singles += 1;
+ if found_singles >= 3 {
+ can_be_pretty = false;
+ }
+ } else {
+ if found_singles > max_found_singles {
+ max_found_singles = found_singles;
+ }
+ found_singles = 0
+ }
+ match ch {
+ '\t' => {},
+ '\n' => ty = Type::NewlineTripple,
+ // note that the following are invalid: \b \f \r
+ c if c < '\u{1f}' => can_be_pretty = false, // Invalid control character
+ _ => {}
+ }
+ out.push(ch);
+ } else {
+ // the string cannot be represented as pretty,
+ // still check if it should be multiline
+ if ch == '\n' {
+ ty = Type::NewlineTripple;
+ }
+ }
+ }
+ if !can_be_pretty {
+ debug_assert!(ty != Type::OnelineTripple);
+ return Repr::Std(ty);
+ }
+ if found_singles > max_found_singles {
+ max_found_singles = found_singles;
+ }
+ debug_assert!(max_found_singles < 3);
+ if ty == Type::OnelineSingle && max_found_singles >= 1 {
+ // no newlines, but must use ''' because it has ' in it
+ ty = Type::OnelineTripple;
+ }
+ Repr::Literal(out, ty)
+ }
+
+ let repr = if !is_key && self.settings.string.is_some() {
+ match (&self.settings.string, do_pretty(value)) {
+ (&Some(StringSettings { literal: false, .. }), Repr::Literal(_, ty)) =>
+ Repr::Std(ty),
+ (_, r @ _) => r,
+ }
+ } else {
+ Repr::Std(Type::OnelineSingle)
+ };
+ match repr {
+ Repr::Literal(literal, ty) => {
+ // A pretty string
+ match ty {
+ Type::NewlineTripple => self.dst.push_str("'''\n"),
+ Type::OnelineTripple => self.dst.push_str("'''"),
+ Type::OnelineSingle => self.dst.push('\''),
+ }
+ self.dst.push_str(&literal);
+ match ty {
+ Type::OnelineSingle => self.dst.push('\''),
+ _ => self.dst.push_str("'''"),
+ }
+ },
+ Repr::Std(ty) => {
+ match ty {
+ Type::NewlineTripple => self.dst.push_str("\"\"\"\n"),
+ // note: OnelineTripple can happen if do_pretty wants to do
+ // '''it's one line'''
+ // but settings.string.literal == false
+ Type::OnelineSingle |
+ Type::OnelineTripple => self.dst.push('"'),
+ }
+ for ch in value.chars() {
+ match ch {
+ '\u{8}' => self.dst.push_str("\\b"),
+ '\u{9}' => self.dst.push_str("\\t"),
+ '\u{a}' => {
+ match ty {
+ Type::NewlineTripple => self.dst.push('\n'),
+ Type::OnelineSingle => self.dst.push_str("\\n"),
+ _ => unreachable!(),
+ }
+ },
+ '\u{c}' => self.dst.push_str("\\f"),
+ '\u{d}' => self.dst.push_str("\\r"),
+ '\u{22}' => self.dst.push_str("\\\""),
+ '\u{5c}' => self.dst.push_str("\\\\"),
+ c if c < '\u{1f}' => drop(write!(self.dst, "\\u{:04X}", ch as u32)),
+ ch => self.dst.push(ch),
+ }
+ }
+ match ty {
+ Type::NewlineTripple => self.dst.push_str("\"\"\""),
+ Type::OnelineSingle | Type::OnelineTripple => self.dst.push('"'),
+ }
+ },
+ }
+ Ok(())
+ }
+
+ fn emit_table_header(&mut self, state: &State) -> Result<(), Error> {
+ let array_of_tables = match *state {
+ State::End => return Ok(()),
+ State::Array { .. } => true,
+ _ => false,
+ };
+
+ // Unlike [..]s, we can't omit [[..]] ancestors, so be sure to emit table
+ // headers for them.
+ let mut p = state;
+ if let State::Array { first, parent, .. } = *state {
+ if first.get() {
+ p = parent;
+ }
+ }
+ while let State::Table { first, parent, .. } = *p {
+ p = parent;
+ if !first.get() {
+ break;
+ }
+ if let State::Array { parent: &State::Table {..}, ..} = *parent {
+ self.emit_table_header(parent)?;
+ break;
+ }
+ }
+
+ match *state {
+ State::Table { first, .. } => {
+ if !first.get() {
+ // Newline if we are a table that is not the first
+ // table in the document.
+ self.dst.push('\n');
+ }
+ },
+ State::Array { parent, first, .. } => {
+ if !first.get() {
+ // Always newline if we are not the first item in the
+ // table-array
+ self.dst.push('\n');
+ } else if let State::Table { first, .. } = *parent {
+ if !first.get() {
+ // Newline if we are not the first item in the document
+ self.dst.push('\n');
+ }
+ }
+ },
+ _ => {}
+ }
+ self.dst.push_str("[");
+ if array_of_tables {
+ self.dst.push_str("[");
+ }
+ self.emit_key_part(state)?;
+ if array_of_tables {
+ self.dst.push_str("]");
+ }
+ self.dst.push_str("]\n");
+ Ok(())
+ }
+
+ fn emit_key_part(&mut self, key: &State) -> Result<bool, Error> {
+ match *key {
+ State::Array { parent, .. } => self.emit_key_part(parent),
+ State::End => Ok(true),
+ State::Table { key, parent, table_emitted, .. } => {
+ table_emitted.set(true);
+ let first = self.emit_key_part(parent)?;
+ if !first {
+ self.dst.push_str(".");
+ }
+ self.escape_key(key)?;
+ Ok(false)
+ }
+ }
+ }
+}
+
+impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> {
+ type Ok = ();
+ type Error = Error;
+ type SerializeSeq = SerializeSeq<'a, 'b>;
+ type SerializeTuple = ser::Impossible<(), Error>;
+ type SerializeTupleStruct = ser::Impossible<(), Error>;
+ type SerializeTupleVariant = ser::Impossible<(), Error>;
+ type SerializeMap = SerializeTable<'a, 'b>;
+ type SerializeStruct = SerializeTable<'a, 'b>;
+ type SerializeStructVariant = ser::Impossible<(), Error>;
+
+ fn serialize_bool(self, v: bool) -> Result<(), Self::Error> {
+ self.display(v, "bool")
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<(), Self::Error> {
+ self.display(v, "integer")
+ }
+
+ fn serialize_f32(mut self, v: f32) -> Result<(), Self::Error> {
+ if !v.is_finite() {
+ return Err(Error::NumberInvalid);
+ }
+
+ self.emit_key("float")?;
+ drop(write!(self.dst, "{}", v));
+ if v % 1.0 == 0.0 {
+ drop(write!(self.dst, ".0"));
+ }
+ if let State::Table { .. } = self.state {
+ self.dst.push_str("\n");
+ }
+ Ok(())
+ }
+
+ fn serialize_f64(mut self, v: f64) -> Result<(), Self::Error> {
+ if !v.is_finite() {
+ return Err(Error::NumberInvalid);
+ }
+
+ self.emit_key("float")?;
+ drop(write!(self.dst, "{}", v));
+ if v % 1.0 == 0.0 {
+ drop(write!(self.dst, ".0"));
+ }
+ if let State::Table { .. } = self.state {
+ self.dst.push_str("\n");
+ }
+ Ok(())
+ }
+
+ fn serialize_char(self, v: char) -> Result<(), Self::Error> {
+ let mut buf = [0; 4];
+ self.serialize_str(v.encode_utf8(&mut buf))
+ }
+
+ fn serialize_str(mut self, value: &str) -> Result<(), Self::Error> {
+ self.emit_key("string")?;
+ self.emit_str(value, false)?;
+ if let State::Table { .. } = self.state {
+ self.dst.push_str("\n");
+ }
+ Ok(())
+ }
+
+ fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
+ use serde::ser::Serialize;
+ value.serialize(self)
+ }
+
+ fn serialize_none(self) -> Result<(), Self::Error> {
+ Err(Error::UnsupportedNone)
+ }
+
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Self::Error>
+ where T: ser::Serialize
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_unit(self) -> Result<(), Self::Error> {
+ Err(Error::UnsupportedType)
+ }
+
+ fn serialize_unit_struct(self,
+ _name: &'static str)
+ -> Result<(), Self::Error> {
+ Err(Error::UnsupportedType)
+ }
+
+ fn serialize_unit_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str)
+ -> Result<(), Self::Error> {
+ self.serialize_str(variant)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T)
+ -> Result<(), Self::Error>
+ where T: ser::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _value: &T)
+ -> Result<(), Self::Error>
+ where T: ser::Serialize,
+ {
+ Err(Error::UnsupportedType)
+ }
+
+ fn serialize_seq(mut self, len: Option<usize>)
+ -> Result<Self::SerializeSeq, Self::Error> {
+ self.array_type("array")?;
+ Ok(SerializeSeq {
+ ser: self,
+ first: Cell::new(true),
+ type_: Cell::new(None),
+ len: len,
+ })
+ }
+
+ fn serialize_tuple(self, _len: usize)
+ -> Result<Self::SerializeTuple, Self::Error> {
+ Err(Error::UnsupportedType)
+ }
+
+ fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
+ -> Result<Self::SerializeTupleStruct, Self::Error> {
+ Err(Error::UnsupportedType)
+ }
+
+ fn serialize_tuple_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeTupleVariant, Self::Error> {
+ Err(Error::UnsupportedType)
+ }
+
+ fn serialize_map(mut self, _len: Option<usize>)
+ -> Result<Self::SerializeMap, Self::Error> {
+ self.array_type("table")?;
+ Ok(SerializeTable::Table {
+ ser: self,
+ key: String::new(),
+ first: Cell::new(true),
+ table_emitted: Cell::new(false),
+ })
+ }
+
+ fn serialize_struct(mut self, name: &'static str, _len: usize)
+ -> Result<Self::SerializeStruct, Self::Error> {
+ if name == SERDE_STRUCT_NAME {
+ self.array_type("datetime")?;
+ Ok(SerializeTable::Datetime(self))
+ } else {
+ self.array_type("table")?;
+ Ok(SerializeTable::Table {
+ ser: self,
+ key: String::new(),
+ first: Cell::new(true),
+ table_emitted: Cell::new(false),
+ })
+ }
+ }
+
+ fn serialize_struct_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeStructVariant, Self::Error> {
+ Err(Error::UnsupportedType)
+ }
+}
+
+impl<'a, 'b> ser::SerializeSeq for SerializeSeq<'a, 'b> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where T: ser::Serialize,
+ {
+ value.serialize(&mut Serializer {
+ dst: &mut *self.ser.dst,
+ state: State::Array {
+ parent: &self.ser.state,
+ first: &self.first,
+ type_: &self.type_,
+ len: self.len,
+ },
+ settings: self.ser.settings.clone(),
+ })?;
+ self.first.set(false);
+ Ok(())
+ }
+
+ fn end(self) -> Result<(), Error> {
+ match self.type_.get() {
+ Some("table") => return Ok(()),
+ Some(_) => {
+ match (self.len, &self.ser.settings.array) {
+ (Some(0...1), _) | (_, &None) => {
+ self.ser.dst.push_str("]");
+ },
+ (_, &Some(ref a)) => {
+ if a.trailing_comma {
+ self.ser.dst.push_str(",");
+ }
+ self.ser.dst.push_str("\n]");
+ },
+ }
+ }
+ None => {
+ assert!(self.first.get());
+ self.ser.emit_key("array")?;
+ self.ser.dst.push_str("[]")
+ }
+ }
+ if let State::Table { .. } = self.ser.state {
+ self.ser.dst.push_str("\n");
+ }
+ Ok(())
+ }
+}
+
+impl<'a, 'b> ser::SerializeMap for SerializeTable<'a, 'b> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Error>
+ where T: ser::Serialize,
+ {
+ match *self {
+ SerializeTable::Datetime(_) => panic!(), // shouldn't be possible
+ SerializeTable::Table { ref mut key, .. } => {
+ key.truncate(0);
+ *key = input.serialize(StringExtractor)?;
+ }
+ }
+ Ok(())
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where T: ser::Serialize,
+ {
+ match *self {
+ SerializeTable::Datetime(_) => panic!(), // shouldn't be possible
+ SerializeTable::Table {
+ ref mut ser,
+ ref key,
+ ref first,
+ ref table_emitted,
+ ..
+ } => {
+ let res = value.serialize(&mut Serializer {
+ dst: &mut *ser.dst,
+ state: State::Table {
+ key: key,
+ parent: &ser.state,
+ first: first,
+ table_emitted: table_emitted,
+ },
+ settings: ser.settings.clone(),
+ });
+ match res {
+ Ok(()) => first.set(false),
+ Err(Error::UnsupportedNone) => {},
+ Err(e) => return Err(e),
+ }
+ }
+ }
+ Ok(())
+ }
+
+ fn end(self) -> Result<(), Error> {
+ match self {
+ SerializeTable::Datetime(_) => panic!(), // shouldn't be possible
+ SerializeTable::Table { mut ser, first, .. } => {
+ if first.get() {
+ let state = ser.state.clone();
+ ser.emit_table_header(&state)?;
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+impl<'a, 'b> ser::SerializeStruct for SerializeTable<'a, 'b> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T)
+ -> Result<(), Error>
+ where T: ser::Serialize,
+ {
+ match *self {
+ SerializeTable::Datetime(ref mut ser) => {
+ if key == SERDE_STRUCT_FIELD_NAME {
+ value.serialize(DateStrEmitter(&mut *ser))?;
+ } else {
+ return Err(Error::DateInvalid)
+ }
+ }
+ SerializeTable::Table {
+ ref mut ser,
+ ref first,
+ ref table_emitted,
+ ..
+ } => {
+ let res = value.serialize(&mut Serializer {
+ dst: &mut *ser.dst,
+ state: State::Table {
+ key: key,
+ parent: &ser.state,
+ first: first,
+ table_emitted: table_emitted,
+ },
+ settings: ser.settings.clone(),
+ });
+ match res {
+ Ok(()) => first.set(false),
+ Err(Error::UnsupportedNone) => {},
+ Err(e) => return Err(e),
+ }
+ }
+ }
+ Ok(())
+ }
+
+ fn end(self) -> Result<(), Error> {
+ match self {
+ SerializeTable::Datetime(_) => {},
+ SerializeTable::Table { mut ser, first, .. } => {
+ if first.get() {
+ let state = ser.state.clone();
+ ser.emit_table_header(&state)?;
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+struct DateStrEmitter<'a: 'b, 'b>(&'b mut Serializer<'a>);
+
+impl<'a, 'b> ser::Serializer for DateStrEmitter<'a, 'b> {
+ type Ok = ();
+ type Error = Error;
+ type SerializeSeq = ser::Impossible<(), Error>;
+ type SerializeTuple = ser::Impossible<(), Error>;
+ type SerializeTupleStruct = ser::Impossible<(), Error>;
+ type SerializeTupleVariant = ser::Impossible<(), Error>;
+ type SerializeMap = ser::Impossible<(), Error>;
+ type SerializeStruct = ser::Impossible<(), Error>;
+ type SerializeStructVariant = ser::Impossible<(), Error>;
+
+ fn serialize_bool(self, _v: bool) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i8(self, _v: i8) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i16(self, _v: i16) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i32(self, _v: i32) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i64(self, _v: i64) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u8(self, _v: u8) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u16(self, _v: u16) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u32(self, _v: u32) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u64(self, _v: u64) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_f32(self, _v: f32) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_f64(self, _v: f64) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_char(self, _v: char) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_str(self, value: &str) -> Result<(), Self::Error> {
+ self.0.display(value, "datetime")?;
+ Ok(())
+ }
+
+ fn serialize_bytes(self, _value: &[u8]) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_none(self) -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<(), Self::Error>
+ where T: ser::Serialize
+ {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit(self) -> Result<(), Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit_struct(self,
+ _name: &'static str)
+ -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_unit_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str)
+ -> Result<(), Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T)
+ -> Result<(), Self::Error>
+ where T: ser::Serialize,
+ {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _value: &T)
+ -> Result<(), Self::Error>
+ where T: ser::Serialize,
+ {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_seq(self, _len: Option<usize>)
+ -> Result<Self::SerializeSeq, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_tuple(self, _len: usize)
+ -> Result<Self::SerializeTuple, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
+ -> Result<Self::SerializeTupleStruct, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_tuple_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeTupleVariant, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_map(self, _len: Option<usize>)
+ -> Result<Self::SerializeMap, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_struct(self, _name: &'static str, _len: usize)
+ -> Result<Self::SerializeStruct, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_struct_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeStructVariant, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+}
+
+struct StringExtractor;
+
+impl ser::Serializer for StringExtractor {
+ type Ok = String;
+ type Error = Error;
+ type SerializeSeq = ser::Impossible<String, Error>;
+ type SerializeTuple = ser::Impossible<String, Error>;
+ type SerializeTupleStruct = ser::Impossible<String, Error>;
+ type SerializeTupleVariant = ser::Impossible<String, Error>;
+ type SerializeMap = ser::Impossible<String, Error>;
+ type SerializeStruct = ser::Impossible<String, Error>;
+ type SerializeStructVariant = ser::Impossible<String, Error>;
+
+ fn serialize_bool(self, _v: bool) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i8(self, _v: i8) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i16(self, _v: i16) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i32(self, _v: i32) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i64(self, _v: i64) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u8(self, _v: u8) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u16(self, _v: u16) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u32(self, _v: u32) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u64(self, _v: u64) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_f32(self, _v: f32) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_f64(self, _v: f64) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_char(self, _v: char) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_str(self, value: &str) -> Result<String, Self::Error> {
+ Ok(value.to_string())
+ }
+
+ fn serialize_bytes(self, _value: &[u8]) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_none(self) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<String, Self::Error>
+ where T: ser::Serialize
+ {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit(self) -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit_struct(self,
+ _name: &'static str)
+ -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str)
+ -> Result<String, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T)
+ -> Result<String, Self::Error>
+ where T: ser::Serialize,
+ {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _value: &T)
+ -> Result<String, Self::Error>
+ where T: ser::Serialize,
+ {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_seq(self, _len: Option<usize>)
+ -> Result<Self::SerializeSeq, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_tuple(self, _len: usize)
+ -> Result<Self::SerializeTuple, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
+ -> Result<Self::SerializeTupleStruct, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_tuple_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeTupleVariant, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_map(self, _len: Option<usize>)
+ -> Result<Self::SerializeMap, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_struct(self, _name: &'static str, _len: usize)
+ -> Result<Self::SerializeStruct, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_struct_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeStructVariant, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Error::UnsupportedType => "unsupported Rust type".fmt(f),
+ Error::KeyNotString => "map key was not a string".fmt(f),
+ Error::ArrayMixedType => "arrays cannot have mixed types".fmt(f),
+ Error::ValueAfterTable => "values must be emitted before tables".fmt(f),
+ Error::DateInvalid => "a serialized date was invalid".fmt(f),
+ Error::NumberInvalid => "a serialized number was invalid".fmt(f),
+ Error::UnsupportedNone => "unsupported None value".fmt(f),
+ Error::Custom(ref s) => s.fmt(f),
+ Error::KeyNewline => unreachable!(),
+ Error::__Nonexhaustive => panic!(),
+ }
+ }
+}
+
+impl error::Error for Error {
+ fn description(&self) -> &str {
+ match *self {
+ Error::UnsupportedType => "unsupported Rust type",
+ Error::KeyNotString => "map key was not a string",
+ Error::ArrayMixedType => "arrays cannot have mixed types",
+ Error::ValueAfterTable => "values must be emitted before tables",
+ Error::DateInvalid => "a serialized date was invalid",
+ Error::NumberInvalid => "a serialized number was invalid",
+ Error::UnsupportedNone => "unsupported None value",
+ Error::Custom(_) => "custom error",
+ Error::KeyNewline => unreachable!(),
+ Error::__Nonexhaustive => panic!(),
+ }
+ }
+}
+
+impl ser::Error for Error {
+ fn custom<T: fmt::Display>(msg: T) -> Error {
+ Error::Custom(msg.to_string())
+ }
+}
+
+enum Category {
+ Primitive,
+ Array,
+ Table,
+}
+
+/// Convenience function to serialize items in a map in an order valid with
+/// TOML.
+///
+/// TOML carries the restriction that keys in a table must be serialized last if
+/// their value is a table itself. This isn't always easy to guarantee, so this
+/// helper can be used like so:
+///
+/// ```rust
+/// # #[macro_use] extern crate serde_derive;
+/// # extern crate toml;
+/// # use std::collections::HashMap;
+/// #[derive(Serialize)]
+/// struct Manifest {
+/// package: Package,
+/// #[serde(serialize_with = "toml::ser::tables_last")]
+/// dependencies: HashMap<String, Dependency>,
+/// }
+/// # type Package = String;
+/// # type Dependency = String;
+/// # fn main() {}
+/// ```
+pub fn tables_last<'a, I, K, V, S>(data: &'a I, serializer: S)
+ -> Result<S::Ok, S::Error>
+ where &'a I: IntoIterator<Item = (K, V)>,
+ K: ser::Serialize,
+ V: ser::Serialize,
+ S: ser::Serializer
+{
+ use serde::ser::SerializeMap;
+
+ let mut map = serializer.serialize_map(None)?;
+ for (k, v) in data {
+ if let Category::Primitive = v.serialize(Categorize::new())? {
+ map.serialize_entry(&k, &v)?;
+ }
+ }
+ for (k, v) in data {
+ if let Category::Array = v.serialize(Categorize::new())? {
+ map.serialize_entry(&k, &v)?;
+ }
+ }
+ for (k, v) in data {
+ if let Category::Table = v.serialize(Categorize::new())? {
+ map.serialize_entry(&k, &v)?;
+ }
+ }
+ map.end()
+}
+
+struct Categorize<E>(marker::PhantomData<E>);
+
+impl<E> Categorize<E> {
+ fn new() -> Self {
+ Categorize(marker::PhantomData)
+ }
+}
+
+impl<E: ser::Error> ser::Serializer for Categorize<E> {
+ type Ok = Category;
+ type Error = E;
+ type SerializeSeq = Self;
+ type SerializeTuple = ser::Impossible<Category, E>;
+ type SerializeTupleStruct = ser::Impossible<Category, E>;
+ type SerializeTupleVariant = ser::Impossible<Category, E>;
+ type SerializeMap = Self;
+ type SerializeStruct = Self;
+ type SerializeStructVariant = ser::Impossible<Category, E>;
+
+ fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Primitive)
+ }
+
+ fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Array)
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_some<T: ?Sized + ser::Serialize>(self, v: &T) -> Result<Self::Ok, Self::Error> {
+ v.serialize(self)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<Self::Ok, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(self, _: &'static str, v: &T) -> Result<Self::Ok, Self::Error> {
+ v.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(self, _: &'static str, _: u32, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_seq(self, _: Option<usize>) -> Result<Self, Self::Error> {
+ Ok(self)
+ }
+
+ fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_tuple_variant(self, _: &'static str, _: u32, _: &'static str, _: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+
+ fn serialize_map(self, _: Option<usize>) -> Result<Self, Self::Error> {
+ Ok(self)
+ }
+
+ fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self, Self::Error> {
+ Ok(self)
+ }
+
+ fn serialize_struct_variant(self, _: &'static str, _: u32, _: &'static str, _: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
+ Err(ser::Error::custom("unsupported"))
+ }
+}
+
+impl<E: ser::Error> ser::SerializeSeq for Categorize<E> {
+ type Ok = Category;
+ type Error = E;
+
+ fn serialize_element<T: ?Sized + ser::Serialize>(&mut self, _: &T)
+ -> Result<(), Self::Error> {
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Array)
+ }
+}
+
+impl<E: ser::Error> ser::SerializeMap for Categorize<E> {
+ type Ok = Category;
+ type Error = E;
+
+ fn serialize_key<T: ?Sized + ser::Serialize>(&mut self, _: &T)
+ -> Result<(), Self::Error> {
+ Ok(())
+ }
+
+ fn serialize_value<T: ?Sized + ser::Serialize>(&mut self, _: &T)
+ -> Result<(), Self::Error> {
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Table)
+ }
+}
+
+impl<E: ser::Error> ser::SerializeStruct for Categorize<E> {
+ type Ok = Category;
+ type Error = E;
+
+ fn serialize_field<T: ?Sized>(&mut self,
+ _: &'static str,
+ _: &T) -> Result<(), Self::Error>
+ where T: ser::Serialize,
+ {
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Category::Table)
+ }
+}
diff --git a/third_party/rust/toml/src/tokens.rs b/third_party/rust/toml/src/tokens.rs
new file mode 100644
index 0000000000..11f47f5682
--- /dev/null
+++ b/third_party/rust/toml/src/tokens.rs
@@ -0,0 +1,620 @@
+use std::borrow::Cow;
+use std::char;
+use std::str;
+use std::string;
+
+use self::Token::*;
+
+#[derive(Eq, PartialEq, Debug)]
+pub enum Token<'a> {
+ Whitespace(&'a str),
+ Newline,
+ Comment(&'a str),
+
+ Equals,
+ Period,
+ Comma,
+ Colon,
+ Plus,
+ LeftBrace,
+ RightBrace,
+ LeftBracket,
+ RightBracket,
+
+ Keylike(&'a str),
+ String { src: &'a str, val: Cow<'a, str> },
+}
+
+#[derive(Eq, PartialEq, Debug)]
+pub enum Error {
+ InvalidCharInString(usize, char),
+ InvalidEscape(usize, char),
+ InvalidHexEscape(usize, char),
+ InvalidEscapeValue(usize, u32),
+ NewlineInString(usize),
+ Unexpected(usize, char),
+ UnterminatedString(usize),
+ NewlineInTableKey(usize),
+ EmptyTableKey(usize),
+ Wanted { at: usize, expected: &'static str, found: &'static str },
+}
+
+#[derive(Clone)]
+pub struct Tokenizer<'a> {
+ input: &'a str,
+ chars: CrlfFold<'a>,
+}
+
+#[derive(Clone)]
+struct CrlfFold<'a> {
+ chars: str::CharIndices<'a>,
+}
+
+#[derive(Debug)]
+enum MaybeString {
+ NotEscaped(usize),
+ Owned(string::String),
+}
+
+impl<'a> Tokenizer<'a> {
+ pub fn new(input: &'a str) -> Tokenizer<'a> {
+ let mut t = Tokenizer {
+ input: input,
+ chars: CrlfFold {
+ chars: input.char_indices(),
+ },
+ };
+ // Eat utf-8 BOM
+ t.eatc('\u{feff}');
+ t
+ }
+
+ pub fn next(&mut self) -> Result<Option<Token<'a>>, Error> {
+ let token = match self.chars.next() {
+ Some((_, '\n')) => Newline,
+ Some((start, ' ')) => self.whitespace_token(start),
+ Some((start, '\t')) => self.whitespace_token(start),
+ Some((start, '#')) => self.comment_token(start),
+ Some((_, '=')) => Equals,
+ Some((_, '.')) => Period,
+ Some((_, ',')) => Comma,
+ Some((_, ':')) => Colon,
+ Some((_, '+')) => Plus,
+ Some((_, '{')) => LeftBrace,
+ Some((_, '}')) => RightBrace,
+ Some((_, '[')) => LeftBracket,
+ Some((_, ']')) => RightBracket,
+ Some((start, '\'')) => return self.literal_string(start).map(Some),
+ Some((start, '"')) => return self.basic_string(start).map(Some),
+ Some((start, ch)) if is_keylike(ch) => self.keylike(start),
+
+ Some((start, ch)) => return Err(Error::Unexpected(start, ch)),
+ None => return Ok(None),
+ };
+ Ok(Some(token))
+ }
+
+ pub fn peek(&mut self) -> Result<Option<Token<'a>>, Error> {
+ self.clone().next()
+ }
+
+ pub fn eat(&mut self, expected: Token<'a>) -> Result<bool, Error> {
+ match self.peek()? {
+ Some(ref found) if expected == *found => {}
+ Some(_) => return Ok(false),
+ None => return Ok(false),
+ }
+ drop(self.next());
+ Ok(true)
+ }
+
+ pub fn expect(&mut self, expected: Token<'a>) -> Result<(), Error> {
+ let current = self.current();
+ match self.next()? {
+ Some(found) => {
+ if expected == found {
+ Ok(())
+ } else {
+ Err(Error::Wanted {
+ at: current,
+ expected: expected.describe(),
+ found: found.describe(),
+ })
+ }
+ }
+ None => {
+ Err(Error::Wanted {
+ at: self.input.len(),
+ expected: expected.describe(),
+ found: "eof",
+ })
+ }
+ }
+ }
+
+ pub fn table_key(&mut self) -> Result<Cow<'a, str>, Error> {
+ let current = self.current();
+ match self.next()? {
+ Some(Token::Keylike(k)) => Ok(k.into()),
+ Some(Token::String { src, val }) => {
+ let offset = self.substr_offset(src);
+ if val == "" {
+ return Err(Error::EmptyTableKey(offset))
+ }
+ match src.find('\n') {
+ None => Ok(val),
+ Some(i) => Err(Error::NewlineInTableKey(offset + i)),
+ }
+ }
+ Some(other) => {
+ Err(Error::Wanted {
+ at: current,
+ expected: "a table key",
+ found: other.describe(),
+ })
+ }
+ None => {
+ Err(Error::Wanted {
+ at: self.input.len(),
+ expected: "a table key",
+ found: "eof",
+ })
+ }
+ }
+ }
+
+ pub fn eat_whitespace(&mut self) -> Result<(), Error> {
+ while self.eatc(' ') || self.eatc('\t') {
+ // ...
+ }
+ Ok(())
+ }
+
+ pub fn eat_comment(&mut self) -> Result<bool, Error> {
+ if !self.eatc('#') {
+ return Ok(false)
+ }
+ drop(self.comment_token(0));
+ self.eat_newline_or_eof().map(|()| true)
+ }
+
+ pub fn eat_newline_or_eof(&mut self) -> Result<(), Error> {
+ let current = self.current();
+ match self.next()? {
+ None |
+ Some(Token::Newline) => Ok(()),
+ Some(other) => {
+ Err(Error::Wanted {
+ at: current,
+ expected: "newline",
+ found: other.describe(),
+ })
+ }
+ }
+ }
+
+ pub fn skip_to_newline(&mut self) {
+ loop {
+ match self.chars.next() {
+ Some((_, '\n')) |
+ None => break,
+ _ => {}
+ }
+ }
+ }
+
+ fn eatc(&mut self, ch: char) -> bool {
+ match self.chars.clone().next() {
+ Some((_, ch2)) if ch == ch2 => {
+ self.chars.next();
+ true
+ }
+ _ => false,
+ }
+ }
+
+ pub fn current(&mut self) -> usize {
+ self.chars.clone().next().map(|i| i.0).unwrap_or(self.input.len())
+ }
+
+ pub fn input(&self) -> &'a str {
+ self.input
+ }
+
+ fn whitespace_token(&mut self, start: usize) -> Token<'a> {
+ while self.eatc(' ') || self.eatc('\t') {
+ // ...
+ }
+ Whitespace(&self.input[start..self.current()])
+ }
+
+ fn comment_token(&mut self, start: usize) -> Token<'a> {
+ while let Some((_, ch)) = self.chars.clone().next() {
+ if ch != '\t' && (ch < '\u{20}' || ch > '\u{10ffff}') {
+ break
+ }
+ self.chars.next();
+ }
+ Comment(&self.input[start..self.current()])
+ }
+
+ fn read_string(&mut self,
+ delim: char,
+ start: usize,
+ new_ch: &mut FnMut(&mut Tokenizer, &mut MaybeString,
+ bool, usize, char)
+ -> Result<(), Error>)
+ -> Result<Token<'a>, Error> {
+ let mut multiline = false;
+ if self.eatc(delim) {
+ if self.eatc(delim) {
+ multiline = true;
+ } else {
+ return Ok(String {
+ src: &self.input[start..start+2],
+ val: Cow::Borrowed(""),
+ })
+ }
+ }
+ let mut val = MaybeString::NotEscaped(self.current());
+ let mut n = 0;
+ 'outer: loop {
+ n += 1;
+ match self.chars.next() {
+ Some((i, '\n')) => {
+ if multiline {
+ if self.input.as_bytes()[i] == b'\r' {
+ val.to_owned(&self.input[..i]);
+ }
+ if n == 1 {
+ val = MaybeString::NotEscaped(self.current());
+ } else {
+ val.push('\n');
+ }
+ continue
+ } else {
+ return Err(Error::NewlineInString(i))
+ }
+ }
+ Some((i, ch)) if ch == delim => {
+ if multiline {
+ for _ in 0..2 {
+ if !self.eatc(delim) {
+ val.push(delim);
+ continue 'outer
+ }
+ }
+ }
+ return Ok(String {
+ src: &self.input[start..self.current()],
+ val: val.into_cow(&self.input[..i]),
+ })
+ }
+ Some((i, c)) => try!(new_ch(self, &mut val, multiline, i, c)),
+ None => return Err(Error::UnterminatedString(start))
+ }
+ }
+ }
+
+ fn literal_string(&mut self, start: usize) -> Result<Token<'a>, Error> {
+ self.read_string('\'', start, &mut |_me, val, _multi, i, ch| {
+ if ch == '\u{09}' || ('\u{20}' <= ch && ch <= '\u{10ffff}') {
+ val.push(ch);
+ Ok(())
+ } else {
+ Err(Error::InvalidCharInString(i, ch))
+ }
+ })
+ }
+
+ fn basic_string(&mut self, start: usize) -> Result<Token<'a>, Error> {
+ self.read_string('"', start, &mut |me, val, multi, i, ch| {
+ match ch {
+ '\\' => {
+ val.to_owned(&me.input[..i]);
+ match me.chars.next() {
+ Some((_, '"')) => val.push('"'),
+ Some((_, '\\')) => val.push('\\'),
+ Some((_, 'b')) => val.push('\u{8}'),
+ Some((_, 'f')) => val.push('\u{c}'),
+ Some((_, 'n')) => val.push('\n'),
+ Some((_, 'r')) => val.push('\r'),
+ Some((_, 't')) => val.push('\t'),
+ Some((i, c @ 'u')) |
+ Some((i, c @ 'U')) => {
+ let len = if c == 'u' {4} else {8};
+ val.push(try!(me.hex(start, i, len)));
+ }
+ Some((_, '\n')) if multi => {
+ while let Some((_, ch)) = me.chars.clone().next() {
+ match ch {
+ ' ' | '\t' | '\n' => {
+ me.chars.next();
+ }
+ _ => break,
+ }
+ }
+ }
+ Some((i, c)) => return Err(Error::InvalidEscape(i, c)),
+ None => return Err(Error::UnterminatedString(start)),
+ }
+ Ok(())
+ }
+ ch if '\u{20}' <= ch && ch <= '\u{10ffff}' => {
+ val.push(ch);
+ Ok(())
+ }
+ _ => Err(Error::InvalidCharInString(i, ch))
+ }
+ })
+ }
+
+ fn hex(&mut self, start: usize, i: usize, len: usize) -> Result<char, Error> {
+ let mut val = 0;
+ for _ in 0..len {
+ match self.chars.next() {
+ Some((_, ch)) if '0' <= ch && ch <= '9' => {
+ val = val * 16 + (ch as u32 - '0' as u32);
+ }
+ Some((_, ch)) if 'A' <= ch && ch <= 'F' => {
+ val = val * 16 + (ch as u32 - 'A' as u32) + 10;
+ }
+ Some((i, ch)) => return Err(Error::InvalidHexEscape(i, ch)),
+ None => return Err(Error::UnterminatedString(start)),
+ }
+ }
+ match char::from_u32(val) {
+ Some(ch) => Ok(ch),
+ None => Err(Error::InvalidEscapeValue(i, val)),
+ }
+ }
+
+ fn keylike(&mut self, start: usize) -> Token<'a> {
+ while let Some((_, ch)) = self.chars.clone().next() {
+ if !is_keylike(ch) {
+ break
+ }
+ self.chars.next();
+ }
+ Keylike(&self.input[start..self.current()])
+ }
+
+ pub fn substr_offset(&self, s: &'a str) -> usize {
+ assert!(s.len() <= self.input.len());
+ let a = self.input.as_ptr() as usize;
+ let b = s.as_ptr() as usize;
+ assert!(a <= b);
+ b - a
+ }
+}
+
+impl<'a> Iterator for CrlfFold<'a> {
+ type Item = (usize, char);
+
+ fn next(&mut self) -> Option<(usize, char)> {
+ self.chars.next().map(|(i, c)| {
+ if c == '\r' {
+ let mut attempt = self.chars.clone();
+ if let Some((_, '\n')) = attempt.next() {
+ self.chars = attempt;
+ return (i, '\n')
+ }
+ }
+ (i, c)
+ })
+ }
+}
+
+impl MaybeString {
+ fn push(&mut self, ch: char) {
+ match *self {
+ MaybeString::NotEscaped(..) => {}
+ MaybeString::Owned(ref mut s) => s.push(ch),
+ }
+ }
+
+ fn to_owned(&mut self, input: &str) {
+ match *self {
+ MaybeString::NotEscaped(start) => {
+ *self = MaybeString::Owned(input[start..].to_owned());
+ }
+ MaybeString::Owned(..) => {}
+ }
+ }
+
+ fn into_cow(self, input: &str) -> Cow<str> {
+ match self {
+ MaybeString::NotEscaped(start) => Cow::Borrowed(&input[start..]),
+ MaybeString::Owned(s) => Cow::Owned(s),
+ }
+ }
+}
+
+fn is_keylike(ch: char) -> bool {
+ ('A' <= ch && ch <= 'Z') ||
+ ('a' <= ch && ch <= 'z') ||
+ ('0' <= ch && ch <= '9') ||
+ ch == '-' ||
+ ch == '_'
+}
+
+impl<'a> Token<'a> {
+ pub fn describe(&self) -> &'static str {
+ match *self {
+ Token::Keylike(_) => "an identifier",
+ Token::Equals => "an equals",
+ Token::Period => "a period",
+ Token::Comment(_) => "a comment",
+ Token::Newline => "a newline",
+ Token::Whitespace(_) => "whitespace",
+ Token::Comma => "a comma",
+ Token::RightBrace => "a right brace",
+ Token::LeftBrace => "a left brace",
+ Token::RightBracket => "a right bracket",
+ Token::LeftBracket => "a left bracket",
+ Token::String { .. } => "a string",
+ Token::Colon => "a colon",
+ Token::Plus => "a plus",
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use std::borrow::Cow;
+ use super::{Tokenizer, Token, Error};
+
+ fn err(input: &str, err: Error) {
+ let mut t = Tokenizer::new(input);
+ let token = t.next().unwrap_err();
+ assert_eq!(token, err);
+ assert!(t.next().unwrap().is_none());
+ }
+
+ #[test]
+ fn literal_strings() {
+ fn t(input: &str, val: &str) {
+ let mut t = Tokenizer::new(input);
+ let token = t.next().unwrap().unwrap();
+ assert_eq!(token, Token::String {
+ src: input,
+ val: Cow::Borrowed(val),
+ });
+ assert!(t.next().unwrap().is_none());
+ }
+
+ t("''", "");
+ t("''''''", "");
+ t("'''\n'''", "");
+ t("'a'", "a");
+ t("'\"a'", "\"a");
+ t("''''a'''", "'a");
+ t("'''\n'a\n'''", "'a\n");
+ t("'''a\n'a\r\n'''", "a\n'a\n");
+ }
+
+ #[test]
+ fn basic_strings() {
+ fn t(input: &str, val: &str) {
+ let mut t = Tokenizer::new(input);
+ let token = t.next().unwrap().unwrap();
+ assert_eq!(token, Token::String {
+ src: input,
+ val: Cow::Borrowed(val),
+ });
+ assert!(t.next().unwrap().is_none());
+ }
+
+ t(r#""""#, "");
+ t(r#""""""""#, "");
+ t(r#""a""#, "a");
+ t(r#""""a""""#, "a");
+ t(r#""\t""#, "\t");
+ t(r#""\u0000""#, "\0");
+ t(r#""\U00000000""#, "\0");
+ t(r#""\U000A0000""#, "\u{A0000}");
+ t(r#""\\t""#, "\\t");
+ t("\"\"\"\\\n\"\"\"", "");
+ t("\"\"\"\\\n \t \t \\\r\n \t \n \t \r\n\"\"\"", "");
+ t(r#""\r""#, "\r");
+ t(r#""\n""#, "\n");
+ t(r#""\b""#, "\u{8}");
+ t(r#""a\fa""#, "a\u{c}a");
+ t(r#""\"a""#, "\"a");
+ t("\"\"\"\na\"\"\"", "a");
+ t("\"\"\"\n\"\"\"", "");
+ err(r#""\a"#, Error::InvalidEscape(2, 'a'));
+ err("\"\\\n", Error::InvalidEscape(2, '\n'));
+ err("\"\\\r\n", Error::InvalidEscape(2, '\n'));
+ err("\"\\", Error::UnterminatedString(0));
+ err("\"\u{0}", Error::InvalidCharInString(1, '\u{0}'));
+ err(r#""\U00""#, Error::InvalidHexEscape(5, '"'));
+ err(r#""\U00"#, Error::UnterminatedString(0));
+ err(r#""\uD800"#, Error::InvalidEscapeValue(2, 0xd800));
+ err(r#""\UFFFFFFFF"#, Error::InvalidEscapeValue(2, 0xffffffff));
+ }
+
+ #[test]
+ fn keylike() {
+ fn t(input: &str) {
+ let mut t = Tokenizer::new(input);
+ let token = t.next().unwrap().unwrap();
+ assert_eq!(token, Token::Keylike(input));
+ assert!(t.next().unwrap().is_none());
+ }
+ t("foo");
+ t("0bar");
+ t("bar0");
+ t("1234");
+ t("a-b");
+ t("a_B");
+ t("-_-");
+ t("___");
+ }
+
+ #[test]
+ fn all() {
+ fn t(input: &str, expected: &[Token]) {
+ let mut tokens = Tokenizer::new(input);
+ let mut actual = Vec::new();
+ while let Some(token) = tokens.next().unwrap() {
+ actual.push(token);
+ }
+ for (a, b) in actual.iter().zip(expected) {
+ assert_eq!(a, b);
+ }
+ assert_eq!(actual.len(), expected.len());
+ }
+
+ t(" a ", &[
+ Token::Whitespace(" "),
+ Token::Keylike("a"),
+ Token::Whitespace(" "),
+ ]);
+
+ t(" a\t [[]] \t [] {} , . =\n# foo \r\n#foo \n ", &[
+ Token::Whitespace(" "),
+ Token::Keylike("a"),
+ Token::Whitespace("\t "),
+ Token::LeftBracket,
+ Token::LeftBracket,
+ Token::RightBracket,
+ Token::RightBracket,
+ Token::Whitespace(" \t "),
+ Token::LeftBracket,
+ Token::RightBracket,
+ Token::Whitespace(" "),
+ Token::LeftBrace,
+ Token::RightBrace,
+ Token::Whitespace(" "),
+ Token::Comma,
+ Token::Whitespace(" "),
+ Token::Period,
+ Token::Whitespace(" "),
+ Token::Equals,
+ Token::Newline,
+ Token::Comment("# foo "),
+ Token::Newline,
+ Token::Comment("#foo "),
+ Token::Newline,
+ Token::Whitespace(" "),
+ ]);
+ }
+
+ #[test]
+ fn bare_cr_bad() {
+ err("\r", Error::Unexpected(0, '\r'));
+ err("'\n", Error::NewlineInString(1));
+ err("'\u{0}", Error::InvalidCharInString(1, '\u{0}'));
+ err("'", Error::UnterminatedString(0));
+ err("\u{0}", Error::Unexpected(0, '\u{0}'));
+ }
+
+ #[test]
+ fn bad_comment() {
+ let mut t = Tokenizer::new("#\u{0}");
+ t.next().unwrap().unwrap();
+ assert_eq!(t.next(), Err(Error::Unexpected(1, '\u{0}')));
+ assert!(t.next().unwrap().is_none());
+ }
+}
diff --git a/third_party/rust/toml/src/value.rs b/third_party/rust/toml/src/value.rs
new file mode 100644
index 0000000000..056eac4f04
--- /dev/null
+++ b/third_party/rust/toml/src/value.rs
@@ -0,0 +1,946 @@
+//! Definition of a TOML value
+
+use std::collections::{BTreeMap, HashMap};
+use std::hash::Hash;
+use std::fmt;
+use std::ops;
+use std::str::FromStr;
+use std::vec;
+
+use serde::ser;
+use serde::de;
+use serde::de::IntoDeserializer;
+
+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<Value>;
+
+/// Type representing a TOML table, payload of the `Value::Table` variant
+pub type Table = BTreeMap<String, Value>;
+
+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<T>(value: T) -> Result<Value, ::ser::Error>
+ 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<T, ::de::Error>
+ 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<I: Index>(&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<I: Index>(&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<i64> {
+ 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<f64> {
+ 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<bool> {
+ 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<Value>> {
+ 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<Value>> {
+ 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<I> ops::Index<I> for Value where I: Index {
+ type Output = Value;
+
+ fn index(&self, index: I) -> &Value {
+ self.get(index).expect("index not found")
+ }
+}
+
+impl<I> ops::IndexMut<I> 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<V: Into<Value>> From<Vec<V>> for Value {
+ fn from(val: Vec<V>) -> Value {
+ Value::Array(val.into_iter().map(|v| v.into()).collect())
+ }
+}
+
+impl<S: Into<String>, V: Into<Value>> From<BTreeMap<S, V>> for Value {
+ fn from(val: BTreeMap<S, V>) -> Value {
+ let table = val.into_iter()
+ .map(|(s, v)| (s.into(), v.into()))
+ .collect();
+
+ Value::Table(table)
+ }
+}
+
+impl<S: Into<String> + Hash + Eq, V: Into<Value>> From<HashMap<S, V>> for Value {
+ fn from(val: HashMap<S, V>) -> 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);
+
+/// 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<Value, Self::Err> {
+ ::from_str(s)
+ }
+}
+
+impl ser::Serialize for Value {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ 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<D>(deserializer: D) -> Result<Value, D::Error>
+ 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<E>(self, value: bool) -> Result<Value, E> {
+ Ok(Value::Boolean(value))
+ }
+
+ fn visit_i64<E>(self, value: i64) -> Result<Value, E> {
+ Ok(Value::Integer(value))
+ }
+
+ fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
+ Ok(Value::Float(value))
+ }
+
+ fn visit_str<E>(self, value: &str) -> Result<Value, E> {
+ Ok(Value::String(value.into()))
+ }
+
+ fn visit_string<E>(self, value: String) -> Result<Value, E> {
+ Ok(Value::String(value))
+ }
+
+ fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
+ where D: de::Deserializer<'de>,
+ {
+ de::Deserialize::deserialize(deserializer)
+ }
+
+ fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error>
+ 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<V>(self, mut visitor: V) -> Result<Value, V::Error>
+ 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<V>(self, visitor: V) -> Result<V::Value, ::de::Error>
+ 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<V>(
+ self,
+ _name: &str,
+ _variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, ::de::Error>
+ 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<V>(self, visitor: V) -> Result<V::Value, ::de::Error>
+ where V: de::Visitor<'de>,
+ {
+ visitor.visit_some(self)
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ _name: &'static str,
+ visitor: V
+ ) -> Result<V::Value, ::de::Error>
+ where V: de::Visitor<'de>
+ {
+ visitor.visit_newtype_struct(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 identifier
+ }
+}
+
+struct SeqDeserializer {
+ iter: vec::IntoIter<Value>,
+}
+
+impl SeqDeserializer {
+ fn new(vec: Vec<Value>) -> Self {
+ SeqDeserializer {
+ iter: vec.into_iter(),
+ }
+ }
+}
+
+impl<'de> de::SeqAccess<'de> for SeqDeserializer {
+ type Error = ::de::Error;
+
+ fn next_element_seed<T>(&mut self, seed: T)
+ -> Result<Option<T::Value>, ::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<usize> {
+ match self.iter.size_hint() {
+ (lower, Some(upper)) if lower == upper => Some(upper),
+ _ => None,
+ }
+ }
+}
+
+struct MapDeserializer {
+ iter: <BTreeMap<String, Value> as IntoIterator>::IntoIter,
+ value: Option<(String, Value)>,
+}
+
+impl MapDeserializer {
+ fn new(map: BTreeMap<String, Value>) -> Self {
+ MapDeserializer {
+ iter: map.into_iter(),
+ value: None,
+ }
+ }
+}
+
+impl<'de> de::MapAccess<'de> for MapDeserializer {
+ type Error = ::de::Error;
+
+ fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, ::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<T>(&mut self, seed: T) -> Result<T::Value, ::de::Error>
+ 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<usize> {
+ match self.iter.size_hint() {
+ (lower, Some(upper)) if lower == upper => Some(upper),
+ _ => None,
+ }
+ }
+}
+
+impl<'de> de::IntoDeserializer<'de, ::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 = ::ser::Error;
+
+ type SerializeSeq = SerializeVec;
+ type SerializeTuple = ser::Impossible<Value, ::ser::Error>;
+ type SerializeTupleStruct = ser::Impossible<Value, ::ser::Error>;
+ type SerializeTupleVariant = ser::Impossible<Value, ::ser::Error>;
+ type SerializeMap = SerializeMap;
+ type SerializeStruct = SerializeMap;
+ type SerializeStructVariant = ser::Impossible<Value, ::ser::Error>;
+
+ fn serialize_bool(self, value: bool) -> Result<Value, ::ser::Error> {
+ Ok(Value::Boolean(value))
+ }
+
+ fn serialize_i8(self, value: i8) -> Result<Value, ::ser::Error> {
+ self.serialize_i64(value.into())
+ }
+
+ fn serialize_i16(self, value: i16) -> Result<Value, ::ser::Error> {
+ self.serialize_i64(value.into())
+ }
+
+ fn serialize_i32(self, value: i32) -> Result<Value, ::ser::Error> {
+ self.serialize_i64(value.into())
+ }
+
+ fn serialize_i64(self, value: i64) -> Result<Value, ::ser::Error> {
+ Ok(Value::Integer(value.into()))
+ }
+
+ fn serialize_u8(self, value: u8) -> Result<Value, ::ser::Error> {
+ self.serialize_i64(value.into())
+ }
+
+ fn serialize_u16(self, value: u16) -> Result<Value, ::ser::Error> {
+ self.serialize_i64(value.into())
+ }
+
+ fn serialize_u32(self, value: u32) -> Result<Value, ::ser::Error> {
+ self.serialize_i64(value.into())
+ }
+
+ fn serialize_u64(self, value: u64) -> Result<Value, ::ser::Error> {
+ 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<Value, ::ser::Error> {
+ self.serialize_f64(value.into())
+ }
+
+ fn serialize_f64(self, value: f64) -> Result<Value, ::ser::Error> {
+ Ok(Value::Float(value))
+ }
+
+ fn serialize_char(self, value: char) -> Result<Value, ::ser::Error> {
+ let mut s = String::new();
+ s.push(value);
+ self.serialize_str(&s)
+ }
+
+ fn serialize_str(self, value: &str) -> Result<Value, ::ser::Error> {
+ Ok(Value::String(value.to_owned()))
+ }
+
+ fn serialize_bytes(self, value: &[u8]) -> Result<Value, ::ser::Error> {
+ let vec = value.iter().map(|&b| Value::Integer(b.into())).collect();
+ Ok(Value::Array(vec))
+ }
+
+ fn serialize_unit(self) -> Result<Value, ::ser::Error> {
+ Err(::ser::Error::UnsupportedType)
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str)
+ -> Result<Value, ::ser::Error> {
+ Err(::ser::Error::UnsupportedType)
+ }
+
+ fn serialize_unit_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str)
+ -> Result<Value, ::ser::Error> {
+ self.serialize_str(_variant)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(self,
+ _name: &'static str,
+ value: &T)
+ -> Result<Value, ::ser::Error>
+ where T: ser::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _value: &T)
+ -> Result<Value, ::ser::Error>
+ where T: ser::Serialize,
+ {
+ Err(::ser::Error::UnsupportedType)
+ }
+
+ fn serialize_none(self) -> Result<Value, ::ser::Error> {
+ Err(::ser::Error::UnsupportedNone)
+ }
+
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, ::ser::Error>
+ where T: ser::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_seq(self, len: Option<usize>)
+ -> Result<Self::SerializeSeq, ::ser::Error>
+ {
+ Ok(SerializeVec {
+ vec: Vec::with_capacity(len.unwrap_or(0))
+ })
+ }
+
+ fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, ::ser::Error> {
+ Err(::ser::Error::UnsupportedType)
+ }
+
+ fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
+ -> Result<Self::SerializeTupleStruct, ::ser::Error> {
+ Err(::ser::Error::UnsupportedType)
+ }
+
+ fn serialize_tuple_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeTupleVariant, ::ser::Error>
+ {
+ Err(::ser::Error::UnsupportedType)
+ }
+
+ fn serialize_map(self, _len: Option<usize>)
+ -> Result<Self::SerializeMap, ::ser::Error>
+ {
+ Ok(SerializeMap {
+ map: BTreeMap::new(),
+ next_key: None,
+ })
+ }
+
+ fn serialize_struct(self, _name: &'static str, len: usize)
+ -> Result<Self::SerializeStruct, ::ser::Error> {
+ self.serialize_map(Some(len))
+ }
+
+ fn serialize_struct_variant(self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize)
+ -> Result<Self::SerializeStructVariant, ::ser::Error>
+ {
+ Err(::ser::Error::UnsupportedType)
+ }
+}
+
+struct SerializeVec {
+ vec: Vec<Value>,
+}
+
+struct SerializeMap {
+ map: BTreeMap<String, Value>,
+ next_key: Option<String>,
+}
+
+impl ser::SerializeSeq for SerializeVec {
+ type Ok = Value;
+ type Error = ::ser::Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), ::ser::Error>
+ where T: ser::Serialize
+ {
+ self.vec.push(Value::try_from(value)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value, ::ser::Error> {
+ Ok(Value::Array(self.vec))
+ }
+}
+
+impl ser::SerializeMap for SerializeMap {
+ type Ok = Value;
+ type Error = ::ser::Error;
+
+ fn serialize_key<T: ?Sized>(&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<T: ?Sized>(&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<Value, ::ser::Error> {
+ Ok(Value::Table(self.map))
+ }
+}
+
+impl ser::SerializeStruct for SerializeMap {
+ type Ok = Value;
+ type Error = ::ser::Error;
+
+ fn serialize_field<T: ?Sized>(&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<Value, ::ser::Error> {
+ 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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ 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<E>(self, s: &str) -> Result<bool, E>
+ where E: de::Error,
+ {
+ if s == SERDE_STRUCT_FIELD_NAME {
+ Ok(true)
+ } else {
+ self.key.push_str(s);
+ Ok(false)
+ }
+ }
+
+ fn visit_string<E>(self, s: String) -> Result<bool, E>
+ where E: de::Error,
+ {
+ if s == SERDE_STRUCT_FIELD_NAME {
+ Ok(true)
+ } else {
+ *self.key = s;
+ Ok(false)
+ }
+ }
+}