Ecosystem Integration
Facet provides Facet trait implementations for many popular Rust crates via feature flags. Enable the feature, and those types work seamlessly with all facet format crates.
Third-Party type support
Enable these features in your Cargo.toml:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , features = [ "uuid" , "chrono" ] }
Available features
| Feature | Crate | Types |
|---|---|---|
uuid | uuid | Uuid |
ulid | ulid | Ulid |
url | url | Url |
chrono | chrono | DateTime<Tz>, NaiveDate, NaiveTime, NaiveDateTime |
time | time | Date, Time, PrimitiveDateTime, OffsetDateTime, Duration |
jiff02 | jiff | Timestamp, Zoned, DateTime, Date, Time, Span, SignedDuration |
camino | camino | Utf8Path, Utf8PathBuf |
bytes | bytes | Bytes, BytesMut |
ordered-float | ordered-float | OrderedFloat<f32>, OrderedFloat<f64>, NotNan<f32>, NotNan<f64> |
ruint | ruint | Uint<BITS, LIMBS>, Bits<BITS, LIMBS> |
Example: uUIDs
use facet:: Facet ;
use uuid:: Uuid ;
# [ derive ( Facet )]
struct User {
id : Uuid ,
name : String ,
}
let json = r#"{"id": "550e8400-e29b-41d4-a716-446655440000", "name": "Alice"}"# ;
let user: User = facet_json:: from_str ( json) ?;
Example: dateTime with chrono
use facet:: Facet ;
use chrono::{ DateTime , Utc };
# [ derive ( Facet )]
struct Event {
name : String ,
timestamp : DateTime < Utc >,
}
let json = r#"{"name": "deploy", "timestamp": "2024-01-15T10:30:00Z"}"# ;
let event: Event = facet_json:: from_str ( json) ?;
Example: UTF-8 paths with camino
use facet:: Facet ;
use camino:: Utf8PathBuf ;
# [ derive ( Facet )]
struct Config {
data_dir : Utf8PathBuf ,
}
Extended tuple support
By default, facet supports tuples up to 4 elements. Enable tuples-12 for tuples up to 12 elements:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , features = [ "tuples-12" ] }
Function pointer support
Enable fn-ptr for Facet implementations on function pointer types:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , features = [ "fn-ptr" ] }
Standard library type support
Some standard library types require feature flags:
| Feature | Types |
|---|---|
nonzero | NonZero<T> types (NonZeroU8, NonZeroI32, etc.) |
net | SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6 |
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , features = [ "nonzero" , "net" ] }
Doc comment extraction
By default, doc comments (/// ...) are not included in generated Shape, Field, and Variant definitions to reduce compile times and binary size. Enable the doc feature to include them:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , features = [ "doc" ] }
This is useful for:
- facet-args: Including doc comments in CLI help text generation
- facet-pretty: Showing doc comments in pretty-printed output
- Custom tooling: Building documentation generators or IDE integrations
Without this feature, .doc fields will be empty slices (&[]).
Typo suggestions in derive errors
By default, when you mistype an attribute name in #[facet(...)], the derive macro suggests corrections using string similarity matching. This requires the strsim dependency.
To disable this and reduce compile times slightly, turn off the helpful-derive feature:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , default-features = false , features = [ "std" ] }
With helpful-derive enabled (default):
error: unknown attribute `renam`, did you mean `rename`?
Without it:
error: unknown attribute `renam`; expected one of: rename, skip, default, ...
facet-args: CLI argument parsing
Beyond basic argument parsing, facet-args provides utilities for help generation and shell completions.
Help generation
Generate formatted help text from your type's structure and doc comments:
use facet:: Facet ;
use facet_args::{ generate_help, HelpConfig };
/// A file processing tool.
# [ derive ( Facet )]
struct Args {
/// Enable verbose output
# [ facet ( args :: named , args :: short )]
verbose : bool ,
/// Input file to process
# [ facet ( args :: positional )]
input : String ,
}
fn main () {
let config = HelpConfig {
program_name : Some ( "mytool" . into ()),
version : Some ( "1.0.0" . into ()),
..Default :: default ()
};
println! ( "{}" , generate_help ::< Args >( & config));
}
Shell completions
Generate completion scripts for bash, zsh, and fish:
use facet_args::{ generate_completions, Shell };
// Generate bash completions
let bash = generate_completions ::< Args >( Shell :: Bash , "mytool" );
println! ( "{}" , bash);
// Generate zsh completions
let zsh = generate_completions ::< Args >( Shell :: Zsh , "mytool" );
// Generate fish completions
let fish = generate_completions ::< Args >( Shell :: Fish , "mytool" );
Install completions by writing to the appropriate location:
- Bash:
~/.local/share/bash-completion/completions/mytool - Zsh:
~/.zsh/completions/_mytool - Fish:
~/.config/fish/completions/mytool.fish
Parsing from std::env
For quick CLI tools:
use facet_args:: from_std_args;
fn main () -> Result <(), Box < dyn std:: error:: Error >> {
let args: Args = from_std_args () ?;
// ...
Ok (())
}
See the Args showcase for comprehensive examples including subcommands, error messages, and more.
When a type doesn't implement Facet
If you have a type that doesn't implement Facet, you have several options:
Your own type
If it's your type, just derive it:
# [ derive ( Facet )]
struct MyType {
// ...
}
Type with non-Facet fields
If your type contains fields that don't implement Facet, use opaque to hide them:
use some_crate:: ExternalType ; // Doesn't implement Facet
# [ derive ( Facet )]
struct MyWrapper {
name : String ,
# [ facet ( opaque )]
internal : ExternalType , // Hidden from serialization
}
Opaque fields can't be serialized on their own. If you need serialization, add a proxy:
# [ derive ( Facet )]
# [ facet ( transparent )]
struct ExternalTypeProxy ( String );
impl TryFrom < ExternalTypeProxy > for ExternalType {
type Error = &' static str ;
fn try_from ( proxy : ExternalTypeProxy ) -> Result < Self , Self :: Error > {
ExternalType :: parse ( & proxy. 0 ). ok_or ( "invalid format" )
}
}
impl TryFrom < & ExternalType > for ExternalTypeProxy {
type Error = std:: convert:: Infallible ;
fn try_from ( val : & ExternalType ) -> Result < Self , Self :: Error > {
Ok ( ExternalTypeProxy ( val. to_string ()))
}
}
# [ derive ( Facet )]
struct MyWrapper {
name : String ,
# [ facet ( opaque , proxy = ExternalTypeProxy )]
internal : ExternalType ,
}
// Serialization: ExternalType → proxy → JSON string
let wrapper = MyWrapper {
name : "example" . into (),
internal : ExternalType :: new (),
};
let json = facet_json:: to_string ( & wrapper);
// {"name":"example","internal":"...serialized form..."}
// Deserialization: JSON → proxy → ExternalType
let parsed: MyWrapper = facet_json:: from_str ( & json). unwrap ();
See the Attributes Reference for details on opaque and proxy.
Third-party type you want full support for
If you want a third-party type to work seamlessly with facet (like uuid::Uuid does), you can contribute an implementation to facet. See Implementing Facet for third-party types.
no_std support
Facet works in no_std environments. Disable default features and enable alloc:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , default-features = false , features = [ "alloc" ] }
Some format crates also support no_std:
facet-json— withallocfeaturefacet-postcard— withallocfeaturefacet-msgpack— withallocfeature