Enum ServiceRef

Source
pub enum ServiceRef<T: ?Sized + Service> {
    Export(ServiceToExport<T>),
    Import(ServiceToImport<T>),
}
Expand description

A union of ServiceToExport and ServiceToImport

In most case, you will mostly use only this struct to export and import services.

This is needed when you want to export and import a service via another service, but using a common single trait as a channel.

Suppose you want to export Box<dyn Pizza> by returning it in another service’s method, fn order_pizza(). One way of doing this is defining two traits, one for export and one for import. Crate that wants to implement & export a PizzaStore and export Pizza will have following code

use remote_trait_object::*;

#[service]
pub trait Pizza: Service {}

#[service(no_proxy)]
pub trait PizzaStore: Service {
    fn order_pizza(&self) -> ServiceToExport<dyn Pizza>;
}

On the other hand, crate that wants to import & remotely call a PizzaStore and import Pizza will have following code

use remote_trait_object::*;

#[service]
pub trait Pizza: Service {}

#[service(no_skeleton)]
pub trait PizzaStore: Service {
    fn order_pizza(&self) -> ServiceToImport<dyn Pizza>;
}

This works perfectly fine, by returning ServiceToExport::new(..) in the former and calling ServiceToImport::into_remote(the_return_value) in the latter, because the two PizzaStores are compatible since ServiceToImport and ServiceToExport are compatible.

However, suppose the case where the two parties may have a common dependent crate which would have defined such a common service trait, or even the case where the two parties are in the same crate. It becomes somewhat bothersome to have both duplicated traits only because of ServiceToExport and ServiceToImport.

ServiceRef is for such purpose. Instead of denoting both ServiceToExport and ServiceToImport for two separate traits, just use a single common trait with those two types replaced with ServiceRef in the very same place.

The above two traits now become a single trait.

use remote_trait_object::*;

#[service]
pub trait Pizza: Service {}

#[service]
pub trait PizzaStore: Service {
    fn order_pizza(&self) -> ServiceRef<dyn Pizza>;
}

And this PizzaStore can be both

  • implemented and exported - you will be using Import variant for an argument, and Export variant for the return value.
  • imported and locally invoked - you will be using Export variant for an argument, and Import variant for the return value.

§Example

// EXPORTER SIDE
impl PizzaStore for SomeType {
    fn order_pizza(&self) -> ServiceRef<dyn Pizza> {
        ServiceRef::create_export(Box::new(SomePizza) as Box<dyn Pizza>)
    }
}

// IMPORTER SIDE
let store: Box<dyn PizzaStore> = some_store();
let pizza: Box<dyn Pizza> = store.order_pizza().unwrap_import().into_proxy();

Variants§

Implementations§

Source§

impl<T: ?Sized + Service> ServiceRef<T>

Source

pub fn create_export(service: impl IntoSkeleton<T>) -> Self

Creates an Export variant from a smart pointer of a service object.

It simply ServiceRef::Export(ServiceToExport::new(service)).

Source

pub fn unwrap_import(self) -> ServiceToImport<T>

Unwraps as an Import variant.

It panics if it is Export.

Source

pub fn into_object<P: ImportProxy<T> + FromSkeleton<T>>(self) -> P

Converts into the object with whatever smart pointer type you want, for both variants.

If ServiceRef is constructed with Import (the common case), it is same as unwrap_import().into_proxy(). If ServiceRef is constructed with Export (where the ServiceRef is given by local object), it just create a light-weight object that simply wraps the skeleton, not involving any connections.

Trait Implementations§

Source§

impl<'de, T: ?Sized + Service> Deserialize<'de> for ServiceRef<T>

Source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<T: ?Sized + Service> Serialize for ServiceRef<T>

Source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for ServiceRef<T>

§

impl<T> !RefUnwindSafe for ServiceRef<T>

§

impl<T> Send for ServiceRef<T>
where T: ?Sized,

§

impl<T> !Sync for ServiceRef<T>

§

impl<T> Unpin for ServiceRef<T>
where T: Unpin + ?Sized,

§

impl<T> !UnwindSafe for ServiceRef<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,