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