Protobuf
Shizuku provides Protocol Buffers serialization support through the protobuf feature flag. This integration uses prost for serialization and deserialization.
Installation
-
Add the
protobuffeature to your Shizuku dependency inCargo.toml:Cargo.toml [dependencies]shizuku = { version = "0.0.2-alpha.2", features = ["protobuf"] } -
Add
prost-buildto your build dependencies:Cargo.toml [build-dependencies]prost-build = "0.13" -
Create a
build.rsfile in your project root to compile.protofiles:/build.rs fn main() {prost_build::compile_protos(&["src/proto/user.proto"], &["src/proto"]).unwrap();} -
Create your
.protofiles in the specified directory (e.g.,src/proto/user.proto):src/proto/user.proto syntax = "proto3";package user;message User {string id = 1;string name = 2;string email = 3;} -
Create a module file to include the generated code (e.g.,
src/user.rs):src/user.rs // Include the generated protobuf codepub mod proto {include!(concat!(env!("OUT_DIR"), "/user.rs"));}// Re-export the types you want to use directlypub use proto::User;pub use proto::CreateUserRequest;pub use proto::CreateUserResponse;// Implement serialization and deserialization for the typesuse shizuku::{protobuf_ser, protobuf_des};protobuf_ser!(User);protobuf_des!(User);protobuf_ser!(CreateUserRequest);protobuf_des!(CreateUserResponse);
Usage
The Protobuf integration provides two macros for implementing serialization traits:
protobuf_ser: ImplementsByteSerializefor Protobuf serializationprotobuf_des: ImplementsByteDeserializefor Protobuf deserialization
Using in Services
The Protobuf serialization works seamlessly with NATS services:
use shizuku::{protobuf_ser, protobuf_des, NatsRpcCallTrait};include!(concat!(env!("OUT_DIR"), "/user.rs"));
impl NatsRpcCallTrait<CreateUserResponse> for CreateUserRequest { fn subject() -> (NatsSubjectPath, PhantomData<CreateUserResponse>) { (subject_path!["user", "create"], PhantomData) }}
protobuf_ser!(CreateUserRequest);protobuf_des!(CreateUserResponse);Using with JetStream
You can use Protobuf serialization for JetStream events and consumers:
use shizuku::{protobuf_ser, protobuf_des, DynamicSubjectMessage, JetStreamMessageSendTrait};include!(concat!(env!("OUT_DIR"), "/order.rs"));
// Implement serializationprotobuf_ser!(OrderCreatedEvent);protobuf_des!(OrderData);use shizuku::{DynamicSubjectMessage, JetStreamMessageSendTrait};use shizuku::jetstream::FinalJetStreamProcessor;use crate::order::{OrderCreatedEvent, OrderData};
// Implement dynamic subject for the eventimpl DynamicSubjectMessage for OrderCreatedEvent { fn subject(&self) -> NatsSubjectPath { subject_path!["order", "created", &self.order_id] }}
// The trait is automatically implementedimpl JetStreamMessageSendTrait for OrderCreatedEvent {}
// Define a consumer that processes Protobuf messages
struct OrderProcessor;
impl Processor<Message, Result<(), Error>> for OrderProcessor { async fn process(&self, msg: Message) -> Result<(), Error> { // Parse Protobuf message let order = OrderData::parse_from_bytes(msg.payload)?;
// Process the order println!("Processing order: {}", order.order_id); Ok(()) }}