diff --git a/src/action_dispatcher.rs b/src/action_dispatcher.rs new file mode 100644 index 00000000..8e101ad4 --- /dev/null +++ b/src/action_dispatcher.rs @@ -0,0 +1,150 @@ +#[derive(PartialEq, Debug, Clone)] +enum State { + Pending, + Waiting, + Done, +} + +impl State { + fn next(&mut self) { + match self { + State::Pending => *self = State::Waiting, + State::Waiting => *self = State::Done, + _ => {} + } + } +} +#[derive(PartialEq, Clone)] +enum Action { + Auth { state: State }, + RateLimit { state: State }, +} + +impl Action { + pub fn trigger(&mut self) { + match self { + Action::Auth { .. } => self.auth(), + Action::RateLimit { .. } => self.rate_limit(), + } + } + + fn get_state(&self) -> &State { + match self { + Action::Auth { state } => state, + Action::RateLimit { state } => state, + } + } + + fn rate_limit(&mut self) { + // Specifics for RL, returning State + if let Action::RateLimit { state } = self { + match state { + State::Pending => { + println!("Trigger the request and return State::Waiting"); + state.next(); + } + State::Waiting => { + println!( + "When got on_grpc_response, process RL response and return State::Done" + ); + state.next(); + } + State::Done => { + println!("Done for RL... calling next action (?)"); + } + } + } + } + + fn auth(&mut self) { + // Specifics for Auth, returning State + if let Action::Auth { state } = self { + match state { + State::Pending => { + println!("Trigger the request and return State::Waiting"); + state.next(); + } + State::Waiting => { + println!( + "When got on_grpc_response, process Auth response and return State::Done" + ); + state.next(); + } + State::Done => { + println!("Done for Auth... calling next action (?)"); + } + } + } + } +} + +pub struct ActionDispatcher { + actions: Vec, +} + +impl ActionDispatcher { + pub fn default() -> ActionDispatcher { + ActionDispatcher { actions: vec![] } + } + + pub fn new(/*vec of PluginConfig actions*/) -> ActionDispatcher { + ActionDispatcher::default() + } + + pub fn next(&mut self) -> bool { + if let Some((i, action)) = self.actions.iter_mut().enumerate().next() { + if let State::Done = action.get_state() { + self.actions.remove(i); + self.actions.len() > 0 + } else { + action.trigger(); + true + } + } else { + false + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn action_transition() { + let mut action = Action::Auth { + state: State::Pending, + }; + assert_eq!(*action.get_state(), State::Pending); + action.trigger(); + assert_eq!(*action.get_state(), State::Waiting); + action.trigger(); + assert_eq!(*action.get_state(), State::Done); + } + + #[test] + fn action_dispatcher_next() { + let mut action_dispatcher = ActionDispatcher{ + actions: vec![ + Action::RateLimit {state: State::Pending} + ], + }; + let mut res = action_dispatcher.next(); + let mut binding = action_dispatcher.actions.clone(); + let mut current_action_state = binding.first().unwrap().get_state(); + + assert_eq!(res, true); + assert_eq!(*current_action_state, State::Waiting); + + res = action_dispatcher.next(); + binding = action_dispatcher.actions.clone(); + current_action_state = binding.first().unwrap().get_state(); + + assert_eq!(res, true); + assert_eq!(*current_action_state, State::Done); + + res = action_dispatcher.next(); + assert_eq!(res, false); + assert_eq!(action_dispatcher.actions.len(), 0); + } +} diff --git a/src/lib.rs b/src/lib.rs index fb1c60aa..eb78d0d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod action_dispatcher; mod attribute; mod configuration; mod envoy;