Facet

Derive Macro Facet 

Source
#[derive(Facet)]
{
    // Attributes available to this derive:
    #[facet]
}
Expand description

§Deriving Facet

The Facet derive macro provides runtime (and to some extent, const-time) knowledge about types, also known as “reflection”.

This macro uses unsynn instead of syn, which makes it lighter but means it does not implement a complete Rust grammar. Some complex syntax may fail to parse. If you encounter a parsing issue, please open an issue.

use facet::Facet;

#[derive(Facet)]
struct FooBar {
    foo: u32,
    bar: String,
}

§How renaming works

Unlike serde, where rename only affects the serialized form, in facet the renamed value becomes the field’s effective name — the name you see when enumerating fields via reflection.

The original Rust identifier is still preserved and accessible, but the effective name is what most operations use by default.

§Serialization and deserialization

The facet crate itself does not perform serialization or deserialization — it only provides reflection capabilities. The #[facet(...)] attributes are stored as metadata on fields, variants, and containers, which other crates can then read and act upon.

Serialization and deserialization are handled by separate crates:

These crates read the field attributes, variant attributes, and container attributes defined below to control their behavior.

§Container Attributes

Container attributes apply to the struct or enum as a whole.

use facet::Facet;

#[derive(Facet)]
#[facet(rename_all = "kebab-case")]
struct FooBar {
    // fields...
}

§Naming

AttributeDescription
rename_all = ".."Rename all the fields (if this is a struct) or variants (if this is an enum) according to the given case convention. The possible values are: "snake_case", "SCREAMING_SNAKE_CASE", "PascalCase", "camelCase", "kebab-case", "SCREAMING-KEBAB-CASE".
type_tag = ".."Identify type by tag and serialize with this tag, e.g., #[facet(type_tag = "com.example.MyType")].

§Type representation

AttributeDescription
transparentSerialize and deserialize a newtype struct exactly the same as if its single field were serialized and deserialized by itself.
opaqueThe inner field does not have to implement Facet.

§Serialization

AttributeDescription
skip_serializingDon’t allow this type to be serialized.
skip_serializing_if = ".."Don’t allow this type to be serialized if the function returns true.
serialize_with = ..Support serialization using the specified function. Takes the form fn(&input_type) -> output_shape where input_type can be any type, including opaque types.

§Deserialization

AttributeDescription
deny_unknown_fieldsAlways throw an error when encountering unknown fields during deserialization. When this attribute is not present, unknown fields are ignored.
deserialize_with = ..Support deserialization using the specified function. Takes the form fn(&input_shape) -> output_type where output_type can be any type, including opaque types.

§Validation

AttributeDescription
invariants = ".."Called when doing Partial::build. TODO

§Field Attributes

Field attributes apply to individual fields within a struct or enum variant.

use facet::Facet;

#[derive(Facet)]
struct FooBar {
    #[facet(default)]
    foo: u32,
}

§Naming

AttributeDescription
rename = ".."Rename this field to the given name.

§Structure

AttributeDescription
flattenFlatten the field’s content into the container structure.
childMark as child node in a hierarchy. TODO

§Serialization

AttributeDescription
skip_serializingIgnore when serializing.
skip_serializing_if = ".."Ignore when serializing if the function returns true.
serialize_with = ..Support serialization of this field using the specified function.

§Deserialization

AttributeDescription
defaultUse the field’s value from the container’s Default::default() implementation when the field is missing during deserializing.
default = ".."Use the expression when the field is missing during deserializing.
deserialize_with = ..Support deserialization of this field using the specified function.

§Debug

AttributeDescription
sensitiveDon’t show the value in debug outputs.

§Variant Attributes

Variant attributes apply to individual variants within an enum.

use facet::Facet;

#[derive(Facet)]
#[repr(C)]
enum FooBar {
    #[facet(rename = "kebab-case")]
    Foo(u32),
}

§Naming

AttributeDescription
rename = ".."Rename this variant to the given name.

§Serialization

AttributeDescription
skip_serializingIgnore when serializing.
skip_serializing_if = ".."Ignore when serializing if the function returns true.
serialize_with = ..Support serialization of this variant using the specified function.

§Deserialization

AttributeDescription
deserialize_with = ..Support deserialization of this variant using the specified function.

§Examples

TODO.