use dyn_shim::dyn_shim;
#[dyn_shim(DynChannel)]
trait Channel {
fn connect() -> Self; fn label(&self) -> String;
fn set_prefix(&mut self, prefix: &str);
fn deliver(&mut self, message: &str);
fn close(self) -> u32; }
struct Email {
address: String,
prefix: String,
sent: u32,
}
impl Channel for Email {
fn connect() -> Self {
Email {
address: "ops@example.com".into(),
prefix: String::new(),
sent: 0,
}
}
fn label(&self) -> String {
format!("email<{}>", self.address)
}
fn set_prefix(&mut self, prefix: &str) {
self.prefix = prefix.into();
}
fn deliver(&mut self, message: &str) {
println!(" [email -> {}] {}{}", self.address, self.prefix, message);
self.sent += 1;
}
fn close(self) -> u32 {
self.sent
}
}
struct Webhook {
url: String,
prefix: String,
sent: u32,
}
impl Channel for Webhook {
fn connect() -> Self {
Webhook {
url: "https://hooks.example.com/abc".into(),
prefix: String::new(),
sent: 0,
}
}
fn label(&self) -> String {
format!("webhook<{}>", self.url)
}
fn set_prefix(&mut self, prefix: &str) {
self.prefix = prefix.into();
}
fn deliver(&mut self, message: &str) {
println!(" [webhook -> {}] {}{}", self.url, self.prefix, message);
self.sent += 1;
}
fn close(self) -> u32 {
self.sent
}
}
fn main() {
let mut channels: Vec<Box<dyn DynChannel>> =
vec![Box::new(Email::connect()), Box::new(Webhook::connect())];
for ch in channels.iter_mut() {
ch.set_prefix("[prod] ");
}
let messages = ["deploy finished", "nightly backup completed"];
for msg in messages {
println!("broadcasting: {msg:?}");
for ch in channels.iter_mut() {
ch.deliver(msg);
}
}
println!("\nshutting down:");
for ch in channels {
let label = ch.label();
let sent = ch.close();
println!(" {label} sent {sent} message(s)");
}
}