/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
/**
* @file
*
* This file defines interface JsonDeserializable
*/
package stdx.encoding.json.stream
import std.collection.*
import std.collection.concurrent.ConcurrentHashMap
public interface JsonDeserializable<T> {
static func fromJson(r: JsonReader): T
}
extend Bool <: JsonDeserializable<Bool> {
public static func fromJson(r: JsonReader): Bool {
if (r.peeked == PEEK_STATE_TRUE) {
return r.readTrue()
} else if (r.peeked == PEEK_STATE_FALSE) {
return r.readFalse()
}
return r.readBool()
}
}
extend<T> Option<T> <: JsonDeserializable<Option<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): Option<T> {
if (r.peeked == PEEK_STATE_NULL || r.nextNonJsonWhitespace() == b'n') { // cjlint-ignore !G.EXP.03
r.readNull()
return None
}
return T.fromJson(r)
}
}
const MAXVAL_I64: UInt64 = 0x7FFF_FFFF_FFFF_FFFF
const MAXVAL_UI64: UInt64 = 0xFFFF_FFFF_FFFF_FFFF
const MAXABSVAL_I64: UInt64 = MAXVAL_I64 + 1
const MAXVAL_I32: Int32 = 0x7FFF_FFFF
const MINVAL_I32: Int32 = -0x8000_0000
const MAXVAL_I16: Int16 = 0x7FFF
const MINVAL_I16: Int16 = -0x8000
const MAXVAL_I8: Int8 = 0x7F
const MINVAL_I8: Int8 = -0x80
const MAXVAL_UI32: UInt32 = 0xFFFF_FFFF
const MAXVAL_UI16: UInt16 = 0xFFFF
const MAXVAL_UI8: UInt8 = 0xFF
let isNative64 = UInt64(!UIntNative(0)) == MAXVAL_UI64
extend Int64 <: JsonDeserializable<Int64> {
public static func fromJson(r: JsonReader): Int64 {
let (res, overflow) = r.readInt()
if (overflow) {
throw OverflowException("The next number is out of range for Int64.")
}
return res
}
}
extend Int32 <: JsonDeserializable<Int32> {
public static func fromJson(r: JsonReader): Int32 {
let (res, overflow) = r.readInt()
if (overflow || res > Int64(MAXVAL_I32) || res < Int64(MINVAL_I32)) {
throw OverflowException("The next number is out of range for Int32.")
}
return Int32(res)
}
}
extend Int16 <: JsonDeserializable<Int16> {
public static func fromJson(r: JsonReader): Int16 {
let (res, overflow) = r.readInt()
if (overflow || res > Int64(MAXVAL_I16) || res < Int64(MINVAL_I16)) {
throw OverflowException("The next number is out of range for Int16.")
}
return Int16(res)
}
}
extend Int8 <: JsonDeserializable<Int8> {
public static func fromJson(r: JsonReader): Int8 {
let (res, overflow) = r.readInt()
if (overflow || res > Int64(MAXVAL_I8) || res < Int64(MINVAL_I8)) {
throw OverflowException("The next number is out of range for Int8.")
}
return Int8(res)
}
}
extend IntNative <: JsonDeserializable<IntNative> {
public static func fromJson(r: JsonReader): IntNative {
let (res, overflow) = r.readInt()
if (overflow || (!isNative64 && (res > Int64(MAXVAL_I32) || res < Int64(MINVAL_I32)))) {
throw OverflowException("The next number is out of range for IntNative.")
}
return IntNative(res)
}
}
extend UInt64 <: JsonDeserializable<UInt64> {
public static func fromJson(r: JsonReader): UInt64 {
let (res, overflow) = r.readUInt()
if (overflow) {
throw OverflowException("The next number is out of range for UInt64.")
}
return res
}
}
extend UInt32 <: JsonDeserializable<UInt32> {
public static func fromJson(r: JsonReader): UInt32 {
let (res, overflow) = r.readUInt()
if (overflow || res > UInt64(MAXVAL_UI32)) {
throw OverflowException("The next number is out of range for UInt32.")
}
return UInt32(res)
}
}
extend UInt16 <: JsonDeserializable<UInt16> {
public static func fromJson(r: JsonReader): UInt16 {
let (res, overflow) = r.readUInt()
if (overflow || res > UInt64(MAXVAL_UI16)) {
throw OverflowException("The next number is out of range for UInt16.")
}
return UInt16(res)
}
}
extend UInt8 <: JsonDeserializable<UInt8> {
public static func fromJson(r: JsonReader): UInt8 {
let (res, overflow) = r.readUInt()
if (overflow || res > UInt64(MAXVAL_UI8)) {
throw OverflowException("The next number is out of range for UInt8.")
}
return UInt8(res)
}
}
extend UIntNative <: JsonDeserializable<UIntNative> {
public static func fromJson(r: JsonReader): UIntNative {
let (res, overflow) = r.readUInt()
if (overflow || (!isNative64 && (res > UInt64(MAXVAL_UI32)))) {
throw OverflowException("The next number is out of range for UIntNative.")
}
return UIntNative(res)
}
}
extend Float64 <: JsonDeserializable<Float64> {
public static func fromJson(r: JsonReader): Float64 {
r.readFloat()
}
}
extend Float32 <: JsonDeserializable<Float32> {
public static func fromJson(r: JsonReader): Float32 {
return Float32(r.readFloat())
}
}
extend Float16 <: JsonDeserializable<Float16> {
public static func fromJson(r: JsonReader): Float16 {
return Float16(r.readFloat())
}
}
extend<T> Array<T> <: JsonDeserializable<Array<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): Array<T> {
return ArrayList<T>.fromJson(r).toArray()
}
}
extend<T> ArrayList<T> <: JsonDeserializable<ArrayList<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): ArrayList<T> {
let result = ArrayList<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.add(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> HashMap<String, T> <: JsonDeserializable<HashMap<String, T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): HashMap<String, T> {
let result = HashMap<String, T>()
r.startObject()
if (r.peek() == EndObject) {
r.endObject()
return result
}
while (true) {
let key = (r.readName() as String).getOrThrow()
let value = r.readValue<T>()
result.add(key, value)
if (r.peeked == PEEK_STATE_OBJECT_END) {
break
}
}
r.endObject()
return result
}
}
extend<T> HashSet<T> <: JsonDeserializable<HashSet<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): HashSet<T> {
let result = HashSet<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.add(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> LinkedList<T> <: JsonDeserializable<LinkedList<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): LinkedList<T> {
let result = LinkedList<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.addLast(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> ArrayQueue<T> <: JsonDeserializable<ArrayQueue<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): ArrayQueue<T> {
let result = ArrayQueue<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.add(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> ArrayDeque<T> <: JsonDeserializable<ArrayDeque<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): ArrayDeque<T> {
let result = ArrayDeque<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.addLast(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> ArrayStack<T> <: JsonDeserializable<ArrayStack<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): ArrayStack<T> {
let result = ArrayStack<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.add(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> TreeSet<T> <: JsonDeserializable<TreeSet<T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): TreeSet<T> {
let result = TreeSet<T>()
r.startArray()
if (r.peek() == EndArray) {
r.endArray()
return result
}
while (true) {
result.add(r.readValue<T>())
if (r.peeked == PEEK_STATE_ARRAY_END) {
break
}
}
r.endArray()
return result
}
}
extend<T> TreeMap<String, T> <: JsonDeserializable<TreeMap<String, T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): TreeMap<String, T> {
let result = TreeMap<String, T>()
r.startObject()
if (r.peek() == EndObject) {
r.endObject()
return result
}
while (true) {
let key = (r.readName() as String).getOrThrow()
let value = r.readValue<T>()
result.add(key, value)
if (r.peeked == PEEK_STATE_OBJECT_END) {
break
}
}
r.endObject()
return result
}
}
extend<T> ConcurrentHashMap<String, T> <: JsonDeserializable<ConcurrentHashMap<String, T>> where T <: JsonDeserializable<T> {
public static func fromJson(r: JsonReader): ConcurrentHashMap<String, T> {
let result = ConcurrentHashMap<String, T>()
r.startObject()
if (r.peek() == EndObject) {
r.endObject()
return result
}
while (true) {
let key = (r.readName() as String).getOrThrow()
let value = r.readValue<T>()
result.add(key, value)
if (r.peeked == PEEK_STATE_OBJECT_END) {
break
}
}
r.endObject()
return result
}
}
let DIGITS_UI64: Array<UInt64> = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 100, 100, 100, 100, 100, 100, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 100, 100, 100, 100, 100,
100, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
const HEXADECIMAL_OVERFLOW_LIMIT_UI64 = MAXVAL_UI64 / 16
const OCTAL_OVERFLOW_LIMIT_UI64 = MAXVAL_UI64 / 8
const BINARY_OVERFLOW_LIMIT_UI64 = MAXVAL_UI64 / 2
const DECIMAL_OVERFLOW_LIMIT_UI64 = MAXVAL_UI64 / 10
func isDecimalDigit(byte: Byte): Bool {
return byte >= b'0' && byte <= b'9'
}