///|
using @json {trait ToJson}
///|
fn json_number(value : Int32) -> Json {
Json::number(value.to_double())
}
///|
fn json_string(value : String) -> Json {
Json::string(value)
}
///|
fn[T : ToJson] json_option(value : T?) -> Json {
match value {
Option::Some(v) => v.to_json()
Option::None => Json::null()
}
}
///|
fn json_docs(contents : String) -> Json {
Json::object({ "contents": json_string(contents) })
}
///|
fn package_name_string(pkg : RPackageName) -> String {
match pkg.version {
Option::Some(v) => pkg.ns + ":" + pkg.name + "@" + v
Option::None => pkg.ns + ":" + pkg.name
}
}
///|
fn sort_strings_for_json(items : Array[String]) -> Unit {
let len = items.length()
if len < 2 {
return
}
for i in 1..= 0 && string_lex_compare(items[j], key) > 0 {
items[j + 1] = items[j]
j = j - 1
}
items[j + 1] = key
}
}
///|
fn string_lex_compare(a : String, b : String) -> Int32 {
let a_chars = a.to_array()
let b_chars = b.to_array()
let a_len = a_chars.length()
let b_len = b_chars.length()
let min_len = if a_len < b_len { a_len } else { b_len }
for i in 0.. b_len {
1
} else {
0
}
}
///|
fn[T : ToJson] map_sorted_to_json(items : Map[String, T]) -> Json {
let keys : Array[String] = []
for key, _ in items {
keys.push(key)
}
sort_strings_for_json(keys)
let result : Map[String, Json] = Map([])
for key in keys {
match items.get(key) {
Option::Some(value) => result.set(key, value.to_json())
Option::None => ()
}
}
Json::object(result)
}
///|
pub impl ToJson for RType with fn to_json(self) {
match self {
RType::Bool => json_string("bool")
RType::U8 => json_string("u8")
RType::U16 => json_string("u16")
RType::U32 => json_string("u32")
RType::U64 => json_string("u64")
RType::S8 => json_string("s8")
RType::S16 => json_string("s16")
RType::S32 => json_string("s32")
RType::S64 => json_string("s64")
RType::F32 => json_string("f32")
RType::F64 => json_string("f64")
RType::Char => json_string("char")
RType::String_ => json_string("string")
RType::ErrorContext => json_string("error-context")
RType::Id(id) => json_number(id)
}
}
///|
pub impl ToJson for RFunctionKind with fn to_json(self) {
match self {
RFunctionKind::Freestanding => json_string("freestanding")
RFunctionKind::Getter => json_string("getter")
RFunctionKind::Setter => json_string("setter")
RFunctionKind::MethodGetter(id) =>
Json::object({ "method-getter": json_number(id) })
RFunctionKind::MethodSetter(id) =>
Json::object({ "method-setter": json_number(id) })
RFunctionKind::StaticGetter(id) =>
Json::object({ "static-getter": json_number(id) })
RFunctionKind::StaticSetter(id) =>
Json::object({ "static-setter": json_number(id) })
RFunctionKind::AsyncFreestanding => json_string("async-freestanding")
RFunctionKind::AsyncMethod(id) =>
Json::object({ "async-method": json_number(id) })
RFunctionKind::AsyncStatic(id) =>
Json::object({ "async-static": json_number(id) })
RFunctionKind::Constructor(id) =>
Json::object({ "constructor": json_number(id) })
RFunctionKind::Method(id) => Json::object({ "method": json_number(id) })
RFunctionKind::Static(id) => Json::object({ "static": json_number(id) })
}
}
///|
pub impl ToJson for RFunction with fn to_json(self) {
let params_json : Array[Json] = []
for item in self.params {
let (name, ty) = item
params_json.push(
Json::object({ "name": json_string(name), "type": ty.to_json() }),
)
}
let obj : Map[String, Json] = Map([])
match self.docs {
Some(text) => obj.set("docs", json_docs(text))
None => ()
}
obj.set("kind", self.kind.to_json())
obj.set("name", json_string(self.name))
obj.set("params", Json::array(params_json))
match self.result {
Some(result) => obj.set("result", result.to_json())
None => ()
}
if self.external_id is Some(id) {
obj.set("external-id", json_string(id))
}
Json::object(obj)
}
///|
fn world_items_to_json(items : Map[String, RWorldItem]) -> Json {
let result : Map[String, Json] = Map([])
for name, item in items {
match item {
RWorldItem::Interface(iface_ref) =>
result.set(name, Json::object({ "interface": iface_ref.to_json() }))
RWorldItem::Function(func) =>
result.set(name, Json::object({ "function": func.to_json() }))
RWorldItem::Type(id) =>
result.set(name, Json::object({ "type": json_number(id) }))
}
}
map_sorted_to_json(result)
}
///|
pub impl ToJson for RWorldItem with fn to_json(self) {
match self {
RWorldItem::Interface(iface_ref) =>
Json::object({ "interface": iface_ref.to_json() })
RWorldItem::Function(func) => Json::object({ "function": func.to_json() })
RWorldItem::Type(id) => Json::object({ "type": json_number(id) })
}
}
///|
pub impl ToJson for RInterfaceRef with fn to_json(self) {
let obj : Map[String, Json] = { "id": json_number(self.id) }
if self.external_id is Some(id) {
obj.set("external-id", json_string(id))
}
Json::object(obj)
}
///|
pub impl ToJson for RInterface with fn to_json(self) {
let obj : Map[String, Json] = Map([])
match self.docs {
Some(text) => obj.set("docs", json_docs(text))
None => ()
}
obj.set("functions", map_sorted_to_json(self.functions))
obj.set("name", json_option(self.name))
obj.set("package", json_option(self.pkg))
obj.set("types", map_sorted_to_json(self.types))
Json::object(obj)
}
///|
pub impl ToJson for RWorld with fn to_json(self) {
let obj : Map[String, Json] = Map([])
match self.docs {
Some(text) => obj.set("docs", json_docs(text))
None => ()
}
obj.set("exports", world_items_to_json(self.exports))
obj.set("imports", world_items_to_json(self.imports))
obj.set("name", json_string(self.name))
obj.set("package", json_option(self.pkg))
Json::object(obj)
}
///|
pub impl ToJson for RPackageName with fn to_json(self) {
json_string(package_name_string(self))
}
///|
pub impl ToJson for RPackage with fn to_json(self) {
Json::object({
"interfaces": map_sorted_to_json(self.interfaces),
"name": self.name.to_json(),
"worlds": map_sorted_to_json(self.worlds),
})
}
///|
pub impl ToJson for RTypeOwner with fn to_json(self) {
match self {
RTypeOwner::Interface(id) => Json::object({ "interface": json_number(id) })
RTypeOwner::World(id) => Json::object({ "world": json_number(id) })
RTypeOwner::None => Json::null()
}
}
///|
pub impl ToJson for RRecordField with fn to_json(self) {
Json::object({
"name": json_string(self.name),
"type": self.field_type.to_json(),
})
}
///|
pub impl ToJson for RVariantCase with fn to_json(self) {
Json::object({
"name": json_string(self.name),
"type": json_option(self.case_type),
})
}
///|
pub impl ToJson for RHandleKind with fn to_json(self) {
match self {
RHandleKind::Own(id) => Json::object({ "own": json_number(id) })
RHandleKind::Borrow(id) => Json::object({ "borrow": json_number(id) })
}
}
///|
pub impl ToJson for RTypeKind with fn to_json(self) {
match self {
RTypeKind::Record(fields) =>
Json::object({
"record": Json::object({ "fields": ToJson::to_json(fields) }),
})
RTypeKind::Variant(cases) =>
Json::object({
"variant": Json::object({ "cases": ToJson::to_json(cases) }),
})
RTypeKind::List(inner) => Json::object({ "list": inner.to_json() })
RTypeKind::FixedLengthList(inner, size) =>
Json::object({
"fixed-length-list": Json::array([
inner.to_json(),
ToJson::to_json(size),
]),
})
RTypeKind::Map(key, value) =>
Json::object({ "map": Json::array([key.to_json(), value.to_json()]) })
RTypeKind::Option(inner) => Json::object({ "option": inner.to_json() })
RTypeKind::Future(inner) => Json::object({ "future": json_option(inner) })
RTypeKind::Stream(inner) => Json::object({ "stream": json_option(inner) })
RTypeKind::Result(ok~, err~) =>
Json::object({
"result": Json::object({
"err": json_option(err),
"ok": json_option(ok),
}),
})
RTypeKind::Tuple(types) =>
Json::object({
"tuple": Json::object({ "types": ToJson::to_json(types) }),
})
RTypeKind::Flags(names) => {
let flags_json : Array[Json] = []
for name in names {
flags_json.push(Json::object({ "name": json_string(name) }))
}
Json::object({
"flags": Json::object({ "flags": Json::array(flags_json) }),
})
}
RTypeKind::Enum(names) => {
let cases_json : Array[Json] = []
for name in names {
cases_json.push(Json::object({ "name": json_string(name) }))
}
Json::object({
"enum": Json::object({ "cases": Json::array(cases_json) }),
})
}
RTypeKind::Alias(ty) => Json::object({ "type": ty.to_json() })
RTypeKind::Resource => json_string("resource")
RTypeKind::Handle(handle) => Json::object({ "handle": handle.to_json() })
}
}
///|
pub impl ToJson for RTypeDef with fn to_json(self) {
let obj : Map[String, Json] = Map([])
match self.docs {
Some(text) => obj.set("docs", json_docs(text))
None => ()
}
obj.set("kind", self.kind.to_json())
obj.set("name", json_option(self.name))
obj.set("owner", self.owner.to_json())
if self.external_id is Some(id) {
obj.set("external-id", json_string(id))
}
Json::object(obj)
}
///|
pub impl ToJson for Resolve with fn to_json(self) {
Json::object({
"interfaces": ToJson::to_json(self.interfaces),
"packages": ToJson::to_json(self.packages),
"types": ToJson::to_json(self.types),
"worlds": ToJson::to_json(self.worlds),
})
}
///|
pub impl ToJson for ResolveInput with fn to_json(self) {
Json::object({
"resolve": self.resolve.to_json(),
"world_id": json_number(self.world_id),
})
}
///|
pub extend RType with ToJson::{to_json}
///|
pub extend RFunctionKind with ToJson::{to_json}
///|
pub extend RFunction with ToJson::{to_json}
///|
pub extend RWorldItem with ToJson::{to_json}
///|
pub extend RInterfaceRef with ToJson::{to_json}
///|
pub extend RInterface with ToJson::{to_json}
///|
pub extend RWorld with ToJson::{to_json}
///|
pub extend RPackageName with ToJson::{to_json}
///|
pub extend RPackage with ToJson::{to_json}
///|
pub extend RTypeOwner with ToJson::{to_json}
///|
pub extend RRecordField with ToJson::{to_json}
///|
pub extend RVariantCase with ToJson::{to_json}
///|
pub extend RHandleKind with ToJson::{to_json}
///|
pub extend RTypeKind with ToJson::{to_json}
///|
pub extend RTypeDef with ToJson::{to_json}
///|
pub extend Resolve with ToJson::{to_json}
///|
pub extend ResolveInput with ToJson::{to_json}