Skip to content

Instantly share code, notes, and snippets.

@CodeSandwich
Last active May 10, 2019 01:00
Show Gist options
  • Save CodeSandwich/9401f7fb95d7f288519d6db1d7b845b0 to your computer and use it in GitHub Desktop.
Save CodeSandwich/9401f7fb95d7f288519d6db1d7b845b0 to your computer and use it in GitHub Desktop.
fn main() {
unsafe {
mock_0(main, Safe);
mock_unsafe_0(main, Safe);
mock_1(foo, SafeB);
mock_unsafe_1(foo, SafeB);
mock_1(foo, || {static RES: bool = true; MockResult::Return(&RES)});
mock_unsafe_1(foo, || {static RES: bool = true; MockResult::Return(&RES)});
}
}
fn foo(x: &bool) -> &bool { x }
fn mock_0<O: 'static>(f: unsafe fn() -> O, mut _m: impl Mock<Output = O>)
{ println!("mock_0 {:p}", f as *const()); }
unsafe fn mock_unsafe_0<O>(f: unsafe fn() -> O, mut _m: impl MockUnsafe<(), Output = O>)
{ println!("mock_unsafe_0 {:p}", f as *const()); }
fn mock_1<I1, O: 'static>(f: unsafe fn(I1) -> O, mut _m: impl Mock<Output = O>)
{ println!("mock_0 {:p}", f as *const()); }
unsafe fn mock_unsafe_1<I1, O>(f: unsafe fn(I1) -> O, mut _m: impl MockUnsafe<(), Output = O>)
{ println!("mock_unsafe_0 {:p}", f as *const()); }
struct Safe;
impl Mock for Safe {
type Output = ();
fn run(&mut self) -> MockResult<(), Self::Output> {
MockResult::Continue(())
}
}
struct SafeB;
impl Mock for SafeB {
type Output = &'static bool;
fn run(&mut self) -> MockResult<(), Self::Output> {
MockResult::Continue(())
}
}
impl<T: FnMut() -> MockResult<(), O> + 'static, O: 'static> Mock for T {
type Output = O;
fn run(&mut self) -> MockResult<(), Self::Output> {
self()
}
}
impl<T: FnMut(I) -> MockResult<I, O>, I, O> MockUnsafe<I> for T {
type Output = O;
fn run(&mut self, input: I) -> MockResult<I, Self::Output> {
self(input)
}
}
trait Mock: 'static {
type Output: 'static;
fn run(&mut self) -> MockResult<(), Self::Output>;
}
trait MockUnsafe<I> {
type Output;
fn run(&mut self, input: I) -> MockResult<I, Self::Output>;
}
#[allow(dead_code)]
enum MockResult<I, O> {
Continue(I),
Return(O),
Fail(I),
}
impl<T: Mock<Output = O>, O: 'static> MockUnsafe<()> for T {
type Output = O;
fn run(&mut self, _input: ()) -> MockResult<(), Self::Output> {
Mock::run(self)
}
}
impl<T: MockUnsafe<(), Output = O>, O, I1> MockUnsafe<(I1,)> for T {
type Output = O;
fn run(&mut self, (i1,): (I1,)) -> MockResult<(I1,), Self::Output> {
match MockUnsafe::run(self, ()) {
MockResult::Continue(()) => MockResult::Continue((i1,)),
MockResult::Return(o) => MockResult::Return(o),
MockResult::Fail(()) => MockResult::Fail((i1,))
}
}
}
// S Mock(???) -> ! + 'static
// U Mock(???) -> !
// U Mock(ABC) -> !
// mock_x (Mock<O>) <- only safe, no input + 'static
// mock_unsafe_x (Mock<O, A, B, C>)
// impl every unsafe_mock<O, A, B> for mock<O>
// impl unsafe_mock<O> for mock<O>
// impl every unsafe_mock<O, A, B> for unsafe_mock<O>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment