remote-trait-object

Build Status License Cargo Documentation chat

remote-trait-object is a general, powerful, and simple remote method invocation library based on trait objects.

It is...

  1. Based on services that can be exported and imported as trait objects - You register a service object, which is a trait object, and export it. On the other side, you import it into a proxy object, which is also a trait object.
  2. Based on a point-to-point connection - All operations are conducted upon a single connection, which has two ends.
  3. Easy to export and import services - During a remote method call in some service, you can export and import another service as an argument or a return value of the method.
  4. Independent from the transport model - The transport model is abstracted and users must provide a concrete implementation of it.
  5. Concurrent - you can both call and handle remote calls concurrently.

See the documentation.

Example

This example code briefly shows how you can use remote-trait-object.

Note that crate::transport::create() is for creating the transport ends that are provided to remote-trait-object contexts, which is just in-process communication for the test. You have to implement your own transport implementation if you're going to actually use this crate./

```rust use remotetraitobject::*;

[service]

pub trait CreditCard: Service { fn pay(&mut self, ammount: u64) -> Result<(), ()>; } struct SomeCreditCard { money: u64, } impl Service for SomeCreditCard {} impl CreditCard for SomeCreditCard { fn pay(&mut self, ammount: u64) -> Result<(), ()> { if ammount <= self.money { self.money -= ammount; Ok(()) } else { Err(()) } } }

[service]

pub trait PizzaStore: Service { fn orderpizza(&self, creditcard: ServiceRef) -> Resultpizza(&self, creditcard: ServiceRef) -> Resultcardproxy: Box = creditcard.unwrapimport().intoproxy(); creditcardproxy.pay(10)?; Ok("Tasty Pizza".toowned()) } }

[test]

fn test() { let crate::transport::TransportEnds { recv1, send1, recv2, send2, } = crate::transport::create();

let _context_pizza_town = Context::with_initial_service_export(
    Config::default_setup(),
    send1,
    recv1,
    ServiceToExport::new(Box::new(SomePizzaStore) as Box<dyn PizzaStore>),
);

let (_context_customer, pizza_store): (_, ServiceToImport<dyn PizzaStore>) =
    Context::with_initial_service_import(Config::default_setup(), send2, recv2);
let pizza_store_proxy: Box<dyn PizzaStore> = pizza_store.into_proxy();

let my_credit_card = Box::new(SomeCreditCard {
    money: 11,
}) as Box<dyn CreditCard>;
assert_eq!(pizza_store_proxy.order_pizza(ServiceRef::create_export(my_credit_card)).unwrap(), "Tasty Pizza");

let my_credit_card = Box::new(SomeCreditCard {
    money: 9,
}) as Box<dyn CreditCard>;
assert!(pizza_store_proxy.order_pizza(ServiceRef::create_export(my_credit_card)).is_err());

} ```