toml_edit/
document.rs

1use std::str::FromStr;
2
3use crate::table::Iter;
4use crate::{Item, RawString, Table};
5
6/// Type representing a parsed TOML document
7#[derive(Debug, Clone)]
8pub struct ImDocument<S> {
9    pub(crate) root: Item,
10    // Trailing comments and whitespaces
11    pub(crate) trailing: RawString,
12    pub(crate) raw: S,
13}
14
15impl ImDocument<&'static str> {
16    /// Creates an empty document
17    pub fn new() -> Self {
18        Default::default()
19    }
20}
21
22#[cfg(feature = "parse")]
23impl<S: AsRef<str>> ImDocument<S> {
24    /// Parse a TOML document
25    pub fn parse(raw: S) -> Result<Self, crate::TomlError> {
26        crate::parser::parse_document(raw)
27    }
28}
29
30impl<S: AsRef<str>> ImDocument<S> {
31    /// # Panics
32    ///
33    /// If run on on a [`DocumentMut`] not generated by the parser
34    pub(crate) fn despan(&mut self) {
35        self.root.despan(self.raw.as_ref());
36        self.trailing.despan(self.raw.as_ref());
37    }
38}
39
40impl<S> ImDocument<S> {
41    /// Returns a reference to the root item.
42    pub fn as_item(&self) -> &Item {
43        &self.root
44    }
45
46    /// Returns a reference to the root table.
47    pub fn as_table(&self) -> &Table {
48        self.root.as_table().expect("root should always be a table")
49    }
50
51    /// Returns an iterator over the root table.
52    pub fn iter(&self) -> Iter<'_> {
53        self.as_table().iter()
54    }
55
56    /// Whitespace after last element
57    pub fn trailing(&self) -> &RawString {
58        &self.trailing
59    }
60}
61
62impl<S: AsRef<str>> ImDocument<S> {
63    /// Access the raw, unparsed document
64    pub fn raw(&self) -> &str {
65        self.raw.as_ref()
66    }
67}
68
69impl<S: AsRef<str>> ImDocument<S> {
70    /// Allow editing of the [`DocumentMut`]
71    pub fn into_mut(mut self) -> DocumentMut {
72        self.despan();
73        DocumentMut {
74            root: self.root,
75            trailing: self.trailing,
76        }
77    }
78}
79
80impl Default for ImDocument<&'static str> {
81    fn default() -> Self {
82        Self {
83            root: Item::Table(Table::with_pos(Some(0))),
84            trailing: Default::default(),
85            raw: "",
86        }
87    }
88}
89
90#[cfg(feature = "parse")]
91impl FromStr for ImDocument<String> {
92    type Err = crate::TomlError;
93
94    /// Parses a document from a &str
95    fn from_str(s: &str) -> Result<Self, Self::Err> {
96        Self::parse(s.to_owned())
97    }
98}
99
100impl<S> std::ops::Deref for ImDocument<S> {
101    type Target = Table;
102
103    fn deref(&self) -> &Self::Target {
104        self.as_table()
105    }
106}
107
108/// Type representing a TOML document
109#[derive(Debug, Clone)]
110pub struct DocumentMut {
111    pub(crate) root: Item,
112    // Trailing comments and whitespaces
113    pub(crate) trailing: RawString,
114}
115
116impl DocumentMut {
117    /// Creates an empty document
118    pub fn new() -> Self {
119        Default::default()
120    }
121
122    /// Returns a reference to the root item.
123    pub fn as_item(&self) -> &Item {
124        &self.root
125    }
126
127    /// Returns a mutable reference to the root item.
128    pub fn as_item_mut(&mut self) -> &mut Item {
129        &mut self.root
130    }
131
132    /// Returns a reference to the root table.
133    pub fn as_table(&self) -> &Table {
134        self.root.as_table().expect("root should always be a table")
135    }
136
137    /// Returns a mutable reference to the root table.
138    pub fn as_table_mut(&mut self) -> &mut Table {
139        self.root
140            .as_table_mut()
141            .expect("root should always be a table")
142    }
143
144    /// Returns an iterator over the root table.
145    pub fn iter(&self) -> Iter<'_> {
146        self.as_table().iter()
147    }
148
149    /// Set whitespace after last element
150    pub fn set_trailing(&mut self, trailing: impl Into<RawString>) {
151        self.trailing = trailing.into();
152    }
153
154    /// Whitespace after last element
155    pub fn trailing(&self) -> &RawString {
156        &self.trailing
157    }
158}
159
160impl Default for DocumentMut {
161    fn default() -> Self {
162        Self {
163            root: Item::Table(Table::with_pos(Some(0))),
164            trailing: Default::default(),
165        }
166    }
167}
168
169#[cfg(feature = "parse")]
170impl FromStr for DocumentMut {
171    type Err = crate::TomlError;
172
173    /// Parses a document from a &str
174    fn from_str(s: &str) -> Result<Self, Self::Err> {
175        let im = ImDocument::from_str(s)?;
176        Ok(im.into_mut())
177    }
178}
179
180impl std::ops::Deref for DocumentMut {
181    type Target = Table;
182
183    fn deref(&self) -> &Self::Target {
184        self.as_table()
185    }
186}
187
188impl std::ops::DerefMut for DocumentMut {
189    fn deref_mut(&mut self) -> &mut Self::Target {
190        self.as_table_mut()
191    }
192}
193
194impl From<Table> for DocumentMut {
195    fn from(root: Table) -> Self {
196        Self {
197            root: Item::Table(root),
198            ..Default::default()
199        }
200    }
201}
202
203#[test]
204#[cfg(feature = "parse")]
205#[cfg(feature = "display")]
206fn default_roundtrip() {
207    DocumentMut::default()
208        .to_string()
209        .parse::<DocumentMut>()
210        .unwrap();
211}