1use std::str::FromStr;
2
3use crate::table::Iter;
4use crate::{Item, RawString, Table};
5
6#[derive(Debug, Clone)]
8pub struct ImDocument<S> {
9 pub(crate) root: Item,
10 pub(crate) trailing: RawString,
12 pub(crate) raw: S,
13}
14
15impl ImDocument<&'static str> {
16 pub fn new() -> Self {
18 Default::default()
19 }
20}
21
22#[cfg(feature = "parse")]
23impl<S: AsRef<str>> ImDocument<S> {
24 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 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 pub fn as_item(&self) -> &Item {
43 &self.root
44 }
45
46 pub fn into_item(self) -> Item {
48 self.root
49 }
50
51 pub fn as_table(&self) -> &Table {
53 self.root.as_table().expect("root should always be a table")
54 }
55
56 pub fn into_table(self) -> Table {
58 self.root
59 .into_table()
60 .expect("root should always be a table")
61 }
62
63 pub fn iter(&self) -> Iter<'_> {
65 self.as_table().iter()
66 }
67
68 pub fn trailing(&self) -> &RawString {
70 &self.trailing
71 }
72}
73
74impl<S: AsRef<str>> ImDocument<S> {
75 pub fn raw(&self) -> &str {
77 self.raw.as_ref()
78 }
79}
80
81impl<S: AsRef<str>> ImDocument<S> {
82 pub fn into_mut(mut self) -> DocumentMut {
84 self.despan();
85 DocumentMut {
86 root: self.root,
87 trailing: self.trailing,
88 }
89 }
90}
91
92impl Default for ImDocument<&'static str> {
93 fn default() -> Self {
94 Self {
95 root: Item::Table(Table::with_pos(Some(0))),
96 trailing: Default::default(),
97 raw: "",
98 }
99 }
100}
101
102#[cfg(feature = "parse")]
103impl FromStr for ImDocument<String> {
104 type Err = crate::TomlError;
105
106 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 Self::parse(s.to_owned())
109 }
110}
111
112impl<S> std::ops::Deref for ImDocument<S> {
113 type Target = Table;
114
115 fn deref(&self) -> &Self::Target {
116 self.as_table()
117 }
118}
119
120#[derive(Debug, Clone)]
122pub struct DocumentMut {
123 pub(crate) root: Item,
124 pub(crate) trailing: RawString,
126}
127
128impl DocumentMut {
129 pub fn new() -> Self {
131 Default::default()
132 }
133
134 pub fn as_item(&self) -> &Item {
136 &self.root
137 }
138
139 pub fn as_item_mut(&mut self) -> &mut Item {
141 &mut self.root
142 }
143
144 pub fn into_item(self) -> Item {
146 self.root
147 }
148
149 pub fn as_table(&self) -> &Table {
151 self.root.as_table().expect("root should always be a table")
152 }
153
154 pub fn as_table_mut(&mut self) -> &mut Table {
156 self.root
157 .as_table_mut()
158 .expect("root should always be a table")
159 }
160
161 pub fn into_table(self) -> Table {
163 self.root
164 .into_table()
165 .expect("root should always be a table")
166 }
167
168 pub fn iter(&self) -> Iter<'_> {
170 self.as_table().iter()
171 }
172
173 pub fn set_trailing(&mut self, trailing: impl Into<RawString>) {
175 self.trailing = trailing.into();
176 }
177
178 pub fn trailing(&self) -> &RawString {
180 &self.trailing
181 }
182}
183
184impl Default for DocumentMut {
185 fn default() -> Self {
186 Self {
187 root: Item::Table(Table::with_pos(Some(0))),
188 trailing: Default::default(),
189 }
190 }
191}
192
193#[cfg(feature = "parse")]
194impl FromStr for DocumentMut {
195 type Err = crate::TomlError;
196
197 fn from_str(s: &str) -> Result<Self, Self::Err> {
199 let im = ImDocument::from_str(s)?;
200 Ok(im.into_mut())
201 }
202}
203
204impl std::ops::Deref for DocumentMut {
205 type Target = Table;
206
207 fn deref(&self) -> &Self::Target {
208 self.as_table()
209 }
210}
211
212impl std::ops::DerefMut for DocumentMut {
213 fn deref_mut(&mut self) -> &mut Self::Target {
214 self.as_table_mut()
215 }
216}
217
218impl From<Table> for DocumentMut {
219 fn from(root: Table) -> Self {
220 Self {
221 root: Item::Table(root),
222 ..Default::default()
223 }
224 }
225}
226
227#[test]
228#[cfg(feature = "parse")]
229#[cfg(feature = "display")]
230fn default_roundtrip() {
231 DocumentMut::default()
232 .to_string()
233 .parse::<DocumentMut>()
234 .unwrap();
235}