use super::reject::Rejects;
use super::request::RequestHandle;
use super::reservation::{PreTradeReservation, ReservationHandle};
use crate::Mutations;
use std::marker::PhantomData;
type RequestExecutor = Box<dyn FnOnce() -> Result<PreTradeReservation, Rejects>>;
pub(crate) struct RequestHandleImpl<Order> {
execute: RequestExecutor,
marker: PhantomData<fn(Order)>,
}
impl<Order> RequestHandleImpl<Order> {
pub(crate) fn new(execute: RequestExecutor) -> Self {
Self {
execute,
marker: PhantomData,
}
}
}
impl<Order> RequestHandle<Order> for RequestHandleImpl<Order> {
fn execute(self: Box<Self>) -> Result<PreTradeReservation, Rejects> {
let this = *self;
(this.execute)()
}
}
pub(crate) struct ReservationHandleImpl {
mutations: Mutations,
}
impl ReservationHandleImpl {
pub(crate) fn new(mutations: Mutations) -> Self {
Self { mutations }
}
}
impl ReservationHandle for ReservationHandleImpl {
fn commit(self: Box<Self>) {
self.mutations.commit_all();
}
fn rollback(self: Box<Self>) {
self.mutations.rollback_all();
}
}
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use std::rc::Rc;
use super::{RequestHandleImpl, ReservationHandleImpl};
use crate::pretrade::request::RequestHandle;
use crate::pretrade::reservation::ReservationHandle;
use crate::pretrade::{Reject, RejectCode, RejectScope, Rejects};
use crate::{Mutation, Mutations};
fn noop_action() {}
#[test]
fn commit_calls_commit_closures_in_order() {
let calls = Rc::new(RefCell::new(Vec::new()));
let mut mutations = Mutations::with_capacity(3);
for id in ["a", "b", "c"] {
let c = Rc::clone(&calls);
mutations.push(Mutation::new(
move || {
c.borrow_mut().push(id);
},
noop_action,
));
}
let handle = Box::new(ReservationHandleImpl::new(mutations));
handle.commit();
assert_eq!(&*calls.borrow(), &["a", "b", "c"]);
}
#[test]
fn rollback_calls_rollback_closures_in_reverse_order() {
let calls = Rc::new(RefCell::new(Vec::new()));
let mut mutations = Mutations::with_capacity(3);
for id in ["a", "b", "c"] {
let r = Rc::clone(&calls);
mutations.push(Mutation::new(noop_action, move || {
r.borrow_mut().push(id);
}));
}
let handle = Box::new(ReservationHandleImpl::new(mutations));
handle.rollback();
assert_eq!(&*calls.borrow(), &["c", "b", "a"]);
}
#[test]
fn request_handle_execute_calls_executor() {
let called = Rc::new(RefCell::new(false));
let called_clone = Rc::clone(&called);
let handle: Box<RequestHandleImpl<()>> =
Box::new(RequestHandleImpl::new(Box::new(move || {
*called_clone.borrow_mut() = true;
Err(Rejects::new(vec![Reject::new(
"test",
RejectScope::Order,
RejectCode::Other,
"expected",
"expected execute error",
)]))
})));
let result = handle.execute();
assert!(result.is_err());
assert!(*called.borrow());
}
}