pub struct Box<T: ?Sized + 'static> { /* private fields */ }
Expand description
A linked object that acts like a std::boxed::Box<dyn MyTrait>
.
Intended to represent linked instances of T
where T: MyTrait
. This is for use with types
that are always exposed to user code as trait objects via linked::Box<dyn MyTrait>
.
The Box
itself implements the linked object mechanics from #[linked::object]
. The type
T
does not need to implement the mechanics of the linked object pattern itself and must not
be decorated with the #[linked::object]
attribute.
§Usage
Use it like a regular std::boxed::Box<T>
that also happens to support the linked object
mechanisms via the linked::instance_per_access!
or linked::instance_per_thread!
macros or PerThread<T>
and offers the API surface for handle-based
transfer across threads via .handle()
.
§Implementation
Instead of a typical constructor, create one that returns linked::Box<dyn MyTrait>
. Inside
this constructor, create a linked::Box
instance using the
linked::new_box!
macro. The first macro parameter is the type inside the
box, and the second is a Self
struct-expression to create one instance of the implementation
type.
// If using linked::Box, do not put `#[linked::object]` on the struct.
// The linked::Box itself is the linked object and our struct is only its contents.
struct XmlConfig {
config: String
}
impl XmlConfig {
pub fn new_as_config_source() -> linked::Box<dyn ConfigSource> {
// Constructing instances works logically the same as for regular linked objects.
//
// The only differences are:
// 1. We use `linked::new_box!` instead of `linked::new!`
// 2. There is an additional parameter to the macro to name the trait object type
linked::new_box!(
dyn ConfigSource,
Self {
config: "xml".to_string(),
}
)
}
}
Any connections between the instances should be established via the captured state of this
closure (e.g. sharing an Arc
or setting up messaging channels).
§Example
Using the linked objects as linked::Box<dyn ConfigSource>
, without the user code knowing the
exact type of the object in the box:
trait ConfigSource {
fn config(&self) -> String;
}
struct XmlConfig {}
struct IniConfig {}
impl ConfigSource for XmlConfig {
fn config(&self) -> String {
"xml".to_string()
}
}
impl ConfigSource for IniConfig {
fn config(&self) -> String {
"ini".to_string()
}
}
impl XmlConfig {
pub fn new_as_config_source() -> linked::Box<dyn ConfigSource> {
linked::new_box!(
dyn ConfigSource,
XmlConfig {}
)
}
}
impl IniConfig {
pub fn new_as_config_source() -> linked::Box<dyn ConfigSource> {
linked::new_box!(
dyn ConfigSource,
IniConfig {}
)
}
}
let xml_config = XmlConfig::new_as_config_source();
let ini_config = IniConfig::new_as_config_source();
let configs = [xml_config, ini_config];
assert_eq!(configs[0].config(), "xml".to_string());
assert_eq!(configs[1].config(), "ini".to_string());