#serde #serialization #const-generics #no-alloc #no-std

no-std serde_default_utils

A set of simple helper functions to cut corners with serde_default

4 releases

0.2.2 Feb 1, 2024
0.2.1 Jan 16, 2024
0.2.0 Jan 15, 2024
0.1.0 Jan 10, 2024

#1031 in Encoding

Download history 19/week @ 2024-01-08 108/week @ 2024-01-15 135/week @ 2024-01-22 144/week @ 2024-01-29 89/week @ 2024-02-05 83/week @ 2024-02-12 240/week @ 2024-02-19 217/week @ 2024-02-26 192/week @ 2024-03-04 203/week @ 2024-03-11 160/week @ 2024-03-18 99/week @ 2024-03-25 191/week @ 2024-04-01

668 downloads per month
Used in zika

MIT/Apache

16KB
94 lines

serde_default_utils

v

Overview

This is a simple set of functions to make your life easier while working with defaults in serde. Based on const generic parameters. Heavily inspired by discussions on issues about serde defaults, but mostly this one

Kudos

  • JohnTheCoolingFan posted this solution, I just made it available as crate and a macro that helps to generate another const generic function for any const generic type.
  • bytedream made a more powerful version of it, and although I still see const generic approach as more readable, I have to admit that for strings it's superior, hence - included under the feature

Example

    use serde_default_utils::*;
    use serde::{Deserialize, Serialize};

        const JSON: &str =
            r#"{
                "yes_or_no":false,
                "max":60,
                "delta":-77,
                "delimeter":"☀",
                "motto":"I matter"
            }"#;
        const INLINE_JSON: &str =
            r#"{
                "inline_motto":"I matter even more",
                "slice":["I", "matter", "even", "more"],
                "slice_u64":[9000, 8000, 10000, 7000]
            }"#;
    const EMPTY_JSON: &str = r#"{}"#;
    const MAX: u32 = 7;

    serde_default!(motto, "You matter");

    #[derive(Serialize, Deserialize, Default)]
    struct Config {
        #[serde(default = "default_bool::<true>")]
        yes_or_no: bool,
        #[serde(default = "default_i16::<-3>")]
        delta: i16,
        // you can even use consts right here
        #[serde(default = "default_u32::<MAX>")]
        max: u32,
        #[serde(default = "default_char::<'☀'>")]
        delimeter: char,
        #[serde(default = "default_motto")]
        motto: &'static str,
    }

    #[cfg(feature = "inline")]
    #[serde_inline_default]
    #[derive(Serialize, Deserialize, Default)]
    struct InlineConfig {
        #[serde_inline_default("You matter even more".to_string())]
        inline_motto: String,
        #[serde_inline_default(vec!["You", "matter", "even", "more"])]
        slice: Vec<&'static str>,
        #[serde_inline_default(vec![98712, 12346, 129389, 102937])]
        slice_u64: Vec<u64>,
    }

    fn main() {
        // existing json fields are not changed
        let config: Config = serde_json::from_str(JSON).unwrap();
        let s = serde_json::to_string(&config).unwrap();
        assert_eq!(r#"{"yes_or_no":false,"delta":-77,"max":60,"delimeter":"☀","motto":"I matter"}"#, &s);
        // if the field is not present - it is substituted with defaults
        let config: Config = serde_json::from_str(EMPTY_JSON).unwrap();
        let s = serde_json::to_string(&config).unwrap();
        assert_eq!(r#"{"yes_or_no":true,"delta":-3,"max":7,"delimeter":"☀","motto":"You matter"}"#, &s);
        // the default impl is just calling underlying type defaults unless you have a custom impl Default
        let config = Config::default();
        let s = serde_json::to_string(&config).unwrap();
        assert_eq!(r#"{"yes_or_no":false,"delta":0,"max":0,"delimeter":"\u0000","motto":""}"#, &s);

        // Inline
        #[cfg(feature = "inline")]
        {
        // existing json fields are not changed
        let config: InlineConfig = serde_json::from_str(INLINE_JSON).unwrap();
        let s = serde_json::to_string(&config).unwrap();
        assert_eq!(r#"{"inline_motto":"I matter even more","slice":["I","matter","even","more"],"slice_u64":[9000,8000,10000,7000]}"#, &s);
        // if the field is not present - it is substituted with defaults
        let config: InlineConfig = serde_json::from_str(EMPTY_JSON).unwrap();
        let s = serde_json::to_string(&config).unwrap();
        assert_eq!(r#"{"inline_motto":"You matter even more","slice":["You","matter","even","more"],"slice_u64":[98712,12346,129389,102937]}"#, &s);
        // the default impl is just calling underlying type defaults unless you have a custom impl Default
        let config = Config::default();
        let s = serde_json::to_string(&config).unwrap();
        assert_eq!(r#"{"inline_motto":"","slice":[],"slice_u64":[]}"#, &s);
        }
    }

License: MIT OR Apache-2.0

Dependencies

~125KB