1use winnow::stream::ContainsToken as _;
2use winnow::stream::FindSlice as _;
3use winnow::stream::Offset as _;
4use winnow::stream::Stream as _;
5
6use crate::decoder::StringBuilder;
7use crate::ErrorSink;
8use crate::Expected;
9use crate::ParseError;
10use crate::Raw;
11use crate::Span;
12
13const ALLOCATION_ERROR: &str = "could not allocate for string";
14
15#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
16pub enum ScalarKind {
17 String,
18 Boolean(bool),
19 DateTime,
20 Float,
21 Integer(IntegerRadix),
22}
23
24impl ScalarKind {
25 pub fn description(&self) -> &'static str {
26 match self {
27 Self::String => "string",
28 Self::Boolean(_) => "boolean",
29 Self::DateTime => "date-time",
30 Self::Float => "float",
31 Self::Integer(radix) => radix.description(),
32 }
33 }
34
35 pub fn invalid_description(&self) -> &'static str {
36 match self {
37 Self::String => "invalid string",
38 Self::Boolean(_) => "invalid boolean",
39 Self::DateTime => "invalid date-time",
40 Self::Float => "invalid float",
41 Self::Integer(radix) => radix.invalid_description(),
42 }
43 }
44}
45
46#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
47pub enum IntegerRadix {
48 #[default]
49 Dec,
50 Hex,
51 Oct,
52 Bin,
53}
54
55impl IntegerRadix {
56 pub fn description(&self) -> &'static str {
57 match self {
58 Self::Dec => "integer",
59 Self::Hex => "hexadecimal",
60 Self::Oct => "octal",
61 Self::Bin => "binary",
62 }
63 }
64
65 pub fn value(&self) -> u32 {
66 match self {
67 Self::Dec => 10,
68 Self::Hex => 16,
69 Self::Oct => 8,
70 Self::Bin => 2,
71 }
72 }
73
74 pub fn invalid_description(&self) -> &'static str {
75 match self {
76 Self::Dec => "invalid integer number",
77 Self::Hex => "invalid hexadecimal number",
78 Self::Oct => "invalid octal number",
79 Self::Bin => "invalid binary number",
80 }
81 }
82
83 fn validator(&self) -> fn(char) -> bool {
84 match self {
85 Self::Dec => |c| c.is_ascii_digit(),
86 Self::Hex => |c| c.is_ascii_hexdigit(),
87 Self::Oct => |c| matches!(c, '0'..='7'),
88 Self::Bin => |c| matches!(c, '0'..='1'),
89 }
90 }
91}
92
93pub(crate) fn decode_unquoted_scalar<'i>(
94 raw: Raw<'i>,
95 output: &mut dyn StringBuilder<'i>,
96 error: &mut dyn ErrorSink,
97) -> ScalarKind {
98 let s = raw.as_str();
99 let Some(first) = s.as_bytes().first() else {
100 return decode_invalid(raw, output, error);
101 };
102 match first {
103 b'+' | b'-' => {
105 let value = &raw.as_str()[1..];
106 decode_sign_prefix(raw, value, output, error)
107 }
108 b'_' => decode_datetime_or_float_or_integer(raw.as_str(), raw, output, error),
110 b'0' => decode_zero_prefix(raw.as_str(), false, raw, output, error),
112 b'1'..=b'9' => decode_datetime_or_float_or_integer(raw.as_str(), raw, output, error),
113 b'.' => {
115 let kind = ScalarKind::Float;
116 let stream = raw.as_str();
117 ensure_float(stream, raw, error);
118 decode_float_or_integer(stream, raw, kind, output, error)
119 }
120 b't' | b'T' => {
121 const SYMBOL: &str = "true";
122 let kind = ScalarKind::Boolean(true);
123 let expected = &[Expected::Literal(SYMBOL)];
124 decode_symbol(raw, SYMBOL, kind, expected, output, error)
125 }
126 b'f' | b'F' => {
127 const SYMBOL: &str = "false";
128 let kind = ScalarKind::Boolean(false);
129 let expected = &[Expected::Literal(SYMBOL)];
130 decode_symbol(raw, SYMBOL, kind, expected, output, error)
131 }
132 b'i' | b'I' => {
133 const SYMBOL: &str = "inf";
134 let kind = ScalarKind::Float;
135 let expected = &[Expected::Literal(SYMBOL)];
136 decode_symbol(raw, SYMBOL, kind, expected, output, error)
137 }
138 b'n' | b'N' => {
139 const SYMBOL: &str = "nan";
140 let kind = ScalarKind::Float;
141 let expected = &[Expected::Literal(SYMBOL)];
142 decode_symbol(raw, SYMBOL, kind, expected, output, error)
143 }
144 _ => decode_invalid(raw, output, error),
145 }
146}
147
148pub(crate) fn decode_sign_prefix<'i>(
149 raw: Raw<'i>,
150 value: &'i str,
151 output: &mut dyn StringBuilder<'i>,
152 error: &mut dyn ErrorSink,
153) -> ScalarKind {
154 let Some(first) = value.as_bytes().first() else {
155 return decode_invalid(raw, output, error);
156 };
157 match first {
158 b'+' | b'-' => {
160 let start = value.offset_from(&raw.as_str());
161 let end = start + 1;
162 error.report_error(
163 ParseError::new("redundant numeric sign")
164 .with_context(Span::new_unchecked(0, raw.len()))
165 .with_expected(&[])
166 .with_unexpected(Span::new_unchecked(start, end)),
167 );
168
169 let value = &value[1..];
170 decode_sign_prefix(raw, value, output, error)
171 }
172 b'_' => decode_datetime_or_float_or_integer(value, raw, output, error),
174 b'0' => decode_zero_prefix(value, true, raw, output, error),
176 b'1'..=b'9' => decode_datetime_or_float_or_integer(value, raw, output, error),
177 b'.' => {
179 let kind = ScalarKind::Float;
180 let stream = raw.as_str();
181 ensure_float(stream, raw, error);
182 decode_float_or_integer(stream, raw, kind, output, error)
183 }
184 b'i' | b'I' => {
185 const SYMBOL: &str = "inf";
186 let kind = ScalarKind::Float;
187 if value != SYMBOL {
188 let expected = &[Expected::Literal(SYMBOL)];
189 let start = value.offset_from(&raw.as_str());
190 let end = start + value.len();
191 error.report_error(
192 ParseError::new(kind.invalid_description())
193 .with_context(Span::new_unchecked(0, raw.len()))
194 .with_expected(expected)
195 .with_unexpected(Span::new_unchecked(start, end)),
196 );
197 decode_as(raw, SYMBOL, kind, output, error)
198 } else {
199 decode_as_is(raw, kind, output, error)
200 }
201 }
202 b'n' | b'N' => {
203 const SYMBOL: &str = "nan";
204 let kind = ScalarKind::Float;
205 if value != SYMBOL {
206 let expected = &[Expected::Literal(SYMBOL)];
207 let start = value.offset_from(&raw.as_str());
208 let end = start + value.len();
209 error.report_error(
210 ParseError::new(kind.invalid_description())
211 .with_context(Span::new_unchecked(0, raw.len()))
212 .with_expected(expected)
213 .with_unexpected(Span::new_unchecked(start, end)),
214 );
215 decode_as(raw, SYMBOL, kind, output, error)
216 } else {
217 decode_as_is(raw, kind, output, error)
218 }
219 }
220 _ => decode_invalid(raw, output, error),
221 }
222}
223
224pub(crate) fn decode_zero_prefix<'i>(
225 value: &'i str,
226 signed: bool,
227 raw: Raw<'i>,
228 output: &mut dyn StringBuilder<'i>,
229 error: &mut dyn ErrorSink,
230) -> ScalarKind {
231 debug_assert_eq!(value.as_bytes()[0], b'0');
232 if value.len() == 1 {
233 let kind = ScalarKind::Integer(IntegerRadix::Dec);
234 decode_float_or_integer(raw.as_str(), raw, kind, output, error)
236 } else {
237 let radix = value.as_bytes()[1];
238 match radix {
239 b'x' | b'X' => {
240 if signed {
241 error.report_error(
242 ParseError::new("integers with a radix cannot be signed")
243 .with_context(Span::new_unchecked(0, raw.len()))
244 .with_expected(&[])
245 .with_unexpected(Span::new_unchecked(0, 1)),
246 );
247 }
248 if radix == b'X' {
249 let start = value.offset_from(&raw.as_str());
250 let end = start + 2;
251 error.report_error(
252 ParseError::new("radix must be lowercase")
253 .with_context(Span::new_unchecked(0, raw.len()))
254 .with_expected(&[Expected::Literal("0x")])
255 .with_unexpected(Span::new_unchecked(start, end)),
256 );
257 }
258 let radix = IntegerRadix::Hex;
259 let kind = ScalarKind::Integer(radix);
260 let stream = &value[2..];
261 ensure_radixed_value(stream, raw, radix, error);
262 decode_float_or_integer(stream, raw, kind, output, error)
263 }
264 b'o' | b'O' => {
265 if signed {
266 error.report_error(
267 ParseError::new("integers with a radix cannot be signed")
268 .with_context(Span::new_unchecked(0, raw.len()))
269 .with_expected(&[])
270 .with_unexpected(Span::new_unchecked(0, 1)),
271 );
272 }
273 if radix == b'O' {
274 let start = value.offset_from(&raw.as_str());
275 let end = start + 2;
276 error.report_error(
277 ParseError::new("radix must be lowercase")
278 .with_context(Span::new_unchecked(0, raw.len()))
279 .with_expected(&[Expected::Literal("0o")])
280 .with_unexpected(Span::new_unchecked(start, end)),
281 );
282 }
283 let radix = IntegerRadix::Oct;
284 let kind = ScalarKind::Integer(radix);
285 let stream = &value[2..];
286 ensure_radixed_value(stream, raw, radix, error);
287 decode_float_or_integer(stream, raw, kind, output, error)
288 }
289 b'b' | b'B' => {
290 if signed {
291 error.report_error(
292 ParseError::new("integers with a radix cannot be signed")
293 .with_context(Span::new_unchecked(0, raw.len()))
294 .with_expected(&[])
295 .with_unexpected(Span::new_unchecked(0, 1)),
296 );
297 }
298 if radix == b'B' {
299 let start = value.offset_from(&raw.as_str());
300 let end = start + 2;
301 error.report_error(
302 ParseError::new("radix must be lowercase")
303 .with_context(Span::new_unchecked(0, raw.len()))
304 .with_expected(&[Expected::Literal("0b")])
305 .with_unexpected(Span::new_unchecked(start, end)),
306 );
307 }
308 let radix = IntegerRadix::Bin;
309 let kind = ScalarKind::Integer(radix);
310 let stream = &value[2..];
311 ensure_radixed_value(stream, raw, radix, error);
312 decode_float_or_integer(stream, raw, kind, output, error)
313 }
314 b'd' | b'D' => {
315 if signed {
316 error.report_error(
317 ParseError::new("integers with a radix cannot be signed")
318 .with_context(Span::new_unchecked(0, raw.len()))
319 .with_expected(&[])
320 .with_unexpected(Span::new_unchecked(0, 1)),
321 );
322 }
323 let radix = IntegerRadix::Dec;
324 let kind = ScalarKind::Integer(radix);
325 let stream = &value[2..];
326 error.report_error(
327 ParseError::new("redundant integer number prefix")
328 .with_context(Span::new_unchecked(0, raw.len()))
329 .with_expected(&[])
330 .with_unexpected(Span::new_unchecked(0, 2)),
331 );
332 ensure_radixed_value(stream, raw, radix, error);
333 decode_float_or_integer(stream, raw, kind, output, error)
334 }
335 _ => decode_datetime_or_float_or_integer(value, raw, output, error),
336 }
337 }
338}
339
340pub(crate) fn decode_datetime_or_float_or_integer<'i>(
341 value: &'i str,
342 raw: Raw<'i>,
343 output: &mut dyn StringBuilder<'i>,
344 error: &mut dyn ErrorSink,
345) -> ScalarKind {
346 let Some(digit_end) = value
347 .as_bytes()
348 .offset_for(|b| !(b'0'..=b'9').contains_token(b))
349 else {
350 let kind = ScalarKind::Integer(IntegerRadix::Dec);
351 let stream = raw.as_str();
352 ensure_no_leading_zero(value, raw, error);
353 return decode_float_or_integer(stream, raw, kind, output, error);
354 };
355
356 #[cfg(feature = "unsafe")] let rest = unsafe { &value.get_unchecked(digit_end..) };
358 #[cfg(not(feature = "unsafe"))]
359 let rest = &value[digit_end..];
360
361 if rest.starts_with("-") || rest.starts_with(":") {
362 decode_as_is(raw, ScalarKind::DateTime, output, error)
363 } else if rest.contains(" ") {
364 decode_invalid(raw, output, error)
365 } else if is_float(rest) {
366 let kind = ScalarKind::Float;
367 let stream = raw.as_str();
368 ensure_float(value, raw, error);
369 decode_float_or_integer(stream, raw, kind, output, error)
370 } else if rest.starts_with("_") {
371 let kind = ScalarKind::Integer(IntegerRadix::Dec);
372 let stream = raw.as_str();
373 ensure_no_leading_zero(value, raw, error);
374 decode_float_or_integer(stream, raw, kind, output, error)
375 } else {
376 decode_invalid(raw, output, error)
377 }
378}
379
380pub(crate) fn ensure_float<'i>(mut value: &'i str, raw: Raw<'i>, error: &mut dyn ErrorSink) {
394 ensure_dec_uint(&mut value, raw, false, "invalid mantissa", error);
395
396 if value.starts_with(".") {
397 let _ = value.next_token();
398 ensure_dec_uint(&mut value, raw, true, "invalid fraction", error);
399 }
400
401 if value.starts_with(['e', 'E']) {
402 let _ = value.next_token();
403 if value.starts_with(['+', '-']) {
404 let _ = value.next_token();
405 }
406 ensure_dec_uint(&mut value, raw, true, "invalid exponent", error);
407 }
408
409 if !value.is_empty() {
410 let start = value.offset_from(&raw.as_str());
411 let end = raw.len();
412 error.report_error(
413 ParseError::new(ScalarKind::Float.invalid_description())
414 .with_context(Span::new_unchecked(0, raw.len()))
415 .with_expected(&[])
416 .with_unexpected(Span::new_unchecked(start, end)),
417 );
418 }
419}
420
421pub(crate) fn ensure_dec_uint<'i>(
422 value: &mut &'i str,
423 raw: Raw<'i>,
424 zero_prefix: bool,
425 invalid_description: &'static str,
426 error: &mut dyn ErrorSink,
427) {
428 let start = *value;
429 let mut digit_count = 0;
430 while let Some(current) = value.chars().next() {
431 if current.is_ascii_digit() {
432 digit_count += 1;
433 } else if current == '_' {
434 } else {
435 break;
436 }
437 let _ = value.next_token();
438 }
439
440 match digit_count {
441 0 => {
442 let start = start.offset_from(&raw.as_str());
443 let end = start;
444 error.report_error(
445 ParseError::new(invalid_description)
446 .with_context(Span::new_unchecked(0, raw.len()))
447 .with_expected(&[Expected::Description("digits")])
448 .with_unexpected(Span::new_unchecked(start, end)),
449 );
450 }
451 1 => {}
452 _ if start.starts_with("0") && !zero_prefix => {
453 let start = start.offset_from(&raw.as_str());
454 let end = start + 1;
455 error.report_error(
456 ParseError::new("unexpected leading zero")
457 .with_context(Span::new_unchecked(0, raw.len()))
458 .with_expected(&[])
459 .with_unexpected(Span::new_unchecked(start, end)),
460 );
461 }
462 _ => {}
463 }
464}
465
466pub(crate) fn ensure_no_leading_zero<'i>(value: &'i str, raw: Raw<'i>, error: &mut dyn ErrorSink) {
467 if value.starts_with("0") {
468 let start = value.offset_from(&raw.as_str());
469 let end = start + 1;
470 error.report_error(
471 ParseError::new("unexpected leading zero")
472 .with_context(Span::new_unchecked(0, raw.len()))
473 .with_expected(&[])
474 .with_unexpected(Span::new_unchecked(start, end)),
475 );
476 }
477}
478
479pub(crate) fn ensure_radixed_value(
480 value: &str,
481 raw: Raw<'_>,
482 radix: IntegerRadix,
483 error: &mut dyn ErrorSink,
484) {
485 let invalid = ['+', '-'];
486 let value = if let Some(value) = value.strip_prefix(invalid) {
487 let pos = raw.as_str().find(invalid).unwrap();
488 error.report_error(
489 ParseError::new("unexpected sign")
490 .with_context(Span::new_unchecked(0, raw.len()))
491 .with_expected(&[])
492 .with_unexpected(Span::new_unchecked(pos, pos + 1)),
493 );
494 value
495 } else {
496 value
497 };
498
499 let valid = radix.validator();
500 for (index, c) in value.char_indices() {
501 if !valid(c) && c != '_' {
502 let pos = value.offset_from(&raw.as_str()) + index;
503 error.report_error(
504 ParseError::new(radix.invalid_description())
505 .with_context(Span::new_unchecked(0, raw.len()))
506 .with_unexpected(Span::new_unchecked(pos, pos)),
507 );
508 }
509 }
510}
511
512pub(crate) fn decode_float_or_integer<'i>(
513 stream: &'i str,
514 raw: Raw<'i>,
515 kind: ScalarKind,
516 output: &mut dyn StringBuilder<'i>,
517 error: &mut dyn ErrorSink,
518) -> ScalarKind {
519 output.clear();
520
521 let underscore = "_";
522
523 if has_underscore(stream) {
524 if stream.starts_with(underscore) {
525 error.report_error(
526 ParseError::new("`_` may only go between digits")
527 .with_context(Span::new_unchecked(0, raw.len()))
528 .with_expected(&[])
529 .with_unexpected(Span::new_unchecked(0, underscore.len())),
530 );
531 }
532 if 1 < stream.len() && stream.ends_with(underscore) {
533 let start = stream.offset_from(&raw.as_str());
534 let end = start + stream.len();
535 error.report_error(
536 ParseError::new("`_` may only go between digits")
537 .with_context(Span::new_unchecked(0, raw.len()))
538 .with_expected(&[])
539 .with_unexpected(Span::new_unchecked(end - underscore.len(), end)),
540 );
541 }
542
543 for part in stream.split(underscore) {
544 let part_start = part.offset_from(&raw.as_str());
545 let part_end = part_start + part.len();
546
547 if 0 < part_start {
548 let first = part.as_bytes().first().copied().unwrap_or(b'0');
549 if !is_any_digit(first, kind) {
550 let start = part_start - 1;
551 let end = part_start;
552 debug_assert_eq!(&raw.as_str()[start..end], underscore);
553 error.report_error(
554 ParseError::new("`_` may only go between digits")
555 .with_context(Span::new_unchecked(0, raw.len()))
556 .with_unexpected(Span::new_unchecked(start, end)),
557 );
558 }
559 }
560 if 1 < part.len() && part_end < raw.len() {
561 let last = part.as_bytes().last().copied().unwrap_or(b'0');
562 if !is_any_digit(last, kind) {
563 let start = part_end;
564 let end = start + underscore.len();
565 debug_assert_eq!(&raw.as_str()[start..end], underscore);
566 error.report_error(
567 ParseError::new("`_` may only go between digits")
568 .with_context(Span::new_unchecked(0, raw.len()))
569 .with_unexpected(Span::new_unchecked(start, end)),
570 );
571 }
572 }
573
574 if part.is_empty() && part_start != 0 && part_end != raw.len() {
575 let start = part_start;
576 let end = start + 1;
577 error.report_error(
578 ParseError::new("`_` may only go between digits")
579 .with_context(Span::new_unchecked(0, raw.len()))
580 .with_unexpected(Span::new_unchecked(start, end)),
581 );
582 }
583
584 if !part.is_empty() && !output.push_str(part) {
585 error.report_error(
586 ParseError::new(ALLOCATION_ERROR)
587 .with_unexpected(Span::new_unchecked(part_start, part_end)),
588 );
589 }
590 }
591 } else {
592 if !output.push_str(stream) {
593 error.report_error(
594 ParseError::new(ALLOCATION_ERROR)
595 .with_unexpected(Span::new_unchecked(0, raw.len())),
596 );
597 }
598 }
599
600 kind
601}
602
603fn is_any_digit(b: u8, kind: ScalarKind) -> bool {
604 if kind == ScalarKind::Float {
605 is_dec_integer_digit(b)
606 } else {
607 is_any_integer_digit(b)
608 }
609}
610
611fn is_any_integer_digit(b: u8) -> bool {
612 (b'0'..=b'9', b'a'..=b'f', b'A'..=b'F').contains_token(b)
613}
614
615fn is_dec_integer_digit(b: u8) -> bool {
616 (b'0'..=b'9').contains_token(b)
617}
618
619fn has_underscore(raw: &str) -> bool {
620 raw.as_bytes().find_slice(b'_').is_some()
621}
622
623fn is_float(raw: &str) -> bool {
624 raw.as_bytes().find_slice((b'.', b'e', b'E')).is_some()
625}
626
627pub(crate) fn decode_as_is<'i>(
628 raw: Raw<'i>,
629 kind: ScalarKind,
630 output: &mut dyn StringBuilder<'i>,
631 error: &mut dyn ErrorSink,
632) -> ScalarKind {
633 let kind = decode_as(raw, raw.as_str(), kind, output, error);
634 kind
635}
636
637pub(crate) fn decode_as<'i>(
638 raw: Raw<'i>,
639 symbol: &'i str,
640 kind: ScalarKind,
641 output: &mut dyn StringBuilder<'i>,
642 error: &mut dyn ErrorSink,
643) -> ScalarKind {
644 output.clear();
645 if !output.push_str(symbol) {
646 error.report_error(
647 ParseError::new(ALLOCATION_ERROR).with_unexpected(Span::new_unchecked(0, raw.len())),
648 );
649 }
650 kind
651}
652
653pub(crate) fn decode_symbol<'i>(
654 raw: Raw<'i>,
655 symbol: &'static str,
656 kind: ScalarKind,
657 expected: &'static [Expected],
658 output: &mut dyn StringBuilder<'i>,
659 error: &mut dyn ErrorSink,
660) -> ScalarKind {
661 if raw.as_str() != symbol {
662 if raw.as_str().contains(" ") {
663 return decode_invalid(raw, output, error);
664 } else {
665 error.report_error(
666 ParseError::new(kind.invalid_description())
667 .with_context(Span::new_unchecked(0, raw.len()))
668 .with_expected(expected)
669 .with_unexpected(Span::new_unchecked(0, raw.len())),
670 );
671 }
672 }
673
674 decode_as(raw, symbol, kind, output, error)
675}
676
677pub(crate) fn decode_invalid<'i>(
678 raw: Raw<'i>,
679 output: &mut dyn StringBuilder<'i>,
680 error: &mut dyn ErrorSink,
681) -> ScalarKind {
682 if raw.as_str().ends_with("'''") {
683 error.report_error(
684 ParseError::new("missing opening quote")
685 .with_context(Span::new_unchecked(0, raw.len()))
686 .with_expected(&[Expected::Literal(r#"'''"#)])
687 .with_unexpected(Span::new_unchecked(0, 0)),
688 );
689 } else if raw.as_str().ends_with(r#"""""#) {
690 error.report_error(
691 ParseError::new("missing opening quote")
692 .with_context(Span::new_unchecked(0, raw.len()))
693 .with_expected(&[Expected::Description("multi-line basic string")])
694 .with_expected(&[Expected::Literal(r#"""""#)])
695 .with_unexpected(Span::new_unchecked(0, 0)),
696 );
697 } else if raw.as_str().ends_with("'") {
698 error.report_error(
699 ParseError::new("missing opening quote")
700 .with_context(Span::new_unchecked(0, raw.len()))
701 .with_expected(&[Expected::Literal(r#"'"#)])
702 .with_unexpected(Span::new_unchecked(0, 0)),
703 );
704 } else if raw.as_str().ends_with(r#"""#) {
705 error.report_error(
706 ParseError::new("missing opening quote")
707 .with_context(Span::new_unchecked(0, raw.len()))
708 .with_expected(&[Expected::Literal(r#"""#)])
709 .with_unexpected(Span::new_unchecked(0, 0)),
710 );
711 } else {
712 error.report_error(
713 ParseError::new("string values must be quoted")
714 .with_context(Span::new_unchecked(0, raw.len()))
715 .with_expected(&[Expected::Description("literal string")])
716 .with_unexpected(Span::new_unchecked(0, raw.len())),
717 );
718 }
719
720 output.clear();
721 if !output.push_str(raw.as_str()) {
722 error.report_error(
723 ParseError::new(ALLOCATION_ERROR).with_unexpected(Span::new_unchecked(0, raw.len())),
724 );
725 }
726 ScalarKind::String
727}