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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! Compile-time field selectors: typed keys that read (and optionally write) one field of a
//! source by monomorphization, with no hashing, boxing, or downcasting.
//!
//! A key is a zero-sized type implementing [`Field`] for the sources that carry its field. The
//! runtime threads the source (a per-delivery context value or the shared application state) and
//! resolves `key.get(src)` to a direct field access. A key middleware writes also implements
//! [`FieldMut`]. Because a key implements [`Field`] only for the sources that actually carry its
//! field, applying an inapplicable key is a compile error rather than a runtime miss.
/// A compile-time key reading one typed field out of `Src`.
///
/// Implemented by a zero-sized selector type for each source that carries the field. Resolution is
/// monomorphized to a direct field read: no hash, no `Box`, no downcast. The key is taken by value
/// (selectors are `Copy` zero-sized types), and the read borrows from the source for the call.
///
/// # Examples
///
/// ```
/// use ruststream::Field;
///
/// struct Delivery {
/// sequence: u64,
/// }
///
/// #[derive(Clone, Copy)]
/// struct Sequence;
///
/// impl Field<Delivery> for Sequence {
/// type Value<'a> = u64;
/// fn get(self, src: &Delivery) -> u64 {
/// src.sequence
/// }
/// }
///
/// let delivery = Delivery { sequence: 7 };
/// assert_eq!(Sequence.get(&delivery), 7);
/// ```
/// A [`Field`] key middleware can also write, for per-delivery scratch values.
///
/// The read side ([`Field::get`]) is typically `Option<&T>` (the value may not have been set yet),
/// while [`set`](FieldMut::set) takes the owned `T`.
///
/// # Examples
///
/// ```
/// use ruststream::{Field, FieldMut};
///
/// #[derive(Default)]
/// struct Ctx {
/// user: Option<u64>,
/// }
///
/// #[derive(Clone, Copy)]
/// struct User;
///
/// impl Field<Ctx> for User {
/// type Value<'a> = Option<&'a u64>;
/// fn get(self, src: &Ctx) -> Option<&u64> {
/// src.user.as_ref()
/// }
/// }
///
/// impl FieldMut<Ctx> for User {
/// type Owned = u64;
/// fn set(self, src: &mut Ctx, value: u64) {
/// src.user = Some(value);
/// }
/// }
///
/// let mut ctx = Ctx::default();
/// User.set(&mut ctx, 42);
/// assert_eq!(User.get(&ctx), Some(&42));
/// ```
/// Builds a handler's per-delivery context value from the broker message.
///
/// The runtime calls this once per delivery to construct the typed context the handler reads its
/// broker fields off (by [`Field`] key). A broker with per-delivery fields implements it for its
/// own context type, reading the fields off its concrete message; the blanket `impl` for `()`
/// gives the zero-field default, so a broker that exposes nothing needs no implementation.
///
/// The built context is an owned value (it reads its fields out of the message rather than
/// borrowing it), so it does not tie the handler's context type to the delivery lifetime; broker
/// metadata is typically `Copy` (offsets, sequence numbers), so this is a stack copy.
///
/// # Examples
///
/// ```
/// use ruststream::BuildContext;
///
/// struct Msg {
/// offset: u64,
/// }
///
/// // A broker context carrying one field, built from the message.
/// struct OrdersContext {
/// offset: u64,
/// }
///
/// impl BuildContext<Msg> for OrdersContext {
/// fn build(msg: &Msg) -> Self {
/// Self { offset: msg.offset }
/// }
/// }
///
/// let msg = Msg { offset: 9 };
/// let cx = OrdersContext::build(&msg);
/// assert_eq!(cx.offset, 9);
/// ```