1use std::collections::HashMap;
2
3use crate::InvocationError;
4
5use super::{unchecked::Unchecked, Mock};
6
7#[derive(Debug)]
8pub struct Store<'stub> {
9 pub struct_name: &'static str,
10 stubs: HashMap<usize, Unchecked<'stub>>,
11}
12
13impl<'stub> Store<'stub> {
14 pub fn new(struct_name: &'static str) -> Self {
15 Store {
16 struct_name,
17 stubs: HashMap::new(),
18 }
19 }
20
21 pub fn get_mut<R, I, O>(
26 &mut self,
27 id: fn(R, I) -> O,
28 fn_name: &'static str,
29 ) -> &mut Mock<'stub, I, O> {
30 let mock = self.stubs.entry(id as usize).or_insert_with(|| {
31 let mock: Mock<I, O> = Mock::new(fn_name);
32 mock.into()
33 });
34
35 let mock = unsafe { mock.as_typed_mut() };
36 assert_name(mock, fn_name);
37 mock
38 }
39
40 pub unsafe fn get<R, I, O>(
44 &self,
45 id: fn(R, I) -> O,
46 fn_name: &'static str,
47 generics: &'static str,
48 ) -> Result<&Mock<'stub, I, O>, InvocationError> {
49 match self.stubs.get(&(id as usize)).map(|m| m.as_typed()) {
50 Some(mock) => {
51 assert_name(mock, fn_name);
52 Ok(mock)
53 }
54 None => Err(InvocationError {
55 fn_name,
56 struct_name: self.struct_name,
57 generics,
58 stub_error: super::InvocationError::NeverStubbed,
59 }),
60 }
61 }
62}
63
64fn assert_name<I, O>(mock: &Mock<I, O>, fn_name: &'static str) {
65 assert_eq!(
66 mock.name(),
67 fn_name,
68 "faux bug: conflicting mock names: '{}' vs '{}'",
69 mock.name(),
70 fn_name
71 );
72}