use std::{env, time::Duration};
use hiroz::Builder;
use hiroz::encoding::Encoding;
use hiroz_msgs::std_msgs::String as RosString;
fn main() -> zenoh::Result<()> {
let args: Vec<String> = env::args().collect();
let mode = args.get(1).map(|s| s.as_str()).unwrap_or("both");
match mode {
"pub" => run_publisher(),
"sub" => run_subscriber(),
"both" => run_both(),
_ => {
println!("Usage: protobuf_interop [pub|sub|both]");
Ok(())
}
}
}
fn run_publisher() -> zenoh::Result<()> {
println!("=== Protobuf Interop - Publisher ===\n");
let ctx = hiroz::context::ZContextBuilder::default().build()?;
let node = ctx.create_node("protobuf_publisher").build()?;
let pub_proto = node
.create_pub::<RosString>("/interop/protobuf")
.with_encoding(Encoding::protobuf().with_schema("std_msgs/msg/String"))
.build()?;
let pub_cdr = node
.create_pub::<RosString>("/interop/cdr")
.with_encoding(Encoding::cdr())
.build()?;
println!("Publishers ready:");
println!(" - /interop/protobuf (Protobuf encoding)");
println!(" - /interop/cdr (CDR encoding)");
println!("\nPublishing messages every second...\n");
let mut counter = 0;
loop {
counter += 1;
let msg_proto = RosString {
data: format!("Protobuf message #{}", counter),
};
pub_proto.publish(&msg_proto)?;
println!(
"[PROTO] Published: '{}' (encoding: application/protobuf)",
msg_proto.data
);
let msg_cdr = RosString {
data: format!("CDR message #{}", counter),
};
pub_cdr.publish(&msg_cdr)?;
println!(
"[CDR] Published: '{}' (encoding: application/octet-stream)",
msg_cdr.data
);
println!();
std::thread::sleep(Duration::from_secs(1));
}
}
fn run_subscriber() -> zenoh::Result<()> {
println!("=== Protobuf Interop - Subscriber ===\n");
let ctx = hiroz::context::ZContextBuilder::default().build()?;
let node = ctx.create_node("protobuf_subscriber").build()?;
let sub_proto = node
.create_sub::<RosString>("/interop/protobuf")
.with_encoding(Encoding::protobuf().with_schema("std_msgs/msg/String"))
.build()?;
let sub_cdr = node
.create_sub::<RosString>("/interop/cdr")
.with_encoding(Encoding::cdr())
.build()?;
println!("Subscribers ready:");
println!(" - /interop/protobuf (expects Protobuf)");
println!(" - /interop/cdr (expects CDR)");
println!("\nListening for messages...\n");
loop {
if let Ok(msg) = sub_proto.recv() {
println!("[PROTO] Received: '{}'", msg.data);
}
if let Ok(msg) = sub_cdr.recv() {
println!("[CDR] Received: '{}'", msg.data);
}
std::thread::sleep(Duration::from_millis(100));
}
}
fn run_both() -> zenoh::Result<()> {
println!("=== Protobuf Interop - Full Demo ===\n");
println!("This demonstrates encoding interoperability:");
println!(" 1. Publishers send messages with explicit encoding");
println!(" 2. Subscribers validate received encoding");
println!(" 3. External Zenoh apps can read the encoding metadata\n");
let ctx = hiroz::context::ZContextBuilder::default().build()?;
let node = ctx.create_node("protobuf_demo").build()?;
let pub_proto = node
.create_pub::<RosString>("/demo/protobuf")
.with_encoding(Encoding::protobuf().with_schema("std_msgs/msg/String"))
.build()?;
let pub_cdr = node
.create_pub::<RosString>("/demo/cdr")
.with_encoding(Encoding::cdr())
.build()?;
let sub_proto = node
.create_sub::<RosString>("/demo/protobuf")
.with_encoding(Encoding::protobuf().with_schema("std_msgs/msg/String"))
.build()?;
let sub_cdr = node
.create_sub::<RosString>("/demo/cdr")
.with_encoding(Encoding::cdr())
.build()?;
println!("✓ Publishers and subscribers ready\n");
println!("Publishing and receiving messages...\n");
let mut counter = 0;
loop {
counter += 1;
let msg_proto = RosString {
data: format!("Interop test #{}", counter),
};
pub_proto.publish(&msg_proto)?;
let msg_cdr = RosString {
data: format!("CDR test #{}", counter),
};
pub_cdr.publish(&msg_cdr)?;
std::thread::sleep(Duration::from_millis(200));
if let Ok(msg) = sub_proto.recv() {
println!("✓ Protobuf: '{}'", msg.data);
}
if let Ok(msg) = sub_cdr.recv() {
println!("✓ CDR: '{}'", msg.data);
}
if counter >= 10 {
break;
}
std::thread::sleep(Duration::from_millis(800));
}
println!("\n=== Demo Complete ===");
println!("\nKey Takeaways:");
println!(" • Encoding metadata is transmitted automatically");
println!(" • Subscribers can validate encoding at runtime");
println!(" • External Zenoh apps can detect format via sample.encoding()");
println!(" • Zero overhead - encoding cached during build()");
Ok(())
}