Macro plumber_rs::protodef [−][src]
macro_rules! protodef { ($(protodef $proto_name:ident { $([$pipe:ident.$($field:tt)*]:$type:ty => $model_name:ident;)* })*) => { ... }; }
Defines a language-neutural protocol binding for the Rust servlet.
This is the major way a ProtocolModel
and DataModel
is created. The input of the macro is
which field of the language-neutural type you want to map into the Rust servlet.
For example, a servlet may want to read a Point2D
type from the input port. And the servlet
uses the Point2D.x
and Point2D.y
, we can actually map it with the following syntax:
protodef!{ protodef MyProtocol { [input.x]:f32 => input_x; [input.y]:f32 => input_y; } }
Which means we want to map the the x
field of the input with f32
type to identifer input_x
and y
field of the input with f32
type to identifer input_y
.
In the init function of the servlet, we should assign the actual pipe object to the protocol
pipes with the macro init_protocol
. For example:
fn init(&mut self, args:&[&str], model:Self::ProtocolType) { .... init_protocol!{ model { self.input => input, self.output => output } } .... }
This will assign self.input
as the input
mentioned in protocol, and self.out
as the
output
mentioned in the protocol.
By doing that we are abe to read the data in the servlet execution function with the data model:
let x = data_model.input_x().get(); // read x let y = data_model.input_y().get(); // read y
In order to make the compiler knows our servlet actually use a specified protcol. The
use_protocol!
macro should be used inside the servlet implementation. For example
impl SyncServlet for MyServlet { use_protocol(MyProtocol); // This makes the servlet uses the protocol we just defined ...... }
The mapping syntax is as following:
[field.path.to.plumber]:rust_type => rust_identifer
Limit:
- Currently we do not support compound object access, for example, we can not read the entire
Point2D
object - We also leak of the RLS object support, which should be done in the future