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}