boxology_cli_core/
classify.rs1#![deny(missing_docs)]
3#![forbid(unsafe_code)]
4
5use boxology_classifier::ClassificationReport;
6use boxology_schema::{Diagnostics, SchemaDocument};
7use std::fmt;
8
9type Rule = (&'static str, &'static str, &'static str);
10const D1_SOURCE: &str =
11 "specs/s4-contract-change-classification.md D1; specs/s5-manifest-and-validation.md D5";
12const PAIRING_SOURCE: &str =
13 "specs/s4-contract-change-classification.md D2 D6; specs/s5-manifest-and-validation.md D5";
14const BASE_TEXT: &str = "the checked-in schema document must satisfy the strict format-1 reader";
15const SUBMITTED_TEXT: &str =
16 "the regenerated schema document must satisfy the strict format-1 reader";
17const PAIRING_TEXT: &str =
18 "the checked-in and regenerated schema documents must pair and satisfy classifier integrity";
19const BASE: Rule = ("BXW0077", BASE_TEXT, D1_SOURCE);
20const SUBMITTED: Rule = ("BXW0078", SUBMITTED_TEXT, D1_SOURCE);
21const PAIRING: Rule = ("BXW0079", PAIRING_TEXT, PAIRING_SOURCE);
22
23#[derive(Debug)]
25pub struct ClassifyError {
26 code: &'static str,
27 side: &'static str,
28 detail: &'static str,
29 diagnostics: Diagnostics,
30}
31
32impl ClassifyError {
33 pub fn code(&self) -> &'static str {
35 self.code
36 }
37
38 pub fn side(&self) -> &'static str {
40 self.side
41 }
42
43 pub fn detail(&self) -> &'static str {
45 self.detail
46 }
47
48 pub fn diagnostics(&self) -> &Diagnostics {
50 &self.diagnostics
51 }
52
53 fn base(diagnostics: Diagnostics) -> Self {
54 Self {
55 code: BASE.0,
56 side: "base",
57 detail: BASE.1,
58 diagnostics,
59 }
60 }
61
62 fn submitted(diagnostics: Diagnostics) -> Self {
63 Self {
64 code: SUBMITTED.0,
65 side: "submitted",
66 detail: SUBMITTED.1,
67 diagnostics,
68 }
69 }
70
71 fn pairing(diagnostics: Diagnostics) -> Self {
72 Self {
73 code: PAIRING.0,
74 side: "pairing",
75 detail: PAIRING.1,
76 diagnostics,
77 }
78 }
79}
80
81impl fmt::Display for ClassifyError {
82 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(
84 formatter,
85 "{} {}: {}: {}",
86 self.code, self.side, self.detail, self.diagnostics
87 )
88 }
89}
90
91impl std::error::Error for ClassifyError {}
92
93pub fn classify(
99 base: Option<&[u8]>,
100 submitted: &[u8],
101) -> Result<ClassificationReport, ClassifyError> {
102 let base = match base {
103 Some(bytes) => Some(SchemaDocument::parse(bytes).map_err(ClassifyError::base)?),
104 None => None,
105 };
106 let submitted = SchemaDocument::parse(submitted).map_err(ClassifyError::submitted)?;
107 boxology_classifier::classify(base.as_ref(), Some(&submitted)).map_err(ClassifyError::pairing)
108}