///|
pub fn MemberKind::label(self : MemberKind) -> String {
match self {
Regular => "regular"
SymbolTable => "symbol_table"
NameTable => "name_table"
}
}
///|
pub fn ChangeKind::label(self : ChangeKind) -> String {
match self {
Added => "added"
Removed => "removed"
Modified => "modified"
}
}
///|
// Decimal strings avoid precision loss in consumers that use IEEE-754 numbers.
fn metadata_value(value : Int64?) -> Json {
match value {
Some(n) => Json::string(n.to_string())
None => Json::null()
}
}
///|
fn index_value(value : Int?) -> Json {
match value {
Some(n) => Json(n)
None => Json::null()
}
}
///|
fn member_json(entry : Member, index : Int) -> Json {
Json::object({
"index": Json(index),
"name_display": Json(entry.name_text()),
"name_hex": Json(entry.name_hex()),
"kind": Json(entry.kind.label()),
"header_offset": Json(entry.header_offset),
"data_offset": Json(entry.data_offset),
"size": Json(entry.size),
"stored_size": Json(entry.stored_size),
"metadata": Json::object({
"timestamp": metadata_value(entry.metadata.timestamp),
"uid": metadata_value(entry.metadata.uid),
"gid": metadata_value(entry.metadata.gid),
"mode": metadata_value(entry.metadata.mode),
}),
})
}
///|
/// Schema version 1. Display names may be lossy; name_hex is the raw identity.
/// Metadata numbers use decimal strings or null. Offsets and sizes are integers.
pub fn Archive::to_json(self : Archive) -> Json {
let entries : Array[Json] = []
for i, entry in self.records {
entries.push(member_json(entry, i))
}
Json::object({
"schema_version": Json(1),
"format": Json("ar"),
"byte_length": Json(self.byte_length()),
"members": Json::array(entries),
"symbol_indexes": Json::array(
self.indexes.map(fn(table) {
Json::object({
"record_index": Json(table.record_index),
"format": Json(table.format),
"symbols": Json::array(
table.symbols.map(fn(symbol) {
Json::object({
"name_display": Json(
@utf8.decode_lossy(symbol.name[:], ignore_bom=false),
),
"name_hex": Json(hex_bytes(symbol.name)),
"member_index": Json(symbol.member_index),
"name_offset": Json(symbol.name_offset),
"offset_field_offset": Json(symbol.offset_field_offset),
})
}),
),
})
}),
),
})
}
///|
fn changes_json(changes : Array[MemberChange]) -> Json {
Json::array(
changes.map(fn(change) {
Json::object({
"change": Json(change.change.label()),
"name_display": Json(
@utf8.decode_lossy(change.name[:], ignore_bom=false),
),
"name_hex": Json(hex_bytes(change.name)),
"member_kind": Json(change.member_kind.label()),
"occurrence": Json(change.occurrence),
"before_index": index_value(change.before_index),
"after_index": index_value(change.after_index),
"payload_changed": Json(change.payload_changed),
"metadata_changed": Json(change.metadata_changed),
})
}),
)
}
///|
fn ambiguities_json(ambiguities : Array[MatchAmbiguity]) -> Json {
Json::array(
ambiguities.map(fn(item) {
Json::object({
"name_display": Json(@utf8.decode_lossy(item.name[:], ignore_bom=false)),
"name_hex": Json(hex_bytes(item.name)),
"member_kind": Json(item.member_kind.label()),
"before_indices": Json::array(
item.before_indices.map(fn(i) { Json(i) }),
),
"after_indices": Json::array(item.after_indices.map(fn(i) { Json(i) })),
})
}),
)
}
///|
pub fn Comparison::to_json(self : Comparison) -> Json {
Json::object({
"schema_version": Json(1),
"bytes_equal": Json(self.bytes_equal),
"comparison_mode": Json("physical"),
"order_changed": Json(self.order_changed),
"changes": changes_json(self.changes),
"ambiguities": ambiguities_json(self.ambiguities),
})
}
///|
pub fn LogicalComparison::to_json(self : LogicalComparison) -> Json {
Json::object({
"schema_version": Json(1),
"comparison_mode": Json("logical"),
"bytes_equal": Json(self.bytes_equal),
"content_equal": Json(self.content_equal),
"metadata_changed": Json(self.metadata_changed),
"order_changed": Json(self.order_changed),
"symbols_equal": Json(self.symbols_equal),
"symbol_index_presence_changed": Json(self.symbol_index_presence_changed),
"changes": changes_json(self.changes),
"ambiguities": ambiguities_json(self.ambiguities),
})
}
///|
pub fn ParseError::to_json(self : ParseError) -> Json {
Json::object({
"schema_version": Json(1),
"error": Json::object({
"code": Json(self.code),
"offset": Json(self.offset),
"message": Json(self.message),
}),
})
}