shex_validation/
reason.rs1use std::fmt::Display;
2
3use shex_ast::{
4 ir::{node_constraint::NodeConstraint, shape::Shape, shape_expr::ShapeExpr},
5 Node,
6};
7
8use crate::ValidatorErrors;
9
10#[derive(Debug, Clone)]
12pub enum Reason {
13 NodeConstraintPassed {
14 node: Node,
15 nc: NodeConstraint,
16 },
17 ShapeAndPassed {
18 node: Node,
19 se: ShapeExpr,
20 reasons: Vec<Vec<Reason>>,
21 },
22 ShapeOrPassed {
23 node: Node,
24 shape_expr: ShapeExpr,
25 reasons: Reasons,
26 },
27 ShapeNotPassed {
28 node: Node,
29 shape_expr: ShapeExpr,
30
31 errors_evidences: ValidatorErrors,
33 },
34 ShapePassed {
35 node: Node,
36 shape: Shape,
37 },
38}
39
40impl Display for Reason {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match self {
43 Reason::NodeConstraintPassed { node, nc } => {
44 write!(f, "Node constraint passed. Node: {node}, Constraint: {nc}",)
45 }
46 Reason::ShapeAndPassed { node, se, reasons } => {
47 write!(f, "AND passed. Node {node}, and: {se}, reasons:")?;
48 for reason in reasons {
49 write!(f, "[")?;
50 for r in reason {
51 write!(f, "{r}, ")?;
52 }
53 write!(f, "], ")?;
54 }
55 Ok(())
56 }
57 Reason::ShapePassed { node, shape } => {
58 write!(f, "Shape passed. Node {node}, shape: {shape}")
59 }
60 Reason::ShapeOrPassed {
61 node,
62 shape_expr,
63 reasons,
64 } => write!(
65 f,
66 "Shape OR passed. Node {node}, shape: {shape_expr}, reasons: {reasons}"
67 ),
68 Reason::ShapeNotPassed {
69 node,
70 shape_expr,
71 errors_evidences,
72 } => write!(
73 f,
74 "Shape NOT passed. Node {node}, shape: {shape_expr}, errors: {errors_evidences}"
75 ),
76 }
77 }
78}
79
80impl Reason {
81 pub fn as_json(&self) -> serde_json::Value {
82 match self {
83 Reason::NodeConstraintPassed { node, nc } => {
84 serde_json::json!({
85 "type": "NodeConstraintPassed",
86 "node": node.to_string(),
87 "constraint": nc.to_string()
88 })
89 }
90 Reason::ShapeAndPassed { node, se, reasons } => {
91 serde_json::json!({
92 "type": "ShapeAndPassed",
93 "node": node.to_string(),
94 "shape_expr": se.to_string(),
95 "reasons": reasons.iter().map(|r| {
96 r.iter().map(|reason| reason.as_json()).collect::<Vec<_>>()
97 }).collect::<Vec<_>>()
98 })
99 }
100 Reason::ShapePassed { node, shape } => {
101 serde_json::json!({
102 "type": "ShapePassed",
103 "node": node.to_string(),
104 "shape": shape.to_string()
105 })
106 }
107 Reason::ShapeOrPassed {
108 node,
109 shape_expr,
110 reasons: _,
111 } => {
112 serde_json::json!({
113 "type": "ShapeOrPassed",
114 "node": node.to_string(),
115 "shape_expr": shape_expr.to_string(),
116 })
120 }
121 Reason::ShapeNotPassed {
122 node,
123 shape_expr,
124 errors_evidences: _,
125 } => {
126 serde_json::json!({
127 "type": "ShapeNotPassed",
128 "node": node.to_string(),
129 "shape_expr": shape_expr.to_string(),
130 })
134 }
135 }
136 }
137}
138
139#[derive(Debug, Clone)]
140pub struct Reasons {
141 reasons: Vec<Reason>,
142}
143
144impl Reasons {
145 pub fn new(reasons: Vec<Reason>) -> Reasons {
146 Reasons { reasons }
147 }
148}
149
150impl Display for Reasons {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 for reason in self.reasons.iter() {
153 writeln!(f, " {reason}")?;
154 }
155 Ok(())
156 }
157}