1use crate::ast::{Count, Missing, Plurality, PreferOptions, Resolution, ReturnRepresentation};
2use crate::error::Error;
3use nom::{branch::alt, bytes::complete::tag, combinator::map, sequence::preceded, IResult};
4
5fn parse_return(input: &str) -> IResult<&str, ReturnRepresentation> {
7 preceded(
8 tag("return="),
9 alt((
10 map(tag("representation"), |_| ReturnRepresentation::Full),
11 map(tag("minimal"), |_| ReturnRepresentation::Minimal),
12 map(tag("headers-only"), |_| ReturnRepresentation::HeadersOnly),
13 )),
14 )(input)
15}
16
17fn parse_resolution(input: &str) -> IResult<&str, Resolution> {
19 preceded(
20 tag("resolution="),
21 alt((
22 map(tag("merge-duplicates"), |_| Resolution::MergeDuplicates),
23 map(tag("ignore-duplicates"), |_| Resolution::IgnoreDuplicates),
24 )),
25 )(input)
26}
27
28fn parse_count(input: &str) -> IResult<&str, Count> {
30 preceded(
31 tag("count="),
32 alt((
33 map(tag("exact"), |_| Count::Exact),
34 map(tag("planned"), |_| Count::Planned),
35 map(tag("estimated"), |_| Count::Estimated),
36 )),
37 )(input)
38}
39
40fn parse_plurality(input: &str) -> IResult<&str, Plurality> {
42 preceded(
43 tag("plurality="),
44 alt((
45 map(tag("singular"), |_| Plurality::Singular),
46 map(tag("multiple"), |_| Plurality::Multiple),
47 )),
48 )(input)
49}
50
51fn parse_missing(input: &str) -> IResult<&str, Missing> {
53 preceded(
54 tag("missing="),
55 alt((
56 map(tag("default"), |_| Missing::Default),
57 map(tag("null"), |_| Missing::Null),
58 )),
59 )(input)
60}
61
62pub fn parse_prefer_header(input: &str) -> Result<PreferOptions, Error> {
74 let parts: Vec<&str> = input.split(',').map(|s| s.trim()).collect();
75
76 let mut options = PreferOptions::new();
77
78 for part in parts {
79 if part.is_empty() {
80 continue;
81 }
82
83 if let Ok((_, ret)) = parse_return(part) {
85 options.return_representation = Some(ret);
86 } else if let Ok((_, res)) = parse_resolution(part) {
87 options.resolution = Some(res);
88 } else if let Ok((_, cnt)) = parse_count(part) {
89 options.count = Some(cnt);
90 } else if let Ok((_, plur)) = parse_plurality(part) {
91 options.plurality = Some(plur);
92 } else if let Ok((_, miss)) = parse_missing(part) {
93 options.missing = Some(miss);
94 } else {
95 continue;
97 }
98 }
99
100 Ok(options)
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn test_parse_return_representation() {
109 assert_eq!(
110 parse_return("return=representation").unwrap().1,
111 ReturnRepresentation::Full
112 );
113 assert_eq!(
114 parse_return("return=minimal").unwrap().1,
115 ReturnRepresentation::Minimal
116 );
117 assert_eq!(
118 parse_return("return=headers-only").unwrap().1,
119 ReturnRepresentation::HeadersOnly
120 );
121 }
122
123 #[test]
124 fn test_parse_resolution() {
125 assert_eq!(
126 parse_resolution("resolution=merge-duplicates").unwrap().1,
127 Resolution::MergeDuplicates
128 );
129 assert_eq!(
130 parse_resolution("resolution=ignore-duplicates").unwrap().1,
131 Resolution::IgnoreDuplicates
132 );
133 }
134
135 #[test]
136 fn test_parse_count() {
137 assert_eq!(parse_count("count=exact").unwrap().1, Count::Exact);
138 assert_eq!(parse_count("count=planned").unwrap().1, Count::Planned);
139 assert_eq!(parse_count("count=estimated").unwrap().1, Count::Estimated);
140 }
141
142 #[test]
143 fn test_parse_plurality() {
144 assert_eq!(
145 parse_plurality("plurality=singular").unwrap().1,
146 Plurality::Singular
147 );
148 assert_eq!(
149 parse_plurality("plurality=multiple").unwrap().1,
150 Plurality::Multiple
151 );
152 }
153
154 #[test]
155 fn test_parse_missing() {
156 assert_eq!(
157 parse_missing("missing=default").unwrap().1,
158 Missing::Default
159 );
160 assert_eq!(parse_missing("missing=null").unwrap().1, Missing::Null);
161 }
162
163 #[test]
164 fn test_parse_prefer_header_single() {
165 let opts = parse_prefer_header("return=representation").unwrap();
166 assert_eq!(opts.return_representation, Some(ReturnRepresentation::Full));
167 }
168
169 #[test]
170 fn test_parse_prefer_header_multiple() {
171 let opts = parse_prefer_header("return=representation, count=exact").unwrap();
172 assert_eq!(opts.return_representation, Some(ReturnRepresentation::Full));
173 assert_eq!(opts.count, Some(Count::Exact));
174 }
175
176 #[test]
177 fn test_parse_prefer_header_all_options() {
178 let input = "return=minimal, resolution=merge-duplicates, count=planned, plurality=singular, missing=default";
179 let opts = parse_prefer_header(input).unwrap();
180
181 assert_eq!(
182 opts.return_representation,
183 Some(ReturnRepresentation::Minimal)
184 );
185 assert_eq!(opts.resolution, Some(Resolution::MergeDuplicates));
186 assert_eq!(opts.count, Some(Count::Planned));
187 assert_eq!(opts.plurality, Some(Plurality::Singular));
188 assert_eq!(opts.missing, Some(Missing::Default));
189 }
190
191 #[test]
192 fn test_parse_prefer_header_with_spaces() {
193 let opts = parse_prefer_header(" return=representation , count=exact ").unwrap();
194 assert_eq!(opts.return_representation, Some(ReturnRepresentation::Full));
195 assert_eq!(opts.count, Some(Count::Exact));
196 }
197
198 #[test]
199 fn test_parse_prefer_header_unknown_option() {
200 let opts =
202 parse_prefer_header("return=representation, unknown=value, count=exact").unwrap();
203 assert_eq!(opts.return_representation, Some(ReturnRepresentation::Full));
204 assert_eq!(opts.count, Some(Count::Exact));
205 }
206
207 #[test]
208 fn test_parse_prefer_header_empty() {
209 let opts = parse_prefer_header("").unwrap();
210 assert!(opts.is_empty());
211 }
212
213 #[test]
214 fn test_parse_prefer_header_empty_parts() {
215 let opts = parse_prefer_header("return=representation, , count=exact").unwrap();
216 assert_eq!(opts.return_representation, Some(ReturnRepresentation::Full));
217 assert_eq!(opts.count, Some(Count::Exact));
218 }
219}