defaulted 0.1.1

Trait and derive macro for testing whether a value equals its default state, with per-field customization and optional serde integration
Documentation

Trait and derive macro for testing whether a value equals its default state, with per-field customization and optional serde integration.

Core trait

[Defaulted] is a single-method trait:

pub trait Defaulted {
    fn is_defaulted(&self) -> bool;
}

Built-in impls cover all primitive types, String, Option<T>, Vec<T>, HashMap, HashSet, and (with feature flags) IndexMap/IndexSet and serde_json types.

Derive macro

Enable the derive feature and annotate your struct or enum:

# #[cfg(feature = "derive")] {
use defaulted::Defaulted;

#[derive(Default, Defaulted)]
struct Config {
    width: u32,
    height: u32,
    label: String,
}

assert!(Config::default().is_defaulted());
assert!(!Config { width: 1920, ..Config::default() }.is_defaulted());
# }

Per-field attributes

Each field can carry #[defaulted(...)] to control how it participates:

Attribute Behavior
(none) Delegate to the field type's Defaulted impl
#[defaulted(default = expr)] Field is "default" when it equals expr
#[defaulted(with = func)] Call func(&field) -- true means "default"
#[defaulted(with = |v| ...)] Inline closure predicate
#[defaulted(ignore)] Always skip this field
# #[cfg(feature = "derive")] {
use defaulted::Defaulted;

#[derive(Defaulted)]
struct Request {
    path: String,

    #[defaulted(default = 30)]
    timeout_secs: u64,

    #[defaulted(with = Vec::is_empty)]
    tags: Vec<String>,

    #[defaulted(ignore)]
    _request_id: u64,
}
# }

Struct-level attributes

#[defaulted(Default)] on a struct generates a Default impl whose per-field values match the #[defaulted(default = expr)] annotations, keeping the two in sync automatically.

Enums

Mark exactly one variant with #[defaulted(default)]:

# #[cfg(feature = "derive")] {
use defaulted::Defaulted;

#[derive(Defaulted)]
enum Status {
    #[defaulted(default)]
    Idle,
    Running,
    Failed(u32),
}

assert!(Status::Idle.is_defaulted());
assert!(!Status::Running.is_defaulted());
# }

Serde integration (serde feature)

#[skip_serializing_defaults] is an attribute macro that rewrites struct fields to add #[serde(skip_serializing_if = "...")] automatically, so fields at their default value are omitted from serialized output. #[defaulted(default = expr)] fields also get a matching #[serde(default = "...")] so they round-trip correctly.

# #[cfg(all(feature = "serde", feature = "serde-json", feature = "derive"))] {
use defaulted::Defaulted;
use serde::Serialize;

#[defaulted::skip_serializing_defaults]
#[derive(Serialize, Defaulted)]
#[defaulted(Default)]
struct ApiConfig {
    #[defaulted(default = "https://api.example.com")]
    base_url: String,

    #[defaulted(default = 60)]
    timeout_secs: u32,

    tags: Vec<String>,
}

let c = ApiConfig::default();
assert_eq!(serde_json::to_string(&c).unwrap(), "{}");
# }

Feature flags

Flag Default Description
std yes Enables impls for HashMap, Mutex, Path, etc. Implies alloc.
alloc yes (via std) Enables impls for String, Vec, Box, Arc, Cow, etc.
derive no Enables #[derive(Defaulted)]
serde no Enables #[skip_serializing_defaults] attribute macro
serde-json no Enables impls for serde_json::Value and serde_json::Map
serde-yaml no Enables impls for serde_yaml::Value and serde_yaml::Mapping
bytes no Enables impls for Bytes and BytesMut
indexmap no Enables impls for IndexMap and IndexSet
smallvec no Enables impls for SmallVec