macro3681

Crates.iomacro3681
lib.rsmacro3681
version0.3.0
created_at2025-07-08 09:10:35.599318+00
updated_at2025-08-25 06:29:40.986845+00
descriptiondefine struct with default field values like rfc3681 via proc-macro
homepage
repositoryhttps://github.com/honhimW/struct-with-defaults
max_upload_size
id1742296
size18,612
(honhimW)

documentation

README

Macro 3681

FYI

About this crate

MSRV

Since crate syn's msrv is 1.61, that also the msrv for this crate.

  • Thinking about default values in structs.
  • Implement via proc-macro.
  • RFC-3681 default field values must be const, which is not enough for most cases e.g. String.

Usage

cargo add macro3681

With Default derive

Default derive will be automatically removed, and generate an impl with default field values. If there are none-default fields, those fields will be added as constructor parameters.

default_field_values! {
    #[derive(Default, Debug)]
    struct Example<'a, T, T2: Default> where T: Default {
        i: u32 = 3,
        j: i128,
        i_option: Option<u64> = Some(1000),
        string: String = {
            let s = format!("{} {}", "hello", "world");
            s
        },
        os: Option<String>,
        foo: Foo = _, // #[derive(Default, Debug)] struct Foo { .. }
        bytes: &'a[u8] = b"hello world",
        t: T,
        t2: T2,
    }
    
    #[derive(Default, Debug)]
    struct Tuple<'a, T: Default>(T, #[allow(unused)] &'a str = "abc", Foo = _, Option<String>);
}

Macro Expansion

#[derive(Debug)]
struct Example<'a, T, T2>
where
    T: Default,
{
    i: u32,
    j: i128,
    i_option: Option<u64>,
    string: String,
    os: Option<String>,
    foo: Foo,
    bytes: &'a [u8],
    t: T,
    t2: T2,
}
impl<'a, T, T2: Default> Example<'a, T, T2>
where
    T: Default,
{
    pub fn new(j: i128, os: Option<String>, t: T, t2: T2) -> Self {
        Self {
            i: 3,
            j,
            i_option: Some(1000),
            string: {
                let s = format!("{} {}", "hello", "world");
                s
            },
            os,
            foo: Default::default(),
            bytes: b"hello world",
            t,
            t2,
        }
    }
}
impl<'a, T, T2: Default> Default for Example<'a, T, T2>
where
    T: Default,
{
    fn default() -> Self {
        Self {
            i: 3,
            i_option: Some(1000),
            string: {
                let s = format!("{} {}", "hello", "world");
                s
            },
            foo: Default::default(),
            bytes: b"hello world",
            j: Default::default(),
            os: Default::default(),
            t: Default::default(),
            t2: Default::default(),
        }
    }
}

#[derive(Debug)]
struct Tuple<'a, T> (T, #[allow(unused)]   &'a str, Foo, Option<String> );
impl<'a, T: Default> Tuple<'a, T> { pub fn new(_0: T, _3: Option<String>) -> Self { Self(_0, "abc", Default::default(), _3 ) } }
impl<'a, T: Default> Default for Tuple<'a, T> { fn default() -> Self { Self(Default::default(), "abc", Default::default(), Default::default() ) } 

Without Default derive

Will not generate Self::default() function, only Self::new(..) is available

default_field_values! {
    #[derive(Clone, Debug)]
    pub(crate) struct Bar {
        pub i: u32,
        j: u32 = 100 * 4,
    }
}
Commit count: 27

cargo fmt