Skip to main content

fromage/
lib.rs

1//! Traits for conversions between non-local types.
2//!
3//! The traits in this crate provide a way to convert from one type to another type.
4//! Each trait serves a different purpose:
5//!
6//! - Implement the [`From`] trait for consuming value-to-value conversions
7//! - Implement the [`Into`] trait for consuming value-to-value conversions to types
8//!   outside the current crate
9//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
10//!   but should be implemented when the conversion can fail.
11#![no_std]
12
13/// A value-to-value conversion that consumes the input value. The
14/// opposite of [`Fromage`].
15///
16/// See [`From`] for documentation on the trait.
17pub trait Intoage<T, X>: Sized {
18    /// Converts this type into the (usually inferred) input type.
19    #[must_use]
20    fn intoage(self) -> T;
21}
22
23/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
24/// [`Intoage`].
25///
26/// See [`Into`] for documentation on the trait.
27pub trait Fromage<T, X>: Sized {
28    /// Converts to this type from the input type.
29    #[must_use]
30    fn fromage(value: T) -> Self;
31}
32
33/// An attempted conversion that consumes `self`, which may or may not be
34/// expensive.
35///
36/// See [`TryInto`] for documentation on the trait.
37pub trait TryIntoage<T, X>: Sized {
38    /// The type returned in the event of a conversion error.
39    type Error;
40
41    /// Performs the conversion.
42    fn try_intoage(self) -> Result<T, Self::Error>;
43}
44
45/// Simple and safe type conversions that may fail in a controlled
46/// way under some circumstances. It is the reciprocal of [`TryIntoage`].
47///
48/// See [`TryFrom`] for documentation on the trait.
49pub trait TryFromage<T, X>: Sized {
50    /// The type returned in the event of a conversion error.
51    type Error;
52
53    /// Performs the conversion.
54    fn try_fromage(value: T) -> Result<Self, Self::Error>;
55}
56
57// From implies Into
58impl<T, U, X> Intoage<U, X> for T
59where
60    U: Fromage<T, X>,
61{
62    /// Calls `U::fromage(self)`.
63    ///
64    /// That is, this conversion is whatever the implementation of
65    /// <code>[Fromage]&lt;T&gt; for U</code> chooses to do.
66    #[inline]
67    #[track_caller]
68    fn intoage(self) -> U {
69        U::fromage(self)
70    }
71}
72
73// From (and thus Into) is reflexive
74impl<T> Fromage<T, ()> for T {
75    /// Returns the argument unchanged.
76    #[inline(always)]
77    fn fromage(t: T) -> T {
78        t
79    }
80}
81
82// TryFrom implies TryInto
83impl<T, U, X> TryIntoage<U, X> for T
84where
85    U: TryFromage<T, X>,
86{
87    type Error = U::Error;
88
89    #[inline]
90    fn try_intoage(self) -> Result<U, U::Error> {
91        U::try_fromage(self)
92    }
93}
94
95// Infallible conversions are semantically equivalent to fallible conversions
96// with an uninhabited error type.
97impl<T, U> TryFromage<U, ()> for T
98where
99    U: Intoage<T, ()>,
100{
101    type Error = core::convert::Infallible;
102
103    #[inline]
104    fn try_fromage(value: U) -> Result<Self, Self::Error> {
105        Ok(U::intoage(value))
106    }
107}