///|
pub struct PayloadField {
key : String
value : String
} derive(Eq, Debug)
///|
pub fn PayloadField::new(key : String, value : String) -> PayloadField {
{ key, value }
}
///|
pub(all) enum PayloadKind {
ObjectPayload
ArrayPayload
ScalarPayload
InvalidPayload
} derive(Eq, Debug)
///|
pub struct PayloadDocument {
body : String
json : Json?
kind : PayloadKind
error : String
} derive(Eq, Debug)
///|
pub fn PayloadDocument::invalid(
body : String,
error : String,
) -> PayloadDocument {
{ body, json: None, kind: InvalidPayload, error }
}
///|
pub fn PayloadDocument::valid(body : String, json : Json) -> PayloadDocument {
let kind = match json {
Object(_) => ObjectPayload
Array(_) => ArrayPayload
_ => ScalarPayload
}
{ body, json: Some(json), kind, error: "" }
}
///|
pub fn parse_payload_document(body : String) -> PayloadDocument {
PayloadDocument::valid(body, @json.parse(body)) catch {
error => PayloadDocument::invalid(body, error.to_string())
}
}
///|
pub fn payload_is_valid_json(body : String) -> Bool {
parse_payload_document(body).json is Some(_)
}
///|
fn json_scalar_text(value : Json) -> String {
match value {
String(text) => text
True => "true"
False => "false"
Null => "null"
Number(_, ..) => value.stringify()
Array(_) | Object(_) => value.stringify()
}
}
///|
pub fn json_path_value(json : Json, path : Array[String]) -> Json? {
let mut current = json
for segment in path {
match current {
Object(fields) =>
match fields.get(segment) {
Some(value) => current = value
None => return None
}
_ => return None
}
}
Some(current)
}
///|
pub fn json_path_text(json : Json, path : Array[String]) -> String? {
match json_path_value(json, path) {
Some(value) => Some(json_scalar_text(value))
None => None
}
}
///|
pub fn payload_path_text(body : String, path : Array[String]) -> String? {
let document = parse_payload_document(body)
match document.json {
Some(json) => json_path_text(json, path)
None => None
}
}
///|
pub fn payload_first_path(
body : String,
paths : Array[Array[String]],
) -> String? {
let document = parse_payload_document(body)
let json = match document.json {
Some(value) => value
None => return None
}
for path in paths {
match json_path_text(json, path) {
Some(value) => return Some(value)
None => ()
}
}
None
}
///|
pub fn parse_payload_fields(body : String) -> Array[PayloadField] {
let document = parse_payload_document(body)
match document.json {
Some(Object(fields)) => {
let result : Array[PayloadField] = []
for key, value in fields {
result.push(PayloadField::new(key, json_scalar_text(value)))
}
result
}
_ => []
}
}
///|
pub fn payload_value(fields : Array[PayloadField], key : String) -> String? {
for field in fields {
if field.key == key {
return Some(field.value)
}
}
None
}
///|
pub fn payload_has_key(fields : Array[PayloadField], key : String) -> Bool {
payload_value(fields, key) is Some(_)
}
///|
pub fn payload_summary(fields : Array[PayloadField]) -> String {
let builder = StringBuilder::new()
for i in 0.. 0 {
builder.write_string(",")
}
builder.write_string(fields[i].key)
builder.write_string("=")
builder.write_string(fields[i].value)
}
builder.to_string()
}
///|
pub fn payload_keys(body : String) -> Array[String] {
let fields = parse_payload_fields(body)
Array::makei(fields.length(), index => fields[index].key)
}
///|
pub fn payload_contains_path(body : String, path : Array[String]) -> Bool {
payload_path_text(body, path) is Some(_)
}
///|
pub fn payload_document_summary(document : PayloadDocument) -> String {
match document.kind {
InvalidPayload => "invalid: " + document.error
ObjectPayload => {
let count = parse_payload_fields(document.body).length()
"object fields=" + count.to_string()
}
ArrayPayload =>
match document.json {
Some(Array(items)) => "array items=" + items.length().to_string()
_ => "array items=0"
}
ScalarPayload => "scalar"
}
}