| use std::str::FromStr; |
| |
| use crate::table::Iter; |
| use crate::{Item, RawString, Table}; |
| |
| /// The root TOML [`Table`], containing [`Key`][crate::Key]/[`Value`][crate::Value] pairs and all other logic [`Table`]s |
| #[derive(Debug, Clone)] |
| pub struct Document<S> { |
| pub(crate) root: Item, |
| // Trailing comments and whitespaces |
| pub(crate) trailing: RawString, |
| pub(crate) raw: S, |
| } |
| |
| impl Document<&'static str> { |
| /// Creates an empty document |
| pub fn new() -> Self { |
| Default::default() |
| } |
| } |
| |
| #[cfg(feature = "parse")] |
| impl<S: AsRef<str>> Document<S> { |
| /// Parse a TOML document |
| pub fn parse(raw: S) -> Result<Self, crate::TomlError> { |
| let source = toml_parser::Source::new(raw.as_ref()); |
| let mut sink = crate::error::TomlSink::<Option<_>>::new(source); |
| let doc = crate::parser::parse_document(source, &mut sink); |
| if let Some(err) = sink.into_inner() { |
| Err(err) |
| } else { |
| Ok(Self { |
| root: doc.root, |
| trailing: doc.trailing, |
| raw, |
| }) |
| } |
| } |
| } |
| |
| impl<S: AsRef<str>> Document<S> { |
| /// # Panics |
| /// |
| /// If run on a [`DocumentMut`] not generated by the parser |
| pub(crate) fn despan(&mut self) { |
| self.root.despan(self.raw.as_ref()); |
| self.trailing.despan(self.raw.as_ref()); |
| } |
| } |
| |
| impl<S> Document<S> { |
| /// Returns a reference to the root item. |
| pub fn as_item(&self) -> &Item { |
| &self.root |
| } |
| |
| /// Returns the root item. |
| pub fn into_item(self) -> Item { |
| 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 the root table. |
| pub fn into_table(self) -> Table { |
| self.root |
| .into_table() |
| .expect("root should always be a table") |
| } |
| |
| /// Returns an iterator over the root table. |
| pub fn iter(&self) -> Iter<'_> { |
| self.as_table().iter() |
| } |
| |
| /// Whitespace after last element |
| pub fn trailing(&self) -> &RawString { |
| &self.trailing |
| } |
| } |
| |
| impl<S: AsRef<str>> Document<S> { |
| /// Access the raw, unparsed document |
| pub fn raw(&self) -> &str { |
| self.raw.as_ref() |
| } |
| } |
| |
| impl<S: AsRef<str>> Document<S> { |
| /// Allow editing of the [`DocumentMut`] |
| pub fn into_mut(mut self) -> DocumentMut { |
| self.despan(); |
| DocumentMut { |
| root: self.root, |
| trailing: self.trailing, |
| } |
| } |
| } |
| |
| impl Default for Document<&'static str> { |
| fn default() -> Self { |
| Self { |
| root: Item::Table(Table::with_pos(Some(0))), |
| trailing: Default::default(), |
| raw: "", |
| } |
| } |
| } |
| |
| #[cfg(feature = "parse")] |
| impl FromStr for Document<String> { |
| type Err = crate::TomlError; |
| |
| /// Parses a document from a &str |
| fn from_str(s: &str) -> Result<Self, Self::Err> { |
| Self::parse(s.to_owned()) |
| } |
| } |
| |
| impl<S> std::ops::Deref for Document<S> { |
| type Target = Table; |
| |
| fn deref(&self) -> &Self::Target { |
| self.as_table() |
| } |
| } |
| |
| /// The editable root TOML [`Table`], containing [`Key`][crate::Key]/[`Value`][crate::Value] pairs and all other logic [`Table`]s |
| #[derive(Debug, Clone)] |
| pub struct DocumentMut { |
| pub(crate) root: Item, |
| // Trailing comments and whitespaces |
| pub(crate) trailing: RawString, |
| } |
| |
| impl DocumentMut { |
| /// 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 the root item. |
| pub fn into_item(self) -> Item { |
| 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 the root table. |
| pub fn into_table(self) -> Table { |
| self.root |
| .into_table() |
| .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 |
| } |
| } |
| |
| impl Default for DocumentMut { |
| fn default() -> Self { |
| Self { |
| root: Item::Table(Table::with_pos(Some(0))), |
| trailing: Default::default(), |
| } |
| } |
| } |
| |
| #[cfg(feature = "parse")] |
| impl FromStr for DocumentMut { |
| type Err = crate::TomlError; |
| |
| /// Parses a document from a &str |
| fn from_str(s: &str) -> Result<Self, Self::Err> { |
| let im = Document::from_str(s)?; |
| Ok(im.into_mut()) |
| } |
| } |
| |
| impl std::ops::Deref for DocumentMut { |
| type Target = Table; |
| |
| fn deref(&self) -> &Self::Target { |
| self.as_table() |
| } |
| } |
| |
| impl std::ops::DerefMut for DocumentMut { |
| fn deref_mut(&mut self) -> &mut Self::Target { |
| self.as_table_mut() |
| } |
| } |
| |
| impl From<Table> for DocumentMut { |
| fn from(root: Table) -> Self { |
| Self { |
| root: Item::Table(root), |
| ..Default::default() |
| } |
| } |
| } |
| |
| #[test] |
| #[cfg(feature = "parse")] |
| #[cfg(feature = "display")] |
| fn default_roundtrip() { |
| DocumentMut::default() |
| .to_string() |
| .parse::<DocumentMut>() |
| .unwrap(); |
| } |