1pub mod stub;
2
3mod store;
4mod unchecked;
5
6use std::{
7 fmt::{self, Formatter},
8 sync::Mutex,
9};
10
11pub use self::{store::Store, stub::Stub};
12
13pub struct Mock<'stub, I, O> {
18 fn_name: &'static str,
19 stubs: Vec<Mutex<Stub<'stub, I, O>>>,
20}
21
22impl<'stub, I, O> Mock<'stub, I, O> {
23 pub fn new(fn_name: &'static str) -> Self {
25 Self {
26 fn_name,
27 stubs: vec![],
28 }
29 }
30
31 pub fn call(&self, mut input: I) -> Result<O, InvocationError> {
39 let mut errors = vec![];
40
41 for stub in self.stubs.iter().rev() {
42 match stub.lock().unwrap().call(input) {
43 Err((i, e)) => {
44 errors.push(e);
45 input = i
46 }
47 Ok(o) => return Ok(o),
48 }
49 }
50
51 Err(if errors.is_empty() {
52 InvocationError::NeverStubbed
53 } else {
54 InvocationError::Stub(errors)
55 })
56 }
57
58 pub fn add_stub(&mut self, stub: Stub<'stub, I, O>) {
60 self.stubs.push(Mutex::new(stub))
61 }
62
63 pub fn name(&self) -> &'static str {
64 self.fn_name
65 }
66}
67
68#[derive(Debug)]
69pub enum InvocationError {
70 NeverStubbed,
71 Stub(Vec<stub::Error>),
72}
73
74impl<I, O> fmt::Debug for Mock<'_, I, O> {
75 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
76 f.debug_struct("Mock").field("stubs", &self.stubs).finish()
77 }
78}