macro_rules! derive_deftly_template_Object {
({ $($driver:tt)* } [$($aoptions:tt)*] ($($future:tt)*) $($tpassthrough:tt)*) => { ... };
($($wrong:tt)*) => { ... };
}
Expand description
Allow a type to participate as an Object in the RPC system.
This template implements Object
for the
target type, and can be used to cause objects to participate in the trait
downcasting system.
§Examples
§Simple case, just implements Object
.
use tor_rpcbase::{self as rpc, templates::*};
use derive_deftly::Deftly;
#[derive(Default, Deftly)]
#[derive_deftly(Object)]
struct Houseplant {
oxygen_per_sec: f64,
benign_neglect: u8
}
// You can downcast an Object to a concrete type.
use downcast_rs::DowncastSync;
use std::sync::Arc;
let plant_obj: Arc<dyn rpc::Object> = Arc::new(Houseplant::default());
let as_plant: Arc<Houseplant> = plant_obj.downcast_arc().ok().unwrap();
§With trait downcasting
By default, you can use [downcast_rs
] to downcast a dyn Object
to its
concrete type. If you also need to be able to downcast a dyn Object
to a given
trait that it implements, you can use the downcastable_to
attributes for Object
to have
it participate in trait downcasting:
use tor_rpcbase::{self as rpc, templates::*};
use derive_deftly::Deftly;
#[derive(Deftly)]
#[derive_deftly(Object)]
#[deftly(rpc(downcastable_to = "Gizmo, Doodad"))]
struct Frobnitz {}
trait Gizmo {}
trait Doodad {}
impl Gizmo for Frobnitz {}
impl Doodad for Frobnitz {}
use std::sync::Arc;
use rpc::ObjectArcExt; // for the cast_to method.
let frob_obj: Arc<dyn rpc::Object> = Arc::new(Frobnitz {});
let gizmo: &dyn Gizmo = frob_obj.cast_to_trait().unwrap();
let doodad: &dyn Doodad = frob_obj.cast_to_trait().unwrap();
§With generic objects
Right now, a generic object can’t participate in our method lookup system, but it can participate in trait downcasting. We’ll try to remove this limitation in the future.
use tor_rpcbase::{self as rpc, templates::*};
use derive_deftly::Deftly;
#[derive(Deftly)]
#[derive_deftly(Object)]
#[deftly(rpc(downcastable_to = "ExampleTrait"))]
struct Generic<T,U> where T:Clone, U:PartialEq {
t: T,
u: U,
}
trait ExampleTrait {}
impl<T:Clone,U:PartialEq> ExampleTrait for Generic<T,U> {}
use std::sync::Arc;
use rpc::ObjectArcExt; // for the cast_to method.
let obj: Arc<dyn rpc::Object> = Arc::new(Generic { t: 42_u8, u: 42_u8 });
let tr: &dyn ExampleTrait = obj.cast_to_trait().unwrap();
§Making an object “exposed outside of the session”
You can flag any kind of Object so that its identifiers will be exported
outside of the local RPC session. (Arti uses this for Objects whose
ObjectId needs to be used as a SOCKS identifier.) To do so,
use the expose_outside_session
attribute:
use tor_rpcbase::{self as rpc, templates::*};
use derive_deftly::Deftly;
#[derive(Deftly)]
#[derive_deftly(Object)]
#[deftly(rpc(expose_outside_of_session))]
struct Visible {}
§Delegation
You can give an Object the ability to delegate
method invocations to another object it contains.
The inner object must be an Arc
.
To do so, use the delegate_with
attribute.
The attribute must contain an expression of type
FnOnce(&Self) -> Option(Arc<T>)
, where T implements Object.
use tor_rpcbase::{self as rpc, templates::*};
use derive_deftly::Deftly;
use std::sync::Arc;
#[derive(Deftly)]
#[derive_deftly(Object)]
struct Inner {}
#[derive(Deftly)]
#[derive_deftly(Object)]
#[deftly(rpc(
delegate_with="|this: &Self| Some(this.inner.clone())",
delegate_type="Inner"
))]
struct Outer {
inner: Arc<Inner>,
}
This is a derive_deftly
template. Do not invoke it directly.
To use it, write: #[derive(Deftly)] #[derive_deftly(Object)]
.