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]<T> 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}