1use std::collections::BTreeMap;
2
3use serde::Serialize;
4
5#[derive(Debug, Clone, PartialEq, Serialize)]
7pub struct Document {
8 sections: BTreeMap<String, Section>,
9}
10
11impl Document {
12 pub fn new() -> Self {
14 Self {
15 sections: BTreeMap::new(),
16 }
17 }
18
19 pub(crate) fn ensure_section_mut(&mut self, name: &str) -> &mut Section {
21 self.sections
22 .entry(name.to_string())
23 .or_insert_with(|| Section::new(name))
24 }
25
26 pub fn section(&self, name: &str) -> Option<&Section> {
28 self.sections.get(name)
29 }
30
31 pub fn sections(&self) -> impl Iterator<Item = (&String, &Section)> + '_ {
33 self.sections.iter()
34 }
35}
36
37impl Default for Document {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43#[derive(Debug, Clone, PartialEq, Serialize)]
45pub struct Section {
46 pub name: String,
48 pub entries: Vec<Entry>,
50}
51
52impl Section {
53 pub fn new(name: &str) -> Self {
55 Self {
56 name: name.to_string(),
57 entries: Vec::new(),
58 }
59 }
60}
61
62#[derive(Debug, Clone, PartialEq, Serialize)]
64pub struct Entry {
65 pub key: String,
67 pub value: Value,
69 pub line: usize,
71}
72
73impl Entry {
74 pub fn new(key: impl Into<String>, value: Value, line: usize) -> Self {
76 Self {
77 key: key.into(),
78 value,
79 line,
80 }
81 }
82}
83
84#[derive(Debug, Clone, PartialEq, Serialize)]
86pub enum Value {
87 String(String),
89 Number(f64),
91 Bool(bool),
93 Array(Vec<Value>),
95}
96
97impl Value {
98 pub fn as_str(&self) -> Option<&str> {
100 match self {
101 Self::String(s) => Some(s),
102 _ => None,
103 }
104 }
105}