///|
fn cmd_parse(args : Array[String]) -> Unit {
match range_input(args) {
Err(error) => print_error("MissingOption", error)
Ok(input) =>
match @range.parse_range(input) {
Err(error) => print_range_error(error)
Ok(request) =>
println(
"{\"ok\":true,\"unit\":\{q(request.unit().name())},\"specs\":\{request.specs().length()},\"canonical\":\{q(@range.serialize_range(request))}}",
)
}
}
}
///|
fn cmd_resolve(args : Array[String]) -> Unit {
match (range_input(args), length_input(args)) {
(Ok(input), Ok(length)) =>
match @range.parse_range(input) {
Err(error) => print_range_error(error)
Ok(request) =>
match @range.resolve_byte_ranges(request, length) {
Err(error) => print_range_error(error)
Ok(result) =>
println(
"{\"ok\":true,\"original\":\{result.original_count()},\"satisfiable\":\{result.satisfiable_count()},\"unsatisfiable\":\{result.unsatisfiable_count()},\"ranges\":\{ranges_json(result.ranges())}}",
)
}
}
(Err(error), _) | (_, Err(error)) => print_error("InvalidOption", error)
}
}
///|
fn cmd_content_range(args : Array[String]) -> Unit {
match required(args, "--value") {
Err(error) => print_error("MissingOption", error)
Ok(value) =>
match @range.parse_content_range(value) {
Ok(parsed) =>
println(
"{\"ok\":true,\"canonical\":\{q(@range.serialize_content_range(parsed))}}",
)
Err(error) => print_range_error(error)
}
}
}
///|
fn cmd_accept_ranges(args : Array[String]) -> Unit {
match required(args, "--value") {
Err(error) => print_error("MissingOption", error)
Ok(value) =>
match @range.parse_accept_ranges(value) {
Ok(parsed) =>
println(
"{\"ok\":true,\"bytes\":\{parsed.supports_bytes()},\"canonical\":\{q(@range.serialize_accept_ranges(parsed))}}",
)
Err(error) => print_range_error(error)
}
}
}
///|
fn cmd_plan(args : Array[String]) -> Unit {
match (range_input(args), length_input(args)) {
(Ok(input), Ok(length)) =>
match @range.parse_range(input) {
Err(error) => print_range_error(error)
Ok(request) =>
match
@range.plan_byte_range_response(request, length, true, true, true) {
Err(error) => print_range_error(error)
Ok(plan) =>
println(
"{\"ok\":true,\"status\":\{plan.recommended_status()},\"kind\":\{q(plan_name(plan))},\"ranges\":\{ranges_json(plan.ranges())}}",
)
}
}
(Err(error), _) | (_, Err(error)) => print_error("InvalidOption", error)
}
}
///|
fn cmd_audit(args : Array[String]) -> Unit {
match range_input(args) {
Err(error) => print_error("MissingOption", error)
Ok(input) => {
let length = match option_value(args, "--length") {
Some(value) =>
match parse_i64(value) {
Ok(parsed) => parsed
Err(error) => {
print_error("InvalidOption", error)
return
}
}
None => 0L
}
match @range.parse_range(input) {
Err(error) => print_range_error(error)
Ok(request) => {
let report = @range.audit_range_request(
request,
raw_input=input,
representation_length=length,
)
if has_flag(args, "--details") {
println(
"{\"ok\":true,\"findings\":\{findings_json(report.findings())}}",
)
} else {
println("{\"ok\":true,\"findings\":\{report.findings().length()}}")
}
}
}
}
}
}
///|
fn cmd_if_range(args : Array[String]) -> Unit {
match
(required(args, "--value"), required(args, "--etag"), length_input(args)) {
(Ok(value), Ok(etag), Ok(length)) =>
match @range.parse_if_range(value) {
Err(error) => print_range_error(error)
Ok(validator) => {
let matches = @range.if_range_matches(validator, etag, length)
println(
"{\"ok\":true,\"kind\":\{q(if_range_kind_name(validator))},\"matches\":\{matches}}",
)
}
}
(Err(error), _, _) | (_, Err(error), _) | (_, _, Err(error)) =>
print_error("InvalidOption", error)
}
}
///|
fn if_range_kind_name(validator : @range.IfRangeValue) -> String {
match validator {
@range.EntityTag(_) => "EntityTag"
@range.HttpDate(_) => "HttpDate"
}
}
///|
fn has_flag(args : Array[String], name : String) -> Bool {
for value in args {
if value == name {
return true
}
}
false
}
///|
fn findings_json(findings : Array[@range.AuditFinding]) -> String {
let parts : Array[String] = []
for finding in findings {
parts.push(
"{\"kind\":\{q(finding.kind().name())},\"context\":\{q(finding.context())}}",
)
}
"[\{join(parts)}]"
}
///|
fn cmd_stats(args : Array[String]) -> Unit {
match range_input(args) {
Err(error) => print_error("MissingOption", error)
Ok(input) =>
match @range.parse_range(input) {
Err(error) => print_range_error(error)
Ok(request) =>
println(
"{\"unit\":\{q(request.unit().name())},\"specs\":\{request.specs().length()},\"input_bytes\":\{input.length()}}",
)
}
}
}
///|
fn ranges_json(ranges : Array[@range.ConcreteRange]) -> String {
let parts : Array[String] = []
for range in ranges {
parts.push(
"{\"first\":\{range.first()},\"last\":\{range.last()},\"length\":\{range.length()}}",
)
}
"[\{join(parts)}]"
}
///|
fn join(values : Array[String]) -> String {
let builder = StringBuilder()
for i = 0; i < values.length(); i = i + 1 {
if i > 0 {
builder.write_char(',')
}
builder.write_string(values[i])
}
builder.to_string()
}
///|
fn plan_name(plan : @range.ResponsePlan) -> String {
match plan {
@range.Ignore => "Ignore"
@range.Unsatisfiable(_) => "Unsatisfiable"
@range.Single(_) => "Single"
@range.Multiple(_) => "Multiple"
}
}