///|
/// Human-readable JSON kind used in diagnostics.
fn json_kind(value : Json) -> String {
match value {
Null => "null"
True | False => "boolean"
Number(_, ..) => "number"
String(_) => "string"
Array(_) => "array"
Object(_) => "object"
}
}
///|
fn json_object(value : Json) -> Map[String, Json]? {
match value {
Object(members) => Some(members)
_ => None
}
}
///|
fn json_string(value : Json) -> String? {
match value {
String(text) => Some(text)
_ => None
}
}
///|
/// Status is an integer JSON number representable by MoonBit Int.
fn json_int(value : Json) -> Int? {
match value {
Number(number, ..) =>
if number.is_nan() ||
number.is_inf() ||
number.trunc() != number ||
number < -2_147_483_648.0 ||
number > 2_147_483_647.0 {
None
} else {
Some(number.to_int())
}
_ => None
}
}
///|
fn map_keys(members : Map[String, Json]) -> Array[String] {
let keys : Array[String] = []
for key in members.keys() {
keys.push(key)
}
keys
}
///|
fn is_reserved_member(name : String) -> Bool {
name == "type" ||
name == "title" ||
name == "status" ||
name == "detail" ||
name == "instance"
}
///|
/// UTF-8 byte length, not code point length.
fn utf8_length(value : String) -> Int {
@utf8.encode(value).length()
}
///|
/// Code-unit lexical ordering, independent of MoonBit's shortlex String Compare.
fn lexical_compare(left : String, right : String) -> Int {
let a = left.to_array()
let b = right.to_array()
let length = if a.length() < b.length() { a.length() } else { b.length() }
for i = 0; i < length; i = i + 1 {
if a[i] < b[i] {
return -1
}
if a[i] > b[i] {
return 1
}
}
if a.length() < b.length() {
-1
} else if a.length() > b.length() {
1
} else {
0
}
}