Last active
May 10, 2019 01:00
-
-
Save CodeSandwich/9401f7fb95d7f288519d6db1d7b845b0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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