toasty_macros/lib.rs
1//! Procedural macros for the Toasty ORM.
2//!
3//! This crate provides `#[derive(Model)]`, `#[derive(Embed)]`, and related
4//! attribute macros that generate query builders, schema registration, and
5//! database mapping code.
6
7#![warn(missing_docs)]
8
9extern crate proc_macro;
10
11mod create;
12mod model;
13mod query;
14mod update;
15
16use proc_macro::TokenStream;
17
18/// Derive macro that turns a struct into a Toasty model backed by a database
19/// table.
20///
21/// For a tutorial-style introduction, see the [Toasty guide].
22///
23#[doc = include_str!(concat!(env!("OUT_DIR"), "/guide_link.md"))]
24///
25/// # Overview
26///
27/// Applying `#[derive(Model)]` to a named struct generates:
28///
29/// - A [`Model`] trait implementation, including the associated `Query`,
30/// `Create`, and `Update` builder types.
31/// - A [`Load`] implementation for deserializing rows from the database.
32/// - The [`Model`] trait's schema-registration methods (`id`, `schema`,
33/// `register`) used to register the model at runtime.
34/// - Static query methods such as `all()`, `filter(expr)`,
35/// `filter_by_<field>()`, and `get_by_<key>()`.
36/// - Instance methods `update()` and `delete()`.
37/// - A `Fields` struct returned by `<Model>::fields()` for building typed
38/// filter expressions.
39///
40/// The struct must have named fields and no generic parameters.
41///
42/// [`Model`]: toasty::schema::Model
43/// [`Load`]: toasty::schema::Load
44///
45/// # Struct-level attributes
46///
47/// ## `#[key(...)]` — primary key
48///
49/// Defines the primary key at the struct level. Mutually exclusive with
50/// field-level `#[key]`.
51///
52/// **Simple form** — every listed field becomes a partition key:
53///
54/// ```
55/// # use toasty::Model;
56/// #[derive(Model)]
57/// #[key(name)]
58/// struct Widget {
59/// name: String,
60/// value: i64,
61/// }
62/// ```
63///
64/// **Composite key with partition/local scoping:**
65///
66/// ```
67/// # use toasty::Model;
68/// #[derive(Model)]
69/// #[key(partition = user_id, local = id)]
70/// struct Todo {
71/// #[auto]
72/// id: uuid::Uuid,
73/// user_id: String,
74/// title: String,
75/// }
76/// ```
77///
78/// The `partition` fields determine data distribution (relevant for
79/// DynamoDB); `local` fields scope within a partition. For SQL databases
80/// both behave as a regular composite primary key.
81///
82/// Multiple `partition` and `local` fields are allowed using bracket syntax:
83///
84/// ```
85/// # use toasty::Model;
86/// # #[derive(Model)]
87/// #[key(partition = [tenant, org], local = [id])]
88/// # struct Example { tenant: String, org: String, id: String }
89/// ```
90///
91/// When using named `partition`/`local` syntax, at least one of each is
92/// required. You cannot mix the simple and named forms.
93///
94/// ## `#[table = "name"]` — custom table name
95///
96/// Overrides the default table name. Without this attribute the table name
97/// is the pluralized, snake_case form of the struct name (e.g. `User` →
98/// `users`).
99///
100/// ```
101/// # use toasty::Model;
102/// #[derive(Model)]
103/// #[table = "legacy_users"]
104/// struct User {
105/// #[key]
106/// #[auto]
107/// id: i64,
108/// name: String,
109/// }
110/// ```
111///
112/// # Field-level attributes
113///
114/// ## `#[key]` — mark a field as a primary key column
115///
116/// Marks one or more fields as the primary key. When used on multiple
117/// fields each becomes a partition key column (equivalent to listing them
118/// in `#[key(...)]` at the struct level).
119///
120/// Cannot be combined with a struct-level `#[key(...)]` attribute.
121///
122/// ```
123/// # use toasty::Model;
124/// #[derive(Model)]
125/// struct User {
126/// #[key]
127/// #[auto]
128/// id: i64,
129/// name: String,
130/// }
131/// ```
132///
133/// ## `#[auto]` — automatic value generation
134///
135/// Tells Toasty to generate this field's value automatically. The strategy
136/// depends on the field type and optional arguments:
137///
138/// | Syntax | Behavior |
139/// |--------|----------|
140/// | `#[auto]` on `uuid::Uuid` | UUID v7 (timestamp-sortable) |
141/// | `#[auto(uuid(v4))]` | UUID v4 (random) |
142/// | `#[auto(uuid(v7))]` | UUID v7 (explicit) |
143/// | `#[auto]` on integer types (`i8`–`i64`, `u8`–`u64`) | Auto-increment |
144/// | `#[auto(increment)]` | Auto-increment (explicit) |
145/// | `#[auto]` on a field named `created_at` | Expands to `#[default(jiff::Timestamp::now())]` |
146/// | `#[auto]` on a field named `updated_at` | Expands to `#[update(jiff::Timestamp::now())]` |
147///
148/// The `created_at`/`updated_at` expansion requires the `jiff` feature and
149/// a field type compatible with `jiff::Timestamp`.
150///
151/// Cannot be combined with `#[default]` or `#[update]` on the same field.
152///
153/// ## `#[default(expr)]` — default value on create
154///
155/// Sets a default value that is used when the field is not explicitly
156/// provided during creation. The expression is any valid Rust expression.
157///
158/// ```
159/// # use toasty::Model;
160/// # #[derive(Model)]
161/// # struct Example {
162/// # #[key]
163/// # #[auto]
164/// # id: i64,
165/// #[default(0)]
166/// view_count: i64,
167///
168/// #[default("draft".to_string())]
169/// status: String,
170/// # }
171/// ```
172///
173/// The default can be overridden by calling the corresponding setter on the
174/// create builder.
175///
176/// Cannot be combined with `#[auto]` on the same field. Can be combined
177/// with `#[update]` (the default applies on create; the update expression
178/// applies on subsequent updates).
179///
180/// ## `#[update(expr)]` — value applied on create and update
181///
182/// Sets a value that Toasty applies every time a record is created or
183/// updated, unless the field is explicitly set on the builder.
184///
185/// ```
186/// # use toasty::Model;
187/// # #[derive(Model)]
188/// # struct Example {
189/// # #[key]
190/// # #[auto]
191/// # id: i64,
192/// #[update(jiff::Timestamp::now())]
193/// updated_at: jiff::Timestamp,
194/// # }
195/// ```
196///
197/// Cannot be combined with `#[auto]` on the same field.
198///
199/// ## `#[index]` — add a database index
200///
201/// Creates a non-unique index on the field. Toasty generates a
202/// `filter_by_<field>` method for indexed fields.
203///
204/// ```
205/// # use toasty::Model;
206/// # #[derive(Model)]
207/// # struct Example {
208/// # #[key]
209/// # #[auto]
210/// # id: i64,
211/// #[index]
212/// email: String,
213/// # }
214/// ```
215///
216/// ## `#[unique]` — add a unique constraint
217///
218/// Creates a unique index on the field. Like `#[index]`, this generates
219/// `filter_by_<field>`. The database enforces uniqueness.
220///
221/// ```
222/// # use toasty::Model;
223/// # #[derive(Model)]
224/// # struct Example {
225/// # #[key]
226/// # #[auto]
227/// # id: i64,
228/// #[unique]
229/// email: String,
230/// # }
231/// ```
232///
233/// ## `#[column(...)]` — customize the database column
234///
235/// Overrides the column name and/or type for a field.
236///
237/// **Custom name:**
238///
239/// ```
240/// # use toasty::Model;
241/// # #[derive(Model)]
242/// # struct Example {
243/// # #[key]
244/// # #[auto]
245/// # id: i64,
246/// #[column("user_email")]
247/// email: String,
248/// # }
249/// ```
250///
251/// **Custom type:**
252///
253/// ```
254/// # use toasty::Model;
255/// # #[derive(Model)]
256/// # struct Example {
257/// # #[key]
258/// # #[auto]
259/// # id: i64,
260/// #[column(type = varchar(255))]
261/// email: String,
262/// # }
263/// ```
264///
265/// **Both:**
266///
267/// ```
268/// # use toasty::Model;
269/// # #[derive(Model)]
270/// # struct Example {
271/// # #[key]
272/// # #[auto]
273/// # id: i64,
274/// #[column("user_email", type = varchar(255))]
275/// email: String,
276/// # }
277/// ```
278///
279/// ### Supported column types
280///
281/// | Syntax | Description |
282/// |--------|-------------|
283/// | `boolean` | Boolean |
284/// | `i8`, `i16`, `i32`, `i64` | Signed integer (1/2/4/8 bytes) |
285/// | `int(N)` | Signed integer with N-byte width |
286/// | `u8`, `u16`, `u32`, `u64` | Unsigned integer (1/2/4/8 bytes) |
287/// | `uint(N)` | Unsigned integer with N-byte width |
288/// | `text` | Unbounded text |
289/// | `varchar(N)` | Text with max length N |
290/// | `numeric` | Arbitrary-precision numeric |
291/// | `numeric(P, S)` | Numeric with precision P and scale S |
292/// | `binary(N)` | Fixed-size binary with N bytes |
293/// | `blob` | Variable-length binary |
294/// | `timestamp(P)` | Timestamp with P fractional-second digits |
295/// | `date` | Date without time |
296/// | `time(P)` | Time with P fractional-second digits |
297/// | `datetime(P)` | Date and time with P fractional-second digits |
298/// | `"custom"` | Arbitrary type string passed through to the driver |
299///
300/// Cannot be used on relation fields.
301///
302/// ## JSON-encoded fields via [`Json<T>`](toasty::stmt::Json)
303///
304/// Wrap a serde-typed value in [`toasty::Json<T>`](toasty::stmt::Json) to
305/// store it as a JSON string in the database. Requires the `serde` feature
306/// and that `T` implements `serde::Serialize` and `serde::Deserialize`.
307///
308/// ```
309/// # use toasty::Model;
310/// # #[derive(Model)]
311/// # struct Example {
312/// # #[key]
313/// # #[auto]
314/// # id: i64,
315/// tags: toasty::Json<Vec<String>>,
316/// # }
317/// ```
318///
319/// For nullable JSON columns, wrap `Json<T>` in `Option` — `None` maps to
320/// SQL `NULL`:
321///
322/// ```
323/// # use toasty::Model;
324/// # use std::collections::HashMap;
325/// # #[derive(Model)]
326/// # struct Example {
327/// # #[key]
328/// # #[auto]
329/// # id: i64,
330/// metadata: Option<toasty::Json<HashMap<String, String>>>,
331/// # }
332/// ```
333///
334/// To instead store `None` as the JSON literal `"null"` (no SQL `NULL`),
335/// wrap the other way: `Json<Option<T>>`.
336///
337/// # Relation attributes
338///
339/// Relation fields can be lazy or eager. Wrap the relation value in
340/// `toasty::Deferred<_>` for lazy loading; ordinary queries leave the field
341/// unloaded until the generated relation accessor or `.include(...)` loads it.
342/// Use the relation value directly for eager loading; every query that returns
343/// the model loads the relation as if the query included that field.
344///
345/// | Attribute | Lazy field type | Eager field type |
346/// |-----------|-----------------|------------------|
347/// | `#[belongs_to]` | `toasty::Deferred<T>` or `toasty::Deferred<Option<T>>` | `T` or `Option<T>` |
348/// | `#[has_many]` | `toasty::Deferred<Vec<T>>` | `Vec<T>` |
349/// | `#[has_one]` | `toasty::Deferred<T>` or `toasty::Deferred<Option<T>>` | `T` or `Option<T>` |
350///
351/// Toasty rejects schemas with eager-load cycles. If two relation paths point
352/// back to each other, wrap at least one field in `toasty::Deferred<_>`.
353///
354/// ## `#[belongs_to(...)]` — foreign-key reference
355///
356/// Declares a many-to-one (or one-to-one) association through a foreign
357/// key stored on this model.
358///
359/// ```
360/// # use toasty::Model;
361/// # #[derive(Model)]
362/// # struct User {
363/// # #[key]
364/// # #[auto]
365/// # id: i64,
366/// # }
367/// # #[derive(Model)]
368/// # struct Example {
369/// # #[key]
370/// # #[auto]
371/// # id: i64,
372/// # user_id: i64,
373/// #[belongs_to(key = user_id, references = id)]
374/// user: toasty::Deferred<User>,
375/// # }
376/// ```
377///
378/// To load the relation with every `Example` query, omit `Deferred`:
379///
380/// ```ignore
381/// #[belongs_to(key = user_id, references = id)]
382/// user: User,
383/// ```
384///
385/// | Parameter | Meaning |
386/// |-----------|---------|
387/// | `key = <field>` | Local field holding the foreign key value |
388/// | `references = <field>` | Field on the target model being referenced |
389///
390/// For composite foreign keys, pass arrays to `key` and `references`:
391///
392/// ```
393/// # use toasty::Model;
394/// # #[derive(Model)]
395/// # #[key(id, tenant_id)]
396/// # struct Org {
397/// # id: i64,
398/// # tenant_id: i64,
399/// # }
400/// # #[derive(Model)]
401/// # struct Example {
402/// # #[key]
403/// # #[auto]
404/// # id: i64,
405/// # org_id: i64,
406/// # tenant_id: i64,
407/// #[belongs_to(key = [org_id, tenant_id], references = [id, tenant_id])]
408/// org: toasty::Deferred<Org>,
409/// # }
410/// ```
411///
412/// The number of fields in `key` must equal the number of fields in
413/// `references`.
414///
415/// Wrap the target type in `Option` for an optional (nullable) foreign key:
416///
417/// ```
418/// # use toasty::Model;
419/// # #[derive(Model)]
420/// # struct User {
421/// # #[key]
422/// # #[auto]
423/// # id: i64,
424/// # }
425/// # #[derive(Model)]
426/// # struct Example {
427/// # #[key]
428/// # #[auto]
429/// # id: i64,
430/// #[index]
431/// manager_id: Option<i64>,
432///
433/// #[belongs_to(key = manager_id, references = id)]
434/// manager: toasty::Deferred<Option<User>>,
435/// # }
436/// ```
437///
438/// ## `#[has_many]` — one-to-many association
439///
440/// Declares a collection of related models. The target model must have a
441/// `#[belongs_to]` field pointing back to this model.
442///
443/// ```
444/// # use toasty::Model;
445/// # #[derive(Model)]
446/// # struct Post {
447/// # #[key]
448/// # #[auto]
449/// # id: i64,
450/// # #[index]
451/// # example_id: i64,
452/// # #[belongs_to(key = example_id, references = id)]
453/// # example: toasty::Deferred<Example>,
454/// # }
455/// # #[derive(Model)]
456/// # struct Example {
457/// # #[key]
458/// # #[auto]
459/// # id: i64,
460/// #[has_many]
461/// posts: toasty::Deferred<Vec<Post>>,
462/// # }
463/// ```
464///
465/// To load the collection with every `Example` query, use `Vec<Post>`:
466///
467/// ```ignore
468/// #[has_many]
469/// posts: Vec<Post>,
470/// ```
471///
472/// Toasty generates an accessor method (e.g. `.posts()`) and an insert
473/// helper (e.g. `.insert_post()`), where the insert helper name is the
474/// auto-singularized field name.
475///
476/// ### `pair` — disambiguate self-referential or multiple relations
477///
478/// When the target model has more than one `#[belongs_to]` pointing to
479/// the same model (or points to itself), use `pair` to specify which
480/// `belongs_to` field this `has_many` corresponds to:
481///
482/// ```
483/// # use toasty::Model;
484/// # #[derive(Model)]
485/// # struct Person {
486/// # #[key]
487/// # #[auto]
488/// # id: i64,
489/// # #[index]
490/// # parent_id: Option<i64>,
491/// # #[belongs_to(key = parent_id, references = id)]
492/// # parent: toasty::Deferred<Option<Self>>,
493/// #[has_many(pair = parent)]
494/// children: toasty::Deferred<Vec<Person>>,
495/// # }
496/// ```
497///
498/// ### `via` — multi-step relations
499///
500/// Instead of pairing with a `belongs_to`, a `has_many` can reach its target
501/// through a path of existing relations with `via`. The path is a dotted
502/// chain of relation fields, read left to right starting from this model. A
503/// `via` relation owns no foreign key — it is derived from the relations it
504/// traverses — so it takes no `pair`:
505///
506/// ```
507/// # use toasty::Model;
508/// # #[derive(Model)]
509/// # struct Comment {
510/// # #[key]
511/// # #[auto]
512/// # id: i64,
513/// # #[index]
514/// # user_id: i64,
515/// # #[belongs_to(key = user_id, references = id)]
516/// # user: toasty::Deferred<User>,
517/// # #[index]
518/// # article_id: i64,
519/// # #[belongs_to(key = article_id, references = id)]
520/// # article: toasty::Deferred<Article>,
521/// # }
522/// # #[derive(Model)]
523/// # struct Article {
524/// # #[key]
525/// # #[auto]
526/// # id: i64,
527/// # #[has_many]
528/// # comments: toasty::Deferred<Vec<Comment>>,
529/// # }
530/// # #[derive(Model)]
531/// # struct User {
532/// # #[key]
533/// # #[auto]
534/// # id: i64,
535/// # #[has_many]
536/// # comments: toasty::Deferred<Vec<Comment>>,
537/// // User → comments → article
538/// #[has_many(via = comments.article)]
539/// commented_articles: toasty::Deferred<Vec<Article>>,
540/// # }
541/// ```
542///
543/// The target type is `Article` because the path `comments.article` ends
544/// there. A `via` relation is read-only and yields distinct targets — a target
545/// reached through several intermediates appears once. Query, filter, and order
546/// it like any other relation. Preloading it with `.include()` or projecting it
547/// with `.select()` is supported on SQL backends; both are not yet available on
548/// DynamoDB.
549///
550/// ## `#[has_one]` — one-to-one association
551///
552/// Declares a single related model. The target model must have a
553/// `#[belongs_to]` field pointing back to this model.
554///
555/// ```
556/// # use toasty::Model;
557/// # #[derive(Model)]
558/// # struct Profile {
559/// # #[key]
560/// # #[auto]
561/// # id: i64,
562/// # #[index]
563/// # example_id: i64,
564/// # #[belongs_to(key = example_id, references = id)]
565/// # example: toasty::Deferred<Example>,
566/// # }
567/// # #[derive(Model)]
568/// # struct Example {
569/// # #[key]
570/// # #[auto]
571/// # id: i64,
572/// #[has_one]
573/// profile: toasty::Deferred<Profile>,
574/// # }
575/// ```
576///
577/// To load the relation with every `Example` query, omit `Deferred`:
578///
579/// ```ignore
580/// #[has_one]
581/// profile: Profile,
582/// ```
583///
584/// Wrap in `Option` for an optional association:
585///
586/// ```
587/// # use toasty::Model;
588/// # #[derive(Model)]
589/// # struct Profile {
590/// # #[key]
591/// # #[auto]
592/// # id: i64,
593/// # #[index]
594/// # example_id: i64,
595/// # #[belongs_to(key = example_id, references = id)]
596/// # example: toasty::Deferred<Example>,
597/// # }
598/// # #[derive(Model)]
599/// # struct Example {
600/// # #[key]
601/// # #[auto]
602/// # id: i64,
603/// #[has_one]
604/// profile: toasty::Deferred<Option<Profile>>,
605/// # }
606/// ```
607///
608/// The eager optional form is `Option<Profile>`.
609///
610/// ### `via` — multi-step relations
611///
612/// Like `#[has_many]`, a `#[has_one]` can reach its target through a path of
613/// existing relations with `via` (see the `#[has_many]` `via` section above for
614/// the full rules). Declare it when the path is expected to reach at most one
615/// target:
616///
617/// ```
618/// # use toasty::Model;
619/// # #[derive(Model)]
620/// # struct Subscription {
621/// # #[key]
622/// # #[auto]
623/// # id: i64,
624/// # #[unique]
625/// # account_id: Option<i64>,
626/// # #[belongs_to(key = account_id, references = id)]
627/// # account: toasty::Deferred<Option<Account>>,
628/// # }
629/// # #[derive(Model)]
630/// # struct Account {
631/// # #[key]
632/// # #[auto]
633/// # id: i64,
634/// # #[unique]
635/// # user_id: Option<i64>,
636/// # #[belongs_to(key = user_id, references = id)]
637/// # user: toasty::Deferred<Option<User>>,
638/// # #[has_one]
639/// # subscription: toasty::Deferred<Option<Subscription>>,
640/// # }
641/// # #[derive(Model)]
642/// # struct User {
643/// # #[key]
644/// # #[auto]
645/// # id: i64,
646/// # #[has_one]
647/// # account: toasty::Deferred<Option<Account>>,
648/// // User → account → subscription
649/// #[has_one(via = account.subscription)]
650/// subscription: toasty::Deferred<Option<Subscription>>,
651/// # }
652/// ```
653///
654/// # Constraints
655///
656/// - The struct must have named fields (tuple structs are not supported).
657/// - Generic parameters are not supported.
658/// - Every root model must have a primary key, defined either by a
659/// struct-level `#[key(...)]` or by one or more field-level `#[key]`
660/// attributes, but not both.
661/// - `#[auto]` cannot be combined with `#[default]` or `#[update]` on the
662/// same field.
663/// - `#[column]`, `#[default]`, and `#[update]` cannot be used on relation
664/// fields (`BelongsTo`, `HasMany`, `HasOne`).
665/// - A field can have at most one relation attribute.
666/// - Eager relation fields cannot form a cycle. Use `toasty::Deferred<_>` on at
667/// least one edge of a bidirectional relation.
668/// - `Self` can be used as a type in relation fields for self-referential
669/// models.
670///
671/// # Full example
672///
673/// ```
674/// #[derive(Debug, toasty::Model)]
675/// struct User {
676/// #[key]
677/// #[auto]
678/// id: i64,
679///
680/// #[unique]
681/// email: String,
682///
683/// name: String,
684///
685/// #[default(jiff::Timestamp::now())]
686/// created_at: jiff::Timestamp,
687///
688/// #[update(jiff::Timestamp::now())]
689/// updated_at: jiff::Timestamp,
690///
691/// #[has_many]
692/// posts: toasty::Deferred<Vec<Post>>,
693/// }
694///
695/// #[derive(Debug, toasty::Model)]
696/// struct Post {
697/// #[key]
698/// #[auto]
699/// id: i64,
700///
701/// title: String,
702///
703/// tags: toasty::Json<Vec<String>>,
704///
705/// #[index]
706/// user_id: i64,
707///
708/// #[belongs_to(key = user_id, references = id)]
709/// user: toasty::Deferred<User>,
710/// }
711/// ```
712#[proc_macro_derive(
713 Model,
714 attributes(
715 key, auto, default, update, column, index, unique, table, has_many, has_one, belongs_to,
716 version, shared, document
717 )
718)]
719pub fn derive_model(input: TokenStream) -> TokenStream {
720 match model::generate_model(input.into()) {
721 Ok(output) => output.into(),
722 Err(e) => e.to_compile_error().into(),
723 }
724}
725
726/// Derive macro that turns a struct or enum into an embedded type stored
727/// inline in a parent model's table.
728///
729/// Embedded types do not have their own tables or primary keys. Their
730/// fields are flattened into the parent model's columns. Use `Embed` for
731/// value objects (addresses, coordinates, metadata) and enums
732/// (status codes, contact info variants).
733///
734/// # Structs
735///
736/// An embedded struct's fields become columns in the parent table, prefixed
737/// with the field name. For example, an `address: Address` field with
738/// `street` and `city` produces columns `address_street` and
739/// `address_city`.
740///
741/// ```
742/// #[derive(toasty::Embed)]
743/// struct Address {
744/// street: String,
745/// city: String,
746/// }
747///
748/// #[derive(toasty::Model)]
749/// struct User {
750/// #[key]
751/// #[auto]
752/// id: i64,
753/// name: String,
754/// address: Address,
755/// }
756/// ```
757///
758/// Applying `#[derive(Embed)]` to a struct generates:
759///
760/// - An [`Embed`] trait implementation (`id` and `schema` methods).
761/// - A `Fields` struct returned by `<Type>::fields()` for building
762/// filter expressions on individual fields.
763/// - An `Update` struct used by the parent model's update builder for
764/// partial field updates.
765///
766/// ## Nesting
767///
768/// Embedded structs can contain other embedded types. Columns are
769/// flattened with chained prefixes:
770///
771/// ```
772/// #[derive(toasty::Embed)]
773/// struct Location {
774/// lat: i64,
775/// lon: i64,
776/// }
777///
778/// #[derive(toasty::Embed)]
779/// struct Address {
780/// street: String,
781/// city: Location,
782/// }
783/// ```
784///
785/// When `Address` is embedded as `address` in a parent model, this
786/// produces columns `address_street`, `address_city_lat`, and
787/// `address_city_lon`.
788///
789/// # Enums
790///
791/// An embedded enum stores a discriminant value identifying the active
792/// variant. By default, Toasty derives a string label for each variant by
793/// converting its Rust name to `snake_case`. Use
794/// `#[column(rename_all = "...")]` on the enum to select another naming
795/// convention, or `#[column(variant = "...")]` on a variant to set one label.
796///
797/// **Unit-only enum:**
798///
799/// ```
800/// #[derive(toasty::Embed)]
801/// enum Status {
802/// Pending,
803/// InProgress,
804/// Archived,
805/// }
806/// ```
807///
808/// A unit-only enum occupies a single column in the parent table. The
809/// example stores the labels `pending`, `in_progress`, and `archived`.
810///
811/// **Data-carrying enum:**
812///
813/// ```
814/// #[derive(toasty::Embed)]
815/// enum ContactInfo {
816/// Email { address: String },
817/// Phone { number: String },
818/// }
819/// ```
820///
821/// A data-carrying enum stores the discriminant column plus one nullable
822/// column per variant field. For example, a `contact: ContactInfo` field
823/// produces columns `contact` (discriminant), `contact_address`, and
824/// `contact_number`. Only the columns belonging to the active variant
825/// contain values; the rest are `NULL`.
826///
827/// **Mixed enum** (unit and data variants together):
828///
829/// ```
830/// #[derive(toasty::Embed)]
831/// enum Status {
832/// Pending,
833/// Failed { reason: String },
834/// Done,
835/// }
836/// ```
837///
838/// Applying `#[derive(Embed)]` to an enum generates:
839///
840/// - An [`Embed`] trait implementation (`id` and `schema` methods).
841/// - A `Fields` struct with `is_<variant>()` methods and comparison
842/// methods (`eq`, `ne`, `in_list`).
843/// - For data-carrying variants, per-variant handle types with a
844/// `matches(closure)` method for pattern matching and field access.
845///
846/// # Newtype `Auto` proxying
847///
848/// A tuple-newtype embedded struct (one unnamed field) automatically
849/// implements `Auto` whenever its inner type does — no annotation
850/// required. Toasty emits a `NewtypeOf` marker carrying the inner type
851/// and a blanket `Auto` impl resolves through it:
852///
853/// ```
854/// #[derive(toasty::Embed)]
855/// struct UserId(uuid::Uuid);
856///
857/// #[derive(toasty::Model)]
858/// struct User {
859/// #[key]
860/// #[auto]
861/// id: UserId,
862/// name: String,
863/// }
864/// ```
865///
866/// Newtypes wrapping non-`Auto` types stay non-`Auto`; nesting works
867/// transparently (`Outer(Inner(u64))` proxies through both layers).
868///
869/// # Attributes
870///
871/// ## `#[column(...)]` — customize the database column
872///
873/// **On struct fields**, overrides the column name and/or type:
874///
875/// ```
876/// #[derive(toasty::Embed)]
877/// struct Address {
878/// #[column("addr_street")]
879/// street: String,
880///
881/// #[column(type = varchar(255))]
882/// city: String,
883/// }
884/// ```
885///
886/// See [`Model`][`derive@Model`] for the full list of supported column
887/// types.
888///
889/// **Changing stored enum discriminants.** On an enum,
890/// `#[column(rename_all = "...")]` changes how Toasty derives string labels
891/// for variants without an explicit label:
892///
893/// ```
894/// #[derive(toasty::Embed)]
895/// #[column(rename_all = "SCREAMING_SNAKE_CASE")]
896/// enum PartyKind {
897/// Customer,
898/// PreferredSupplier,
899/// }
900/// ```
901///
902/// This example uses the labels `CUSTOMER` and `PREFERRED_SUPPLIER`. Without
903/// `rename_all`, Toasty uses `snake_case`.
904///
905/// The supported rules and their result for `PreferredSupplier` are:
906///
907/// | Rule | Label |
908/// | --- | --- |
909/// | `lowercase` | `preferredsupplier` |
910/// | `UPPERCASE` | `PREFERREDSUPPLIER` |
911/// | `PascalCase` | `PreferredSupplier` |
912/// | `camelCase` | `preferredSupplier` |
913/// | `snake_case` | `preferred_supplier` |
914/// | `SCREAMING_SNAKE_CASE` | `PREFERRED_SUPPLIER` |
915/// | `kebab-case` | `preferred-supplier` |
916/// | `SCREAMING-KEBAB-CASE` | `PREFERRED-SUPPLIER` |
917///
918/// Use `#[column(variant = "...")]` to set individual labels:
919///
920/// ```
921/// #[derive(toasty::Embed)]
922/// enum PartyKind {
923/// #[column(variant = "customer")]
924/// Customer,
925/// #[column(variant = "preferred-supplier")]
926/// PreferredSupplier,
927/// }
928/// ```
929///
930/// An explicit variant label takes precedence over `rename_all` when an enum
931/// uses both attributes.
932///
933/// String-label enums use Toasty's enum storage by default. Use
934/// `#[column(type = enum("type_name"))]` to set the database enum type name,
935/// or `#[column(type = text)]` or `#[column(type = varchar(N))]` to use a
936/// plain string column. `rename_all` changes variant labels only; it does not
937/// change the enum type name.
938///
939/// To store integers instead, assign an integer to every variant:
940///
941/// ```
942/// #[derive(toasty::Embed)]
943/// enum Priority {
944/// #[column(variant = 10)]
945/// Low,
946/// #[column(variant = 20)]
947/// High,
948/// }
949/// ```
950///
951/// An enum cannot mix string and integer discriminants. Integer discriminants
952/// are stored as `i64` and do not support `rename_all`. All discriminant values
953/// must be unique. String labels may contain at most 63 bytes.
954///
955/// ## `#[index]` — add a database index
956///
957/// Creates a non-unique index on the field's flattened column.
958///
959/// ```
960/// #[derive(toasty::Embed)]
961/// struct Contact {
962/// #[index]
963/// country: String,
964/// }
965/// ```
966///
967/// ## `#[unique]` — add a unique constraint
968///
969/// Creates a unique index on the field's flattened column. The database
970/// enforces uniqueness.
971///
972/// ```
973/// #[derive(toasty::Embed)]
974/// struct Contact {
975/// #[unique]
976/// email: String,
977/// }
978/// ```
979///
980/// ## `#[shared(ident)]` — share a column across enum variants
981///
982/// Declares a shared logical field on the enum. Variant fields declaring
983/// the same identifier are backed by a single nullable column instead of
984/// one column per variant. The identifier — not the Rust field names,
985/// which may differ per variant — names the field: the column name derives
986/// from it (`{enum_field}_{ident}`), and enum-level `#[index]` /
987/// `#[unique]` attributes reference it.
988///
989/// ```
990/// #[derive(toasty::Embed)]
991/// enum Creature {
992/// #[column(variant = 1)]
993/// Human {
994/// #[shared(name)]
995/// full_name: String,
996/// profession: String,
997/// },
998/// #[column(variant = 2)]
999/// Animal {
1000/// #[shared(name)]
1001/// nickname: String,
1002/// species: String,
1003/// },
1004/// }
1005/// // Columns: creature, creature_name (shared), creature_profession,
1006/// // creature_species
1007/// ```
1008///
1009/// Fields sharing an identifier must have the same type. To rename the
1010/// shared column, add `#[column("...")]` to any one member of the group
1011/// (if several declare it, they must agree):
1012///
1013/// ```
1014/// # #[derive(toasty::Embed)]
1015/// # enum Example {
1016/// # #[column(variant = 1)]
1017/// # V {
1018/// #[shared(name)]
1019/// #[column("legacy_name")]
1020/// name: String,
1021/// # },
1022/// # }
1023/// ```
1024///
1025/// ## Enum-level `#[index(...)]` / `#[unique(...)]`
1026///
1027/// On the enum itself, `#[index(...)]` and `#[unique(...)]` create an
1028/// index over variant-field columns. Each reference is a shared field
1029/// identifier or a `variant::field` path naming a variant field that owns
1030/// its column; the two forms compose into composite indices.
1031///
1032/// ```
1033/// #[derive(toasty::Embed)]
1034/// #[unique(name)]
1035/// #[index(name, human::profession)]
1036/// enum Creature {
1037/// #[column(variant = 1)]
1038/// Human {
1039/// #[shared(name)]
1040/// name: String,
1041/// profession: String,
1042/// },
1043/// #[column(variant = 2)]
1044/// Animal {
1045/// #[shared(name)]
1046/// name: String,
1047/// },
1048/// }
1049/// ```
1050///
1051/// An index on a shared column covers rows of **every** variant: with
1052/// `#[unique(name)]` above, a `Human` named "Bob" and an `Animal` named
1053/// "Bob" conflict. Rows of variants that do not declare the shared field
1054/// store `NULL` and never conflict. For this reason, field-level
1055/// `#[index]` / `#[unique]` on a `#[shared]` field is a compile error
1056/// pointing at the enum-level form.
1057///
1058/// # Using embedded types in a model
1059///
1060/// Reference an embedded type as a field on a [`Model`][`derive@Model`]
1061/// struct. The parent model's create and update builders gain a setter for
1062/// the embedded field. Partial updates of individual sub-fields use
1063/// `stmt::patch`:
1064///
1065/// ```no_run
1066/// # #[derive(toasty::Embed)]
1067/// # struct Address { street: String, city: String }
1068/// # #[derive(toasty::Model)]
1069/// # struct User {
1070/// # #[key]
1071/// # #[auto]
1072/// # id: i64,
1073/// # name: String,
1074/// # address: Address,
1075/// # }
1076/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
1077/// use toasty::stmt;
1078///
1079/// // Full replacement
1080/// user.update()
1081/// .address(Address { street: "456 Oak Ave".into(), city: "Seattle".into() })
1082/// .exec(&mut db).await?;
1083///
1084/// // Partial update — updates city, leaves street unchanged
1085/// user.update()
1086/// .address(stmt::patch(Address::fields().city(), "Portland"))
1087/// .exec(&mut db).await?;
1088/// # Ok(())
1089/// # }
1090/// ```
1091///
1092/// Embedded struct fields are queryable through the parent model's
1093/// `fields()` accessor:
1094///
1095/// ```no_run
1096/// # #[derive(toasty::Embed)]
1097/// # struct Address { street: String, city: String }
1098/// # #[derive(toasty::Model)]
1099/// # struct User {
1100/// # #[key]
1101/// # #[auto]
1102/// # id: i64,
1103/// # name: String,
1104/// # address: Address,
1105/// # }
1106/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1107/// let users = User::filter(User::fields().address().city().eq("Seattle"))
1108/// .exec(&mut db).await?;
1109/// # Ok(())
1110/// # }
1111/// ```
1112///
1113/// # Constraints
1114///
1115/// - Embedded structs must have named fields (tuple structs are not
1116/// supported).
1117/// - Generic parameters are not supported.
1118/// - Enum discriminants must all be strings or all be integers. Integer
1119/// discriminants must be specified on every variant.
1120/// - `#[column(rename_all = "...")]` applies only to string labels.
1121/// - Enum variants may be unit variants or have named fields. Tuple
1122/// variants are not supported.
1123/// - Embedded types cannot have primary keys, relations, `#[auto]`,
1124/// `#[default]`, or `#[update]` attributes.
1125///
1126/// # Full example
1127///
1128/// ```no_run
1129/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1130/// #[derive(Debug, PartialEq, toasty::Embed)]
1131/// #[column(rename_all = "SCREAMING_SNAKE_CASE")]
1132/// enum Priority {
1133/// Low,
1134/// Normal,
1135/// High,
1136/// }
1137///
1138/// #[derive(Debug, toasty::Embed)]
1139/// struct Metadata {
1140/// version: i64,
1141/// status: String,
1142/// priority: Priority,
1143/// }
1144///
1145/// #[derive(Debug, toasty::Model)]
1146/// struct Document {
1147/// #[key]
1148/// #[auto]
1149/// id: i64,
1150///
1151/// title: String,
1152///
1153/// #[unique]
1154/// slug: String,
1155///
1156/// meta: Metadata,
1157/// }
1158///
1159/// // Create
1160/// let mut doc = Document::create()
1161/// .title("Design doc")
1162/// .slug("design-doc")
1163/// .meta(Metadata {
1164/// version: 1,
1165/// status: "draft".to_string(),
1166/// priority: Priority::Normal,
1167/// })
1168/// .exec(&mut db).await?;
1169///
1170/// // Query by embedded field
1171/// let drafts = Document::filter(
1172/// Document::fields().meta().status().eq("draft")
1173/// ).exec(&mut db).await?;
1174///
1175/// // Partial update
1176/// use toasty::stmt;
1177/// doc.update()
1178/// .meta(stmt::apply([
1179/// stmt::patch(Metadata::fields().version(), 2),
1180/// stmt::patch(Metadata::fields().status(), "published"),
1181/// ]))
1182/// .exec(&mut db).await?;
1183/// # Ok(())
1184/// # }
1185/// ```
1186///
1187/// [`Embed`]: toasty::Embed
1188#[proc_macro_derive(Embed, attributes(column, document, index, unique, shared))]
1189pub fn derive_embed(input: TokenStream) -> TokenStream {
1190 match model::generate_embed(input.into()) {
1191 Ok(output) => output.into(),
1192 Err(e) => e.to_compile_error().into(),
1193 }
1194}
1195
1196/// Builds a query using the Toasty query language. The macro expands into
1197/// the equivalent method-chain calls on the query builder API. It does
1198/// not execute the query — chain `.exec(&mut db).await?` on the result to run
1199/// it.
1200///
1201/// # Syntax
1202///
1203/// ```text
1204/// query!(Source [FILTER expr] [ORDER BY .field ASC|DESC] [OFFSET n] [LIMIT n])
1205/// ```
1206///
1207/// `Source` is a model type path (e.g., `User`). All clauses are optional and
1208/// can appear in any combination, but must follow the order shown above when
1209/// present. All keywords are case-insensitive: `FILTER`, `filter`, and `Filter`
1210/// all work.
1211///
1212/// # Basic queries
1213///
1214/// With no clauses, `query!` returns all records of the given model.
1215///
1216/// ```
1217/// # #[derive(toasty::Model)]
1218/// # struct User {
1219/// # #[key]
1220/// # id: i64,
1221/// # name: String,
1222/// # age: i64,
1223/// # active: bool,
1224/// # }
1225/// // Returns all users — expands to User::all()
1226/// let _ = toasty::query!(User);
1227/// ```
1228///
1229/// # Filter expressions
1230///
1231/// The `FILTER` clause accepts an expression built from field comparisons,
1232/// boolean operators, and external references.
1233///
1234/// ## Comparison operators
1235///
1236/// Dot-prefixed field paths (`.name`, `.age`) refer to fields on the source
1237/// model. The right-hand side is a literal or external reference.
1238///
1239/// | Operator | Expansion |
1240/// |----------|-------------------|
1241/// | `==` | `.eq(val)` |
1242/// | `!=` | `.ne(val)` |
1243/// | `>` | `.gt(val)` |
1244/// | `>=` | `.ge(val)` |
1245/// | `<` | `.lt(val)` |
1246/// | `<=` | `.le(val)` |
1247///
1248/// ```
1249/// # #[derive(toasty::Model)]
1250/// # struct User {
1251/// # #[key]
1252/// # id: i64,
1253/// # name: String,
1254/// # age: i64,
1255/// # active: bool,
1256/// # }
1257/// // Equality — expands to User::filter(User::fields().name().eq("Alice"))
1258/// let _ = toasty::query!(User FILTER .name == "Alice");
1259///
1260/// // Not equal
1261/// let _ = toasty::query!(User FILTER .name != "Bob");
1262///
1263/// // Greater than
1264/// let _ = toasty::query!(User FILTER .age > 18);
1265///
1266/// // Greater than or equal
1267/// let _ = toasty::query!(User FILTER .age >= 21);
1268///
1269/// // Less than
1270/// let _ = toasty::query!(User FILTER .age < 65);
1271///
1272/// // Less than or equal
1273/// let _ = toasty::query!(User FILTER .age <= 99);
1274/// ```
1275///
1276/// ## Boolean operators
1277///
1278/// `AND`, `OR`, and `NOT` combine filter expressions. Precedence follows
1279/// standard boolean logic: `NOT` binds tightest, then `AND`, then `OR`.
1280///
1281/// ```
1282/// # #[derive(toasty::Model)]
1283/// # struct User {
1284/// # #[key]
1285/// # id: i64,
1286/// # name: String,
1287/// # age: i64,
1288/// # active: bool,
1289/// # }
1290/// // AND — both conditions must match
1291/// let _ = toasty::query!(User FILTER .name == "Alice" AND .age > 18);
1292///
1293/// // OR — either condition matches
1294/// let _ = toasty::query!(User FILTER .name == "Alice" OR .name == "Bob");
1295///
1296/// // NOT — negates the following expression
1297/// let _ = toasty::query!(User FILTER NOT .active == true);
1298///
1299/// // Combining all three
1300/// let _ = toasty::query!(User FILTER NOT .active == true AND (.name == "Alice" OR .age >= 21));
1301/// ```
1302///
1303/// ## Operator precedence
1304///
1305/// Without parentheses, `NOT` binds tightest, then `AND`, then `OR`. Use
1306/// parentheses to override.
1307///
1308/// ```
1309/// # #[derive(toasty::Model)]
1310/// # struct User {
1311/// # #[key]
1312/// # id: i64,
1313/// # name: String,
1314/// # age: i64,
1315/// # active: bool,
1316/// # }
1317/// // Without parens: parsed as (.name == "A" AND .age > 0) OR .active == false
1318/// let _ = toasty::query!(User FILTER .name == "A" AND .age > 0 OR .active == false);
1319///
1320/// // With parens: forces OR to bind first
1321/// let _ = toasty::query!(User FILTER .name == "A" AND (.age > 0 OR .active == false));
1322/// ```
1323///
1324/// ## Boolean and integer literals
1325///
1326/// Boolean fields can be compared against `true` and `false` literals.
1327/// Integer literals work as expected.
1328///
1329/// ```
1330/// # #[derive(toasty::Model)]
1331/// # struct User {
1332/// # #[key]
1333/// # id: i64,
1334/// # name: String,
1335/// # age: i64,
1336/// # active: bool,
1337/// # }
1338/// let _ = toasty::query!(User FILTER .active == true);
1339/// let _ = toasty::query!(User FILTER .active == false);
1340/// let _ = toasty::query!(User FILTER .age == 42);
1341/// ```
1342///
1343/// # Referencing surrounding code
1344///
1345/// `#ident` pulls a variable from the surrounding scope. `#(expr)` embeds an
1346/// arbitrary Rust expression.
1347///
1348/// ```
1349/// # #[derive(toasty::Model)]
1350/// # struct User {
1351/// # #[key]
1352/// # id: i64,
1353/// # name: String,
1354/// # age: i64,
1355/// # active: bool,
1356/// # }
1357/// // Variable reference — expands to User::filter(User::fields().name().eq(name))
1358/// let name = "Carl";
1359/// let _ = toasty::query!(User FILTER .name == #name);
1360///
1361/// // Expression reference
1362/// fn min_age() -> i64 { 18 }
1363/// let _ = toasty::query!(User FILTER .age > #(min_age()));
1364/// ```
1365///
1366/// # Dot-prefixed field paths
1367///
1368/// A leading `.` starts a field path rooted at the source model's `fields()`
1369/// method. Chained dots navigate multi-segment paths.
1370///
1371/// ```
1372/// # #[derive(toasty::Model)]
1373/// # struct User {
1374/// # #[key]
1375/// # id: i64,
1376/// # name: String,
1377/// # age: i64,
1378/// # active: bool,
1379/// # }
1380/// // .name expands to User::fields().name()
1381/// let _ = toasty::query!(User FILTER .name == "Alice");
1382///
1383/// // Multiple fields in a single expression
1384/// let _ = toasty::query!(User FILTER .id == 1 AND .name == "X" AND .age > 0);
1385/// ```
1386///
1387/// # ORDER BY
1388///
1389/// Sort results by a field in ascending (`ASC`) or descending (`DESC`) order.
1390/// If no direction is specified, ascending is the default.
1391///
1392/// ```
1393/// # #[derive(toasty::Model)]
1394/// # struct User {
1395/// # #[key]
1396/// # id: i64,
1397/// # name: String,
1398/// # age: i64,
1399/// # active: bool,
1400/// # }
1401/// // Ascending order (explicit)
1402/// let _ = toasty::query!(User ORDER BY .name ASC);
1403///
1404/// // Descending order
1405/// let _ = toasty::query!(User ORDER BY .age DESC);
1406///
1407/// // Combined with filter
1408/// let _ = toasty::query!(User FILTER .active == true ORDER BY .name ASC);
1409/// ```
1410///
1411/// # LIMIT and OFFSET
1412///
1413/// `LIMIT` restricts the number of returned records. `OFFSET` skips a number
1414/// of records before returning. Both accept integer literals, `#ident`
1415/// variables, and `#(expr)` expressions.
1416///
1417/// ```
1418/// # #[derive(toasty::Model)]
1419/// # struct User {
1420/// # #[key]
1421/// # id: i64,
1422/// # name: String,
1423/// # age: i64,
1424/// # active: bool,
1425/// # }
1426/// // Return at most 10 records
1427/// let _ = toasty::query!(User LIMIT 10);
1428///
1429/// // Skip 20, then return 10
1430/// let _ = toasty::query!(User OFFSET 20 LIMIT 10);
1431///
1432/// // Variable pagination
1433/// let page_size = 25usize;
1434/// let _ = toasty::query!(User LIMIT #page_size);
1435///
1436/// // Expression pagination
1437/// let _ = toasty::query!(User LIMIT #(5 + 5));
1438/// ```
1439///
1440/// # Combining clauses
1441///
1442/// All clauses can be combined. When present, they must appear in this order:
1443/// `FILTER`, `ORDER BY`, `OFFSET`, `LIMIT`.
1444///
1445/// ```
1446/// # #[derive(toasty::Model)]
1447/// # struct User {
1448/// # #[key]
1449/// # id: i64,
1450/// # name: String,
1451/// # age: i64,
1452/// # active: bool,
1453/// # }
1454/// let _ = toasty::query!(User FILTER .active == true ORDER BY .name ASC LIMIT 10);
1455/// let _ = toasty::query!(User FILTER .age > 18 ORDER BY .age DESC OFFSET 0 LIMIT 50);
1456/// ```
1457///
1458/// # Case-insensitive keywords
1459///
1460/// All keywords — `FILTER`, `AND`, `OR`, `NOT`, `ORDER`, `BY`, `ASC`, `DESC`,
1461/// `OFFSET`, `LIMIT` — are matched case-insensitively. Any casing works.
1462///
1463/// ```
1464/// # #[derive(toasty::Model)]
1465/// # struct User {
1466/// # #[key]
1467/// # id: i64,
1468/// # name: String,
1469/// # age: i64,
1470/// # active: bool,
1471/// # }
1472/// // These are all equivalent
1473/// let _ = toasty::query!(User FILTER .name == "A");
1474/// let _ = toasty::query!(User filter .name == "A");
1475/// let _ = toasty::query!(User Filter .name == "A");
1476/// ```
1477///
1478/// # Expansion details
1479///
1480/// The macro translates each syntactic element into method-chain calls on the
1481/// query builder.
1482///
1483/// ## No filter
1484///
1485/// ```text
1486/// query!(User) → User::all()
1487/// ```
1488///
1489/// ## Filter
1490///
1491/// ```text
1492/// query!(User FILTER .name == "A")
1493/// → User::filter(User::fields().name().eq("A"))
1494/// ```
1495///
1496/// ## Logical operators
1497///
1498/// ```text
1499/// query!(User FILTER .a == 1 AND .b == 2)
1500/// → User::filter(User::fields().a().eq(1).and(User::fields().b().eq(2)))
1501///
1502/// query!(User FILTER .a == 1 OR .b == 2)
1503/// → User::filter(User::fields().a().eq(1).or(User::fields().b().eq(2)))
1504///
1505/// query!(User FILTER NOT .a == 1)
1506/// → User::filter((User::fields().a().eq(1)).not())
1507/// ```
1508///
1509/// ## ORDER BY
1510///
1511/// ```text
1512/// query!(User ORDER BY .name ASC)
1513/// → { let mut q = User::all(); q = q.order_by(User::fields().name().asc()); q }
1514/// ```
1515///
1516/// ## LIMIT / OFFSET
1517///
1518/// ```text
1519/// query!(User LIMIT 10)
1520/// → { let mut q = User::all(); q = q.limit(10); q }
1521///
1522/// query!(User OFFSET 5 LIMIT 10)
1523/// → { let mut q = User::all(); q = q.limit(10); q = q.offset(5); q }
1524/// ```
1525///
1526/// Note: in the expansion, `limit` is called before `offset` because the
1527/// API requires it.
1528///
1529/// ## External references
1530///
1531/// ```text
1532/// let x = "Carl";
1533/// query!(User FILTER .name == #x)
1534/// → User::filter(User::fields().name().eq(x))
1535///
1536/// query!(User FILTER .age > #(compute()))
1537/// → User::filter(User::fields().age().gt(compute()))
1538/// ```
1539///
1540/// # Errors
1541///
1542/// The macro produces compile-time errors for:
1543///
1544/// - **Missing model path**: the first token must be a valid type path.
1545/// - **Unknown fields**: dot-prefixed paths that don't match a field on the
1546/// model produce a type error from the generated `fields()` method.
1547/// - **Type mismatches**: comparing a field to a value of the wrong type
1548/// produces a standard Rust type error (e.g., `.age == "not a number"`).
1549/// - **Unexpected tokens**: tokens after the last recognized clause cause
1550/// `"unexpected tokens after query"`.
1551/// - **Invalid clause order**: placing `FILTER` after `ORDER BY` or `LIMIT`
1552/// before `OFFSET` causes a parse error since the clauses are parsed in
1553/// fixed order.
1554/// - **Missing `BY` after `ORDER`**: writing `ORDER .name` instead of
1555/// `ORDER BY .name` produces `"expected 'BY' after 'ORDER'"`.
1556/// - **Invalid pagination value**: `LIMIT` and `OFFSET` require an integer
1557/// literal, `#variable`, or `#(expression)`.
1558#[proc_macro]
1559pub fn query(input: TokenStream) -> TokenStream {
1560 match query::generate(input.into()) {
1561 Ok(output) => output.into(),
1562 Err(e) => e.to_compile_error().into(),
1563 }
1564}
1565
1566/// Expands struct-literal syntax into create builder method chains. Returns one
1567/// or more create builders — call `.exec(&mut db).await?` to insert the
1568/// record(s).
1569///
1570/// # Syntax forms
1571///
1572/// ## Field syntax
1573///
1574/// Fields inside `{ ... }` can use either explicit or shorthand syntax:
1575///
1576/// - **Explicit:** `field: expr` — sets the field to the given expression.
1577/// - **Shorthand:** `field` — equivalent to `field: field`, using a variable
1578/// with the same name as the field.
1579///
1580/// These can be mixed freely, just like Rust struct literals:
1581///
1582/// ```ignore
1583/// let name = "Alice".to_string();
1584/// toasty::create!(User { name, email: "alice@example.com" })
1585/// ```
1586///
1587/// ## Single creation
1588///
1589/// ```ignore
1590/// toasty::create!(Type { field: value, ... })
1591/// ```
1592///
1593/// Expands to `Type::create().field(value)...` and returns the model's create
1594/// builder (e.g., `UserCreate`).
1595///
1596/// ```no_run
1597/// # #[derive(toasty::Model)]
1598/// # struct User {
1599/// # #[key]
1600/// # #[auto]
1601/// # id: i64,
1602/// # name: String,
1603/// # email: String,
1604/// # }
1605/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1606/// let user = toasty::create!(User {
1607/// name: "Alice",
1608/// email: "alice@example.com"
1609/// })
1610/// .exec(&mut db)
1611/// .await?;
1612/// # Ok(())
1613/// # }
1614/// ```
1615///
1616/// ## Scoped creation
1617///
1618/// ```ignore
1619/// toasty::create!(in expr { field: value, ... })
1620/// ```
1621///
1622/// Expands to `expr.create().field(value)...`. Creates a record through a
1623/// relation accessor. The foreign key is set automatically.
1624///
1625/// ```no_run
1626/// # #[derive(toasty::Model)]
1627/// # struct User {
1628/// # #[key]
1629/// # #[auto]
1630/// # id: i64,
1631/// # name: String,
1632/// # #[has_many]
1633/// # todos: toasty::Deferred<Vec<Todo>>,
1634/// # }
1635/// # #[derive(toasty::Model)]
1636/// # struct Todo {
1637/// # #[key]
1638/// # #[auto]
1639/// # id: i64,
1640/// # title: String,
1641/// # #[index]
1642/// # user_id: i64,
1643/// # #[belongs_to(key = user_id, references = id)]
1644/// # user: toasty::Deferred<User>,
1645/// # }
1646/// # async fn example(mut db: toasty::Db, user: User) -> toasty::Result<()> {
1647/// let todo = toasty::create!(in user.todos() { title: "buy milk" })
1648/// .exec(&mut db)
1649/// .await?;
1650///
1651/// // todo.user_id == user.id
1652/// # Ok(())
1653/// # }
1654/// ```
1655///
1656/// ## Typed batch
1657///
1658/// ```ignore
1659/// toasty::create!(Type::[ { fields }, { fields }, ... ])
1660/// ```
1661///
1662/// Expands to `toasty::batch([builder1, builder2, ...])` and returns
1663/// `Vec<Type>` when executed:
1664///
1665/// ```no_run
1666/// # #[derive(toasty::Model)]
1667/// # struct User {
1668/// # #[key]
1669/// # #[auto]
1670/// # id: i64,
1671/// # name: String,
1672/// # }
1673/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1674/// let users = toasty::create!(User::[
1675/// { name: "Alice" },
1676/// { name: "Bob" },
1677/// ])
1678/// .exec(&mut db)
1679/// .await?;
1680/// // users: Vec<User>
1681/// # Ok(())
1682/// # }
1683/// ```
1684///
1685/// ## Tuple
1686///
1687/// ```ignore
1688/// toasty::create!((
1689/// Type1 { fields },
1690/// Type2 { fields },
1691/// ...
1692/// ))
1693/// ```
1694///
1695/// Expands to `toasty::batch((builder1, builder2, ...))` and returns a
1696/// tuple matching the input types:
1697///
1698/// ```no_run
1699/// # #[derive(toasty::Model)]
1700/// # struct User {
1701/// # #[key]
1702/// # #[auto]
1703/// # id: i64,
1704/// # name: String,
1705/// # }
1706/// # #[derive(toasty::Model)]
1707/// # struct Post {
1708/// # #[key]
1709/// # #[auto]
1710/// # id: i64,
1711/// # title: String,
1712/// # }
1713/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1714/// let (user, post) = toasty::create!((
1715/// User { name: "Alice" },
1716/// Post { title: "Hello" },
1717/// ))
1718/// .exec(&mut db)
1719/// .await?;
1720/// // (User, Post)
1721/// # Ok(())
1722/// # }
1723/// ```
1724///
1725/// ## Mixed tuple
1726///
1727/// Typed batches and single creates can be mixed inside a tuple:
1728///
1729/// ```no_run
1730/// # #[derive(toasty::Model)]
1731/// # struct User {
1732/// # #[key]
1733/// # #[auto]
1734/// # id: i64,
1735/// # name: String,
1736/// # }
1737/// # #[derive(toasty::Model)]
1738/// # struct Post {
1739/// # #[key]
1740/// # #[auto]
1741/// # id: i64,
1742/// # title: String,
1743/// # }
1744/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1745/// let (users, post) = toasty::create!((
1746/// User::[ { name: "Alice" }, { name: "Bob" } ],
1747/// Post { title: "Hello" },
1748/// ))
1749/// .exec(&mut db)
1750/// .await?;
1751/// // (Vec<User>, Post)
1752/// # Ok(())
1753/// # }
1754/// ```
1755///
1756/// # Field values
1757///
1758/// ## Expressions
1759///
1760/// Any Rust expression is valid as a field value — literals, variables, and
1761/// function calls all work. When a variable has the same name as the field,
1762/// you can use the shorthand syntax (just `name` instead of `name: name`):
1763///
1764/// ```
1765/// # #[derive(toasty::Model)]
1766/// # struct User {
1767/// # #[key]
1768/// # #[auto]
1769/// # id: i64,
1770/// # name: String,
1771/// # email: String,
1772/// # }
1773/// let name = "Alice";
1774/// let _ = toasty::create!(User { name, email: format!("{}@example.com", name) });
1775/// ```
1776///
1777/// When the variable name differs from the field name, use the explicit
1778/// `field: expr` form:
1779///
1780/// ```
1781/// # #[derive(toasty::Model)]
1782/// # struct User {
1783/// # #[key]
1784/// # #[auto]
1785/// # id: i64,
1786/// # name: String,
1787/// # }
1788/// let user_name = "Alice";
1789/// let _ = toasty::create!(User { name: user_name });
1790/// ```
1791///
1792/// ## Nested struct (BelongsTo / HasOne)
1793///
1794/// Use `{ ... }` **without** a type prefix to create a related record inline.
1795/// The macro expands the nested fields into a create builder and passes it
1796/// to the field's setter method.
1797///
1798/// ```
1799/// # #[derive(toasty::Model)]
1800/// # struct User {
1801/// # #[key]
1802/// # #[auto]
1803/// # id: i64,
1804/// # name: String,
1805/// # }
1806/// # #[derive(toasty::Model)]
1807/// # struct Todo {
1808/// # #[key]
1809/// # #[auto]
1810/// # id: i64,
1811/// # title: String,
1812/// # #[index]
1813/// # user_id: i64,
1814/// # #[belongs_to(key = user_id, references = id)]
1815/// # user: toasty::Deferred<User>,
1816/// # }
1817/// let _ = toasty::create!(Todo {
1818/// title: "buy milk",
1819/// user: { name: "Alice" }
1820/// });
1821/// // Expands to:
1822/// // Todo::create()
1823/// // .title("buy milk")
1824/// // .user(Todo::fields().user().create().name("Alice"))
1825/// ```
1826///
1827/// The related record is created first and the foreign key is set
1828/// automatically.
1829///
1830/// ## Nested list (HasMany)
1831///
1832/// Use `[{ ... }, { ... }]` to create multiple related records. The macro
1833/// expands each entry into a create builder and passes them as an array to
1834/// the plural field setter.
1835///
1836/// ```
1837/// # #[derive(toasty::Model)]
1838/// # struct User {
1839/// # #[key]
1840/// # #[auto]
1841/// # id: i64,
1842/// # name: String,
1843/// # #[has_many]
1844/// # todos: toasty::Deferred<Vec<Todo>>,
1845/// # }
1846/// # #[derive(toasty::Model)]
1847/// # struct Todo {
1848/// # #[key]
1849/// # #[auto]
1850/// # id: i64,
1851/// # title: String,
1852/// # #[index]
1853/// # user_id: i64,
1854/// # #[belongs_to(key = user_id, references = id)]
1855/// # user: toasty::Deferred<User>,
1856/// # }
1857/// let _ = toasty::create!(User {
1858/// name: "Alice",
1859/// todos: [{ title: "first" }, { title: "second" }]
1860/// });
1861/// // Expands to:
1862/// // User::create()
1863/// // .name("Alice")
1864/// // .todos([
1865/// // User::fields().todos().create().title("first"),
1866/// // User::fields().todos().create().title("second"),
1867/// // ])
1868/// ```
1869///
1870/// Items in a nested list can also be plain expressions (e.g., an existing
1871/// builder value).
1872///
1873/// ## Deep nesting
1874///
1875/// Nesting composes to arbitrary depth:
1876///
1877/// ```
1878/// # #[derive(toasty::Model)]
1879/// # struct User {
1880/// # #[key]
1881/// # #[auto]
1882/// # id: i64,
1883/// # name: String,
1884/// # #[has_many]
1885/// # todos: toasty::Deferred<Vec<Todo>>,
1886/// # }
1887/// # #[derive(toasty::Model)]
1888/// # struct Todo {
1889/// # #[key]
1890/// # #[auto]
1891/// # id: i64,
1892/// # title: String,
1893/// # #[index]
1894/// # user_id: i64,
1895/// # #[belongs_to(key = user_id, references = id)]
1896/// # user: toasty::Deferred<User>,
1897/// # #[has_many]
1898/// # tags: toasty::Deferred<Vec<Tag>>,
1899/// # }
1900/// # #[derive(toasty::Model)]
1901/// # struct Tag {
1902/// # #[key]
1903/// # #[auto]
1904/// # id: i64,
1905/// # name: String,
1906/// # #[index]
1907/// # todo_id: i64,
1908/// # #[belongs_to(key = todo_id, references = id)]
1909/// # todo: toasty::Deferred<Todo>,
1910/// # }
1911/// let _ = toasty::create!(User {
1912/// name: "Alice",
1913/// todos: [{
1914/// title: "task",
1915/// tags: [{ name: "urgent" }, { name: "work" }]
1916/// }]
1917/// });
1918/// ```
1919///
1920/// This creates a `User`, then a `Todo` linked to that user, then two `Tag`
1921/// records linked to that todo.
1922///
1923/// # Fields that can be omitted
1924///
1925/// | Field type | Behavior when omitted |
1926/// |---|---|
1927/// | `#[auto]` | Value generated by the database or Toasty |
1928/// | `Option<T>` | Defaults to `None` (`NULL`) |
1929/// | `#[default(expr)]` | Uses the default expression |
1930/// | `#[update(expr)]` | Uses the expression as the initial value |
1931/// | `#[has_many] Deferred<Vec<T>>` or `#[has_many] Vec<T>` | No related records created |
1932/// | `#[has_one] Deferred<Option<T>>` or `#[has_one] Option<T>` | No related record created |
1933/// | `#[belongs_to] Deferred<Option<T>>` or `#[belongs_to] Option<T>` | Foreign key set to `NULL` |
1934///
1935/// Required fields (`String`, `i64`, non-optional `BelongsTo`, etc.) that are
1936/// missing do not cause a compile-time error. The insert fails at runtime with
1937/// a database constraint violation.
1938///
1939/// # Compile errors
1940///
1941/// **Type prefix on nested struct:**
1942///
1943/// ```compile_fail
1944/// # #[derive(toasty::Model)]
1945/// # struct User {
1946/// # #[key]
1947/// # #[auto]
1948/// # id: i64,
1949/// # name: String,
1950/// # }
1951/// # #[derive(toasty::Model)]
1952/// # struct Todo {
1953/// # #[key]
1954/// # #[auto]
1955/// # id: i64,
1956/// # #[index]
1957/// # user_id: i64,
1958/// # #[belongs_to(key = user_id, references = id)]
1959/// # user: toasty::Deferred<User>,
1960/// # }
1961/// // Error: remove the type prefix `User` — use `{ ... }` without a type name
1962/// toasty::create!(Todo { user: User { name: "Alice" } })
1963/// ```
1964///
1965/// Correct:
1966///
1967/// ```
1968/// # #[derive(toasty::Model)]
1969/// # struct User {
1970/// # #[key]
1971/// # #[auto]
1972/// # id: i64,
1973/// # name: String,
1974/// # }
1975/// # #[derive(toasty::Model)]
1976/// # struct Todo {
1977/// # #[key]
1978/// # #[auto]
1979/// # id: i64,
1980/// # #[index]
1981/// # user_id: i64,
1982/// # #[belongs_to(key = user_id, references = id)]
1983/// # user: toasty::Deferred<User>,
1984/// # }
1985/// let _ = toasty::create!(Todo { user: { name: "Alice" } });
1986/// ```
1987///
1988/// Nested struct values infer their type from the field.
1989///
1990/// **Nested lists:**
1991///
1992/// ```compile_fail
1993/// # #[derive(toasty::Model)]
1994/// # struct User {
1995/// # #[key]
1996/// # #[auto]
1997/// # id: i64,
1998/// # field: String,
1999/// # }
2000/// // Error: nested lists are not supported in create!
2001/// toasty::create!(User { field: [[{ }]] })
2002/// ```
2003///
2004/// **Missing braces or batch bracket:**
2005///
2006/// ```compile_fail
2007/// # #[derive(toasty::Model)]
2008/// # struct User {
2009/// # #[key]
2010/// # #[auto]
2011/// # id: i64,
2012/// # }
2013/// // Error: expected `{` for single creation or `::[` for batch creation after type path
2014/// toasty::create!(User)
2015/// ```
2016///
2017/// # Return type
2018///
2019/// | Form | Returns |
2020/// |---|---|
2021/// | `Type { ... }` | `TypeCreate` (single builder) |
2022/// | `in expr { ... }` | Builder for the relation's model |
2023/// | `Type::[ ... ]` | `Batch` — executes to `Vec<Type>` |
2024/// | `( ... )` | `Batch` — executes to tuple of results |
2025///
2026/// Single and scoped forms return a builder — call `.exec(&mut db).await?`.
2027/// Batch and tuple forms return a `Batch` — also call `.exec(&mut db).await?`.
2028#[proc_macro]
2029pub fn create(input: TokenStream) -> TokenStream {
2030 match create::generate(input.into()) {
2031 Ok(output) => output.into(),
2032 Err(e) => e.to_compile_error().into(),
2033 }
2034}
2035
2036/// Expands struct-literal syntax into update-builder method chains. Returns
2037/// the same builder `target.update()` would return — call
2038/// `.exec(&mut db).await?` to execute the update.
2039///
2040/// # Syntax
2041///
2042/// ```ignore
2043/// toasty::update!(target { field: value, ... })
2044/// ```
2045///
2046/// `target` is any expression that has an `.update()` method — a model
2047/// instance, a query builder, or a scoped relation accessor.
2048///
2049/// ```no_run
2050/// # #[derive(toasty::Model)]
2051/// # struct User {
2052/// # #[key]
2053/// # #[auto]
2054/// # id: i64,
2055/// # name: String,
2056/// # }
2057/// # async fn example(mut db: toasty::Db, mut user: User, id: i64) -> toasty::Result<()> {
2058/// // Instance target
2059/// toasty::update!(user { name: "Alice Smith" })
2060/// .exec(&mut db).await?;
2061///
2062/// // Query target
2063/// toasty::update!(User::filter_by_id(id) { name: "Bob" })
2064/// .exec(&mut db).await?;
2065/// # Ok(())
2066/// # }
2067/// ```
2068///
2069/// Instance targets do not consume the binding — the macro expands to
2070/// `user.update()`, which auto-borrows `&mut user` the same way the
2071/// chain form does. `user` stays owned after the macro returns.
2072///
2073/// Value expressions are evaluated before the target is borrowed, so
2074/// they may read the target's own fields:
2075///
2076/// ```no_run
2077/// # #[derive(toasty::Model)]
2078/// # struct Todo {
2079/// # #[key]
2080/// # #[auto]
2081/// # id: i64,
2082/// # done: bool,
2083/// # }
2084/// # async fn example(mut db: toasty::Db, mut todo: Todo) -> toasty::Result<()> {
2085/// toasty::update!(todo { done: !todo.done }).exec(&mut db).await?;
2086/// # Ok(())
2087/// # }
2088/// ```
2089///
2090/// # Field shapes
2091///
2092/// ## Explicit
2093///
2094/// `field: expr` sets the field to `expr`:
2095///
2096/// ```no_run
2097/// # #[derive(toasty::Model)]
2098/// # struct User {
2099/// # #[key]
2100/// # #[auto]
2101/// # id: i64,
2102/// # name: String,
2103/// # email: String,
2104/// # }
2105/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
2106/// toasty::update!(user {
2107/// name: "Alice Smith",
2108/// email: "alice.smith@example.com",
2109/// }).exec(&mut db).await?;
2110/// # Ok(())
2111/// # }
2112/// ```
2113///
2114/// `expr` is any Rust expression. For collection fields, pass a
2115/// `toasty::stmt::*` combinator (e.g. `stmt::push("x")`,
2116/// `stmt::apply([...])`) for non-set semantics.
2117///
2118/// ## Shorthand
2119///
2120/// `field` alone is equivalent to `field: field`, matching Rust struct
2121/// literal shorthand:
2122///
2123/// ```no_run
2124/// # #[derive(toasty::Model)]
2125/// # struct User {
2126/// # #[key]
2127/// # #[auto]
2128/// # id: i64,
2129/// # name: String,
2130/// # }
2131/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
2132/// let name = "Alice Smith";
2133/// toasty::update!(user { name }).exec(&mut db).await?;
2134/// # Ok(())
2135/// # }
2136/// ```
2137///
2138/// ## Method shorthand
2139///
2140/// `field.combinator(args)` is shorthand for
2141/// `field: toasty::stmt::combinator(args)`. Any function in `toasty::stmt`
2142/// works; missing functions surface as ordinary "no function" errors:
2143///
2144/// ```no_run
2145/// # #[derive(toasty::Model)]
2146/// # struct Article {
2147/// # #[key]
2148/// # #[auto]
2149/// # id: i64,
2150/// # tags: Vec<String>,
2151/// # }
2152/// # async fn example(mut db: toasty::Db, mut article: Article) -> toasty::Result<()> {
2153/// // tags.push("rust") expands to tags: stmt::push("rust")
2154/// toasty::update!(article { tags.push("rust") })
2155/// .exec(&mut db).await?;
2156/// # Ok(())
2157/// # }
2158/// ```
2159///
2160/// The shorthand is one method call deep. For chained expressions, use
2161/// the explicit `field: expr` form.
2162///
2163/// ## Embedded patch
2164///
2165/// `field: { sub: val, ... }` partially updates an embedded struct
2166/// field, leaving sub-fields not listed unchanged. Expands to
2167/// `stmt::apply([stmt::patch(...), ...])`:
2168///
2169/// ```no_run
2170/// # #[derive(toasty::Embed)]
2171/// # struct Metadata { version: i64, status: String }
2172/// # #[derive(toasty::Model)]
2173/// # struct Document {
2174/// # #[key]
2175/// # #[auto]
2176/// # id: i64,
2177/// # meta: Metadata,
2178/// # }
2179/// # async fn example(mut db: toasty::Db, mut doc: Document) -> toasty::Result<()> {
2180/// toasty::update!(doc {
2181/// meta: { version: 2, status: "published" },
2182/// }).exec(&mut db).await?;
2183/// # Ok(())
2184/// # }
2185/// ```
2186///
2187/// Sub-fields nest to arbitrary depth. To replace an embedded value
2188/// wholesale, pass the typed value directly: `meta: Metadata { ... }`.
2189///
2190/// ## Has-many insert
2191///
2192/// `field: [{ ... }, ...]` inserts new children of a has-many relation.
2193/// Each `{ ... }` becomes a create builder wrapped in
2194/// `stmt::insert(...)`; the whole list is wrapped in
2195/// `stmt::apply([...])`:
2196///
2197/// ```no_run
2198/// # #[derive(toasty::Model)]
2199/// # struct User {
2200/// # #[key]
2201/// # #[auto]
2202/// # id: i64,
2203/// # name: String,
2204/// # #[has_many]
2205/// # todos: toasty::Deferred<Vec<Todo>>,
2206/// # }
2207/// # #[derive(toasty::Model)]
2208/// # struct Todo {
2209/// # #[key]
2210/// # #[auto]
2211/// # id: i64,
2212/// # title: String,
2213/// # #[index]
2214/// # user_id: i64,
2215/// # #[belongs_to(key = user_id, references = id)]
2216/// # user: toasty::Deferred<User>,
2217/// # }
2218/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
2219/// toasty::update!(user {
2220/// todos: [{ title: "buy milk" }, { title: "walk dog" }],
2221/// }).exec(&mut db).await?;
2222/// # Ok(())
2223/// # }
2224/// ```
2225///
2226/// Items can also be plain expressions, mixed in with builder
2227/// shorthands — useful for combining inserts and removals:
2228///
2229/// ```no_run
2230/// # #[derive(toasty::Model)]
2231/// # struct User {
2232/// # #[key]
2233/// # #[auto]
2234/// # id: i64,
2235/// # #[has_many]
2236/// # todos: toasty::Deferred<Vec<Todo>>,
2237/// # }
2238/// # #[derive(toasty::Model)]
2239/// # struct Todo {
2240/// # #[key]
2241/// # #[auto]
2242/// # id: i64,
2243/// # title: String,
2244/// # #[index]
2245/// # user_id: i64,
2246/// # #[belongs_to(key = user_id, references = id)]
2247/// # user: toasty::Deferred<User>,
2248/// # }
2249/// # async fn example(mut db: toasty::Db, mut user: User, old: Todo) -> toasty::Result<()> {
2250/// toasty::update!(user {
2251/// todos: [{ title: "new" }, toasty::stmt::remove(&old)],
2252/// }).exec(&mut db).await?;
2253/// # Ok(())
2254/// # }
2255/// ```
2256///
2257/// # Field validation
2258///
2259/// The macro emits a method call per named field on the update builder.
2260/// A field name the model does not expose for update fails with the
2261/// compiler's standard "no method named …" error at the macro call
2262/// site.
2263#[proc_macro]
2264pub fn update(input: TokenStream) -> TokenStream {
2265 match update::generate(input.into()) {
2266 Ok(output) => output.into(),
2267 Err(e) => e.to_compile_error().into(),
2268 }
2269}