Skip to main content

typewire_derive/
lib.rs

1//! Derive macro for the `Typewire` trait.
2//!
3//! This crate provides `#[derive(Typewire)]`, which generates platform-specific
4//! conversion methods and compile-time schema records from Rust types.
5//!
6//! Most users should depend on [`typewire`](https://docs.rs/typewire) (which
7//! re-exports this macro) rather than depending on `typewire-derive` directly.
8//! See the [typewire crate docs](https://docs.rs/typewire) for supported
9//! targets and the full pipeline overview.
10//!
11//! # Attribute reference
12//!
13//! Attributes can be placed under `#[serde(...)]`,
14//! [`#[diffable(...)]`](https://docs.rs/difficient/latest/difficient/trait.Diffable.html), or
15//! `#[typewire(...)]`. The `#[typewire(...)]` namespace is a superset — when
16//! a type also derives [`Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html)/[`Deserialize`](https://docs.rs/serde/latest/serde/trait.Deserialize.html),
17//! typewire reads `#[serde]` attributes too so you don't need to duplicate them.
18//!
19//! ## Container attributes
20//!
21//! | Attribute | Effect |
22//! |-----------|--------|
23//! | `rename_all = "..."` | Rename all fields (e.g. `"camelCase"`, `"snake_case"`) |
24//! | `rename_all_fields = "..."` | Rename fields in all enum variants |
25//! | `tag = "..."` | Internally-tagged enum |
26//! | `content = "..."` | Adjacent tagging (requires `tag`) |
27//! | `untagged` | Untagged enum |
28//! | `transparent` | Newtype wrapper — delegates to inner type |
29//! | `default` | Per-field `Default::default()` fallback for missing fields |
30//! | `deny_unknown_fields` | Error on unrecognized fields |
31//! | `from = "Type"` / `try_from = "Type"` | Proxy deserialization |
32//! | `into = "Type"` | Proxy serialization |
33//!
34//! ## Variant attributes
35//!
36//! | Attribute | Effect |
37//! |-----------|--------|
38//! | `rename = "..."` | Wire name for this variant |
39//! | `alias = "..."` | Additional accepted names (repeatable) |
40//! | `rename_all = "..."` | Rename fields within this variant |
41//! | `skip` | Skip entirely |
42//! | `skip_serializing` / `skip_deserializing` | Skip one direction |
43//! | `other` | Catch-all for unknown variant names |
44//! | `untagged` | Untagged within a tagged enum |
45//!
46//! ## Field attributes
47//!
48//! | Attribute | Effect |
49//! |-----------|--------|
50//! | `rename = "..."` | Wire name for this field |
51//! | `alias = "..."` | Additional accepted names (repeatable) |
52//! | `skip` | Skip entirely (field must impl `Default`) |
53//! | `default` / `default = "path"` | Use `Default` or custom fn when absent |
54//! | `flatten` | Flatten nested struct fields into parent |
55//! | `skip_serializing_if = "path"` | Conditionally omit on serialization |
56//! | `with = "serde_bytes"` | Use `serde_bytes` encoding |
57//! | `base64` | Base64 encode/decode `Vec<u8>` fields |
58//! | `display` | Use `Display`/`FromStr` for conversion |
59//! | `lenient` | Skip invalid elements instead of failing |
60//!
61//! ## [`Diffable`](https://docs.rs/difficient/latest/difficient/trait.Diffable.html) attributes
62//!
63//! | Attribute | Effect |
64//! |-----------|--------|
65//! | `atomic` | Treat as opaque for patching (no field-level diff) |
66//! | `visit_transparent` | Generate patching code for transparent types |
67//!
68//! # [Serde](https://docs.rs/serde) divergence
69//!
70//! `#[serde(default)]` on a **container** uses per-field `Default::default()`
71//! fallbacks, **not** the container's `Default` impl. This is intentional —
72//! the derive generates independent field fallbacks rather than constructing
73//! a default instance and overwriting present fields.
74
75extern crate proc_macro;
76
77mod attr;
78mod case;
79mod expand;
80mod wasm;
81
82use proc_macro::TokenStream;
83use syn::{DeriveInput, parse_macro_input};
84
85/// Derive macro for the `Typewire` trait.
86///
87/// Generates platform-specific conversion methods (gated by `#[cfg]`) and
88/// the compile-time `Ident`/`IDENT` schema identity. See the
89/// [crate-level documentation](crate) for the full attribute reference.
90///
91/// For usage examples, see the [`typewire`](https://docs.rs/typewire) crate docs.
92#[proc_macro_derive(Typewire, attributes(serde, diffable, typewire))]
93pub fn derive_typewire(input: TokenStream) -> TokenStream {
94  let input = parse_macro_input!(input as DeriveInput);
95  expand::expand::<wasm::WasmCodegen>(&input).into()
96}