Skip to content

Commit fd31771

Browse files
authored
x.json2: fix decode_number for u8 (fix #26027) (#26033)
1 parent f1c023d commit fd31771

2 files changed

Lines changed: 30 additions & 89 deletions

File tree

vlib/x/json2/decode.v

Lines changed: 13 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -930,95 +930,19 @@ fn (mut decoder Decoder) decode_number[T](val &T) ! {
930930
$if T.unaliased_typ is $float {
931931
*val = T(strconv.atof_quick(decoder.json[number_info.position..number_info.position +
932932
number_info.length]))
933-
} $else { // this part is a minefield
934-
mut is_negative := false
935-
mut index := 0
936-
937-
if decoder.json[number_info.position] == `-` {
938-
$if T.unaliased_typ is u8 || T.unaliased_typ is u16 || T.unaliased_typ is u32
939-
|| T.unaliased_typ is u64 || T.unaliased_typ is $enum {
940-
decoder.decode_error('expected positive integer for ${typeof(val).name} but got ${decoder.json[number_info.position..
941-
number_info.position + number_info.length]}')!
942-
}
943-
944-
is_negative = true
945-
index++
946-
}
947-
948-
// doing it like this means the minimum of signed numbers does not overflow before being inverted
949-
*val = 0 // initialize to zero before accumulating digits
950-
if !is_negative {
951-
digit_amount := get_number_digits(*val)
952-
953-
if number_info.length > digit_amount {
954-
decoder.decode_error('overflows ${typeof(val).name}')!
955-
}
956-
957-
for index < int_min(number_info.length, digit_amount - 1) {
958-
digit := T(decoder.json[number_info.position + index] - `0`)
959-
960-
if digit > 9 { // comma, e and E are all smaller 0 in ASCII so they underflow
961-
decoder.decode_error('expected integer but got real number')!
962-
}
963-
964-
*val = *val * 10 + digit
965-
966-
index++
967-
}
968-
969-
if index == digit_amount - 1 {
970-
digit := T(decoder.json[number_info.position + index] - `0`)
971-
972-
if digit > 9 { // comma, e and E are all smaller 0 in ASCII so they underflow
973-
decoder.decode_error('expected integer but got real number')!
974-
}
975-
976-
type_max := get_number_max(*val)
977-
max_digits := type_max / 10
978-
last_digit := type_max % 10
979-
980-
if *val > max_digits || (*val == max_digits && digit > last_digit) {
981-
decoder.decode_error('overflows ${typeof(val).name}s')!
982-
}
983-
984-
*val = *val * 10 + digit
985-
}
986-
} else {
987-
digit_amount := get_number_digits(*val) + 1
988-
989-
if number_info.length > digit_amount {
990-
decoder.decode_error('underflows ${typeof(val).name}')!
991-
}
992-
993-
for index < int_min(number_info.length, digit_amount - 1) {
994-
digit := T(decoder.json[number_info.position + index] - `0`)
995-
996-
if digit > 9 { // comma, e and E are all smaller 0 in ASCII so they underflow
997-
decoder.decode_error('expected integer but got real number')!
998-
}
999-
1000-
*val = *val * 10 - digit
1001-
1002-
index++
1003-
}
1004-
1005-
if index == digit_amount - 1 {
1006-
digit := T(decoder.json[number_info.position + index] - `0`)
1007-
1008-
if digit > 9 { // comma, e and E are all smaller 0 in ASCII so they underflow
1009-
decoder.decode_error('expected integer but got real number')!
1010-
}
1011-
1012-
type_min := get_number_min(*val)
1013-
min_digits := type_min / 10
1014-
last_digit := type_min % 10
1015-
1016-
if *val < min_digits || (*val == min_digits && -digit < last_digit) {
1017-
decoder.decode_error('underflows ${typeof(val).name}')!
1018-
}
1019-
1020-
*val = *val * 10 - digit
1021-
}
933+
} $else {
934+
str := decoder.json[number_info.position..number_info.position + number_info.length]
935+
$match T.unaliased_typ {
936+
i8 { *val = strconv.atoi8(str)! }
937+
i16 { *val = strconv.atoi16(str)! }
938+
i32 { *val = strconv.atoi32(str)! }
939+
i64 { *val = strconv.atoi64(str)! }
940+
u8 { *val = strconv.atou8(str)! }
941+
u16 { *val = strconv.atou16(str)! }
942+
u32 { *val = strconv.atou32(str)! }
943+
u64 { *val = strconv.atou64(str)! }
944+
int { *val = strconv.atoi(str)! }
945+
$else { return error('`decode_number` can not decode ${T.name} type') }
1022946
}
1023947
}
1024948
}

vlib/x/json2/tests/decode_struct_test.v

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,20 @@ fn test_option_types() {
7373
assert false, 'Should not return none'
7474
}
7575
}
76+
77+
struct JsonU8 {
78+
val1 u8
79+
val2 u8
80+
}
81+
82+
fn test_u8_vals() {
83+
x := JsonU8{
84+
val1: 58
85+
val2: 58
86+
}
87+
88+
str := json.encode(x)
89+
90+
y := json.decode[JsonU8](str) or { panic(err) }
91+
assert x == y
92+
}

0 commit comments

Comments
 (0)