Written by Mo
on
on
2024-07-16 meeting summary
Today, this website has been published :D
We also talked about dealing with configuration files with serde:
- Deserializing a simple
Cargo.toml
file - The
default
field attribute with a function. - Enums with the
rename_all
container attribute - Manually implementing the
Deserialize
trait for a custom type
The example was about deserializing this demo.toml
file:
[package]
name = "axum-example"
version = "0.1.0"
edition = "2021"
authors = ["Max Mustermann <maxmustermann@proton.me>"]
publish = false
[dependencies]
askama = "0.12.1"
axum = "0.7.5"
serde = { version = "1.0.203", features = ["derive"] }
tokio = { version = "1.38.0", default-features = false, features = ["macros", "rt-multi-thread"] }
Code:
use serde::{de::Error, Deserialize};
use std::{collections::HashMap, fs};
#[derive(Debug)]
struct Version {
major: u8,
minor: u8,
patch: u8,
}
impl<'de> Deserialize<'de> for Version {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let mut iter = s.split('.').filter_map(|part| part.parse::<u8>().ok());
let (Some(major), Some(minor), Some(patch), None) =
(iter.next(), iter.next(), iter.next(), iter.next())
else {
return Err(D::Error::custom("Invalid version"));
};
Ok(Self {
major,
minor,
patch,
})
}
}
#[derive(Deserialize, Debug)]
struct Package {
name: String,
version: Version,
edition: String,
authors: Vec<String>,
publish: bool,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "kebab-case")]
struct DetailedDependency {
version: Version,
#[serde(default = "default_true")]
default_features: bool,
features: Vec<String>,
}
fn default_true() -> bool {
true
}
#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum Dependency {
VersionOnly(Version),
Detailed(DetailedDependency),
}
#[derive(Deserialize, Debug)]
struct CargoToml {
package: Package,
dependencies: HashMap<String, Dependency>,
}
fn main() {
let config_file = fs::read_to_string("demo.toml").unwrap();
let config: CargoToml = toml_edit::de::from_str(&config_file).unwrap();
println!("{config:#?}");
}