summaryrefslogtreecommitdiffstats
path: root/vendor/toml_edit-0.19.11/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/toml_edit-0.19.11/src')
-rw-r--r--vendor/toml_edit-0.19.11/src/array.rs389
-rw-r--r--vendor/toml_edit-0.19.11/src/array_of_tables.rs152
-rw-r--r--vendor/toml_edit-0.19.11/src/de/array.rs97
-rw-r--r--vendor/toml_edit-0.19.11/src/de/datetime.rs43
-rw-r--r--vendor/toml_edit-0.19.11/src/de/key.rs140
-rw-r--r--vendor/toml_edit-0.19.11/src/de/mod.rs289
-rw-r--r--vendor/toml_edit-0.19.11/src/de/spanned.rs70
-rw-r--r--vendor/toml_edit-0.19.11/src/de/table.rs213
-rw-r--r--vendor/toml_edit-0.19.11/src/de/table_enum.rs160
-rw-r--r--vendor/toml_edit-0.19.11/src/de/value.rs252
-rw-r--r--vendor/toml_edit-0.19.11/src/document.rs113
-rw-r--r--vendor/toml_edit-0.19.11/src/encode.rs569
-rw-r--r--vendor/toml_edit-0.19.11/src/index.rs156
-rw-r--r--vendor/toml_edit-0.19.11/src/inline_table.rs661
-rw-r--r--vendor/toml_edit-0.19.11/src/internal_string.rs183
-rw-r--r--vendor/toml_edit-0.19.11/src/item.rs381
-rw-r--r--vendor/toml_edit-0.19.11/src/key.rs333
-rw-r--r--vendor/toml_edit-0.19.11/src/lib.rs124
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/array.rs147
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/datetime.rs433
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/document.rs148
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/errors.rs476
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/inline_table.rs182
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/key.rs104
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/macros.rs13
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/mod.rs302
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/numbers.rs369
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/state.rs323
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/strings.rs464
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/table.rs89
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/trivia.rs158
-rw-r--r--vendor/toml_edit-0.19.11/src/parser/value.rs157
-rw-r--r--vendor/toml_edit-0.19.11/src/raw_string.rs182
-rw-r--r--vendor/toml_edit-0.19.11/src/repr.rs253
-rw-r--r--vendor/toml_edit-0.19.11/src/ser/array.rs84
-rw-r--r--vendor/toml_edit-0.19.11/src/ser/key.rs173
-rw-r--r--vendor/toml_edit-0.19.11/src/ser/map.rs405
-rw-r--r--vendor/toml_edit-0.19.11/src/ser/mod.rs165
-rw-r--r--vendor/toml_edit-0.19.11/src/ser/pretty.rs45
-rw-r--r--vendor/toml_edit-0.19.11/src/ser/value.rs243
-rw-r--r--vendor/toml_edit-0.19.11/src/table.rs743
-rw-r--r--vendor/toml_edit-0.19.11/src/value.rs372
-rw-r--r--vendor/toml_edit-0.19.11/src/visit.rs236
-rw-r--r--vendor/toml_edit-0.19.11/src/visit_mut.rs252
44 files changed, 10843 insertions, 0 deletions
diff --git a/vendor/toml_edit-0.19.11/src/array.rs b/vendor/toml_edit-0.19.11/src/array.rs
new file mode 100644
index 000000000..68cb4467a
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/array.rs
@@ -0,0 +1,389 @@
+use std::iter::FromIterator;
+use std::mem;
+
+use crate::repr::Decor;
+use crate::value::{DEFAULT_LEADING_VALUE_DECOR, DEFAULT_VALUE_DECOR};
+use crate::{Item, RawString, Value};
+
+/// Type representing a TOML array,
+/// payload of the `Value::Array` variant's value
+#[derive(Debug, Default, Clone)]
+pub struct Array {
+ // `trailing` represents whitespaces, newlines
+ // and comments in an empty array or after the trailing comma
+ trailing: RawString,
+ trailing_comma: bool,
+ // prefix before `[` and suffix after `]`
+ decor: Decor,
+ pub(crate) span: Option<std::ops::Range<usize>>,
+ // always Vec<Item::Value>
+ pub(crate) values: Vec<Item>,
+}
+
+/// An owned iterator type over `Table`'s key/value pairs.
+pub type ArrayIntoIter = Box<dyn Iterator<Item = Value>>;
+/// An iterator type over `Array`'s values.
+pub type ArrayIter<'a> = Box<dyn Iterator<Item = &'a Value> + 'a>;
+/// An iterator type over `Array`'s values.
+pub type ArrayIterMut<'a> = Box<dyn Iterator<Item = &'a mut Value> + 'a>;
+
+/// Constructors
+///
+/// See also `FromIterator`
+impl Array {
+ /// Create an empty `Array`
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// ```
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub(crate) fn with_vec(values: Vec<Item>) -> Self {
+ Self {
+ values,
+ ..Default::default()
+ }
+ }
+}
+
+/// Formatting
+impl Array {
+ /// Auto formats the array.
+ pub fn fmt(&mut self) {
+ decorate_array(self);
+ }
+
+ /// Set whether the array will use a trailing comma
+ pub fn set_trailing_comma(&mut self, yes: bool) {
+ self.trailing_comma = yes;
+ }
+
+ /// Whether the array will use a trailing comma
+ pub fn trailing_comma(&self) -> bool {
+ self.trailing_comma
+ }
+
+ /// Set whitespace after last element
+ pub fn set_trailing(&mut self, trailing: impl Into<RawString>) {
+ self.trailing = trailing.into();
+ }
+
+ /// Whitespace after last element
+ pub fn trailing(&self) -> &RawString {
+ &self.trailing
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ &mut self.decor
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor(&self) -> &Decor {
+ &self.decor
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.span.clone()
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.span = None;
+ self.decor.despan(input);
+ self.trailing.despan(input);
+ for value in &mut self.values {
+ value.despan(input);
+ }
+ }
+}
+
+impl Array {
+ /// Returns an iterator over all values.
+ pub fn iter(&self) -> ArrayIter<'_> {
+ Box::new(self.values.iter().filter_map(Item::as_value))
+ }
+
+ /// Returns an iterator over all values.
+ pub fn iter_mut(&mut self) -> ArrayIterMut<'_> {
+ Box::new(self.values.iter_mut().filter_map(Item::as_value_mut))
+ }
+
+ /// Returns the length of the underlying Vec.
+ ///
+ /// In some rare cases, placeholder elements will exist. For a more accurate count, call
+ /// `a.iter().count()`
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ /// assert_eq!(arr.len(), 2);
+ /// ```
+ pub fn len(&self) -> usize {
+ self.values.len()
+ }
+
+ /// Return true iff `self.len() == 0`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// assert!(arr.is_empty());
+ ///
+ /// arr.push(1);
+ /// arr.push("foo");
+ /// assert!(! arr.is_empty());
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ /// Clears the array, removing all values. Keeps the allocated memory for reuse.
+ pub fn clear(&mut self) {
+ self.values.clear()
+ }
+
+ /// Returns a reference to the value at the given index, or `None` if the index is out of
+ /// bounds.
+ pub fn get(&self, index: usize) -> Option<&Value> {
+ self.values.get(index).and_then(Item::as_value)
+ }
+
+ /// Returns a reference to the value at the given index, or `None` if the index is out of
+ /// bounds.
+ pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
+ self.values.get_mut(index).and_then(Item::as_value_mut)
+ }
+
+ /// Appends a new value to the end of the array, applying default formatting to it.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ /// ```
+ pub fn push<V: Into<Value>>(&mut self, v: V) {
+ self.value_op(v.into(), true, |items, value| {
+ items.push(Item::Value(value))
+ })
+ }
+
+ /// Appends a new, already formatted value to the end of the array.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let formatted_value = "'literal'".parse::<toml_edit::Value>().unwrap();
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push_formatted(formatted_value);
+ /// ```
+ pub fn push_formatted(&mut self, v: Value) {
+ self.values.push(Item::Value(v));
+ }
+
+ /// Inserts an element at the given position within the array, applying default formatting to
+ /// it and shifting all values after it to the right.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index > len`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ ///
+ /// arr.insert(0, "start");
+ /// ```
+ pub fn insert<V: Into<Value>>(&mut self, index: usize, v: V) {
+ self.value_op(v.into(), true, |items, value| {
+ items.insert(index, Item::Value(value))
+ })
+ }
+
+ /// Inserts an already formatted value at the given position within the array, shifting all
+ /// values after it to the right.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index > len`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ ///
+ /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap();
+ /// arr.insert_formatted(0, formatted_value);
+ /// ```
+ pub fn insert_formatted(&mut self, index: usize, v: Value) {
+ self.values.insert(index, Item::Value(v))
+ }
+
+ /// Replaces the element at the given position within the array, preserving existing formatting.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index >= len`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ ///
+ /// arr.replace(0, "start");
+ /// ```
+ pub fn replace<V: Into<Value>>(&mut self, index: usize, v: V) -> Value {
+ // Read the existing value's decor and preserve it.
+ let existing_decor = self
+ .get(index)
+ .unwrap_or_else(|| panic!("index {} out of bounds (len = {})", index, self.len()))
+ .decor();
+ let mut value = v.into();
+ *value.decor_mut() = existing_decor.clone();
+ self.replace_formatted(index, value)
+ }
+
+ /// Replaces the element at the given position within the array with an already formatted value.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index >= len`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ ///
+ /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap();
+ /// arr.replace_formatted(0, formatted_value);
+ /// ```
+ pub fn replace_formatted(&mut self, index: usize, v: Value) -> Value {
+ match mem::replace(&mut self.values[index], Item::Value(v)) {
+ Item::Value(old_value) => old_value,
+ x => panic!("non-value item {:?} in an array", x),
+ }
+ }
+
+ /// Removes the value at the given index.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// let mut arr = toml_edit::Array::new();
+ /// arr.push(1);
+ /// arr.push("foo");
+ ///
+ /// arr.remove(0);
+ /// assert_eq!(arr.len(), 1);
+ /// ```
+ pub fn remove(&mut self, index: usize) -> Value {
+ let removed = self.values.remove(index);
+ match removed {
+ Item::Value(v) => v,
+ x => panic!("non-value item {:?} in an array", x),
+ }
+ }
+
+ fn value_op<T>(
+ &mut self,
+ v: Value,
+ decorate: bool,
+ op: impl FnOnce(&mut Vec<Item>, Value) -> T,
+ ) -> T {
+ let mut value = v;
+ if !self.is_empty() && decorate {
+ value.decorate(" ", "");
+ } else if decorate {
+ value.decorate("", "");
+ }
+ op(&mut self.values, value)
+ }
+}
+
+impl std::fmt::Display for Array {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ crate::encode::Encode::encode(self, f, None, ("", ""))
+ }
+}
+
+impl<V: Into<Value>> Extend<V> for Array {
+ fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
+ for value in iter {
+ self.push_formatted(value.into());
+ }
+ }
+}
+
+impl<V: Into<Value>> FromIterator<V> for Array {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = V>,
+ {
+ let v = iter.into_iter().map(|a| Item::Value(a.into()));
+ Array {
+ values: v.collect(),
+ ..Default::default()
+ }
+ }
+}
+
+impl IntoIterator for Array {
+ type Item = Value;
+ type IntoIter = ArrayIntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Box::new(
+ self.values
+ .into_iter()
+ .filter(|v| v.is_value())
+ .map(|v| v.into_value().unwrap()),
+ )
+ }
+}
+
+impl<'s> IntoIterator for &'s Array {
+ type Item = &'s Value;
+ type IntoIter = ArrayIter<'s>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+fn decorate_array(array: &mut Array) {
+ for (i, value) in array
+ .values
+ .iter_mut()
+ .filter_map(Item::as_value_mut)
+ .enumerate()
+ {
+ // [value1, value2, value3]
+ if i == 0 {
+ value.decorate(DEFAULT_LEADING_VALUE_DECOR.0, DEFAULT_LEADING_VALUE_DECOR.1);
+ } else {
+ value.decorate(DEFAULT_VALUE_DECOR.0, DEFAULT_VALUE_DECOR.1);
+ }
+ }
+ // Since everything is now on the same line, remove trailing commas and whitespace.
+ array.set_trailing_comma(false);
+ array.set_trailing("");
+}
diff --git a/vendor/toml_edit-0.19.11/src/array_of_tables.rs b/vendor/toml_edit-0.19.11/src/array_of_tables.rs
new file mode 100644
index 000000000..461a716c2
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/array_of_tables.rs
@@ -0,0 +1,152 @@
+use std::iter::FromIterator;
+
+use crate::{Array, Item, Table};
+
+/// Type representing a TOML array of tables
+#[derive(Clone, Debug, Default)]
+pub struct ArrayOfTables {
+ // Always Vec<Item::Table>, just `Item` to make `Index` work
+ pub(crate) span: Option<std::ops::Range<usize>>,
+ pub(crate) values: Vec<Item>,
+}
+
+/// Constructors
+///
+/// See also `FromIterator`
+impl ArrayOfTables {
+ /// Creates an empty array of tables.
+ pub fn new() -> Self {
+ Default::default()
+ }
+}
+
+/// Formatting
+impl ArrayOfTables {
+ /// Convert to an inline array
+ pub fn into_array(mut self) -> Array {
+ for value in self.values.iter_mut() {
+ value.make_value();
+ }
+ let mut a = Array::with_vec(self.values);
+ a.fmt();
+ a
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.span.clone()
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.span = None;
+ for value in &mut self.values {
+ value.despan(input);
+ }
+ }
+}
+
+impl ArrayOfTables {
+ /// Returns an iterator over tables.
+ pub fn iter(&self) -> ArrayOfTablesIter<'_> {
+ Box::new(self.values.iter().filter_map(Item::as_table))
+ }
+
+ /// Returns an iterator over tables.
+ pub fn iter_mut(&mut self) -> ArrayOfTablesIterMut<'_> {
+ Box::new(self.values.iter_mut().filter_map(Item::as_table_mut))
+ }
+
+ /// Returns the length of the underlying Vec.
+ /// To get the actual number of items use `a.iter().count()`.
+ pub fn len(&self) -> usize {
+ self.values.len()
+ }
+
+ /// Returns true iff `self.len() == 0`.
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ /// Removes all the tables.
+ pub fn clear(&mut self) {
+ self.values.clear()
+ }
+
+ /// Returns an optional reference to the table.
+ pub fn get(&self, index: usize) -> Option<&Table> {
+ self.values.get(index).and_then(Item::as_table)
+ }
+
+ /// Returns an optional mutable reference to the table.
+ pub fn get_mut(&mut self, index: usize) -> Option<&mut Table> {
+ self.values.get_mut(index).and_then(Item::as_table_mut)
+ }
+
+ /// Appends a table to the array.
+ pub fn push(&mut self, table: Table) {
+ self.values.push(Item::Table(table));
+ }
+
+ /// Removes a table with the given index.
+ pub fn remove(&mut self, index: usize) {
+ self.values.remove(index);
+ }
+}
+
+/// An iterator type over `ArrayOfTables`'s values.
+pub type ArrayOfTablesIter<'a> = Box<dyn Iterator<Item = &'a Table> + 'a>;
+/// An iterator type over `ArrayOfTables`'s values.
+pub type ArrayOfTablesIterMut<'a> = Box<dyn Iterator<Item = &'a mut Table> + 'a>;
+/// An iterator type over `ArrayOfTables`'s values.
+pub type ArrayOfTablesIntoIter = Box<dyn Iterator<Item = Table>>;
+
+impl Extend<Table> for ArrayOfTables {
+ fn extend<T: IntoIterator<Item = Table>>(&mut self, iter: T) {
+ for value in iter {
+ self.push(value);
+ }
+ }
+}
+
+impl FromIterator<Table> for ArrayOfTables {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = Table>,
+ {
+ let v = iter.into_iter().map(Item::Table);
+ ArrayOfTables {
+ values: v.collect(),
+ span: None,
+ }
+ }
+}
+
+impl IntoIterator for ArrayOfTables {
+ type Item = Table;
+ type IntoIter = ArrayOfTablesIntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Box::new(
+ self.values
+ .into_iter()
+ .filter(|v| v.is_table())
+ .map(|v| v.into_table().unwrap()),
+ )
+ }
+}
+
+impl<'s> IntoIterator for &'s ArrayOfTables {
+ type Item = &'s Table;
+ type IntoIter = ArrayOfTablesIter<'s>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl std::fmt::Display for ArrayOfTables {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ // HACK: Without the header, we don't really have a proper way of printing this
+ self.clone().into_array().fmt(f)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/array.rs b/vendor/toml_edit-0.19.11/src/de/array.rs
new file mode 100644
index 000000000..adc54016b
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/array.rs
@@ -0,0 +1,97 @@
+use crate::de::Error;
+
+pub(crate) struct ArrayDeserializer {
+ input: Vec<crate::Item>,
+ span: Option<std::ops::Range<usize>>,
+}
+
+impl ArrayDeserializer {
+ pub(crate) fn new(input: Vec<crate::Item>, span: Option<std::ops::Range<usize>>) -> Self {
+ Self { input, span }
+ }
+}
+
+// Note: this is wrapped by `ValueDeserializer` and any trait methods
+// implemented here need to be wrapped there
+impl<'de> serde::Deserializer<'de> for ArrayDeserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ visitor.visit_seq(ArraySeqAccess::new(self.input))
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ if serde_spanned::__unstable::is_spanned(name, fields) {
+ if let Some(span) = self.span.clone() {
+ return visitor.visit_map(super::SpannedDeserializer::new(self, span));
+ }
+ }
+
+ self.deserialize_any(visitor)
+ }
+
+ serde::forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map option unit newtype_struct
+ ignored_any unit_struct tuple_struct tuple enum identifier
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for ArrayDeserializer {
+ type Deserializer = Self;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
+impl crate::Array {
+ pub(crate) fn into_deserializer(self) -> ArrayDeserializer {
+ ArrayDeserializer::new(self.values, self.span)
+ }
+}
+
+impl crate::ArrayOfTables {
+ pub(crate) fn into_deserializer(self) -> ArrayDeserializer {
+ ArrayDeserializer::new(self.values, self.span)
+ }
+}
+
+pub(crate) struct ArraySeqAccess {
+ iter: std::vec::IntoIter<crate::Item>,
+}
+
+impl ArraySeqAccess {
+ pub(crate) fn new(input: Vec<crate::Item>) -> Self {
+ Self {
+ iter: input.into_iter(),
+ }
+ }
+}
+
+impl<'de> serde::de::SeqAccess<'de> for ArraySeqAccess {
+ type Error = Error;
+
+ fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ match self.iter.next() {
+ Some(v) => seed
+ .deserialize(crate::de::ValueDeserializer::new(v))
+ .map(Some),
+ None => Ok(None),
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/datetime.rs b/vendor/toml_edit-0.19.11/src/de/datetime.rs
new file mode 100644
index 000000000..14de28b3f
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/datetime.rs
@@ -0,0 +1,43 @@
+use serde::de::value::BorrowedStrDeserializer;
+use serde::de::IntoDeserializer;
+
+use crate::de::Error;
+
+pub(crate) struct DatetimeDeserializer {
+ date: Option<crate::Datetime>,
+}
+
+impl DatetimeDeserializer {
+ pub(crate) fn new(date: crate::Datetime) -> Self {
+ Self { date: Some(date) }
+ }
+}
+
+impl<'de> serde::de::MapAccess<'de> for DatetimeDeserializer {
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
+ where
+ K: serde::de::DeserializeSeed<'de>,
+ {
+ if self.date.is_some() {
+ seed.deserialize(BorrowedStrDeserializer::new(
+ toml_datetime::__unstable::FIELD,
+ ))
+ .map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
+ where
+ V: serde::de::DeserializeSeed<'de>,
+ {
+ if let Some(date) = self.date.take() {
+ seed.deserialize(date.to_string().into_deserializer())
+ } else {
+ panic!("next_value_seed called before next_key_seed")
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/key.rs b/vendor/toml_edit-0.19.11/src/de/key.rs
new file mode 100644
index 000000000..3da41df41
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/key.rs
@@ -0,0 +1,140 @@
+use serde::de::IntoDeserializer;
+
+use super::Error;
+
+pub(crate) struct KeyDeserializer {
+ span: Option<std::ops::Range<usize>>,
+ key: crate::InternalString,
+}
+
+impl KeyDeserializer {
+ pub(crate) fn new(key: crate::InternalString, span: Option<std::ops::Range<usize>>) -> Self {
+ KeyDeserializer { span, key }
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, Error> for KeyDeserializer {
+ type Deserializer = Self;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
+impl<'de> serde::de::Deserializer<'de> for KeyDeserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ self.key.into_deserializer().deserialize_any(visitor)
+ }
+
+ fn deserialize_enum<V>(
+ self,
+ name: &str,
+ variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let _ = name;
+ let _ = variants;
+ visitor.visit_enum(self)
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ if serde_spanned::__unstable::is_spanned(name, fields) {
+ if let Some(span) = self.span.clone() {
+ return visitor.visit_map(super::SpannedDeserializer::new(self.key.as_str(), span));
+ }
+ }
+ self.deserialize_any(visitor)
+ }
+
+ serde::forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map option unit newtype_struct
+ ignored_any unit_struct tuple_struct tuple identifier
+ }
+}
+
+impl<'de> serde::de::EnumAccess<'de> for KeyDeserializer {
+ type Error = super::Error;
+ type Variant = UnitOnly<Self::Error>;
+
+ fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ seed.deserialize(self).map(unit_only)
+ }
+}
+
+pub(crate) struct UnitOnly<E> {
+ marker: std::marker::PhantomData<E>,
+}
+
+fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
+ (
+ t,
+ UnitOnly {
+ marker: std::marker::PhantomData,
+ },
+ )
+}
+
+impl<'de, E> serde::de::VariantAccess<'de> for UnitOnly<E>
+where
+ E: serde::de::Error,
+{
+ type Error = E;
+
+ fn unit_variant(self) -> Result<(), Self::Error> {
+ Ok(())
+ }
+
+ fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::UnitVariant,
+ &"newtype variant",
+ ))
+ }
+
+ fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::UnitVariant,
+ &"tuple variant",
+ ))
+ }
+
+ fn struct_variant<V>(
+ self,
+ _fields: &'static [&'static str],
+ _visitor: V,
+ ) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::UnitVariant,
+ &"struct variant",
+ ))
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/mod.rs b/vendor/toml_edit-0.19.11/src/de/mod.rs
new file mode 100644
index 000000000..09ea12096
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/mod.rs
@@ -0,0 +1,289 @@
+//! Deserializing TOML into Rust structures.
+//!
+//! This module contains all the Serde support for deserializing TOML documents into Rust structures.
+
+use serde::de::DeserializeOwned;
+
+mod array;
+mod datetime;
+mod key;
+mod spanned;
+mod table;
+mod table_enum;
+mod value;
+
+use array::ArrayDeserializer;
+use datetime::DatetimeDeserializer;
+use key::KeyDeserializer;
+use spanned::SpannedDeserializer;
+use table::TableMapAccess;
+use table_enum::TableEnumDeserializer;
+
+pub use value::ValueDeserializer;
+
+/// Errors that can occur when deserializing a type.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Error {
+ inner: crate::TomlError,
+}
+
+impl Error {
+ pub(crate) fn custom<T>(msg: T, span: Option<std::ops::Range<usize>>) -> Self
+ where
+ T: std::fmt::Display,
+ {
+ Error {
+ inner: crate::TomlError::custom(msg.to_string(), span),
+ }
+ }
+
+ /// Add key while unwinding
+ pub fn add_key(&mut self, key: String) {
+ self.inner.add_key(key)
+ }
+
+ /// What went wrong
+ pub fn message(&self) -> &str {
+ self.inner.message()
+ }
+
+ /// The start/end index into the original document where the error occurred
+ pub fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.inner.span()
+ }
+
+ pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) {
+ self.inner.set_span(span);
+ }
+}
+
+impl serde::de::Error for Error {
+ fn custom<T>(msg: T) -> Self
+ where
+ T: std::fmt::Display,
+ {
+ Error::custom(msg, None)
+ }
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ self.inner.fmt(f)
+ }
+}
+
+impl From<crate::TomlError> for Error {
+ fn from(e: crate::TomlError) -> Error {
+ Self { inner: e }
+ }
+}
+
+impl From<Error> for crate::TomlError {
+ fn from(e: Error) -> crate::TomlError {
+ e.inner
+ }
+}
+
+impl std::error::Error for Error {}
+
+/// Convert a value into `T`.
+pub fn from_str<T>(s: &'_ str) -> Result<T, Error>
+where
+ T: DeserializeOwned,
+{
+ let de = s.parse::<Deserializer>()?;
+ T::deserialize(de)
+}
+
+/// Convert a value into `T`.
+pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error>
+where
+ T: DeserializeOwned,
+{
+ let s = std::str::from_utf8(s).map_err(|e| Error::custom(e, None))?;
+ from_str(s)
+}
+
+/// Convert a document into `T`.
+pub fn from_document<T>(d: crate::Document) -> Result<T, Error>
+where
+ T: DeserializeOwned,
+{
+ let deserializer = Deserializer::new(d);
+ T::deserialize(deserializer)
+}
+
+/// Deserialization for TOML [documents][crate::Document].
+pub struct Deserializer {
+ input: crate::Document,
+}
+
+impl Deserializer {
+ /// Deserialization implementation for TOML.
+ pub fn new(input: crate::Document) -> Self {
+ Self { input }
+ }
+}
+
+impl std::str::FromStr for Deserializer {
+ type Err = Error;
+
+ /// Parses a document from a &str
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let d = crate::parser::parse_document(s).map_err(Error::from)?;
+ Ok(Self::new(d))
+ }
+}
+
+// Note: this is wrapped by `toml::de::Deserializer` and any trait methods
+// implemented here need to be wrapped there
+impl<'de> serde::Deserializer<'de> for Deserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let original = self.input.original;
+ self.input
+ .root
+ .into_deserializer()
+ .deserialize_any(visitor)
+ .map_err(|mut e: Self::Error| {
+ e.inner.set_original(original);
+ e
+ })
+ }
+
+ // `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: serde::de::Visitor<'de>,
+ {
+ let original = self.input.original;
+ self.input
+ .root
+ .into_deserializer()
+ .deserialize_option(visitor)
+ .map_err(|mut e: Self::Error| {
+ e.inner.set_original(original);
+ e
+ })
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ name: &'static str,
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let original = self.input.original;
+ self.input
+ .root
+ .into_deserializer()
+ .deserialize_newtype_struct(name, visitor)
+ .map_err(|mut e: Self::Error| {
+ e.inner.set_original(original);
+ e
+ })
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let original = self.input.original;
+ self.input
+ .root
+ .into_deserializer()
+ .deserialize_struct(name, fields, visitor)
+ .map_err(|mut e: Self::Error| {
+ e.inner.set_original(original);
+ e
+ })
+ }
+
+ // Called when the type to deserialize is an enum, as opposed to a field in the type.
+ fn deserialize_enum<V>(
+ self,
+ name: &'static str,
+ variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let original = self.input.original;
+ self.input
+ .root
+ .into_deserializer()
+ .deserialize_enum(name, variants, visitor)
+ .map_err(|mut e: Self::Error| {
+ e.inner.set_original(original);
+ e
+ })
+ }
+
+ serde::forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map unit
+ ignored_any unit_struct tuple_struct tuple identifier
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for Deserializer {
+ type Deserializer = Deserializer;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Document {
+ type Deserializer = Deserializer;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ Deserializer::new(self)
+ }
+}
+
+pub(crate) fn validate_struct_keys(
+ table: &crate::table::KeyValuePairs,
+ fields: &'static [&'static str],
+) -> Result<(), Error> {
+ let extra_fields = table
+ .iter()
+ .filter_map(|(key, val)| {
+ if !fields.contains(&key.as_str()) {
+ Some(val.clone())
+ } else {
+ None
+ }
+ })
+ .collect::<Vec<_>>();
+
+ if extra_fields.is_empty() {
+ Ok(())
+ } else {
+ Err(Error::custom(
+ format!(
+ "unexpected keys in table: {}, available keys: {}",
+ extra_fields
+ .iter()
+ .map(|k| k.key.get())
+ .collect::<Vec<_>>()
+ .join(", "),
+ fields.join(", "),
+ ),
+ extra_fields[0].key.span(),
+ ))
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/spanned.rs b/vendor/toml_edit-0.19.11/src/de/spanned.rs
new file mode 100644
index 000000000..7ce58640a
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/spanned.rs
@@ -0,0 +1,70 @@
+use serde::de::value::BorrowedStrDeserializer;
+use serde::de::IntoDeserializer as _;
+
+use super::Error;
+
+pub(crate) struct SpannedDeserializer<'de, T: serde::de::IntoDeserializer<'de, Error>> {
+ phantom_data: std::marker::PhantomData<&'de ()>,
+ start: Option<usize>,
+ end: Option<usize>,
+ value: Option<T>,
+}
+
+impl<'de, T> SpannedDeserializer<'de, T>
+where
+ T: serde::de::IntoDeserializer<'de, Error>,
+{
+ pub(crate) fn new(value: T, span: std::ops::Range<usize>) -> Self {
+ Self {
+ phantom_data: Default::default(),
+ start: Some(span.start),
+ end: Some(span.end),
+ value: Some(value),
+ }
+ }
+}
+
+impl<'de, T> serde::de::MapAccess<'de> for SpannedDeserializer<'de, T>
+where
+ T: serde::de::IntoDeserializer<'de, Error>,
+{
+ type Error = Error;
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
+ where
+ K: serde::de::DeserializeSeed<'de>,
+ {
+ if self.start.is_some() {
+ seed.deserialize(BorrowedStrDeserializer::new(
+ serde_spanned::__unstable::START_FIELD,
+ ))
+ .map(Some)
+ } else if self.end.is_some() {
+ seed.deserialize(BorrowedStrDeserializer::new(
+ serde_spanned::__unstable::END_FIELD,
+ ))
+ .map(Some)
+ } else if self.value.is_some() {
+ seed.deserialize(BorrowedStrDeserializer::new(
+ serde_spanned::__unstable::VALUE_FIELD,
+ ))
+ .map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
+ where
+ V: serde::de::DeserializeSeed<'de>,
+ {
+ if let Some(start) = self.start.take() {
+ seed.deserialize(start.into_deserializer())
+ } else if let Some(end) = self.end.take() {
+ seed.deserialize(end.into_deserializer())
+ } else if let Some(value) = self.value.take() {
+ seed.deserialize(value.into_deserializer())
+ } else {
+ panic!("next_value_seed called before next_key_seed")
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/table.rs b/vendor/toml_edit-0.19.11/src/de/table.rs
new file mode 100644
index 000000000..0b6183e09
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/table.rs
@@ -0,0 +1,213 @@
+use serde::de::IntoDeserializer;
+
+use crate::de::Error;
+
+pub(crate) struct TableDeserializer {
+ span: Option<std::ops::Range<usize>>,
+ items: crate::table::KeyValuePairs,
+}
+
+// Note: this is wrapped by `Deserializer` and `ValueDeserializer` and any trait methods
+// implemented here need to be wrapped there
+impl<'de> serde::Deserializer<'de> for TableDeserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ visitor.visit_map(crate::de::TableMapAccess::new(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: serde::de::Visitor<'de>,
+ {
+ visitor.visit_some(self)
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ _name: &'static str,
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ visitor.visit_newtype_struct(self)
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ if serde_spanned::__unstable::is_spanned(name, fields) {
+ if let Some(span) = self.span.clone() {
+ return visitor.visit_map(super::SpannedDeserializer::new(self, span));
+ }
+ }
+
+ self.deserialize_any(visitor)
+ }
+
+ // Called when the type to deserialize is an enum, as opposed to a field in the type.
+ fn deserialize_enum<V>(
+ self,
+ _name: &'static str,
+ _variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ if self.items.is_empty() {
+ Err(crate::de::Error::custom(
+ "wanted exactly 1 element, found 0 elements",
+ self.span,
+ ))
+ } else if self.items.len() != 1 {
+ Err(crate::de::Error::custom(
+ "wanted exactly 1 element, more than 1 element",
+ self.span,
+ ))
+ } else {
+ visitor.visit_enum(crate::de::TableMapAccess::new(self))
+ }
+ }
+
+ serde::forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map unit
+ ignored_any unit_struct tuple_struct tuple identifier
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for TableDeserializer {
+ type Deserializer = TableDeserializer;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
+impl crate::Table {
+ pub(crate) fn into_deserializer(self) -> TableDeserializer {
+ TableDeserializer {
+ span: self.span(),
+ items: self.items,
+ }
+ }
+}
+
+impl crate::InlineTable {
+ pub(crate) fn into_deserializer(self) -> TableDeserializer {
+ TableDeserializer {
+ span: self.span(),
+ items: self.items,
+ }
+ }
+}
+
+pub(crate) struct TableMapAccess {
+ iter: indexmap::map::IntoIter<crate::InternalString, crate::table::TableKeyValue>,
+ span: Option<std::ops::Range<usize>>,
+ value: Option<(crate::InternalString, crate::Item)>,
+}
+
+impl TableMapAccess {
+ pub(crate) fn new(input: TableDeserializer) -> Self {
+ Self {
+ iter: input.items.into_iter(),
+ span: input.span,
+ value: None,
+ }
+ }
+}
+
+impl<'de> serde::de::MapAccess<'de> for TableMapAccess {
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
+ where
+ K: serde::de::DeserializeSeed<'de>,
+ {
+ match self.iter.next() {
+ Some((k, v)) => {
+ let ret = seed
+ .deserialize(super::KeyDeserializer::new(k, v.key.span()))
+ .map(Some)
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(v.key.span());
+ }
+ e
+ });
+ self.value = Some((v.key.into(), v.value));
+ ret
+ }
+ None => Ok(None),
+ }
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::DeserializeSeed<'de>,
+ {
+ match self.value.take() {
+ Some((k, v)) => {
+ let span = v.span();
+ seed.deserialize(crate::de::ValueDeserializer::new(v))
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e.add_key(k.as_str().to_owned());
+ e
+ })
+ }
+ None => {
+ panic!("no more values in next_value_seed, internal error in ValueDeserializer")
+ }
+ }
+ }
+}
+
+impl<'de> serde::de::EnumAccess<'de> for TableMapAccess {
+ type Error = Error;
+ type Variant = super::TableEnumDeserializer;
+
+ fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
+ where
+ V: serde::de::DeserializeSeed<'de>,
+ {
+ let (key, value) = match self.iter.next() {
+ Some(pair) => pair,
+ None => {
+ return Err(Error::custom(
+ "expected table with exactly 1 entry, found empty table",
+ self.span,
+ ));
+ }
+ };
+
+ let val = seed
+ .deserialize(key.into_deserializer())
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(value.key.span());
+ }
+ e
+ })?;
+
+ let variant = super::TableEnumDeserializer::new(value.value);
+
+ Ok((val, variant))
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/table_enum.rs b/vendor/toml_edit-0.19.11/src/de/table_enum.rs
new file mode 100644
index 000000000..197ad6ea7
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/table_enum.rs
@@ -0,0 +1,160 @@
+use crate::de::Error;
+
+/// Deserializes table values into enum variants.
+pub(crate) struct TableEnumDeserializer {
+ value: crate::Item,
+}
+
+impl TableEnumDeserializer {
+ pub(crate) fn new(value: crate::Item) -> Self {
+ TableEnumDeserializer { value }
+ }
+}
+
+impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer {
+ type Error = Error;
+
+ fn unit_variant(self) -> Result<(), Self::Error> {
+ match self.value {
+ crate::Item::Table(values) => {
+ if values.is_empty() {
+ Ok(())
+ } else {
+ Err(Error::custom("expected empty table", values.span()))
+ }
+ }
+ crate::Item::Value(crate::Value::InlineTable(values)) => {
+ if values.is_empty() {
+ Ok(())
+ } else {
+ Err(Error::custom("expected empty table", values.span()))
+ }
+ }
+ e => Err(Error::custom(
+ format!("expected table, found {}", e.type_name()),
+ e.span(),
+ )),
+ }
+ }
+
+ fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ seed.deserialize(super::ValueDeserializer::new(self.value))
+ }
+
+ fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.value {
+ crate::Item::Table(values) => {
+ let values_span = values.span();
+ let tuple_values = values
+ .items
+ .into_iter()
+ .enumerate()
+ .map(
+ |(index, (_, value))| match value.key.get().parse::<usize>() {
+ Ok(key_index) if key_index == index => Ok(value.value),
+ Ok(_) | Err(_) => Err(Error::custom(
+ format!(
+ "expected table key `{}`, but was `{}`",
+ index,
+ value.key.get()
+ ),
+ value.key.span(),
+ )),
+ },
+ )
+ // Fold all values into a `Vec`, or return the first error.
+ .fold(Ok(Vec::with_capacity(len)), |result, value_result| {
+ result.and_then(move |mut tuple_values| match value_result {
+ Ok(value) => {
+ tuple_values.push(value);
+ Ok(tuple_values)
+ }
+ // `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>`
+ Err(e) => Err(e),
+ })
+ })?;
+
+ if tuple_values.len() == len {
+ serde::de::Deserializer::deserialize_seq(
+ super::ArrayDeserializer::new(tuple_values, values_span),
+ visitor,
+ )
+ } else {
+ Err(Error::custom(
+ format!("expected tuple with length {}", len),
+ values_span,
+ ))
+ }
+ }
+ crate::Item::Value(crate::Value::InlineTable(values)) => {
+ let values_span = values.span();
+ let tuple_values = values
+ .items
+ .into_iter()
+ .enumerate()
+ .map(
+ |(index, (_, value))| match value.key.get().parse::<usize>() {
+ Ok(key_index) if key_index == index => Ok(value.value),
+ Ok(_) | Err(_) => Err(Error::custom(
+ format!(
+ "expected table key `{}`, but was `{}`",
+ index,
+ value.key.get()
+ ),
+ value.key.span(),
+ )),
+ },
+ )
+ // Fold all values into a `Vec`, or return the first error.
+ .fold(Ok(Vec::with_capacity(len)), |result, value_result| {
+ result.and_then(move |mut tuple_values| match value_result {
+ Ok(value) => {
+ tuple_values.push(value);
+ Ok(tuple_values)
+ }
+ // `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>`
+ Err(e) => Err(e),
+ })
+ })?;
+
+ if tuple_values.len() == len {
+ serde::de::Deserializer::deserialize_seq(
+ super::ArrayDeserializer::new(tuple_values, values_span),
+ visitor,
+ )
+ } else {
+ Err(Error::custom(
+ format!("expected tuple with length {}", len),
+ values_span,
+ ))
+ }
+ }
+ e => Err(Error::custom(
+ format!("expected table, found {}", e.type_name()),
+ e.span(),
+ )),
+ }
+ }
+
+ fn struct_variant<V>(
+ self,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ serde::de::Deserializer::deserialize_struct(
+ super::ValueDeserializer::new(self.value).with_struct_key_validation(),
+ "", // TODO: this should be the variant name
+ fields,
+ visitor,
+ )
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/de/value.rs b/vendor/toml_edit-0.19.11/src/de/value.rs
new file mode 100644
index 000000000..39842875a
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/de/value.rs
@@ -0,0 +1,252 @@
+use serde::de::IntoDeserializer as _;
+
+use crate::de::DatetimeDeserializer;
+use crate::de::Error;
+
+/// Deserialization implementation for TOML [values][crate::Value].
+///
+/// Can be creater either directly from TOML strings, using [`std::str::FromStr`],
+/// or from parsed [values][crate::Value] using [`serde::de::IntoDeserializer::into_deserializer`].
+///
+/// # Example
+///
+/// ```
+/// use serde::Deserialize;
+///
+/// #[derive(Deserialize)]
+/// struct Config {
+/// title: String,
+/// owner: Owner,
+/// }
+///
+/// #[derive(Deserialize)]
+/// struct Owner {
+/// name: String,
+/// }
+///
+/// let value = r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"#;
+/// let deserializer = value.parse::<toml_edit::de::ValueDeserializer>().unwrap();
+/// let config = Config::deserialize(deserializer).unwrap();
+/// assert_eq!(config.title, "TOML Example");
+/// assert_eq!(config.owner.name, "Lisa");
+/// ```
+pub struct ValueDeserializer {
+ input: crate::Item,
+ validate_struct_keys: bool,
+}
+
+impl ValueDeserializer {
+ pub(crate) fn new(input: crate::Item) -> Self {
+ Self {
+ input,
+ validate_struct_keys: false,
+ }
+ }
+
+ pub(crate) fn with_struct_key_validation(mut self) -> Self {
+ self.validate_struct_keys = true;
+ self
+ }
+}
+
+// Note: this is wrapped by `toml::de::ValueDeserializer` and any trait methods
+// implemented here need to be wrapped there
+impl<'de> serde::Deserializer<'de> for ValueDeserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let span = self.input.span();
+ match self.input {
+ crate::Item::None => visitor.visit_none(),
+ crate::Item::Value(crate::Value::String(v)) => visitor.visit_string(v.into_value()),
+ crate::Item::Value(crate::Value::Integer(v)) => visitor.visit_i64(v.into_value()),
+ crate::Item::Value(crate::Value::Float(v)) => visitor.visit_f64(v.into_value()),
+ crate::Item::Value(crate::Value::Boolean(v)) => visitor.visit_bool(v.into_value()),
+ crate::Item::Value(crate::Value::Datetime(v)) => {
+ visitor.visit_map(DatetimeDeserializer::new(v.into_value()))
+ }
+ crate::Item::Value(crate::Value::Array(v)) => {
+ v.into_deserializer().deserialize_any(visitor)
+ }
+ crate::Item::Value(crate::Value::InlineTable(v)) => {
+ v.into_deserializer().deserialize_any(visitor)
+ }
+ crate::Item::Table(v) => v.into_deserializer().deserialize_any(visitor),
+ crate::Item::ArrayOfTables(v) => v.into_deserializer().deserialize_any(visitor),
+ }
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e
+ })
+ }
+
+ // `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: serde::de::Visitor<'de>,
+ {
+ let span = self.input.span();
+ visitor.visit_some(self).map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e
+ })
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ _name: &'static str,
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let span = self.input.span();
+ visitor
+ .visit_newtype_struct(self)
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e
+ })
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ if serde_spanned::__unstable::is_spanned(name, fields) {
+ if let Some(span) = self.input.span() {
+ return visitor.visit_map(super::SpannedDeserializer::new(self, span));
+ }
+ }
+
+ if name == toml_datetime::__unstable::NAME && fields == [toml_datetime::__unstable::FIELD] {
+ let span = self.input.span();
+ if let crate::Item::Value(crate::Value::Datetime(d)) = self.input {
+ return visitor
+ .visit_map(DatetimeDeserializer::new(d.into_value()))
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e
+ });
+ }
+ }
+
+ if self.validate_struct_keys {
+ let span = self.input.span();
+ match &self.input {
+ crate::Item::Table(values) => super::validate_struct_keys(&values.items, fields),
+ crate::Item::Value(crate::Value::InlineTable(values)) => {
+ super::validate_struct_keys(&values.items, fields)
+ }
+ _ => Ok(()),
+ }
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e
+ })?
+ }
+
+ self.deserialize_any(visitor)
+ }
+
+ // Called when the type to deserialize is an enum, as opposed to a field in the type.
+ fn deserialize_enum<V>(
+ self,
+ name: &'static str,
+ variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let span = self.input.span();
+ match self.input {
+ crate::Item::Value(crate::Value::String(v)) => {
+ visitor.visit_enum(v.into_value().into_deserializer())
+ }
+ crate::Item::Value(crate::Value::InlineTable(v)) => {
+ if v.is_empty() {
+ Err(crate::de::Error::custom(
+ "wanted exactly 1 element, found 0 elements",
+ v.span(),
+ ))
+ } else if v.len() != 1 {
+ Err(crate::de::Error::custom(
+ "wanted exactly 1 element, more than 1 element",
+ v.span(),
+ ))
+ } else {
+ v.into_deserializer()
+ .deserialize_enum(name, variants, visitor)
+ }
+ }
+ crate::Item::Table(v) => v
+ .into_deserializer()
+ .deserialize_enum(name, variants, visitor),
+ e => Err(crate::de::Error::custom("wanted string or table", e.span())),
+ }
+ .map_err(|mut e: Self::Error| {
+ if e.span().is_none() {
+ e.set_span(span);
+ }
+ e
+ })
+ }
+
+ serde::forward_to_deserialize_any! {
+ bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
+ bytes byte_buf map unit
+ ignored_any unit_struct tuple_struct tuple identifier
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for ValueDeserializer {
+ type Deserializer = Self;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
+impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Value {
+ type Deserializer = ValueDeserializer;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ ValueDeserializer::new(crate::Item::Value(self))
+ }
+}
+
+impl crate::Item {
+ pub(crate) fn into_deserializer(self) -> ValueDeserializer {
+ ValueDeserializer::new(self)
+ }
+}
+
+impl std::str::FromStr for ValueDeserializer {
+ type Err = Error;
+
+ /// Parses a value from a &str
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let v = crate::parser::parse_value(s).map_err(Error::from)?;
+ Ok(v.into_deserializer())
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/document.rs b/vendor/toml_edit-0.19.11/src/document.rs
new file mode 100644
index 000000000..67dd293dd
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/document.rs
@@ -0,0 +1,113 @@
+use std::str::FromStr;
+
+use crate::parser;
+use crate::table::Iter;
+use crate::{Item, RawString, Table};
+
+/// Type representing a TOML document
+#[derive(Debug, Clone)]
+pub struct Document {
+ pub(crate) root: Item,
+ // Trailing comments and whitespaces
+ pub(crate) trailing: RawString,
+ pub(crate) original: Option<String>,
+ pub(crate) span: Option<std::ops::Range<usize>>,
+}
+
+impl Document {
+ /// Creates an empty document
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ /// Returns a reference to the root item.
+ pub fn as_item(&self) -> &Item {
+ &self.root
+ }
+
+ /// Returns a mutable reference to the root item.
+ pub fn as_item_mut(&mut self) -> &mut Item {
+ &mut self.root
+ }
+
+ /// Returns a reference to the root table.
+ pub fn as_table(&self) -> &Table {
+ self.root.as_table().expect("root should always be a table")
+ }
+
+ /// Returns a mutable reference to the root table.
+ pub fn as_table_mut(&mut self) -> &mut Table {
+ self.root
+ .as_table_mut()
+ .expect("root should always be a table")
+ }
+
+ /// Returns an iterator over the root table.
+ pub fn iter(&self) -> Iter<'_> {
+ self.as_table().iter()
+ }
+
+ /// Set whitespace after last element
+ pub fn set_trailing(&mut self, trailing: impl Into<RawString>) {
+ self.trailing = trailing.into();
+ }
+
+ /// Whitespace after last element
+ pub fn trailing(&self) -> &RawString {
+ &self.trailing
+ }
+
+ /// # Panics
+ ///
+ /// If run on on a `Document` not generated by the parser
+ pub(crate) fn despan(&mut self) {
+ self.span = None;
+ self.root.despan(self.original.as_deref().unwrap());
+ self.trailing.despan(self.original.as_deref().unwrap());
+ }
+}
+
+impl Default for Document {
+ fn default() -> Self {
+ Self {
+ root: Item::Table(Table::with_pos(Some(0))),
+ trailing: Default::default(),
+ original: Default::default(),
+ span: Default::default(),
+ }
+ }
+}
+
+impl FromStr for Document {
+ type Err = crate::TomlError;
+
+ /// Parses a document from a &str
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut d = parser::parse_document(s)?;
+ d.despan();
+ Ok(d)
+ }
+}
+
+impl std::ops::Deref for Document {
+ type Target = Table;
+
+ fn deref(&self) -> &Self::Target {
+ self.as_table()
+ }
+}
+
+impl std::ops::DerefMut for Document {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.as_table_mut()
+ }
+}
+
+impl From<Table> for Document {
+ fn from(root: Table) -> Self {
+ Self {
+ root: Item::Table(root),
+ ..Default::default()
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/encode.rs b/vendor/toml_edit-0.19.11/src/encode.rs
new file mode 100644
index 000000000..9940f282b
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/encode.rs
@@ -0,0 +1,569 @@
+use std::borrow::Cow;
+use std::fmt::{Display, Formatter, Result, Write};
+
+use toml_datetime::*;
+
+use crate::document::Document;
+use crate::inline_table::DEFAULT_INLINE_KEY_DECOR;
+use crate::key::Key;
+use crate::repr::{Formatted, Repr, ValueRepr};
+use crate::table::{DEFAULT_KEY_DECOR, DEFAULT_KEY_PATH_DECOR, DEFAULT_TABLE_DECOR};
+use crate::value::{
+ DEFAULT_LEADING_VALUE_DECOR, DEFAULT_TRAILING_VALUE_DECOR, DEFAULT_VALUE_DECOR,
+};
+use crate::{Array, InlineTable, Item, Table, Value};
+
+pub(crate) trait Encode {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result;
+}
+
+impl Encode for Key {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ let decor = self.decor();
+ decor.prefix_encode(buf, input, default_decor.0)?;
+
+ if let Some(input) = input {
+ let repr = self
+ .as_repr()
+ .map(Cow::Borrowed)
+ .unwrap_or_else(|| Cow::Owned(self.default_repr()));
+ repr.encode(buf, input)?;
+ } else {
+ let repr = self.display_repr();
+ write!(buf, "{}", repr)?;
+ };
+
+ decor.suffix_encode(buf, input, default_decor.1)?;
+ Ok(())
+ }
+}
+
+impl<'k> Encode for &'k [Key] {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ for (i, key) in self.iter().enumerate() {
+ let first = i == 0;
+ let last = i + 1 == self.len();
+
+ let prefix = if first {
+ default_decor.0
+ } else {
+ DEFAULT_KEY_PATH_DECOR.0
+ };
+ let suffix = if last {
+ default_decor.1
+ } else {
+ DEFAULT_KEY_PATH_DECOR.1
+ };
+
+ if !first {
+ write!(buf, ".")?;
+ }
+ key.encode(buf, input, (prefix, suffix))?;
+ }
+ Ok(())
+ }
+}
+
+impl<'k> Encode for &'k [&'k Key] {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ for (i, key) in self.iter().enumerate() {
+ let first = i == 0;
+ let last = i + 1 == self.len();
+
+ let prefix = if first {
+ default_decor.0
+ } else {
+ DEFAULT_KEY_PATH_DECOR.0
+ };
+ let suffix = if last {
+ default_decor.1
+ } else {
+ DEFAULT_KEY_PATH_DECOR.1
+ };
+
+ if !first {
+ write!(buf, ".")?;
+ }
+ key.encode(buf, input, (prefix, suffix))?;
+ }
+ Ok(())
+ }
+}
+
+impl<T> Encode for Formatted<T>
+where
+ T: ValueRepr,
+{
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ let decor = self.decor();
+ decor.prefix_encode(buf, input, default_decor.0)?;
+
+ if let Some(input) = input {
+ let repr = self
+ .as_repr()
+ .map(Cow::Borrowed)
+ .unwrap_or_else(|| Cow::Owned(self.default_repr()));
+ repr.encode(buf, input)?;
+ } else {
+ let repr = self.display_repr();
+ write!(buf, "{}", repr)?;
+ };
+
+ decor.suffix_encode(buf, input, default_decor.1)?;
+ Ok(())
+ }
+}
+
+impl Encode for Array {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ let decor = self.decor();
+ decor.prefix_encode(buf, input, default_decor.0)?;
+ write!(buf, "[")?;
+
+ for (i, elem) in self.iter().enumerate() {
+ let inner_decor;
+ if i == 0 {
+ inner_decor = DEFAULT_LEADING_VALUE_DECOR;
+ } else {
+ inner_decor = DEFAULT_VALUE_DECOR;
+ write!(buf, ",")?;
+ }
+ elem.encode(buf, input, inner_decor)?;
+ }
+ if self.trailing_comma() && !self.is_empty() {
+ write!(buf, ",")?;
+ }
+
+ self.trailing().encode_with_default(buf, input, "")?;
+ write!(buf, "]")?;
+ decor.suffix_encode(buf, input, default_decor.1)?;
+
+ Ok(())
+ }
+}
+
+impl Encode for InlineTable {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ let decor = self.decor();
+ decor.prefix_encode(buf, input, default_decor.0)?;
+ write!(buf, "{{")?;
+ self.preamble().encode_with_default(buf, input, "")?;
+
+ let children = self.get_values();
+ let len = children.len();
+ for (i, (key_path, value)) in children.into_iter().enumerate() {
+ if i != 0 {
+ write!(buf, ",")?;
+ }
+ let inner_decor = if i == len - 1 {
+ DEFAULT_TRAILING_VALUE_DECOR
+ } else {
+ DEFAULT_VALUE_DECOR
+ };
+ key_path
+ .as_slice()
+ .encode(buf, input, DEFAULT_INLINE_KEY_DECOR)?;
+ write!(buf, "=")?;
+ value.encode(buf, input, inner_decor)?;
+ }
+
+ write!(buf, "}}")?;
+ decor.suffix_encode(buf, input, default_decor.1)?;
+
+ Ok(())
+ }
+}
+
+impl Encode for Value {
+ fn encode(
+ &self,
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ default_decor: (&str, &str),
+ ) -> Result {
+ match self {
+ Value::String(repr) => repr.encode(buf, input, default_decor),
+ Value::Integer(repr) => repr.encode(buf, input, default_decor),
+ Value::Float(repr) => repr.encode(buf, input, default_decor),
+ Value::Boolean(repr) => repr.encode(buf, input, default_decor),
+ Value::Datetime(repr) => repr.encode(buf, input, default_decor),
+ Value::Array(array) => array.encode(buf, input, default_decor),
+ Value::InlineTable(table) => table.encode(buf, input, default_decor),
+ }
+ }
+}
+
+impl Display for Document {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let mut path = Vec::new();
+ let mut last_position = 0;
+ let mut tables = Vec::new();
+ visit_nested_tables(self.as_table(), &mut path, false, &mut |t, p, is_array| {
+ if let Some(pos) = t.position() {
+ last_position = pos;
+ }
+ tables.push((last_position, t, p.clone(), is_array));
+ Ok(())
+ })
+ .unwrap();
+
+ tables.sort_by_key(|&(id, _, _, _)| id);
+ let mut first_table = true;
+ for (_, table, path, is_array) in tables {
+ visit_table(
+ f,
+ self.original.as_deref(),
+ table,
+ &path,
+ is_array,
+ &mut first_table,
+ )?;
+ }
+ self.trailing()
+ .encode_with_default(f, self.original.as_deref(), "")
+ }
+}
+
+fn visit_nested_tables<'t, F>(
+ table: &'t Table,
+ path: &mut Vec<Key>,
+ is_array_of_tables: bool,
+ callback: &mut F,
+) -> Result
+where
+ F: FnMut(&'t Table, &Vec<Key>, bool) -> Result,
+{
+ if !table.is_dotted() {
+ callback(table, path, is_array_of_tables)?;
+ }
+
+ for kv in table.items.values() {
+ match kv.value {
+ Item::Table(ref t) => {
+ let mut key = kv.key.clone();
+ if t.is_dotted() {
+ // May have newlines and generally isn't written for standard tables
+ key.decor_mut().clear();
+ }
+ path.push(key);
+ visit_nested_tables(t, path, false, callback)?;
+ path.pop();
+ }
+ Item::ArrayOfTables(ref a) => {
+ for t in a.iter() {
+ let key = kv.key.clone();
+ path.push(key);
+ visit_nested_tables(t, path, true, callback)?;
+ path.pop();
+ }
+ }
+ _ => {}
+ }
+ }
+ Ok(())
+}
+
+fn visit_table(
+ buf: &mut dyn Write,
+ input: Option<&str>,
+ table: &Table,
+ path: &[Key],
+ is_array_of_tables: bool,
+ first_table: &mut bool,
+) -> Result {
+ let children = table.get_values();
+ // We are intentionally hiding implicit tables without any tables nested under them (ie
+ // `table.is_empty()` which is in contrast to `table.get_values().is_empty()`). We are
+ // trusting the user that an empty implicit table is not semantically meaningful
+ //
+ // This allows a user to delete all tables under this implicit table and the implicit table
+ // will disappear.
+ //
+ // However, this means that users need to take care in deciding what tables get marked as
+ // implicit.
+ let is_visible_std_table = !(table.implicit && children.is_empty());
+
+ if path.is_empty() {
+ // don't print header for the root node
+ if !children.is_empty() {
+ *first_table = false;
+ }
+ } else if is_array_of_tables {
+ let default_decor = if *first_table {
+ *first_table = false;
+ ("", DEFAULT_TABLE_DECOR.1)
+ } else {
+ DEFAULT_TABLE_DECOR
+ };
+ table.decor.prefix_encode(buf, input, default_decor.0)?;
+ write!(buf, "[[")?;
+ path.encode(buf, input, DEFAULT_KEY_PATH_DECOR)?;
+ write!(buf, "]]")?;
+ table.decor.suffix_encode(buf, input, default_decor.1)?;
+ writeln!(buf)?;
+ } else if is_visible_std_table {
+ let default_decor = if *first_table {
+ *first_table = false;
+ ("", DEFAULT_TABLE_DECOR.1)
+ } else {
+ DEFAULT_TABLE_DECOR
+ };
+ table.decor.prefix_encode(buf, input, default_decor.0)?;
+ write!(buf, "[")?;
+ path.encode(buf, input, DEFAULT_KEY_PATH_DECOR)?;
+ write!(buf, "]")?;
+ table.decor.suffix_encode(buf, input, default_decor.1)?;
+ writeln!(buf)?;
+ }
+ // print table body
+ for (key_path, value) in children {
+ key_path.as_slice().encode(buf, input, DEFAULT_KEY_DECOR)?;
+ write!(buf, "=")?;
+ value.encode(buf, input, DEFAULT_VALUE_DECOR)?;
+ writeln!(buf)?;
+ }
+ Ok(())
+}
+
+impl ValueRepr for String {
+ fn to_repr(&self) -> Repr {
+ to_string_repr(self, None, None)
+ }
+}
+
+pub(crate) fn to_string_repr(
+ value: &str,
+ style: Option<StringStyle>,
+ literal: Option<bool>,
+) -> Repr {
+ let (style, literal) = match (style, literal) {
+ (Some(style), Some(literal)) => (style, literal),
+ (_, Some(literal)) => (infer_style(value).0, literal),
+ (Some(style), _) => (style, infer_style(value).1),
+ (_, _) => infer_style(value),
+ };
+
+ let mut output = String::with_capacity(value.len() * 2);
+ if literal {
+ output.push_str(style.literal_start());
+ output.push_str(value);
+ output.push_str(style.literal_end());
+ } else {
+ output.push_str(style.standard_start());
+ for ch in value.chars() {
+ match ch {
+ '\u{8}' => output.push_str("\\b"),
+ '\u{9}' => output.push_str("\\t"),
+ '\u{a}' => match style {
+ StringStyle::NewlineTripple => output.push('\n'),
+ StringStyle::OnelineSingle => output.push_str("\\n"),
+ _ => unreachable!(),
+ },
+ '\u{c}' => output.push_str("\\f"),
+ '\u{d}' => output.push_str("\\r"),
+ '\u{22}' => output.push_str("\\\""),
+ '\u{5c}' => output.push_str("\\\\"),
+ c if c <= '\u{1f}' || c == '\u{7f}' => {
+ write!(output, "\\u{:04X}", ch as u32).unwrap();
+ }
+ ch => output.push(ch),
+ }
+ }
+ output.push_str(style.standard_end());
+ }
+
+ Repr::new_unchecked(output)
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub(crate) enum StringStyle {
+ NewlineTripple,
+ OnelineTripple,
+ OnelineSingle,
+}
+
+impl StringStyle {
+ fn literal_start(self) -> &'static str {
+ match self {
+ Self::NewlineTripple => "'''\n",
+ Self::OnelineTripple => "'''",
+ Self::OnelineSingle => "'",
+ }
+ }
+ fn literal_end(self) -> &'static str {
+ match self {
+ Self::NewlineTripple => "'''",
+ Self::OnelineTripple => "'''",
+ Self::OnelineSingle => "'",
+ }
+ }
+
+ fn standard_start(self) -> &'static str {
+ match self {
+ Self::NewlineTripple => "\"\"\"\n",
+ // note: OnelineTripple can happen if do_pretty wants to do
+ // '''it's one line'''
+ // but literal == false
+ Self::OnelineTripple | Self::OnelineSingle => "\"",
+ }
+ }
+
+ fn standard_end(self) -> &'static str {
+ match self {
+ Self::NewlineTripple => "\"\"\"",
+ // note: OnelineTripple can happen if do_pretty wants to do
+ // '''it's one line'''
+ // but literal == false
+ Self::OnelineTripple | Self::OnelineSingle => "\"",
+ }
+ }
+}
+
+fn infer_style(value: &str) -> (StringStyle, bool) {
+ // 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 = StringStyle::OnelineSingle;
+ // found consecutive single quotes
+ let mut max_found_singles = 0;
+ let mut found_singles = 0;
+ let mut prefer_literal = false;
+ 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' => {}
+ '\\' => {
+ prefer_literal = true;
+ }
+ '\n' => ty = StringStyle::NewlineTripple,
+ // Escape codes are needed if any ascii control
+ // characters are present, including \b \f \r.
+ c if c <= '\u{1f}' || c == '\u{7f}' => can_be_pretty = false,
+ _ => {}
+ }
+ out.push(ch);
+ } else {
+ // the string cannot be represented as pretty,
+ // still check if it should be multiline
+ if ch == '\n' {
+ ty = StringStyle::NewlineTripple;
+ }
+ }
+ }
+ if found_singles > 0 && value.ends_with('\'') {
+ // We cannot escape the ending quote so we must use """
+ can_be_pretty = false;
+ }
+ if !prefer_literal {
+ can_be_pretty = false;
+ }
+ if !can_be_pretty {
+ debug_assert!(ty != StringStyle::OnelineTripple);
+ return (ty, false);
+ }
+ if found_singles > max_found_singles {
+ max_found_singles = found_singles;
+ }
+ debug_assert!(max_found_singles < 3);
+ if ty == StringStyle::OnelineSingle && max_found_singles >= 1 {
+ // no newlines, but must use ''' because it has ' in it
+ ty = StringStyle::OnelineTripple;
+ }
+ (ty, true)
+}
+
+impl ValueRepr for i64 {
+ fn to_repr(&self) -> Repr {
+ Repr::new_unchecked(self.to_string())
+ }
+}
+
+impl ValueRepr for f64 {
+ fn to_repr(&self) -> Repr {
+ to_f64_repr(*self)
+ }
+}
+
+fn to_f64_repr(f: f64) -> Repr {
+ let repr = match (f.is_sign_negative(), f.is_nan(), f == 0.0) {
+ (true, true, _) => "-nan".to_owned(),
+ (false, true, _) => "nan".to_owned(),
+ (true, false, true) => "-0.0".to_owned(),
+ (false, false, true) => "0.0".to_owned(),
+ (_, false, false) => {
+ if f % 1.0 == 0.0 {
+ format!("{}.0", f)
+ } else {
+ format!("{}", f)
+ }
+ }
+ };
+ Repr::new_unchecked(repr)
+}
+
+impl ValueRepr for bool {
+ fn to_repr(&self) -> Repr {
+ Repr::new_unchecked(self.to_string())
+ }
+}
+
+impl ValueRepr for Datetime {
+ fn to_repr(&self) -> Repr {
+ Repr::new_unchecked(self.to_string())
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/index.rs b/vendor/toml_edit-0.19.11/src/index.rs
new file mode 100644
index 000000000..276db7957
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/index.rs
@@ -0,0 +1,156 @@
+use std::ops;
+
+use crate::document::Document;
+use crate::key::Key;
+use crate::table::TableKeyValue;
+use crate::{value, InlineTable, InternalString, Item, Table, Value};
+
+// copied from
+// https://github.com/serde-rs/json/blob/master/src/value/index.rs
+
+pub trait Index: crate::private::Sealed {
+ #[doc(hidden)]
+ fn index<'v>(&self, val: &'v Item) -> Option<&'v Item>;
+ #[doc(hidden)]
+ fn index_mut<'v>(&self, val: &'v mut Item) -> Option<&'v mut Item>;
+}
+
+impl Index for usize {
+ fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
+ match *v {
+ Item::ArrayOfTables(ref aot) => aot.values.get(*self),
+ Item::Value(ref a) if a.is_array() => a.as_array().and_then(|a| a.values.get(*self)),
+ _ => None,
+ }
+ }
+ fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
+ match *v {
+ Item::ArrayOfTables(ref mut vec) => vec.values.get_mut(*self),
+ Item::Value(ref mut a) => a.as_array_mut().and_then(|a| a.values.get_mut(*self)),
+ _ => None,
+ }
+ }
+}
+
+impl Index for str {
+ fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
+ match *v {
+ Item::Table(ref t) => t.get(self),
+ Item::Value(ref v) => v
+ .as_inline_table()
+ .and_then(|t| t.items.get(self))
+ .and_then(|kv| {
+ if !kv.value.is_none() {
+ Some(&kv.value)
+ } else {
+ None
+ }
+ }),
+ _ => None,
+ }
+ }
+ fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
+ if let Item::None = *v {
+ let mut t = InlineTable::default();
+ t.items.insert(
+ InternalString::from(self),
+ TableKeyValue::new(Key::new(self), Item::None),
+ );
+ *v = value(Value::InlineTable(t));
+ }
+ match *v {
+ Item::Table(ref mut t) => Some(t.entry(self).or_insert(Item::None)),
+ Item::Value(ref mut v) => v.as_inline_table_mut().map(|t| {
+ &mut t
+ .items
+ .entry(InternalString::from(self))
+ .or_insert_with(|| TableKeyValue::new(Key::new(self), Item::None))
+ .value
+ }),
+ _ => None,
+ }
+ }
+}
+
+impl Index for String {
+ fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
+ self[..].index(v)
+ }
+ fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
+ self[..].index_mut(v)
+ }
+}
+
+impl<'a, T: ?Sized> Index for &'a T
+where
+ T: Index,
+{
+ fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
+ (**self).index(v)
+ }
+ fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
+ (**self).index_mut(v)
+ }
+}
+
+impl<I> ops::Index<I> for Item
+where
+ I: Index,
+{
+ type Output = Item;
+
+ fn index(&self, index: I) -> &Item {
+ index.index(self).expect("index not found")
+ }
+}
+
+impl<I> ops::IndexMut<I> for Item
+where
+ I: Index,
+{
+ fn index_mut(&mut self, index: I) -> &mut Item {
+ index.index_mut(self).expect("index not found")
+ }
+}
+
+impl<'s> ops::Index<&'s str> for Table {
+ type Output = Item;
+
+ fn index(&self, key: &'s str) -> &Item {
+ self.get(key).expect("index not found")
+ }
+}
+
+impl<'s> ops::IndexMut<&'s str> for Table {
+ fn index_mut(&mut self, key: &'s str) -> &mut Item {
+ self.entry(key).or_insert(Item::None)
+ }
+}
+
+impl<'s> ops::Index<&'s str> for InlineTable {
+ type Output = Value;
+
+ fn index(&self, key: &'s str) -> &Value {
+ self.get(key).expect("index not found")
+ }
+}
+
+impl<'s> ops::IndexMut<&'s str> for InlineTable {
+ fn index_mut(&mut self, key: &'s str) -> &mut Value {
+ self.get_mut(key).expect("index not found")
+ }
+}
+
+impl<'s> ops::Index<&'s str> for Document {
+ type Output = Item;
+
+ fn index(&self, key: &'s str) -> &Item {
+ self.root.index(key)
+ }
+}
+
+impl<'s> ops::IndexMut<&'s str> for Document {
+ fn index_mut(&mut self, key: &'s str) -> &mut Item {
+ self.root.index_mut(key)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/inline_table.rs b/vendor/toml_edit-0.19.11/src/inline_table.rs
new file mode 100644
index 000000000..9327818e6
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/inline_table.rs
@@ -0,0 +1,661 @@
+use std::iter::FromIterator;
+
+use crate::key::Key;
+use crate::repr::Decor;
+use crate::table::{Iter, IterMut, KeyValuePairs, TableKeyValue, TableLike};
+use crate::{InternalString, Item, KeyMut, RawString, Table, Value};
+
+/// Type representing a TOML inline table,
+/// payload of the `Value::InlineTable` variant
+#[derive(Debug, Default, Clone)]
+pub struct InlineTable {
+ // `preamble` represents whitespaces in an empty table
+ preamble: RawString,
+ // prefix before `{` and suffix after `}`
+ decor: Decor,
+ pub(crate) span: Option<std::ops::Range<usize>>,
+ // whether this is a proxy for dotted keys
+ dotted: bool,
+ pub(crate) items: KeyValuePairs,
+}
+
+/// Constructors
+///
+/// See also `FromIterator`
+impl InlineTable {
+ /// Creates an empty table.
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub(crate) fn with_pairs(items: KeyValuePairs) -> Self {
+ Self {
+ items,
+ ..Default::default()
+ }
+ }
+
+ /// Convert to a table
+ pub fn into_table(self) -> Table {
+ let mut t = Table::with_pairs(self.items);
+ t.fmt();
+ t
+ }
+}
+
+/// Formatting
+impl InlineTable {
+ /// Get key/values for values that are visually children of this table
+ ///
+ /// For example, this will return dotted keys
+ pub fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
+ let mut values = Vec::new();
+ let root = Vec::new();
+ self.append_values(&root, &mut values);
+ values
+ }
+
+ pub(crate) fn append_values<'s, 'c>(
+ &'s self,
+ parent: &[&'s Key],
+ values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>,
+ ) {
+ for value in self.items.values() {
+ let mut path = parent.to_vec();
+ path.push(&value.key);
+ match &value.value {
+ Item::Value(Value::InlineTable(table)) if table.is_dotted() => {
+ table.append_values(&path, values);
+ }
+ Item::Value(value) => {
+ values.push((path, value));
+ }
+ _ => {}
+ }
+ }
+ }
+
+ /// Auto formats the table.
+ pub fn fmt(&mut self) {
+ decorate_inline_table(self);
+ }
+
+ /// Sorts the key/value pairs by key.
+ pub fn sort_values(&mut self) {
+ // Assuming standard tables have their position set and this won't negatively impact them
+ self.items.sort_keys();
+ for kv in self.items.values_mut() {
+ match &mut kv.value {
+ Item::Value(Value::InlineTable(table)) if table.is_dotted() => {
+ table.sort_values();
+ }
+ _ => {}
+ }
+ }
+ }
+
+ /// Sort Key/Value Pairs of the table using the using the comparison function `compare`.
+ ///
+ /// The comparison function receives two key and value pairs to compare (you can sort by keys or
+ /// values or their combination as needed).
+ pub fn sort_values_by<F>(&mut self, mut compare: F)
+ where
+ F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering,
+ {
+ self.sort_values_by_internal(&mut compare);
+ }
+
+ fn sort_values_by_internal<F>(&mut self, compare: &mut F)
+ where
+ F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering,
+ {
+ let modified_cmp = |_: &InternalString,
+ val1: &TableKeyValue,
+ _: &InternalString,
+ val2: &TableKeyValue|
+ -> std::cmp::Ordering {
+ match (val1.value.as_value(), val2.value.as_value()) {
+ (Some(v1), Some(v2)) => compare(&val1.key, v1, &val2.key, v2),
+ (Some(_), None) => std::cmp::Ordering::Greater,
+ (None, Some(_)) => std::cmp::Ordering::Less,
+ (None, None) => std::cmp::Ordering::Equal,
+ }
+ };
+
+ self.items.sort_by(modified_cmp);
+ for kv in self.items.values_mut() {
+ match &mut kv.value {
+ Item::Value(Value::InlineTable(table)) if table.is_dotted() => {
+ table.sort_values_by_internal(compare);
+ }
+ _ => {}
+ }
+ }
+ }
+
+ /// Change this table's dotted status
+ pub fn set_dotted(&mut self, yes: bool) {
+ self.dotted = yes;
+ }
+
+ /// Check if this is a wrapper for dotted keys, rather than a standard table
+ pub fn is_dotted(&self) -> bool {
+ self.dotted
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ &mut self.decor
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor(&self) -> &Decor {
+ &self.decor
+ }
+
+ /// Returns the decor associated with a given key of the table.
+ pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> {
+ self.items.get_mut(key).map(|kv| &mut kv.key.decor)
+ }
+
+ /// Returns the decor associated with a given key of the table.
+ pub fn key_decor(&self, key: &str) -> Option<&Decor> {
+ self.items.get(key).map(|kv| &kv.key.decor)
+ }
+
+ /// Set whitespace after before element
+ pub fn set_preamble(&mut self, preamble: impl Into<RawString>) {
+ self.preamble = preamble.into();
+ }
+
+ /// Whitespace after before element
+ pub fn preamble(&self) -> &RawString {
+ &self.preamble
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.span.clone()
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.span = None;
+ self.decor.despan(input);
+ self.preamble.despan(input);
+ for kv in self.items.values_mut() {
+ kv.key.despan(input);
+ kv.value.despan(input);
+ }
+ }
+}
+
+impl InlineTable {
+ /// Returns an iterator over key/value pairs.
+ pub fn iter(&self) -> InlineTableIter<'_> {
+ Box::new(
+ self.items
+ .iter()
+ .filter(|&(_, kv)| kv.value.is_value())
+ .map(|(k, kv)| (&k[..], kv.value.as_value().unwrap())),
+ )
+ }
+
+ /// Returns an iterator over key/value pairs.
+ pub fn iter_mut(&mut self) -> InlineTableIterMut<'_> {
+ Box::new(
+ self.items
+ .iter_mut()
+ .filter(|(_, kv)| kv.value.is_value())
+ .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())),
+ )
+ }
+
+ /// Returns the number of key/value pairs.
+ pub fn len(&self) -> usize {
+ self.iter().count()
+ }
+
+ /// Returns true iff the table is empty.
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse.
+ pub fn clear(&mut self) {
+ self.items.clear()
+ }
+
+ /// Gets the given key's corresponding entry in the Table for in-place manipulation.
+ pub fn entry(&'_ mut self, key: impl Into<InternalString>) -> InlineEntry<'_> {
+ match self.items.entry(key.into()) {
+ indexmap::map::Entry::Occupied(mut entry) => {
+ // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code.
+ let scratch = std::mem::take(&mut entry.get_mut().value);
+ let scratch = Item::Value(
+ scratch
+ .into_value()
+ // HACK: `Item::None` is a corner case of a corner case, let's just pick a
+ // "safe" value
+ .unwrap_or_else(|_| Value::InlineTable(Default::default())),
+ );
+ entry.get_mut().value = scratch;
+
+ InlineEntry::Occupied(InlineOccupiedEntry { entry })
+ }
+ indexmap::map::Entry::Vacant(entry) => {
+ InlineEntry::Vacant(InlineVacantEntry { entry, key: None })
+ }
+ }
+ }
+
+ /// Gets the given key's corresponding entry in the Table for in-place manipulation.
+ pub fn entry_format<'a>(&'a mut self, key: &Key) -> InlineEntry<'a> {
+ // Accept a `&Key` to be consistent with `entry`
+ match self.items.entry(key.get().into()) {
+ indexmap::map::Entry::Occupied(mut entry) => {
+ // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code.
+ let scratch = std::mem::take(&mut entry.get_mut().value);
+ let scratch = Item::Value(
+ scratch
+ .into_value()
+ // HACK: `Item::None` is a corner case of a corner case, let's just pick a
+ // "safe" value
+ .unwrap_or_else(|_| Value::InlineTable(Default::default())),
+ );
+ entry.get_mut().value = scratch;
+
+ InlineEntry::Occupied(InlineOccupiedEntry { entry })
+ }
+ indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry {
+ entry,
+ key: Some(key.clone()),
+ }),
+ }
+ }
+ /// Return an optional reference to the value at the given the key.
+ pub fn get(&self, key: &str) -> Option<&Value> {
+ self.items.get(key).and_then(|kv| kv.value.as_value())
+ }
+
+ /// Return an optional mutable reference to the value at the given the key.
+ pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
+ self.items
+ .get_mut(key)
+ .and_then(|kv| kv.value.as_value_mut())
+ }
+
+ /// Return references to the key-value pair stored for key, if it is present, else None.
+ pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> {
+ self.items.get(key).and_then(|kv| {
+ if !kv.value.is_none() {
+ Some((&kv.key, &kv.value))
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Return mutable references to the key-value pair stored for key, if it is present, else None.
+ pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> {
+ self.items.get_mut(key).and_then(|kv| {
+ if !kv.value.is_none() {
+ Some((kv.key.as_mut(), &mut kv.value))
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Returns true iff the table contains given key.
+ pub fn contains_key(&self, key: &str) -> bool {
+ if let Some(kv) = self.items.get(key) {
+ kv.value.is_value()
+ } else {
+ false
+ }
+ }
+
+ /// Inserts a key/value pair if the table does not contain the key.
+ /// Returns a mutable reference to the corresponding value.
+ pub fn get_or_insert<V: Into<Value>>(
+ &mut self,
+ key: impl Into<InternalString>,
+ value: V,
+ ) -> &mut Value {
+ let key = key.into();
+ self.items
+ .entry(key.clone())
+ .or_insert(TableKeyValue::new(Key::new(key), Item::Value(value.into())))
+ .value
+ .as_value_mut()
+ .expect("non-value type in inline table")
+ }
+
+ /// Inserts a key-value pair into the map.
+ pub fn insert(&mut self, key: impl Into<InternalString>, value: Value) -> Option<Value> {
+ let key = key.into();
+ let kv = TableKeyValue::new(Key::new(key.clone()), Item::Value(value));
+ self.items
+ .insert(key, kv)
+ .and_then(|kv| kv.value.into_value().ok())
+ }
+
+ /// Inserts a key-value pair into the map.
+ pub fn insert_formatted(&mut self, key: &Key, value: Value) -> Option<Value> {
+ let kv = TableKeyValue::new(key.to_owned(), Item::Value(value));
+ self.items
+ .insert(InternalString::from(key.get()), kv)
+ .filter(|kv| kv.value.is_value())
+ .map(|kv| kv.value.into_value().unwrap())
+ }
+
+ /// Removes an item given the key.
+ pub fn remove(&mut self, key: &str) -> Option<Value> {
+ self.items
+ .shift_remove(key)
+ .and_then(|kv| kv.value.into_value().ok())
+ }
+
+ /// Removes a key from the map, returning the stored key and value if the key was previously in the map.
+ pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Value)> {
+ self.items.shift_remove(key).and_then(|kv| {
+ let key = kv.key;
+ kv.value.into_value().ok().map(|value| (key, value))
+ })
+ }
+}
+
+impl std::fmt::Display for InlineTable {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ crate::encode::Encode::encode(self, f, None, ("", ""))
+ }
+}
+
+impl<K: Into<Key>, V: Into<Value>> Extend<(K, V)> for InlineTable {
+ fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
+ for (key, value) in iter {
+ let key = key.into();
+ let value = Item::Value(value.into());
+ let value = TableKeyValue::new(key, value);
+ self.items
+ .insert(InternalString::from(value.key.get()), value);
+ }
+ }
+}
+
+impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for InlineTable {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = (K, V)>,
+ {
+ let mut table = InlineTable::new();
+ table.extend(iter);
+ table
+ }
+}
+
+impl IntoIterator for InlineTable {
+ type Item = (InternalString, Value);
+ type IntoIter = InlineTableIntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Box::new(
+ self.items
+ .into_iter()
+ .filter(|(_, kv)| kv.value.is_value())
+ .map(|(k, kv)| (k, kv.value.into_value().unwrap())),
+ )
+ }
+}
+
+impl<'s> IntoIterator for &'s InlineTable {
+ type Item = (&'s str, &'s Value);
+ type IntoIter = InlineTableIter<'s>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+fn decorate_inline_table(table: &mut InlineTable) {
+ for (key_decor, value) in table
+ .items
+ .iter_mut()
+ .filter(|&(_, ref kv)| kv.value.is_value())
+ .map(|(_, kv)| (&mut kv.key.decor, kv.value.as_value_mut().unwrap()))
+ {
+ key_decor.clear();
+ value.decor_mut().clear();
+ }
+}
+
+/// An owned iterator type over key/value pairs of an inline table.
+pub type InlineTableIntoIter = Box<dyn Iterator<Item = (InternalString, Value)>>;
+/// An iterator type over key/value pairs of an inline table.
+pub type InlineTableIter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Value)> + 'a>;
+/// A mutable iterator type over key/value pairs of an inline table.
+pub type InlineTableIterMut<'a> = Box<dyn Iterator<Item = (KeyMut<'a>, &'a mut Value)> + 'a>;
+
+impl TableLike for InlineTable {
+ fn iter(&self) -> Iter<'_> {
+ Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value)))
+ }
+ fn iter_mut(&mut self) -> IterMut<'_> {
+ Box::new(
+ self.items
+ .iter_mut()
+ .map(|(_, kv)| (kv.key.as_mut(), &mut kv.value)),
+ )
+ }
+ fn clear(&mut self) {
+ self.clear();
+ }
+ fn entry<'a>(&'a mut self, key: &str) -> crate::Entry<'a> {
+ // Accept a `&str` rather than an owned type to keep `InternalString`, well, internal
+ match self.items.entry(key.into()) {
+ indexmap::map::Entry::Occupied(entry) => {
+ crate::Entry::Occupied(crate::OccupiedEntry { entry })
+ }
+ indexmap::map::Entry::Vacant(entry) => {
+ crate::Entry::Vacant(crate::VacantEntry { entry, key: None })
+ }
+ }
+ }
+ fn entry_format<'a>(&'a mut self, key: &Key) -> crate::Entry<'a> {
+ // Accept a `&Key` to be consistent with `entry`
+ match self.items.entry(key.get().into()) {
+ indexmap::map::Entry::Occupied(entry) => {
+ crate::Entry::Occupied(crate::OccupiedEntry { entry })
+ }
+ indexmap::map::Entry::Vacant(entry) => crate::Entry::Vacant(crate::VacantEntry {
+ entry,
+ key: Some(key.to_owned()),
+ }),
+ }
+ }
+ fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
+ self.items.get(key).map(|kv| &kv.value)
+ }
+ fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> {
+ self.items.get_mut(key).map(|kv| &mut kv.value)
+ }
+ fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> {
+ self.get_key_value(key)
+ }
+ fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> {
+ self.get_key_value_mut(key)
+ }
+ fn contains_key(&self, key: &str) -> bool {
+ self.contains_key(key)
+ }
+ fn insert(&mut self, key: &str, value: Item) -> Option<Item> {
+ self.insert(key, value.into_value().unwrap())
+ .map(Item::Value)
+ }
+ fn remove(&mut self, key: &str) -> Option<Item> {
+ self.remove(key).map(Item::Value)
+ }
+
+ fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
+ self.get_values()
+ }
+ fn fmt(&mut self) {
+ self.fmt()
+ }
+ fn sort_values(&mut self) {
+ self.sort_values()
+ }
+ fn set_dotted(&mut self, yes: bool) {
+ self.set_dotted(yes)
+ }
+ fn is_dotted(&self) -> bool {
+ self.is_dotted()
+ }
+
+ fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> {
+ self.key_decor_mut(key)
+ }
+ fn key_decor(&self, key: &str) -> Option<&Decor> {
+ self.key_decor(key)
+ }
+}
+
+// `{ key1 = value1, ... }`
+pub(crate) const DEFAULT_INLINE_KEY_DECOR: (&str, &str) = (" ", " ");
+
+/// A view into a single location in a map, which may be vacant or occupied.
+pub enum InlineEntry<'a> {
+ /// An occupied Entry.
+ Occupied(InlineOccupiedEntry<'a>),
+ /// A vacant Entry.
+ Vacant(InlineVacantEntry<'a>),
+}
+
+impl<'a> InlineEntry<'a> {
+ /// Returns the entry key
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use toml_edit::Table;
+ ///
+ /// let mut map = Table::new();
+ ///
+ /// assert_eq!("hello", map.entry("hello").key());
+ /// ```
+ pub fn key(&self) -> &str {
+ match self {
+ InlineEntry::Occupied(e) => e.key(),
+ InlineEntry::Vacant(e) => e.key(),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting the default if empty, and returns
+ /// a mutable reference to the value in the entry.
+ pub fn or_insert(self, default: Value) -> &'a mut Value {
+ match self {
+ InlineEntry::Occupied(entry) => entry.into_mut(),
+ InlineEntry::Vacant(entry) => entry.insert(default),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting the result of the default function if empty,
+ /// and returns a mutable reference to the value in the entry.
+ pub fn or_insert_with<F: FnOnce() -> Value>(self, default: F) -> &'a mut Value {
+ match self {
+ InlineEntry::Occupied(entry) => entry.into_mut(),
+ InlineEntry::Vacant(entry) => entry.insert(default()),
+ }
+ }
+}
+
+/// A view into a single occupied location in a `IndexMap`.
+pub struct InlineOccupiedEntry<'a> {
+ entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>,
+}
+
+impl<'a> InlineOccupiedEntry<'a> {
+ /// Gets a reference to the entry key
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use toml_edit::Table;
+ ///
+ /// let mut map = Table::new();
+ ///
+ /// assert_eq!("foo", map.entry("foo").key());
+ /// ```
+ pub fn key(&self) -> &str {
+ self.entry.key().as_str()
+ }
+
+ /// Gets a mutable reference to the entry key
+ pub fn key_mut(&mut self) -> KeyMut<'_> {
+ self.entry.get_mut().key.as_mut()
+ }
+
+ /// Gets a reference to the value in the entry.
+ pub fn get(&self) -> &Value {
+ self.entry.get().value.as_value().unwrap()
+ }
+
+ /// Gets a mutable reference to the value in the entry.
+ pub fn get_mut(&mut self) -> &mut Value {
+ self.entry.get_mut().value.as_value_mut().unwrap()
+ }
+
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+ /// with a lifetime bound to the map itself
+ pub fn into_mut(self) -> &'a mut Value {
+ self.entry.into_mut().value.as_value_mut().unwrap()
+ }
+
+ /// Sets the value of the entry, and returns the entry's old value
+ pub fn insert(&mut self, value: Value) -> Value {
+ let mut value = Item::Value(value);
+ std::mem::swap(&mut value, &mut self.entry.get_mut().value);
+ value.into_value().unwrap()
+ }
+
+ /// Takes the value out of the entry, and returns it
+ pub fn remove(self) -> Value {
+ self.entry.shift_remove().value.into_value().unwrap()
+ }
+}
+
+/// A view into a single empty location in a `IndexMap`.
+pub struct InlineVacantEntry<'a> {
+ entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>,
+ key: Option<Key>,
+}
+
+impl<'a> InlineVacantEntry<'a> {
+ /// Gets a reference to the entry key
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use toml_edit::Table;
+ ///
+ /// let mut map = Table::new();
+ ///
+ /// assert_eq!("foo", map.entry("foo").key());
+ /// ```
+ pub fn key(&self) -> &str {
+ self.entry.key().as_str()
+ }
+
+ /// Sets the value of the entry with the VacantEntry's key,
+ /// and returns a mutable reference to it
+ pub fn insert(self, value: Value) -> &'a mut Value {
+ let entry = self.entry;
+ let key = self.key.unwrap_or_else(|| Key::new(entry.key().as_str()));
+ let value = Item::Value(value);
+ entry
+ .insert(TableKeyValue::new(key, value))
+ .value
+ .as_value_mut()
+ .unwrap()
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/internal_string.rs b/vendor/toml_edit-0.19.11/src/internal_string.rs
new file mode 100644
index 000000000..d4347d25b
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/internal_string.rs
@@ -0,0 +1,183 @@
+use std::borrow::Borrow;
+use std::str::FromStr;
+
+/// Opaque string storage internal to `toml_edit`
+#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct InternalString(Inner);
+
+#[cfg(feature = "kstring")]
+type Inner = kstring::KString;
+#[cfg(not(feature = "kstring"))]
+type Inner = String;
+
+impl InternalString {
+ /// Create an empty string
+ pub fn new() -> Self {
+ InternalString(Inner::new())
+ }
+
+ /// Access the underlying string
+ #[inline]
+ pub fn as_str(&self) -> &str {
+ self.0.as_str()
+ }
+}
+
+impl std::fmt::Debug for InternalString {
+ #[inline]
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ self.0.fmt(formatter)
+ }
+}
+
+impl std::ops::Deref for InternalString {
+ type Target = str;
+
+ #[inline]
+ fn deref(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl Borrow<str> for InternalString {
+ #[inline]
+ fn borrow(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl AsRef<str> for InternalString {
+ #[inline]
+ fn as_ref(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl From<&str> for InternalString {
+ #[inline]
+ fn from(s: &str) -> Self {
+ #[cfg(feature = "kstring")]
+ let inner = kstring::KString::from_ref(s);
+ #[cfg(not(feature = "kstring"))]
+ let inner = String::from(s);
+
+ InternalString(inner)
+ }
+}
+
+impl From<String> for InternalString {
+ #[inline]
+ fn from(s: String) -> Self {
+ #[allow(clippy::useless_conversion)] // handle any string type
+ InternalString(s.into())
+ }
+}
+
+impl From<&String> for InternalString {
+ #[inline]
+ fn from(s: &String) -> Self {
+ InternalString(s.into())
+ }
+}
+
+impl From<&InternalString> for InternalString {
+ #[inline]
+ fn from(s: &InternalString) -> Self {
+ s.clone()
+ }
+}
+
+impl From<Box<str>> for InternalString {
+ #[inline]
+ fn from(s: Box<str>) -> Self {
+ InternalString(s.into())
+ }
+}
+
+impl FromStr for InternalString {
+ type Err = core::convert::Infallible;
+ #[inline]
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Ok(Self::from(s))
+ }
+}
+
+impl std::fmt::Display for InternalString {
+ #[inline]
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.as_str().fmt(f)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl serde::Serialize for InternalString {
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serializer.serialize_str(self.as_str())
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for InternalString {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ deserializer.deserialize_string(StringVisitor)
+ }
+}
+
+#[cfg(feature = "serde")]
+struct StringVisitor;
+
+#[cfg(feature = "serde")]
+impl<'de> serde::de::Visitor<'de> for StringVisitor {
+ type Value = InternalString;
+
+ fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ formatter.write_str("a string")
+ }
+
+ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ Ok(InternalString::from(v))
+ }
+
+ fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ Ok(InternalString::from(v))
+ }
+
+ fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ match std::str::from_utf8(v) {
+ Ok(s) => Ok(InternalString::from(s)),
+ Err(_) => Err(serde::de::Error::invalid_value(
+ serde::de::Unexpected::Bytes(v),
+ &self,
+ )),
+ }
+ }
+
+ fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ match String::from_utf8(v) {
+ Ok(s) => Ok(InternalString::from(s)),
+ Err(e) => Err(serde::de::Error::invalid_value(
+ serde::de::Unexpected::Bytes(&e.into_bytes()),
+ &self,
+ )),
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/item.rs b/vendor/toml_edit-0.19.11/src/item.rs
new file mode 100644
index 000000000..48a1a3566
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/item.rs
@@ -0,0 +1,381 @@
+use std::str::FromStr;
+
+use toml_datetime::*;
+
+use crate::array_of_tables::ArrayOfTables;
+use crate::table::TableLike;
+use crate::{Array, InlineTable, Table, Value};
+
+/// Type representing either a value, a table, an array of tables, or none.
+#[derive(Debug, Clone)]
+pub enum Item {
+ /// Type representing none.
+ None,
+ /// Type representing value.
+ Value(Value),
+ /// Type representing table.
+ Table(Table),
+ /// Type representing array of tables.
+ ArrayOfTables(ArrayOfTables),
+}
+
+impl Item {
+ /// Sets `self` to the given item iff `self` is none and
+ /// returns a mutable reference to `self`.
+ pub fn or_insert(&mut self, item: Item) -> &mut Item {
+ if self.is_none() {
+ *self = item
+ }
+ self
+ }
+}
+
+// TODO: This should be generated by macro or derive
+/// Downcasting
+impl Item {
+ /// Text description of value type
+ pub fn type_name(&self) -> &'static str {
+ match self {
+ Item::None => "none",
+ Item::Value(v) => v.type_name(),
+ Item::Table(..) => "table",
+ Item::ArrayOfTables(..) => "array of tables",
+ }
+ }
+
+ /// 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.
+ /// - 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: crate::index::Index>(&self, index: I) -> Option<&Item> {
+ 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.
+ /// - 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: crate::index::Index>(&mut self, index: I) -> Option<&mut Item> {
+ index.index_mut(self)
+ }
+
+ /// Casts `self` to value.
+ pub fn as_value(&self) -> Option<&Value> {
+ match *self {
+ Item::Value(ref v) => Some(v),
+ _ => None,
+ }
+ }
+ /// Casts `self` to table.
+ pub fn as_table(&self) -> Option<&Table> {
+ match *self {
+ Item::Table(ref t) => Some(t),
+ _ => None,
+ }
+ }
+ /// Casts `self` to array of tables.
+ pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> {
+ match *self {
+ Item::ArrayOfTables(ref a) => Some(a),
+ _ => None,
+ }
+ }
+ /// Casts `self` to mutable value.
+ pub fn as_value_mut(&mut self) -> Option<&mut Value> {
+ match *self {
+ Item::Value(ref mut v) => Some(v),
+ _ => None,
+ }
+ }
+ /// Casts `self` to mutable table.
+ pub fn as_table_mut(&mut self) -> Option<&mut Table> {
+ match *self {
+ Item::Table(ref mut t) => Some(t),
+ _ => None,
+ }
+ }
+ /// Casts `self` to mutable array of tables.
+ pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> {
+ match *self {
+ Item::ArrayOfTables(ref mut a) => Some(a),
+ _ => None,
+ }
+ }
+ /// Casts `self` to value.
+ pub fn into_value(self) -> Result<Value, Self> {
+ match self {
+ Item::None => Err(self),
+ Item::Value(v) => Ok(v),
+ Item::Table(v) => {
+ let v = v.into_inline_table();
+ Ok(Value::InlineTable(v))
+ }
+ Item::ArrayOfTables(v) => {
+ let v = v.into_array();
+ Ok(Value::Array(v))
+ }
+ }
+ }
+ /// In-place convert to a value
+ pub fn make_value(&mut self) {
+ let other = std::mem::take(self);
+ let other = other.into_value().map(Item::Value).unwrap_or(Item::None);
+ *self = other;
+ }
+ /// Casts `self` to table.
+ pub fn into_table(self) -> Result<Table, Self> {
+ match self {
+ Item::Table(t) => Ok(t),
+ Item::Value(Value::InlineTable(t)) => Ok(t.into_table()),
+ _ => Err(self),
+ }
+ }
+ /// Casts `self` to array of tables.
+ pub fn into_array_of_tables(self) -> Result<ArrayOfTables, Self> {
+ match self {
+ Item::ArrayOfTables(a) => Ok(a),
+ Item::Value(Value::Array(a)) => {
+ if a.is_empty() {
+ Err(Item::Value(Value::Array(a)))
+ } else if a.iter().all(|v| v.is_inline_table()) {
+ let mut aot = ArrayOfTables::new();
+ aot.values = a.values;
+ for value in aot.values.iter_mut() {
+ value.make_item();
+ }
+ Ok(aot)
+ } else {
+ Err(Item::Value(Value::Array(a)))
+ }
+ }
+ _ => Err(self),
+ }
+ }
+ // Starting private because the name is unclear
+ pub(crate) fn make_item(&mut self) {
+ let other = std::mem::take(self);
+ let other = match other.into_table().map(crate::Item::Table) {
+ Ok(i) => i,
+ Err(i) => i,
+ };
+ let other = match other.into_array_of_tables().map(crate::Item::ArrayOfTables) {
+ Ok(i) => i,
+ Err(i) => i,
+ };
+ *self = other;
+ }
+ /// Returns true iff `self` is a value.
+ pub fn is_value(&self) -> bool {
+ self.as_value().is_some()
+ }
+ /// Returns true iff `self` is a table.
+ pub fn is_table(&self) -> bool {
+ self.as_table().is_some()
+ }
+ /// Returns true iff `self` is an array of tables.
+ pub fn is_array_of_tables(&self) -> bool {
+ self.as_array_of_tables().is_some()
+ }
+ /// Returns true iff `self` is `None`.
+ pub fn is_none(&self) -> bool {
+ matches!(*self, Item::None)
+ }
+
+ // Duplicate Value downcasting API
+
+ /// Casts `self` to integer.
+ pub fn as_integer(&self) -> Option<i64> {
+ self.as_value().and_then(Value::as_integer)
+ }
+
+ /// Returns true iff `self` is an integer.
+ pub fn is_integer(&self) -> bool {
+ self.as_integer().is_some()
+ }
+
+ /// Casts `self` to float.
+ pub fn as_float(&self) -> Option<f64> {
+ self.as_value().and_then(Value::as_float)
+ }
+
+ /// Returns true iff `self` is a float.
+ pub fn is_float(&self) -> bool {
+ self.as_float().is_some()
+ }
+
+ /// Casts `self` to boolean.
+ pub fn as_bool(&self) -> Option<bool> {
+ self.as_value().and_then(Value::as_bool)
+ }
+
+ /// Returns true iff `self` is a boolean.
+ pub fn is_bool(&self) -> bool {
+ self.as_bool().is_some()
+ }
+
+ /// Casts `self` to str.
+ pub fn as_str(&self) -> Option<&str> {
+ self.as_value().and_then(Value::as_str)
+ }
+
+ /// Returns true iff `self` is a string.
+ pub fn is_str(&self) -> bool {
+ self.as_str().is_some()
+ }
+
+ /// Casts `self` to date-time.
+ pub fn as_datetime(&self) -> Option<&Datetime> {
+ self.as_value().and_then(Value::as_datetime)
+ }
+
+ /// Returns true iff `self` is a date-time.
+ pub fn is_datetime(&self) -> bool {
+ self.as_datetime().is_some()
+ }
+
+ /// Casts `self` to array.
+ pub fn as_array(&self) -> Option<&Array> {
+ self.as_value().and_then(Value::as_array)
+ }
+
+ /// Casts `self` to mutable array.
+ pub fn as_array_mut(&mut self) -> Option<&mut Array> {
+ self.as_value_mut().and_then(Value::as_array_mut)
+ }
+
+ /// Returns true iff `self` is an array.
+ pub fn is_array(&self) -> bool {
+ self.as_array().is_some()
+ }
+
+ /// Casts `self` to inline table.
+ pub fn as_inline_table(&self) -> Option<&InlineTable> {
+ self.as_value().and_then(Value::as_inline_table)
+ }
+
+ /// Casts `self` to mutable inline table.
+ pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
+ self.as_value_mut().and_then(Value::as_inline_table_mut)
+ }
+
+ /// Returns true iff `self` is an inline table.
+ pub fn is_inline_table(&self) -> bool {
+ self.as_inline_table().is_some()
+ }
+
+ /// Casts `self` to either a table or an inline table.
+ pub fn as_table_like(&self) -> Option<&dyn TableLike> {
+ self.as_table()
+ .map(|t| t as &dyn TableLike)
+ .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
+ }
+
+ /// Casts `self` to either a table or an inline table.
+ pub fn as_table_like_mut(&mut self) -> Option<&mut dyn TableLike> {
+ match self {
+ Item::Table(t) => Some(t as &mut dyn TableLike),
+ Item::Value(Value::InlineTable(t)) => Some(t as &mut dyn TableLike),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is either a table, or an inline table.
+ pub fn is_table_like(&self) -> bool {
+ self.as_table_like().is_some()
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ match self {
+ Item::None => None,
+ Item::Value(v) => v.span(),
+ Item::Table(v) => v.span(),
+ Item::ArrayOfTables(v) => v.span(),
+ }
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ match self {
+ Item::None => {}
+ Item::Value(v) => v.despan(input),
+ Item::Table(v) => v.despan(input),
+ Item::ArrayOfTables(v) => v.despan(input),
+ }
+ }
+}
+
+impl Default for Item {
+ fn default() -> Self {
+ Item::None
+ }
+}
+
+impl FromStr for Item {
+ type Err = crate::TomlError;
+
+ /// Parses a value from a &str
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let value = s.parse::<Value>()?;
+ Ok(Item::Value(value))
+ }
+}
+
+impl std::fmt::Display for Item {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match &self {
+ Item::None => Ok(()),
+ Item::Value(v) => v.fmt(f),
+ Item::Table(v) => v.fmt(f),
+ Item::ArrayOfTables(v) => v.fmt(f),
+ }
+ }
+}
+
+/// Returns a formatted value.
+///
+/// Since formatting is part of a `Value`, the right hand side of the
+/// assignment needs to be decorated with a space before the value.
+/// The `value` function does just that.
+///
+/// # Examples
+/// ```rust
+/// # use snapbox::assert_eq;
+/// # use toml_edit::*;
+/// let mut table = Table::default();
+/// let mut array = Array::default();
+/// array.push("hello");
+/// array.push("\\, world"); // \ is only allowed in a literal string
+/// table["key1"] = value("value1");
+/// table["key2"] = value(42);
+/// table["key3"] = value(array);
+/// assert_eq(table.to_string(),
+/// r#"key1 = "value1"
+/// key2 = 42
+/// key3 = ["hello", '\, world']
+/// "#);
+/// ```
+pub fn value<V: Into<Value>>(v: V) -> Item {
+ Item::Value(v.into())
+}
+
+/// Returns an empty table.
+pub fn table() -> Item {
+ Item::Table(Table::new())
+}
+
+/// Returns an empty array of tables.
+pub fn array() -> Item {
+ Item::ArrayOfTables(ArrayOfTables::new())
+}
diff --git a/vendor/toml_edit-0.19.11/src/key.rs b/vendor/toml_edit-0.19.11/src/key.rs
new file mode 100644
index 000000000..b7038c36d
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/key.rs
@@ -0,0 +1,333 @@
+use std::borrow::Cow;
+use std::str::FromStr;
+
+use crate::encode::{to_string_repr, StringStyle};
+use crate::parser;
+use crate::parser::key::is_unquoted_char;
+use crate::repr::{Decor, Repr};
+use crate::InternalString;
+
+/// Key as part of a Key/Value Pair or a table header.
+///
+/// # Examples
+///
+/// ```notrust
+/// [dependencies."nom"]
+/// version = "5.0"
+/// 'literal key' = "nonsense"
+/// "basic string key" = 42
+/// ```
+///
+/// There are 3 types of keys:
+///
+/// 1. Bare keys (`version` and `dependencies`)
+///
+/// 2. Basic quoted keys (`"basic string key"` and `"nom"`)
+///
+/// 3. Literal quoted keys (`'literal key'`)
+///
+/// For details see [toml spec](https://github.com/toml-lang/toml/#keyvalue-pair).
+///
+/// To parse a key use `FromStr` trait implementation: `"string".parse::<Key>()`.
+#[derive(Debug, Clone)]
+pub struct Key {
+ key: InternalString,
+ pub(crate) repr: Option<Repr>,
+ pub(crate) decor: Decor,
+}
+
+impl Key {
+ /// Create a new table key
+ pub fn new(key: impl Into<InternalString>) -> Self {
+ Self {
+ key: key.into(),
+ repr: None,
+ decor: Default::default(),
+ }
+ }
+
+ /// Parse a TOML key expression
+ ///
+ /// Unlike `"".parse<Key>()`, this supports dotted keys.
+ pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> {
+ Self::try_parse_path(repr)
+ }
+
+ pub(crate) fn with_repr_unchecked(mut self, repr: Repr) -> Self {
+ self.repr = Some(repr);
+ self
+ }
+
+ /// While creating the `Key`, add `Decor` to it
+ pub fn with_decor(mut self, decor: Decor) -> Self {
+ self.decor = decor;
+ self
+ }
+
+ /// Access a mutable proxy for the `Key`.
+ pub fn as_mut(&mut self) -> KeyMut<'_> {
+ KeyMut { key: self }
+ }
+
+ /// Returns the parsed key value.
+ pub fn get(&self) -> &str {
+ &self.key
+ }
+
+ pub(crate) fn get_internal(&self) -> &InternalString {
+ &self.key
+ }
+
+ /// Returns key raw representation, if available.
+ pub fn as_repr(&self) -> Option<&Repr> {
+ self.repr.as_ref()
+ }
+
+ /// Returns the default raw representation.
+ pub fn default_repr(&self) -> Repr {
+ to_key_repr(&self.key)
+ }
+
+ /// Returns a raw representation.
+ pub fn display_repr(&self) -> Cow<'_, str> {
+ self.as_repr()
+ .and_then(|r| r.as_raw().as_str())
+ .map(Cow::Borrowed)
+ .unwrap_or_else(|| {
+ Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned())
+ })
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ &mut self.decor
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor(&self) -> &Decor {
+ &self.decor
+ }
+
+ /// Returns the location within the original document
+ #[cfg(feature = "serde")]
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.repr.as_ref().and_then(|r| r.span())
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.decor.despan(input);
+ if let Some(repr) = &mut self.repr {
+ repr.despan(input)
+ }
+ }
+
+ /// Auto formats the key.
+ pub fn fmt(&mut self) {
+ self.repr = Some(to_key_repr(&self.key));
+ self.decor.clear();
+ }
+
+ fn try_parse_simple(s: &str) -> Result<Key, crate::TomlError> {
+ let mut key = parser::parse_key(s)?;
+ key.despan(s);
+ Ok(key)
+ }
+
+ fn try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError> {
+ let mut keys = parser::parse_key_path(s)?;
+ for key in &mut keys {
+ key.despan(s);
+ }
+ Ok(keys)
+ }
+}
+
+impl std::ops::Deref for Key {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ self.get()
+ }
+}
+
+impl std::hash::Hash for Key {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.get().hash(state);
+ }
+}
+
+impl Ord for Key {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.get().cmp(other.get())
+ }
+}
+
+impl PartialOrd for Key {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Eq for Key {}
+
+impl PartialEq for Key {
+ #[inline]
+ fn eq(&self, other: &Key) -> bool {
+ PartialEq::eq(self.get(), other.get())
+ }
+}
+
+impl PartialEq<str> for Key {
+ #[inline]
+ fn eq(&self, other: &str) -> bool {
+ PartialEq::eq(self.get(), other)
+ }
+}
+
+impl<'s> PartialEq<&'s str> for Key {
+ #[inline]
+ fn eq(&self, other: &&str) -> bool {
+ PartialEq::eq(self.get(), *other)
+ }
+}
+
+impl PartialEq<String> for Key {
+ #[inline]
+ fn eq(&self, other: &String) -> bool {
+ PartialEq::eq(self.get(), other.as_str())
+ }
+}
+
+impl std::fmt::Display for Key {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ crate::encode::Encode::encode(self, f, None, ("", ""))
+ }
+}
+
+impl FromStr for Key {
+ type Err = crate::TomlError;
+
+ /// Tries to parse a key from a &str,
+ /// if fails, tries as basic quoted key (surrounds with "")
+ /// and then literal quoted key (surrounds with '')
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Key::try_parse_simple(s)
+ }
+}
+
+fn to_key_repr(key: &str) -> Repr {
+ if key.as_bytes().iter().copied().all(is_unquoted_char) && !key.is_empty() {
+ Repr::new_unchecked(key)
+ } else {
+ to_string_repr(key, Some(StringStyle::OnelineSingle), Some(false))
+ }
+}
+
+impl<'b> From<&'b str> for Key {
+ fn from(s: &'b str) -> Self {
+ Key::new(s)
+ }
+}
+
+impl<'b> From<&'b String> for Key {
+ fn from(s: &'b String) -> Self {
+ Key::new(s)
+ }
+}
+
+impl From<String> for Key {
+ fn from(s: String) -> Self {
+ Key::new(s)
+ }
+}
+
+impl From<InternalString> for Key {
+ fn from(s: InternalString) -> Self {
+ Key::new(s)
+ }
+}
+
+#[doc(hidden)]
+impl From<Key> for InternalString {
+ fn from(key: Key) -> InternalString {
+ key.key
+ }
+}
+
+/// A mutable reference to a `Key`
+#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+pub struct KeyMut<'k> {
+ key: &'k mut Key,
+}
+
+impl<'k> KeyMut<'k> {
+ /// Returns the parsed key value.
+ pub fn get(&self) -> &str {
+ self.key.get()
+ }
+
+ /// Returns the raw representation, if available.
+ pub fn as_repr(&self) -> Option<&Repr> {
+ self.key.as_repr()
+ }
+
+ /// Returns the default raw representation.
+ pub fn default_repr(&self) -> Repr {
+ self.key.default_repr()
+ }
+
+ /// Returns a raw representation.
+ pub fn display_repr(&self) -> Cow<str> {
+ self.key.display_repr()
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ self.key.decor_mut()
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor(&self) -> &Decor {
+ self.key.decor()
+ }
+
+ /// Auto formats the key.
+ pub fn fmt(&mut self) {
+ self.key.fmt()
+ }
+}
+
+impl<'k> std::ops::Deref for KeyMut<'k> {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ self.get()
+ }
+}
+
+impl<'s> PartialEq<str> for KeyMut<'s> {
+ #[inline]
+ fn eq(&self, other: &str) -> bool {
+ PartialEq::eq(self.get(), other)
+ }
+}
+
+impl<'s> PartialEq<&'s str> for KeyMut<'s> {
+ #[inline]
+ fn eq(&self, other: &&str) -> bool {
+ PartialEq::eq(self.get(), *other)
+ }
+}
+
+impl<'s> PartialEq<String> for KeyMut<'s> {
+ #[inline]
+ fn eq(&self, other: &String) -> bool {
+ PartialEq::eq(self.get(), other.as_str())
+ }
+}
+
+impl<'k> std::fmt::Display for KeyMut<'k> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(&self.key, f)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/lib.rs b/vendor/toml_edit-0.19.11/src/lib.rs
new file mode 100644
index 000000000..80c0ddda2
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/lib.rs
@@ -0,0 +1,124 @@
+#![deny(missing_docs)]
+// https://github.com/Marwes/combine/issues/172
+#![recursion_limit = "256"]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+
+//! # `toml_edit`
+//!
+//! This crate allows you to parse and modify toml
+//! documents, while preserving comments, spaces *and
+//! relative order* or items.
+//!
+//! If you also need the ease of a more traditional API, see the [`toml`] crate.
+//!
+//! # Example
+//!
+//! ```rust
+//! use toml_edit::{Document, value};
+//!
+//! let toml = r#"
+//! "hello" = 'toml!' # comment
+//! ['a'.b]
+//! "#;
+//! let mut doc = toml.parse::<Document>().expect("invalid doc");
+//! assert_eq!(doc.to_string(), toml);
+//! // let's add a new key/value pair inside a.b: c = {d = "hello"}
+//! doc["a"]["b"]["c"]["d"] = value("hello");
+//! // autoformat inline table a.b.c: { d = "hello" }
+//! doc["a"]["b"]["c"].as_inline_table_mut().map(|t| t.fmt());
+//! let expected = r#"
+//! "hello" = 'toml!' # comment
+//! ['a'.b]
+//! c = { d = "hello" }
+//! "#;
+//! assert_eq!(doc.to_string(), expected);
+//! ```
+//!
+//! ## Controlling formatting
+//!
+//! By default, values are created with default formatting
+//! ```rust
+//! let mut doc = toml_edit::Document::new();
+//! doc["foo"] = toml_edit::value("bar");
+//! let expected = r#"foo = "bar"
+//! "#;
+//! assert_eq!(doc.to_string(), expected);
+//! ```
+//!
+//! You can choose a custom TOML representation by parsing the value.
+//! ```rust
+//! let mut doc = toml_edit::Document::new();
+//! doc["foo"] = "'bar'".parse::<toml_edit::Item>().unwrap();
+//! let expected = r#"foo = 'bar'
+//! "#;
+//! assert_eq!(doc.to_string(), expected);
+//! ```
+//!
+//! ## Limitations
+//!
+//! Things it does not preserve:
+//!
+//! * Scattered array of tables (tables are reordered by default, see [test]).
+//! * Order of dotted keys, see [issue](https://github.com/ordian/toml_edit/issues/163).
+//!
+//! [`toml`]: https://docs.rs/toml/latest/toml/
+//! [test]: https://github.com/ordian/toml_edit/blob/f09bd5d075fdb7d2ef8d9bb3270a34506c276753/tests/test_valid.rs#L84
+
+mod array;
+mod array_of_tables;
+mod document;
+mod encode;
+mod index;
+mod inline_table;
+mod internal_string;
+mod item;
+mod key;
+mod parser;
+mod raw_string;
+mod repr;
+mod table;
+mod value;
+
+#[cfg(feature = "serde")]
+pub mod de;
+#[cfg(feature = "serde")]
+pub mod ser;
+
+pub mod visit;
+pub mod visit_mut;
+
+pub use crate::array::{Array, ArrayIntoIter, ArrayIter, ArrayIterMut};
+pub use crate::array_of_tables::{
+ ArrayOfTables, ArrayOfTablesIntoIter, ArrayOfTablesIter, ArrayOfTablesIterMut,
+};
+pub use crate::document::Document;
+pub use crate::inline_table::{
+ InlineEntry, InlineOccupiedEntry, InlineTable, InlineTableIntoIter, InlineTableIter,
+ InlineTableIterMut, InlineVacantEntry,
+};
+pub use crate::internal_string::InternalString;
+pub use crate::item::{array, table, value, Item};
+pub use crate::key::{Key, KeyMut};
+pub use crate::parser::TomlError;
+pub use crate::raw_string::RawString;
+pub use crate::repr::{Decor, Formatted, Repr};
+pub use crate::table::{
+ Entry, IntoIter, Iter, IterMut, OccupiedEntry, Table, TableLike, VacantEntry,
+};
+pub use crate::value::Value;
+pub use toml_datetime::*;
+
+// Prevent users from some traits.
+pub(crate) mod private {
+ pub trait Sealed {}
+ impl Sealed for usize {}
+ impl Sealed for str {}
+ impl Sealed for String {}
+ impl Sealed for i64 {}
+ impl Sealed for f64 {}
+ impl Sealed for bool {}
+ impl Sealed for crate::Datetime {}
+ impl<'a, T: ?Sized> Sealed for &'a T where T: Sealed {}
+ impl Sealed for crate::Table {}
+ impl Sealed for crate::InlineTable {}
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/array.rs b/vendor/toml_edit-0.19.11/src/parser/array.rs
new file mode 100644
index 000000000..a99bb8241
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/array.rs
@@ -0,0 +1,147 @@
+use winnow::combinator::cut_err;
+use winnow::combinator::delimited;
+use winnow::combinator::opt;
+use winnow::combinator::separated1;
+
+use crate::parser::trivia::ws_comment_newline;
+use crate::parser::value::value;
+use crate::{Array, Item, RawString, Value};
+
+use crate::parser::prelude::*;
+
+// ;; Array
+
+// array = array-open array-values array-close
+pub(crate) fn array(
+ check: RecursionCheck,
+) -> impl FnMut(Input<'_>) -> IResult<Input<'_>, Array, ParserError<'_>> {
+ move |input| {
+ delimited(
+ ARRAY_OPEN,
+ cut_err(array_values(check)),
+ cut_err(ARRAY_CLOSE)
+ .context(Context::Expression("array"))
+ .context(Context::Expected(ParserValue::CharLiteral(']'))),
+ )
+ .parse_next(input)
+ }
+}
+
+// note: we're omitting ws and newlines here, because
+// they should be part of the formatted values
+// array-open = %x5B ws-newline ; [
+pub(crate) const ARRAY_OPEN: u8 = b'[';
+// array-close = ws-newline %x5D ; ]
+const ARRAY_CLOSE: u8 = b']';
+// array-sep = ws %x2C ws ; , Comma
+const ARRAY_SEP: u8 = b',';
+
+// note: this rule is modified
+// array-values = [ ( array-value array-sep array-values ) /
+// array-value / ws-comment-newline ]
+pub(crate) fn array_values(
+ check: RecursionCheck,
+) -> impl FnMut(Input<'_>) -> IResult<Input<'_>, Array, ParserError<'_>> {
+ move |input| {
+ let check = check.recursing(input)?;
+ (
+ opt(
+ (separated1(array_value(check), ARRAY_SEP), opt(ARRAY_SEP)).map(
+ |(v, trailing): (Vec<Value>, Option<u8>)| {
+ (
+ Array::with_vec(v.into_iter().map(Item::Value).collect()),
+ trailing.is_some(),
+ )
+ },
+ ),
+ ),
+ ws_comment_newline.span(),
+ )
+ .try_map::<_, _, std::str::Utf8Error>(|(array, trailing)| {
+ let (mut array, comma) = array.unwrap_or_default();
+ array.set_trailing_comma(comma);
+ array.set_trailing(RawString::with_span(trailing));
+ Ok(array)
+ })
+ .parse_next(input)
+ }
+}
+
+pub(crate) fn array_value(
+ check: RecursionCheck,
+) -> impl FnMut(Input<'_>) -> IResult<Input<'_>, Value, ParserError<'_>> {
+ move |input| {
+ (
+ ws_comment_newline.span(),
+ value(check),
+ ws_comment_newline.span(),
+ )
+ .map(|(ws1, v, ws2)| v.decorated(RawString::with_span(ws1), RawString::with_span(ws2)))
+ .parse_next(input)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn arrays() {
+ let inputs = [
+ r#"[]"#,
+ r#"[ ]"#,
+ r#"[
+ 1, 2, 3
+]"#,
+ r#"[
+ 1,
+ 2, # this is ok
+]"#,
+ r#"[# comment
+# comment2
+
+
+ ]"#,
+ r#"[# comment
+# comment2
+ 1
+
+#sd
+,
+# comment3
+
+ ]"#,
+ r#"[1]"#,
+ r#"[1,]"#,
+ r#"[ "all", 'strings', """are the same""", '''type''']"#,
+ r#"[ 100, -2,]"#,
+ r#"[1, 2, 3]"#,
+ r#"[1.1, 2.1, 3.1]"#,
+ r#"["a", "b", "c"]"#,
+ r#"[ [ 1, 2 ], [3, 4, 5] ]"#,
+ r#"[ [ 1, 2 ], ["a", "b", "c"] ]"#,
+ r#"[ { x = 1, a = "2" }, {a = "a",b = "b", c = "c"} ]"#,
+ ];
+ for input in inputs {
+ dbg!(input);
+ let mut parsed = array(Default::default()).parse(new_input(input));
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan(input);
+ }
+ assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned()));
+ }
+ }
+
+ #[test]
+ fn invalid_arrays() {
+ let invalid_inputs = [r#"["#, r#"[,]"#, r#"[,2]"#, r#"[1e165,,]"#];
+ for input in invalid_inputs {
+ dbg!(input);
+ let mut parsed = array(Default::default()).parse(new_input(input));
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan(input);
+ }
+ assert!(parsed.is_err());
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/datetime.rs b/vendor/toml_edit-0.19.11/src/parser/datetime.rs
new file mode 100644
index 000000000..122a00f5a
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/datetime.rs
@@ -0,0 +1,433 @@
+use std::ops::RangeInclusive;
+
+use crate::parser::errors::CustomError;
+use crate::parser::prelude::*;
+use crate::parser::trivia::from_utf8_unchecked;
+
+use toml_datetime::*;
+use winnow::combinator::alt;
+use winnow::combinator::cut_err;
+use winnow::combinator::opt;
+use winnow::combinator::preceded;
+use winnow::token::one_of;
+use winnow::token::take_while;
+
+// ;; Date and Time (as defined in RFC 3339)
+
+// date-time = offset-date-time / local-date-time / local-date / local-time
+// offset-date-time = full-date time-delim full-time
+// local-date-time = full-date time-delim partial-time
+// local-date = full-date
+// local-time = partial-time
+// full-time = partial-time time-offset
+pub(crate) fn date_time(input: Input<'_>) -> IResult<Input<'_>, Datetime, ParserError<'_>> {
+ alt((
+ (full_date, opt((time_delim, partial_time, opt(time_offset))))
+ .map(|(date, opt)| {
+ match opt {
+ // Offset Date-Time
+ Some((_, time, offset)) => Datetime {
+ date: Some(date),
+ time: Some(time),
+ offset,
+ },
+ // Local Date
+ None => Datetime {
+ date: Some(date),
+ time: None,
+ offset: None,
+ },
+ }
+ })
+ .context(Context::Expression("date-time")),
+ partial_time
+ .map(|t| t.into())
+ .context(Context::Expression("time")),
+ ))
+ .parse_next(input)
+}
+
+// full-date = date-fullyear "-" date-month "-" date-mday
+pub(crate) fn full_date(input: Input<'_>) -> IResult<Input<'_>, Date, ParserError<'_>> {
+ (date_fullyear, b'-', cut_err((date_month, b'-', date_mday)))
+ .map(|(year, _, (month, _, day))| Date { year, month, day })
+ .parse_next(input)
+}
+
+// partial-time = time-hour ":" time-minute ":" time-second [time-secfrac]
+pub(crate) fn partial_time(input: Input<'_>) -> IResult<Input<'_>, Time, ParserError<'_>> {
+ (
+ time_hour,
+ b':',
+ cut_err((time_minute, b':', time_second, opt(time_secfrac))),
+ )
+ .map(|(hour, _, (minute, _, second, nanosecond))| Time {
+ hour,
+ minute,
+ second,
+ nanosecond: nanosecond.unwrap_or_default(),
+ })
+ .parse_next(input)
+}
+
+// time-offset = "Z" / time-numoffset
+// time-numoffset = ( "+" / "-" ) time-hour ":" time-minute
+pub(crate) fn time_offset(input: Input<'_>) -> IResult<Input<'_>, Offset, ParserError<'_>> {
+ alt((
+ one_of((b'Z', b'z')).value(Offset::Z),
+ (
+ one_of((b'+', b'-')),
+ cut_err((time_hour, b':', time_minute)),
+ )
+ .map(|(sign, (hours, _, minutes))| {
+ let sign = match sign {
+ b'+' => 1,
+ b'-' => -1,
+ _ => unreachable!("Parser prevents this"),
+ };
+ sign * (hours as i16 * 60 + minutes as i16)
+ })
+ .verify(|minutes| ((-24 * 60)..=(24 * 60)).contains(minutes))
+ .map(|minutes| Offset::Custom { minutes }),
+ ))
+ .context(Context::Expression("time offset"))
+ .parse_next(input)
+}
+
+// date-fullyear = 4DIGIT
+pub(crate) fn date_fullyear(input: Input<'_>) -> IResult<Input<'_>, u16, ParserError<'_>> {
+ unsigned_digits::<4, 4>
+ .map(|s: &str| s.parse::<u16>().expect("4DIGIT should match u8"))
+ .parse_next(input)
+}
+
+// date-month = 2DIGIT ; 01-12
+pub(crate) fn date_month(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ unsigned_digits::<2, 2>
+ .try_map(|s: &str| {
+ let d = s.parse::<u8>().expect("2DIGIT should match u8");
+ if (1..=12).contains(&d) {
+ Ok(d)
+ } else {
+ Err(CustomError::OutOfRange)
+ }
+ })
+ .parse_next(input)
+}
+
+// date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year
+pub(crate) fn date_mday(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ unsigned_digits::<2, 2>
+ .try_map(|s: &str| {
+ let d = s.parse::<u8>().expect("2DIGIT should match u8");
+ if (1..=31).contains(&d) {
+ Ok(d)
+ } else {
+ Err(CustomError::OutOfRange)
+ }
+ })
+ .parse_next(input)
+}
+
+// time-delim = "T" / %x20 ; T, t, or space
+pub(crate) fn time_delim(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ one_of(TIME_DELIM).parse_next(input)
+}
+
+const TIME_DELIM: (u8, u8, u8) = (b'T', b't', b' ');
+
+// time-hour = 2DIGIT ; 00-23
+pub(crate) fn time_hour(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ unsigned_digits::<2, 2>
+ .try_map(|s: &str| {
+ let d = s.parse::<u8>().expect("2DIGIT should match u8");
+ if (0..=23).contains(&d) {
+ Ok(d)
+ } else {
+ Err(CustomError::OutOfRange)
+ }
+ })
+ .parse_next(input)
+}
+
+// time-minute = 2DIGIT ; 00-59
+pub(crate) fn time_minute(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ unsigned_digits::<2, 2>
+ .try_map(|s: &str| {
+ let d = s.parse::<u8>().expect("2DIGIT should match u8");
+ if (0..=59).contains(&d) {
+ Ok(d)
+ } else {
+ Err(CustomError::OutOfRange)
+ }
+ })
+ .parse_next(input)
+}
+
+// time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules
+pub(crate) fn time_second(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ unsigned_digits::<2, 2>
+ .try_map(|s: &str| {
+ let d = s.parse::<u8>().expect("2DIGIT should match u8");
+ if (0..=60).contains(&d) {
+ Ok(d)
+ } else {
+ Err(CustomError::OutOfRange)
+ }
+ })
+ .parse_next(input)
+}
+
+// time-secfrac = "." 1*DIGIT
+pub(crate) fn time_secfrac(input: Input<'_>) -> IResult<Input<'_>, u32, ParserError<'_>> {
+ static SCALE: [u32; 10] = [
+ 0,
+ 100_000_000,
+ 10_000_000,
+ 1_000_000,
+ 100_000,
+ 10_000,
+ 1_000,
+ 100,
+ 10,
+ 1,
+ ];
+ const INF: usize = usize::MAX;
+ preceded(b'.', unsigned_digits::<1, INF>)
+ .try_map(|mut repr: &str| -> Result<u32, CustomError> {
+ let max_digits = SCALE.len() - 1;
+ if max_digits < repr.len() {
+ // Millisecond precision is required. Further precision of fractional seconds is
+ // implementation-specific. If the value contains greater precision than the
+ // implementation can support, the additional precision must be truncated, not rounded.
+ repr = &repr[0..max_digits];
+ }
+
+ let v = repr.parse::<u32>().map_err(|_| CustomError::OutOfRange)?;
+ let num_digits = repr.len();
+
+ // scale the number accordingly.
+ let scale = SCALE.get(num_digits).ok_or(CustomError::OutOfRange)?;
+ let v = v.checked_mul(*scale).ok_or(CustomError::OutOfRange)?;
+ Ok(v)
+ })
+ .parse_next(input)
+}
+
+pub(crate) fn unsigned_digits<const MIN: usize, const MAX: usize>(
+ input: Input<'_>,
+) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ take_while(MIN..=MAX, DIGIT)
+ .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`is_ascii_digit` filters out on-ASCII") })
+ .parse_next(input)
+}
+
+// DIGIT = %x30-39 ; 0-9
+const DIGIT: RangeInclusive<u8> = b'0'..=b'9';
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn offset_date_time() {
+ let inputs = [
+ (
+ "1979-05-27T07:32:00Z",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: Some(Time {
+ hour: 7,
+ minute: 32,
+ second: 0,
+ nanosecond: 0,
+ }),
+ offset: Some(Offset::Z),
+ },
+ ),
+ (
+ "1979-05-27T00:32:00-07:00",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: Some(Time {
+ hour: 0,
+ minute: 32,
+ second: 0,
+ nanosecond: 0,
+ }),
+ offset: Some(Offset::Custom { minutes: -7 * 60 }),
+ },
+ ),
+ (
+ "1979-05-27T00:32:00-00:36",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: Some(Time {
+ hour: 0,
+ minute: 32,
+ second: 0,
+ nanosecond: 0,
+ }),
+ offset: Some(Offset::Custom { minutes: -36 }),
+ },
+ ),
+ (
+ "1979-05-27T00:32:00.999999",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: Some(Time {
+ hour: 0,
+ minute: 32,
+ second: 0,
+ nanosecond: 999999000,
+ }),
+ offset: None,
+ },
+ ),
+ ];
+ for (input, expected) in inputs {
+ dbg!(input);
+ let actual = date_time.parse(new_input(input)).unwrap();
+ assert_eq!(expected, actual);
+ }
+ }
+
+ #[test]
+ fn local_date_time() {
+ let inputs = [
+ (
+ "1979-05-27T07:32:00",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: Some(Time {
+ hour: 7,
+ minute: 32,
+ second: 0,
+ nanosecond: 0,
+ }),
+ offset: None,
+ },
+ ),
+ (
+ "1979-05-27T00:32:00.999999",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: Some(Time {
+ hour: 0,
+ minute: 32,
+ second: 0,
+ nanosecond: 999999000,
+ }),
+ offset: None,
+ },
+ ),
+ ];
+ for (input, expected) in inputs {
+ dbg!(input);
+ let actual = date_time.parse(new_input(input)).unwrap();
+ assert_eq!(expected, actual);
+ }
+ }
+
+ #[test]
+ fn local_date() {
+ let inputs = [
+ (
+ "1979-05-27",
+ Datetime {
+ date: Some(Date {
+ year: 1979,
+ month: 5,
+ day: 27,
+ }),
+ time: None,
+ offset: None,
+ },
+ ),
+ (
+ "2017-07-20",
+ Datetime {
+ date: Some(Date {
+ year: 2017,
+ month: 7,
+ day: 20,
+ }),
+ time: None,
+ offset: None,
+ },
+ ),
+ ];
+ for (input, expected) in inputs {
+ dbg!(input);
+ let actual = date_time.parse(new_input(input)).unwrap();
+ assert_eq!(expected, actual);
+ }
+ }
+
+ #[test]
+ fn local_time() {
+ let inputs = [
+ (
+ "07:32:00",
+ Datetime {
+ date: None,
+ time: Some(Time {
+ hour: 7,
+ minute: 32,
+ second: 0,
+ nanosecond: 0,
+ }),
+ offset: None,
+ },
+ ),
+ (
+ "00:32:00.999999",
+ Datetime {
+ date: None,
+ time: Some(Time {
+ hour: 0,
+ minute: 32,
+ second: 0,
+ nanosecond: 999999000,
+ }),
+ offset: None,
+ },
+ ),
+ ];
+ for (input, expected) in inputs {
+ dbg!(input);
+ let actual = date_time.parse(new_input(input)).unwrap();
+ assert_eq!(expected, actual);
+ }
+ }
+
+ #[test]
+ fn time_fraction_truncated() {
+ let input = "1987-07-05T17:45:00.123456789012345Z";
+ date_time.parse(new_input(input)).unwrap();
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/document.rs b/vendor/toml_edit-0.19.11/src/parser/document.rs
new file mode 100644
index 000000000..791185b68
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/document.rs
@@ -0,0 +1,148 @@
+use std::cell::RefCell;
+
+use winnow::combinator::cut_err;
+use winnow::combinator::eof;
+use winnow::combinator::opt;
+use winnow::combinator::peek;
+use winnow::combinator::repeat;
+use winnow::error::FromExternalError;
+use winnow::token::any;
+use winnow::token::one_of;
+
+use crate::document::Document;
+use crate::key::Key;
+use crate::parser::inline_table::KEYVAL_SEP;
+use crate::parser::key::key;
+use crate::parser::prelude::*;
+use crate::parser::state::ParseState;
+use crate::parser::table::table;
+use crate::parser::trivia::{comment, line_ending, line_trailing, newline, ws};
+use crate::parser::value::value;
+use crate::table::TableKeyValue;
+use crate::Item;
+use crate::RawString;
+
+// ;; TOML
+
+// toml = expression *( newline expression )
+
+// expression = ( ( ws comment ) /
+// ( ws keyval ws [ comment ] ) /
+// ( ws table ws [ comment ] ) /
+// ws )
+pub(crate) fn document(input: Input<'_>) -> IResult<Input<'_>, Document, ParserError<'_>> {
+ let state = RefCell::new(ParseState::default());
+ let state_ref = &state;
+
+ let (i, _o) = (
+ // Remove BOM if present
+ opt(b"\xEF\xBB\xBF"),
+ parse_ws(state_ref),
+ repeat(0.., (
+ dispatch! {peek(any);
+ crate::parser::trivia::COMMENT_START_SYMBOL => cut_err(parse_comment(state_ref)),
+ crate::parser::table::STD_TABLE_OPEN => cut_err(table(state_ref)),
+ crate::parser::trivia::LF |
+ crate::parser::trivia::CR => parse_newline(state_ref),
+ _ => cut_err(keyval(state_ref)),
+ },
+ parse_ws(state_ref),
+ ))
+ .map(|()| ()),
+ eof,
+ )
+ .parse_next(input)?;
+ state
+ .into_inner()
+ .into_document()
+ .map(|document| (i, document))
+ .map_err(|err| {
+ winnow::error::ErrMode::Backtrack(ParserError::from_external_error(
+ i,
+ winnow::error::ErrorKind::Verify,
+ err,
+ ))
+ })
+}
+
+pub(crate) fn parse_comment<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'_>> + 's {
+ move |i| {
+ (comment, line_ending)
+ .span()
+ .map(|span| {
+ state.borrow_mut().on_comment(span);
+ })
+ .parse_next(i)
+ }
+}
+
+pub(crate) fn parse_ws<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
+ move |i| {
+ ws.span()
+ .map(|span| state.borrow_mut().on_ws(span))
+ .parse_next(i)
+ }
+}
+
+pub(crate) fn parse_newline<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
+ move |i| {
+ newline
+ .span()
+ .map(|span| state.borrow_mut().on_ws(span))
+ .parse_next(i)
+ }
+}
+
+pub(crate) fn keyval<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
+ move |i| {
+ parse_keyval
+ .try_map(|(p, kv)| state.borrow_mut().on_keyval(p, kv))
+ .parse_next(i)
+ }
+}
+
+// keyval = key keyval-sep val
+pub(crate) fn parse_keyval(
+ input: Input<'_>,
+) -> IResult<Input<'_>, (Vec<Key>, TableKeyValue), ParserError<'_>> {
+ (
+ key,
+ cut_err((
+ one_of(KEYVAL_SEP)
+ .context(Context::Expected(ParserValue::CharLiteral('.')))
+ .context(Context::Expected(ParserValue::CharLiteral('='))),
+ (
+ ws.span(),
+ value(RecursionCheck::default()),
+ line_trailing
+ .context(Context::Expected(ParserValue::CharLiteral('\n')))
+ .context(Context::Expected(ParserValue::CharLiteral('#'))),
+ ),
+ )),
+ )
+ .try_map::<_, _, std::str::Utf8Error>(|(key, (_, v))| {
+ let mut path = key;
+ let key = path.pop().expect("grammar ensures at least 1");
+
+ let (pre, v, suf) = v;
+ let pre = RawString::with_span(pre);
+ let suf = RawString::with_span(suf);
+ let v = v.decorated(pre, suf);
+ Ok((
+ path,
+ TableKeyValue {
+ key,
+ value: Item::Value(v),
+ },
+ ))
+ })
+ .parse_next(input)
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/errors.rs b/vendor/toml_edit-0.19.11/src/parser/errors.rs
new file mode 100644
index 000000000..4e3825f99
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/errors.rs
@@ -0,0 +1,476 @@
+use std::error::Error as StdError;
+use std::fmt::{Display, Formatter, Result};
+
+use crate::parser::prelude::*;
+use crate::Key;
+
+use winnow::BStr;
+
+/// Type representing a TOML parse error
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub struct TomlError {
+ message: String,
+ original: Option<String>,
+ keys: Vec<String>,
+ span: Option<std::ops::Range<usize>>,
+}
+
+impl TomlError {
+ pub(crate) fn new(error: ParserError<'_>, original: Input<'_>) -> Self {
+ use winnow::stream::Offset;
+ use winnow::stream::Stream;
+
+ let offset = original.offset_to(&error.input);
+ let span = if offset == original.len() {
+ offset..offset
+ } else {
+ offset..(offset + 1)
+ };
+
+ let message = error.to_string();
+ let original = original.next_slice(original.eof_offset()).1;
+
+ Self {
+ message,
+ original: Some(
+ String::from_utf8(original.to_owned()).expect("original document was utf8"),
+ ),
+ keys: Vec::new(),
+ span: Some(span),
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ pub(crate) fn custom(message: String, span: Option<std::ops::Range<usize>>) -> Self {
+ Self {
+ message,
+ original: None,
+ keys: Vec::new(),
+ span,
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ pub(crate) fn add_key(&mut self, key: String) {
+ self.keys.insert(0, key);
+ }
+
+ /// What went wrong
+ pub fn message(&self) -> &str {
+ &self.message
+ }
+
+ /// The start/end index into the original document where the error occurred
+ pub fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.span.clone()
+ }
+
+ #[cfg(feature = "serde")]
+ pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) {
+ self.span = span;
+ }
+
+ #[cfg(feature = "serde")]
+ pub(crate) fn set_original(&mut self, original: Option<String>) {
+ self.original = original;
+ }
+}
+
+/// Displays a TOML parse error
+///
+/// # Example
+///
+/// TOML parse error at line 1, column 10
+/// |
+/// 1 | 00:32:00.a999999
+/// | ^
+/// Unexpected `a`
+/// Expected `digit`
+/// While parsing a Time
+/// While parsing a Date-Time
+impl Display for TomlError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let mut context = false;
+ if let (Some(original), Some(span)) = (&self.original, self.span()) {
+ context = true;
+
+ let (line, column) = translate_position(original.as_bytes(), span.start);
+ let line_num = line + 1;
+ let col_num = column + 1;
+ let gutter = line_num.to_string().len();
+ let content = original.split('\n').nth(line).expect("valid line number");
+
+ writeln!(
+ f,
+ "TOML parse error at line {}, column {}",
+ line_num, col_num
+ )?;
+ // |
+ for _ in 0..=gutter {
+ write!(f, " ")?;
+ }
+ writeln!(f, "|")?;
+
+ // 1 | 00:32:00.a999999
+ write!(f, "{} | ", line_num)?;
+ writeln!(f, "{}", content)?;
+
+ // | ^
+ for _ in 0..=gutter {
+ write!(f, " ")?;
+ }
+ write!(f, "|")?;
+ for _ in 0..=column {
+ write!(f, " ")?;
+ }
+ // The span will be empty at eof, so we need to make sure we always print at least
+ // one `^`
+ write!(f, "^")?;
+ for _ in (span.start + 1)..(span.end.min(span.start + content.len())) {
+ write!(f, "^")?;
+ }
+ writeln!(f)?;
+ }
+ writeln!(f, "{}", self.message)?;
+ if !context && !self.keys.is_empty() {
+ writeln!(f, "in `{}`", self.keys.join("."))?;
+ }
+
+ Ok(())
+ }
+}
+
+impl StdError for TomlError {
+ fn description(&self) -> &'static str {
+ "TOML parse error"
+ }
+}
+
+#[derive(Debug)]
+pub(crate) struct ParserError<'b> {
+ input: Input<'b>,
+ context: Vec<Context>,
+ cause: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
+}
+
+impl<'b> winnow::error::ParseError<Input<'b>> for ParserError<'b> {
+ fn from_error_kind(input: Input<'b>, _kind: winnow::error::ErrorKind) -> Self {
+ Self {
+ input,
+ context: Default::default(),
+ cause: Default::default(),
+ }
+ }
+
+ fn append(self, _input: Input<'b>, _kind: winnow::error::ErrorKind) -> Self {
+ self
+ }
+
+ fn or(self, other: Self) -> Self {
+ other
+ }
+}
+
+impl<'b> winnow::error::ParseError<&'b str> for ParserError<'b> {
+ fn from_error_kind(input: &'b str, _kind: winnow::error::ErrorKind) -> Self {
+ Self {
+ input: Input::new(BStr::new(input)),
+ context: Default::default(),
+ cause: Default::default(),
+ }
+ }
+
+ fn append(self, _input: &'b str, _kind: winnow::error::ErrorKind) -> Self {
+ self
+ }
+
+ fn or(self, other: Self) -> Self {
+ other
+ }
+}
+
+impl<'b> winnow::error::ContextError<Input<'b>, Context> for ParserError<'b> {
+ fn add_context(mut self, _input: Input<'b>, ctx: Context) -> Self {
+ self.context.push(ctx);
+ self
+ }
+}
+
+impl<'b, E: std::error::Error + Send + Sync + 'static>
+ winnow::error::FromExternalError<Input<'b>, E> for ParserError<'b>
+{
+ fn from_external_error(input: Input<'b>, _kind: winnow::error::ErrorKind, e: E) -> Self {
+ Self {
+ input,
+ context: Default::default(),
+ cause: Some(Box::new(e)),
+ }
+ }
+}
+
+impl<'b, E: std::error::Error + Send + Sync + 'static> winnow::error::FromExternalError<&'b str, E>
+ for ParserError<'b>
+{
+ fn from_external_error(input: &'b str, _kind: winnow::error::ErrorKind, e: E) -> Self {
+ Self {
+ input: Input::new(BStr::new(input)),
+ context: Default::default(),
+ cause: Some(Box::new(e)),
+ }
+ }
+}
+
+// For tests
+impl<'b> std::cmp::PartialEq for ParserError<'b> {
+ fn eq(&self, other: &Self) -> bool {
+ self.input == other.input
+ && self.context == other.context
+ && self.cause.as_ref().map(ToString::to_string)
+ == other.cause.as_ref().map(ToString::to_string)
+ }
+}
+
+impl<'a> std::fmt::Display for ParserError<'a> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let expression = self.context.iter().find_map(|c| match c {
+ Context::Expression(c) => Some(c),
+ _ => None,
+ });
+ let expected = self
+ .context
+ .iter()
+ .filter_map(|c| match c {
+ Context::Expected(c) => Some(c),
+ _ => None,
+ })
+ .collect::<Vec<_>>();
+
+ let mut newline = false;
+
+ if let Some(expression) = expression {
+ newline = true;
+
+ write!(f, "invalid {}", expression)?;
+ }
+
+ if !expected.is_empty() {
+ if newline {
+ writeln!(f)?;
+ }
+ newline = true;
+
+ write!(f, "expected ")?;
+ for (i, expected) in expected.iter().enumerate() {
+ if i != 0 {
+ write!(f, ", ")?;
+ }
+ write!(f, "{}", expected)?;
+ }
+ }
+ if let Some(cause) = &self.cause {
+ if newline {
+ writeln!(f)?;
+ }
+ write!(f, "{}", cause)?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub(crate) enum Context {
+ Expression(&'static str),
+ Expected(ParserValue),
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub(crate) enum ParserValue {
+ CharLiteral(char),
+ StringLiteral(&'static str),
+ Description(&'static str),
+}
+
+impl std::fmt::Display for ParserValue {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ ParserValue::CharLiteral('\n') => "newline".fmt(f),
+ ParserValue::CharLiteral('`') => "'`'".fmt(f),
+ ParserValue::CharLiteral(c) if c.is_ascii_control() => {
+ write!(f, "`{}`", c.escape_debug())
+ }
+ ParserValue::CharLiteral(c) => write!(f, "`{}`", c),
+ ParserValue::StringLiteral(c) => write!(f, "`{}`", c),
+ ParserValue::Description(c) => write!(f, "{}", c),
+ }
+ }
+}
+
+fn translate_position(input: &[u8], index: usize) -> (usize, usize) {
+ if input.is_empty() {
+ return (0, index);
+ }
+
+ let safe_index = index.min(input.len() - 1);
+ let column_offset = index - safe_index;
+ let index = safe_index;
+
+ let nl = input[0..index]
+ .iter()
+ .rev()
+ .enumerate()
+ .find(|(_, b)| **b == b'\n')
+ .map(|(nl, _)| index - nl - 1);
+ let line_start = match nl {
+ Some(nl) => nl + 1,
+ None => 0,
+ };
+ let line = input[0..line_start].iter().filter(|b| **b == b'\n').count();
+ let line = line;
+
+ let column = std::str::from_utf8(&input[line_start..=index])
+ .map(|s| s.chars().count() - 1)
+ .unwrap_or_else(|_| index - line_start);
+ let column = column + column_offset;
+
+ (line, column)
+}
+
+#[cfg(test)]
+mod test_translate_position {
+ use super::*;
+
+ #[test]
+ fn empty() {
+ let input = b"";
+ let index = 0;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (0, 0));
+ }
+
+ #[test]
+ fn start() {
+ let input = b"Hello";
+ let index = 0;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (0, 0));
+ }
+
+ #[test]
+ fn end() {
+ let input = b"Hello";
+ let index = input.len() - 1;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (0, input.len() - 1));
+ }
+
+ #[test]
+ fn after() {
+ let input = b"Hello";
+ let index = input.len();
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (0, input.len()));
+ }
+
+ #[test]
+ fn first_line() {
+ let input = b"Hello\nWorld\n";
+ let index = 2;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (0, 2));
+ }
+
+ #[test]
+ fn end_of_line() {
+ let input = b"Hello\nWorld\n";
+ let index = 5;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (0, 5));
+ }
+
+ #[test]
+ fn start_of_second_line() {
+ let input = b"Hello\nWorld\n";
+ let index = 6;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (1, 0));
+ }
+
+ #[test]
+ fn second_line() {
+ let input = b"Hello\nWorld\n";
+ let index = 8;
+ let position = translate_position(&input[..], index);
+ assert_eq!(position, (1, 2));
+ }
+}
+
+#[derive(Debug, Clone)]
+pub(crate) enum CustomError {
+ DuplicateKey {
+ key: String,
+ table: Option<Vec<Key>>,
+ },
+ DottedKeyExtendWrongType {
+ key: Vec<Key>,
+ actual: &'static str,
+ },
+ OutOfRange,
+ #[cfg_attr(feature = "unbounded", allow(dead_code))]
+ RecursionLimitExceeded,
+}
+
+impl CustomError {
+ pub(crate) fn duplicate_key(path: &[Key], i: usize) -> Self {
+ assert!(i < path.len());
+ let key = &path[i];
+ let repr = key.display_repr();
+ Self::DuplicateKey {
+ key: repr.into(),
+ table: Some(path[..i].to_vec()),
+ }
+ }
+
+ pub(crate) fn extend_wrong_type(path: &[Key], i: usize, actual: &'static str) -> Self {
+ assert!(i < path.len());
+ Self::DottedKeyExtendWrongType {
+ key: path[..=i].to_vec(),
+ actual,
+ }
+ }
+}
+
+impl StdError for CustomError {
+ fn description(&self) -> &'static str {
+ "TOML parse error"
+ }
+}
+
+impl Display for CustomError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ match self {
+ CustomError::DuplicateKey { key, table } => {
+ if let Some(table) = table {
+ if table.is_empty() {
+ write!(f, "duplicate key `{}` in document root", key)
+ } else {
+ let path = table.iter().map(|k| k.get()).collect::<Vec<_>>().join(".");
+ write!(f, "duplicate key `{}` in table `{}`", key, path)
+ }
+ } else {
+ write!(f, "duplicate key `{}`", key)
+ }
+ }
+ CustomError::DottedKeyExtendWrongType { key, actual } => {
+ let path = key.iter().map(|k| k.get()).collect::<Vec<_>>().join(".");
+ write!(
+ f,
+ "dotted key `{}` attempted to extend non-table type ({})",
+ path, actual
+ )
+ }
+ CustomError::OutOfRange => write!(f, "value is out of range"),
+ CustomError::RecursionLimitExceeded => write!(f, "recursion limit exceded"),
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/inline_table.rs b/vendor/toml_edit-0.19.11/src/parser/inline_table.rs
new file mode 100644
index 000000000..0a75c2104
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/inline_table.rs
@@ -0,0 +1,182 @@
+use winnow::combinator::cut_err;
+use winnow::combinator::delimited;
+use winnow::combinator::separated0;
+use winnow::token::one_of;
+
+use crate::key::Key;
+use crate::parser::errors::CustomError;
+use crate::parser::key::key;
+use crate::parser::prelude::*;
+use crate::parser::trivia::ws;
+use crate::parser::value::value;
+use crate::table::TableKeyValue;
+use crate::{InlineTable, InternalString, Item, RawString, Value};
+
+use indexmap::map::Entry;
+
+// ;; Inline Table
+
+// inline-table = inline-table-open inline-table-keyvals inline-table-close
+pub(crate) fn inline_table(
+ check: RecursionCheck,
+) -> impl FnMut(Input<'_>) -> IResult<Input<'_>, InlineTable, ParserError<'_>> {
+ move |input| {
+ delimited(
+ INLINE_TABLE_OPEN,
+ cut_err(inline_table_keyvals(check).try_map(|(kv, p)| table_from_pairs(kv, p))),
+ cut_err(INLINE_TABLE_CLOSE)
+ .context(Context::Expression("inline table"))
+ .context(Context::Expected(ParserValue::CharLiteral('}'))),
+ )
+ .parse_next(input)
+ }
+}
+
+fn table_from_pairs(
+ v: Vec<(Vec<Key>, TableKeyValue)>,
+ preamble: RawString,
+) -> Result<InlineTable, CustomError> {
+ let mut root = InlineTable::new();
+ root.set_preamble(preamble);
+ // Assuming almost all pairs will be directly in `root`
+ root.items.reserve(v.len());
+
+ for (path, kv) in v {
+ let table = descend_path(&mut root, &path)?;
+ let key: InternalString = kv.key.get_internal().into();
+ match table.items.entry(key) {
+ Entry::Vacant(o) => {
+ o.insert(kv);
+ }
+ Entry::Occupied(o) => {
+ return Err(CustomError::DuplicateKey {
+ key: o.key().as_str().into(),
+ table: None,
+ });
+ }
+ }
+ }
+ Ok(root)
+}
+
+fn descend_path<'a>(
+ mut table: &'a mut InlineTable,
+ path: &'a [Key],
+) -> Result<&'a mut InlineTable, CustomError> {
+ for (i, key) in path.iter().enumerate() {
+ let entry = table.entry_format(key).or_insert_with(|| {
+ let mut new_table = InlineTable::new();
+ new_table.set_dotted(true);
+
+ Value::InlineTable(new_table)
+ });
+ match *entry {
+ Value::InlineTable(ref mut sweet_child_of_mine) => {
+ table = sweet_child_of_mine;
+ }
+ ref v => {
+ return Err(CustomError::extend_wrong_type(path, i, v.type_name()));
+ }
+ }
+ }
+ Ok(table)
+}
+
+// inline-table-open = %x7B ws ; {
+pub(crate) const INLINE_TABLE_OPEN: u8 = b'{';
+// inline-table-close = ws %x7D ; }
+const INLINE_TABLE_CLOSE: u8 = b'}';
+// inline-table-sep = ws %x2C ws ; , Comma
+const INLINE_TABLE_SEP: u8 = b',';
+// keyval-sep = ws %x3D ws ; =
+pub(crate) const KEYVAL_SEP: u8 = b'=';
+
+// inline-table-keyvals = [ inline-table-keyvals-non-empty ]
+// inline-table-keyvals-non-empty =
+// ( key keyval-sep val inline-table-sep inline-table-keyvals-non-empty ) /
+// ( key keyval-sep val )
+
+fn inline_table_keyvals(
+ check: RecursionCheck,
+) -> impl FnMut(
+ Input<'_>,
+) -> IResult<Input<'_>, (Vec<(Vec<Key>, TableKeyValue)>, RawString), ParserError<'_>> {
+ move |input| {
+ let check = check.recursing(input)?;
+ (
+ separated0(keyval(check), INLINE_TABLE_SEP),
+ ws.span().map(RawString::with_span),
+ )
+ .parse_next(input)
+ }
+}
+
+fn keyval(
+ check: RecursionCheck,
+) -> impl FnMut(Input<'_>) -> IResult<Input<'_>, (Vec<Key>, TableKeyValue), ParserError<'_>> {
+ move |input| {
+ (
+ key,
+ cut_err((
+ one_of(KEYVAL_SEP)
+ .context(Context::Expected(ParserValue::CharLiteral('.')))
+ .context(Context::Expected(ParserValue::CharLiteral('='))),
+ (ws.span(), value(check), ws.span()),
+ )),
+ )
+ .map(|(key, (_, v))| {
+ let mut path = key;
+ let key = path.pop().expect("grammar ensures at least 1");
+
+ let (pre, v, suf) = v;
+ let pre = RawString::with_span(pre);
+ let suf = RawString::with_span(suf);
+ let v = v.decorated(pre, suf);
+ (
+ path,
+ TableKeyValue {
+ key,
+ value: Item::Value(v),
+ },
+ )
+ })
+ .parse_next(input)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn inline_tables() {
+ let inputs = [
+ r#"{}"#,
+ r#"{ }"#,
+ r#"{a = 1e165}"#,
+ r#"{ hello = "world", a = 1}"#,
+ r#"{ hello.world = "a" }"#,
+ ];
+ for input in inputs {
+ dbg!(input);
+ let mut parsed = inline_table(Default::default()).parse(new_input(input));
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan(input);
+ }
+ assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned()));
+ }
+ }
+
+ #[test]
+ fn invalid_inline_tables() {
+ let invalid_inputs = [r#"{a = 1e165"#, r#"{ hello = "world", a = 2, hello = 1}"#];
+ for input in invalid_inputs {
+ dbg!(input);
+ let mut parsed = inline_table(Default::default()).parse(new_input(input));
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan(input);
+ }
+ assert!(parsed.is_err());
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/key.rs b/vendor/toml_edit-0.19.11/src/parser/key.rs
new file mode 100644
index 000000000..eda319307
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/key.rs
@@ -0,0 +1,104 @@
+use std::ops::RangeInclusive;
+
+use winnow::combinator::peek;
+use winnow::combinator::separated1;
+use winnow::token::any;
+use winnow::token::take_while;
+
+use crate::key::Key;
+use crate::parser::errors::CustomError;
+use crate::parser::prelude::*;
+use crate::parser::strings::{basic_string, literal_string};
+use crate::parser::trivia::{from_utf8_unchecked, ws};
+use crate::repr::{Decor, Repr};
+use crate::InternalString;
+use crate::RawString;
+
+// key = simple-key / dotted-key
+// dotted-key = simple-key 1*( dot-sep simple-key )
+pub(crate) fn key(input: Input<'_>) -> IResult<Input<'_>, Vec<Key>, ParserError<'_>> {
+ separated1(
+ (ws.span(), simple_key, ws.span()).map(|(pre, (raw, key), suffix)| {
+ Key::new(key)
+ .with_repr_unchecked(Repr::new_unchecked(raw))
+ .with_decor(Decor::new(
+ RawString::with_span(pre),
+ RawString::with_span(suffix),
+ ))
+ }),
+ DOT_SEP,
+ )
+ .context(Context::Expression("key"))
+ .try_map(|k: Vec<_>| {
+ // Inserting the key will require recursion down the line
+ RecursionCheck::check_depth(k.len())?;
+ Ok::<_, CustomError>(k)
+ })
+ .parse_next(input)
+}
+
+// simple-key = quoted-key / unquoted-key
+// quoted-key = basic-string / literal-string
+pub(crate) fn simple_key(
+ input: Input<'_>,
+) -> IResult<Input<'_>, (RawString, InternalString), ParserError<'_>> {
+ dispatch! {peek(any);
+ crate::parser::strings::QUOTATION_MARK => basic_string
+ .map(|s: std::borrow::Cow<'_, str>| s.as_ref().into()),
+ crate::parser::strings::APOSTROPHE => literal_string.map(|s: &str| s.into()),
+ _ => unquoted_key.map(|s: &str| s.into()),
+ }
+ .with_span()
+ .map(|(k, span)| {
+ let raw = RawString::with_span(span);
+ (raw, k)
+ })
+ .parse_next(input)
+}
+
+// unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
+fn unquoted_key(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ take_while(1.., UNQUOTED_CHAR)
+ .map(|b| unsafe { from_utf8_unchecked(b, "`is_unquoted_char` filters out on-ASCII") })
+ .parse_next(input)
+}
+
+pub(crate) fn is_unquoted_char(c: u8) -> bool {
+ use winnow::stream::ContainsToken;
+ UNQUOTED_CHAR.contains_token(c)
+}
+
+const UNQUOTED_CHAR: (
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+ u8,
+ u8,
+) = (b'A'..=b'Z', b'a'..=b'z', b'0'..=b'9', b'-', b'_');
+
+// dot-sep = ws %x2E ws ; . Period
+const DOT_SEP: u8 = b'.';
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn keys() {
+ let cases = [
+ ("a", "a"),
+ (r#""hello\n ""#, "hello\n "),
+ (r#"'hello\n '"#, "hello\\n "),
+ ];
+
+ for (input, expected) in cases {
+ dbg!(input);
+ let parsed = simple_key.parse(new_input(input));
+ assert_eq!(
+ parsed,
+ Ok((RawString::with_span(0..(input.len())), expected.into())),
+ "Parsing {input:?}"
+ );
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/macros.rs b/vendor/toml_edit-0.19.11/src/parser/macros.rs
new file mode 100644
index 000000000..93050f5ad
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/macros.rs
@@ -0,0 +1,13 @@
+macro_rules! dispatch {
+ ($match_parser: expr; $( $pat:pat $(if $pred:expr)? => $expr: expr ),+ $(,)? ) => {
+ move |i|
+ {
+ let (i, initial) = $match_parser.parse_next(i)?;
+ match initial {
+ $(
+ $pat $(if $pred)? => $expr.parse_next(i),
+ )*
+ }
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/mod.rs b/vendor/toml_edit-0.19.11/src/parser/mod.rs
new file mode 100644
index 000000000..b2ce4bc5e
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/mod.rs
@@ -0,0 +1,302 @@
+#![allow(clippy::type_complexity)]
+
+#[macro_use]
+pub(crate) mod macros;
+
+pub(crate) mod array;
+pub(crate) mod datetime;
+pub(crate) mod document;
+pub(crate) mod errors;
+pub(crate) mod inline_table;
+pub(crate) mod key;
+pub(crate) mod numbers;
+pub(crate) mod state;
+pub(crate) mod strings;
+pub(crate) mod table;
+pub(crate) mod trivia;
+pub(crate) mod value;
+
+pub use errors::TomlError;
+
+pub(crate) fn parse_document(raw: &str) -> Result<crate::Document, TomlError> {
+ use prelude::*;
+
+ let b = new_input(raw);
+ let mut doc = document::document
+ .parse(b)
+ .map_err(|e| TomlError::new(e, b))?;
+ doc.span = Some(0..(raw.len()));
+ doc.original = Some(raw.to_owned());
+ Ok(doc)
+}
+
+pub(crate) fn parse_key(raw: &str) -> Result<crate::Key, TomlError> {
+ use prelude::*;
+
+ let b = new_input(raw);
+ let result = key::simple_key.parse(b);
+ match result {
+ Ok((raw, key)) => {
+ Ok(crate::Key::new(key).with_repr_unchecked(crate::Repr::new_unchecked(raw)))
+ }
+ Err(e) => Err(TomlError::new(e, b)),
+ }
+}
+
+pub(crate) fn parse_key_path(raw: &str) -> Result<Vec<crate::Key>, TomlError> {
+ use prelude::*;
+
+ let b = new_input(raw);
+ let result = key::key.parse(b);
+ match result {
+ Ok(mut keys) => {
+ for key in &mut keys {
+ key.despan(raw);
+ }
+ Ok(keys)
+ }
+ Err(e) => Err(TomlError::new(e, b)),
+ }
+}
+
+pub(crate) fn parse_value(raw: &str) -> Result<crate::Value, TomlError> {
+ use prelude::*;
+
+ let b = new_input(raw);
+ let parsed = value::value(RecursionCheck::default()).parse(b);
+ match parsed {
+ Ok(mut value) => {
+ // Only take the repr and not decor, as its probably not intended
+ value.decor_mut().clear();
+ value.despan(raw);
+ Ok(value)
+ }
+ Err(e) => Err(TomlError::new(e, b)),
+ }
+}
+
+pub(crate) mod prelude {
+ pub(crate) use super::errors::Context;
+ pub(crate) use super::errors::ParserError;
+ pub(crate) use super::errors::ParserValue;
+ pub(crate) use winnow::IResult;
+ pub(crate) use winnow::Parser as _;
+
+ pub(crate) type Input<'b> = winnow::Located<&'b winnow::BStr>;
+
+ pub(crate) fn new_input(s: &str) -> Input<'_> {
+ winnow::Located::new(winnow::BStr::new(s))
+ }
+
+ pub(crate) fn ok_error<I, O, E>(
+ res: IResult<I, O, E>,
+ ) -> Result<Option<(I, O)>, winnow::error::ErrMode<E>> {
+ match res {
+ Ok(ok) => Ok(Some(ok)),
+ Err(winnow::error::ErrMode::Backtrack(_)) => Ok(None),
+ Err(err) => Err(err),
+ }
+ }
+
+ #[allow(dead_code)]
+ pub(crate) fn trace<I: std::fmt::Debug, O: std::fmt::Debug, E: std::fmt::Debug>(
+ context: impl std::fmt::Display,
+ mut parser: impl winnow::Parser<I, O, E>,
+ ) -> impl FnMut(I) -> IResult<I, O, E> {
+ static DEPTH: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
+ move |input: I| {
+ let depth = DEPTH.fetch_add(1, std::sync::atomic::Ordering::SeqCst) * 2;
+ eprintln!("{:depth$}--> {} {:?}", "", context, input);
+ match parser.parse_next(input) {
+ Ok((i, o)) => {
+ DEPTH.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
+ eprintln!("{:depth$}<-- {} {:?}", "", context, i);
+ Ok((i, o))
+ }
+ Err(err) => {
+ DEPTH.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
+ eprintln!("{:depth$}<-- {} {:?}", "", context, err);
+ Err(err)
+ }
+ }
+ }
+ }
+
+ #[cfg(not(feature = "unbounded"))]
+ #[derive(Copy, Clone, Debug, Default)]
+ pub(crate) struct RecursionCheck {
+ current: usize,
+ }
+
+ #[cfg(not(feature = "unbounded"))]
+ impl RecursionCheck {
+ pub(crate) fn check_depth(depth: usize) -> Result<(), super::errors::CustomError> {
+ if depth < 128 {
+ Ok(())
+ } else {
+ Err(super::errors::CustomError::RecursionLimitExceeded)
+ }
+ }
+
+ pub(crate) fn recursing(
+ mut self,
+ input: Input<'_>,
+ ) -> Result<Self, winnow::error::ErrMode<ParserError<'_>>> {
+ self.current += 1;
+ if self.current < 128 {
+ Ok(self)
+ } else {
+ Err(winnow::error::ErrMode::Backtrack(
+ winnow::error::FromExternalError::from_external_error(
+ input,
+ winnow::error::ErrorKind::Eof,
+ super::errors::CustomError::RecursionLimitExceeded,
+ ),
+ ))
+ }
+ }
+ }
+
+ #[cfg(feature = "unbounded")]
+ #[derive(Copy, Clone, Debug, Default)]
+ pub(crate) struct RecursionCheck {}
+
+ #[cfg(feature = "unbounded")]
+ impl RecursionCheck {
+ pub(crate) fn check_depth(_depth: usize) -> Result<(), super::errors::CustomError> {
+ Ok(())
+ }
+
+ pub(crate) fn recursing(
+ self,
+ _input: Input<'_>,
+ ) -> Result<Self, winnow::error::ErrMode<ParserError<'_>>> {
+ Ok(self)
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn documents() {
+ let documents = [
+ "",
+ r#"
+# This is a TOML document.
+
+title = "TOML Example"
+
+ [owner]
+ name = "Tom Preston-Werner"
+ dob = 1979-05-27T07:32:00-08:00 # First class dates
+
+ [database]
+ server = "192.168.1.1"
+ ports = [ 8001, 8001, 8002 ]
+ connection_max = 5000
+ enabled = true
+
+ [servers]
+
+ # Indentation (tabs and/or spaces) is allowed but not required
+[servers.alpha]
+ ip = "10.0.0.1"
+ dc = "eqdc10"
+
+ [servers.beta]
+ ip = "10.0.0.2"
+ dc = "eqdc10"
+
+ [clients]
+ data = [ ["gamma", "delta"], [1, 2] ]
+
+ # Line breaks are OK when inside arrays
+hosts = [
+ "alpha",
+ "omega"
+]
+
+ 'some.wierd .stuff' = """
+ like
+ that
+ # """ # this broke my sintax highlighting
+ " also. like " = '''
+that
+'''
+ double = 2e39 # this number looks familiar
+# trailing comment"#,
+ r#""#,
+ r#" "#,
+ r#" hello = 'darkness' # my old friend
+"#,
+ r#"[parent . child]
+key = "value"
+"#,
+ r#"hello.world = "a"
+"#,
+ r#"foo = 1979-05-27 # Comment
+"#,
+ ];
+ for input in documents {
+ dbg!(input);
+ let mut parsed = parse_document(input);
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan();
+ }
+ let doc = match parsed {
+ Ok(doc) => doc,
+ Err(err) => {
+ panic!(
+ "Parse error: {:?}\nFailed to parse:\n```\n{}\n```",
+ err, input
+ )
+ }
+ };
+
+ snapbox::assert_eq(input, doc.to_string());
+ }
+ }
+
+ #[test]
+ fn documents_parse_only() {
+ let parse_only = ["\u{FEFF}
+[package]
+name = \"foo\"
+version = \"0.0.1\"
+authors = []
+"];
+ for input in parse_only {
+ dbg!(input);
+ let mut parsed = parse_document(input);
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan();
+ }
+ match parsed {
+ Ok(_) => (),
+ Err(err) => {
+ panic!(
+ "Parse error: {:?}\nFailed to parse:\n```\n{}\n```",
+ err, input
+ )
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn invalid_documents() {
+ let invalid_inputs = [r#" hello = 'darkness' # my old friend
+$"#];
+ for input in invalid_inputs {
+ dbg!(input);
+ let mut parsed = parse_document(input);
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan();
+ }
+ assert!(parsed.is_err(), "Input: {:?}", input);
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/numbers.rs b/vendor/toml_edit-0.19.11/src/parser/numbers.rs
new file mode 100644
index 000000000..803cc9d57
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/numbers.rs
@@ -0,0 +1,369 @@
+use std::ops::RangeInclusive;
+
+use winnow::combinator::alt;
+use winnow::combinator::cut_err;
+use winnow::combinator::opt;
+use winnow::combinator::peek;
+use winnow::combinator::preceded;
+use winnow::combinator::repeat;
+use winnow::combinator::rest;
+use winnow::token::one_of;
+use winnow::token::tag;
+use winnow::token::take;
+
+use crate::parser::prelude::*;
+use crate::parser::trivia::from_utf8_unchecked;
+
+// ;; Boolean
+
+// boolean = true / false
+#[allow(dead_code)] // directly define in `fn value`
+pub(crate) fn boolean(input: Input<'_>) -> IResult<Input<'_>, bool, ParserError<'_>> {
+ alt((true_, false_)).parse_next(input)
+}
+
+pub(crate) fn true_(input: Input<'_>) -> IResult<Input<'_>, bool, ParserError<'_>> {
+ (peek(TRUE[0]), cut_err(TRUE)).value(true).parse_next(input)
+}
+const TRUE: &[u8] = b"true";
+
+pub(crate) fn false_(input: Input<'_>) -> IResult<Input<'_>, bool, ParserError<'_>> {
+ (peek(FALSE[0]), cut_err(FALSE))
+ .value(false)
+ .parse_next(input)
+}
+const FALSE: &[u8] = b"false";
+
+// ;; Integer
+
+// integer = dec-int / hex-int / oct-int / bin-int
+pub(crate) fn integer(input: Input<'_>) -> IResult<Input<'_>, i64, ParserError<'_>> {
+ dispatch! {peek(opt::<_, &[u8], _, _>(take(2usize)));
+ Some(b"0x") => cut_err(hex_int.try_map(|s| i64::from_str_radix(&s.replace('_', ""), 16))),
+ Some(b"0o") => cut_err(oct_int.try_map(|s| i64::from_str_radix(&s.replace('_', ""), 8))),
+ Some(b"0b") => cut_err(bin_int.try_map(|s| i64::from_str_radix(&s.replace('_', ""), 2))),
+ _ => dec_int.and_then(cut_err(rest
+ .try_map(|s: &str| s.replace('_', "").parse())))
+ }
+ .parse_next(input)
+}
+
+// dec-int = [ minus / plus ] unsigned-dec-int
+// unsigned-dec-int = DIGIT / digit1-9 1*( DIGIT / underscore DIGIT )
+pub(crate) fn dec_int(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (
+ opt(one_of((b'+', b'-'))),
+ alt((
+ (
+ one_of(DIGIT1_9),
+ repeat(
+ 0..,
+ alt((
+ digit.value(()),
+ (
+ one_of(b'_'),
+ cut_err(digit)
+ .context(Context::Expected(ParserValue::Description("digit"))),
+ )
+ .value(()),
+ )),
+ )
+ .map(|()| ()),
+ )
+ .value(()),
+ digit.value(()),
+ )),
+ )
+ .recognize()
+ .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`digit` and `_` filter out non-ASCII") })
+ .context(Context::Expression("integer"))
+ .parse_next(input)
+}
+const DIGIT1_9: RangeInclusive<u8> = b'1'..=b'9';
+
+// hex-prefix = %x30.78 ; 0x
+// hex-int = hex-prefix HEXDIG *( HEXDIG / underscore HEXDIG )
+pub(crate) fn hex_int(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ preceded(
+ HEX_PREFIX,
+ cut_err((
+ hexdig,
+ repeat(
+ 0..,
+ alt((
+ hexdig.value(()),
+ (
+ one_of(b'_'),
+ cut_err(hexdig)
+ .context(Context::Expected(ParserValue::Description("digit"))),
+ )
+ .value(()),
+ )),
+ )
+ .map(|()| ()),
+ ))
+ .recognize(),
+ )
+ .map(|b| unsafe { from_utf8_unchecked(b, "`hexdig` and `_` filter out non-ASCII") })
+ .context(Context::Expression("hexadecimal integer"))
+ .parse_next(input)
+}
+const HEX_PREFIX: &[u8] = b"0x";
+
+// oct-prefix = %x30.6F ; 0o
+// oct-int = oct-prefix digit0-7 *( digit0-7 / underscore digit0-7 )
+pub(crate) fn oct_int(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ preceded(
+ OCT_PREFIX,
+ cut_err((
+ one_of(DIGIT0_7),
+ repeat(
+ 0..,
+ alt((
+ one_of(DIGIT0_7).value(()),
+ (
+ one_of(b'_'),
+ cut_err(one_of(DIGIT0_7))
+ .context(Context::Expected(ParserValue::Description("digit"))),
+ )
+ .value(()),
+ )),
+ )
+ .map(|()| ()),
+ ))
+ .recognize(),
+ )
+ .map(|b| unsafe { from_utf8_unchecked(b, "`DIGIT0_7` and `_` filter out non-ASCII") })
+ .context(Context::Expression("octal integer"))
+ .parse_next(input)
+}
+const OCT_PREFIX: &[u8] = b"0o";
+const DIGIT0_7: RangeInclusive<u8> = b'0'..=b'7';
+
+// bin-prefix = %x30.62 ; 0b
+// bin-int = bin-prefix digit0-1 *( digit0-1 / underscore digit0-1 )
+pub(crate) fn bin_int(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ preceded(
+ BIN_PREFIX,
+ cut_err((
+ one_of(DIGIT0_1),
+ repeat(
+ 0..,
+ alt((
+ one_of(DIGIT0_1).value(()),
+ (
+ one_of(b'_'),
+ cut_err(one_of(DIGIT0_1))
+ .context(Context::Expected(ParserValue::Description("digit"))),
+ )
+ .value(()),
+ )),
+ )
+ .map(|()| ()),
+ ))
+ .recognize(),
+ )
+ .map(|b| unsafe { from_utf8_unchecked(b, "`DIGIT0_1` and `_` filter out non-ASCII") })
+ .context(Context::Expression("binary integer"))
+ .parse_next(input)
+}
+const BIN_PREFIX: &[u8] = b"0b";
+const DIGIT0_1: RangeInclusive<u8> = b'0'..=b'1';
+
+// ;; Float
+
+// float = float-int-part ( exp / frac [ exp ] )
+// float =/ special-float
+// float-int-part = dec-int
+pub(crate) fn float(input: Input<'_>) -> IResult<Input<'_>, f64, ParserError<'_>> {
+ alt((
+ float_.and_then(cut_err(
+ rest.try_map(|s: &str| s.replace('_', "").parse())
+ .verify(|f: &f64| *f != f64::INFINITY),
+ )),
+ special_float,
+ ))
+ .context(Context::Expression("floating-point number"))
+ .parse_next(input)
+}
+
+pub(crate) fn float_(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (dec_int, alt((exp, (frac, opt(exp)).map(|_| ""))))
+ .recognize()
+ .map(|b: &[u8]| unsafe {
+ from_utf8_unchecked(
+ b,
+ "`dec_int`, `one_of`, `exp`, and `frac` filter out non-ASCII",
+ )
+ })
+ .parse_next(input)
+}
+
+// frac = decimal-point zero-prefixable-int
+// decimal-point = %x2E ; .
+pub(crate) fn frac(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (
+ b'.',
+ cut_err(zero_prefixable_int).context(Context::Expected(ParserValue::Description("digit"))),
+ )
+ .recognize()
+ .map(|b: &[u8]| unsafe {
+ from_utf8_unchecked(
+ b,
+ "`.` and `parse_zero_prefixable_int` filter out non-ASCII",
+ )
+ })
+ .parse_next(input)
+}
+
+// zero-prefixable-int = DIGIT *( DIGIT / underscore DIGIT )
+pub(crate) fn zero_prefixable_int(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (
+ digit,
+ repeat(
+ 0..,
+ alt((
+ digit.value(()),
+ (
+ one_of(b'_'),
+ cut_err(digit).context(Context::Expected(ParserValue::Description("digit"))),
+ )
+ .value(()),
+ )),
+ )
+ .map(|()| ()),
+ )
+ .recognize()
+ .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`digit` and `_` filter out non-ASCII") })
+ .parse_next(input)
+}
+
+// exp = "e" float-exp-part
+// float-exp-part = [ minus / plus ] zero-prefixable-int
+pub(crate) fn exp(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (
+ one_of((b'e', b'E')),
+ opt(one_of([b'+', b'-'])),
+ cut_err(zero_prefixable_int),
+ )
+ .recognize()
+ .map(|b: &[u8]| unsafe {
+ from_utf8_unchecked(
+ b,
+ "`one_of` and `parse_zero_prefixable_int` filter out non-ASCII",
+ )
+ })
+ .parse_next(input)
+}
+
+// special-float = [ minus / plus ] ( inf / nan )
+pub(crate) fn special_float(input: Input<'_>) -> IResult<Input<'_>, f64, ParserError<'_>> {
+ (opt(one_of((b'+', b'-'))), alt((inf, nan)))
+ .map(|(s, f)| match s {
+ Some(b'+') | None => f,
+ Some(b'-') => -f,
+ _ => unreachable!("one_of should prevent this"),
+ })
+ .parse_next(input)
+}
+// inf = %x69.6e.66 ; inf
+pub(crate) fn inf(input: Input<'_>) -> IResult<Input<'_>, f64, ParserError<'_>> {
+ tag(INF).value(f64::INFINITY).parse_next(input)
+}
+const INF: &[u8] = b"inf";
+// nan = %x6e.61.6e ; nan
+pub(crate) fn nan(input: Input<'_>) -> IResult<Input<'_>, f64, ParserError<'_>> {
+ tag(NAN).value(f64::NAN).parse_next(input)
+}
+const NAN: &[u8] = b"nan";
+
+// DIGIT = %x30-39 ; 0-9
+pub(crate) fn digit(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ one_of(DIGIT).parse_next(input)
+}
+const DIGIT: RangeInclusive<u8> = b'0'..=b'9';
+
+// HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
+pub(crate) fn hexdig(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ one_of(HEXDIG).parse_next(input)
+}
+pub(crate) const HEXDIG: (RangeInclusive<u8>, RangeInclusive<u8>, RangeInclusive<u8>) =
+ (DIGIT, b'A'..=b'F', b'a'..=b'f');
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn integers() {
+ let cases = [
+ ("+99", 99),
+ ("42", 42),
+ ("0", 0),
+ ("-17", -17),
+ ("1_000", 1_000),
+ ("5_349_221", 5_349_221),
+ ("1_2_3_4_5", 1_2_3_4_5),
+ ("0xF", 15),
+ ("0o0_755", 493),
+ ("0b1_0_1", 5),
+ (&std::i64::MIN.to_string()[..], std::i64::MIN),
+ (&std::i64::MAX.to_string()[..], std::i64::MAX),
+ ];
+ for &(input, expected) in &cases {
+ dbg!(input);
+ let parsed = integer.parse(new_input(input));
+ assert_eq!(parsed, Ok(expected), "Parsing {input:?}");
+ }
+
+ let overflow = "1000000000000000000000000000000000";
+ let parsed = integer.parse(new_input(overflow));
+ assert!(parsed.is_err());
+ }
+
+ #[track_caller]
+ fn assert_float_eq(actual: f64, expected: f64) {
+ if expected.is_nan() {
+ assert!(actual.is_nan());
+ } else if expected.is_infinite() {
+ assert!(actual.is_infinite());
+ assert_eq!(expected.is_sign_positive(), actual.is_sign_positive());
+ } else {
+ dbg!(expected);
+ dbg!(actual);
+ assert!((expected - actual).abs() < std::f64::EPSILON);
+ }
+ }
+
+ #[test]
+ fn floats() {
+ let cases = [
+ ("+1.0", 1.0),
+ ("3.1419", 3.1419),
+ ("-0.01", -0.01),
+ ("5e+22", 5e+22),
+ ("1e6", 1e6),
+ ("-2E-2", -2E-2),
+ ("6.626e-34", 6.626e-34),
+ ("9_224_617.445_991_228_313", 9_224_617.445_991_227),
+ ("-1.7976931348623157e+308", std::f64::MIN),
+ ("1.7976931348623157e+308", std::f64::MAX),
+ ("nan", f64::NAN),
+ ("+nan", f64::NAN),
+ ("-nan", f64::NAN),
+ ("inf", f64::INFINITY),
+ ("+inf", f64::INFINITY),
+ ("-inf", f64::NEG_INFINITY),
+ // ("1e+400", std::f64::INFINITY),
+ ];
+ for &(input, expected) in &cases {
+ dbg!(input);
+ let parsed = float.parse(new_input(input)).unwrap();
+ assert_float_eq(parsed, expected);
+
+ let overflow = "9e99999";
+ let parsed = float.parse(new_input(overflow));
+ assert!(parsed.is_err(), "{:?}", parsed);
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/state.rs b/vendor/toml_edit-0.19.11/src/parser/state.rs
new file mode 100644
index 000000000..efa884d2f
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/state.rs
@@ -0,0 +1,323 @@
+use crate::key::Key;
+use crate::parser::errors::CustomError;
+use crate::repr::Decor;
+use crate::table::TableKeyValue;
+use crate::{ArrayOfTables, Document, InternalString, Item, RawString, Table};
+
+pub(crate) struct ParseState {
+ document: Document,
+ trailing: Option<std::ops::Range<usize>>,
+ current_table_position: usize,
+ current_table: Table,
+ current_is_array: bool,
+ current_table_path: Vec<Key>,
+}
+
+impl ParseState {
+ pub(crate) fn into_document(mut self) -> Result<Document, CustomError> {
+ self.finalize_table()?;
+ let trailing = self.trailing.map(RawString::with_span);
+ self.document.trailing = trailing.unwrap_or_default();
+ Ok(self.document)
+ }
+
+ pub(crate) fn on_ws(&mut self, span: std::ops::Range<usize>) {
+ if let Some(old) = self.trailing.take() {
+ self.trailing = Some(old.start..span.end);
+ } else {
+ self.trailing = Some(span);
+ }
+ }
+
+ pub(crate) fn on_comment(&mut self, span: std::ops::Range<usize>) {
+ if let Some(old) = self.trailing.take() {
+ self.trailing = Some(old.start..span.end);
+ } else {
+ self.trailing = Some(span);
+ }
+ }
+
+ pub(crate) fn on_keyval(
+ &mut self,
+ mut path: Vec<Key>,
+ mut kv: TableKeyValue,
+ ) -> Result<(), CustomError> {
+ {
+ let mut prefix = self.trailing.take();
+ let first_key = if path.is_empty() {
+ &mut kv.key
+ } else {
+ &mut path[0]
+ };
+ let prefix = match (
+ prefix.take(),
+ first_key.decor.prefix().and_then(|d| d.span()),
+ ) {
+ (Some(p), Some(k)) => Some(p.start..k.end),
+ (Some(p), None) | (None, Some(p)) => Some(p),
+ (None, None) => None,
+ };
+ first_key
+ .decor
+ .set_prefix(prefix.map(RawString::with_span).unwrap_or_default());
+ }
+
+ if let (Some(existing), Some(value)) = (self.current_table.span(), kv.value.span()) {
+ self.current_table.span = Some((existing.start)..(value.end));
+ }
+ let table = &mut self.current_table;
+ let table = Self::descend_path(table, &path, true)?;
+
+ // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed"
+ let mixed_table_types = table.is_dotted() == path.is_empty();
+ if mixed_table_types {
+ return Err(CustomError::DuplicateKey {
+ key: kv.key.get().into(),
+ table: None,
+ });
+ }
+
+ let key: InternalString = kv.key.get_internal().into();
+ match table.items.entry(key) {
+ indexmap::map::Entry::Vacant(o) => {
+ o.insert(kv);
+ }
+ indexmap::map::Entry::Occupied(o) => {
+ // "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed"
+ return Err(CustomError::DuplicateKey {
+ key: o.key().as_str().into(),
+ table: Some(self.current_table_path.clone()),
+ });
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(crate) fn start_aray_table(
+ &mut self,
+ path: Vec<Key>,
+ decor: Decor,
+ span: std::ops::Range<usize>,
+ ) -> Result<(), CustomError> {
+ debug_assert!(!path.is_empty());
+ debug_assert!(self.current_table.is_empty());
+ debug_assert!(self.current_table_path.is_empty());
+
+ // Look up the table on start to ensure the duplicate_key error points to the right line
+ let root = self.document.as_table_mut();
+ let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
+ let key = &path[path.len() - 1];
+ let entry = parent_table
+ .entry_format(key)
+ .or_insert(Item::ArrayOfTables(ArrayOfTables::new()));
+ entry
+ .as_array_of_tables()
+ .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?;
+
+ self.current_table_position += 1;
+ self.current_table.decor = decor;
+ self.current_table.set_implicit(false);
+ self.current_table.set_dotted(false);
+ self.current_table.set_position(self.current_table_position);
+ self.current_table.span = Some(span);
+ self.current_is_array = true;
+ self.current_table_path = path;
+
+ Ok(())
+ }
+
+ pub(crate) fn start_table(
+ &mut self,
+ path: Vec<Key>,
+ decor: Decor,
+ span: std::ops::Range<usize>,
+ ) -> Result<(), CustomError> {
+ debug_assert!(!path.is_empty());
+ debug_assert!(self.current_table.is_empty());
+ debug_assert!(self.current_table_path.is_empty());
+
+ // 1. Look up the table on start to ensure the duplicate_key error points to the right line
+ // 2. Ensure any child tables from an implicit table are preserved
+ let root = self.document.as_table_mut();
+ let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
+ let key = &path[path.len() - 1];
+ if let Some(entry) = parent_table.remove(key.get()) {
+ match entry {
+ Item::Table(t) if t.implicit && !t.is_dotted() => {
+ self.current_table = t;
+ }
+ // Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed. Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed.
+ _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)),
+ }
+ }
+
+ self.current_table_position += 1;
+ self.current_table.decor = decor;
+ self.current_table.set_implicit(false);
+ self.current_table.set_dotted(false);
+ self.current_table.set_position(self.current_table_position);
+ self.current_table.span = Some(span);
+ self.current_is_array = false;
+ self.current_table_path = path;
+
+ Ok(())
+ }
+
+ pub(crate) fn finalize_table(&mut self) -> Result<(), CustomError> {
+ let mut table = std::mem::take(&mut self.current_table);
+ let path = std::mem::take(&mut self.current_table_path);
+
+ let root = self.document.as_table_mut();
+ if path.is_empty() {
+ assert!(root.is_empty());
+ std::mem::swap(&mut table, root);
+ } else if self.current_is_array {
+ let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
+ let key = &path[path.len() - 1];
+
+ let entry = parent_table
+ .entry_format(key)
+ .or_insert(Item::ArrayOfTables(ArrayOfTables::new()));
+ let array = entry
+ .as_array_of_tables_mut()
+ .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?;
+ array.push(table);
+ let span = if let (Some(first), Some(last)) = (
+ array.values.first().and_then(|t| t.span()),
+ array.values.last().and_then(|t| t.span()),
+ ) {
+ Some((first.start)..(last.end))
+ } else {
+ None
+ };
+ array.span = span;
+ } else {
+ let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
+ let key = &path[path.len() - 1];
+
+ let entry = parent_table.entry_format(key);
+ match entry {
+ crate::Entry::Occupied(entry) => {
+ match entry.into_mut() {
+ // if [a.b.c] header preceded [a.b]
+ Item::Table(ref mut t) if t.implicit => {
+ std::mem::swap(t, &mut table);
+ }
+ _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)),
+ }
+ }
+ crate::Entry::Vacant(entry) => {
+ let item = Item::Table(table);
+ entry.insert(item);
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(crate) fn descend_path<'t, 'k>(
+ mut table: &'t mut Table,
+ path: &'k [Key],
+ dotted: bool,
+ ) -> Result<&'t mut Table, CustomError> {
+ for (i, key) in path.iter().enumerate() {
+ let entry = table.entry_format(key).or_insert_with(|| {
+ let mut new_table = Table::new();
+ new_table.set_implicit(true);
+ new_table.set_dotted(dotted);
+
+ Item::Table(new_table)
+ });
+ match *entry {
+ Item::Value(ref v) => {
+ return Err(CustomError::extend_wrong_type(path, i, v.type_name()));
+ }
+ Item::ArrayOfTables(ref mut array) => {
+ debug_assert!(!array.is_empty());
+
+ let index = array.len() - 1;
+ let last_child = array.get_mut(index).unwrap();
+
+ table = last_child;
+ }
+ Item::Table(ref mut sweet_child_of_mine) => {
+ // Since tables cannot be defined more than once, redefining such tables using a
+ // [table] header is not allowed. Likewise, using dotted keys to redefine tables
+ // already defined in [table] form is not allowed.
+ if dotted && !sweet_child_of_mine.is_implicit() {
+ return Err(CustomError::DuplicateKey {
+ key: key.get().into(),
+ table: None,
+ });
+ }
+ table = sweet_child_of_mine;
+ }
+ _ => unreachable!(),
+ }
+ }
+ Ok(table)
+ }
+
+ pub(crate) fn on_std_header(
+ &mut self,
+ path: Vec<Key>,
+ trailing: std::ops::Range<usize>,
+ span: std::ops::Range<usize>,
+ ) -> Result<(), CustomError> {
+ debug_assert!(!path.is_empty());
+
+ self.finalize_table()?;
+ let leading = self
+ .trailing
+ .take()
+ .map(RawString::with_span)
+ .unwrap_or_default();
+ self.start_table(
+ path,
+ Decor::new(leading, RawString::with_span(trailing)),
+ span,
+ )?;
+
+ Ok(())
+ }
+
+ pub(crate) fn on_array_header(
+ &mut self,
+ path: Vec<Key>,
+ trailing: std::ops::Range<usize>,
+ span: std::ops::Range<usize>,
+ ) -> Result<(), CustomError> {
+ debug_assert!(!path.is_empty());
+
+ self.finalize_table()?;
+ let leading = self
+ .trailing
+ .take()
+ .map(RawString::with_span)
+ .unwrap_or_default();
+ self.start_aray_table(
+ path,
+ Decor::new(leading, RawString::with_span(trailing)),
+ span,
+ )?;
+
+ Ok(())
+ }
+}
+
+impl Default for ParseState {
+ fn default() -> Self {
+ let mut root = Table::new();
+ root.span = Some(0..0);
+ Self {
+ document: Document::new(),
+ trailing: None,
+ current_table_position: 0,
+ current_table: root,
+ current_is_array: false,
+ current_table_path: Vec::new(),
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/strings.rs b/vendor/toml_edit-0.19.11/src/parser/strings.rs
new file mode 100644
index 000000000..2ce160506
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/strings.rs
@@ -0,0 +1,464 @@
+use std::borrow::Cow;
+use std::char;
+use std::ops::RangeInclusive;
+
+use winnow::combinator::alt;
+use winnow::combinator::cut_err;
+use winnow::combinator::delimited;
+use winnow::combinator::fail;
+use winnow::combinator::opt;
+use winnow::combinator::peek;
+use winnow::combinator::preceded;
+use winnow::combinator::repeat;
+use winnow::combinator::success;
+use winnow::combinator::terminated;
+use winnow::prelude::*;
+use winnow::token::any;
+use winnow::token::none_of;
+use winnow::token::one_of;
+use winnow::token::tag;
+use winnow::token::take_while;
+
+use crate::parser::errors::CustomError;
+use crate::parser::numbers::HEXDIG;
+use crate::parser::prelude::*;
+use crate::parser::trivia::{from_utf8_unchecked, newline, ws, ws_newlines, NON_ASCII, WSCHAR};
+
+// ;; String
+
+// string = ml-basic-string / basic-string / ml-literal-string / literal-string
+pub(crate) fn string(input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ alt((
+ ml_basic_string,
+ basic_string,
+ ml_literal_string,
+ literal_string.map(Cow::Borrowed),
+ ))
+ .parse_next(input)
+}
+
+// ;; Basic String
+
+// basic-string = quotation-mark *basic-char quotation-mark
+pub(crate) fn basic_string(input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ let (mut input, _) = one_of(QUOTATION_MARK).parse_next(input)?;
+
+ let mut c = Cow::Borrowed("");
+ if let Some((i, ci)) = ok_error(basic_chars.parse_next(input))? {
+ input = i;
+ c = ci;
+ }
+ while let Some((i, ci)) = ok_error(basic_chars.parse_next(input))? {
+ input = i;
+ c.to_mut().push_str(&ci);
+ }
+
+ let (input, _) = cut_err(one_of(QUOTATION_MARK))
+ .context(Context::Expression("basic string"))
+ .parse_next(input)?;
+
+ Ok((input, c))
+}
+
+// quotation-mark = %x22 ; "
+pub(crate) const QUOTATION_MARK: u8 = b'"';
+
+// basic-char = basic-unescaped / escaped
+fn basic_chars(input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ alt((
+ // Deviate from the official grammar by batching the unescaped chars so we build a string a
+ // chunk at a time, rather than a `char` at a time.
+ take_while(1.., BASIC_UNESCAPED)
+ .try_map(std::str::from_utf8)
+ .map(Cow::Borrowed),
+ escaped.map(|c| Cow::Owned(String::from(c))),
+ ))
+ .parse_next(input)
+}
+
+// basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
+pub(crate) const BASIC_UNESCAPED: (
+ (u8, u8),
+ u8,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+) = (WSCHAR, 0x21, 0x23..=0x5B, 0x5D..=0x7E, NON_ASCII);
+
+// escaped = escape escape-seq-char
+fn escaped(input: Input<'_>) -> IResult<Input<'_>, char, ParserError<'_>> {
+ preceded(ESCAPE, escape_seq_char).parse_next(input)
+}
+
+// escape = %x5C ; \
+pub(crate) const ESCAPE: u8 = b'\\';
+
+// escape-seq-char = %x22 ; " quotation mark U+0022
+// escape-seq-char =/ %x5C ; \ reverse solidus U+005C
+// escape-seq-char =/ %x62 ; b backspace U+0008
+// escape-seq-char =/ %x66 ; f form feed U+000C
+// escape-seq-char =/ %x6E ; n line feed U+000A
+// escape-seq-char =/ %x72 ; r carriage return U+000D
+// escape-seq-char =/ %x74 ; t tab U+0009
+// escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX
+// escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX
+fn escape_seq_char(input: Input<'_>) -> IResult<Input<'_>, char, ParserError<'_>> {
+ dispatch! {any;
+ b'b' => success('\u{8}'),
+ b'f' => success('\u{c}'),
+ b'n' => success('\n'),
+ b'r' => success('\r'),
+ b't' => success('\t'),
+ b'u' => cut_err(hexescape::<4>).context(Context::Expression("unicode 4-digit hex code")),
+ b'U' => cut_err(hexescape::<8>).context(Context::Expression("unicode 8-digit hex code")),
+ b'\\' => success('\\'),
+ b'"' => success('"'),
+ _ => {
+ cut_err(fail::<_, char, _>)
+ .context(Context::Expression("escape sequence"))
+ .context(Context::Expected(ParserValue::CharLiteral('b')))
+ .context(Context::Expected(ParserValue::CharLiteral('f')))
+ .context(Context::Expected(ParserValue::CharLiteral('n')))
+ .context(Context::Expected(ParserValue::CharLiteral('r')))
+ .context(Context::Expected(ParserValue::CharLiteral('t')))
+ .context(Context::Expected(ParserValue::CharLiteral('u')))
+ .context(Context::Expected(ParserValue::CharLiteral('U')))
+ .context(Context::Expected(ParserValue::CharLiteral('\\')))
+ .context(Context::Expected(ParserValue::CharLiteral('"')))
+ }
+ }
+ .parse_next(input)
+}
+
+pub(crate) fn hexescape<const N: usize>(
+ input: Input<'_>,
+) -> IResult<Input<'_>, char, ParserError<'_>> {
+ take_while(0..=N, HEXDIG)
+ .verify(|b: &[u8]| b.len() == N)
+ .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`is_ascii_digit` filters out on-ASCII") })
+ .verify_map(|s| u32::from_str_radix(s, 16).ok())
+ .try_map(|h| char::from_u32(h).ok_or(CustomError::OutOfRange))
+ .parse_next(input)
+}
+
+// ;; Multiline Basic String
+
+// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
+// ml-basic-string-delim
+fn ml_basic_string(input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ delimited(
+ ML_BASIC_STRING_DELIM,
+ preceded(opt(newline), cut_err(ml_basic_body)),
+ cut_err(ML_BASIC_STRING_DELIM),
+ )
+ .context(Context::Expression("multiline basic string"))
+ .parse_next(input)
+}
+
+// ml-basic-string-delim = 3quotation-mark
+pub(crate) const ML_BASIC_STRING_DELIM: &[u8] = b"\"\"\"";
+
+// ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ]
+fn ml_basic_body(mut input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ let mut c = Cow::Borrowed("");
+ if let Some((i, ci)) = ok_error(mlb_content.parse_next(input))? {
+ input = i;
+ c = ci;
+ }
+ while let Some((i, ci)) = ok_error(mlb_content.parse_next(input))? {
+ input = i;
+ c.to_mut().push_str(&ci);
+ }
+
+ while let Some((i, qi)) = ok_error(mlb_quotes(none_of(b'\"').value(())).parse_next(input))? {
+ if let Some((i, ci)) = ok_error(mlb_content.parse_next(i))? {
+ input = i;
+ c.to_mut().push_str(qi);
+ c.to_mut().push_str(&ci);
+ while let Some((i, ci)) = ok_error(mlb_content.parse_next(input))? {
+ input = i;
+ c.to_mut().push_str(&ci);
+ }
+ } else {
+ break;
+ }
+ }
+
+ if let Some((i, qi)) =
+ ok_error(mlb_quotes(tag(ML_BASIC_STRING_DELIM).value(())).parse_next(input))?
+ {
+ input = i;
+ c.to_mut().push_str(qi);
+ }
+
+ Ok((input, c))
+}
+
+// mlb-content = mlb-char / newline / mlb-escaped-nl
+// mlb-char = mlb-unescaped / escaped
+fn mlb_content(input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ alt((
+ // Deviate from the official grammar by batching the unescaped chars so we build a string a
+ // chunk at a time, rather than a `char` at a time.
+ take_while(1.., MLB_UNESCAPED)
+ .try_map(std::str::from_utf8)
+ .map(Cow::Borrowed),
+ // Order changed fromg grammar so `escaped` can more easily `cut_err` on bad escape sequences
+ mlb_escaped_nl.map(|_| Cow::Borrowed("")),
+ escaped.map(|c| Cow::Owned(String::from(c))),
+ newline.map(|_| Cow::Borrowed("\n")),
+ ))
+ .parse_next(input)
+}
+
+// mlb-quotes = 1*2quotation-mark
+fn mlb_quotes<'i>(
+ mut term: impl winnow::Parser<Input<'i>, (), ParserError<'i>>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, &str, ParserError<'i>> {
+ move |input| {
+ let res = terminated(b"\"\"", peek(term.by_ref()))
+ .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") })
+ .parse_next(input);
+
+ match res {
+ Err(winnow::error::ErrMode::Backtrack(_)) => terminated(b"\"", peek(term.by_ref()))
+ .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") })
+ .parse_next(input),
+ res => res,
+ }
+ }
+}
+
+// mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
+pub(crate) const MLB_UNESCAPED: (
+ (u8, u8),
+ u8,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+) = (WSCHAR, 0x21, 0x23..=0x5B, 0x5D..=0x7E, NON_ASCII);
+
+// mlb-escaped-nl = escape ws newline *( wschar / newline
+// When the last non-whitespace character on a line is a \,
+// it will be trimmed along with all whitespace
+// (including newlines) up to the next non-whitespace
+// character or closing delimiter.
+fn mlb_escaped_nl(input: Input<'_>) -> IResult<Input<'_>, (), ParserError<'_>> {
+ repeat(1.., (ESCAPE, ws, ws_newlines))
+ .map(|()| ())
+ .value(())
+ .parse_next(input)
+}
+
+// ;; Literal String
+
+// literal-string = apostrophe *literal-char apostrophe
+pub(crate) fn literal_string(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ delimited(
+ APOSTROPHE,
+ cut_err(take_while(0.., LITERAL_CHAR)),
+ cut_err(APOSTROPHE),
+ )
+ .try_map(std::str::from_utf8)
+ .context(Context::Expression("literal string"))
+ .parse_next(input)
+}
+
+// apostrophe = %x27 ; ' apostrophe
+pub(crate) const APOSTROPHE: u8 = b'\'';
+
+// literal-char = %x09 / %x20-26 / %x28-7E / non-ascii
+pub(crate) const LITERAL_CHAR: (
+ u8,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+) = (0x9, 0x20..=0x26, 0x28..=0x7E, NON_ASCII);
+
+// ;; Multiline Literal String
+
+// ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body
+// ml-literal-string-delim
+fn ml_literal_string(input: Input<'_>) -> IResult<Input<'_>, Cow<'_, str>, ParserError<'_>> {
+ delimited(
+ (ML_LITERAL_STRING_DELIM, opt(newline)),
+ cut_err(ml_literal_body.map(|t| {
+ if t.contains("\r\n") {
+ Cow::Owned(t.replace("\r\n", "\n"))
+ } else {
+ Cow::Borrowed(t)
+ }
+ })),
+ cut_err(ML_LITERAL_STRING_DELIM),
+ )
+ .context(Context::Expression("multiline literal string"))
+ .parse_next(input)
+}
+
+// ml-literal-string-delim = 3apostrophe
+pub(crate) const ML_LITERAL_STRING_DELIM: &[u8] = b"'''";
+
+// ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ]
+fn ml_literal_body(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (
+ repeat(0.., mll_content).map(|()| ()),
+ repeat(
+ 0..,
+ (
+ mll_quotes(none_of(APOSTROPHE).value(())),
+ repeat(1.., mll_content).map(|()| ()),
+ ),
+ )
+ .map(|()| ()),
+ opt(mll_quotes(tag(ML_LITERAL_STRING_DELIM).value(()))),
+ )
+ .recognize()
+ .try_map(std::str::from_utf8)
+ .parse_next(input)
+}
+
+// mll-content = mll-char / newline
+fn mll_content(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ alt((one_of(MLL_CHAR), newline)).parse_next(input)
+}
+
+// mll-char = %x09 / %x20-26 / %x28-7E / non-ascii
+const MLL_CHAR: (
+ u8,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+ RangeInclusive<u8>,
+) = (0x9, 0x20..=0x26, 0x28..=0x7E, NON_ASCII);
+
+// mll-quotes = 1*2apostrophe
+fn mll_quotes<'i>(
+ mut term: impl winnow::Parser<Input<'i>, (), ParserError<'i>>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, &str, ParserError<'i>> {
+ move |input| {
+ let res = terminated(b"''", peek(term.by_ref()))
+ .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") })
+ .parse_next(input);
+
+ match res {
+ Err(winnow::error::ErrMode::Backtrack(_)) => terminated(b"'", peek(term.by_ref()))
+ .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") })
+ .parse_next(input),
+ res => res,
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn basic_string() {
+ let input =
+ r#""I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF. \U0002070E""#;
+ let expected = "I\'m a string. \"You can quote me\". Name\tJosé\nLocation\tSF. \u{2070E}";
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+
+ #[test]
+ fn ml_basic_string() {
+ let cases = [
+ (
+ r#""""
+Roses are red
+Violets are blue""""#,
+ r#"Roses are red
+Violets are blue"#,
+ ),
+ (r#"""" \""" """"#, " \"\"\" "),
+ (r#"""" \\""""#, " \\"),
+ ];
+
+ for &(input, expected) in &cases {
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+
+ let invalid_cases = [r#"""" """#, r#"""" \""""#];
+
+ for input in &invalid_cases {
+ let parsed = string.parse(new_input(input));
+ assert!(parsed.is_err());
+ }
+ }
+
+ #[test]
+ fn ml_basic_string_escape_ws() {
+ let inputs = [
+ r#""""
+The quick brown \
+
+
+ fox jumps over \
+ the lazy dog.""""#,
+ r#""""\
+ The quick brown \
+ fox jumps over \
+ the lazy dog.\
+ """"#,
+ ];
+ for input in &inputs {
+ let expected = "The quick brown fox jumps over the lazy dog.";
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+ let empties = [
+ r#""""\
+ """"#,
+ r#""""
+\
+ \
+""""#,
+ ];
+ for input in &empties {
+ let expected = "";
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+ }
+
+ #[test]
+ fn literal_string() {
+ let inputs = [
+ r#"'C:\Users\nodejs\templates'"#,
+ r#"'\\ServerX\admin$\system32\'"#,
+ r#"'Tom "Dubs" Preston-Werner'"#,
+ r#"'<\i\c*\s*>'"#,
+ ];
+
+ for input in &inputs {
+ let expected = &input[1..input.len() - 1];
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+ }
+
+ #[test]
+ fn ml_literal_string() {
+ let inputs = [
+ r#"'''I [dw]on't need \d{2} apples'''"#,
+ r#"''''one_quote''''"#,
+ ];
+ for input in &inputs {
+ let expected = &input[3..input.len() - 3];
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+
+ let input = r#"'''
+The first newline is
+trimmed in raw strings.
+ All other whitespace
+ is preserved.
+'''"#;
+ let expected = &input[4..input.len() - 3];
+ let parsed = string.parse(new_input(input));
+ assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}");
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/table.rs b/vendor/toml_edit-0.19.11/src/parser/table.rs
new file mode 100644
index 000000000..9d2675868
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/table.rs
@@ -0,0 +1,89 @@
+use std::cell::RefCell;
+#[allow(unused_imports)]
+use std::ops::DerefMut;
+
+use winnow::combinator::cut_err;
+use winnow::combinator::delimited;
+use winnow::combinator::peek;
+use winnow::token::take;
+
+// https://github.com/rust-lang/rust/issues/41358
+use crate::parser::key::key;
+use crate::parser::prelude::*;
+use crate::parser::state::ParseState;
+use crate::parser::trivia::line_trailing;
+
+// std-table-open = %x5B ws ; [ Left square bracket
+pub(crate) const STD_TABLE_OPEN: u8 = b'[';
+// std-table-close = ws %x5D ; ] Right square bracket
+const STD_TABLE_CLOSE: u8 = b']';
+// array-table-open = %x5B.5B ws ; [[ Double left square bracket
+const ARRAY_TABLE_OPEN: &[u8] = b"[[";
+// array-table-close = ws %x5D.5D ; ]] Double right quare bracket
+const ARRAY_TABLE_CLOSE: &[u8] = b"]]";
+
+// ;; Standard Table
+
+// std-table = std-table-open key *( table-key-sep key) std-table-close
+pub(crate) fn std_table<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
+ move |i| {
+ (
+ delimited(
+ STD_TABLE_OPEN,
+ cut_err(key),
+ cut_err(STD_TABLE_CLOSE)
+ .context(Context::Expected(ParserValue::CharLiteral('.')))
+ .context(Context::Expected(ParserValue::StringLiteral("]"))),
+ )
+ .with_span(),
+ cut_err(line_trailing)
+ .context(Context::Expected(ParserValue::CharLiteral('\n')))
+ .context(Context::Expected(ParserValue::CharLiteral('#'))),
+ )
+ .try_map(|((h, span), t)| state.borrow_mut().deref_mut().on_std_header(h, t, span))
+ .parse_next(i)
+ }
+}
+
+// ;; Array Table
+
+// array-table = array-table-open key *( table-key-sep key) array-table-close
+pub(crate) fn array_table<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
+ move |i| {
+ (
+ delimited(
+ ARRAY_TABLE_OPEN,
+ cut_err(key),
+ cut_err(ARRAY_TABLE_CLOSE)
+ .context(Context::Expected(ParserValue::CharLiteral('.')))
+ .context(Context::Expected(ParserValue::StringLiteral("]]"))),
+ )
+ .with_span(),
+ cut_err(line_trailing)
+ .context(Context::Expected(ParserValue::CharLiteral('\n')))
+ .context(Context::Expected(ParserValue::CharLiteral('#'))),
+ )
+ .try_map(|((h, span), t)| state.borrow_mut().deref_mut().on_array_header(h, t, span))
+ .parse_next(i)
+ }
+}
+
+// ;; Table
+
+// table = std-table / array-table
+pub(crate) fn table<'s, 'i>(
+ state: &'s RefCell<ParseState>,
+) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
+ move |i| {
+ dispatch!(peek::<_, &[u8],_,_>(take(2usize));
+ b"[[" => array_table(state),
+ _ => std_table(state),
+ )
+ .context(Context::Expression("table header"))
+ .parse_next(i)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/trivia.rs b/vendor/toml_edit-0.19.11/src/parser/trivia.rs
new file mode 100644
index 000000000..ba47dcde6
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/trivia.rs
@@ -0,0 +1,158 @@
+use std::ops::RangeInclusive;
+
+use winnow::combinator::alt;
+use winnow::combinator::eof;
+use winnow::combinator::opt;
+use winnow::combinator::repeat;
+use winnow::combinator::terminated;
+use winnow::prelude::*;
+use winnow::token::one_of;
+use winnow::token::take_while;
+
+use crate::parser::prelude::*;
+
+pub(crate) unsafe fn from_utf8_unchecked<'b>(
+ bytes: &'b [u8],
+ safety_justification: &'static str,
+) -> &'b str {
+ if cfg!(debug_assertions) {
+ // Catch problems more quickly when testing
+ std::str::from_utf8(bytes).expect(safety_justification)
+ } else {
+ std::str::from_utf8_unchecked(bytes)
+ }
+}
+
+// wschar = ( %x20 / ; Space
+// %x09 ) ; Horizontal tab
+pub(crate) const WSCHAR: (u8, u8) = (b' ', b'\t');
+
+// ws = *wschar
+pub(crate) fn ws(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ take_while(0.., WSCHAR)
+ .map(|b| unsafe { from_utf8_unchecked(b, "`is_wschar` filters out on-ASCII") })
+ .parse_next(input)
+}
+
+// non-ascii = %x80-D7FF / %xE000-10FFFF
+// - ASCII is 0xxxxxxx
+// - First byte for UTF-8 is 11xxxxxx
+// - Subsequent UTF-8 bytes are 10xxxxxx
+pub(crate) const NON_ASCII: RangeInclusive<u8> = 0x80..=0xff;
+
+// non-eol = %x09 / %x20-7E / non-ascii
+pub(crate) const NON_EOL: (u8, RangeInclusive<u8>, RangeInclusive<u8>) =
+ (0x09, 0x20..=0x7E, NON_ASCII);
+
+// comment-start-symbol = %x23 ; #
+pub(crate) const COMMENT_START_SYMBOL: u8 = b'#';
+
+// comment = comment-start-symbol *non-eol
+pub(crate) fn comment(input: Input<'_>) -> IResult<Input<'_>, &[u8], ParserError<'_>> {
+ (COMMENT_START_SYMBOL, take_while(0.., NON_EOL))
+ .recognize()
+ .parse_next(input)
+}
+
+// newline = ( %x0A / ; LF
+// %x0D.0A ) ; CRLF
+pub(crate) fn newline(input: Input<'_>) -> IResult<Input<'_>, u8, ParserError<'_>> {
+ alt((
+ one_of(LF).value(b'\n'),
+ (one_of(CR), one_of(LF)).value(b'\n'),
+ ))
+ .parse_next(input)
+}
+pub(crate) const LF: u8 = b'\n';
+pub(crate) const CR: u8 = b'\r';
+
+// ws-newline = *( wschar / newline )
+pub(crate) fn ws_newline(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ repeat(
+ 0..,
+ alt((newline.value(&b"\n"[..]), take_while(1.., WSCHAR))),
+ )
+ .map(|()| ())
+ .recognize()
+ .map(|b| unsafe { from_utf8_unchecked(b, "`is_wschar` and `newline` filters out on-ASCII") })
+ .parse_next(input)
+}
+
+// ws-newlines = newline *( wschar / newline )
+pub(crate) fn ws_newlines(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ (newline, ws_newline)
+ .recognize()
+ .map(|b| unsafe {
+ from_utf8_unchecked(b, "`is_wschar` and `newline` filters out on-ASCII")
+ })
+ .parse_next(input)
+}
+
+// note: this rule is not present in the original grammar
+// ws-comment-newline = *( ws-newline-nonempty / comment )
+pub(crate) fn ws_comment_newline(input: Input<'_>) -> IResult<Input<'_>, &[u8], ParserError<'_>> {
+ repeat(
+ 0..,
+ alt((
+ repeat(
+ 1..,
+ alt((take_while(1.., WSCHAR), newline.value(&b"\n"[..]))),
+ )
+ .map(|()| ()),
+ comment.value(()),
+ )),
+ )
+ .map(|()| ())
+ .recognize()
+ .parse_next(input)
+}
+
+// note: this rule is not present in the original grammar
+// line-ending = newline / eof
+pub(crate) fn line_ending(input: Input<'_>) -> IResult<Input<'_>, &str, ParserError<'_>> {
+ alt((newline.value("\n"), eof.value(""))).parse_next(input)
+}
+
+// note: this rule is not present in the original grammar
+// line-trailing = ws [comment] skip-line-ending
+pub(crate) fn line_trailing(
+ input: Input<'_>,
+) -> IResult<Input<'_>, std::ops::Range<usize>, ParserError<'_>> {
+ terminated((ws, opt(comment)).span(), line_ending).parse_next(input)
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn trivia() {
+ let inputs = [
+ "",
+ r#" "#,
+ r#"
+"#,
+ r#"
+# comment
+
+# comment2
+
+
+"#,
+ r#"
+ "#,
+ r#"# comment
+# comment2
+
+
+ "#,
+ ];
+ for input in inputs {
+ dbg!(input);
+ let parsed = ws_comment_newline.parse(new_input(input));
+ assert!(parsed.is_ok(), "{:?}", parsed);
+ let parsed = parsed.unwrap();
+ assert_eq!(parsed, input.as_bytes());
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/parser/value.rs b/vendor/toml_edit-0.19.11/src/parser/value.rs
new file mode 100644
index 000000000..19950585b
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/parser/value.rs
@@ -0,0 +1,157 @@
+use winnow::branch::alt;
+use winnow::bytes::any;
+use winnow::combinator::fail;
+use winnow::combinator::peek;
+
+use crate::parser::array::array;
+use crate::parser::datetime::date_time;
+use crate::parser::inline_table::inline_table;
+use crate::parser::numbers::{float, integer};
+use crate::parser::prelude::*;
+use crate::parser::strings::string;
+use crate::repr::{Formatted, Repr};
+use crate::value as v;
+use crate::RawString;
+use crate::Value;
+
+// val = string / boolean / array / inline-table / date-time / float / integer
+pub(crate) fn value(
+ check: RecursionCheck,
+) -> impl FnMut(Input<'_>) -> IResult<Input<'_>, v::Value, ParserError<'_>> {
+ move |input| {
+ dispatch!{peek(any);
+ crate::parser::strings::QUOTATION_MARK |
+ crate::parser::strings::APOSTROPHE => string.map(|s| {
+ v::Value::String(Formatted::new(
+ s.into_owned()
+ ))
+ }),
+ crate::parser::array::ARRAY_OPEN => array(check).map(v::Value::Array),
+ crate::parser::inline_table::INLINE_TABLE_OPEN => inline_table(check).map(v::Value::InlineTable),
+ // Date/number starts
+ b'+' | b'-' | b'0'..=b'9' => {
+ // Uncommon enough not to be worth optimizing at this time
+ alt((
+ date_time
+ .map(v::Value::from),
+ float
+ .map(v::Value::from),
+ integer
+ .map(v::Value::from),
+ ))
+ },
+ // Report as if they were numbers because its most likely a typo
+ b'_' => {
+ integer
+ .map(v::Value::from)
+ .context(Context::Expected(ParserValue::Description("leading digit")))
+ },
+ // Report as if they were numbers because its most likely a typo
+ b'.' => {
+ float
+ .map(v::Value::from)
+ .context(Context::Expected(ParserValue::Description("leading digit")))
+ },
+ b't' => {
+ crate::parser::numbers::true_.map(v::Value::from)
+ .context(Context::Expression("string"))
+ .context(Context::Expected(ParserValue::CharLiteral('"')))
+ .context(Context::Expected(ParserValue::CharLiteral('\'')))
+ },
+ b'f' => {
+ crate::parser::numbers::false_.map(v::Value::from)
+ .context(Context::Expression("string"))
+ .context(Context::Expected(ParserValue::CharLiteral('"')))
+ .context(Context::Expected(ParserValue::CharLiteral('\'')))
+ },
+ b'i' => {
+ crate::parser::numbers::inf.map(v::Value::from)
+ .context(Context::Expression("string"))
+ .context(Context::Expected(ParserValue::CharLiteral('"')))
+ .context(Context::Expected(ParserValue::CharLiteral('\'')))
+ },
+ b'n' => {
+ crate::parser::numbers::nan.map(v::Value::from)
+ .context(Context::Expression("string"))
+ .context(Context::Expected(ParserValue::CharLiteral('"')))
+ .context(Context::Expected(ParserValue::CharLiteral('\'')))
+ },
+ _ => {
+ fail
+ .context(Context::Expression("string"))
+ .context(Context::Expected(ParserValue::CharLiteral('"')))
+ .context(Context::Expected(ParserValue::CharLiteral('\'')))
+ },
+ }
+ .with_span()
+ .try_map(|(value, span)| apply_raw(value, span))
+ .parse_next(input)
+ }
+}
+
+fn apply_raw(mut val: Value, span: std::ops::Range<usize>) -> Result<Value, std::str::Utf8Error> {
+ match val {
+ Value::String(ref mut f) => {
+ let raw = RawString::with_span(span);
+ f.set_repr_unchecked(Repr::new_unchecked(raw));
+ }
+ Value::Integer(ref mut f) => {
+ let raw = RawString::with_span(span);
+ f.set_repr_unchecked(Repr::new_unchecked(raw));
+ }
+ Value::Float(ref mut f) => {
+ let raw = RawString::with_span(span);
+ f.set_repr_unchecked(Repr::new_unchecked(raw));
+ }
+ Value::Boolean(ref mut f) => {
+ let raw = RawString::with_span(span);
+ f.set_repr_unchecked(Repr::new_unchecked(raw));
+ }
+ Value::Datetime(ref mut f) => {
+ let raw = RawString::with_span(span);
+ f.set_repr_unchecked(Repr::new_unchecked(raw));
+ }
+ Value::Array(ref mut arr) => {
+ arr.span = Some(span);
+ }
+ Value::InlineTable(ref mut table) => {
+ table.span = Some(span);
+ }
+ };
+ val.decorate("", "");
+ Ok(val)
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn values() {
+ let inputs = [
+ "1979-05-27T00:32:00.999999",
+ "-239",
+ "1e200",
+ "9_224_617.445_991_228_313",
+ r#"'''I [dw]on't need \d{2} apples'''"#,
+ r#"'''
+The first newline is
+trimmed in raw strings.
+ All other whitespace
+ is preserved.
+'''"#,
+ r#""Jos\u00E9\n""#,
+ r#""\\\"\b/\f\n\r\t\u00E9\U000A0000""#,
+ r#"{ hello = "world", a = 1}"#,
+ r#"[ { x = 1, a = "2" }, {a = "a",b = "b", c = "c"} ]"#,
+ ];
+ for input in inputs {
+ dbg!(input);
+ let mut parsed = value(Default::default()).parse(new_input(input));
+ if let Ok(parsed) = &mut parsed {
+ parsed.despan(input);
+ }
+ assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned()));
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/raw_string.rs b/vendor/toml_edit-0.19.11/src/raw_string.rs
new file mode 100644
index 000000000..c5961f133
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/raw_string.rs
@@ -0,0 +1,182 @@
+use crate::InternalString;
+
+/// Opaque string storage for raw TOML; internal to `toml_edit`
+#[derive(PartialEq, Eq, Clone, Hash)]
+pub struct RawString(RawStringInner);
+
+#[derive(PartialEq, Eq, Clone, Hash)]
+enum RawStringInner {
+ Empty,
+ Explicit(InternalString),
+ Spanned(std::ops::Range<usize>),
+}
+
+impl RawString {
+ pub(crate) fn with_span(span: std::ops::Range<usize>) -> Self {
+ if span.start == span.end {
+ RawString(RawStringInner::Empty)
+ } else {
+ RawString(RawStringInner::Spanned(span))
+ }
+ }
+
+ /// Access the underlying string
+ pub fn as_str(&self) -> Option<&str> {
+ match &self.0 {
+ RawStringInner::Empty => Some(""),
+ RawStringInner::Explicit(s) => Some(s.as_str()),
+ RawStringInner::Spanned(_) => None,
+ }
+ }
+
+ pub(crate) fn to_str<'s>(&'s self, input: &'s str) -> &'s str {
+ match &self.0 {
+ RawStringInner::Empty => "",
+ RawStringInner::Explicit(s) => s.as_str(),
+ RawStringInner::Spanned(span) => input.get(span.clone()).unwrap_or_else(|| {
+ panic!("span {:?} should be in input:\n```\n{}\n```", span, input)
+ }),
+ }
+ }
+
+ pub(crate) fn to_str_with_default<'s>(
+ &'s self,
+ input: Option<&'s str>,
+ default: &'s str,
+ ) -> &'s str {
+ match &self.0 {
+ RawStringInner::Empty => "",
+ RawStringInner::Explicit(s) => s.as_str(),
+ RawStringInner::Spanned(span) => {
+ if let Some(input) = input {
+ input.get(span.clone()).unwrap_or_else(|| {
+ panic!("span {:?} should be in input:\n```\n{}\n```", span, input)
+ })
+ } else {
+ default
+ }
+ }
+ }
+ }
+
+ /// Access the underlying span
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ match &self.0 {
+ RawStringInner::Empty => None,
+ RawStringInner::Explicit(_) => None,
+ RawStringInner::Spanned(span) => Some(span.clone()),
+ }
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ match &self.0 {
+ RawStringInner::Empty => {}
+ RawStringInner::Explicit(_) => {}
+ RawStringInner::Spanned(span) => {
+ *self = Self::from(input.get(span.clone()).unwrap_or_else(|| {
+ panic!("span {:?} should be in input:\n```\n{}\n```", span, input)
+ }))
+ }
+ }
+ }
+
+ pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result {
+ let raw = self.to_str(input);
+ for part in raw.split('\r') {
+ write!(buf, "{}", part)?;
+ }
+ Ok(())
+ }
+
+ pub(crate) fn encode_with_default(
+ &self,
+ buf: &mut dyn std::fmt::Write,
+ input: Option<&str>,
+ default: &str,
+ ) -> std::fmt::Result {
+ let raw = self.to_str_with_default(input, default);
+ for part in raw.split('\r') {
+ write!(buf, "{}", part)?;
+ }
+ Ok(())
+ }
+}
+
+impl Default for RawString {
+ fn default() -> Self {
+ Self(RawStringInner::Empty)
+ }
+}
+
+impl std::fmt::Debug for RawString {
+ #[inline]
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ match &self.0 {
+ RawStringInner::Empty => write!(formatter, "empty"),
+ RawStringInner::Explicit(s) => write!(formatter, "{:?}", s),
+ RawStringInner::Spanned(s) => write!(formatter, "{:?}", s),
+ }
+ }
+}
+
+impl From<&str> for RawString {
+ #[inline]
+ fn from(s: &str) -> Self {
+ if s.is_empty() {
+ Self(RawStringInner::Empty)
+ } else {
+ InternalString::from(s).into()
+ }
+ }
+}
+
+impl From<String> for RawString {
+ #[inline]
+ fn from(s: String) -> Self {
+ if s.is_empty() {
+ Self(RawStringInner::Empty)
+ } else {
+ InternalString::from(s).into()
+ }
+ }
+}
+
+impl From<&String> for RawString {
+ #[inline]
+ fn from(s: &String) -> Self {
+ if s.is_empty() {
+ Self(RawStringInner::Empty)
+ } else {
+ InternalString::from(s).into()
+ }
+ }
+}
+
+impl From<InternalString> for RawString {
+ #[inline]
+ fn from(inner: InternalString) -> Self {
+ Self(RawStringInner::Explicit(inner))
+ }
+}
+
+impl From<&InternalString> for RawString {
+ #[inline]
+ fn from(s: &InternalString) -> Self {
+ if s.is_empty() {
+ Self(RawStringInner::Empty)
+ } else {
+ InternalString::from(s).into()
+ }
+ }
+}
+
+impl From<Box<str>> for RawString {
+ #[inline]
+ fn from(s: Box<str>) -> Self {
+ if s.is_empty() {
+ Self(RawStringInner::Empty)
+ } else {
+ InternalString::from(s).into()
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/repr.rs b/vendor/toml_edit-0.19.11/src/repr.rs
new file mode 100644
index 000000000..d4ab6c231
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/repr.rs
@@ -0,0 +1,253 @@
+use std::borrow::Cow;
+
+use crate::RawString;
+
+/// A value together with its `to_string` representation,
+/// including surrounding it whitespaces and comments.
+#[derive(Eq, PartialEq, Clone, Hash)]
+pub struct Formatted<T> {
+ value: T,
+ repr: Option<Repr>,
+ decor: Decor,
+}
+
+impl<T> Formatted<T>
+where
+ T: ValueRepr,
+{
+ /// Default-formatted value
+ pub fn new(value: T) -> Self {
+ Self {
+ value,
+ repr: None,
+ decor: Default::default(),
+ }
+ }
+
+ pub(crate) fn set_repr_unchecked(&mut self, repr: Repr) {
+ self.repr = Some(repr);
+ }
+
+ /// The wrapped value
+ pub fn value(&self) -> &T {
+ &self.value
+ }
+
+ /// The wrapped value
+ pub fn into_value(self) -> T {
+ self.value
+ }
+
+ /// Returns the raw representation, if available.
+ pub fn as_repr(&self) -> Option<&Repr> {
+ self.repr.as_ref()
+ }
+
+ /// Returns the default raw representation.
+ pub fn default_repr(&self) -> Repr {
+ self.value.to_repr()
+ }
+
+ /// Returns a raw representation.
+ pub fn display_repr(&self) -> Cow<str> {
+ self.as_repr()
+ .and_then(|r| r.as_raw().as_str())
+ .map(Cow::Borrowed)
+ .unwrap_or_else(|| {
+ Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned())
+ })
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.repr.as_ref().and_then(|r| r.span())
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.decor.despan(input);
+ if let Some(repr) = &mut self.repr {
+ repr.despan(input);
+ }
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ &mut self.decor
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor(&self) -> &Decor {
+ &self.decor
+ }
+
+ /// Auto formats the value.
+ pub fn fmt(&mut self) {
+ self.repr = Some(self.value.to_repr());
+ }
+}
+
+impl<T> std::fmt::Debug for Formatted<T>
+where
+ T: std::fmt::Debug,
+{
+ #[inline]
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ let mut d = formatter.debug_struct("Formatted");
+ d.field("value", &self.value);
+ match &self.repr {
+ Some(r) => d.field("repr", r),
+ None => d.field("repr", &"default"),
+ };
+ d.field("decor", &self.decor);
+ d.finish()
+ }
+}
+
+impl<T> std::fmt::Display for Formatted<T>
+where
+ T: ValueRepr,
+{
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ crate::encode::Encode::encode(self, f, None, ("", ""))
+ }
+}
+
+pub trait ValueRepr: crate::private::Sealed {
+ /// The TOML representation of the value
+ fn to_repr(&self) -> Repr;
+}
+
+/// TOML-encoded value
+#[derive(Eq, PartialEq, Clone, Hash)]
+pub struct Repr {
+ raw_value: RawString,
+}
+
+impl Repr {
+ pub(crate) fn new_unchecked(raw: impl Into<RawString>) -> Self {
+ Repr {
+ raw_value: raw.into(),
+ }
+ }
+
+ /// Access the underlying value
+ pub fn as_raw(&self) -> &RawString {
+ &self.raw_value
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.raw_value.span()
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.raw_value.despan(input)
+ }
+
+ pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result {
+ self.as_raw().encode(buf, input)
+ }
+}
+
+impl std::fmt::Debug for Repr {
+ #[inline]
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ self.raw_value.fmt(formatter)
+ }
+}
+
+/// A prefix and suffix,
+///
+/// Including comments, whitespaces and newlines.
+#[derive(Eq, PartialEq, Clone, Default, Hash)]
+pub struct Decor {
+ prefix: Option<RawString>,
+ suffix: Option<RawString>,
+}
+
+impl Decor {
+ /// Creates a new decor from the given prefix and suffix.
+ pub fn new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self {
+ Self {
+ prefix: Some(prefix.into()),
+ suffix: Some(suffix.into()),
+ }
+ }
+
+ /// Go back to default decor
+ pub fn clear(&mut self) {
+ self.prefix = None;
+ self.suffix = None;
+ }
+
+ /// Get the prefix.
+ pub fn prefix(&self) -> Option<&RawString> {
+ self.prefix.as_ref()
+ }
+
+ pub(crate) fn prefix_encode(
+ &self,
+ buf: &mut dyn std::fmt::Write,
+ input: Option<&str>,
+ default: &str,
+ ) -> std::fmt::Result {
+ if let Some(prefix) = self.prefix() {
+ prefix.encode_with_default(buf, input, default)
+ } else {
+ write!(buf, "{}", default)
+ }
+ }
+
+ /// Set the prefix.
+ pub fn set_prefix(&mut self, prefix: impl Into<RawString>) {
+ self.prefix = Some(prefix.into());
+ }
+
+ /// Get the suffix.
+ pub fn suffix(&self) -> Option<&RawString> {
+ self.suffix.as_ref()
+ }
+
+ pub(crate) fn suffix_encode(
+ &self,
+ buf: &mut dyn std::fmt::Write,
+ input: Option<&str>,
+ default: &str,
+ ) -> std::fmt::Result {
+ if let Some(suffix) = self.suffix() {
+ suffix.encode_with_default(buf, input, default)
+ } else {
+ write!(buf, "{}", default)
+ }
+ }
+
+ /// Set the suffix.
+ pub fn set_suffix(&mut self, suffix: impl Into<RawString>) {
+ self.suffix = Some(suffix.into());
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ if let Some(prefix) = &mut self.prefix {
+ prefix.despan(input);
+ }
+ if let Some(suffix) = &mut self.suffix {
+ suffix.despan(input);
+ }
+ }
+}
+
+impl std::fmt::Debug for Decor {
+ #[inline]
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ let mut d = formatter.debug_struct("Decor");
+ match &self.prefix {
+ Some(r) => d.field("prefix", r),
+ None => d.field("prefix", &"default"),
+ };
+ match &self.suffix {
+ Some(r) => d.field("suffix", r),
+ None => d.field("suffix", &"default"),
+ };
+ d.finish()
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/ser/array.rs b/vendor/toml_edit-0.19.11/src/ser/array.rs
new file mode 100644
index 000000000..80eba8ba7
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/ser/array.rs
@@ -0,0 +1,84 @@
+use super::Error;
+
+#[doc(hidden)]
+pub struct SerializeValueArray {
+ values: Vec<crate::Item>,
+}
+
+impl SerializeValueArray {
+ pub(crate) fn new() -> Self {
+ Self { values: Vec::new() }
+ }
+
+ pub(crate) fn with_capacity(len: usize) -> Self {
+ Self {
+ values: Vec::with_capacity(len),
+ }
+ }
+}
+
+impl serde::ser::SerializeSeq for SerializeValueArray {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ let value = value.serialize(super::ValueSerializer {})?;
+ self.values.push(crate::Item::Value(value));
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(crate::Value::Array(crate::Array::with_vec(self.values)))
+ }
+}
+
+impl serde::ser::SerializeTuple for SerializeValueArray {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
+
+impl serde::ser::SerializeTupleVariant for SerializeValueArray {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
+
+impl serde::ser::SerializeTupleStruct for SerializeValueArray {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/ser/key.rs b/vendor/toml_edit-0.19.11/src/ser/key.rs
new file mode 100644
index 000000000..d5e381bf7
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/ser/key.rs
@@ -0,0 +1,173 @@
+use crate::InternalString;
+
+use super::Error;
+
+pub(crate) struct KeySerializer;
+
+impl serde::ser::Serializer for KeySerializer {
+ type Ok = InternalString;
+ type Error = Error;
+ type SerializeSeq = serde::ser::Impossible<InternalString, Error>;
+ type SerializeTuple = serde::ser::Impossible<InternalString, Error>;
+ type SerializeTupleStruct = serde::ser::Impossible<InternalString, Error>;
+ type SerializeTupleVariant = serde::ser::Impossible<InternalString, Error>;
+ type SerializeMap = serde::ser::Impossible<InternalString, Error>;
+ type SerializeStruct = serde::ser::Impossible<InternalString, Error>;
+ type SerializeStructVariant = serde::ser::Impossible<InternalString, Error>;
+
+ fn serialize_bool(self, _v: bool) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i8(self, _v: i8) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i16(self, _v: i16) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i32(self, _v: i32) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_i64(self, _v: i64) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u8(self, _v: u8) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u16(self, _v: u16) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u32(self, _v: u32) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_u64(self, _v: u64) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_f32(self, _v: f32) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_f64(self, _v: f64) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_char(self, _v: char) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_str(self, value: &str) -> Result<InternalString, Self::Error> {
+ Ok(InternalString::from(value))
+ }
+
+ fn serialize_bytes(self, _value: &[u8]) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_none(self) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<InternalString, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit(self) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<InternalString, Self::Error> {
+ Err(Error::KeyNotString)
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ ) -> Result<InternalString, Self::Error> {
+ Ok(variant.into())
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _name: &'static str,
+ value: &T,
+ ) -> Result<InternalString, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _value: &T,
+ ) -> Result<InternalString, Self::Error>
+ where
+ T: serde::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)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/ser/map.rs b/vendor/toml_edit-0.19.11/src/ser/map.rs
new file mode 100644
index 000000000..d743e3d5d
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/ser/map.rs
@@ -0,0 +1,405 @@
+use super::{Error, KeySerializer};
+
+#[doc(hidden)]
+pub enum SerializeMap {
+ Datetime(SerializeDatetime),
+ Table(SerializeInlineTable),
+}
+
+impl SerializeMap {
+ pub(crate) fn table() -> Self {
+ Self::Table(SerializeInlineTable::new())
+ }
+
+ pub(crate) fn table_with_capacity(len: usize) -> Self {
+ Self::Table(SerializeInlineTable::with_capacity(len))
+ }
+
+ pub(crate) fn datetime() -> Self {
+ Self::Datetime(SerializeDatetime::new())
+ }
+}
+
+impl serde::ser::SerializeMap for SerializeMap {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ match self {
+ Self::Datetime(s) => s.serialize_key(input),
+ Self::Table(s) => s.serialize_key(input),
+ }
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ match self {
+ Self::Datetime(s) => s.serialize_value(value),
+ Self::Table(s) => s.serialize_value(value),
+ }
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ match self {
+ Self::Datetime(s) => s.end().map(|items| items.into()),
+ Self::Table(s) => s.end().map(|items| items.into()),
+ }
+ }
+}
+
+impl serde::ser::SerializeStruct for SerializeMap {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(
+ &mut self,
+ key: &'static str,
+ value: &T,
+ ) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ match self {
+ Self::Datetime(s) => s.serialize_field(key, value),
+ Self::Table(s) => s.serialize_field(key, value),
+ }
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ match self {
+ Self::Datetime(s) => s.end().map(|items| items.into()),
+ Self::Table(s) => s.end().map(|items| items.into()),
+ }
+ }
+}
+
+#[doc(hidden)]
+pub struct SerializeDatetime {
+ value: Option<crate::Datetime>,
+}
+
+impl SerializeDatetime {
+ pub(crate) fn new() -> Self {
+ Self { value: None }
+ }
+}
+
+impl serde::ser::SerializeMap for SerializeDatetime {
+ type Ok = crate::Datetime;
+ type Error = Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, _input: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ unreachable!("datetimes should only be serialized as structs, not maps")
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ unreachable!("datetimes should only be serialized as structs, not maps")
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ unreachable!("datetimes should only be serialized as structs, not maps")
+ }
+}
+
+impl serde::ser::SerializeStruct for SerializeDatetime {
+ type Ok = crate::Datetime;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(
+ &mut self,
+ key: &'static str,
+ value: &T,
+ ) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ if key == toml_datetime::__unstable::FIELD {
+ self.value = Some(value.serialize(DatetimeFieldSerializer::default())?);
+ }
+
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ self.value.ok_or(Error::UnsupportedNone)
+ }
+}
+
+#[doc(hidden)]
+pub struct SerializeInlineTable {
+ items: crate::table::KeyValuePairs,
+ key: Option<crate::InternalString>,
+}
+
+impl SerializeInlineTable {
+ pub(crate) fn new() -> Self {
+ Self {
+ items: Default::default(),
+ key: Default::default(),
+ }
+ }
+
+ pub(crate) fn with_capacity(len: usize) -> Self {
+ let mut s = Self::new();
+ s.items.reserve(len);
+ s
+ }
+}
+
+impl serde::ser::SerializeMap for SerializeInlineTable {
+ type Ok = crate::InlineTable;
+ type Error = Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ self.key = None;
+ self.key = Some(input.serialize(KeySerializer)?);
+ Ok(())
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ let res = value.serialize(super::ValueSerializer {});
+ match res {
+ Ok(item) => {
+ let key = self.key.take().unwrap();
+ let kv = crate::table::TableKeyValue::new(
+ crate::Key::new(&key),
+ crate::Item::Value(item),
+ );
+ self.items.insert(key, kv);
+ }
+ Err(e) => {
+ if e != Error::UnsupportedNone {
+ return Err(e);
+ }
+ }
+ }
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(crate::InlineTable::with_pairs(self.items))
+ }
+}
+
+impl serde::ser::SerializeStruct for SerializeInlineTable {
+ type Ok = crate::InlineTable;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(
+ &mut self,
+ key: &'static str,
+ value: &T,
+ ) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ let res = value.serialize(super::ValueSerializer {});
+ match res {
+ Ok(item) => {
+ let kv = crate::table::TableKeyValue::new(
+ crate::Key::new(key),
+ crate::Item::Value(item),
+ );
+ self.items.insert(crate::InternalString::from(key), kv);
+ }
+ Err(e) => {
+ if e != Error::UnsupportedNone {
+ return Err(e);
+ }
+ }
+ };
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(crate::InlineTable::with_pairs(self.items))
+ }
+}
+
+#[derive(Default)]
+struct DatetimeFieldSerializer {}
+
+impl serde::ser::Serializer for DatetimeFieldSerializer {
+ type Ok = toml_datetime::Datetime;
+ type Error = Error;
+ type SerializeSeq = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeTuple = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeTupleStruct = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeTupleVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeMap = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeStruct = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
+
+ fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i16(self, _value: i16) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i32(self, _value: i32) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_i64(self, _value: i64) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u8(self, _value: u8) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u16(self, _value: u16) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u32(self, _value: u32) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_u64(self, _value: u64) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_f32(self, _value: f32) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_f64(self, _value: f64) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_char(self, _value: char) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
+ v.parse::<toml_datetime::Datetime>().map_err(Error::custom)
+ }
+
+ fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ ) -> Result<Self::Ok, Self::Error> {
+ Err(Error::DateInvalid)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _name: &'static str,
+ _value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::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::Ok, Self::Error>
+ where
+ T: serde::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)
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/ser/mod.rs b/vendor/toml_edit-0.19.11/src/ser/mod.rs
new file mode 100644
index 000000000..2c310206b
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/ser/mod.rs
@@ -0,0 +1,165 @@
+//! Serializing Rust structures into TOML.
+//!
+//! This module contains all the Serde support for serializing Rust structures into TOML.
+
+mod array;
+mod key;
+mod map;
+mod pretty;
+mod value;
+
+pub(crate) use array::*;
+pub(crate) use key::*;
+pub(crate) use map::*;
+
+use crate::visit_mut::VisitMut;
+
+/// Errors that can occur when deserializing a type.
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum Error {
+ /// Type could not be serialized to TOML
+ UnsupportedType(Option<&'static str>),
+ /// Value was out of range for the given type
+ OutOfRange(Option<&'static str>),
+ /// `None` could not be serialized to TOML
+ UnsupportedNone,
+ /// Key was not convertable to `String` for serializing to TOML
+ KeyNotString,
+ /// A serialized date was invalid
+ DateInvalid,
+ /// Other serialization error
+ Custom(String),
+}
+
+impl Error {
+ pub(crate) fn custom<T>(msg: T) -> Self
+ where
+ T: std::fmt::Display,
+ {
+ Error::Custom(msg.to_string())
+ }
+}
+
+impl serde::ser::Error for Error {
+ fn custom<T>(msg: T) -> Self
+ where
+ T: std::fmt::Display,
+ {
+ Self::custom(msg)
+ }
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+ match self {
+ Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"),
+ Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"),
+ Self::OutOfRange(Some(t)) => write!(formatter, "out-of-range value for {t} type"),
+ Self::OutOfRange(None) => write!(formatter, "out-of-range value"),
+ Self::UnsupportedNone => "unsupported None value".fmt(formatter),
+ Self::KeyNotString => "map key was not a string".fmt(formatter),
+ Self::DateInvalid => "a serialized date was invalid".fmt(formatter),
+ Self::Custom(s) => s.fmt(formatter),
+ }
+ }
+}
+
+impl From<crate::TomlError> for Error {
+ fn from(e: crate::TomlError) -> Error {
+ Self::custom(e)
+ }
+}
+
+impl From<Error> for crate::TomlError {
+ fn from(e: Error) -> crate::TomlError {
+ Self::custom(e.to_string(), None)
+ }
+}
+
+impl std::error::Error for Error {}
+
+/// 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: serde::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
+///
+/// ```
+/// use serde::Serialize;
+///
+/// #[derive(Serialize)]
+/// struct Config {
+/// database: Database,
+/// }
+///
+/// #[derive(Serialize)]
+/// struct Database {
+/// ip: String,
+/// port: Vec<u16>,
+/// connection_max: u32,
+/// enabled: bool,
+/// }
+///
+/// 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_edit::ser::to_string(&config).unwrap();
+/// println!("{}", toml)
+/// ```
+pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error>
+where
+ T: serde::ser::Serialize,
+{
+ to_document(value).map(|e| e.to_string())
+}
+
+/// 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 `ValueSerializer::pretty` for more details.
+pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error>
+where
+ T: serde::ser::Serialize,
+{
+ let mut document = to_document(value)?;
+ pretty::Pretty.visit_document_mut(&mut document);
+ Ok(document.to_string())
+}
+
+/// Serialize the given data structure into a TOML document.
+///
+/// This would allow custom formatting to be applied, mixing with format preserving edits, etc.
+pub fn to_document<T: ?Sized>(value: &T) -> Result<crate::Document, Error>
+where
+ T: serde::ser::Serialize,
+{
+ let value = value.serialize(ValueSerializer::new())?;
+ let item = crate::Item::Value(value);
+ let root = item
+ .into_table()
+ .map_err(|_| Error::UnsupportedType(None))?;
+ Ok(root.into())
+}
+
+pub use value::ValueSerializer;
diff --git a/vendor/toml_edit-0.19.11/src/ser/pretty.rs b/vendor/toml_edit-0.19.11/src/ser/pretty.rs
new file mode 100644
index 000000000..2c22f6804
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/ser/pretty.rs
@@ -0,0 +1,45 @@
+pub(crate) struct Pretty;
+
+impl crate::visit_mut::VisitMut for Pretty {
+ fn visit_document_mut(&mut self, node: &mut crate::Document) {
+ crate::visit_mut::visit_document_mut(self, node);
+ }
+
+ fn visit_item_mut(&mut self, node: &mut crate::Item) {
+ node.make_item();
+
+ crate::visit_mut::visit_item_mut(self, node);
+ }
+
+ fn visit_table_mut(&mut self, node: &mut crate::Table) {
+ node.decor_mut().clear();
+
+ // Empty tables could be semantically meaningful, so make sure they are not implicit
+ if !node.is_empty() {
+ node.set_implicit(true);
+ }
+
+ crate::visit_mut::visit_table_mut(self, node);
+ }
+
+ fn visit_value_mut(&mut self, node: &mut crate::Value) {
+ node.decor_mut().clear();
+
+ crate::visit_mut::visit_value_mut(self, node);
+ }
+
+ fn visit_array_mut(&mut self, node: &mut crate::Array) {
+ crate::visit_mut::visit_array_mut(self, node);
+
+ if (0..=1).contains(&node.len()) {
+ node.set_trailing("");
+ node.set_trailing_comma(false);
+ } else {
+ for item in node.iter_mut() {
+ item.decor_mut().set_prefix("\n ");
+ }
+ node.set_trailing("\n");
+ node.set_trailing_comma(true);
+ }
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/ser/value.rs b/vendor/toml_edit-0.19.11/src/ser/value.rs
new file mode 100644
index 000000000..d29390a4c
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/ser/value.rs
@@ -0,0 +1,243 @@
+use super::Error;
+
+/// Serialization for TOML [values][crate::Value].
+///
+/// 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.
+///
+/// # Examples
+///
+/// ```
+/// use serde::Serialize;
+///
+/// #[derive(Serialize)]
+/// struct Config {
+/// database: Database,
+/// }
+///
+/// #[derive(Serialize)]
+/// struct Database {
+/// ip: String,
+/// port: Vec<u16>,
+/// connection_max: u32,
+/// enabled: bool,
+/// }
+///
+/// let config = Config {
+/// database: Database {
+/// ip: "192.168.1.1".to_string(),
+/// port: vec![8001, 8002, 8003],
+/// connection_max: 5000,
+/// enabled: false,
+/// },
+/// };
+///
+/// let value = serde::Serialize::serialize(
+/// &config,
+/// toml_edit::ser::ValueSerializer::new()
+/// ).unwrap();
+/// println!("{}", value)
+/// ```
+#[derive(Default)]
+#[non_exhaustive]
+pub struct ValueSerializer {}
+
+impl ValueSerializer {
+ /// Creates a new serializer generate a TOML document.
+ pub fn new() -> Self {
+ Self {}
+ }
+}
+
+impl serde::ser::Serializer for ValueSerializer {
+ type Ok = crate::Value;
+ type Error = Error;
+ type SerializeSeq = super::SerializeValueArray;
+ type SerializeTuple = super::SerializeValueArray;
+ type SerializeTupleStruct = super::SerializeValueArray;
+ type SerializeTupleVariant = super::SerializeValueArray;
+ type SerializeMap = super::SerializeMap;
+ type SerializeStruct = super::SerializeMap;
+ type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
+
+ fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
+ Ok(v.into())
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
+ Ok(v.into())
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
+ let v: i64 = v
+ .try_into()
+ .map_err(|_err| Error::OutOfRange(Some("u64")))?;
+ self.serialize_i64(v)
+ }
+
+ fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
+ self.serialize_f64(v as f64)
+ }
+
+ fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
+ Ok(v.into())
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
+ let mut buf = [0; 4];
+ self.serialize_str(v.encode_utf8(&mut buf))
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
+ Ok(v.into())
+ }
+
+ fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> {
+ use serde::ser::Serialize;
+ value.serialize(self)
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+ Err(Error::UnsupportedNone)
+ }
+
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+ Err(Error::UnsupportedType(Some("unit")))
+ }
+
+ fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
+ Err(Error::UnsupportedType(Some(name)))
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ ) -> Result<Self::Ok, Self::Error> {
+ self.serialize_str(variant)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _name: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::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::Ok, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ let value = value.serialize(self)?;
+ let mut table = crate::InlineTable::new();
+ table.insert(variant, value);
+ Ok(table.into())
+ }
+
+ fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+ let serializer = match len {
+ Some(len) => super::SerializeValueArray::with_capacity(len),
+ None => super::SerializeValueArray::new(),
+ };
+ Ok(serializer)
+ }
+
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
+ let serializer = match len {
+ Some(len) => super::SerializeMap::table_with_capacity(len),
+ None => super::SerializeMap::table(),
+ };
+ Ok(serializer)
+ }
+
+ fn serialize_struct(
+ self,
+ name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeStruct, Self::Error> {
+ if name == toml_datetime::__unstable::NAME {
+ Ok(super::SerializeMap::datetime())
+ } else {
+ self.serialize_map(Some(len))
+ }
+ }
+
+ fn serialize_struct_variant(
+ self,
+ name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStructVariant, Self::Error> {
+ Err(Error::UnsupportedType(Some(name)))
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/table.rs b/vendor/toml_edit-0.19.11/src/table.rs
new file mode 100644
index 000000000..2f61abf73
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/table.rs
@@ -0,0 +1,743 @@
+use std::iter::FromIterator;
+
+use indexmap::map::IndexMap;
+
+use crate::key::Key;
+use crate::repr::Decor;
+use crate::value::DEFAULT_VALUE_DECOR;
+use crate::{InlineTable, InternalString, Item, KeyMut, Value};
+
+/// Type representing a TOML non-inline table
+#[derive(Clone, Debug, Default)]
+pub struct Table {
+ // Comments/spaces before and after the header
+ pub(crate) decor: Decor,
+ // Whether to hide an empty table
+ pub(crate) implicit: bool,
+ // Whether this is a proxy for dotted keys
+ pub(crate) dotted: bool,
+ // Used for putting tables back in their original order when serialising.
+ //
+ // `None` for user created tables (can be overridden with `set_position`)
+ doc_position: Option<usize>,
+ pub(crate) span: Option<std::ops::Range<usize>>,
+ pub(crate) items: KeyValuePairs,
+}
+
+/// Constructors
+///
+/// See also `FromIterator`
+impl Table {
+ /// Creates an empty table.
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub(crate) fn with_pos(doc_position: Option<usize>) -> Self {
+ Self {
+ doc_position,
+ ..Default::default()
+ }
+ }
+
+ pub(crate) fn with_pairs(items: KeyValuePairs) -> Self {
+ Self {
+ items,
+ ..Default::default()
+ }
+ }
+
+ /// Convert to an inline table
+ pub fn into_inline_table(mut self) -> InlineTable {
+ for (_, kv) in self.items.iter_mut() {
+ kv.value.make_value();
+ }
+ let mut t = InlineTable::with_pairs(self.items);
+ t.fmt();
+ t
+ }
+}
+
+/// Formatting
+impl Table {
+ /// Get key/values for values that are visually children of this table
+ ///
+ /// For example, this will return dotted keys
+ pub fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
+ let mut values = Vec::new();
+ let root = Vec::new();
+ self.append_values(&root, &mut values);
+ values
+ }
+
+ fn append_values<'s, 'c>(
+ &'s self,
+ parent: &[&'s Key],
+ values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>,
+ ) {
+ for value in self.items.values() {
+ let mut path = parent.to_vec();
+ path.push(&value.key);
+ match &value.value {
+ Item::Table(table) if table.is_dotted() => {
+ table.append_values(&path, values);
+ }
+ Item::Value(value) => {
+ if let Some(table) = value.as_inline_table() {
+ if table.is_dotted() {
+ table.append_values(&path, values);
+ } else {
+ values.push((path, value));
+ }
+ } else {
+ values.push((path, value));
+ }
+ }
+ _ => {}
+ }
+ }
+ }
+
+ /// Auto formats the table.
+ pub fn fmt(&mut self) {
+ decorate_table(self);
+ }
+
+ /// Sorts Key/Value Pairs of the table.
+ ///
+ /// Doesn't affect subtables or subarrays.
+ pub fn sort_values(&mut self) {
+ // Assuming standard tables have their doc_position set and this won't negatively impact them
+ self.items.sort_keys();
+ for kv in self.items.values_mut() {
+ match &mut kv.value {
+ Item::Table(table) if table.is_dotted() => {
+ table.sort_values();
+ }
+ _ => {}
+ }
+ }
+ }
+
+ /// Sort Key/Value Pairs of the table using the using the comparison function `compare`.
+ ///
+ /// The comparison function receives two key and value pairs to compare (you can sort by keys or
+ /// values or their combination as needed).
+ pub fn sort_values_by<F>(&mut self, mut compare: F)
+ where
+ F: FnMut(&Key, &Item, &Key, &Item) -> std::cmp::Ordering,
+ {
+ self.sort_values_by_internal(&mut compare);
+ }
+
+ fn sort_values_by_internal<F>(&mut self, compare: &mut F)
+ where
+ F: FnMut(&Key, &Item, &Key, &Item) -> std::cmp::Ordering,
+ {
+ let modified_cmp = |_: &InternalString,
+ val1: &TableKeyValue,
+ _: &InternalString,
+ val2: &TableKeyValue|
+ -> std::cmp::Ordering {
+ compare(&val1.key, &val1.value, &val2.key, &val2.value)
+ };
+
+ self.items.sort_by(modified_cmp);
+
+ for kv in self.items.values_mut() {
+ match &mut kv.value {
+ Item::Table(table) if table.is_dotted() => {
+ table.sort_values_by_internal(compare);
+ }
+ _ => {}
+ }
+ }
+ }
+
+ /// If a table has no key/value pairs and implicit, it will not be displayed.
+ ///
+ /// # Examples
+ ///
+ /// ```notrust
+ /// [target."x86_64/windows.json".dependencies]
+ /// ```
+ ///
+ /// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit.
+ ///
+ /// ```
+ /// use toml_edit::Document;
+ /// let mut doc = "[a]\n[a.b]\n".parse::<Document>().expect("invalid toml");
+ ///
+ /// doc["a"].as_table_mut().unwrap().set_implicit(true);
+ /// assert_eq!(doc.to_string(), "[a.b]\n");
+ /// ```
+ pub fn set_implicit(&mut self, implicit: bool) {
+ self.implicit = implicit;
+ }
+
+ /// If a table has no key/value pairs and implicit, it will not be displayed.
+ pub fn is_implicit(&self) -> bool {
+ self.implicit
+ }
+
+ /// Change this table's dotted status
+ pub fn set_dotted(&mut self, yes: bool) {
+ self.dotted = yes;
+ }
+
+ /// Check if this is a wrapper for dotted keys, rather than a standard table
+ pub fn is_dotted(&self) -> bool {
+ self.dotted
+ }
+
+ /// Sets the position of the `Table` within the `Document`.
+ pub fn set_position(&mut self, doc_position: usize) {
+ self.doc_position = Some(doc_position);
+ }
+
+ /// The position of the `Table` within the `Document`.
+ ///
+ /// Returns `None` if the `Table` was created manually (i.e. not via parsing)
+ /// in which case its position is set automatically. This can be overridden with
+ /// [`Table::set_position`].
+ pub fn position(&self) -> Option<usize> {
+ self.doc_position
+ }
+
+ /// Returns the surrounding whitespace
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ &mut self.decor
+ }
+
+ /// Returns the decor associated with a given key of the table.
+ pub fn decor(&self) -> &Decor {
+ &self.decor
+ }
+
+ /// Returns the decor associated with a given key of the table.
+ pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> {
+ self.items.get_mut(key).map(|kv| &mut kv.key.decor)
+ }
+
+ /// Returns the decor associated with a given key of the table.
+ pub fn key_decor(&self, key: &str) -> Option<&Decor> {
+ self.items.get(key).map(|kv| &kv.key.decor)
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ self.span.clone()
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ self.span = None;
+ self.decor.despan(input);
+ for kv in self.items.values_mut() {
+ kv.key.despan(input);
+ kv.value.despan(input);
+ }
+ }
+}
+
+impl Table {
+ /// Returns an iterator over all key/value pairs, including empty.
+ pub fn iter(&self) -> Iter<'_> {
+ Box::new(
+ self.items
+ .iter()
+ .filter(|(_, kv)| !kv.value.is_none())
+ .map(|(key, kv)| (&key[..], &kv.value)),
+ )
+ }
+
+ /// Returns an mutable iterator over all key/value pairs, including empty.
+ pub fn iter_mut(&mut self) -> IterMut<'_> {
+ Box::new(
+ self.items
+ .iter_mut()
+ .filter(|(_, kv)| !kv.value.is_none())
+ .map(|(_, kv)| (kv.key.as_mut(), &mut kv.value)),
+ )
+ }
+
+ /// Returns the number of non-empty items in the table.
+ pub fn len(&self) -> usize {
+ self.items.iter().filter(|i| !(i.1).value.is_none()).count()
+ }
+
+ /// Returns true if the table is empty.
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse.
+ pub fn clear(&mut self) {
+ self.items.clear()
+ }
+
+ /// Gets the given key's corresponding entry in the Table for in-place manipulation.
+ pub fn entry<'a>(&'a mut self, key: &str) -> Entry<'a> {
+ // Accept a `&str` rather than an owned type to keep `InternalString`, well, internal
+ match self.items.entry(key.into()) {
+ indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }),
+ indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry, key: None }),
+ }
+ }
+
+ /// Gets the given key's corresponding entry in the Table for in-place manipulation.
+ pub fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a> {
+ // Accept a `&Key` to be consistent with `entry`
+ match self.items.entry(key.get().into()) {
+ indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }),
+ indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry {
+ entry,
+ key: Some(key.to_owned()),
+ }),
+ }
+ }
+
+ /// Returns an optional reference to an item given the key.
+ pub fn get<'a>(&'a self, key: &str) -> Option<&'a Item> {
+ self.items.get(key).and_then(|kv| {
+ if !kv.value.is_none() {
+ Some(&kv.value)
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Returns an optional mutable reference to an item given the key.
+ pub fn get_mut<'a>(&'a mut self, key: &str) -> Option<&'a mut Item> {
+ self.items.get_mut(key).and_then(|kv| {
+ if !kv.value.is_none() {
+ Some(&mut kv.value)
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Return references to the key-value pair stored for key, if it is present, else None.
+ pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> {
+ self.items.get(key).and_then(|kv| {
+ if !kv.value.is_none() {
+ Some((&kv.key, &kv.value))
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Return mutable references to the key-value pair stored for key, if it is present, else None.
+ pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> {
+ self.items.get_mut(key).and_then(|kv| {
+ if !kv.value.is_none() {
+ Some((kv.key.as_mut(), &mut kv.value))
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Returns true if the table contains an item with the given key.
+ pub fn contains_key(&self, key: &str) -> bool {
+ if let Some(kv) = self.items.get(key) {
+ !kv.value.is_none()
+ } else {
+ false
+ }
+ }
+
+ /// Returns true if the table contains a table with the given key.
+ pub fn contains_table(&self, key: &str) -> bool {
+ if let Some(kv) = self.items.get(key) {
+ kv.value.is_table()
+ } else {
+ false
+ }
+ }
+
+ /// Returns true if the table contains a value with the given key.
+ pub fn contains_value(&self, key: &str) -> bool {
+ if let Some(kv) = self.items.get(key) {
+ kv.value.is_value()
+ } else {
+ false
+ }
+ }
+
+ /// Returns true if the table contains an array of tables with the given key.
+ pub fn contains_array_of_tables(&self, key: &str) -> bool {
+ if let Some(kv) = self.items.get(key) {
+ kv.value.is_array_of_tables()
+ } else {
+ false
+ }
+ }
+
+ /// Inserts a key-value pair into the map.
+ pub fn insert(&mut self, key: &str, item: Item) -> Option<Item> {
+ let kv = TableKeyValue::new(Key::new(key), item);
+ self.items.insert(key.into(), kv).map(|kv| kv.value)
+ }
+
+ /// Inserts a key-value pair into the map.
+ pub fn insert_formatted(&mut self, key: &Key, item: Item) -> Option<Item> {
+ let kv = TableKeyValue::new(key.to_owned(), item);
+ self.items.insert(key.get().into(), kv).map(|kv| kv.value)
+ }
+
+ /// Removes an item given the key.
+ pub fn remove(&mut self, key: &str) -> Option<Item> {
+ self.items.shift_remove(key).map(|kv| kv.value)
+ }
+
+ /// Removes a key from the map, returning the stored key and value if the key was previously in the map.
+ pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Item)> {
+ self.items.shift_remove(key).map(|kv| (kv.key, kv.value))
+ }
+}
+
+impl std::fmt::Display for Table {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ use crate::encode::Encode;
+ let children = self.get_values();
+ // print table body
+ for (key_path, value) in children {
+ key_path.as_slice().encode(f, None, DEFAULT_KEY_DECOR)?;
+ write!(f, "=")?;
+ value.encode(f, None, DEFAULT_VALUE_DECOR)?;
+ writeln!(f)?;
+ }
+ Ok(())
+ }
+}
+
+impl<K: Into<Key>, V: Into<Value>> Extend<(K, V)> for Table {
+ fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
+ for (key, value) in iter {
+ let key = key.into();
+ let value = Item::Value(value.into());
+ let value = TableKeyValue::new(key, value);
+ self.items.insert(value.key.get().into(), value);
+ }
+ }
+}
+
+impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Table {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = (K, V)>,
+ {
+ let mut table = Table::new();
+ table.extend(iter);
+ table
+ }
+}
+
+impl IntoIterator for Table {
+ type Item = (InternalString, Item);
+ type IntoIter = IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Box::new(self.items.into_iter().map(|(k, kv)| (k, kv.value)))
+ }
+}
+
+impl<'s> IntoIterator for &'s Table {
+ type Item = (&'s str, &'s Item);
+ type IntoIter = Iter<'s>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+pub(crate) type KeyValuePairs = IndexMap<InternalString, TableKeyValue>;
+
+fn decorate_table(table: &mut Table) {
+ for (key_decor, value) in table
+ .items
+ .iter_mut()
+ .filter(|&(_, ref kv)| kv.value.is_value())
+ .map(|(_, kv)| (&mut kv.key.decor, kv.value.as_value_mut().unwrap()))
+ {
+ key_decor.clear();
+ value.decor_mut().clear();
+ }
+}
+
+// `key1 = value1`
+pub(crate) const DEFAULT_KEY_DECOR: (&str, &str) = ("", " ");
+pub(crate) const DEFAULT_TABLE_DECOR: (&str, &str) = ("\n", "");
+pub(crate) const DEFAULT_KEY_PATH_DECOR: (&str, &str) = ("", "");
+
+#[derive(Debug, Clone)]
+pub(crate) struct TableKeyValue {
+ pub(crate) key: Key,
+ pub(crate) value: Item,
+}
+
+impl TableKeyValue {
+ pub(crate) fn new(key: Key, value: Item) -> Self {
+ TableKeyValue { key, value }
+ }
+}
+
+/// An owned iterator type over `Table`'s key/value pairs.
+pub type IntoIter = Box<dyn Iterator<Item = (InternalString, Item)>>;
+/// An iterator type over `Table`'s key/value pairs.
+pub type Iter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Item)> + 'a>;
+/// A mutable iterator type over `Table`'s key/value pairs.
+pub type IterMut<'a> = Box<dyn Iterator<Item = (KeyMut<'a>, &'a mut Item)> + 'a>;
+
+/// This trait represents either a `Table`, or an `InlineTable`.
+pub trait TableLike: crate::private::Sealed {
+ /// Returns an iterator over key/value pairs.
+ fn iter(&self) -> Iter<'_>;
+ /// Returns an mutable iterator over all key/value pairs, including empty.
+ fn iter_mut(&mut self) -> IterMut<'_>;
+ /// Returns the number of nonempty items.
+ fn len(&self) -> usize {
+ self.iter().filter(|&(_, v)| !v.is_none()).count()
+ }
+ /// Returns true if the table is empty.
+ fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+ /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse.
+ fn clear(&mut self);
+ /// Gets the given key's corresponding entry in the Table for in-place manipulation.
+ fn entry<'a>(&'a mut self, key: &str) -> Entry<'a>;
+ /// Gets the given key's corresponding entry in the Table for in-place manipulation.
+ fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a>;
+ /// Returns an optional reference to an item given the key.
+ fn get<'s>(&'s self, key: &str) -> Option<&'s Item>;
+ /// Returns an optional mutable reference to an item given the key.
+ fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item>;
+ /// Return references to the key-value pair stored for key, if it is present, else None.
+ fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)>;
+ /// Return mutable references to the key-value pair stored for key, if it is present, else None.
+ fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)>;
+ /// Returns true if the table contains an item with the given key.
+ fn contains_key(&self, key: &str) -> bool;
+ /// Inserts a key-value pair into the map.
+ fn insert(&mut self, key: &str, value: Item) -> Option<Item>;
+ /// Removes an item given the key.
+ fn remove(&mut self, key: &str) -> Option<Item>;
+
+ /// Get key/values for values that are visually children of this table
+ ///
+ /// For example, this will return dotted keys
+ fn get_values(&self) -> Vec<(Vec<&Key>, &Value)>;
+
+ /// Auto formats the table.
+ fn fmt(&mut self);
+ /// Sorts Key/Value Pairs of the table.
+ ///
+ /// Doesn't affect subtables or subarrays.
+ fn sort_values(&mut self);
+ /// Change this table's dotted status
+ fn set_dotted(&mut self, yes: bool);
+ /// Check if this is a wrapper for dotted keys, rather than a standard table
+ fn is_dotted(&self) -> bool;
+
+ /// Returns the decor associated with a given key of the table.
+ fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor>;
+ /// Returns the decor associated with a given key of the table.
+ fn key_decor(&self, key: &str) -> Option<&Decor>;
+}
+
+impl TableLike for Table {
+ fn iter(&self) -> Iter<'_> {
+ self.iter()
+ }
+ fn iter_mut(&mut self) -> IterMut<'_> {
+ self.iter_mut()
+ }
+ fn clear(&mut self) {
+ self.clear();
+ }
+ fn entry<'a>(&'a mut self, key: &str) -> Entry<'a> {
+ self.entry(key)
+ }
+ fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a> {
+ self.entry_format(key)
+ }
+ fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
+ self.get(key)
+ }
+ fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> {
+ self.get_mut(key)
+ }
+ fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> {
+ self.get_key_value(key)
+ }
+ fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> {
+ self.get_key_value_mut(key)
+ }
+ fn contains_key(&self, key: &str) -> bool {
+ self.contains_key(key)
+ }
+ fn insert(&mut self, key: &str, value: Item) -> Option<Item> {
+ self.insert(key, value)
+ }
+ fn remove(&mut self, key: &str) -> Option<Item> {
+ self.remove(key)
+ }
+
+ fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
+ self.get_values()
+ }
+ fn fmt(&mut self) {
+ self.fmt()
+ }
+ fn sort_values(&mut self) {
+ self.sort_values()
+ }
+ fn is_dotted(&self) -> bool {
+ self.is_dotted()
+ }
+ fn set_dotted(&mut self, yes: bool) {
+ self.set_dotted(yes)
+ }
+
+ fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> {
+ self.key_decor_mut(key)
+ }
+ fn key_decor(&self, key: &str) -> Option<&Decor> {
+ self.key_decor(key)
+ }
+}
+
+/// A view into a single location in a map, which may be vacant or occupied.
+pub enum Entry<'a> {
+ /// An occupied Entry.
+ Occupied(OccupiedEntry<'a>),
+ /// A vacant Entry.
+ Vacant(VacantEntry<'a>),
+}
+
+impl<'a> Entry<'a> {
+ /// Returns the entry key
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use toml_edit::Table;
+ ///
+ /// let mut map = Table::new();
+ ///
+ /// assert_eq!("hello", map.entry("hello").key());
+ /// ```
+ pub fn key(&self) -> &str {
+ match self {
+ Entry::Occupied(e) => e.key(),
+ Entry::Vacant(e) => e.key(),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting the default if empty, and returns
+ /// a mutable reference to the value in the entry.
+ pub fn or_insert(self, default: Item) -> &'a mut Item {
+ match self {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => entry.insert(default),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting the result of the default function if empty,
+ /// and returns a mutable reference to the value in the entry.
+ pub fn or_insert_with<F: FnOnce() -> Item>(self, default: F) -> &'a mut Item {
+ match self {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => entry.insert(default()),
+ }
+ }
+}
+
+/// A view into a single occupied location in a `IndexMap`.
+pub struct OccupiedEntry<'a> {
+ pub(crate) entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>,
+}
+
+impl<'a> OccupiedEntry<'a> {
+ /// Gets a reference to the entry key
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use toml_edit::Table;
+ ///
+ /// let mut map = Table::new();
+ ///
+ /// assert_eq!("foo", map.entry("foo").key());
+ /// ```
+ pub fn key(&self) -> &str {
+ self.entry.key().as_str()
+ }
+
+ /// Gets a mutable reference to the entry key
+ pub fn key_mut(&mut self) -> KeyMut<'_> {
+ self.entry.get_mut().key.as_mut()
+ }
+
+ /// Gets a reference to the value in the entry.
+ pub fn get(&self) -> &Item {
+ &self.entry.get().value
+ }
+
+ /// Gets a mutable reference to the value in the entry.
+ pub fn get_mut(&mut self) -> &mut Item {
+ &mut self.entry.get_mut().value
+ }
+
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+ /// with a lifetime bound to the map itself
+ pub fn into_mut(self) -> &'a mut Item {
+ &mut self.entry.into_mut().value
+ }
+
+ /// Sets the value of the entry, and returns the entry's old value
+ pub fn insert(&mut self, mut value: Item) -> Item {
+ std::mem::swap(&mut value, &mut self.entry.get_mut().value);
+ value
+ }
+
+ /// Takes the value out of the entry, and returns it
+ pub fn remove(self) -> Item {
+ self.entry.shift_remove().value
+ }
+}
+
+/// A view into a single empty location in a `IndexMap`.
+pub struct VacantEntry<'a> {
+ pub(crate) entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>,
+ pub(crate) key: Option<Key>,
+}
+
+impl<'a> VacantEntry<'a> {
+ /// Gets a reference to the entry key
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use toml_edit::Table;
+ ///
+ /// let mut map = Table::new();
+ ///
+ /// assert_eq!("foo", map.entry("foo").key());
+ /// ```
+ pub fn key(&self) -> &str {
+ self.entry.key().as_str()
+ }
+
+ /// Sets the value of the entry with the VacantEntry's key,
+ /// and returns a mutable reference to it
+ pub fn insert(self, value: Item) -> &'a mut Item {
+ let entry = self.entry;
+ let key = self.key.unwrap_or_else(|| Key::new(entry.key().as_str()));
+ &mut entry.insert(TableKeyValue::new(key, value)).value
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/value.rs b/vendor/toml_edit-0.19.11/src/value.rs
new file mode 100644
index 000000000..f10da9a4c
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/value.rs
@@ -0,0 +1,372 @@
+use std::iter::FromIterator;
+use std::str::FromStr;
+
+use toml_datetime::*;
+
+use crate::key::Key;
+use crate::parser;
+use crate::repr::{Decor, Formatted};
+use crate::{Array, InlineTable, InternalString, RawString};
+
+/// Representation of a TOML Value (as part of a Key/Value Pair).
+#[derive(Debug, Clone)]
+pub enum Value {
+ /// A string value.
+ String(Formatted<String>),
+ /// A 64-bit integer value.
+ Integer(Formatted<i64>),
+ /// A 64-bit float value.
+ Float(Formatted<f64>),
+ /// A boolean value.
+ Boolean(Formatted<bool>),
+ /// An RFC 3339 formatted date-time with offset.
+ Datetime(Formatted<Datetime>),
+ /// An inline array of values.
+ Array(Array),
+ /// An inline table of key/value pairs.
+ InlineTable(InlineTable),
+}
+
+/// Downcasting
+impl Value {
+ /// Text description of value type
+ pub fn type_name(&self) -> &'static str {
+ match self {
+ Value::String(..) => "string",
+ Value::Integer(..) => "integer",
+ Value::Float(..) => "float",
+ Value::Boolean(..) => "boolean",
+ Value::Datetime(..) => "datetime",
+ Value::Array(..) => "array",
+ Value::InlineTable(..) => "inline table",
+ }
+ }
+
+ /// Casts `self` to str.
+ pub fn as_str(&self) -> Option<&str> {
+ match *self {
+ Value::String(ref value) => Some(value.value()),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is a string.
+ pub fn is_str(&self) -> bool {
+ self.as_str().is_some()
+ }
+
+ /// Casts `self` to integer.
+ pub fn as_integer(&self) -> Option<i64> {
+ match *self {
+ Value::Integer(ref value) => Some(*value.value()),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is an integer.
+ pub fn is_integer(&self) -> bool {
+ self.as_integer().is_some()
+ }
+
+ /// Casts `self` to float.
+ pub fn as_float(&self) -> Option<f64> {
+ match *self {
+ Value::Float(ref value) => Some(*value.value()),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is a float.
+ pub fn is_float(&self) -> bool {
+ self.as_float().is_some()
+ }
+
+ /// Casts `self` to boolean.
+ pub fn as_bool(&self) -> Option<bool> {
+ match *self {
+ Value::Boolean(ref value) => Some(*value.value()),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is a boolean.
+ pub fn is_bool(&self) -> bool {
+ self.as_bool().is_some()
+ }
+
+ /// Casts `self` to date-time.
+ pub fn as_datetime(&self) -> Option<&Datetime> {
+ match *self {
+ Value::Datetime(ref value) => Some(value.value()),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is a date-time.
+ pub fn is_datetime(&self) -> bool {
+ self.as_datetime().is_some()
+ }
+
+ /// Casts `self` to array.
+ pub fn as_array(&self) -> Option<&Array> {
+ match *self {
+ Value::Array(ref value) => Some(value),
+ _ => None,
+ }
+ }
+
+ /// Casts `self` to mutable array.
+ pub fn as_array_mut(&mut self) -> Option<&mut Array> {
+ match *self {
+ Value::Array(ref mut value) => Some(value),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is an array.
+ pub fn is_array(&self) -> bool {
+ self.as_array().is_some()
+ }
+
+ /// Casts `self` to inline table.
+ pub fn as_inline_table(&self) -> Option<&InlineTable> {
+ match *self {
+ Value::InlineTable(ref value) => Some(value),
+ _ => None,
+ }
+ }
+
+ /// Casts `self` to mutable inline table.
+ pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
+ match *self {
+ Value::InlineTable(ref mut value) => Some(value),
+ _ => None,
+ }
+ }
+
+ /// Returns true iff `self` is an inline table.
+ pub fn is_inline_table(&self) -> bool {
+ self.as_inline_table().is_some()
+ }
+}
+
+impl Value {
+ /// Get the decoration of the value.
+ /// # Example
+ /// ```rust
+ /// let v = toml_edit::Value::from(true);
+ /// assert_eq!(v.decor().suffix(), None);
+ ///```
+ pub fn decor_mut(&mut self) -> &mut Decor {
+ match self {
+ Value::String(f) => f.decor_mut(),
+ Value::Integer(f) => f.decor_mut(),
+ Value::Float(f) => f.decor_mut(),
+ Value::Boolean(f) => f.decor_mut(),
+ Value::Datetime(f) => f.decor_mut(),
+ Value::Array(a) => a.decor_mut(),
+ Value::InlineTable(t) => t.decor_mut(),
+ }
+ }
+
+ /// Get the decoration of the value.
+ /// # Example
+ /// ```rust
+ /// let v = toml_edit::Value::from(true);
+ /// assert_eq!(v.decor().suffix(), None);
+ ///```
+ pub fn decor(&self) -> &Decor {
+ match *self {
+ Value::String(ref f) => f.decor(),
+ Value::Integer(ref f) => f.decor(),
+ Value::Float(ref f) => f.decor(),
+ Value::Boolean(ref f) => f.decor(),
+ Value::Datetime(ref f) => f.decor(),
+ Value::Array(ref a) => a.decor(),
+ Value::InlineTable(ref t) => t.decor(),
+ }
+ }
+
+ /// Sets the prefix and the suffix for value.
+ /// # Example
+ /// ```rust
+ /// let mut v = toml_edit::Value::from(42);
+ /// assert_eq!(&v.to_string(), "42");
+ /// let d = v.decorated(" ", " ");
+ /// assert_eq!(&d.to_string(), " 42 ");
+ /// ```
+ pub fn decorated(mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self {
+ self.decorate(prefix, suffix);
+ self
+ }
+
+ pub(crate) fn decorate(&mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) {
+ let decor = self.decor_mut();
+ *decor = Decor::new(prefix, suffix);
+ }
+
+ /// Returns the location within the original document
+ pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
+ match self {
+ Value::String(f) => f.span(),
+ Value::Integer(f) => f.span(),
+ Value::Float(f) => f.span(),
+ Value::Boolean(f) => f.span(),
+ Value::Datetime(f) => f.span(),
+ Value::Array(a) => a.span(),
+ Value::InlineTable(t) => t.span(),
+ }
+ }
+
+ pub(crate) fn despan(&mut self, input: &str) {
+ match self {
+ Value::String(f) => f.despan(input),
+ Value::Integer(f) => f.despan(input),
+ Value::Float(f) => f.despan(input),
+ Value::Boolean(f) => f.despan(input),
+ Value::Datetime(f) => f.despan(input),
+ Value::Array(a) => a.despan(input),
+ Value::InlineTable(t) => t.despan(input),
+ }
+ }
+}
+
+impl FromStr for Value {
+ type Err = crate::TomlError;
+
+ /// Parses a value from a &str
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ parser::parse_value(s)
+ }
+}
+
+impl<'b> From<&'b Value> for Value {
+ fn from(s: &'b Value) -> Self {
+ s.clone()
+ }
+}
+
+impl<'b> From<&'b str> for Value {
+ fn from(s: &'b str) -> Self {
+ s.to_owned().into()
+ }
+}
+
+impl<'b> From<&'b String> for Value {
+ fn from(s: &'b String) -> Self {
+ s.to_owned().into()
+ }
+}
+
+impl From<String> for Value {
+ fn from(s: String) -> Self {
+ Value::String(Formatted::new(s))
+ }
+}
+
+impl<'b> From<&'b InternalString> for Value {
+ fn from(s: &'b InternalString) -> Self {
+ s.as_str().into()
+ }
+}
+
+impl From<InternalString> for Value {
+ fn from(s: InternalString) -> Self {
+ s.as_str().into()
+ }
+}
+
+impl From<i64> for Value {
+ fn from(i: i64) -> Self {
+ Value::Integer(Formatted::new(i))
+ }
+}
+
+impl From<f64> for Value {
+ fn from(f: f64) -> Self {
+ Value::Float(Formatted::new(f))
+ }
+}
+
+impl From<bool> for Value {
+ fn from(b: bool) -> Self {
+ Value::Boolean(Formatted::new(b))
+ }
+}
+
+impl From<Datetime> for Value {
+ fn from(d: Datetime) -> Self {
+ Value::Datetime(Formatted::new(d))
+ }
+}
+
+impl From<Date> for Value {
+ fn from(d: Date) -> Self {
+ let d: Datetime = d.into();
+ d.into()
+ }
+}
+
+impl From<Time> for Value {
+ fn from(d: Time) -> Self {
+ let d: Datetime = d.into();
+ d.into()
+ }
+}
+
+impl From<Array> for Value {
+ fn from(array: Array) -> Self {
+ Value::Array(array)
+ }
+}
+
+impl From<InlineTable> for Value {
+ fn from(table: InlineTable) -> Self {
+ Value::InlineTable(table)
+ }
+}
+
+impl<V: Into<Value>> FromIterator<V> for Value {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = V>,
+ {
+ let array: Array = iter.into_iter().collect();
+ Value::Array(array)
+ }
+}
+
+impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Value {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = (K, V)>,
+ {
+ let table: InlineTable = iter.into_iter().collect();
+ Value::InlineTable(table)
+ }
+}
+
+impl std::fmt::Display for Value {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ crate::encode::Encode::encode(self, f, None, ("", ""))
+ }
+}
+
+// `key1 = value1`
+pub(crate) const DEFAULT_VALUE_DECOR: (&str, &str) = (" ", "");
+// `{ key = value }`
+pub(crate) const DEFAULT_TRAILING_VALUE_DECOR: (&str, &str) = (" ", " ");
+// `[value1, value2]`
+pub(crate) const DEFAULT_LEADING_VALUE_DECOR: (&str, &str) = ("", "");
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn from_iter_formatting() {
+ let features = vec!["node".to_owned(), "mouth".to_owned()];
+ let features: Value = features.iter().cloned().collect();
+ assert_eq!(features.to_string(), r#"["node", "mouth"]"#);
+ }
+}
diff --git a/vendor/toml_edit-0.19.11/src/visit.rs b/vendor/toml_edit-0.19.11/src/visit.rs
new file mode 100644
index 000000000..1bc640a88
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/visit.rs
@@ -0,0 +1,236 @@
+#![allow(missing_docs)]
+
+//! Document tree traversal to walk a shared borrow of a document tree.
+//!
+//! Each method of the [`Visit`] trait is a hook that can be overridden
+//! to customize the behavior when mutating the corresponding type of node.
+//! By default, every method recursively visits the substructure of the
+//! input by invoking the right visitor method of each of its fields.
+//!
+//! ```
+//! # use toml_edit::{Item, ArrayOfTables, Table, Value};
+//!
+//! pub trait Visit<'doc> {
+//! /* ... */
+//!
+//! fn visit_item(&mut self, i: &'doc Item) {
+//! visit_item(self, i);
+//! }
+//!
+//! /* ... */
+//! # fn visit_value(&mut self, i: &'doc Value);
+//! # fn visit_table(&mut self, i: &'doc Table);
+//! # fn visit_array_of_tables(&mut self, i: &'doc ArrayOfTables);
+//! }
+//!
+//! pub fn visit_item<'doc, V>(v: &mut V, node: &'doc Item)
+//! where
+//! V: Visit<'doc> + ?Sized,
+//! {
+//! match node {
+//! Item::None => {}
+//! Item::Value(value) => v.visit_value(value),
+//! Item::Table(table) => v.visit_table(table),
+//! Item::ArrayOfTables(array) => v.visit_array_of_tables(array),
+//! }
+//! }
+//! ```
+//!
+//! The API is modeled after [`syn::visit`](https://docs.rs/syn/1/syn/visit).
+//!
+//! # Examples
+//!
+//! This visitor stores every string in the document.
+//!
+//! ```
+//! # use toml_edit::*;
+//! use toml_edit::visit::*;
+//!
+//! #[derive(Default)]
+//! struct StringCollector<'doc> {
+//! strings: Vec<&'doc str>,
+//! }
+//!
+//! impl<'doc> Visit<'doc> for StringCollector<'doc> {
+//! fn visit_string(&mut self, node: &'doc Formatted<String>) {
+//! self.strings.push(node.value().as_str());
+//! }
+//! }
+//!
+//! let input = r#"
+//! laputa = "sky-castle"
+//! the-force = { value = "surrounds-you" }
+//! "#;
+//!
+//! let mut document: Document = input.parse().unwrap();
+//! let mut visitor = StringCollector::default();
+//! visitor.visit_document(&document);
+//!
+//! assert_eq!(visitor.strings, vec!["sky-castle", "surrounds-you"]);
+//! ```
+//!
+//! For a more complex example where the visitor has internal state, see `examples/visit.rs`
+//! [on GitHub](https://github.com/ordian/toml_edit/blob/master/examples/visit.rs).
+
+use crate::{
+ Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, Table, TableLike, Value,
+};
+
+/// Document tree traversal to mutate an exclusive borrow of a document tree in-place.
+///
+/// See the [module documentation](self) for details.
+pub trait Visit<'doc> {
+ fn visit_document(&mut self, node: &'doc Document) {
+ visit_document(self, node);
+ }
+
+ fn visit_item(&mut self, node: &'doc Item) {
+ visit_item(self, node);
+ }
+
+ fn visit_table(&mut self, node: &'doc Table) {
+ visit_table(self, node);
+ }
+
+ fn visit_inline_table(&mut self, node: &'doc InlineTable) {
+ visit_inline_table(self, node)
+ }
+
+ fn visit_table_like(&mut self, node: &'doc dyn TableLike) {
+ visit_table_like(self, node);
+ }
+
+ fn visit_table_like_kv(&mut self, key: &'doc str, node: &'doc Item) {
+ visit_table_like_kv(self, key, node);
+ }
+
+ fn visit_array(&mut self, node: &'doc Array) {
+ visit_array(self, node);
+ }
+
+ fn visit_array_of_tables(&mut self, node: &'doc ArrayOfTables) {
+ visit_array_of_tables(self, node);
+ }
+
+ fn visit_value(&mut self, node: &'doc Value) {
+ visit_value(self, node);
+ }
+
+ fn visit_boolean(&mut self, node: &'doc Formatted<bool>) {
+ visit_boolean(self, node)
+ }
+
+ fn visit_datetime(&mut self, node: &'doc Formatted<Datetime>) {
+ visit_datetime(self, node);
+ }
+
+ fn visit_float(&mut self, node: &'doc Formatted<f64>) {
+ visit_float(self, node)
+ }
+
+ fn visit_integer(&mut self, node: &'doc Formatted<i64>) {
+ visit_integer(self, node)
+ }
+
+ fn visit_string(&mut self, node: &'doc Formatted<String>) {
+ visit_string(self, node)
+ }
+}
+
+pub fn visit_document<'doc, V>(v: &mut V, node: &'doc Document)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ v.visit_table(node.as_table());
+}
+
+pub fn visit_item<'doc, V>(v: &mut V, node: &'doc Item)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ match node {
+ Item::None => {}
+ Item::Value(value) => v.visit_value(value),
+ Item::Table(table) => v.visit_table(table),
+ Item::ArrayOfTables(array) => v.visit_array_of_tables(array),
+ }
+}
+
+pub fn visit_table<'doc, V>(v: &mut V, node: &'doc Table)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ v.visit_table_like(node)
+}
+
+pub fn visit_inline_table<'doc, V>(v: &mut V, node: &'doc InlineTable)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ v.visit_table_like(node)
+}
+
+pub fn visit_table_like<'doc, V>(v: &mut V, node: &'doc dyn TableLike)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ for (key, item) in node.iter() {
+ v.visit_table_like_kv(key, item)
+ }
+}
+
+pub fn visit_table_like_kv<'doc, V>(v: &mut V, _key: &'doc str, node: &'doc Item)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ v.visit_item(node)
+}
+
+pub fn visit_array<'doc, V>(v: &mut V, node: &'doc Array)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ for value in node.iter() {
+ v.visit_value(value);
+ }
+}
+
+pub fn visit_array_of_tables<'doc, V>(v: &mut V, node: &'doc ArrayOfTables)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ for table in node.iter() {
+ v.visit_table(table);
+ }
+}
+
+pub fn visit_value<'doc, V>(v: &mut V, node: &'doc Value)
+where
+ V: Visit<'doc> + ?Sized,
+{
+ match node {
+ Value::String(s) => v.visit_string(s),
+ Value::Integer(i) => v.visit_integer(i),
+ Value::Float(f) => v.visit_float(f),
+ Value::Boolean(b) => v.visit_boolean(b),
+ Value::Datetime(dt) => v.visit_datetime(dt),
+ Value::Array(array) => v.visit_array(array),
+ Value::InlineTable(table) => v.visit_inline_table(table),
+ }
+}
+
+macro_rules! empty_visit {
+ ($name: ident, $t: ty) => {
+ fn $name<'doc, V>(_v: &mut V, _node: &'doc $t)
+ where
+ V: Visit<'doc> + ?Sized,
+ {
+ }
+ };
+}
+
+empty_visit!(visit_boolean, Formatted<bool>);
+empty_visit!(visit_datetime, Formatted<Datetime>);
+empty_visit!(visit_float, Formatted<f64>);
+empty_visit!(visit_integer, Formatted<i64>);
+empty_visit!(visit_string, Formatted<String>);
diff --git a/vendor/toml_edit-0.19.11/src/visit_mut.rs b/vendor/toml_edit-0.19.11/src/visit_mut.rs
new file mode 100644
index 000000000..2c2af9752
--- /dev/null
+++ b/vendor/toml_edit-0.19.11/src/visit_mut.rs
@@ -0,0 +1,252 @@
+#![allow(missing_docs)]
+
+//! Document tree traversal to mutate an exclusive borrow of a document tree in place.
+//!
+//!
+//! Each method of the [`VisitMut`] trait is a hook that can be overridden
+//! to customize the behavior when mutating the corresponding type of node.
+//! By default, every method recursively visits the substructure of the
+//! input by invoking the right visitor method of each of its fields.
+//!
+//! ```
+//! # use toml_edit::{Item, ArrayOfTables, Table, Value};
+//!
+//! pub trait VisitMut {
+//! /* ... */
+//!
+//! fn visit_item_mut(&mut self, i: &mut Item) {
+//! visit_item_mut(self, i);
+//! }
+//!
+//! /* ... */
+//! # fn visit_value_mut(&mut self, i: &mut Value);
+//! # fn visit_table_mut(&mut self, i: &mut Table);
+//! # fn visit_array_of_tables_mut(&mut self, i: &mut ArrayOfTables);
+//! }
+//!
+//! pub fn visit_item_mut<V>(v: &mut V, node: &mut Item)
+//! where
+//! V: VisitMut + ?Sized,
+//! {
+//! match node {
+//! Item::None => {}
+//! Item::Value(value) => v.visit_value_mut(value),
+//! Item::Table(table) => v.visit_table_mut(table),
+//! Item::ArrayOfTables(array) => v.visit_array_of_tables_mut(array),
+//! }
+//! }
+//! ```
+//!
+//! The API is modeled after [`syn::visit_mut`](https://docs.rs/syn/1/syn/visit_mut).
+//!
+//! # Examples
+//!
+//! This visitor replaces every floating point value with its decimal string representation, to
+//! 2 decimal points.
+//!
+//! ```
+//! # use toml_edit::*;
+//! use toml_edit::visit_mut::*;
+//!
+//! struct FloatToString;
+//!
+//! impl VisitMut for FloatToString {
+//! fn visit_value_mut(&mut self, node: &mut Value) {
+//! if let Value::Float(f) = node {
+//! // Convert the float to a string.
+//! let mut s = Formatted::new(format!("{:.2}", f.value()));
+//! // Copy over the formatting.
+//! std::mem::swap(s.decor_mut(), f.decor_mut());
+//! *node = Value::String(s);
+//! }
+//! // Most of the time, you will also need to call the default implementation to recurse
+//! // further down the document tree.
+//! visit_value_mut(self, node);
+//! }
+//! }
+//!
+//! let input = r#"
+//! banana = 3.26
+//! table = { apple = 4.5 }
+//! "#;
+//!
+//! let mut document: Document = input.parse().unwrap();
+//! let mut visitor = FloatToString;
+//! visitor.visit_document_mut(&mut document);
+//!
+//! let output = r#"
+//! banana = "3.26"
+//! table = { apple = "4.50" }
+//! "#;
+//!
+//! assert_eq!(format!("{}", document), output);
+//! ```
+//!
+//! For a more complex example where the visitor has internal state, see `examples/visit.rs`
+//! [on GitHub](https://github.com/ordian/toml_edit/blob/master/examples/visit.rs).
+
+use crate::{
+ Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, KeyMut, Table,
+ TableLike, Value,
+};
+
+/// Document tree traversal to mutate an exclusive borrow of a document tree in-place.
+///
+/// See the [module documentation](self) for details.
+pub trait VisitMut {
+ fn visit_document_mut(&mut self, node: &mut Document) {
+ visit_document_mut(self, node);
+ }
+
+ fn visit_item_mut(&mut self, node: &mut Item) {
+ visit_item_mut(self, node);
+ }
+
+ fn visit_table_mut(&mut self, node: &mut Table) {
+ visit_table_mut(self, node);
+ }
+
+ fn visit_inline_table_mut(&mut self, node: &mut InlineTable) {
+ visit_inline_table_mut(self, node)
+ }
+
+ /// [`visit_table_mut`](Self::visit_table_mut) and
+ /// [`visit_inline_table_mut`](Self::visit_inline_table_mut) both recurse into this method.
+ fn visit_table_like_mut(&mut self, node: &mut dyn TableLike) {
+ visit_table_like_mut(self, node);
+ }
+
+ fn visit_table_like_kv_mut(&mut self, key: KeyMut<'_>, node: &mut Item) {
+ visit_table_like_kv_mut(self, key, node);
+ }
+
+ fn visit_array_mut(&mut self, node: &mut Array) {
+ visit_array_mut(self, node);
+ }
+
+ fn visit_array_of_tables_mut(&mut self, node: &mut ArrayOfTables) {
+ visit_array_of_tables_mut(self, node);
+ }
+
+ fn visit_value_mut(&mut self, node: &mut Value) {
+ visit_value_mut(self, node);
+ }
+
+ fn visit_boolean_mut(&mut self, node: &mut Formatted<bool>) {
+ visit_boolean_mut(self, node)
+ }
+
+ fn visit_datetime_mut(&mut self, node: &mut Formatted<Datetime>) {
+ visit_datetime_mut(self, node);
+ }
+
+ fn visit_float_mut(&mut self, node: &mut Formatted<f64>) {
+ visit_float_mut(self, node)
+ }
+
+ fn visit_integer_mut(&mut self, node: &mut Formatted<i64>) {
+ visit_integer_mut(self, node)
+ }
+
+ fn visit_string_mut(&mut self, node: &mut Formatted<String>) {
+ visit_string_mut(self, node)
+ }
+}
+
+pub fn visit_document_mut<V>(v: &mut V, node: &mut Document)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_table_mut(node.as_table_mut());
+}
+
+pub fn visit_item_mut<V>(v: &mut V, node: &mut Item)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ Item::None => {}
+ Item::Value(value) => v.visit_value_mut(value),
+ Item::Table(table) => v.visit_table_mut(table),
+ Item::ArrayOfTables(array) => v.visit_array_of_tables_mut(array),
+ }
+}
+
+pub fn visit_table_mut<V>(v: &mut V, node: &mut Table)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_table_like_mut(node);
+}
+
+pub fn visit_inline_table_mut<V>(v: &mut V, node: &mut InlineTable)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_table_like_mut(node);
+}
+
+pub fn visit_table_like_mut<V>(v: &mut V, node: &mut dyn TableLike)
+where
+ V: VisitMut + ?Sized,
+{
+ for (key, item) in node.iter_mut() {
+ v.visit_table_like_kv_mut(key, item);
+ }
+}
+
+pub fn visit_table_like_kv_mut<V>(v: &mut V, _key: KeyMut<'_>, node: &mut Item)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_item_mut(node)
+}
+
+pub fn visit_array_mut<V>(v: &mut V, node: &mut Array)
+where
+ V: VisitMut + ?Sized,
+{
+ for value in node.iter_mut() {
+ v.visit_value_mut(value);
+ }
+}
+
+pub fn visit_array_of_tables_mut<V>(v: &mut V, node: &mut ArrayOfTables)
+where
+ V: VisitMut + ?Sized,
+{
+ for table in node.iter_mut() {
+ v.visit_table_mut(table);
+ }
+}
+
+pub fn visit_value_mut<V>(v: &mut V, node: &mut Value)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ Value::String(s) => v.visit_string_mut(s),
+ Value::Integer(i) => v.visit_integer_mut(i),
+ Value::Float(f) => v.visit_float_mut(f),
+ Value::Boolean(b) => v.visit_boolean_mut(b),
+ Value::Datetime(dt) => v.visit_datetime_mut(dt),
+ Value::Array(array) => v.visit_array_mut(array),
+ Value::InlineTable(table) => v.visit_inline_table_mut(table),
+ }
+}
+
+macro_rules! empty_visit_mut {
+ ($name: ident, $t: ty) => {
+ fn $name<V>(_v: &mut V, _node: &mut $t)
+ where
+ V: VisitMut + ?Sized,
+ {
+ }
+ };
+}
+
+empty_visit_mut!(visit_boolean_mut, Formatted<bool>);
+empty_visit_mut!(visit_datetime_mut, Formatted<Datetime>);
+empty_visit_mut!(visit_float_mut, Formatted<f64>);
+empty_visit_mut!(visit_integer_mut, Formatted<i64>);
+empty_visit_mut!(visit_string_mut, Formatted<String>);