pub mod dump;
pub mod error;
pub mod types;
mod validate;
pub use error::HirError;
pub use types::{
Annotation, AnnotationArg, Declaration, DictEntry, DirectiveRecord, DirectiveValue, Event,
Expr, Generator, OptimizationState, Position, PreprocessingSnapshot, PreprocessingState,
Program, Protocol, Rule, RuleEntry, Settings, SettingsListElement, SettingsNode, SourceFile,
Span, Stmt, SwitchArm, TranslationState, default_var_index,
};
use serde_json::Value;
pub fn parse_str(input: &str) -> Result<Program, HirError> {
let value: Value = serde_json::from_str(input)?;
parse_value(value)
}
pub fn parse_value(value: Value) -> Result<Program, HirError> {
validate::check_envelope(&value)?;
validate::check_unknown_kinds(&value)?;
let program: Program = serde_json::from_value(value)?;
program.validate()?;
Ok(program)
}
impl Program {
pub fn validate(&self) -> Result<(), HirError> {
validate::validate_program(self)
}
pub fn dump(&self) -> String {
dump::dump(self)
}
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::validate::check_envelope;
#[test]
fn v2_envelope_is_accepted_and_v1_is_rejected_before_body_inspection() {
let v2 = json!({
"protocol": { "name": "wright/opy-hir", "version": "2.0.0" }
});
assert!(check_envelope(&v2).is_ok());
let v1 = json!({
"protocol": { "name": "wright/opy-hir", "version": "1.1.0" },
"rules": [{ "kind": "malformed-v1-body" }]
});
let error = check_envelope(&v1).expect_err("v1 payload must not enter the v2 parser");
assert_eq!(error.code(), "incompatible-protocol");
}
}