1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
use crate::MockStore;
use std::any::TypeId;

/// Stores who and what to mock and provides methods to mock the
/// method both safely and unsafely.
///
/// See [when!] for how to get a instance of this
/// struct.
///
/// [when!]: macro.when.html
pub struct When<'q, I, O> {
    id: TypeId,
    store: &'q mut MockStore,
    // *const for variance -- I think that's what I want.
    _marker: std::marker::PhantomData<(*const I, *const O)>,
}

impl<'q, I, O> When<'q, I, O> {
    #[doc(hidden)]
    pub fn new(id: TypeId, store: &'q mut MockStore) -> Self {
        When {
            id,
            store,
            _marker: std::marker::PhantomData,
        }
    }

    /// Mocks the method stored in the `When` with the given closure
    /// for the saved instance. This mock has no restrictions on the
    /// lifetimes for the inputs, outputs, nor the mocked function
    /// itself for maximum flexibility.
    ///
    /// The input for the given closure is a tuple of all its
    /// non-receiver parameters (not `self`, `&self`, nor `&mut
    /// self`). While this method is "type" safe for the types in the
    /// mocked method, it is not lifetime safe. See [safety].
    ///
    /// [safety]: #safety
    ///
    /// # Usage
    ///
    /// ```rust
    /// #[faux::create]
    /// pub struct Foo {}
    ///
    /// #[faux::methods]
    /// impl Foo {
    ///     pub fn no_args(&mut self) -> &i32 {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    ///
    ///     pub fn single_arg(&self, a: u8) -> Vec<i8> {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    ///
    ///     pub fn multi_args(self, a: &i32, b: i8) -> u32 {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    /// }
    ///
    /// fn main() {
    ///   let mut mock = Foo::faux();
    ///
    ///   // the output can be a reference to the environment
    ///   // but this can be *very* dangerous so be careful
    ///   // note that the closure still has an argument, it is just an empty tuple
    ///   let x = 5;
    ///   unsafe { faux::when!(mock.no_args).then(|_empty: ()| &x) }
    ///   assert_eq!(*mock.no_args(), 5);
    ///
    ///   // unit tuples do not need parentheses
    ///   unsafe { faux::when!(mock.single_arg).then(|input| vec![input as i8]) }
    ///   assert_eq!(mock.single_arg(8), vec![8]);
    ///
    ///   // inputs can be references
    ///   unsafe { faux::when!(mock.multi_args).then(|(&a, b)| a as u32 + b as u32) }
    ///   assert_eq!(mock.multi_args(&5, 23), 28)
    /// }
    ///
    /// ```
    ///
    ///
    /// # Safety
    ///
    /// This function effectively erases the lifetime relationships of
    /// the inputs and outputs. It is the user's responsability to not
    /// pass a mock that would capture a variable that would be used
    /// after it has been deallocated.
    ///
    /// Another way in which this function is unsafe is if the output
    /// of this function has a logical lifetime link to the input.  At
    /// the moment the mock gets called, that link would be erased
    /// which could create multiple mutable references to the same
    /// object.
    ///
    /// Example:
    ///
    /// ```
    /// #[faux::create]
    /// pub struct Foo {}
    ///
    /// #[faux::methods]
    /// impl Foo {
    ///     pub fn out_ref(&self, a : &mut i32) -> &mut i32 {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    /// }
    ///
    /// fn main() {
    ///   let mut mock = Foo::faux();
    ///   // set up the mock such that the output is the same reference as the input
    ///   unsafe { faux::when!(mock.out_ref).then(|i| i) }
    ///
    ///   let mut x = 5;
    ///   // y is now a mutable reference back x
    ///   // but there is no compile-time link between the two
    ///   let y = mock.out_ref(&mut x);
    ///
    ///   // We can check that they are both the same value
    ///   assert_eq!(*y, 5);
    ///   assert_eq!(x, 5);
    ///
    ///   // x now changes y. This is UB and is not allowed in safe Rust!
    ///   x += 1;
    ///   assert_eq!(x, 6);
    ///   assert_eq!(*y, 6);
    ///
    ///   // and if we change y then x also gets changed
    ///   *y += 1;
    ///   assert_eq!(x, 7);
    ///   assert_eq!(*y, 7);
    /// }
    /// ```
    pub unsafe fn then(self, mock: impl FnOnce(I) -> O + Send) {
        self.store.unsafe_mock_once(self.id, mock);
    }

    /// Mocks the method stored in the `When` with the given closure
    /// for the saved instance. This mock is restricted only to static
    /// inputs, outputs, and closures. While this is very restrictive
    /// it allows for a purely safe interface. See [then] for the
    /// unsafe version.
    ///
    /// The input for the given closure is a tuple of all its
    /// non-receiver parameters (not `self`, `&self`, nor `&mut
    /// self`).
    ///
    /// [then]: #method.then
    ///
    /// # Usage
    ///
    /// ```rust
    /// #[faux::create]
    /// pub struct Foo {}
    ///
    /// #[faux::methods]
    /// impl Foo {
    ///     pub fn no_args(&mut self) -> i32 {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    ///
    ///     pub fn single_arg(&self, a: u8) -> Vec<i8> {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    ///
    ///     pub fn multi_args(self, a: &i32, b: i8) -> u32 {
    ///       /* implementation code */
    ///       # panic!()
    ///     }
    /// }
    ///
    /// fn main() {
    ///   let mut mock = Foo::faux();
    ///
    ///   // closure still has an argument, it is just an empty tuple
    ///   faux::when!(mock.no_args).safe_then(|_empty: ()| 5);
    ///   assert_eq!(mock.no_args(), 5);
    ///
    ///   // unit tuples do not need parentheses
    ///   faux::when!(mock.single_arg).safe_then(|input| vec![input as i8]);
    ///   assert_eq!(mock.single_arg(8), vec![8]);
    ///
    ///   // one of the arguments for `multi_args` is not a static type
    ///   // so the following line would not compile
    ///   // faux::when!(mock.multi_args).safe_then(|(_, _)| 5);
    /// }
    ///
    /// ```
    pub fn safe_then(self, mock: impl FnOnce(I) -> O + 'static + Send)
    where
        I: 'static,
        O: 'static,
    {
        self.store.mock_once(self.id, mock);
    }
}