I have a configuration "server" written in Rust (not in the sense of a public internet server, but a process other processes can talk to via IPC). It makes heavy use of Serde, especially the JSON integration. There's a lot of repeated idioms that I'd like to make a bit less verbose though. I think an example illustrates it well.
Consider eg. a contact info data type:
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub enum ContactInfo {
pub name: String,
pub address: String,
pub phone: String,
pub email: String,
}
Any of these fields can be updated. The updates arrive as differences encoded as JSON eg.
{
"address" : "123 Fake St",
}
I think this naturally lends itself to a type composed of Option
s:
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub enum ContactInfoUpdate {
pub name: Option<String>,
pub address: Option<String>,
pub phone: Option<String>,
pub email: Option<String>,
}
And then I can implement an update function on ContactInfo
that updates the fields from the non-None fields in the update. The JSON messages trivially deserialises to the update type, and the non-optional type trivially serialises to a config file. So far so good.
However, I have dozens of these, and it's a lot of boilerplate. They're not all strings, some are numeric or boolean. Other approaches I've considered:
- Just make the original type the same as the update type ie. all
Option
s. But then I need a lot of runtime checks to make sure the data in the actual config is allSome(...)
. - Descend into the JSON one more level when I get an update and have an update function for each field. That's probably more boilerplate I suspect, plus then I have JSON code mixed in with my pure-Rust-type code.
Is there a way to (a) just generate the all-Option type from the original type, and (b) have a generic implementation for "applying" it ie. overwriting the existing fields with the non-None values from the update type? Does such a thing already exist?
I'm not even sure what to call this, although I think of it as a difference type (even though it's not strictly symmetric) or a delta type. But searching for that has not been fruitful.