#![cfg(feature="flume")] use trait_enumizer::flume_class; trait MyIface { fn foo(&self) -> String; fn bar(&self, x: i32) -> i32; fn baz(&self, y: String, z: Vec); } struct Implementor {} impl MyIface for Implementor { fn foo(&self) -> String { dbg!("foo"); "qqq".to_owned() } fn bar(&self, x: i32) -> i32 { dbg!("bar", x); x * x + 1 } fn baz(&self, y: String, z: Vec) { dbg!("baz", y, z); } } // Begin of the part which is supposed to be auto-generated enum MyIfaceEnum { Foo { ret: flume_class!(Sender) }, Bar { x: i32, ret: flume_class!(Sender) }, Baz { y: String, z: Vec }, } impl MyIfaceEnum { fn try_call(self, o: &I) -> Result<(), flume_class!(SendError)> { match self { MyIfaceEnum::Foo { ret } => Ok(flume_class!(send::(ret, o.foo()))?), MyIfaceEnum::Bar { x, ret } => Ok(flume_class!(send::(ret, o.bar(x)))?), MyIfaceEnum::Baz { y, z } => Ok(o.baz(y, z)), } } } trait MyIfaceResultified { fn try_foo(&self) -> Result, E>; fn try_bar(&self, x: i32) -> Result, E>; fn try_baz(&self, y: String, z: Vec) -> Result<(), E>; } struct MyIfaceProxy(F) where F: Fn(MyIfaceEnum) -> Result<(), E>; impl MyIfaceResultified for MyIfaceProxy where F: Fn(MyIfaceEnum) -> Result<(), E>, { fn try_foo(&self) -> Result, E> { let (tx, rx) = flume_class!(create::()); self.0(MyIfaceEnum::Foo { ret: tx })?; Ok(flume_class!(recv::(rx))) } fn try_bar(&self, x: i32) -> Result, E> { let (tx, rx) = flume_class!(create::()); self.0(MyIfaceEnum::Bar { x, ret: tx })?; Ok(flume_class!(recv::(rx))) } fn try_baz(&self, y: String, z: Vec) -> Result<(), E> { self.0(MyIfaceEnum::Baz { y, z }) } } impl MyIface for MyIfaceProxy where F: Fn(MyIfaceEnum) -> Result<(), E>, E : std::fmt::Debug, flume_class!(RecvError) : std::fmt::Debug, { fn foo(&self) -> String { MyIfaceResultified::try_foo(self).unwrap().unwrap() } fn bar(&self, x: i32) -> i32 { MyIfaceResultified::try_bar(self, x).unwrap().unwrap() } fn baz(&self, y: String, z: Vec) { MyIfaceResultified::try_baz(self, y, z).unwrap() } } // End of the part which is supposed to be auto-generated #[test] fn simple() { let o = Implementor {}; let p = MyIfaceProxy::<_, _>(move |c| c.try_call(&o)); dbg!(p.foo()); dbg!(p.bar(4)); } #[test] fn threaded() { let (tx,rx) = flume::bounded::(1); std::thread::spawn(move || { let o = Implementor {}; for msg in rx { msg.try_call(&o).unwrap(); } }); let p = MyIfaceProxy::<_, _>(|c| tx.send(c)); dbg!(p.foo()); dbg!(p.bar(4)); }