kv3/
from_str.rs

1use pest::Parser;
2use pest::error::Error;
3use pest::iterators::Pair;
4use pest_derive::Parser;
5
6use crate::{Header, Metadata, ObjectKey, Value};
7
8#[derive(Parser)]
9#[grammar = "grammar.pest"]
10struct KV3Parser;
11
12pub fn from_str(str: &str) -> Result<Value, Error<Rule>> {
13    let file = KV3Parser::parse(Rule::file, str)?.next().unwrap();
14
15    fn parse_value(pair: Pair<Rule>) -> Value {
16        match pair.as_rule() {
17            Rule::file => {
18                let mut inner = pair.into_inner();
19
20                let next = inner.next().unwrap();
21
22                if next.as_rule() == Rule::header {
23                    let metadata = next
24                        .into_inner()
25                        .map(|pair| {
26                            let mut inner = pair.into_inner();
27
28                            let key = inner.next().unwrap().as_str().to_owned();
29                            let value = inner.next().unwrap().as_str().to_owned();
30                            let version = inner.next().unwrap().as_str().to_owned();
31
32                            Metadata {
33                                key,
34                                value,
35                                version,
36                            }
37                        })
38                        .collect::<Vec<_>>();
39                    let header = Header(metadata);
40                    let root = Box::new(parse_value(inner.next().unwrap()));
41                    Value::File(header, root)
42                } else {
43                    parse_value(next)
44                }
45            }
46            Rule::object => Value::Object(
47                pair.into_inner()
48                    .map(|pair| {
49                        let mut inner = pair.into_inner();
50
51                        let key = inner.next().unwrap();
52                        let key = match key.as_rule() {
53                            Rule::identifier => ObjectKey::Identifier(key.as_str().to_owned()),
54                            Rule::string => ObjectKey::String(
55                                key.into_inner().next().unwrap().as_str().to_owned(),
56                            ),
57                            _ => unreachable!(),
58                        };
59
60                        let value = parse_value(inner.next().unwrap());
61
62                        (key, value)
63                    })
64                    .collect(),
65            ),
66            Rule::array => Value::Array(pair.into_inner().map(parse_value).collect()),
67            Rule::flag => {
68                let mut inner = pair.into_inner();
69                let key = inner.next().unwrap().as_str().to_owned();
70                let value = parse_value(inner.next().unwrap());
71                Value::Flag(key, Box::new(value))
72            }
73            Rule::string => Value::String(pair.into_inner().next().unwrap().as_str().to_owned()),
74            Rule::multiline_string => Value::MultilineString(pair.into_inner().next().unwrap().as_str().to_owned()),
75            Rule::number => Value::Number(pair.as_str().parse().unwrap()),
76            Rule::boolean => Value::Bool(pair.as_str().parse().unwrap()),
77            Rule::null => Value::Null,
78            _ => unreachable!(),
79        }
80    }
81
82    Ok(parse_value(file))
83}