]> git.proxmox.com Git - rustc.git/blame - vendor/winnow/examples/ini/parser_str.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / vendor / winnow / examples / ini / parser_str.rs
CommitLineData
49aad941
FG
1use std::collections::HashMap;
2
3use winnow::prelude::*;
4use winnow::{
fe692bf9 5 ascii::{alphanumeric1 as alphanumeric, space0 as space},
49aad941 6 combinator::opt,
fe692bf9
FG
7 combinator::repeat,
8 combinator::{delimited, terminated},
9 token::{take_till0, take_while},
49aad941
FG
10};
11
12pub type Stream<'i> = &'i str;
13
14pub fn categories(input: Stream<'_>) -> IResult<Stream<'_>, HashMap<&str, HashMap<&str, &str>>> {
fe692bf9 15 repeat(0.., category_and_keys).parse_next(input)
49aad941
FG
16}
17
18fn category_and_keys(i: Stream<'_>) -> IResult<Stream<'_>, (&str, HashMap<&str, &str>)> {
19 (category, keys_and_values).parse_next(i)
20}
21
22fn category(i: Stream<'_>) -> IResult<Stream<'_>, &str> {
23 terminated(
fe692bf9
FG
24 delimited('[', take_while(0.., |c| c != ']'), ']'),
25 opt(take_while(1.., " \r\n")),
49aad941
FG
26 )
27 .parse_next(i)
28}
29
30fn keys_and_values(input: Stream<'_>) -> IResult<Stream<'_>, HashMap<&str, &str>> {
fe692bf9 31 repeat(0.., key_value).parse_next(input)
49aad941
FG
32}
33
34fn key_value(i: Stream<'_>) -> IResult<Stream<'_>, (&str, &str)> {
35 let (i, key) = alphanumeric(i)?;
36 let (i, _) = (opt(space), "=", opt(space)).parse_next(i)?;
37 let (i, val) = take_till0(is_line_ending_or_comment).parse_next(i)?;
38 let (i, _) = opt(space).parse_next(i)?;
39 let (i, _) = opt((";", not_line_ending)).parse_next(i)?;
40 let (i, _) = opt(space_or_line_ending).parse_next(i)?;
41
42 Ok((i, (key, val)))
43}
44
45fn is_line_ending_or_comment(chr: char) -> bool {
46 chr == ';' || chr == '\n'
47}
48
49fn not_line_ending(i: Stream<'_>) -> IResult<Stream<'_>, &str> {
fe692bf9 50 take_while(0.., |c| c != '\r' && c != '\n').parse_next(i)
49aad941
FG
51}
52
53fn space_or_line_ending(i: Stream<'_>) -> IResult<Stream<'_>, &str> {
fe692bf9 54 take_while(1.., " \r\n").parse_next(i)
49aad941
FG
55}
56
57#[test]
58fn parse_category_test() {
59 let ini_file = "[category]
60
61parameter=value
62key = value2";
63
64 let ini_without_category = "parameter=value
65key = value2";
66
67 let res = category(ini_file);
68 println!("{:?}", res);
69 match res {
70 Ok((i, o)) => println!("i: {} | o: {:?}", i, o),
71 _ => println!("error"),
72 }
73
74 assert_eq!(res, Ok((ini_without_category, "category")));
75}
76
77#[test]
78fn parse_key_value_test() {
79 let ini_file = "parameter=value
80key = value2";
81
82 let ini_without_key_value = "key = value2";
83
84 let res = key_value(ini_file);
85 println!("{:?}", res);
86 match res {
87 Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
88 _ => println!("error"),
89 }
90
91 assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
92}
93
94#[test]
95fn parse_key_value_with_space_test() {
96 let ini_file = "parameter = value
97key = value2";
98
99 let ini_without_key_value = "key = value2";
100
101 let res = key_value(ini_file);
102 println!("{:?}", res);
103 match res {
104 Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
105 _ => println!("error"),
106 }
107
108 assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
109}
110
111#[test]
112fn parse_key_value_with_comment_test() {
113 let ini_file = "parameter=value;abc
114key = value2";
115
116 let ini_without_key_value = "key = value2";
117
118 let res = key_value(ini_file);
119 println!("{:?}", res);
120 match res {
121 Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
122 _ => println!("error"),
123 }
124
125 assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
126}
127
128#[test]
129fn parse_multiple_keys_and_values_test() {
130 let ini_file = "parameter=value;abc
131
132key = value2
133
134[category]";
135
136 let ini_without_key_value = "[category]";
137
138 let res = keys_and_values(ini_file);
139 println!("{:?}", res);
140 match res {
141 Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o),
142 _ => println!("error"),
143 }
144
145 let mut expected: HashMap<&str, &str> = HashMap::new();
146 expected.insert("parameter", "value");
147 expected.insert("key", "value2");
148 assert_eq!(res, Ok((ini_without_key_value, expected)));
149}
150
151#[test]
152fn parse_category_then_multiple_keys_and_values_test() {
153 //FIXME: there can be an empty line or a comment line after a category
154 let ini_file = "[abcd]
155parameter=value;abc
156
157key = value2
158
159[category]";
160
161 let ini_after_parser = "[category]";
162
163 let res = category_and_keys(ini_file);
164 println!("{:?}", res);
165 match res {
166 Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o),
167 _ => println!("error"),
168 }
169
170 let mut expected_h: HashMap<&str, &str> = HashMap::new();
171 expected_h.insert("parameter", "value");
172 expected_h.insert("key", "value2");
173 assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h))));
174}
175
176#[test]
177fn parse_multiple_categories_test() {
178 let ini_file = "[abcd]
179
180parameter=value;abc
181
182key = value2
183
184[category]
185parameter3=value3
186key4 = value4
187";
188
189 let res = categories(ini_file);
190 //println!("{:?}", res);
191 match res {
192 Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o),
193 _ => println!("error"),
194 }
195
196 let mut expected_1: HashMap<&str, &str> = HashMap::new();
197 expected_1.insert("parameter", "value");
198 expected_1.insert("key", "value2");
199 let mut expected_2: HashMap<&str, &str> = HashMap::new();
200 expected_2.insert("parameter3", "value3");
201 expected_2.insert("key4", "value4");
202 let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
203 expected_h.insert("abcd", expected_1);
204 expected_h.insert("category", expected_2);
205 assert_eq!(res, Ok(("", expected_h)));
206}