Skip to main content

rulemorph/
model.rs

1use serde::Deserialize;
2use serde_json::Value as JsonValue;
3
4#[derive(Debug, Deserialize, Clone)]
5#[serde(deny_unknown_fields)]
6pub struct RuleFile {
7    pub version: u8,
8    pub input: InputSpec,
9    #[serde(default)]
10    pub output: Option<OutputSpec>,
11    #[serde(default)]
12    pub record_when: Option<Expr>,
13    #[serde(default)]
14    pub mappings: Vec<Mapping>,
15    #[serde(default)]
16    pub steps: Option<Vec<V2RuleStep>>,
17    #[serde(default)]
18    pub finalize: Option<FinalizeSpec>,
19}
20
21#[derive(Debug, Deserialize, Clone)]
22#[serde(deny_unknown_fields)]
23pub struct OutputSpec {
24    pub name: Option<String>,
25}
26
27#[derive(Debug, Deserialize, Clone)]
28#[serde(deny_unknown_fields)]
29pub struct InputSpec {
30    pub format: InputFormat,
31    pub csv: Option<CsvInput>,
32    pub json: Option<JsonInput>,
33}
34
35#[derive(Debug, Deserialize, Clone, Copy)]
36#[serde(rename_all = "lowercase")]
37pub enum InputFormat {
38    Csv,
39    Json,
40}
41
42fn default_true() -> bool {
43    true
44}
45
46fn default_delimiter() -> String {
47    ",".to_string()
48}
49
50#[derive(Debug, Deserialize, Clone)]
51#[serde(deny_unknown_fields)]
52pub struct CsvInput {
53    #[serde(default = "default_true")]
54    pub has_header: bool,
55    #[serde(default = "default_delimiter")]
56    pub delimiter: String,
57    pub columns: Option<Vec<Column>>,
58}
59
60#[derive(Debug, Deserialize, Clone)]
61#[serde(deny_unknown_fields)]
62pub struct Column {
63    pub name: String,
64    #[serde(rename = "type")]
65    pub value_type: Option<String>,
66}
67
68#[derive(Debug, Deserialize, Clone)]
69#[serde(deny_unknown_fields)]
70pub struct JsonInput {
71    pub records_path: Option<String>,
72}
73
74#[derive(Debug, Deserialize, Clone)]
75#[serde(deny_unknown_fields)]
76pub struct Mapping {
77    pub target: String,
78    pub source: Option<String>,
79    pub value: Option<JsonValue>,
80    pub expr: Option<Expr>,
81    pub when: Option<Expr>,
82    #[serde(rename = "type")]
83    pub value_type: Option<String>,
84    #[serde(default)]
85    pub required: bool,
86    pub default: Option<JsonValue>,
87}
88
89// =============================================================================
90// v2 Rule Steps / Finalize
91// =============================================================================
92
93#[derive(Debug, Deserialize, Clone)]
94#[serde(deny_unknown_fields)]
95pub struct V2RuleStep {
96    #[serde(default)]
97    pub name: Option<String>,
98    #[serde(default)]
99    pub mappings: Option<Vec<Mapping>>,
100    #[serde(default)]
101    pub record_when: Option<Expr>,
102    #[serde(default)]
103    pub asserts: Option<Vec<V2Assert>>,
104    #[serde(default)]
105    pub branch: Option<V2Branch>,
106}
107
108#[derive(Debug, Deserialize, Clone)]
109#[serde(deny_unknown_fields)]
110pub struct V2Assert {
111    pub when: Expr,
112    pub error: V2AssertError,
113}
114
115#[derive(Debug, Deserialize, Clone)]
116#[serde(deny_unknown_fields)]
117pub struct V2AssertError {
118    pub code: String,
119    pub message: String,
120}
121
122#[derive(Debug, Deserialize, Clone)]
123#[serde(deny_unknown_fields)]
124pub struct V2Branch {
125    pub when: Expr,
126    pub then: String,
127    #[serde(default)]
128    pub r#else: Option<String>,
129    #[serde(rename = "return", default)]
130    pub return_: bool,
131}
132
133#[derive(Debug, Deserialize, Clone)]
134#[serde(deny_unknown_fields)]
135pub struct FinalizeSpec {
136    #[serde(default)]
137    pub filter: Option<Expr>,
138    #[serde(default)]
139    pub sort: Option<FinalizeSort>,
140    #[serde(default)]
141    pub limit: Option<usize>,
142    #[serde(default)]
143    pub offset: Option<usize>,
144    #[serde(default)]
145    pub wrap: Option<JsonValue>,
146}
147
148#[derive(Debug, Deserialize, Clone)]
149#[serde(deny_unknown_fields)]
150pub struct FinalizeSort {
151    pub by: String,
152    #[serde(default = "default_sort_order")]
153    pub order: String,
154}
155
156fn default_sort_order() -> String {
157    "asc".to_string()
158}
159
160#[derive(Debug, Deserialize, Clone, PartialEq)]
161#[serde(untagged)]
162pub enum Expr {
163    Ref(ExprRef),
164    Op(ExprOp),
165    Chain(ExprChain),
166    Literal(JsonValue),
167}
168
169#[derive(Debug, Deserialize, Clone, PartialEq)]
170#[serde(deny_unknown_fields)]
171pub struct ExprRef {
172    #[serde(rename = "ref")]
173    pub ref_path: String,
174}
175
176#[derive(Debug, Deserialize, Clone, PartialEq)]
177#[serde(deny_unknown_fields)]
178pub struct ExprOp {
179    pub op: String,
180    #[serde(default)]
181    pub args: Vec<Expr>,
182}
183
184#[derive(Debug, Deserialize, Clone, PartialEq)]
185#[serde(deny_unknown_fields)]
186pub struct ExprChain {
187    pub chain: Vec<Expr>,
188}