///|
pub(all) struct ReplayRequest {
study : AliquotStudy
parameters : Array[ParameterValue]
} derive(Debug, ToJson, FromJson)
///|
pub extend ReplayRequest with @debug.Debug::{to_repr}
///|
pub extend ReplayRequest with @json.ToJson::{to_json}
///|
pub extend ReplayRequest with @json.FromJson::{from_json}
///|
// Deriving FromJson checks required types. Also reject unknown fields so that
// e.g. sulfate is never silently dropped from this deliberately narrow model.
fn known_fields(original : Json, decoded : Json) -> Bool {
match (original, decoded) {
(Object(a), Object(b)) => {
for key, value in a {
match b.get(key) {
Some(other) => if !known_fields(value, other) { return false }
None => return false
}
}
true
}
(Array(a), Array(b)) => {
if a.length() != b.length() {
return false
}
for i = 0; i < a.length(); i = i + 1 {
if !known_fields(a[i], b[i]) {
return false
}
}
true
}
_ => original == decoded
}
}
///|
fn rejected_json(message : String) -> String {
let payload : Json = { "ok": false, "error": message }
payload.stringify()
}
///|
pub fn reconcile_json(input : String) -> String {
try {
let value = @json.parse(input)
let study : AliquotStudy = @json.from_json(value)
if !known_fields(value, @json.to_json(study)) {
return rejected_json(
"unknown field or noninteger value; untracked ions/processes are not supported",
)
}
match reconcile_aliquots(study) {
Ok(result) => {
let payload : Json = { "ok": true, "result": @json.to_json(result) }
payload.stringify()
}
Err(error) => rejected_json(error)
}
} catch {
_ =>
rejected_json(
"invalid AliquotStudy JSON; integer units and every required field are mandatory",
)
}
}
///|
pub fn challenge_json(input : String) -> String {
try {
let value = @json.parse(input)
let claim : ZeroTransferClaim = @json.from_json(value)
if !known_fields(value, @json.to_json(claim)) {
return rejected_json("unknown field or noninteger value in claim/study")
}
match challenge_zero_transfer(claim) {
Ok(result) => {
let payload : Json = { "ok": true, "result": @json.to_json(result) }
payload.stringify()
}
Err(error) => rejected_json(error)
}
} catch {
_ => rejected_json("invalid ZeroTransferClaim JSON")
}
}
///|
pub fn replay_json(input : String) -> String {
try {
let value = @json.parse(input)
let request : ReplayRequest = @json.from_json(value)
if !known_fields(value, @json.to_json(request)) {
return rejected_json("unknown field or noninteger value in replay/study")
}
match replay_handling(request.study, request.parameters) {
Ok(result) => {
let payload : Json = { "ok": true, "result": @json.to_json(result) }
payload.stringify()
}
Err(error) => rejected_json(error)
}
} catch {
_ => rejected_json("invalid ReplayRequest JSON")
}
}