///|
/// Encode an ordered cohort input; identities must be unique.
pub fn encode_cohort_usage(
usages : ArrayView[Usage],
) -> String raise PricingError {
check_cohort(usages)
let json : Json = {
"schema": "jieheng.cohort-usage.v1",
"usages": usages.map(usage_json),
}
bounded_json(json)
}
///|
pub fn decode_cohort_usage(text : String) -> Array[Usage] raise PricingError {
let root = fields(parse_document(text), ["schema", "usages"], "cohort")
expect_value(root, "schema", "jieheng.cohort-usage.v1", "cohort")
let items = bounded_items(root["usages"], 256, "cohort.usages")
let usages = items.map(usage_from_json)
check_cohort(usages[:])
usages
}
///|
fn bounded_items(
value : Json,
max : Int32,
path : String,
) -> Array[Json] raise PricingError {
guard value is Array(items) else {
invalid("type", path, "expected an array")
return []
}
if items.length() == 0 || items.length() > max {
invalid("size", path, "expected 1 to \{max} entries")
}
items
}
///|
fn bounded_json(value : Json) -> String raise PricingError {
let text = value.stringify()
if text.length() > 1048576 {
invalid(
"size", "$", "encoded document exceeds the 1048576 UTF-16 code unit exchange limit; split the request",
)
}
text
}
///|
/// Structural encoding only; verify against trusted plans and usages on receipt.
pub fn encode_cohort(report : CohortComparison) -> String raise PricingError {
if report.rows.length() == 0 || report.rows.length() > 256 {
invalid("size", "cohort.rows", "expected 1 to 256 rows")
}
let json : Json = {
"schema": "jieheng.cohort-comparison.v1",
"rows": report.rows.map(comparison_json),
"baseline_exact": report.baseline_exact,
"candidate_exact": report.candidate_exact,
"baseline_settled": report.baseline_settled,
"candidate_settled": report.candidate_settled,
"exact_delta": report.exact_delta,
"settled_delta": report.settled_delta,
}
bounded_json(json)
}
///|
pub fn decode_cohort(text : String) -> CohortComparison raise PricingError {
let root = fields(
parse_document(text),
[
"schema", "rows", "baseline_exact", "candidate_exact", "baseline_settled",
"candidate_settled", "exact_delta", "settled_delta",
],
"cohort",
)
expect_value(root, "schema", "jieheng.cohort-comparison.v1", "cohort")
{
rows: bounded_items(root["rows"], 256, "cohort.rows").map(
comparison_from_json,
),
baseline_exact: text_value(root["baseline_exact"], "cohort.baseline_exact"),
candidate_exact: text_value(
root["candidate_exact"],
"cohort.candidate_exact",
),
baseline_settled: text_value(
root["baseline_settled"],
"cohort.baseline_settled",
),
candidate_settled: text_value(
root["candidate_settled"],
"cohort.candidate_settled",
),
exact_delta: text_value(root["exact_delta"], "cohort.exact_delta"),
settled_delta: text_value(root["settled_delta"], "cohort.settled_delta"),
}
}