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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! [`supply`](crate) implements an API similar to that proposed in
//! [RFC 3192](https://rust-lang.github.io/rfcs/3192-dyno.html).
//! It was proposed to provide [`Error`](core::error::Error) and API to expose extra context
//! information for errors. While the original RFC was a general API, the current implementation in
//! `core`/`std` is specifically for `Error`. The original proof of concept implementation can be
//! found at <https://github.com/nrc/provide-any>.
//!
//! [`supply`](crate) is a reimagining of the provide API to be more flexable and general purpose.
//! The motivation section of RFC 3192 states the problem this API is trying to solve very well.
//!
//! > However, in practice some kind of partial abstraction is required, where objects are treated
//! > abstractly but can be queried for data only present in a subset of all types which implement
//! > the trait interface. In this case there are only bad options: speculatively downcasting to
//! > concrete types (inefficient, boilerplatey, and fragile due to breaking abstraction) or adding
//! > numerous methods to the trait which might be functionally implemented, typically returning an
//! > Option where None means not applicable for the concrete type (boilerplatey, confusing, and
//! > leads to poor abstractions).
//!
//! <sub> <https://rust-lang.github.io/rfcs/3192-dyno.html#motivation> </sub>
//!
//! A similar pattern that is very useful but rarely seen in the wild is that proposed by
//! [`gdbstub`](https://docs.rs/gdbstub/latest/gdbstub/target/ext/index.html).
//! That of so called Inlineable Dyn Extension Traits (IDETs). You can think of the provide API
//! as an abstract form of this pattern.
//!
//! The core idea of the provide pattern is to use an output parameter to receive a type erased value.
//!
//! You may ask why just returning a type erased value is an issue, and its a good question. The
//! answer is that returning ownership directly requires something like a `Box`. However, we
//! don't always have access to a box or don't want the extra allocation. But wait what if we just
//! returned a `&dyn Any`? This doesn't need a box. However, this prevents returning owned values.
//! We are limited to things that can be borrowed from the source.
//!
//! Instead we take another approach. We construct a "hole". A place a value should go. We then
//! give a borrow of this hole to a value for it to "fill".
//!
//! This design has some major advantages.
//! For one it solves the returning ownership issue. Instead the provider transfers ownership into
//! the existing hole we gave it. Because as the requester we know the type of data we want we can
//! use some stack space to store the hole and eventual value.
//! Additionally, this design allows a requester to change the behavior of the hole. For example
//! we can have many holes that all need to be filled by the provider in one operation.
//!
//! Another aspect that `supply` expands on over the RFC is the use of arbitrary length lifetime
//! lists. We won't get into those here. See the [`ty-tag`](https://crates.io/crates/ty-tag) crate for
//! more information about those.
//!
//! Connecting this theoretical design to `supply`'s implementation we get the following.
//! The hole is represented by something implementing the [`Want`] trait. This trait has methods
//! for providing it a value to store. The provider then implements [`Provider`] and when it's
//! methods are called provides any values it can to the passed in want.
//!
//! A requester uses a provider by first constructing an empty [`Want`] implementer. Then, the
//! requester calls `.provide()` on the [`Provider`] to give the want a value. Then the requester
//! can remove the value from the want and use it however it needs to. Using [`ProviderExt`] we
//! can use a simple method
//! call of the form `provider.request::<Request>()` to request values from a provider.
//!
//! It is recommended to use the prelude which has the common API elements.
//! ```
//! use supply::prelude::*;
//! ```
//!
//! Most users should start with implementing the [`Provider`] trait on one or more
//! types they want to expose extra information from. Then the `.request::<T>()` method
//! can be used to request a specific type of information from the provider. This
//! is the core API flow of `supply`. Below is an example with a couple of the more advanced
//! features for demonstration.
//!
//! ### Examples
//!
//! ```
//! use supply::prelude::*;
//!
//! struct Person<'a> {
//! name: &'a str,
//! age: u8,
//! }
//!
//! // Implementing Provider allows requesting data from a Person value.
//! impl<'r, 'a> Provider<'r> for Person<'a> {
//! type Lifetimes = l!['a];
//!
//! fn provide(&'r self, want: &mut dyn Want<Self::Lifetimes>) {
//! // Provide the name and age fields.
//! want.provide_value(self.name)
//! .provide_value(self.age);
//! }
//! }
//!
//! // Make an example person to request data from.
//! let name = String::from("bob");
//!
//! let provided_name;
//! {
//! let person = Person {
//! name: &name,
//! age: 42,
//! };
//!
//! // Convert to a trait object to show Provider is object safe.
//! let provider: &dyn ProviderDyn<l!['_]> = &person;
//!
//! // Request the person's name.
//! provided_name = provider.request::<&str>();
//! assert_eq!(provided_name, Some("bob"));
//!
//! // Request the person's age.
//! let provided_age = provider.request::<u8>();
//! assert_eq!(provided_age, Some(42));
//!
//! // Request something Person doesn't provide.
//! // We just don't get a value from the request.
//! let provided_something = provider.request::<f32>();
//! assert_eq!(provided_something, None);
//! };
//!
//! // Because the name was tagged as &'a str we can still access it here.
//! assert_eq!(provided_name, Some("bob"));
//! ```
//!
//! ## `no_std` Support
//!
//! This crate is always `#![no_std]`, it can be used anywhere Rust can.
//!
//! ## Minimum Supported Rust Version
//!
//! Requires Rust 1.83.0.
//!
//! This crate follows the ["Latest stable Rust" policy](https://gist.github.com/alexheretic/d1e98d8433b602e57f5d0a9637927e0c). The listed MSRV won't be changed unless needed.
//! However, updating the MSRV anywhere up to the latest stable at time of release
//! is allowed.
/// Commonly needed traits.
pub use *;
use ;
use TagTypeId;
use ErasedWantFor;
/// Provider of values.
///
/// Provided values may contain lifetimes from the `Self` type and the `'r` lifetime.
/// A want for some number of values.