1
/*
2
 * Hurl (https://hurl.dev)
3
 * Copyright (C) 2026 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::Bytes;
19
use crate::combinator::choice;
20
use crate::reader::Reader;
21

            
22
use super::json::parse as parse_json;
23
use super::multiline::multiline_string;
24
use super::string::backtick_template;
25
use super::{ParseResult, primitives, xml};
26

            
27
26628
pub fn bytes(reader: &mut Reader) -> ParseResult<Bytes> {
28
26628
    choice(
29
26628
        &[
30
26628
            multiline_string_bytes,
31
26628
            string_bytes,
32
26628
            json_bytes,
33
26628
            xml_bytes,
34
26628
            base64_bytes,
35
26628
            hex_bytes,
36
26628
            file_bytes,
37
26628
        ],
38
26628
        reader,
39
    )
40
}
41

            
42
23788
fn xml_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
43
23788
    match xml::parse(reader) {
44
23700
        Err(e) => Err(e),
45
88
        Ok(value) => Ok(Bytes::Xml(value)),
46
    }
47
}
48

            
49
24248
fn json_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
50
24248
    match parse_json(reader) {
51
23824
        Err(e) => Err(e),
52
424
        Ok(value) => Ok(Bytes::Json(value)),
53
    }
54
}
55

            
56
23240
fn file_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
57
23240
    primitives::file(reader).map(Bytes::File)
58
}
59

            
60
23696
fn base64_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
61
23696
    primitives::base64(reader).map(Bytes::Base64)
62
}
63

            
64
23420
fn hex_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
65
23420
    primitives::hex(reader).map(Bytes::Hex)
66
}
67

            
68
26628
pub fn multiline_string_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
69
26628
    multiline_string(reader).map(Bytes::MultilineString)
70
}
71

            
72
25888
fn string_bytes(reader: &mut Reader) -> ParseResult<Bytes> {
73
25888
    backtick_template(reader).map(Bytes::OnelineString)
74
}
75

            
76
#[cfg(test)]
77
mod tests {
78
    use crate::ast::{
79
        JsonListElement, JsonValue, JsonValueKind, SourceInfo, Template, TemplateElement,
80
    };
81
    use crate::parser::ParseErrorKind;
82
    use crate::reader::{CharPos, Pos};
83
    use crate::types::ToSource;
84

            
85
    use super::*;
86

            
87
    #[test]
88
    fn test_bytes_json() {
89
        let mut reader = Reader::new("[1,2,3] ");
90
        assert_eq!(
91
            bytes(&mut reader).unwrap(),
92
            Bytes::Json(JsonValue::new(
93
                SourceInfo::new(Pos::new(1, 1), Pos::new(1, 8)),
94
                JsonValueKind::List {
95
                    space0: String::new(),
96
                    elements: vec![
97
                        JsonListElement {
98
                            space0: String::new(),
99
                            value: JsonValue::new(
100
                                SourceInfo::new(Pos::new(1, 2), Pos::new(1, 3)),
101
                                JsonValueKind::Number("1".to_string()),
102
                            ),
103
                            space1: String::new(),
104
                        },
105
                        JsonListElement {
106
                            space0: String::new(),
107
                            value: JsonValue::new(
108
                                SourceInfo::new(Pos::new(1, 4), Pos::new(1, 5)),
109
                                JsonValueKind::Number("2".to_string()),
110
                            ),
111
                            space1: String::new(),
112
                        },
113
                        JsonListElement {
114
                            space0: String::new(),
115
                            value: JsonValue::new(
116
                                SourceInfo::new(Pos::new(1, 6), Pos::new(1, 7)),
117
                                JsonValueKind::Number("3".to_string()),
118
                            ),
119
                            space1: String::new(),
120
                        },
121
                    ],
122
                },
123
            ))
124
        );
125
        assert_eq!(reader.cursor().index, CharPos(7));
126

            
127
        let mut reader = Reader::new("{ } ");
128
        assert_eq!(
129
            bytes(&mut reader).unwrap(),
130
            Bytes::Json(JsonValue::new(
131
                SourceInfo::new(Pos::new(1, 1), Pos::new(1, 4)),
132
                JsonValueKind::Object {
133
                    space0: " ".to_string(),
134
                    elements: vec![],
135
                },
136
            ))
137
        );
138
        assert_eq!(reader.cursor().index, CharPos(3));
139

            
140
        let mut reader = Reader::new("true");
141
        assert_eq!(
142
            bytes(&mut reader).unwrap(),
143
            Bytes::Json(JsonValue::new(
144
                SourceInfo::new(Pos::new(1, 1), Pos::new(1, 5)),
145
                JsonValueKind::Boolean(true),
146
            ))
147
        );
148
        assert_eq!(reader.cursor().index, CharPos(4));
149

            
150
        let mut reader = Reader::new("\"\" x");
151
        let template = Template::new(
152
            Some('"'),
153
            vec![],
154
            SourceInfo::new(Pos::new(1, 2), Pos::new(1, 2)),
155
        );
156
        assert_eq!(
157
            bytes(&mut reader).unwrap(),
158
            Bytes::Json(JsonValue::new(
159
                SourceInfo::new(Pos::new(1, 1), Pos::new(1, 3)),
160
                JsonValueKind::String(template),
161
            ))
162
        );
163
        assert_eq!(reader.cursor().index, CharPos(2));
164
    }
165

            
166
    #[test]
167
    fn test_bytes_xml() {
168
        let mut reader = Reader::new("<a/>");
169
        assert_eq!(
170
            bytes(&mut reader).unwrap(),
171
            Bytes::Xml(String::from("<a/>"))
172
        );
173
    }
174

            
175
    #[test]
176
    fn test_bytes_json_error() {
177
        let mut reader = Reader::new("{ x ");
178
        let error = bytes(&mut reader).err().unwrap();
179
        assert_eq!(error.pos, Pos { line: 1, column: 3 });
180
        assert_eq!(
181
            error.kind,
182
            ParseErrorKind::Expecting {
183
                value: "\"".to_string()
184
            },
185
        );
186
    }
187

            
188
    #[test]
189
    fn test_bytes_multilines_error() {
190
        let mut reader = Reader::new("```\nxxx ");
191
        let error = bytes(&mut reader).err().unwrap();
192
        assert_eq!(error.pos, Pos { line: 2, column: 5 });
193
        assert_eq!(
194
            error.kind,
195
            ParseErrorKind::Expecting {
196
                value: "```".to_string()
197
            }
198
        );
199
    }
200

            
201
    #[test]
202
    fn test_bytes_eof() {
203
        let mut reader = Reader::new("");
204
        let error = bytes(&mut reader).err().unwrap();
205
        assert_eq!(
206
            error.kind,
207
            ParseErrorKind::Expecting {
208
                value: String::from("file")
209
            }
210
        );
211
        assert!(error.recoverable);
212
    }
213

            
214
    #[test]
215
    fn test_json_bytes() {
216
        let mut reader = Reader::new("100");
217
        assert_eq!(
218
            json_bytes(&mut reader).unwrap(),
219
            Bytes::Json(JsonValue::new(
220
                SourceInfo::new(Pos::new(1, 1), Pos::new(1, 4)),
221
                JsonValueKind::Number("100".to_string()),
222
            ))
223
        );
224
    }
225

            
226
    #[test]
227
    fn test_bytes_string() {
228
        let mut reader = Reader::new("`foo`  ");
229
        let template = Template::new(
230
            Some('`'),
231
            vec![TemplateElement::String {
232
                value: "foo".to_string(),
233
                source: "foo".to_source(),
234
            }],
235
            SourceInfo::new(Pos::new(1, 1), Pos::new(1, 6)),
236
        );
237
        assert_eq!(bytes(&mut reader).unwrap(), Bytes::OnelineString(template));
238
        assert_eq!(reader.cursor().index.0, 5);
239
    }
240
}