x.json2.decoder2: rename fields, add more comments (#22037)

This commit is contained in:
Hitalo Souza 2024-08-12 09:08:24 -04:00 committed by GitHub
parent e8305d240c
commit e16d727da1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2,16 +2,18 @@ module decoder2
import time import time
// Node represents a node in a JSON decoder tree.
struct Node { struct Node {
key_pos int key_pos int // The position of the key in the JSON string.
key_len int key_len int // The length of the key in the JSON string.
children ?[]Node children ?[]Node // The children nodes of the current node.
} }
// Decoder represents a JSON decoder.
struct Decoder { struct Decoder {
json_data string json string // json is the JSON data to be decoded.
mut: mut:
idx int idx int // idx is the current index of the decoder.
} }
pub enum ValueKind { pub enum ValueKind {
@ -37,7 +39,7 @@ pub fn decode[T](val string) !T {
mut nodes := []Node{} mut nodes := []Node{}
mut decoder := Decoder{ mut decoder := Decoder{
json_data: val json: val
} }
// TODO needs performance improvements // TODO needs performance improvements
@ -96,30 +98,30 @@ fn (mut decoder Decoder) decode_optional_value_in_actual_node[T](node Node, val
start := (node.key_pos + node.key_len) + 3 start := (node.key_pos + node.key_len) + 3
mut end := start mut end := start
for { for {
if decoder.json_data[end] == `,` || decoder.json_data[end] == `}` { if decoder.json[end] == `,` || decoder.json[end] == `}` {
break break
} }
end++ end++
} }
mut value_kind := get_value_kind(decoder.json_data[start]) mut value_kind := get_value_kind(decoder.json[start])
$if T is string { $if T is string {
if value_kind == .string_ { if value_kind == .string_ {
return decoder.json_data[start + 1..end - 1] return decoder.json[start + 1..end - 1]
} else if value_kind == .object { } else if value_kind == .object {
} else if value_kind == .array { } else if value_kind == .array {
} else { } else {
return decoder.json_data[start..end] return decoder.json[start..end]
} }
return '' return ''
} $else $if T is $int { } $else $if T is $int {
if value_kind == .string_ { if value_kind == .string_ {
return decoder.json_data[start + 1..end - 1].int() return decoder.json[start + 1..end - 1].int()
} else if value_kind == .object { } else if value_kind == .object {
} else if value_kind == .array { } else if value_kind == .array {
} else { } else {
return decoder.json_data[start..end].int() return decoder.json[start..end].int()
} }
} }
return T{} return T{}
@ -132,36 +134,37 @@ fn (mut decoder Decoder) decode_struct[T](nodes []Node, value &T) {
mut node := nodes[i] mut node := nodes[i]
if node.key_len == field.name.len { if node.key_len == field.name.len {
// This `vmemcmp` compares the name of a key in a JSON with a given struct field.
if unsafe { if unsafe {
vmemcmp(decoder.json_data.str + node.key_pos, field.name.str, field.name.len) == 0 vmemcmp(decoder.json.str + node.key_pos, field.name.str, field.name.len) == 0
} { } {
start := (node.key_pos + node.key_len) + 3 start := (node.key_pos + node.key_len) + 3
mut end := start mut end := start
for { for {
if decoder.json_data[end] == `,` || decoder.json_data[end] == `}` { if decoder.json[end] == `,` || decoder.json[end] == `}` {
break break
} }
end++ end++
} }
mut value_kind := get_value_kind(decoder.json_data[start]) mut value_kind := get_value_kind(decoder.json[start])
$if field.indirections != 0 { $if field.indirections != 0 {
// REVIEW Needs clone? // REVIEW Needs clone?
$if field.indirections == 1 { $if field.indirections == 1 {
// TODO // TODO
// unsafe { // unsafe {
// value.$(field.name) = &(decoder.json_data[start + 1..end - 1]) // value.$(field.name) = &(decoder.json[start + 1..end - 1])
// } // }
} $else $if field.indirections == 2 { } $else $if field.indirections == 2 {
// TODO // TODO
// unsafe { // unsafe {
// value.$(field.name) = &&(decoder.json_data[start + 1..end - 1]) // value.$(field.name) = &&(decoder.json[start + 1..end - 1])
// } // }
} $else $if field.indirections == 3 { } $else $if field.indirections == 3 {
// TODO // TODO
// unsafe { // unsafe {
// value.$(field.name) = &&&(decoder.json_data[start + 1..end - 1]) // value.$(field.name) = &&&(decoder.json[start + 1..end - 1])
// } // }
} }
} $else $if field.typ is $option { } $else $if field.typ is $option {
@ -176,48 +179,48 @@ fn (mut decoder Decoder) decode_struct[T](nodes []Node, value &T) {
$for v in workaround.variants { $for v in workaround.variants {
$if v.typ is string { $if v.typ is string {
if value_kind == .string_ { if value_kind == .string_ {
// value.$(field.name) = decoder.json_data[start + 1..end - 1] // value.$(field.name) = decoder.json[start + 1..end - 1]
} else { } else {
// value.$(field.name) = decoder.json_data[start..end] // value.$(field.name) = decoder.json[start..end]
} }
} $else $if v.typ in [$int, $float] { } $else $if v.typ in [$int, $float] {
$if v.typ is u32 { $if v.typ is u32 {
value.$(field.name) = decoder.json_data[start..end].u32() value.$(field.name) = decoder.json[start..end].u32()
} $else $if v.typ is u32 { } $else $if v.typ is u32 {
} }
$if v.typ is i8 { $if v.typ is i8 {
value.$(field.name) = decoder.json_data[start..end].i8() value.$(field.name) = decoder.json[start..end].i8()
} $else $if v.typ is i16 { } $else $if v.typ is i16 {
value.$(field.name) = decoder.json_data[start..end].i16() value.$(field.name) = decoder.json[start..end].i16()
} $else $if v.typ is i32 { } $else $if v.typ is i32 {
value.$(field.name) = decoder.json_data[start..end].i32() value.$(field.name) = decoder.json[start..end].i32()
} $else $if v.typ is int { } $else $if v.typ is int {
value.$(field.name) = decoder.json_data[start..end].int() value.$(field.name) = decoder.json[start..end].int()
} $else $if v.typ is i64 { } $else $if v.typ is i64 {
value.$(field.name) = decoder.json_data[start..end].i64() value.$(field.name) = decoder.json[start..end].i64()
} $else $if v.typ is u8 { } $else $if v.typ is u8 {
value.$(field.name) = decoder.json_data[start..end].u8() value.$(field.name) = decoder.json[start..end].u8()
} $else $if v.typ is u16 { } $else $if v.typ is u16 {
value.$(field.name) = decoder.json_data[start..end].u16() value.$(field.name) = decoder.json[start..end].u16()
} $else $if v.typ is u32 { } $else $if v.typ is u32 {
value.$(field.name) = decoder.json_data[start..end].u32() value.$(field.name) = decoder.json[start..end].u32()
} $else $if v.typ is u64 { } $else $if v.typ is u64 {
value.$(field.name) = decoder.json_data[start..end].u64() value.$(field.name) = decoder.json[start..end].u64()
} $else $if v.typ is f32 { } $else $if v.typ is f32 {
value.$(field.name) = decoder.json_data[start..end].f32() value.$(field.name) = decoder.json[start..end].f32()
} $else $if v.typ is f64 { } $else $if v.typ is f64 {
value.$(field.name) = decoder.json_data[start..end].f64() value.$(field.name) = decoder.json[start..end].f64()
} }
} $else $if v.typ is bool { } $else $if v.typ is bool {
if decoder.json_data[start] == `t` { if decoder.json[start] == `t` {
value.$(field.name) = true value.$(field.name) = true
} else if decoder.json_data[start] == `f` { } else if decoder.json[start] == `f` {
value.$(field.name) = false value.$(field.name) = false
} }
} $else $if v.typ is time.Time { } $else $if v.typ is time.Time {
if value_kind == .string_ { if value_kind == .string_ {
value.$(field.name) = time.parse(decoder.json_data[start + 1..end - 1]) or { value.$(field.name) = time.parse(decoder.json[start + 1..end - 1]) or {
time.Time{} time.Time{}
} }
} }
@ -242,56 +245,56 @@ fn (mut decoder Decoder) decode_struct[T](nodes []Node, value &T) {
} }
} }
if value_kind == .string_ { if value_kind == .string_ {
// value.$(field.name) = decoder.json_data[start + 1..end - 1] // value.$(field.name) = decoder.json[start + 1..end - 1]
} else if decoder.json_data[start] == `t` { } else if decoder.json[start] == `t` {
value.$(field.name) = true value.$(field.name) = true
} else if decoder.json_data[start] == `f` { } else if decoder.json[start] == `f` {
value.$(field.name) = false value.$(field.name) = false
} else if value_kind == .object { } else if value_kind == .object {
} else if value_kind == .array { } else if value_kind == .array {
} else if value_kind == .number { } else if value_kind == .number {
// value.$(field.name) = decoder.json_data[start..end].int() // value.$(field.name) = decoder.json[start..end].int()
} else { } else {
} }
} $else $if field.typ is string { } $else $if field.typ is string {
if value_kind == .string_ { if value_kind == .string_ {
value.$(field.name) = decoder.json_data[start + 1..end - 1] value.$(field.name) = decoder.json[start + 1..end - 1]
} else { } else {
value.$(field.name) = decoder.json_data[start..end] value.$(field.name) = decoder.json[start..end]
} }
} $else $if field.typ in [$int, $float] { } $else $if field.typ in [$int, $float] {
$if field.typ is i8 { $if field.typ is i8 {
value.$(field.name) = decoder.json_data[start..end].i8() value.$(field.name) = decoder.json[start..end].i8()
} $else $if field.typ is i16 { } $else $if field.typ is i16 {
value.$(field.name) = decoder.json_data[start..end].i16() value.$(field.name) = decoder.json[start..end].i16()
} $else $if field.typ is i32 { } $else $if field.typ is i32 {
value.$(field.name) = decoder.json_data[start..end].i32() value.$(field.name) = decoder.json[start..end].i32()
} $else $if field.typ is int { } $else $if field.typ is int {
value.$(field.name) = decoder.json_data[start..end].int() value.$(field.name) = decoder.json[start..end].int()
} $else $if field.typ is i64 { } $else $if field.typ is i64 {
value.$(field.name) = decoder.json_data[start..end].i64() value.$(field.name) = decoder.json[start..end].i64()
} $else $if field.typ is u8 { } $else $if field.typ is u8 {
value.$(field.name) = decoder.json_data[start..end].u8() value.$(field.name) = decoder.json[start..end].u8()
} $else $if field.typ is u16 { } $else $if field.typ is u16 {
value.$(field.name) = decoder.json_data[start..end].u16() value.$(field.name) = decoder.json[start..end].u16()
} $else $if field.typ is u32 { } $else $if field.typ is u32 {
value.$(field.name) = decoder.json_data[start..end].u32() value.$(field.name) = decoder.json[start..end].u32()
} $else $if field.typ is u64 { } $else $if field.typ is u64 {
value.$(field.name) = decoder.json_data[start..end].u64() value.$(field.name) = decoder.json[start..end].u64()
} $else $if field.typ is f32 { } $else $if field.typ is f32 {
value.$(field.name) = decoder.json_data[start..end].f32() value.$(field.name) = decoder.json[start..end].f32()
} $else $if field.typ is f64 { } $else $if field.typ is f64 {
value.$(field.name) = decoder.json_data[start..end].f64() value.$(field.name) = decoder.json[start..end].f64()
} }
} $else $if field.typ is bool { } $else $if field.typ is bool {
if decoder.json_data[start] == `t` { if decoder.json[start] == `t` {
value.$(field.name) = true value.$(field.name) = true
} else if decoder.json_data[start] == `f` { } else if decoder.json[start] == `f` {
value.$(field.name) = false value.$(field.name) = false
} }
} $else $if field.typ is time.Time { } $else $if field.typ is time.Time {
if value_kind == .string_ { if value_kind == .string_ {
value.$(field.name) = time.parse_rfc3339(decoder.json_data[start + 1..end - 1]) or { value.$(field.name) = time.parse_rfc3339(decoder.json[start + 1..end - 1]) or {
time.Time{} time.Time{}
} }
} }
@ -313,37 +316,37 @@ fn (mut decoder Decoder) decode_struct[T](nodes []Node, value &T) {
} }
} }
} $else $if field.typ is $enum { } $else $if field.typ is $enum {
value.$(field.name) = decoder.json_data[start..end].int() value.$(field.name) = decoder.json[start..end].int()
} $else $if field.typ is $alias { } $else $if field.typ is $alias {
$if field.unaliased_typ is string { $if field.unaliased_typ is string {
if value_kind == .string_ { if value_kind == .string_ {
value.$(field.name) = decoder.json_data[start + 1..end - 1] value.$(field.name) = decoder.json[start + 1..end - 1]
} }
} $else $if field.unaliased_typ is time.Time { } $else $if field.unaliased_typ is time.Time {
} $else $if field.unaliased_typ is bool { } $else $if field.unaliased_typ is bool {
} $else $if field.unaliased_typ in [$float, $int] { } $else $if field.unaliased_typ in [$float, $int] {
$if field.unaliased_typ is i8 { $if field.unaliased_typ is i8 {
value.$(field.name) = decoder.json_data[start..end].i8() value.$(field.name) = decoder.json[start..end].i8()
} $else $if field.unaliased_typ is i16 { } $else $if field.unaliased_typ is i16 {
value.$(field.name) = decoder.json_data[start..end].i16() value.$(field.name) = decoder.json[start..end].i16()
} $else $if field.unaliased_typ is i32 { } $else $if field.unaliased_typ is i32 {
value.$(field.name) = decoder.json_data[start..end].i32() value.$(field.name) = decoder.json[start..end].i32()
} $else $if field.unaliased_typ is int { } $else $if field.unaliased_typ is int {
value.$(field.name) = decoder.json_data[start..end].int() value.$(field.name) = decoder.json[start..end].int()
} $else $if field.unaliased_typ is i64 { } $else $if field.unaliased_typ is i64 {
value.$(field.name) = decoder.json_data[start..end].i64() value.$(field.name) = decoder.json[start..end].i64()
} $else $if field.unaliased_typ is u8 { } $else $if field.unaliased_typ is u8 {
value.$(field.name) = decoder.json_data[start..end].u8() value.$(field.name) = decoder.json[start..end].u8()
} $else $if field.unaliased_typ is u16 { } $else $if field.unaliased_typ is u16 {
value.$(field.name) = decoder.json_data[start..end].u16() value.$(field.name) = decoder.json[start..end].u16()
} $else $if field.unaliased_typ is u32 { } $else $if field.unaliased_typ is u32 {
value.$(field.name) = decoder.json_data[start..end].u32() value.$(field.name) = decoder.json[start..end].u32()
} $else $if field.unaliased_typ is u64 { } $else $if field.unaliased_typ is u64 {
value.$(field.name) = decoder.json_data[start..end].u64() value.$(field.name) = decoder.json[start..end].u64()
} $else $if field.unaliased_typ is f32 { } $else $if field.unaliased_typ is f32 {
value.$(field.name) = decoder.json_data[start..end].f32() value.$(field.name) = decoder.json[start..end].f32()
} $else $if field.unaliased_typ is f64 { } $else $if field.unaliased_typ is f64 {
value.$(field.name) = decoder.json_data[start..end].f64() value.$(field.name) = decoder.json[start..end].f64()
} }
} $else $if field.unaliased_typ is $array { } $else $if field.unaliased_typ is $array {
// TODO // TODO
@ -375,20 +378,19 @@ fn (mut decoder Decoder) decode_map[T](nodes []Node, mut val T) {
mut end := start mut end := start
for { for {
if decoder.json_data[end] == `,` || decoder.json_data[end] == `}` { if decoder.json[end] == `,` || decoder.json[end] == `}` {
break break
} }
end++ end++
} }
mut value_kind := get_value_kind(decoder.json_data[start]) mut value_kind := get_value_kind(decoder.json[start])
if value_kind == .string_ { if value_kind == .string_ {
val[decoder.json_data[node.key_pos..node.key_pos + node.key_len]] = decoder.json_data[ val[decoder.json[node.key_pos..node.key_pos + node.key_len]] = decoder.json[start + 1..end - 1]
start + 1..end - 1]
} else { } else {
val[decoder.json_data[node.key_pos..node.key_pos + node.key_len]] = decoder.json_data[start..end] val[decoder.json[node.key_pos..node.key_pos + node.key_len]] = decoder.json[start..end]
} }
} }
} }
@ -399,15 +401,14 @@ fn (mut decoder Decoder) fulfill_nodes(mut nodes []Node) {
mut inside_key := false mut inside_key := false
mut actual_key_len := 0 mut actual_key_len := 0
for decoder.idx < decoder.json_data.len { for decoder.idx < decoder.json.len {
letter := decoder.json_data[decoder.idx] letter := decoder.json[decoder.idx]
if letter == ` ` && !inside_string { if letter == ` ` && !inside_string {
} else if letter == `\"` { } else if letter == `\"` {
if decoder.json_data[decoder.idx - 1] == `{` if decoder.json[decoder.idx - 1] == `{` || decoder.json[decoder.idx - 2] == `,` {
|| decoder.json_data[decoder.idx - 2] == `,` {
inside_key = true inside_key = true
} else if decoder.json_data[decoder.idx + 1] == `:` { } else if decoder.json[decoder.idx + 1] == `:` {
if decoder.json_data[decoder.idx + 3] == `{` { if decoder.json[decoder.idx + 3] == `{` {
mut children := []Node{} mut children := []Node{}
key_pos := decoder.idx - actual_key_len key_pos := decoder.idx - actual_key_len
key_len := actual_key_len key_len := actual_key_len