v2 / vlib / x / json2 / decode.v
1562 lines · 1401 sloc · 43.96 KB · b4339f8d50e1ed03c54114c6af20cff8d153a108
Raw
1module json2
2
3import strconv
4import time
5
6const null_in_string = 'null'
7
8const true_in_string = 'true'
9
10const false_in_string = 'false'
11
12const float_zero_in_string = '0.0'
13
14const whitespace_chars = [` `, `\t`, `\n`, `\r`]!
15
16// Node represents a node in a linked list to store ValueInfo.
17struct Node[T] {
18mut:
19 value T
20 next &Node[T] = unsafe { nil } // next is the next node in the linked list.
21}
22
23// ValueInfo represents the position and length of a value, such as string, number, array, object key, and object value in a JSON string.
24struct ValueInfo {
25 position int // The position of the value in the JSON string.
26 value_kind ValueKind // The kind of the value.
27mut:
28 length int // The length of the value in the JSON string.
29}
30
31struct DecoderFieldInfo {
32 key_name string
33
34 is_omitempty bool
35 is_skip bool
36 is_required bool
37 is_raw bool
38}
39
40@[markused]
41struct StructFieldInfo {
42 json_name_ptr voidptr
43 json_name_len int
44 is_omitempty bool
45 is_skip bool
46 is_required bool
47 is_raw bool
48}
49
50struct StructKeyDecodeResult[T] {
51 matched bool
52 value T
53}
54
55// DecoderOptions provides options for JSON decoding.
56// By default, decoding is lenient. Use `strict: true` for strict JSON spec compliance.
57@[markused; params]
58pub struct DecoderOptions {
59pub:
60 // In strict mode, quoted strings are not accepted as numbers.
61 // For example, '"123"' will fail to decode as int in strict mode,
62 // but will succeed in default mode.
63 strict bool
64}
65
66// Decoder is the internal decoding state.
67@[markused]
68struct Decoder {
69 json string // json is the JSON data to be decoded.
70 strict bool // strict mode rejects quoted strings as numbers
71mut:
72 values_info LinkedList[ValueInfo] // A linked list to store ValueInfo.
73 checker_idx int // checker_idx is the current index of the decoder.
74 current_node &Node[ValueInfo] = unsafe { nil } // The current node in the linked list.
75}
76
77// LinkedList represents a linked list to store ValueInfo.
78struct LinkedList[T] {
79mut:
80 head &Node[T] = unsafe { nil } // head is the first node in the linked list.
81 tail &Node[T] = unsafe { nil } // tail is the last node in the linked list.
82 len int // len is the length of the linked list.
83}
84
85// push adds a new element to the linked list.
86fn (mut list LinkedList[T]) push(value T) {
87 new_node := &Node[T]{
88 value: value
89 }
90 if list.head == unsafe { nil } {
91 list.head = new_node
92 list.tail = new_node
93 } else {
94 list.tail.next = new_node
95 list.tail = new_node
96 }
97 list.len++
98}
99
100// last returns the last element added to the linked list.
101fn (list &LinkedList[T]) last() &T {
102 return &list.tail.value
103}
104
105// str returns a string representation of the linked list.
106fn (list &LinkedList[ValueInfo]) str() string {
107 mut result_buffer := []u8{}
108 mut current := list.head
109 for current != unsafe { nil } {
110 value_kind_as_string := current.value.value_kind.str()
111 unsafe { result_buffer.push_many(value_kind_as_string.str, value_kind_as_string.len) }
112 result_buffer << u8(` `)
113
114 current = current.next
115 }
116 return result_buffer.bytestr()
117}
118
119@[unsafe]
120fn (list &LinkedList[T]) free() {
121 mut current := list.head
122 for current != unsafe { nil } {
123 mut next := current.next
124 current.next = unsafe { nil }
125 unsafe { free(current) }
126 current = next
127 }
128 list.head = unsafe { nil }
129 list.tail = unsafe { nil }
130 list.len = 0
131}
132
133const max_context_length = 50
134const max_extra_characters = 5
135const tab_width = 8
136
137pub struct JsonDecodeError {
138 Error
139 context string
140pub:
141 message string
142
143 line int
144 character int
145}
146
147fn (e JsonDecodeError) msg() string {
148 return '\n${e.line}:${e.character}: Invalid json: ${e.message}\n${e.context}'
149}
150
151// checker_error generates a checker error message showing the position in the json string
152@[markused]
153fn (mut checker Decoder) checker_error(message string) ! {
154 position := checker.checker_idx
155
156 mut line_number := 0
157 mut character_number := 0
158 mut last_newline := 0
159
160 for i := position - 1; i >= 0; i-- {
161 if last_newline == 0 {
162 if checker.json[i] == `\n` {
163 last_newline = i + 1
164 } else if checker.json[i] == `\t` {
165 character_number += tab_width
166 } else {
167 character_number++
168 }
169 }
170 if checker.json[i] == `\n` {
171 line_number++
172 }
173 }
174
175 cutoff := character_number > max_context_length
176
177 // either start of string, last newline or a limited amount of characters
178 context_start := if cutoff { position - max_context_length } else { last_newline }
179
180 // print some extra characters
181 mut context_end := int_min(checker.json.len, position + max_extra_characters)
182 context_end_newline := checker.json[position..context_end].index_u8(`\n`)
183
184 if context_end_newline != -1 {
185 context_end = position + context_end_newline
186 }
187
188 mut context := ''
189
190 if cutoff {
191 context += '...'
192 }
193 context += checker.json[context_start..position]
194 context += '\e[31m${checker.json[position].ascii_str()}\e[0m'
195 context += checker.json[position + 1..context_end]
196 context += '\n'
197
198 if cutoff {
199 context += ' '.repeat(max_context_length + 3)
200 } else {
201 context += ' '.repeat(character_number)
202 }
203 context += '\e[31m^\e[0m'
204
205 return JsonDecodeError{
206 context: context
207 message: 'Syntax: ${message}'
208 line: line_number + 1
209 character: character_number + 1
210 }
211}
212
213// decode_error generates a decoding error from the decoding stage
214@[markused]
215fn (mut decoder Decoder) decode_error(message string) ! {
216 mut error_info := ValueInfo{}
217 if decoder.current_node != unsafe { nil } {
218 error_info = decoder.current_node.value
219 } else {
220 error_info = decoder.values_info.tail.value
221 }
222
223 start := error_info.position
224 end := start + int_min(error_info.length, max_context_length)
225
226 mut line_number := 0
227 mut character_number := 0
228 mut last_newline := 0
229
230 for i := start - 1; i >= 0; i-- {
231 if last_newline == 0 {
232 if decoder.json[i] == `\n` {
233 last_newline = i + 1
234 } else if decoder.json[i] == `\t` {
235 character_number += tab_width
236 } else {
237 character_number++
238 }
239 }
240 if decoder.json[i] == `\n` {
241 line_number++
242 }
243 }
244
245 cutoff := character_number > max_context_length
246
247 // either start of string, last newline or a limited amount of characters
248 context_start := if cutoff { start - max_context_length } else { last_newline }
249
250 // print some extra characters
251 mut context_end := int_min(decoder.json.len, end + max_extra_characters)
252 context_end_newline := decoder.json[end..context_end].index_u8(`\n`)
253
254 if context_end_newline != -1 {
255 context_end = end + context_end_newline
256 }
257
258 mut context := ''
259
260 if cutoff {
261 context += '...'
262 }
263 context += decoder.json[context_start..start]
264 context += '\e[31m${decoder.json[start..end]}\e[0m'
265 context += decoder.json[end..context_end]
266 context += '\n'
267
268 if cutoff {
269 context += ' '.repeat(max_context_length + 3)
270 } else {
271 context += ' '.repeat(character_number)
272 }
273 context += '\e[31m${'~'.repeat(error_info.length)}\e[0m'
274
275 return JsonDecodeError{
276 context: context
277 message: 'Data: ${message}'
278 line: line_number + 1
279 character: character_number + 1
280 }
281}
282
283// decode decodes a JSON string into a specified type.
284// By default, decoding is lenient. Use `strict: true` for strict JSON spec compliance.
285@[manualfree]
286pub fn decode[T](val string, params DecoderOptions) !T {
287 if val == '' {
288 return JsonDecodeError{
289 message: 'empty string'
290 line: 1
291 character: 1
292 }
293 }
294 mut decoder := Decoder{
295 json: val
296 strict: params.strict
297 }
298
299 decoder.check_json_format()!
300
301 mut result := T{}
302 decoder.current_node = decoder.values_info.head
303 $if T.unaliased_typ is $array_dynamic {
304 result.clear()
305 decoder.decode_array(mut result)!
306 } $else $if T.unaliased_typ is $map {
307 decoder.decode_map(mut result)!
308 } $else $if T.indirections == 1 {
309 if decoder.current_node.value.value_kind == .null {
310 if decoder.current_node != unsafe { nil } {
311 decoder.current_node = decoder.current_node.next
312 }
313 } else {
314 mut decoded_ptr := create_decoded_ptr(result)
315 decoder.decode_value(mut decoded_ptr)!
316 result = decoded_ptr
317 }
318 } $else {
319 decoder.decode_value(mut result)!
320 }
321 return result
322}
323
324fn get_dynamic_from_element[T](_t T) []T {
325 return []T{}
326}
327
328fn create_decoded_ptr[T](_ &T) &T {
329 $if T is $interface {
330 return unsafe { nil }
331 } $else $if T.unaliased_typ is voidptr {
332 return unsafe { nil }
333 } $else {
334 return unsafe { &T(vcalloc(sizeof(T))) }
335 }
336}
337
338fn create_decoded_option_ptr[U](_ ?&U) &U {
339 return &U{}
340}
341
342fn decoder_field_infos[T]() []DecoderFieldInfo {
343 mut field_infos := []DecoderFieldInfo{}
344 $for field in T.fields {
345 mut key_name := field.name
346 mut is_json_skip := false
347 for attr in field.attrs {
348 if start, end := json_attr_value_range(attr) {
349 if end <= start {
350 continue
351 }
352 if end == start + 1 && attr[start] == `-` {
353 is_json_skip = true
354 break
355 }
356 key_name = attr[start..end]
357 break
358 }
359 }
360 field_infos << DecoderFieldInfo{
361 key_name: key_name
362 is_omitempty: field.attrs.contains('omitempty')
363 is_skip: field.attrs.contains('skip') || is_json_skip
364 is_required: field.attrs.contains('required')
365 is_raw: field.attrs.contains('raw')
366 }
367 }
368 return field_infos
369}
370
371@[manualfree; unsafe]
372fn (mut decoder Decoder) cached_struct_field_infos[T]() []StructFieldInfo {
373 static field_infos := &[]StructFieldInfo(nil)
374 if field_infos == nil {
375 field_infos = &[]StructFieldInfo{}
376 $for field in T.fields {
377 mut json_name_str := field.name.str
378 mut json_name_len := field.name.len
379 mut is_json_skip := false
380 for attr in field.attrs {
381 if start, end := json_attr_value_range(attr) {
382 if end <= start {
383 continue
384 }
385 if end == start + 1 && attr[start] == `-` {
386 is_json_skip = true
387 break
388 }
389 json_name_str = unsafe { attr.str + start }
390 json_name_len = end - start
391 break
392 }
393 }
394 field_infos << StructFieldInfo{
395 json_name_ptr: voidptr(json_name_str)
396 json_name_len: json_name_len
397 is_omitempty: field.attrs.contains('omitempty')
398 is_skip: field.attrs.contains('skip') || is_json_skip
399 is_required: field.attrs.contains('required')
400 is_raw: field.attrs.contains('raw')
401 }
402 }
403 }
404 return *field_infos
405}
406
407@[inline; markused]
408fn struct_field_is_decoded(decoded_mask u64, decoded_fields []bool, field_idx int) bool {
409 if field_idx < 64 {
410 return (decoded_mask & (u64(1) << u64(field_idx))) != 0
411 }
412 return decoded_fields[field_idx]
413}
414
415@[inline; markused]
416fn mark_struct_field_decoded(decoded_mask u64, mut decoded_fields []bool, field_idx int) u64 {
417 if field_idx < 64 {
418 return decoded_mask | (u64(1) << u64(field_idx))
419 }
420 decoded_fields[field_idx] = true
421 return decoded_mask
422}
423
424@[inline]
425fn (decoder &Decoder) json_key_matches(key_info ValueInfo, key_name string) bool {
426 if key_info.length - 2 != key_name.len {
427 return false
428 }
429 return unsafe {
430 vmemcmp(decoder.json.str + key_info.position + 1, key_name.str, key_name.len) == 0
431 }
432}
433
434@[inline; markused]
435fn (decoder &Decoder) is_empty_value(value_info ValueInfo) bool {
436 match value_info.value_kind {
437 .null {
438 return true
439 }
440 .string {
441 return value_info.length == 2
442 }
443 .number {
444 if decoder.json[value_info.position] == `0` {
445 if value_info.length == 1 {
446 return true
447 }
448 if value_info.length == 3 {
449 return unsafe {
450 vmemcmp(decoder.json.str + value_info.position, float_zero_in_string.str,
451 float_zero_in_string.len) == 0
452 }
453 }
454 }
455 }
456 else {}
457 }
458
459 return false
460}
461
462@[markused]
463fn (mut decoder Decoder) skip_current_value() {
464 if decoder.current_node == unsafe { nil } {
465 return
466 }
467 value_end := decoder.current_node.value.position + decoder.current_node.value.length
468 for decoder.current_node != unsafe { nil } && decoder.current_node.value.position < value_end {
469 decoder.current_node = decoder.current_node.next
470 }
471}
472
473@[manualfree]
474fn decode_struct_key[T](mut decoder Decoder, val T, key_info ValueInfo, prefix string, mut seen_required []string) !StructKeyDecodeResult[T] {
475 field_infos := decoder_field_infos[T]()
476 mut new_val := val
477 mut i := 0
478 $for field in T.fields {
479 field_info := field_infos[i]
480 $if !field.is_embed {
481 if decoder.json_key_matches(key_info, field_info.key_name)
482 || (prefix != ''
483 && decoder.json_key_matches(key_info, prefix + field_info.key_name)) {
484 decoder.current_node = decoder.current_node.next
485
486 if field_info.is_skip {
487 if field_info.is_required {
488 seen_required << prefix + field.name
489 }
490 decoder.skip_current_value()
491 return StructKeyDecodeResult[T]{
492 matched: true
493 value: new_val
494 }
495 }
496
497 if field_info.is_omitempty && decoder.current_node != unsafe { nil }
498 && decoder.is_empty_value(decoder.current_node.value) {
499 decoder.skip_current_value()
500 return StructKeyDecodeResult[T]{
501 matched: true
502 value: new_val
503 }
504 }
505
506 if field_info.is_required {
507 seen_required << prefix + field.name
508 }
509
510 if field_info.is_raw {
511 $if field.unaliased_typ is $enum {
512 decoder.decode_error('`raw` attribute cannot be used with enum fields')!
513 } $else $if field.typ is ?string {
514 position := decoder.current_node.value.position
515 end := position + decoder.current_node.value.length
516
517 new_val.$(field.name) = decoder.json[position..end]
518 decoder.current_node = decoder.current_node.next
519
520 for {
521 if decoder.current_node == unsafe { nil }
522 || decoder.current_node.value.position + decoder.current_node.value.length >= end {
523 break
524 }
525 decoder.current_node = decoder.current_node.next
526 }
527 } $else $if field.typ is string {
528 position := decoder.current_node.value.position
529 end := position + decoder.current_node.value.length
530
531 new_val.$(field.name) = decoder.json[position..end]
532 decoder.current_node = decoder.current_node.next
533
534 for {
535 if decoder.current_node == unsafe { nil }
536 || decoder.current_node.value.position + decoder.current_node.value.length >= end {
537 break
538 }
539 decoder.current_node = decoder.current_node.next
540 }
541 } $else {
542 decoder.decode_error('`raw` attribute can only be used with string fields')!
543 }
544 } else {
545 $if field.typ is $option {
546 if decoder.current_node.value.value_kind == .null {
547 new_val.$(field.name) = none
548
549 if decoder.current_node != unsafe { nil } {
550 decoder.current_node = decoder.current_node.next
551 }
552 } else {
553 $if field.indirections == 1 {
554 mut decoded_ptr := create_decoded_option_ptr(new_val.$(field.name))
555 decoder.decode_value(mut decoded_ptr)!
556 new_val.$(field.name) = decoded_ptr
557 } $else {
558 mut unwrapped_val := create_value_from_optional(new_val.$(field.name)) or {
559 return StructKeyDecodeResult[T]{
560 matched: false
561 value: val
562 }
563 }
564 decoder.decode_value(mut unwrapped_val)!
565 new_val.$(field.name) = unwrapped_val
566 }
567 }
568 } $else $if field.unaliased_typ is $array_dynamic {
569 new_val.$(field.name).clear()
570 decoder.decode_array(mut new_val.$(field.name))!
571 } $else $if field.unaliased_typ is $map {
572 decoder.decode_map(mut new_val.$(field.name))!
573 } $else $if field.indirections == 1 {
574 if decoder.current_node.value.value_kind == .null {
575 new_val.$(field.name) = unsafe { nil }
576
577 if decoder.current_node != unsafe { nil } {
578 decoder.current_node = decoder.current_node.next
579 }
580 } else {
581 mut decoded_ptr := create_decoded_ptr(new_val.$(field.name))
582 decoder.decode_value(mut decoded_ptr)!
583 new_val.$(field.name) = decoded_ptr
584 }
585 } $else {
586 decoder.decode_value(mut new_val.$(field.name))!
587 }
588 }
589 return StructKeyDecodeResult[T]{
590 matched: true
591 value: new_val
592 }
593 }
594 }
595 i++
596 }
597 i = 0
598 $for field in T.fields {
599 field_info := field_infos[i]
600 $if field.is_embed {
601 if decoder.json_key_matches(key_info, field_info.key_name)
602 && decoder.current_node.next != unsafe { nil }
603 && decoder.current_node.next.value.value_kind == .object {
604 if field_info.is_required {
605 seen_required << prefix + field.name
606 }
607 decoder.current_node = decoder.current_node.next
608 decoder.decode_value(mut new_val.$(field.name))!
609 return StructKeyDecodeResult[T]{
610 matched: true
611 value: new_val
612 }
613 }
614 {
615 embed_result := decode_struct_key(mut decoder, new_val.$(field.name), key_info,
616
617 prefix + field.name + '.', mut seen_required)!
618 if embed_result.matched {
619 new_val.$(field.name) = embed_result.value
620 return StructKeyDecodeResult[T]{
621 matched: true
622 value: new_val
623 }
624 }
625 }
626 }
627 i++
628 }
629 return StructKeyDecodeResult[T]{
630 matched: false
631 value: val
632 }
633}
634
635fn check_required_struct_fields[T](mut decoder Decoder, val T, seen_required []string, prefix string) ! {
636 field_infos := decoder_field_infos[T]()
637 mut i := 0
638 $for field in T.fields {
639 field_info := field_infos[i]
640 if field_info.is_required && prefix + field.name !in seen_required {
641 decoder.decode_error('missing required field `${field.name}`')!
642 }
643 $if field.is_embed {
644 check_required_struct_fields(mut decoder, val.$(field.name), seen_required, prefix +
645 field.name + '.')!
646 }
647 i++
648 }
649}
650
651// decode_value decodes a value from the JSON nodes.
652@[manualfree]
653fn (mut decoder Decoder) decode_value[T](mut val T) ! {
654 $if T.unaliased_typ is voidptr {
655 // skip voidptr fields - they cannot be decoded from JSON
656 if decoder.current_node != unsafe { nil } {
657 decoder.current_node = decoder.current_node.next
658 }
659 return
660 } $else $if T is $interface {
661 // skip interface fields - they cannot be decoded from JSON
662 if decoder.current_node != unsafe { nil } {
663 decoder.current_node = decoder.current_node.next
664 }
665 return
666 } $else {
667 // Custom Decoders
668 $if val is StringDecoder {
669 struct_info := decoder.current_node.value
670
671 if struct_info.value_kind == .string {
672 val.from_json_string(decoder.json[struct_info.position + 1..struct_info.position +
673 struct_info.length - 1]) or {
674 decoder.decode_error('${typeof(val).name}: ${err.msg()}')!
675 }
676 if decoder.current_node != unsafe { nil } {
677 decoder.current_node = decoder.current_node.next
678 }
679
680 return
681 }
682 }
683 $if val is NumberDecoder {
684 struct_info := decoder.current_node.value
685
686 if struct_info.value_kind == .number {
687 val.from_json_number(decoder.json[struct_info.position..struct_info.position +
688 struct_info.length]) or {
689 decoder.decode_error('${typeof(val).name}: ${err.msg()}')!
690 }
691 if decoder.current_node != unsafe { nil } {
692 decoder.current_node = decoder.current_node.next
693 }
694
695 return
696 }
697 }
698 $if val is BooleanDecoder {
699 struct_info := decoder.current_node.value
700
701 if struct_info.value_kind == .boolean {
702 val.from_json_boolean(decoder.json[struct_info.position] == `t`)
703 if decoder.current_node != unsafe { nil } {
704 decoder.current_node = decoder.current_node.next
705 }
706
707 return
708 }
709 }
710 $if val is NullDecoder {
711 struct_info := decoder.current_node.value
712
713 if struct_info.value_kind == .null {
714 val.from_json_null()
715 if decoder.current_node != unsafe { nil } {
716 decoder.current_node = decoder.current_node.next
717 }
718
719 return
720 }
721 }
722 $if T.unaliased_typ is voidptr {
723 // skip voidptr fields - they cannot be decoded from JSON
724 if decoder.current_node != unsafe { nil } {
725 decoder.current_node = decoder.current_node.next
726 }
727 return
728 } $else $if T.unaliased_typ is string {
729 decoder.decode_string(mut val)!
730 } $else $if T.unaliased_typ is time.Time {
731 value_info := decoder.current_node.value
732 mut decoded_time := time.Time{}
733 if value_info.value_kind == .string {
734 decoded_time.from_json_string(decoder.json[value_info.position + 1..
735 value_info.position + value_info.length - 1]) or {
736 decoder.decode_error('${typeof(val).name}: ${err.msg()}')!
737 }
738 } else if value_info.value_kind == .number {
739 decoded_time.from_json_number(decoder.json[value_info.position..
740 value_info.position + value_info.length]) or {
741 decoder.decode_error('${typeof(val).name}: ${err.msg()}')!
742 }
743 } else {
744 decoder.decode_error('Expected string or number, but got ${value_info.value_kind}')!
745 }
746 val = T(decoded_time)
747 } $else $if T.unaliased_typ is $sumtype {
748 decoder.decode_sumtype(mut val)!
749 return
750 } $else $if T.unaliased_typ is $map {
751 decoder.decode_map(mut val)!
752 return
753 } $else $if T.unaliased_typ is $array_dynamic {
754 val.clear()
755 decoder.decode_array(mut val)!
756 // return to avoid the next increment of the current node
757 // this is because the current node is already incremented in the decode_array function
758 // remove this line will cause the current node to be incremented twice
759 // and bug recursive array decoding like `[][]int{}`
760 return
761 } $else $if T.unaliased_typ is $array_fixed {
762 mut dynamic_val := get_dynamic_from_element(val[0])
763
764 // avoid copying by pointing dynamic_val to val
765 unsafe {
766 dynamic_val.len = 0
767 dynamic_val.cap = val.len // ensures data wont reallocate
768 dynamic_val.data = &val
769 }
770 decoder.decode_array(mut dynamic_val)!
771
772 if dynamic_val.len != val.len {
773 decoder.decode_error('Fixed size array expected ${val.len} elements but got ${dynamic_val.len} elements')!
774 }
775 return
776 } $else $if T.unaliased_typ is $struct {
777 struct_info := decoder.current_node.value
778
779 if struct_info.value_kind == .object {
780 struct_position := struct_info.position
781 struct_end := struct_position + struct_info.length
782 mut has_embeds := false
783 $for field in T.fields {
784 $if field.is_embed {
785 has_embeds = true
786 }
787 }
788 decoder.current_node = decoder.current_node.next
789 if has_embeds {
790 mut seen_required := []string{}
791
792 // json object loop
793 for {
794 if decoder.current_node == unsafe { nil } {
795 break
796 }
797
798 key_info := decoder.current_node.value
799
800 if key_info.position >= struct_end {
801 break
802 }
803
804 decode_result := decode_struct_key(mut decoder, val, key_info, '', mut
805 seen_required)!
806 if decode_result.matched {
807 val = decode_result.value
808 } else {
809 // The key doesn't match any field in the struct, skip the entire value
810 // including all nested objects/arrays.
811 decoder.current_node = decoder.current_node.next
812 decoder.skip_current_value()
813 }
814 }
815
816 check_required_struct_fields(mut decoder, val, seen_required, '')!
817 } else {
818 field_infos := unsafe { decoder.cached_struct_field_infos[T]() }
819 mut decoded_mask := u64(0)
820 mut decoded_fields := []bool{}
821 if field_infos.len > 64 {
822 decoded_fields = []bool{len: field_infos.len}
823 }
824
825 mut field_idx := 0
826 // json object loop
827 for {
828 if decoder.current_node == unsafe { nil } {
829 break
830 }
831
832 key_info := decoder.current_node.value
833
834 if key_info.position >= struct_end {
835 break
836 }
837
838 mut matched := false
839 field_idx = 0
840 $for field in T.fields {
841 if !matched {
842 field_info := field_infos[field_idx]
843 field_can_match := (!field_info.is_skip || field_info.is_required)
844 && !(field_info.is_omitempty
845 && decoder.is_empty_value(decoder.current_node.next.value))
846 field_name_matches := key_info.length - 2 == field_info.json_name_len && unsafe {
847 vmemcmp(decoder.json.str + key_info.position + 1, field_info.json_name_ptr, field_info.json_name_len) == 0
848 }
849 if field_can_match && field_name_matches {
850 // value node
851 decoder.current_node = decoder.current_node.next
852
853 if field_info.is_skip {
854 // Preserve the existing inline decode behavior for `skip`+`required`.
855 decoded_mask = mark_struct_field_decoded(decoded_mask, mut
856 decoded_fields, field_idx)
857 if decoder.current_node != unsafe { nil } {
858 decoder.current_node = decoder.current_node.next
859 }
860 } else if field_info.is_raw {
861 $if field.unaliased_typ is $enum {
862 // workaround to avoid the error: enums can only be assigned `int` values
863 decoder.decode_error('`raw` attribute cannot be used with enum fields')!
864 } $else $if field.typ is ?string {
865 position := decoder.current_node.value.position
866 end := position + decoder.current_node.value.length
867
868 val.$(field.name) = decoder.json[position..end]
869 decoder.current_node = decoder.current_node.next
870
871 for {
872 if decoder.current_node == unsafe { nil }
873 || decoder.current_node.value.position + decoder.current_node.value.length >= end {
874 break
875 }
876 decoder.current_node = decoder.current_node.next
877 }
878 } $else $if field.typ is string {
879 position := decoder.current_node.value.position
880 end := position + decoder.current_node.value.length
881
882 val.$(field.name) = decoder.json[position..end]
883 decoder.current_node = decoder.current_node.next
884
885 for {
886 if decoder.current_node == unsafe { nil }
887 || decoder.current_node.value.position + decoder.current_node.value.length >= end {
888 break
889 }
890 decoder.current_node = decoder.current_node.next
891 }
892 } $else {
893 decoder.decode_error('`raw` attribute can only be used with string fields')!
894 }
895 } else {
896 $if field.typ is $option {
897 // it would be nicer to do this at the start of the function
898 // but options cant be passed to generic functions
899 if decoder.current_node.value.value_kind == .null {
900 val.$(field.name) = none
901
902 if decoder.current_node != unsafe { nil } {
903 decoder.current_node = decoder.current_node.next
904 }
905 } else {
906 $if field.indirections == 1 {
907 mut decoded_ptr :=
908 create_decoded_option_ptr(val.$(field.name))
909 decoder.decode_value(mut decoded_ptr)!
910 val.$(field.name) = decoded_ptr
911 } $else {
912 mut unwrapped_val := create_value_from_optional(val.$(field.name)) or {
913 return
914 }
915 decoder.decode_value(mut unwrapped_val)!
916 val.$(field.name) = unwrapped_val
917 }
918 }
919 } $else $if field.unaliased_typ is $array_dynamic {
920 val.$(field.name).clear()
921 decoder.decode_array(mut val.$(field.name))!
922 } $else $if field.unaliased_typ is $map {
923 decoder.decode_map(mut val.$(field.name))!
924 } $else $if field.indirections == 1 {
925 if decoder.current_node.value.value_kind == .null {
926 val.$(field.name) = unsafe { nil }
927
928 if decoder.current_node != unsafe { nil } {
929 decoder.current_node = decoder.current_node.next
930 }
931 } else {
932 mut decoded_ptr :=
933 create_decoded_ptr(val.$(field.name))
934 decoder.decode_value(mut decoded_ptr)!
935 val.$(field.name) = decoded_ptr
936 }
937 } $else {
938 mut decoded_field_value := val.$(field.name)
939 decoder.decode_value(mut decoded_field_value)!
940 $if field.unaliased_typ is $map {
941 val.$(field.name) = decoded_field_value.move()
942 } $else {
943 val.$(field.name) = decoded_field_value
944 }
945 }
946 }
947
948 decoded_mask = mark_struct_field_decoded(decoded_mask, mut
949 decoded_fields, field_idx)
950 matched = true
951 }
952 }
953 field_idx++
954 }
955 if !matched {
956 // The key doesn't match any field in the struct, skip the entire value
957 // including all nested objects/arrays.
958 decoder.current_node = decoder.current_node.next
959 decoder.skip_current_value()
960 }
961 }
962
963 // check if all required fields are present
964 field_idx = 0
965 $for field in T.fields {
966 field_info := field_infos[field_idx]
967 if field_info.is_required
968 && !struct_field_is_decoded(decoded_mask, decoded_fields, field_idx) {
969 decoder.decode_error('missing required field `${field.name}`')!
970 }
971 field_idx++
972 }
973 }
974 } else {
975 decoder.decode_error('Expected object, but got ${struct_info.value_kind}')!
976 }
977 return
978 } $else $if T.unaliased_typ is bool {
979 value_info := decoder.current_node.value
980
981 if value_info.value_kind != .boolean {
982 decoder.decode_error('Expected boolean, but got ${value_info.value_kind}')!
983 }
984
985 unsafe {
986 val = vmemcmp(decoder.json.str + value_info.position, c'true', 'true'.len) == 0
987 }
988 } $else $if T.unaliased_typ is $float || T.unaliased_typ is $int {
989 value_info := decoder.current_node.value
990
991 if value_info.value_kind == .number {
992 unsafe { decoder.decode_number(&val)! }
993 } else if value_info.value_kind == .string && !decoder.strict {
994 // In default mode, try to parse quoted strings as numbers
995 val = decoder.decode_number_from_string[T]()!
996 } else {
997 decoder.decode_error('Expected number, but got ${value_info.value_kind}')!
998 }
999 } $else $if T.unaliased_typ is $enum {
1000 decoder.decode_enum(mut val)!
1001 } $else {
1002 decoder.decode_error('cannot decode value with ${typeof(val).name} type')!
1003 }
1004
1005 if decoder.current_node != unsafe { nil } {
1006 decoder.current_node = decoder.current_node.next
1007 }
1008 } // $else (not voidptr / interface)
1009}
1010
1011fn (mut decoder Decoder) decode_string[T](mut val T) ! {
1012 _ = val
1013 string_info := decoder.current_node.value
1014
1015 if string_info.value_kind == .string {
1016 string_start := string_info.position + 1
1017 string_end := string_info.position + string_info.length - 1
1018 string_body := decoder.json[string_start..string_end]
1019 if string_body.index_u8(`\\`) == -1 {
1020 val = string_body
1021 return
1022 }
1023
1024 mut string_buffer := []u8{cap: string_info.length} // might be too long but most json strings don't contain many escape characters anyways
1025
1026 mut buffer_index := 1
1027 mut string_index := 1
1028
1029 for string_index < string_info.length - 1 {
1030 current_byte := decoder.json[string_info.position + string_index]
1031
1032 if current_byte == `\\` {
1033 // push all characters up to this point
1034 unsafe {
1035 string_buffer.push_many(decoder.json.str + string_info.position + buffer_index,
1036 string_index - buffer_index)
1037 }
1038
1039 string_index++
1040
1041 escaped_char := decoder.json[string_info.position + string_index]
1042
1043 string_index++
1044
1045 match escaped_char {
1046 `/`, `"`, `\\` {
1047 string_buffer << escaped_char
1048 }
1049 `b` {
1050 string_buffer << `\b`
1051 }
1052 `f` {
1053 string_buffer << `\f`
1054 }
1055 `n` {
1056 string_buffer << `\n`
1057 }
1058 `r` {
1059 string_buffer << `\r`
1060 }
1061 `t` {
1062 string_buffer << `\t`
1063 }
1064 `u` {
1065 unicode_point := rune(strconv.parse_uint(decoder.json[
1066 string_info.position + string_index..string_info.position +
1067 string_index + 4], 16, 32)!)
1068
1069 string_index += 4
1070
1071 if unicode_point < 0xD800 || unicode_point > 0xDFFF { // normal utf-8
1072 string_buffer << unicode_point.bytes()
1073 } else if unicode_point >= 0xDC00 { // trail surrogate -> invalid
1074 decoder.decode_error('Got trail surrogate: ${u32(unicode_point):04X} before head surrogate.')!
1075 } else { // head surrogate -> treat as utf-16
1076 if string_index > string_info.length - 6 {
1077 decoder.decode_error('Expected a trail surrogate after a head surrogate, but got no valid escape sequence.')!
1078 }
1079 if decoder.json[string_info.position + string_index..
1080 string_info.position + string_index + 2] != '\\u' {
1081 decoder.decode_error('Expected a trail surrogate after a head surrogate, but got no valid escape sequence.')!
1082 }
1083
1084 string_index += 2
1085
1086 unicode_point2 := rune(strconv.parse_uint(decoder.json[
1087 string_info.position + string_index..string_info.position +
1088 string_index + 4], 16, 32)!)
1089
1090 string_index += 4
1091
1092 if unicode_point2 < 0xDC00 {
1093 decoder.decode_error('Expected a trail surrogate after a head surrogate, but got ${u32(unicode_point):04X}.')!
1094 }
1095
1096 final_unicode_point := (unicode_point2 & 0x3FF) +
1097 ((unicode_point & 0x3FF) << 10) + 0x10000
1098 string_buffer << final_unicode_point.bytes()
1099 }
1100 }
1101 else {} // has already been checked
1102 }
1103
1104 buffer_index = string_index
1105 } else {
1106 string_index++
1107 }
1108 }
1109
1110 // push the rest
1111 unsafe {
1112 string_buffer.push_many(decoder.json.str + string_info.position + buffer_index,
1113 string_index - buffer_index)
1114 }
1115
1116 val = string_buffer.bytestr()
1117 } else {
1118 decoder.decode_error('Expected string, but got ${string_info.value_kind}')!
1119 }
1120}
1121
1122fn (mut decoder Decoder) decode_array[T](mut val []T) ! {
1123 $if T is $interface {
1124 decoder.skip_current_value()
1125 return
1126 } $else $if T.unaliased_typ is voidptr {
1127 decoder.skip_current_value()
1128 return
1129 } $else {
1130 array_info := decoder.current_node.value
1131
1132 if array_info.value_kind == .array {
1133 decoder.current_node = decoder.current_node.next
1134
1135 array_position := array_info.position
1136 array_end := array_position + array_info.length
1137
1138 for {
1139 if decoder.current_node == unsafe { nil }
1140 || decoder.current_node.value.position >= array_end {
1141 break
1142 }
1143
1144 mut array_element := T{}
1145
1146 $if T.indirections == 1 {
1147 if decoder.current_node.value.value_kind == .null {
1148 if decoder.current_node != unsafe { nil } {
1149 decoder.current_node = decoder.current_node.next
1150 }
1151 } else {
1152 mut decoded_ptr := create_decoded_ptr(array_element)
1153 decoder.decode_value(mut decoded_ptr)!
1154 array_element = decoded_ptr
1155 }
1156 } $else {
1157 decoder.decode_value(mut array_element)!
1158 }
1159
1160 val << array_element
1161 }
1162 } else {
1163 decoder.decode_error('Expected array, but got ${array_info.value_kind}')!
1164 }
1165 }
1166}
1167
1168fn (mut decoder Decoder) decode_map[V](mut val map[string]V) ! {
1169 $if V is $interface {
1170 decoder.skip_current_value()
1171 return
1172 } $else $if V.unaliased_typ is voidptr {
1173 decoder.skip_current_value()
1174 return
1175 } $else {
1176 map_info := decoder.current_node.value
1177
1178 if map_info.value_kind == .object {
1179 map_position := map_info.position
1180 map_end := map_position + map_info.length
1181
1182 decoder.current_node = decoder.current_node.next
1183 for {
1184 if decoder.current_node == unsafe { nil }
1185 || decoder.current_node.value.position >= map_end {
1186 break
1187 }
1188
1189 key_info := decoder.current_node.value
1190
1191 if key_info.position >= map_end {
1192 break
1193 }
1194
1195 key_str := decoder.json[key_info.position + 1..key_info.position + key_info.length -
1196 1]
1197
1198 decoder.current_node = decoder.current_node.next
1199
1200 value_info := decoder.current_node.value
1201
1202 if value_info.position + value_info.length > map_end {
1203 break
1204 }
1205
1206 mut map_value := V{}
1207
1208 $if V.indirections == 1 {
1209 if decoder.current_node.value.value_kind == .null {
1210 if decoder.current_node != unsafe { nil } {
1211 decoder.current_node = decoder.current_node.next
1212 }
1213 } else {
1214 mut decoded_ptr := create_decoded_ptr(map_value)
1215 decoder.decode_value(mut decoded_ptr)!
1216 map_value = decoded_ptr
1217 }
1218 } $else {
1219 decoder.decode_value(mut map_value)!
1220 }
1221
1222 $if V is $alias && V.unaliased_typ is $map {
1223 // V is a map alias (e.g. `type SyntaxStyle = map[string]X`).
1224 // V's checker reports `val[key]` as the unaliased element type
1225 // while `map_value` keeps the alias type, so direct assignment
1226 // fails to type-check. Skip to keep generic instantiations
1227 // compilable; decoding into map-alias map values is unsupported.
1228 } $else $if K is string {
1229 $if V is $map {
1230 val[key_str] = map_value.move()
1231 } $else {
1232 val[key_str] = map_value
1233 }
1234 } $else $if K is rune {
1235 $if V is $map {
1236 val[rune(key_str.int())] = map_value.move()
1237 } $else {
1238 val[rune(key_str.int())] = map_value
1239 }
1240 } $else $if K is $int {
1241 $if V is $map {
1242 val[K(key_str.int())] = map_value.move()
1243 } $else {
1244 val[K(key_str.int())] = map_value
1245 }
1246 } $else {
1247 $if V is $map {
1248 val[key_str] = map_value.move()
1249 } $else {
1250 val[key_str] = map_value
1251 }
1252 }
1253 }
1254 } else {
1255 decoder.decode_error('Expected object, but got ${map_info.value_kind}')!
1256 }
1257 }
1258}
1259
1260fn create_value_from_optional[T](_val ?T) ?T {
1261 return T{}
1262}
1263
1264fn (mut decoder Decoder) decode_enum[T](mut val T) ! {
1265 enum_info := decoder.current_node.value
1266
1267 if enum_info.value_kind == .number {
1268 mut result := 0
1269 unsafe { decoder.decode_number(&result)! }
1270
1271 $for value in T.values {
1272 if int(value.value) == result {
1273 val = value.value
1274 return
1275 }
1276 }
1277 decoder.decode_error('Number value: `${result}` does not match any field in enum: ${typeof(val).name}')!
1278 } else if enum_info.value_kind == .string {
1279 mut result := ''
1280 decoder.decode_string(mut result)!
1281
1282 $for value in T.values {
1283 for attr in value.attrs {
1284 if json_attr := json_attr_value(attr) {
1285 if json_attr == result {
1286 val = value.value
1287 return
1288 }
1289 }
1290 }
1291 if value.name == result {
1292 val = value.value
1293 return
1294 }
1295 }
1296 decoder.decode_error('String value: `${result}` does not match any field in enum: ${typeof(val).name}')!
1297 }
1298
1299 decoder.decode_error('Expected number or string value for enum, got: ${enum_info.value_kind}')!
1300}
1301
1302const max_integer_number_digits = 20
1303
1304@[markused]
1305fn has_exponent_number_syntax(str string) bool {
1306 for c in str {
1307 if c == `e` || c == `E` {
1308 return true
1309 }
1310 }
1311 return false
1312}
1313
1314@[markused]
1315fn scientific_number_to_integer_string(str string) !string {
1316 if !has_exponent_number_syntax(str) {
1317 // Handle plain decimal numbers with zero fractional part (e.g., "-123.0")
1318 dot_pos := str.index_u8(`.`)
1319 if dot_pos >= 0 {
1320 frac := str[dot_pos + 1..]
1321 mut all_zeros := frac.len > 0
1322 for c in frac {
1323 if c != `0` {
1324 all_zeros = false
1325 break
1326 }
1327 }
1328 if all_zeros {
1329 result := str[..dot_pos]
1330 if result.len == 0 || result == '-' || result == '+' {
1331 return '0'
1332 }
1333 return result
1334 }
1335 }
1336 return str
1337 }
1338 if str.len == 0 {
1339 return error('invalid scientific notation number')
1340 }
1341 mut i := 0
1342 mut is_negative := false
1343 if str[i] == `+` || str[i] == `-` {
1344 is_negative = str[i] == `-`
1345 i++
1346 }
1347 if i >= str.len {
1348 return error('invalid scientific notation number')
1349 }
1350 mut digits := []u8{cap: str.len}
1351 mut fractional_digits := 0
1352 mut seen_digit := false
1353 mut seen_dot := false
1354 for i < str.len {
1355 c := str[i]
1356 if c >= `0` && c <= `9` {
1357 digits << c
1358 seen_digit = true
1359 if seen_dot {
1360 fractional_digits++
1361 }
1362 i++
1363 continue
1364 }
1365 if c == `.` && !seen_dot {
1366 seen_dot = true
1367 i++
1368 continue
1369 }
1370 break
1371 }
1372 if !seen_digit || i >= str.len || (str[i] != `e` && str[i] != `E`) {
1373 return error('invalid scientific notation number')
1374 }
1375 i++
1376 mut exponent_sign := 1
1377 if i < str.len && (str[i] == `+` || str[i] == `-`) {
1378 if str[i] == `-` {
1379 exponent_sign = -1
1380 }
1381 i++
1382 }
1383 if i >= str.len || str[i] < `0` || str[i] > `9` {
1384 return error('invalid scientific notation number')
1385 }
1386 mut exponent := 0
1387 exponent_cap := max_integer_number_digits + fractional_digits + 1
1388 for i < str.len && str[i] >= `0` && str[i] <= `9` {
1389 if exponent < exponent_cap {
1390 exponent = (exponent * 10) + int(str[i] - `0`)
1391 }
1392 i++
1393 }
1394 if i != str.len {
1395 return error('invalid scientific notation number')
1396 }
1397 if exponent_sign == -1 {
1398 exponent = -exponent
1399 }
1400 mut first_non_zero := 0
1401 for first_non_zero < digits.len && digits[first_non_zero] == `0` {
1402 first_non_zero++
1403 }
1404 if first_non_zero == digits.len {
1405 return '0'
1406 }
1407 digits = digits[first_non_zero..].clone()
1408 scale := exponent - fractional_digits
1409 if scale < 0 {
1410 truncated_digits := -scale
1411 if truncated_digits >= digits.len {
1412 return '0'
1413 }
1414 digits = digits[..digits.len - truncated_digits].clone()
1415 } else if scale > 0 {
1416 final_len := digits.len + scale
1417 if final_len > max_integer_number_digits {
1418 return error('number `${str}` exceeds 64-bit integer range')
1419 }
1420 mut out := []u8{cap: final_len + if is_negative { 1 } else { 0 }}
1421 if is_negative {
1422 out << `-`
1423 }
1424 out << digits
1425 for _ in 0 .. scale {
1426 out << `0`
1427 }
1428 return out.bytestr()
1429 }
1430 if digits.len == 0 {
1431 return '0'
1432 }
1433 mut out := []u8{cap: digits.len + if is_negative { 1 } else { 0 }}
1434 if is_negative {
1435 out << `-`
1436 }
1437 out << digits
1438 return out.bytestr()
1439}
1440
1441fn parse_integer_number[T](str string) !T {
1442 int_str := scientific_number_to_integer_string(str)!
1443 $if T.unaliased_typ is i8 {
1444 return T(strconv.atoi8(int_str)!)
1445 } $else $if T.unaliased_typ is i16 {
1446 return T(strconv.atoi16(int_str)!)
1447 } $else $if T.unaliased_typ is i32 {
1448 return T(strconv.atoi32(int_str)!)
1449 } $else $if T.unaliased_typ is i64 {
1450 return T(strconv.atoi64(int_str)!)
1451 } $else $if T.unaliased_typ is u8 {
1452 return T(strconv.atou8(int_str)!)
1453 } $else $if T.unaliased_typ is u16 {
1454 return T(strconv.atou16(int_str)!)
1455 } $else $if T.unaliased_typ is u32 {
1456 return T(strconv.atou32(int_str)!)
1457 } $else $if T.unaliased_typ is u64 {
1458 return T(strconv.atou64(int_str)!)
1459 } $else $if T is int {
1460 return int(strconv.atoi64(int_str)!)
1461 } $else $if T.unaliased_typ is int {
1462 return T(int(strconv.atoi64(int_str)!))
1463 } $else $if T.unaliased_typ is isize {
1464 return T(isize(strconv.atoi64(int_str)!))
1465 } $else $if T.unaliased_typ is usize {
1466 return T(usize(strconv.atou64(int_str)!))
1467 } $else {
1468 return error('`parse_integer_number` cannot decode ${T.name} type')
1469 }
1470}
1471
1472@[markused]
1473fn parse_int_number(str string) !int {
1474 int_str := scientific_number_to_integer_string(str)!
1475 return int(strconv.atoi64(int_str)!)
1476}
1477
1478fn parse_float_number[T](str string) !T {
1479 $if js {
1480 $if T.unaliased_typ is f32 {
1481 return T(f32(strconv.atof64(str)!))
1482 } $else $if T.unaliased_typ is f64 {
1483 return T(strconv.atof64(str)!)
1484 } $else {
1485 return error('`parse_float_number` cannot decode ${T.name} type')
1486 }
1487 } $else {
1488 $if T.unaliased_typ is f32 {
1489 return T(f32(strconv.atof64(str, allow_extra_chars: false)!))
1490 } $else $if T.unaliased_typ is f64 {
1491 return T(strconv.atof64(str, allow_extra_chars: false)!)
1492 } $else {
1493 return error('`parse_float_number` cannot decode ${T.name} type')
1494 }
1495 }
1496}
1497
1498// use pointer instead of mut so enum cast works
1499@[unsafe]
1500fn (mut decoder Decoder) decode_number[T](val &T) ! {
1501 _ = val
1502 number_info := decoder.current_node.value
1503 str := decoder.json[number_info.position..number_info.position + number_info.length]
1504 $match T.unaliased_typ {
1505 i8 { *val = parse_integer_number[T](str)! }
1506 i16 { *val = parse_integer_number[T](str)! }
1507 i32 { *val = parse_integer_number[T](str)! }
1508 i64 { *val = parse_integer_number[T](str)! }
1509 u8 { *val = parse_integer_number[T](str)! }
1510 u16 { *val = parse_integer_number[T](str)! }
1511 u32 { *val = parse_integer_number[T](str)! }
1512 u64 { *val = parse_integer_number[T](str)! }
1513 int { *val = parse_int_number(str)! }
1514 isize { *val = parse_integer_number[T](str)! }
1515 usize { *val = parse_integer_number[T](str)! }
1516 f32 { *val = parse_float_number[T](str)! }
1517 f64 { *val = parse_float_number[T](str)! }
1518 $else { return error('`decode_number` can not decode ${T.name} type') }
1519 }
1520}
1521
1522// decode_number_from_string parses a number from a JSON string value (default mode).
1523// This extracts the content between quotes and parses it as a number.
1524fn (mut decoder Decoder) decode_number_from_string[T]() !T {
1525 string_info := decoder.current_node.value
1526 // Extract string content without quotes (position+1 to skip opening quote, length-2 to exclude both quotes)
1527 if string_info.length < 2 {
1528 return error('invalid string for number conversion')
1529 }
1530 str := decoder.json[string_info.position + 1..string_info.position + string_info.length - 1]
1531 $if T.unaliased_typ is i8 {
1532 return parse_integer_number[T](str)!
1533 } $else $if T.unaliased_typ is i16 {
1534 return parse_integer_number[T](str)!
1535 } $else $if T.unaliased_typ is i32 {
1536 return parse_integer_number[T](str)!
1537 } $else $if T.unaliased_typ is i64 {
1538 return parse_integer_number[T](str)!
1539 } $else $if T.unaliased_typ is u8 {
1540 return parse_integer_number[T](str)!
1541 } $else $if T.unaliased_typ is u16 {
1542 return parse_integer_number[T](str)!
1543 } $else $if T.unaliased_typ is u32 {
1544 return parse_integer_number[T](str)!
1545 } $else $if T.unaliased_typ is u64 {
1546 return parse_integer_number[T](str)!
1547 } $else $if T is int {
1548 return parse_int_number(str)!
1549 } $else $if T.unaliased_typ is int {
1550 return parse_integer_number[T](str)!
1551 } $else $if T.unaliased_typ is isize {
1552 return parse_integer_number[T](str)!
1553 } $else $if T.unaliased_typ is usize {
1554 return parse_integer_number[T](str)!
1555 } $else $if T.unaliased_typ is f32 {
1556 return parse_float_number[T](str)!
1557 } $else $if T.unaliased_typ is f64 {
1558 return parse_float_number[T](str)!
1559 } $else {
1560 return error('`decode_number_from_string` cannot decode ${T.name} type')
1561 }
1562}
1563