toml_edit/
item.rs
1use std::str::FromStr;
2
3use toml_datetime::Datetime;
4
5use crate::array_of_tables::ArrayOfTables;
6use crate::table::TableLike;
7use crate::{Array, InlineTable, Table, Value};
8
9#[derive(Debug, Default)]
11pub enum Item {
12 #[default]
14 None,
15 Value(Value),
17 Table(Table),
19 ArrayOfTables(ArrayOfTables),
21}
22
23impl Item {
24 pub fn or_insert(&mut self, item: Item) -> &mut Item {
27 if self.is_none() {
28 *self = item;
29 }
30 self
31 }
32}
33
34impl Item {
37 pub fn type_name(&self) -> &'static str {
39 match self {
40 Item::None => "none",
41 Item::Value(v) => v.type_name(),
42 Item::Table(..) => "table",
43 Item::ArrayOfTables(..) => "array of tables",
44 }
45 }
46
47 pub fn get<I: crate::index::Index>(&self, index: I) -> Option<&Item> {
58 index.index(self)
59 }
60
61 pub fn get_mut<I: crate::index::Index>(&mut self, index: I) -> Option<&mut Item> {
72 index.index_mut(self)
73 }
74
75 pub fn as_value(&self) -> Option<&Value> {
77 match *self {
78 Item::Value(ref v) => Some(v),
79 _ => None,
80 }
81 }
82 pub fn as_table(&self) -> Option<&Table> {
90 match *self {
91 Item::Table(ref t) => Some(t),
92 _ => None,
93 }
94 }
95 pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> {
97 match *self {
98 Item::ArrayOfTables(ref a) => Some(a),
99 _ => None,
100 }
101 }
102 pub fn as_value_mut(&mut self) -> Option<&mut Value> {
104 match *self {
105 Item::Value(ref mut v) => Some(v),
106 _ => None,
107 }
108 }
109 pub fn as_table_mut(&mut self) -> Option<&mut Table> {
117 match *self {
118 Item::Table(ref mut t) => Some(t),
119 _ => None,
120 }
121 }
122 pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> {
124 match *self {
125 Item::ArrayOfTables(ref mut a) => Some(a),
126 _ => None,
127 }
128 }
129 pub fn into_value(self) -> Result<Value, Self> {
131 match self {
132 Item::None => Err(self),
133 Item::Value(v) => Ok(v),
134 Item::Table(v) => {
135 let v = v.into_inline_table();
136 Ok(Value::InlineTable(v))
137 }
138 Item::ArrayOfTables(v) => {
139 let v = v.into_array();
140 Ok(Value::Array(v))
141 }
142 }
143 }
144 pub fn make_value(&mut self) {
146 let other = std::mem::take(self);
147 let other = other.into_value().map(Item::Value).unwrap_or(Item::None);
148 *self = other;
149 }
150 pub fn into_table(self) -> Result<Table, Self> {
158 match self {
159 Item::Table(t) => Ok(t),
160 Item::Value(Value::InlineTable(t)) => Ok(t.into_table()),
161 _ => Err(self),
162 }
163 }
164 pub fn into_array_of_tables(self) -> Result<ArrayOfTables, Self> {
166 match self {
167 Item::ArrayOfTables(a) => Ok(a),
168 Item::Value(Value::Array(a)) => {
169 if a.is_empty() {
170 Err(Item::Value(Value::Array(a)))
171 } else if a.iter().all(|v| v.is_inline_table()) {
172 let mut aot = ArrayOfTables::new();
173 aot.values = a.values;
174 for value in aot.values.iter_mut() {
175 value.make_item();
176 }
177 Ok(aot)
178 } else {
179 Err(Item::Value(Value::Array(a)))
180 }
181 }
182 _ => Err(self),
183 }
184 }
185 pub(crate) fn make_item(&mut self) {
187 let other = std::mem::take(self);
188 let other = match other.into_table().map(Item::Table) {
189 Ok(i) => i,
190 Err(i) => i,
191 };
192 let other = match other.into_array_of_tables().map(Item::ArrayOfTables) {
193 Ok(i) => i,
194 Err(i) => i,
195 };
196 *self = other;
197 }
198 pub fn is_value(&self) -> bool {
200 self.as_value().is_some()
201 }
202 pub fn is_table(&self) -> bool {
210 self.as_table().is_some()
211 }
212 pub fn is_array_of_tables(&self) -> bool {
214 self.as_array_of_tables().is_some()
215 }
216 pub fn is_none(&self) -> bool {
218 matches!(*self, Item::None)
219 }
220
221 pub fn as_integer(&self) -> Option<i64> {
225 self.as_value().and_then(Value::as_integer)
226 }
227
228 pub fn is_integer(&self) -> bool {
230 self.as_integer().is_some()
231 }
232
233 pub fn as_float(&self) -> Option<f64> {
235 self.as_value().and_then(Value::as_float)
236 }
237
238 pub fn is_float(&self) -> bool {
240 self.as_float().is_some()
241 }
242
243 pub fn as_bool(&self) -> Option<bool> {
245 self.as_value().and_then(Value::as_bool)
246 }
247
248 pub fn is_bool(&self) -> bool {
250 self.as_bool().is_some()
251 }
252
253 pub fn as_str(&self) -> Option<&str> {
255 self.as_value().and_then(Value::as_str)
256 }
257
258 pub fn is_str(&self) -> bool {
260 self.as_str().is_some()
261 }
262
263 pub fn as_datetime(&self) -> Option<&Datetime> {
265 self.as_value().and_then(Value::as_datetime)
266 }
267
268 pub fn is_datetime(&self) -> bool {
270 self.as_datetime().is_some()
271 }
272
273 pub fn as_array(&self) -> Option<&Array> {
275 self.as_value().and_then(Value::as_array)
276 }
277
278 pub fn as_array_mut(&mut self) -> Option<&mut Array> {
280 self.as_value_mut().and_then(Value::as_array_mut)
281 }
282
283 pub fn is_array(&self) -> bool {
285 self.as_array().is_some()
286 }
287
288 pub fn as_inline_table(&self) -> Option<&InlineTable> {
290 self.as_value().and_then(Value::as_inline_table)
291 }
292
293 pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
295 self.as_value_mut().and_then(Value::as_inline_table_mut)
296 }
297
298 pub fn is_inline_table(&self) -> bool {
300 self.as_inline_table().is_some()
301 }
302
303 pub fn as_table_like(&self) -> Option<&dyn TableLike> {
305 self.as_table()
306 .map(|t| t as &dyn TableLike)
307 .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
308 }
309
310 pub fn as_table_like_mut(&mut self) -> Option<&mut dyn TableLike> {
312 match self {
313 Item::Table(t) => Some(t as &mut dyn TableLike),
314 Item::Value(Value::InlineTable(t)) => Some(t as &mut dyn TableLike),
315 _ => None,
316 }
317 }
318
319 pub fn is_table_like(&self) -> bool {
321 self.as_table_like().is_some()
322 }
323
324 pub fn span(&self) -> Option<std::ops::Range<usize>> {
328 match self {
329 Item::None => None,
330 Item::Value(v) => v.span(),
331 Item::Table(v) => v.span(),
332 Item::ArrayOfTables(v) => v.span(),
333 }
334 }
335
336 pub(crate) fn despan(&mut self, input: &str) {
337 match self {
338 Item::None => {}
339 Item::Value(v) => v.despan(input),
340 Item::Table(v) => v.despan(input),
341 Item::ArrayOfTables(v) => v.despan(input),
342 }
343 }
344}
345
346impl Clone for Item {
347 #[inline(never)]
348 fn clone(&self) -> Self {
349 match self {
350 Item::None => Item::None,
351 Item::Value(v) => Item::Value(v.clone()),
352 Item::Table(v) => Item::Table(v.clone()),
353 Item::ArrayOfTables(v) => Item::ArrayOfTables(v.clone()),
354 }
355 }
356}
357
358#[cfg(feature = "parse")]
359impl FromStr for Item {
360 type Err = crate::TomlError;
361
362 fn from_str(s: &str) -> Result<Self, Self::Err> {
364 let value = s.parse::<Value>()?;
365 Ok(Item::Value(value))
366 }
367}
368
369impl<'b> From<&'b Item> for Item {
370 fn from(s: &'b Item) -> Self {
371 s.clone()
372 }
373}
374
375impl From<Table> for Item {
376 fn from(s: Table) -> Self {
377 Item::Table(s)
378 }
379}
380
381impl From<ArrayOfTables> for Item {
382 fn from(s: ArrayOfTables) -> Self {
383 Item::ArrayOfTables(s)
384 }
385}
386
387impl<V: Into<Value>> From<V> for Item {
388 fn from(s: V) -> Self {
389 Item::Value(s.into())
390 }
391}
392
393#[cfg(feature = "display")]
394impl std::fmt::Display for Item {
395 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
396 match &self {
397 Item::None => Ok(()),
398 Item::Value(v) => v.fmt(f),
399 Item::Table(v) => v.fmt(f),
400 Item::ArrayOfTables(v) => v.fmt(f),
401 }
402 }
403}
404
405pub fn value<V: Into<Value>>(v: V) -> Item {
432 Item::Value(v.into())
433}
434
435pub fn table() -> Item {
437 Item::Table(Table::new())
438}
439
440pub fn array() -> Item {
442 Item::ArrayOfTables(ArrayOfTables::new())
443}
444
445#[test]
446#[cfg(feature = "parse")]
447#[cfg(feature = "display")]
448fn string_roundtrip() {
449 value("hello").to_string().parse::<Item>().unwrap();
450}