1
/*
2
 * Hurl (https://hurl.dev)
3
 * Copyright (C) 2024 Orange
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *          http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
use crate::ast::*;
19
use crate::parser::error::*;
20
use crate::parser::primitives::*;
21
use crate::parser::template::template;
22
use crate::parser::{string, ParseResult};
23
use crate::reader::Reader;
24

            
25
31800
pub fn parse(reader: &mut Reader) -> ParseResult<Template> {
26
31800
    let start = reader.cursor();
27
31800

            
28
31800
    let mut elements = vec![];
29
    loop {
30
61695
        match template(reader) {
31
210
            Ok(expr) => {
32
210
                let element = TemplateElement::Expression(expr);
33
210
                elements.push(element);
34
            }
35
61485
            Err(e) => {
36
61485
                if e.recoverable {
37
61485
                    let value = key_string_content(reader)?;
38
61485
                    if value.is_empty() {
39
31800
                        break;
40
                    }
41
29685
                    let encoded = reader.read_from(start.index);
42
29685
                    let element = TemplateElement::String { value, encoded };
43
29685
                    elements.push(element);
44
                } else {
45
                    return Err(e);
46
                }
47
            }
48
        }
49
    }
50
31800
    if elements.is_empty() {
51
1905
        let kind = ParseErrorKind::Expecting {
52
1905
            value: "key-string".to_string(),
53
1905
        };
54
1905
        return Err(ParseError::new(start.pos, false, kind));
55
    }
56
29895
    if let Some(TemplateElement::String { encoded, .. }) = elements.first() {
57
29685
        if encoded.starts_with('[') {
58
10505
            let kind = ParseErrorKind::Expecting {
59
10505
                value: "key-string".to_string(),
60
10505
            };
61
10505
            return Err(ParseError::new(start.pos, false, kind));
62
        }
63
    }
64

            
65
19390
    let end = reader.cursor();
66
19390
    Ok(Template {
67
19390
        delimiter: None,
68
19390
        elements,
69
19390
        source_info: SourceInfo::new(start.pos, end.pos),
70
19390
    })
71
}
72

            
73
61485
fn key_string_content(reader: &mut Reader) -> ParseResult<String> {
74
61485
    let mut s = String::new();
75
    loop {
76
91290
        match key_string_escaped_char(reader) {
77
80
            Ok(c) => {
78
80
                s.push(c);
79
            }
80
91210
            Err(e) => {
81
91210
                if e.recoverable {
82
91210
                    let s2 = key_string_text(reader);
83
91210
                    if s2.is_empty() {
84
61485
                        break;
85
29725
                    } else {
86
29725
                        s.push_str(&s2);
87
                    }
88
                } else {
89
                    return Err(e);
90
                }
91
            }
92
        }
93
    }
94
61485
    Ok(s)
95
}
96

            
97
91210
fn key_string_text(reader: &mut Reader) -> String {
98
91210
    let mut s = String::new();
99
    loop {
100
288080
        let save = reader.cursor();
101
288080
        match reader.read() {
102
345
            None => break,
103
287735
            Some(c) => {
104
287735
                if c.is_alphanumeric()
105
114590
                    || c == '_'
106
113645
                    || c == '-'
107
112140
                    || c == '.'
108
112085
                    || c == '['
109
101540
                    || c == ']'
110
91000
                    || c == '@'
111
90945
                    || c == '$'
112
196870
                {
113
196870
                    s.push(c);
114
196870
                } else {
115
90865
                    reader.seek(save);
116
90865
                    break;
117
                }
118
            }
119
        }
120
    }
121

            
122
91210
    s
123
}
124

            
125
91290
fn key_string_escaped_char(reader: &mut Reader) -> ParseResult<char> {
126
91290
    try_literal("\\", reader)?;
127
80
    let start = reader.cursor();
128
80
    match reader.read() {
129
        Some('#') => Ok('#'),
130
        Some(':') => Ok(':'),
131
        Some('\\') => Ok('\\'),
132
        Some('/') => Ok('/'),
133
        Some('b') => Ok('\x08'),
134
        Some('f') => Ok('\x0c'),
135
        Some('n') => Ok('\n'),
136
        Some('r') => Ok('\r'),
137
        Some('t') => Ok('\t'),
138
80
        Some('u') => string::unicode(reader),
139
        _ => Err(ParseError::new(
140
            start.pos,
141
            false,
142
            ParseErrorKind::EscapeChar,
143
        )),
144
    }
145
}
146

            
147
#[cfg(test)]
148
mod tests {
149
    use super::*;
150
    use crate::reader::Pos;
151

            
152
    #[test]
153
    fn test_key_string() {
154
        let mut reader = Reader::new("aaa\\: ");
155
        assert_eq!(
156
            parse(&mut reader).unwrap(),
157
            Template {
158
                delimiter: None,
159
                elements: vec![TemplateElement::String {
160
                    value: "aaa:".to_string(),
161
                    encoded: "aaa\\:".to_string(),
162
                }],
163
                source_info: SourceInfo::new(Pos::new(1, 1), Pos::new(1, 6)),
164
            }
165
        );
166
        assert_eq!(reader.cursor().index, 5);
167

            
168
        let mut reader = Reader::new("$top:");
169
        assert_eq!(
170
            parse(&mut reader).unwrap(),
171
            Template {
172
                delimiter: None,
173
                elements: vec![TemplateElement::String {
174
                    value: "$top".to_string(),
175
                    encoded: "$top".to_string(),
176
                }],
177
                source_info: SourceInfo::new(Pos::new(1, 1), Pos::new(1, 5)),
178
            }
179
        );
180
        assert_eq!(reader.cursor().index, 4);
181

            
182
        let mut reader = Reader::new("key\\u{20}\\u{3a} :");
183
        assert_eq!(
184
            parse(&mut reader).unwrap(),
185
            Template {
186
                delimiter: None,
187
                elements: vec![TemplateElement::String {
188
                    value: "key :".to_string(),
189
                    encoded: "key\\u{20}\\u{3a}".to_string(),
190
                }],
191
                source_info: SourceInfo::new(Pos::new(1, 1), Pos::new(1, 16)),
192
            }
193
        );
194
        assert_eq!(reader.cursor().index, 15);
195

            
196
        let mut reader = Reader::new("values\\u{5b}0\\u{5d} :");
197
        assert_eq!(
198
            parse(&mut reader).unwrap(),
199
            Template {
200
                delimiter: None,
201
                elements: vec![TemplateElement::String {
202
                    value: "values[0]".to_string(),
203
                    encoded: "values\\u{5b}0\\u{5d}".to_string(),
204
                }],
205
                source_info: SourceInfo::new(Pos::new(1, 1), Pos::new(1, 20)),
206
            }
207
        );
208
        assert_eq!(reader.cursor().index, 19);
209

            
210
        let mut reader = Reader::new("values[0] :");
211
        assert_eq!(
212
            parse(&mut reader).unwrap(),
213
            Template {
214
                delimiter: None,
215
                elements: vec![TemplateElement::String {
216
                    value: "values[0]".to_string(),
217
                    encoded: "values[0]".to_string(),
218
                }],
219
                source_info: SourceInfo::new(Pos::new(1, 1), Pos::new(1, 10)),
220
            }
221
        );
222
        assert_eq!(reader.cursor().index, 9);
223

            
224
        let mut reader = Reader::new("\\u{5b}0\\u{5d}");
225
        assert_eq!(
226
            parse(&mut reader).unwrap(),
227
            Template {
228
                delimiter: None,
229
                elements: vec![TemplateElement::String {
230
                    value: "[0]".to_string(),
231
                    encoded: "\\u{5b}0\\u{5d}".to_string(),
232
                }],
233
                source_info: SourceInfo::new(Pos::new(1, 1), Pos::new(1, 14)),
234
            }
235
        );
236
        assert_eq!(reader.cursor().index, 13);
237
    }
238

            
239
    #[test]
240
    fn test_key_string_error() {
241
        let mut reader = Reader::new("");
242
        let error = parse(&mut reader).err().unwrap();
243
        assert!(!error.recoverable);
244
        assert_eq!(error.pos, Pos { line: 1, column: 1 });
245

            
246
        let mut reader = Reader::new("{{key");
247
        let error = parse(&mut reader).err().unwrap();
248
        assert!(!error.recoverable);
249
        assert_eq!(error.pos, Pos { line: 1, column: 6 });
250

            
251
        // key string can not start with a '[' (reserved for section)
252
        let mut reader = Reader::new("[0]:");
253
        let error = parse(&mut reader).err().unwrap();
254
        assert!(!error.recoverable);
255
        assert_eq!(reader.cursor().index, 3);
256

            
257
        let mut reader = Reader::new("\\l");
258
        let error = parse(&mut reader).err().unwrap();
259
        assert_eq!(error.pos, Pos { line: 1, column: 2 });
260
        assert_eq!(error.kind, ParseErrorKind::EscapeChar);
261

            
262
        let mut reader = Reader::new(r#"{"id":1}"#);
263
        let error = parse(&mut reader).err().unwrap();
264
        assert_eq!(error.pos, Pos { line: 1, column: 1 });
265
        assert_eq!(
266
            error.kind,
267
            ParseErrorKind::Expecting {
268
                value: "key-string".to_string()
269
            }
270
        );
271
    }
272

            
273
    #[test]
274
    fn test_key_string_content() {
275
        let mut reader = Reader::new("aaa\\:");
276
        assert_eq!(key_string_content(&mut reader).unwrap(), "aaa:");
277
    }
278

            
279
    #[test]
280
    fn test_key_string_text() {
281
        let mut reader = Reader::new("aaa\\:");
282
        assert_eq!(key_string_text(&mut reader), "aaa");
283
        assert_eq!(reader.cursor().index, 3);
284
    }
285

            
286
    #[test]
287
    fn test_key_string_escaped_char() {
288
        let mut reader = Reader::new("\\u{0a}");
289
        assert_eq!(key_string_escaped_char(&mut reader).unwrap(), '\n');
290
        assert_eq!(reader.cursor().index, 6);
291

            
292
        let mut reader = Reader::new("\\:");
293
        assert_eq!(key_string_escaped_char(&mut reader).unwrap(), ':');
294
        assert_eq!(reader.cursor().index, 2);
295

            
296
        let mut reader = Reader::new("x");
297
        let error = key_string_escaped_char(&mut reader).err().unwrap();
298
        assert_eq!(error.pos, Pos { line: 1, column: 1 });
299
        assert_eq!(
300
            error.kind,
301
            ParseErrorKind::Expecting {
302
                value: "\\".to_string()
303
            }
304
        );
305
        assert!(error.recoverable);
306
        assert_eq!(reader.cursor().index, 0);
307
    }
308
}