hocon_rs/parser/
object.rs1use crate::Result;
2use crate::error::Error;
3use crate::parser::HoconParser;
4use crate::parser::include::INCLUDE;
5use crate::parser::read::Read;
6use crate::parser::string::TRIPLE_DOUBLE_QUOTE;
7use crate::raw::{
8 comment::Comment, field::ObjectField, raw_object::RawObject, raw_string::RawString,
9 raw_value::RawValue,
10};
11use std::str::FromStr;
12
13#[macro_export]
14macro_rules! try_peek {
15 ($reader:expr) => {
16 match $reader.peek() {
17 Ok(ch) => ch,
18 Err($crate::error::Error::Eof) => break,
19 Err(err) => return Err(err),
20 }
21 };
22}
23
24impl<'de, R: Read<'de>> HoconParser<R> {
25 pub(crate) fn parse_key(&mut self) -> Result<RawString> {
26 self.drop_horizontal_whitespace()?;
27 self.parse_path_expression()
28 }
29
30 pub(crate) fn parse_value(&mut self) -> Result<RawValue> {
31 self.drop_whitespace()?;
32 let mut values = vec![];
33 let mut scratch = vec![];
34 let mut spaces = vec![];
35 let mut prev_space = None;
36 #[inline]
37 fn push_value_and_space(
38 values: &mut Vec<RawValue>,
39 spaces: &mut Vec<Option<String>>,
40 mut space_after_value: Option<String>,
41 v: RawValue,
42 ) -> Option<String> {
43 if !values.is_empty() {
44 spaces.push(space_after_value);
45 space_after_value = None;
46 }
47 values.push(v);
48 space_after_value
49 }
50 loop {
51 let ch = try_peek!(self.reader);
52 match ch {
53 b'[' => {
54 let max_depth = self.options.max_depth;
56 let current_depth = self.ctx.increase_depth();
57 if current_depth > max_depth {
58 return Err(Error::RecursionDepthExceeded { max_depth });
59 }
60 let array = self.parse_array(false)?;
61 self.ctx.decrease_depth();
62 let v = RawValue::Array(array);
63 prev_space = push_value_and_space(&mut values, &mut spaces, prev_space, v);
64 }
65 b'{' => {
66 let max_depth = self.options.max_depth;
68 let current_depth = self.ctx.increase_depth();
69 if current_depth > max_depth {
70 return Err(Error::RecursionDepthExceeded { max_depth });
71 }
72 let object = self.parse_object(false)?;
73 self.ctx.decrease_depth();
74 let v = RawValue::Object(object);
75 prev_space = push_value_and_space(&mut values, &mut spaces, prev_space, v);
76 }
77 b'"' => {
78 let v = if let Ok(chars) = self.reader.peek_n(3)
80 && chars == TRIPLE_DOUBLE_QUOTE
81 {
82 let multiline = self.parse_multiline_string(false)?;
83 RawValue::String(RawString::MultilineString(multiline))
84 } else {
85 let quoted = self.parse_quoted_string(false)?;
86 RawValue::String(RawString::QuotedString(quoted))
87 };
88 prev_space = push_value_and_space(&mut values, &mut spaces, prev_space, v);
89 }
90 b'$' => {
91 let substitution = self.parse_substitution()?;
92 let v = RawValue::Substitution(substitution);
93 prev_space = push_value_and_space(&mut values, &mut spaces, prev_space, v);
94 }
95 b']' | b'}' => {
96 break;
97 }
98 b',' | b'#' | b'\n' => {
99 if values.is_empty() {
100 return Err(Error::UnexpectedToken {
101 expected: "a valid value",
102 found_beginning: ch,
103 });
104 }
105 break;
106 }
107 b'/' if self.reader.peek2().is_ok_and(|(_, ch2)| ch2 == b'/') => {
108 if !values.is_empty() {
109 break;
110 } else {
111 return Err(Error::UnexpectedToken {
112 expected: "a valid value",
113 found_beginning: ch,
114 });
115 }
116 }
117 b'\r' => {
118 if let Ok((_, ch2)) = self.reader.peek2() {
119 if ch2 == b'\n' && !values.is_empty() {
120 break;
121 } else {
122 return Err(Error::UnexpectedToken {
123 expected: "a valid value",
124 found_beginning: ch,
125 });
126 }
127 }
128 }
129 _ => {
130 if self.reader.starts_with_horizontal_whitespace()? {
132 scratch.clear();
133 self.parse_horizontal_whitespace(&mut scratch)?;
134 let space = unsafe { str::from_utf8_unchecked(&scratch) };
135 if space.is_empty() {
136 prev_space = None
137 } else {
138 prev_space = Some(space.to_string());
139 }
140 } else {
141 let unquoted = self.parse_unquoted_string()?;
142 let v = RawValue::String(RawString::UnquotedString(unquoted));
143 prev_space = push_value_and_space(&mut values, &mut spaces, prev_space, v);
144 }
145 }
146 };
147 }
148 debug_assert!(!values.is_empty());
149 if values.len() == 1 {
150 let v = values.remove(0);
151 let v = if let RawValue::String(s) = v {
152 Self::resolve_unquoted_string(s)
153 } else {
154 v
155 };
156 Ok(v)
157 } else {
158 debug_assert_eq!(values.len(), spaces.len() + 1);
159 RawValue::concat(values, spaces)
160 }
161 }
162
163 pub(crate) fn parse_key_value(&mut self) -> Result<(RawString, RawValue)> {
165 self.drop_whitespace()?;
166 let key = self.parse_key()?;
167 self.drop_whitespace()?;
168 let is_add_assign = self.drop_kv_separator()?;
169 self.drop_whitespace()?;
170 let mut value = self.parse_value()?;
171 if is_add_assign {
172 value = RawValue::add_assign(value)
173 }
174 Ok((key, value))
175 }
176
177 pub fn drop_kv_separator(&mut self) -> Result<bool> {
178 let ch = self.reader.peek()?;
179 match ch {
180 b':' | b'=' => {
181 self.reader.discard(1)?;
182 }
183 b'+' => {
184 let (_, ch2) = self.reader.peek2()?;
185 if ch2 != b'=' {
186 return Err(Error::UnexpectedToken {
187 expected: "=",
188 found_beginning: ch2,
189 });
190 }
191 self.reader.discard(2)?;
192 return Ok(true);
193 }
194 b'{' => {}
195 ch => {
196 return Err(Error::UnexpectedToken {
197 expected: ": or =",
198 found_beginning: ch,
199 });
200 }
201 }
202 Ok(false)
203 }
204
205 #[inline]
206 pub(crate) fn parse_object_field(&mut self) -> Result<ObjectField> {
207 let ch = self.reader.peek()?;
208 let field = if ch == b'i' && self.reader.peek_n(7)? == INCLUDE {
210 let mut inclusion = self.parse_include()?;
211 self.parse_inclusion(&mut inclusion)?;
212 ObjectField::inclusion(inclusion)
213 } else {
214 let (key, value) = self.parse_key_value()?;
215 ObjectField::key_value(key, value)
216 };
217 Ok(field)
218 }
219
220 pub(crate) fn parse_braces_omitted_object(&mut self) -> Result<RawObject> {
221 let mut fields = vec![];
222 loop {
223 self.drop_whitespace_and_comments()?;
224 let ch = self.reader.peek()?;
225 if ch == b'}' {
226 break;
227 }
228 match self.parse_object_field() {
229 Ok(field) => {
230 fields.push(field);
231 }
232 Err(Error::Eof) => {
233 break;
234 }
235 Err(err) => {
236 return Err(err);
237 }
238 }
239 self.drop_whitespace_and_comments()?;
240 if self.drop_comma_separator()? {
241 break;
242 }
243 }
244 let raw_obj = RawObject::new(fields);
245 Ok(raw_obj)
246 }
247
248 pub(crate) fn parse_object(&mut self, verify_delimiter: bool) -> Result<RawObject> {
249 if verify_delimiter {
250 let ch = self.reader.peek()?;
251 if ch != b'{' {
252 return Err(Error::UnexpectedToken {
253 expected: "{",
254 found_beginning: ch,
255 });
256 }
257 }
258 self.reader.discard(1)?;
259 let raw_obj = self.parse_braces_omitted_object()?;
260 let ch = self.reader.peek()?;
261 if ch != b'}' {
262 return Err(Error::UnexpectedToken {
263 expected: "}",
264 found_beginning: ch,
265 });
266 }
267 self.reader.discard(1)?;
268 Ok(raw_obj)
269 }
270
271 pub(crate) fn resolve_unquoted_string(string: RawString) -> RawValue {
272 if let RawString::UnquotedString(unquoted) = string {
273 match &*unquoted {
274 "true" => RawValue::Boolean(true),
275 "false" => RawValue::Boolean(false),
276 "null" => RawValue::Null,
277 other => match serde_json::Number::from_str(other) {
278 Ok(number) => RawValue::Number(number),
279 Err(_) => RawValue::unquoted_string(unquoted),
280 },
281 }
282 } else {
283 RawValue::String(string)
284 }
285 }
286
287 #[allow(unused)]
288 pub(crate) fn parse_newline_comments(&mut self) -> Result<Vec<ObjectField>> {
289 let mut fields = vec![];
290 loop {
291 match self.parse_comment() {
292 Ok((ty, content)) => {
293 let comment = Comment::new(content, ty);
294 fields.push(ObjectField::newline_comment(comment));
295 }
296 Err(Error::Eof | Error::UnexpectedToken { .. }) => {
297 break Ok(fields);
298 }
299 Err(err) => {
300 return Err(err);
301 }
302 }
303 }
304 }
305}