use super::super::parser::{Plan, Refused, Source, Stage};
use crate::serve::storage::Failure;
pub(super) fn parse(text: &str) -> Result<Result<Plan, Refused>, Failure> {
let parsed = super::rg::parsed(text)?;
if braces(text) {
parsed
.map(Ok)
.map_err(|error| Failure::new(error.code(), error.to_string()))
} else {
Ok(parsed)
}
}
pub(super) fn shaped(plan: &Plan) -> bool {
matches!(plan.source, Source::Shaped(_))
|| plan
.stages
.iter()
.any(|stage| matches!(stage.value, Stage::Shape(_)))
}
pub(super) fn program(text: &str, parsed: &Result<Plan, Refused>) -> String {
match parsed {
Ok(plan) if shaped(plan) => super::plan::jq(plan).to_owned(),
_ => text.to_owned(),
}
}
fn braces(text: &str) -> bool {
let mut quote = None;
let mut escaped = false;
let mut depth = 0_usize;
let mut beginning = true;
for character in text.chars() {
if let Some(delimiter) = quote {
if escaped {
escaped = false;
} else if character == '\\' && delimiter == '"' {
escaped = true;
} else if character == delimiter {
quote = None;
}
continue;
}
if beginning && character.is_whitespace() {
continue;
}
if beginning && character == '{' {
return true;
}
beginning = false;
match character {
'\'' | '"' => quote = Some(character),
'(' | '[' | '{' => depth += 1,
')' | ']' | '}' => depth = depth.saturating_sub(1),
'|' if depth == 0 => beginning = true,
_ => {}
}
}
false
}