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
use crate::tup_struct::{TupDefault, Unused, Used};
named_tup_derive::sealed_trait_builder!();
/// A copy of the [`Into`] trait from the standard library. The [`Into`] trait could unfortunately
/// not be used due to it's type reflexivity which clashed with the Tup implementation.
///
/// This trait is sealed as it should only ever be implemented on the Tup type.
///
/// A Tup can be transformed to another type if for all arguments it falls
/// in one of the following categories:
///
/// ```rust
/// # use named_tup::{TupInto, tup, Tup, tup_default};
/// #[tup_default]
/// pub fn main() {
/// let unused_to_unused: Tup!(bar: () = ()) = tup!().into_tup();
/// assert_eq!(unused_to_unused, tup!());
///
/// let used_to_used: Tup!(foo: i32) = tup!(foo: 3).into_tup();
/// assert_eq!(used_to_used, tup!(foo: 3));
///
/// let used_to_default: Tup!(foo: &'static str = "hi") = tup!(foo: "yum").into_tup();
/// assert_eq!(used_to_default, tup!(foo: "yum"));
///
/// let unused_to_default: Tup!(foo: f64 = 1.3) = tup!().into_tup();
/// assert_eq!(unused_to_default, tup!(foo: 1.3));
///
/// let default_to_used: Tup!(foo: f64) = unused_to_default.into_tup();
/// assert_eq!(default_to_used, tup!(foo: 1.3));
/// }
/// ```
///
/// <br>
///
/// Since each rule acts individually on the tup's arguments we can combine them together.
///
/// ```rust
/// # use named_tup::{TupInto, Tup, tup, tup_default};
/// let colour = tup!(red: 65, green: 105, blue: 225);
/// let pixel = tup!(x: 5.0, y: 6.4, height: 4.7);
///
/// paint(pixel.into_tup(), colour.into_tup());
///
/// #[tup_default]
/// fn paint(pixel: Tup!(x: f64, y: f64, height: f64 = 1.0, width: f64 = 1.0),
/// colour: Tup!(red: i32, green: i32, blue: i32, opacity: f64 = 1.0))
/// {
/// let pixel_colour = pixel + colour;
/// // Paint
/// }
/// ```
///
pub trait TupInto<T>: private::Sealed {
/// Performs the conversion.
#[must_use]
fn into_tup(self) -> T;
}
/// A copy of the [`From`] trait from the standard library. The [`From`] trait could unfortunately
/// not be used due to it's type reflexivity which clashed with the Tup implementation.
///
/// This trait is sealed as it should only ever be implemented on the Tup type.
///
/// For more information please look at the [`TupInto`] trait.
/// ```rust
/// # use named_tup::{TupFrom, tup, Tup, tup_default};
/// #[tup_default]
/// pub fn main() {
/// let rick = tup!(funny: true);
/// let rick = <Tup!(funny: bool, lyrics: &'static str = "Never Gonna Give You Up...")>::from_tup(rick);
/// assert_eq!(rick, tup!(funny: true, lyrics: "Never Gonna Give You Up..."))
/// }
/// ```
pub trait TupFrom<T>: private::Sealed {
/// Performs the conversion
#[must_use]
fn from_tup(_: T) -> Self;
}
impl<T, U> TupInto<U> for T
where
U: TupFrom<T>,
T: private::Sealed,
{
fn into_tup(self) -> U {
U::from_tup(self)
}
}
/// A helper trait to figure out if a tup field can transformed.
pub trait CanInto<OLD, NEW> {
type Output;
fn into(self) -> Self::Output;
}
impl CanInto<Unused, Unused> for () {
type Output = ();
fn into(self) {}
}
impl<T> CanInto<Used, Used> for T {
type Output = T;
fn into(self) -> T {
self
}
}
impl<D: TupDefault> CanInto<Unused, D> for () {
type Output = D::Output;
fn into(self) -> D::Output {
D::default()
}
}
impl<T, D> CanInto<Used, D> for T
where
D: TupDefault<Output = T>,
{
type Output = T;
fn into(self) -> T {
self
}
}
impl<T, D> CanInto<D, Used> for T
where
D: TupDefault<Output = T>,
{
type Output = T;
fn into(self) -> T {
self
}
}