///|
/// A stable machine-readable diagnostic. Offsets count UTF-16 code units.
pub(all) struct Diagnostic {
code : String
path : String
message : String
offset : Int32?
related : Array[String]
} derive(Eq, ToJson, @debug.Debug)
///|
pub(all) suberror TraceError {
TraceError(Diagnostic)
} derive(@debug.Debug)
///|
fn reject(
code : String,
path : String,
message : String,
offset? : Int32,
related~ : Array[String] = [],
) -> Unit raise TraceError {
raise TraceError({ code, path, message, offset, related, })
}
///|
/// Sidecar source text is retained; no caller-supplied Json can be mutated.
pub struct SidecarInput {
priv path : String
priv text : String
}
///|
pub fn SidecarInput::new(path : String, text : String) -> SidecarInput {
{ path, text, }
}
///|
priv struct Selector {
path : String
directory : String
depth : Int32
suffix : String
entities : Map[String, String]
}
///|
priv struct Sidecar {
selector : Selector
metadata : Map[String, Json]
}
///|
/// An immutable construction-time dataset snapshot, with no filesystem access.
pub struct DatasetIndex {
priv files : Array[Selector]
priv sidecars : Array[Sidecar]
priv file_positions : Map[String, Int32]
priv source_buckets : Map[String, Map[String, SourceBucket]]
}
///|
/// One assignment of a top-level metadata field, in root-to-leaf order.
pub struct FieldOrigin {
priv path : String
priv value : Json
}
///|
pub fn FieldOrigin::path(self : FieldOrigin) -> String {
self.path
}
///|
/// Returns a defensive copy, preserving numeric source representations.
pub fn FieldOrigin::value(self : FieldOrigin) -> Json {
copy_json(self.value)
}
///|
pub struct ResolvedMetadata {
priv path : String
priv values : Map[String, Json]
priv origins : Map[String, Array[FieldOrigin]]
priv applied : Array[String]
}
///|
pub fn ResolvedMetadata::path(self : ResolvedMetadata) -> String {
self.path
}
///|
pub fn ResolvedMetadata::get(self : ResolvedMetadata, key : String) -> Json? {
self.values.get(key).map(copy_json)
}
///|
pub fn ResolvedMetadata::keys(self : ResolvedMetadata) -> Array[String] {
sorted_keys(self.values)
}
///|
pub fn ResolvedMetadata::trace(
self : ResolvedMetadata,
key : String,
) -> Array[FieldOrigin] {
match self.origins.get(key) {
Some(origins) => origins.copy()
None => []
}
}
///|
pub fn ResolvedMetadata::applied_sidecars(
self : ResolvedMetadata,
) -> Array[String] {
self.applied.copy()
}
///|
/// Sorted object keys, preserved array order and numeric lexemes; no float math.
pub fn ResolvedMetadata::to_json(self : ResolvedMetadata) -> String {
canonical_json(Json::object(self.values))
}
///|
fn ResolvedMetadata::report_value(self : ResolvedMetadata) -> Json {
let fields : Map[String, Json] = Map([])
for key in self.keys() {
fields[key] = Json::array(
self
.trace(key)
.map(origin => {
Json::object({
"path": Json::string(origin.path),
"value": copy_json(origin.value),
})
}),
)
}
Json::object({
"data_path": Json::string(self.path),
"metadata": Json::object(self.values),
"applied_sidecars": Json::array(self.applied.map(Json::string)),
"fields": Json::object(fields),
})
}
///|
pub fn ResolvedMetadata::to_report_json(self : ResolvedMetadata) -> String {
canonical_json(self.report_value())
}
///|
pub extend Diagnostic with Eq::{equal, not_equal}
///|
pub extend Diagnostic with ToJson::{to_json}
///|
/// Deterministic JSON for logs and CLI error streams.
pub fn Diagnostic::to_report_json(self : Diagnostic) -> String {
canonical_json(self.to_json())
}
///|
pub extend Diagnostic with @debug.Debug::{to_repr}
///|
pub extend TraceError with @debug.Debug::{to_repr}