#protocols #server #networking #rmi

remote-trait-object

基于特质对象实现的远程方法调用库

8 个不稳定版本 (3 个破坏性更改)

0.5.0 2021 年 1 月 6 日
0.4.3 2020 年 9 月 4 日
0.4.2 2020 年 8 月 24 日
0.3.1 2020 年 8 月 7 日
0.2.0 2020 年 7 月 15 日

#205 in #network

每月 30 次下载

MIT/Apache

115KB
2K SLoC

remote-trait-object

Build Status License Cargo Documentation chat

remote-trait-object 是一个通用、强大且简单的基于特质对象的 远程方法调用 库。

它是...

  1. 基于可以导出和导入 作为特质对象服务 - 你注册一个服务对象,它是一个特质对象,然后导出它。在另一边,你将其导入到一个代理对象中,它也是一个特质对象。
  2. 基于点对点连接 - 所有操作都在单个连接上进行,该连接有两个端点。
  3. 易于导出和导入服务 - 在某些服务的远程方法调用过程中,你可以将另一个服务作为方法的参数或返回值来导出或导入。
  4. 独立于传输模型 - 传输模型被抽象化,并且 用户必须提供其实际实现
  5. 并发 - 你可以同时 调用和处理远程调用

查看 文档

示例

此示例代码 简要展示了如何使用 remote-trait-object

请注意,crate::transport::create() 用于创建提供给 remote-trait-object 环境的传输端,这只是一个测试中的进程内通信。如果你打算真正使用此包,你必须实现自己的传输实现。

use remote_trait_object::*;

#[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 order_pizza(&self, credit_card: ServiceRef<dyn CreditCard>) -> Result<String, ()>;
}
struct SomePizzaStore;
impl Service for SomePizzaStore {}
impl PizzaStore for SomePizzaStore {
    fn order_pizza(&self, credit_card: ServiceRef<dyn CreditCard>) -> Result<String, ()> {
        let mut credit_card_proxy: Box<dyn CreditCard> = credit_card.unwrap_import().into_proxy();
        credit_card_proxy.pay(10)?;
        Ok("Tasty Pizza".to_owned())
    }
}

#[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());
}

依赖项

~2.2–3MB
~63K SLoC