kutil_std/foster/
foster.rs

1//
2// Foster
3//
4
5/// Fostering allows for *subjective* equivalence between owned values and differently-typed
6/// fostered values. Equivalence can mean comparison, iteration, hashing, representation, etc.
7///
8/// An example use case:
9///
10/// You create [Vec]\<[String]\> values dynamically in your program, but you also want to allow for
11/// constant values, which *cannot* be a [Vec]. A reasonable constant equivalent would be
12/// `&'static [&'static str]`, which is a very different type.
13///
14/// Although you could convert `&'static [&'static str]` to [Vec]\<[String]\>, it would require
15/// allocation, which is unnecessary and wasteful in situations in which you don't actually need or
16/// care about ownership, e.g. comparisons. (Although we *can* allow for efficient conversion via
17/// the [IntoOwned](super::super::borrow::IntoOwned) trait.)
18///
19/// "Fostering" means creating a single type on top of both types, and then implementing necessary
20/// traits for that type, e.g. [PartialEq].
21///
22/// This type simply provides a unified mechanism for fostering. Furthermore, this module contains
23/// commonly useful implementations, such as [FosterString](super::string::FosterString) and
24/// [FosterStringVector](super::string_vector::FosterStringVector), as well as macros for
25/// delegating the implemented traits to newtypes.
26///
27/// Note that [Cow](std::borrow::Cow) also counts as fostering, but it's more specific in that the
28/// fostered type is always a reference of the owned type, which allows for generalized conversion
29/// to ownership when necessary via [ToOwned].
30#[derive(Clone, Debug)]
31pub enum Foster<OwnedT, FosteredT> {
32    /// Owned.
33    Owned(OwnedT),
34
35    /// Fostered.
36    Fostered(FosteredT),
37}
38
39impl<OwnedT, FosteredT> Foster<OwnedT, FosteredT> {
40    /// Constructor.
41    pub const fn new_owned(value: OwnedT) -> Self {
42        Self::Owned(value)
43    }
44
45    /// Constructor.
46    pub const fn new_fostered(value: FosteredT) -> Self {
47        Self::Fostered(value)
48    }
49
50    /// True if owned.
51    pub const fn is_owned(&self) -> bool {
52        matches!(self, Self::Owned(_))
53    }
54}
55
56impl<OwnedT, FosteredT> From<OwnedT> for Foster<OwnedT, FosteredT> {
57    fn from(value: OwnedT) -> Self {
58        Self::Owned(value)
59    }
60}