Skip to main content

refining_core/
refinement.rs

1//! Refinement types.
2
3use core::{
4    cmp::Ordering,
5    fmt,
6    hash::{Hash, Hasher},
7    marker::PhantomData,
8    mem::transmute,
9    ops::Deref,
10};
11
12#[cfg(feature = "unsafe-assert")]
13use core::hint::assert_unchecked;
14
15use crate::{
16    context::NoContext,
17    errors::{Error, Recoverable, RecoverableRef},
18    predicate::Predicate,
19    types::TypeStr,
20};
21
22/// Represents refinement types.
23#[repr(transparent)]
24pub struct Refinement<T: ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized = NoContext> {
25    predicate: PhantomData<P>,
26    context: PhantomData<C>,
27    value: T,
28}
29
30impl<T: fmt::Debug + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> fmt::Debug
31    for Refinement<T, P, C>
32{
33    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
34        self.get_ref().fmt(formatter)
35    }
36}
37
38impl<T: fmt::Display + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> fmt::Display
39    for Refinement<T, P, C>
40{
41    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
42        self.get_ref().fmt(formatter)
43    }
44}
45
46impl<T: PartialEq + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> PartialEq
47    for Refinement<T, P, C>
48{
49    fn eq(&self, other: &Self) -> bool {
50        self.get_ref().eq(other.get_ref())
51    }
52}
53
54impl<T: Eq + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Eq for Refinement<T, P, C> {}
55
56impl<T: PartialOrd + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> PartialOrd
57    for Refinement<T, P, C>
58{
59    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
60        self.get_ref().partial_cmp(other.get_ref())
61    }
62}
63
64impl<T: Ord + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Ord for Refinement<T, P, C> {
65    fn cmp(&self, other: &Self) -> Ordering {
66        self.get_ref().cmp(other.get_ref())
67    }
68}
69
70impl<T: Hash + ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Hash for Refinement<T, P, C> {
71    fn hash<H: Hasher>(&self, state: &mut H) {
72        self.get_ref().hash(state);
73    }
74}
75
76impl<T: ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> AsRef<T> for Refinement<T, P, C> {
77    fn as_ref(&self) -> &T {
78        self.get_ref()
79    }
80}
81
82impl<T: ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Deref for Refinement<T, P, C> {
83    type Target = T;
84
85    fn deref(&self) -> &Self::Target {
86        self.get_ref()
87    }
88}
89
90mod sealed {
91    pub trait Sealed {}
92}
93
94/// Represents recoverable refining results.
95pub type RecoverableRefinement<R> =
96    Recoverable<R, <R as Refining>::Predicate, <R as Refining>::Context, <R as Refining>::Value>;
97
98/// Represents recoverable reference refining results.
99pub type RecoverableRefinementRef<'a, R> = RecoverableRef<
100    'a,
101    R,
102    <R as Refining>::Predicate,
103    <R as Refining>::Context,
104    <R as Refining>::Value,
105>;
106
107/// Refinement methods.
108///
109/// This sealed trait is used for generics over [`Refinement<T, P, C>`].
110pub trait Refining: Deref<Target = Self::Value> + sealed::Sealed {
111    /// The refinement value (`T` in [`Refinement<T, P, C>`]).
112    type Value: ?Sized;
113
114    /// The refinement predicate (`P` in [`Refinement<T, P, C>`]).
115    type Predicate: Predicate<Self::Value> + ?Sized;
116
117    /// The refinement context (`C` in [`Refinement<T, P, C>`]).
118    type Context: TypeStr + ?Sized;
119
120    /// Constructs [`Self`] from [`Self::Value`] by reference without checking.
121    ///
122    /// # Safety
123    ///
124    /// This method should only be called for references that satisfy [`Self::Predicate`].
125    ///
126    /// Alternatively, this can be checked using the [`is_fine`] method.
127    ///
128    /// [`is_fine`]: Self::is_fine
129    unsafe fn unchecked_ref(value: &Self::Value) -> &Self;
130
131    /// Constructs [`Self`] from [`Self::Value`] without checking.
132    ///
133    /// # Safety
134    ///
135    /// This method should only be called for values that satisfy [`Self::Predicate`].
136    ///
137    /// Alternatively, this can be checked using the [`is_fine`] method.
138    ///
139    /// [`is_fine`]: Self::is_fine
140    unsafe fn unchecked(value: Self::Value) -> Self
141    where
142        Self::Value: Sized;
143
144    /// Checks whether the given [`Self::Value`] satisfies [`Self::Predicate`].
145    ///
146    /// This is the same as calling [`Self::Predicate::check`] on the value.
147    ///
148    /// [`Self::Predicate::check`]: Predicate::check
149    fn is_fine(value: &Self::Value) -> bool {
150        Self::Predicate::check(value)
151    }
152
153    /// Returns the contained value reference.
154    fn get_ref(&self) -> &Self::Value;
155
156    /// Returns the contained value.
157    fn get(self) -> Self::Value
158    where
159        Self::Value: Sized;
160
161    /// Constructs [`Self`] from [`Self::Value`] by reference.
162    ///
163    /// # Errors
164    ///
165    /// Returns [`Error<Self::Value, Self::Predicate, Self::Context>`](Error)
166    /// reference in case the reference does not satisfy the predicate.
167    fn checked_ref(value: &Self::Value) -> RecoverableRefinementRef<'_, Self>;
168
169    /// Constructs [`Self`] from [`Self::Value`].
170    ///
171    /// # Errors
172    ///
173    /// Returns [`Error<Self::Value, Self::Predicate, Self::Context>`](Error)
174    /// in case the value does not satisfy the predicate.
175    fn checked(value: Self::Value) -> RecoverableRefinement<Self>
176    where
177        Self::Value: Sized,
178        Self: Sized;
179}
180
181impl<T: ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Refinement<T, P, C> {
182    /// Constructs [`Self`] by reference without checking.
183    ///
184    /// # Safety
185    ///
186    /// This method should only be called for references that satisfy `P`,
187    /// which can be checked via [`is_fine`].
188    ///
189    /// [`is_fine`]: Self::is_fine
190    pub const unsafe fn unchecked_ref(value: &T) -> &Self {
191        // SAFETY: layout of `T` matches `Self` due to `repr(transparent)`, so this is safe
192        // moreover, the caller guarantees that `value` satisfies `P`
193        unsafe { transmute(value) }
194    }
195
196    /// Returns the contained value reference.
197    ///
198    /// If the `unsafe-assert` feature is enabled, [`assert_unchecked`] is called on the reference
199    /// before returning.
200    ///
201    /// The [`get_ref_no_assert`] method is provided in case the assertion is explicitly not needed.
202    ///
203    /// [`assert_unchecked`]: core::hint::assert_unchecked
204    /// [`get_ref_no_assert`]: Self::get_ref_no_assert
205    #[allow(clippy::missing_const_for_fn)] // conditionally const
206    pub fn get_ref(&self) -> &T {
207        let reference = self.get_ref_no_assert();
208
209        #[cfg(feature = "unsafe-assert")]
210        unsafe {
211            assert_unchecked(Self::is_fine(reference));
212        }
213
214        reference
215    }
216
217    /// Returns the contained value.
218    pub const fn get_ref_no_assert(&self) -> &T {
219        &self.value
220    }
221
222    /// Checks whether the provided value satisfies `P`.
223    ///
224    /// This is the same as calling [`P::check`] on it.
225    ///
226    /// [`P::check`]: Predicate::check
227    pub fn is_fine(value: &T) -> bool {
228        P::check(value)
229    }
230
231    /// Constructs [`Self`] by reference.
232    ///
233    /// # Errors
234    ///
235    /// Returns [`Error<T, P, C>`] in case the reference does not satisfy `P`.
236    ///
237    /// [`Error<T, P, C>]: Error
238    pub fn checked_ref(value: &T) -> RecoverableRef<'_, Self, P, C, T> {
239        if Self::is_fine(value) {
240            Ok(unsafe { Self::unchecked_ref(value) })
241        } else {
242            Err(Error::new_ref(value))
243        }
244    }
245}
246
247impl<T, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Refinement<T, P, C> {
248    /// Constructs [`Self`] without checking the value.
249    ///
250    /// # Safety
251    ///
252    /// This method should only be called for values that satisfy the predicate `P`,
253    /// which can be checked using [`is_fine`].
254    ///
255    /// [`is_fine`]: Self::is_fine
256    pub const unsafe fn unchecked(value: T) -> Self {
257        Self {
258            predicate: PhantomData,
259            context: PhantomData,
260            value,
261        }
262    }
263
264    /// Returns the contained value.
265    ///
266    /// If the `unsafe-assert` feature is enabled, [`assert_unchecked`] is called on the reference
267    /// before returning the value.
268    ///
269    /// The [`get_no_assert`] method is provided in case the assertion is explicitly not needed.
270    ///
271    /// [`assert_unchecked`]: core::hint::assert_unchecked
272    /// [`get_no_assert`]: Self::get_no_assert
273    pub fn get(self) -> T {
274        let value = self.get_no_assert();
275
276        #[cfg(feature = "unsafe-assert")]
277        unsafe {
278            assert_unchecked(Self::is_fine(&value));
279        }
280
281        value
282    }
283
284    /// Returns the contained value.
285    pub fn get_no_assert(self) -> T {
286        self.value
287    }
288
289    /// Constructs [`Self`] from the given value.
290    ///
291    /// # Errors
292    ///
293    /// Returns [`Error<T, P, C>`] in case the value does not satisfy `P`.
294    ///
295    /// [`Error<T, P, C>]: Error
296    pub fn checked(value: T) -> Recoverable<Self, P, C, T> {
297        if Self::is_fine(&value) {
298            Ok(unsafe { Self::unchecked(value) })
299        } else {
300            Err(Error::new(value))
301        }
302    }
303}
304
305impl<T: ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> sealed::Sealed
306    for Refinement<T, P, C>
307{
308}
309
310impl<T: ?Sized, P: Predicate<T> + ?Sized, C: TypeStr + ?Sized> Refining for Refinement<T, P, C> {
311    type Value = T;
312    type Predicate = P;
313    type Context = C;
314
315    unsafe fn unchecked_ref(value: &Self::Value) -> &Self {
316        unsafe { Self::unchecked_ref(value) }
317    }
318
319    unsafe fn unchecked(value: Self::Value) -> Self
320    where
321        Self::Value: Sized,
322    {
323        unsafe { Self::unchecked(value) }
324    }
325
326    fn is_fine(value: &Self::Value) -> bool {
327        Self::is_fine(value)
328    }
329
330    fn get_ref(&self) -> &Self::Value {
331        self.get_ref()
332    }
333
334    fn get(self) -> Self::Value
335    where
336        Self::Value: Sized,
337    {
338        self.get()
339    }
340
341    fn checked_ref(value: &Self::Value) -> RecoverableRefinementRef<'_, Self> {
342        Self::checked_ref(value)
343    }
344
345    fn checked(value: Self::Value) -> RecoverableRefinement<Self>
346    where
347        Self::Value: Sized,
348    {
349        Self::checked(value)
350    }
351}
352
353/// Extends any type `T` to allow refining its values with `R` implementing [`Refining<Value = T>`].
354pub trait Refine {
355    /// Refines the given value with `R` by reference.
356    ///
357    /// This is the same as calling [`R::checked_ref`] on `Self` reference.
358    ///
359    /// # Errors
360    ///
361    /// See [`checked_ref`].
362    ///
363    /// [`R::checked_ref`]: Refining::checked_ref
364    /// [`checked_ref`]: Refining::checked_ref
365    fn refine_ref<R: Refining<Value = Self> + ?Sized>(&self) -> RecoverableRefinementRef<'_, R> {
366        R::checked_ref(self)
367    }
368
369    /// Refines the given value with `R`.
370    ///
371    /// This is the same as calling [`R::checked`] on `Self` value.
372    ///
373    /// # Errors
374    ///
375    /// See [`checked`].
376    ///
377    /// [`R::checked`]: Refining::checked
378    /// [`checked`]: Refining::checked
379    fn refine<R: Refining<Value = Self>>(self) -> RecoverableRefinement<R>
380    where
381        Self: Sized,
382    {
383        R::checked(self)
384    }
385}
386
387impl<T: ?Sized> Refine for T {}