2024-07-16 meeting summary

Today, this website has been published :D

We also talked about dealing with configuration files with serde:

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:#?}");
}