implementation/
lib.rs

1//! A crate for targeting and accessing _actual implementation_.
2//!
3//! Take an example trait:
4//!
5//! ```rust
6//! # struct Website;
7//! trait ScrapeTheInternet {
8//!     fn scrape_the_internet(&self) -> Vec<Website>;
9//! }
10//! ```
11//!
12//! The trait represents some abstract computation. The trait exports a method signature that
13//! can be implemented by types. In this case, we can imagine what a true implementation of the
14//! trait will do: _Actually scrape the internet_.
15//!
16//! `implementation` provides the [Impl] type as an implementation target for traits having the following semantics:
17//!
18//! * The trait has only one actual, true implementation.
19//! * Other implementations of the trait _may exist_, but these are interpreted as _fake_, _mocked_ in some way.
20//!
21//! `implementation` enables a standardized way of writing these actual implementations in a way
22//! that allows the actual `Self`-receiver type to be unknown.
23//!
24//! # Usage
25//! To define the actual, generic implementation of `ScrapeTheInternet`, we can write the following impl:
26//!
27//! ```rust
28//! # struct Website;
29//! # trait ScrapeTheInternet {
30//! #    fn scrape_the_internet(&self) -> Vec<Website>;
31//! # }
32//! impl<T> ScrapeTheInternet for implementation::Impl<T> {
33//!     fn scrape_the_internet(&self) -> Vec<Website> {
34//!         todo!("find all the web pages, etc")
35//!     }
36//! }
37//! ```
38//!
39//! This code implements the trait for [Impl], and by doing that we have asserted
40//! that it is the actual, true implementation.
41//!
42//! The implementation is fully generic, and works for any `T`.
43//!
44//! ```no_run
45//! # struct Website;
46//! # trait ScrapeTheInternet {
47//! #    fn scrape_the_internet(&self) -> Vec<Website>;
48//! # }
49//! # impl<T> ScrapeTheInternet for implementation::Impl<T> {
50//! #     fn scrape_the_internet(&self) -> Vec<Website> {
51//! #         todo!("find all the web pages, etc")
52//! #     }
53//! # }
54//! use implementation::Impl;
55//!
56//! struct MyType;
57//!
58//! let websites = Impl::new(MyType).scrape_the_internet();
59//! ```
60//!
61//! ## Trait bounds
62//! The advantage of keeping trait implementations generic, is that the self type might
63//! live in a downstream crate. Let's say we need to access a configuration parameter
64//! from `scrape_the_internet`. E.g. the maximum number of pages to scrape:
65//!
66//! ```rust
67//! use implementation::Impl;
68//!
69//! # struct Website;
70//! # trait ScrapeTheInternet {
71//! #    fn scrape_the_internet(&self) -> Vec<Website>;
72//! # }
73//! trait GetMaxNumberOfPages {
74//!     fn get_max_number_of_pages(&self) -> Option<usize>;
75//! }
76//!
77//! impl<T> ScrapeTheInternet for Impl<T>
78//!     where Impl<T>: GetMaxNumberOfPages
79//! {
80//!     fn scrape_the_internet(&self) -> Vec<Website> {
81//!         let max_number_of_pages = self.get_max_number_of_pages();
82//!         todo!("find all the web pages, etc")
83//!     }
84//! }
85//! ```
86//!
87//! Now, for this to work, `Impl<T>` also needs to implement `GetMaxNumberOfPages` (for the same `T` that is going to be used).
88//!
89//! `GetMaxNumberOfPages` would likely be implemented for a specific `T` rather than a generic one,
90//! since that `T` would typically be some configuration holding that number:
91//!
92//! ```rust
93//! # trait GetMaxNumberOfPages {
94//! #     fn get_max_number_of_pages(&self) -> Option<usize>;
95//! # }
96//! struct Config {
97//!     max_number_of_pages: Option<usize>
98//! }
99//!
100//! impl GetMaxNumberOfPages for implementation::Impl<Config> {
101//!     fn get_max_number_of_pages(&self) -> Option<usize> {
102//!         self.max_number_of_pages
103//!     }
104//! }
105//! ```
106//!
107//! # Explanation
108//!
109//! This crate is the solution to a trait coherence problem.
110//!
111//! Given the trait above, we would like to provide an actual and a mocked implementation.
112//! We might know what its actual implementation looks like as an algorithm, but
113//! _not what type it should be implemented for_. There could be several reasons
114//! to have a generic Self:
115//!
116//! * The `Self` type might live in a downstream crate
117//! * It is actually designed to work generically
118//!
119//! If we had used a generic Self type (`impl<T> DoSomething for T`), the trait
120//! would be unable to also have distinct fake implementations, because that would break
121//! the coherence rules: A generic ("blanket") impl and a specialized
122//! impl are not allowed to exist at the same time, because that would lead to ambiguity.
123//!
124//! To solve that, a concrete type is needed as implementation target. But that
125//! type is allowed to be generic _internally_. It's just the root level that
126//! needs to be a concretely named type.
127//!
128//! That type is the [Impl] type.
129//!
130//! When we use this implementation, we can create as many fake implementations as we want.
131//!
132
133#![no_std]
134
135/// Wrapper type for targeting and accessing actual implementation.
136///
137/// [Impl] has smart-pointer capabilities, as it implements [std::ops::Deref] and [std::ops::DerefMut].
138/// You may freely choose what kind of `T` you want to wrap. It may be an owned one or it could be
139/// a `&T`. Each have different tradeoffs.
140///
141/// An owned `T` is the most flexible in implementations, but that requires always owning "sub-implementations"
142/// through an `Impl`:
143///
144/// ```rust
145/// use implementation::Impl;
146///
147/// struct MyConfig {
148///     param1: i32,
149///     sub_config: Impl<SubConfig>,
150/// }
151///
152/// struct SubConfig {
153///     param2: i32,
154/// }
155/// ```
156///
157/// A referenced `&T` makes it possible to _borrow_ an `Impl` from any `T`, but that _could_ prove to be
158/// more troublesome in some implementations. This also will require a reference-within-reference
159/// design in trait methods with a `&self` receiver, and some more boilerplate if it needs to be cloned:
160///
161/// ```
162/// use implementation::Impl;
163///
164/// trait DoSomething {
165///     fn something(&self);
166/// }
167///
168/// impl<'t, T> DoSomething for Impl<&'t T>
169///     where T: Clone + Send + 'static
170/// {
171///     // self is an `&Impl<&T>`:
172///     fn something(&self) {
173///
174///         // it will require some more code to make a proper clone of T:
175///         let t_clone = self.into_inner().clone();
176///
177///         let handle = std::thread::spawn(move || {
178///             let implementation = Impl::new(&t_clone);
179///
180///             // Do something else with Impl<&T>
181///         });
182///
183///         handle.join().unwrap();
184///     }
185/// }
186/// ```
187#[derive(Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
188pub struct Impl<T>(T);
189
190impl<T> Impl<T> {
191    /// Construct a new [Impl].
192    pub fn new(value: T) -> Impl<T> {
193        Impl(value)
194    }
195
196    pub fn into_inner(self) -> T {
197        self.0
198    }
199}
200
201impl<T> From<T> for Impl<T> {
202    fn from(value: T) -> Impl<T> {
203        Impl(value)
204    }
205}
206
207impl<T> core::ops::Deref for Impl<T> {
208    type Target = T;
209
210    fn deref(&self) -> &Self::Target {
211        &self.0
212    }
213}
214
215impl<T> core::ops::DerefMut for Impl<T> {
216    fn deref_mut(&mut self) -> &mut Self::Target {
217        &mut self.0
218    }
219}
220
221impl<T> AsRef<T> for Impl<T> {
222    fn as_ref(&self) -> &T {
223        &self.0
224    }
225}