vantage_table/table/
hooks.rs1use std::future::Future;
8use std::pin::Pin;
9use std::sync::Arc;
10
11use vantage_types::{EmptyEntity, Entity, Record};
12
13use crate::table::Table;
14use crate::traits::table_source::TableSource;
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
19pub enum Phase {
20 Normalize,
22 Populate,
24 Validate,
26}
27
28pub enum HookReturn {
30 Proceed,
32 Handled,
35}
36
37pub type BeforeFn<T> = Arc<
41 dyn for<'r> Fn(
42 &'r mut Record<<T as TableSource>::Value>,
43 &'r Table<T, EmptyEntity>,
44 ) -> Pin<Box<dyn Future<Output = vantage_core::Result<()>> + Send + 'r>>
45 + Send
46 + Sync,
47>;
48
49pub type BeforeDeleteFn<T> = Arc<
52 dyn for<'r> Fn(
53 &'r <T as TableSource>::Id,
54 &'r Record<<T as TableSource>::Value>,
55 &'r Table<T, EmptyEntity>,
56 )
57 -> Pin<Box<dyn Future<Output = vantage_core::Result<HookReturn>> + Send + 'r>>
58 + Send
59 + Sync,
60>;
61
62pub type AfterFn<T> = Arc<
65 dyn for<'r> Fn(
66 &'r <T as TableSource>::Id,
67 &'r Record<<T as TableSource>::Value>,
68 &'r Table<T, EmptyEntity>,
69 ) -> Pin<Box<dyn Future<Output = vantage_core::Result<()>> + Send + 'r>>
70 + Send
71 + Sync,
72>;
73
74pub enum Hook<T: TableSource> {
78 BeforeInsert(Phase, BeforeFn<T>),
79 BeforeUpdate(Phase, BeforeFn<T>),
80 BeforeSave(Phase, BeforeFn<T>),
81 BeforeDelete(BeforeDeleteFn<T>),
82 AfterInsert(AfterFn<T>),
83 AfterUpdate(AfterFn<T>),
84 AfterSave(AfterFn<T>),
85 AfterDelete(AfterFn<T>),
86}
87
88#[derive(Clone)]
91pub struct Hooks<T: TableSource> {
92 pub(crate) before_insert: Vec<(Phase, BeforeFn<T>)>,
93 pub(crate) before_update: Vec<(Phase, BeforeFn<T>)>,
94 pub(crate) before_delete: Vec<BeforeDeleteFn<T>>,
95 pub(crate) after_insert: Vec<AfterFn<T>>,
96 pub(crate) after_update: Vec<AfterFn<T>>,
97 pub(crate) after_delete: Vec<AfterFn<T>>,
98}
99
100impl<T: TableSource> Default for Hooks<T> {
101 fn default() -> Self {
102 Self {
103 before_insert: Vec::new(),
104 before_update: Vec::new(),
105 before_delete: Vec::new(),
106 after_insert: Vec::new(),
107 after_update: Vec::new(),
108 after_delete: Vec::new(),
109 }
110 }
111}
112
113impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
114 pub(crate) fn before_insert_hooks(&self) -> &[(Phase, BeforeFn<T>)] {
115 &self.hooks.before_insert
116 }
117 pub(crate) fn before_update_hooks(&self) -> &[(Phase, BeforeFn<T>)] {
118 &self.hooks.before_update
119 }
120 pub(crate) fn before_delete_hooks(&self) -> &[BeforeDeleteFn<T>] {
121 &self.hooks.before_delete
122 }
123 pub(crate) fn after_insert_hooks(&self) -> &[AfterFn<T>] {
124 &self.hooks.after_insert
125 }
126 pub(crate) fn after_update_hooks(&self) -> &[AfterFn<T>] {
127 &self.hooks.after_update
128 }
129 pub(crate) fn after_delete_hooks(&self) -> &[AfterFn<T>] {
130 &self.hooks.after_delete
131 }
132
133 pub fn add_hook(&mut self, hook: Hook<T>) {
137 let hooks = &mut self.hooks;
138 match hook {
139 Hook::BeforeInsert(phase, f) => push_phased(&mut hooks.before_insert, phase, f),
140 Hook::BeforeUpdate(phase, f) => push_phased(&mut hooks.before_update, phase, f),
141 Hook::BeforeSave(phase, f) => {
142 push_phased(&mut hooks.before_insert, phase, f.clone());
143 push_phased(&mut hooks.before_update, phase, f);
144 }
145 Hook::BeforeDelete(f) => hooks.before_delete.push(f),
146 Hook::AfterInsert(f) => hooks.after_insert.push(f),
147 Hook::AfterUpdate(f) => hooks.after_update.push(f),
148 Hook::AfterSave(f) => {
149 hooks.after_insert.push(f.clone());
150 hooks.after_update.push(f);
151 }
152 Hook::AfterDelete(f) => hooks.after_delete.push(f),
153 }
154 }
155
156 pub fn with_hook(mut self, hook: Hook<T>) -> Self {
158 self.add_hook(hook);
159 self
160 }
161}
162
163fn push_phased<T: TableSource>(
166 hooks: &mut Vec<(Phase, BeforeFn<T>)>,
167 phase: Phase,
168 f: BeforeFn<T>,
169) {
170 hooks.push((phase, f));
171 hooks.sort_by_key(|(p, _)| *p);
172}