I'm using serde to deserialize items in an array to one of two types of struct. Both types implement a trait: Startable
If I want to start all of the deserialzed items in a loop, I'm currently doing something like:
for item in status.items {
match item {
ItemEntry::Pump(mut p) => p.start(),
ItemEntry::Servo(mut s) => s.start(),
}
}
Is there some cleaner way I can do this so that I can do something like the following?
for item in status.items {
item.start();
}
This is the complete code I'm working with:
use std::fs;
use serde::Deserialize;
pub trait Startable {
fn start(&mut self);
fn stop(&mut self);
}
#[derive(Deserialize,Debug)]
pub struct Pump {
speed: u32,
running: bool
}
#[derive(Deserialize,Debug)]
pub struct Servo {
speed: u32,
running: bool
}
#[derive(Deserialize,Debug)]
#[serde(tag = "type")]
pub enum ItemEntry {
Pump(Pump),
Servo(Servo)
}
#[derive(Deserialize,Debug)]
pub struct Status {
items: Vec<ItemEntry>
}
impl Startable for Pump {
fn start(&mut self) {
println!("Starting pump at speed: {}", self.speed);
self.running = true;
}
fn stop(&mut self) {
self.running = false;
}
}
impl Startable for Servo {
fn start(&mut self) {
println!("Starting servo at speed: {}", self.speed);
self.running = true;
}
fn stop(&mut self) {
self.running = false;
}
}
fn main() {
let data = fs::read_to_string("./status.json")
.expect("Unable to read file");
let status: Status = serde_json::from_str(&data)
.expect("JSON does not have correct format.");
for item in status.items {
match item {
ItemEntry::Pump(mut p) => p.start(),
ItemEntry::Servo(mut s) => s.start(),
}
}
}
Example JSON file:
{
"items": [
{
"type": "Pump",
"speed": 1,
"running": false
},
{
"type": "Servo",
"speed": 2,
"running": false
}
]
}