@@ -897,6 +897,35 @@ fn (mut decoder Decoder) decode_enum[T](mut val T) ! {
897897 decoder.decode_error ('Expected number or string value for enum, got: ${enum_info.value_kind} ' )!
898898}
899899
900+ @[inline]
901+ fn number_string_is_real (str string ) bool {
902+ for ch in str {
903+ if ch == `.` || ch == `e` || ch == `E` {
904+ return true
905+ }
906+ }
907+ return false
908+ }
909+
910+ // Keep compatibility with the legacy json module, which truncates real-number
911+ // tokens when decoding into 64-bit integer targets.
912+ fn decode_i64_from_number_string (str string ) ! i64 {
913+ if number_string_is_real (str) {
914+ return i64 (strconv.atof_quick (str))
915+ }
916+ return strconv.atoi64 (str)!
917+ }
918+
919+ fn decode_u64_from_number_string (str string ) ! u64 {
920+ if number_string_is_real (str) {
921+ if str.len > 0 && str[0 ] == `-` {
922+ return strconv.atou64 (str)!
923+ }
924+ return u64 (strconv.atof_quick (str))
925+ }
926+ return strconv.atou64 (str)!
927+ }
928+
900929// use pointer instead of mut so enum cast works
901930@[unsafe ]
902931fn (mut decoder Decoder) decode_number [T](val & T) ! {
@@ -906,14 +935,14 @@ fn (mut decoder Decoder) decode_number[T](val &T) ! {
906935 i8 { * val = strconv.atoi8 (str)! }
907936 i16 { * val = strconv.atoi16 (str)! }
908937 i32 { * val = strconv.atoi32 (str)! }
909- i64 { * val = strconv. atoi64 (str)! }
938+ i64 { * val = decode_i64_from_number_string (str)! }
910939 u8 { * val = strconv.atou8 (str)! }
911940 u16 { * val = strconv.atou16 (str)! }
912941 u32 { * val = strconv.atou32 (str)! }
913- u64 { * val = strconv. atou64 (str)! }
942+ u64 { * val = decode_u64_from_number_string (str)! }
914943 int { * val = strconv.atoi (str)! }
915- isize { * val = isize (strconv. atoi64 (str)! ) }
916- usize { * val = usize (strconv. atou64 (str)! ) }
944+ isize { * val = isize (decode_i64_from_number_string (str)! ) }
945+ usize { * val = usize (decode_u64_from_number_string (str)! ) }
917946 f32 { * val = f32 (strconv.atof_quick (str)) }
918947 f64 { * val = strconv.atof_quick (str) }
919948 $else { return error ('`decode_number` can not decode ${T.name} type' ) }
@@ -936,21 +965,21 @@ fn (mut decoder Decoder) decode_number_from_string[T]() !T {
936965 } $else $if T.unaliased_typ is i32 {
937966 return T (strconv.atoi32 (str)! )
938967 } $else $if T.unaliased_typ is i64 {
939- return T (strconv. atoi64 (str)! )
968+ return T (decode_i64_from_number_string (str)! )
940969 } $else $if T.unaliased_typ is u8 {
941970 return T (strconv.atou8 (str)! )
942971 } $else $if T.unaliased_typ is u16 {
943972 return T (strconv.atou16 (str)! )
944973 } $else $if T.unaliased_typ is u32 {
945974 return T (strconv.atou32 (str)! )
946975 } $else $if T.unaliased_typ is u64 {
947- return T (strconv. atou64 (str)! )
976+ return T (decode_u64_from_number_string (str)! )
948977 } $else $if T.unaliased_typ is int {
949978 return T (strconv.atoi (str)! )
950979 } $else $if T.unaliased_typ is isize {
951- return T (isize (strconv. atoi64 (str)! ))
980+ return T (isize (decode_i64_from_number_string (str)! ))
952981 } $else $if T.unaliased_typ is usize {
953- return T (usize (strconv. atou64 (str)! ))
982+ return T (usize (decode_u64_from_number_string (str)! ))
954983 } $else $if T.unaliased_typ is f32 {
955984 return T (f32 (strconv.atof_quick (str)))
956985 } $else $if T.unaliased_typ is f64 {
0 commit comments