rinia/numeric/casting.rs
1/// A trait which represents an infallible cast from one type to another.
2///
3/// Implementations must guarantee that the conversion is always valid and
4/// does not lose information.
5pub trait Cast<T> {
6 /// Casts `self` to type `T`.
7 fn cast(self) -> T;
8}
9
10/// A trait which represents an infallible cast into `Self` from another type.
11///
12/// See [Cast] for more information.
13pub trait CastFrom<T> {
14 /// Casts `value` to type `Self`.
15 fn cast_from(value: T) -> Self;
16}
17
18/// A trait which represents a potentially lossy cast from one type to another.
19///
20/// A lossy cast always performs the conversion, even when information may be
21/// discarded. This may include reduced precision, truncation, clamping, or
22/// other changes to the original value.
23pub trait LossyCast<T> {
24 /// Casts `self` to type `T`, potentially losing information.
25 fn lossy_cast(self) -> T;
26}
27
28/// A trait which represents a potentially lossy cast into `Self` from another type.
29///
30/// See [LossyCast] for more information.
31pub trait LossyCastFrom<T> {
32 /// Casts `value` to type `Self`, potentially losing information.
33 fn lossy_cast_from(value: T) -> Self;
34}
35
36/// A trait which represents a saturating cast from one type to another.
37///
38/// A saturating cast always performs the conversion. If the value is outside
39/// the range representable by the target type, it is clamped to the nearest
40/// representable value.
41///
42/// Non-finite floating-point values are handled as out-of-range values:
43/// NaN converts to zero, positive infinity converts to the target maximum,
44/// and negative infinity converts to the target minimum.
45pub trait SaturatingCast<T> {
46 /// Casts `self` to type `T`, saturating the value if it is out of range.
47 fn saturating_cast(self) -> T;
48}
49
50/// A trait which represents a saturating cast into `Self` from another type.
51///
52/// See [SaturatingCast] for more information.
53pub trait SaturatingCastFrom<T> {
54 /// Casts `value` to type `Self`, saturating the value if it is out of range.
55 fn saturating_cast_from(value: T) -> Self;
56}
57
58/// A trait which represents a cast from one type to the corresponding signed type.
59pub trait SignedCast<T> {
60 /// Casts `self` to type `T`, which is the signed equivalent of the original type.
61 fn signed_cast(self) -> T;
62}
63
64/// A trait which represents a cast into `Self` from another type that is the corresponding signed type.
65pub trait SignedCastFrom<T> {
66 /// Casts `value` to type `Self`, which is the signed equivalent of the original type.
67 fn signed_cast_from(value: T) -> Self;
68}
69
70/// A trait which represents a cast from one type to the corresponding unsigned type.
71pub trait UnsignedCast<T> {
72 /// Casts `self` to type `T`, which is the unsigned equivalent of the original type.
73 fn unsigned_cast(self) -> T;
74}
75
76pub trait UnsignedCastFrom<T> {
77 /// Casts `value` to type `Self`, which is the unsigned equivalent of the original type.
78 fn unsigned_cast_from(value: T) -> Self;
79}
80
81/// A trait which represents a fallible cast that preserves the value exactly.
82///
83/// The conversion succeeds only when the value can be represented exactly
84/// by the target type. Conversions which would lose precision or otherwise
85/// alter the value return an error.
86pub trait TryExactCast<T> {
87 /// Attempts to cast `self` to type `T` without loss of information.
88 fn try_exact_cast(self) -> Result<T, CastError>;
89}
90
91/// A trait which represents a fallible cast into `Self` from another type that preserves the value exactly.
92///
93/// See [TryExactCast] for more information.
94pub trait TryExactCastFrom<T>
95where
96 Self: Sized,
97{
98 /// Attempts to cast `value` to type `Self` without loss of information.
99 fn try_exact_cast_from(value: T) -> Result<Self, CastError>;
100}
101
102/// A trait which represents a fallible cast between types.
103///
104/// The conversion succeeds when the value can be represented by the target
105/// type according to the target type's conversion rules. Conversions which
106/// cannot be performed safely return an error.
107pub trait TryCast<T> {
108 /// Attempts to cast `self` to type `T`.
109 fn try_cast(self) -> Result<T, CastError>;
110}
111
112/// A trait which represents a fallible cast into `Self` from another type.
113///
114/// See [TryCast] for more information.
115pub trait TryCastFrom<T>
116where
117 Self: Sized,
118{
119 /// Attempts to cast `value` to type `Self`.
120 fn try_cast_from(value: T) -> Result<Self, CastError>;
121}
122
123/// An error returned by fallible cast operations.
124#[derive(Debug, PartialEq)]
125pub enum CastError {
126 /// The value cannot be represented within the range of the target type.
127 OutOfRange,
128
129 /// The value contains a fractional component that cannot be represented
130 /// by the target type.
131 Fractional,
132
133 /// The value is not a finite number, such as NaN or infinity.
134 NonFinite,
135
136 /// The conversion would lose precision or otherwise fail to preserve the
137 /// original value exactly.
138 Inexact,
139}
140
141// Blanket impls for the From variants
142
143impl<T, U> CastFrom<T> for U
144where
145 T: Cast<U>,
146{
147 #[inline]
148 fn cast_from(value: T) -> Self {
149 value.cast()
150 }
151}
152
153impl<T, U> LossyCastFrom<T> for U
154where
155 T: LossyCast<U>,
156{
157 #[inline]
158 fn lossy_cast_from(value: T) -> Self {
159 value.lossy_cast()
160 }
161}
162
163impl<T, U> SaturatingCastFrom<T> for U
164where
165 T: SaturatingCast<U>,
166{
167 #[inline]
168 fn saturating_cast_from(value: T) -> Self {
169 value.saturating_cast()
170 }
171}
172
173impl<T, U> SignedCastFrom<T> for U
174where
175 T: SignedCast<U>,
176{
177 #[inline]
178 fn signed_cast_from(value: T) -> Self {
179 value.signed_cast()
180 }
181}
182
183impl<T, U> UnsignedCastFrom<T> for U
184where
185 T: UnsignedCast<U>,
186{
187 #[inline]
188 fn unsigned_cast_from(value: T) -> Self {
189 value.unsigned_cast()
190 }
191}
192
193impl<T, U> TryCastFrom<T> for U
194where
195 T: TryCast<U>,
196{
197 #[inline]
198 fn try_cast_from(value: T) -> Result<Self, CastError> {
199 value.try_cast()
200 }
201}
202
203impl<T, U> TryExactCastFrom<T> for U
204where
205 T: TryExactCast<U>,
206{
207 #[inline]
208 fn try_exact_cast_from(value: T) -> Result<Self, CastError> {
209 value.try_exact_cast()
210 }
211}