1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! # Structural Typing for Rust
//!
//! Track which struct fields are present/absent at the type level.
//!
//! ## Quick Example
//!
//! ```
//! use structural_typing::{structural, presence::Present, select};
//!
//! #[structural]
//! struct User { name: String, email: String }
//!
//! // Build incrementally - type tracks which fields are set
//! let user = User::empty().name("Alice".to_owned());
//!
//! // Methods can require specific fields
//! impl<F: user::Fields<name = Present>> User<F> {
//! fn greet(&self) -> String {
//! format!("Hello, {}!", self.name)
//! }
//! }
//!
//! user.greet(); // ✓ Compiles - name is Present
//! // User::empty().greet(); // ✗ Compile error - name is Absent
//!
//! // Use select! to create field sets
//! type NameAndEmail = select!(user: name, email);
//! ```
//!
//! ## Core Concepts
//!
//! - **Field States**: `Present` (has value), `Optional` (has `Option<T>`), `Absent` (no value)
//! - **Builder API**: `.field(value)` infers presence from type (`T` → `Present`, `Option<T>` → `Optional`, `PhantomData<T>` → Absent)
//! - **Type Selection**: `select!(module: field1, ?field2)` macro or type aliases like `with::name::Present<with::email::Optional>`
//! - **Bounded Impls**: Methods requiring specific fields via trait bounds
//!
//! See the [examples](https://github.com/Crazytieguy/structural-typing-rs/tree/master/examples) directory for comprehensive usage including merge, split, serde integration, and more.
/// Runtime field access trait for checking presence and getting values.
/// Type-level presence markers and traits for field state tracking.
/// Traits for splitting structs into selected fields and remainder.
pub use structural;
pub use derive_where;
/// Construct a `FieldSet` by selecting fields from a module.
///
/// # Syntax
/// - `select!(module: field)` - field is Present
/// - `select!(module: ?field)` - field is Optional
/// - `select!(module: all)` - all fields Present (expands to `module::with::all::Present`)
/// - Multiple fields compose: `select!(module: field1, ?field2)` expands to `module::with::field1::Present<module::with::field2::Optional>`
///
/// # Examples
/// ```rust
/// # use structural_typing::{structural, select};
/// # #[structural]
/// # struct User { name: String, email: String, id: u64 }
/// // For User { name, email, id }
/// type NameAndEmail = select!(user: name, email);
/// type NameOptionalEmail = select!(user: name, ?email);
/// type AllPresent = select!(user: all);
/// ```