1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct BrddError {
6 pub code: String,
7 pub message: String,
8}
9
10pub trait ValidationContext {
12 fn add_error(&mut self, code: String, message: String);
13 fn is_valid(&self) -> bool;
14 fn get_errors(&self) -> &[BrddError];
15}
16
17pub trait ExecutionContext<T>: ValidationContext {
19 fn add_effect(&mut self, code: String);
20 fn add_setter(&mut self, code: String);
21 fn set_data(&mut self, data: T);
22
23 fn get_data(&self) -> Option<&T>;
24 fn get_effects(&self) -> &[String];
25 fn get_setters(&self) -> &[String];
26 fn get_status(&self) -> u16;
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct DefaultExecutionContext<T> {
32 pub data: Option<T>,
33 pub errors: Vec<BrddError>,
34 pub setters: Vec<String>,
35 pub effects: Vec<String>,
36 pub status: u16,
37}
38
39impl<T> DefaultExecutionContext<T> {
40 pub fn new(initial_data: Option<T>) -> Self {
42 Self {
43 data: initial_data,
44 errors: Vec::new(),
45 setters: Vec::new(),
46 effects: Vec::new(),
47 status: 200,
48 }
49 }
50}
51
52impl<T> ValidationContext for DefaultExecutionContext<T> {
53 fn add_error(&mut self, code: String, message: String) {
54 self.errors.push(BrddError { code, message });
55 self.status = 400; }
57
58 fn is_valid(&self) -> bool {
59 self.errors.is_empty()
60 }
61
62 fn get_errors(&self) -> &[BrddError] {
63 &self.errors
64 }
65}
66
67impl<T> ExecutionContext<T> for DefaultExecutionContext<T> {
68 fn add_effect(&mut self, code: String) {
69 self.effects.push(code);
70 }
71
72 fn add_setter(&mut self, code: String) {
73 self.setters.push(code);
74 }
75
76 fn set_data(&mut self, data: T) {
77 self.data = Some(data);
78 }
79
80 fn get_data(&self) -> Option<&T> {
81 self.data.as_ref()
82 }
83
84 fn get_effects(&self) -> &[String] {
85 &self.effects
86 }
87
88 fn get_setters(&self) -> &[String] {
89 &self.setters
90 }
91
92 fn get_status(&self) -> u16 {
93 self.status
94 }
95}
96
97pub trait ValidateService<I> {
99 fn validate(&self, ctx: &mut dyn ValidationContext, input: &I);
100}
101
102pub trait EnrichService<I, E, T> {
104 fn enrich(&self, ctx: &mut dyn ExecutionContext<T>, input: &I) -> Result<E, BrddError>;
105}
106
107pub trait ClientService<I, T> {
109 fn execute(&self, ctx: &mut dyn ExecutionContext<T>, input: &I);
110}
111
112pub trait UseCase<I, O> {
114 fn execute(&self, input: I) -> DefaultExecutionContext<O>;
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_initialization() {
123 let ctx = DefaultExecutionContext::new(Some(1));
124 assert_eq!(ctx.get_data(), Some(&1));
125 assert!(ctx.is_valid());
126 assert_eq!(ctx.get_status(), 200);
127 assert!(ctx.get_errors().is_empty());
128 assert!(ctx.get_effects().is_empty());
129 assert!(ctx.get_setters().is_empty());
130 }
131
132 #[test]
133 fn test_add_error() {
134 let mut ctx: DefaultExecutionContext<i32> = DefaultExecutionContext::new(None);
135 ctx.add_error("R001".to_string(), "Invalid".to_string());
136
137 assert!(!ctx.is_valid());
138 assert_eq!(ctx.get_status(), 400);
139 assert_eq!(ctx.get_errors().len(), 1);
140 assert_eq!(ctx.get_errors()[0].code, "R001");
141 }
142
143 #[test]
144 fn test_add_effect_and_setter() {
145 let mut ctx: DefaultExecutionContext<i32> = DefaultExecutionContext::new(None);
146 ctx.add_effect("E001".to_string());
147 ctx.add_setter("S001".to_string());
148
149 assert_eq!(ctx.get_effects().len(), 1);
150 assert_eq!(ctx.get_effects()[0], "E001");
151 assert_eq!(ctx.get_setters().len(), 1);
152 assert_eq!(ctx.get_setters()[0], "S001");
153 }
154
155 #[test]
156 fn test_set_data() {
157 let mut ctx: DefaultExecutionContext<i32> = DefaultExecutionContext::new(None);
158 ctx.set_data(2);
159 assert_eq!(ctx.get_data(), Some(&2));
160 }
161}
162
163pub use brdd_macros::{brdd_use_case, brdd_rule};
164