1use 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#[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 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
103pub type RecoverableRefinement<R> =
105 Recoverable<R, <R as Refining>::Predicate, <R as Refining>::Context, <R as Refining>::Value>;
106
107pub 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
116pub trait Refining: Deref<Target = Self::Value> + sealed::Sealed {
120 type Value: ?Sized;
122
123 type Predicate: Predicate<Self::Value> + ?Sized;
125
126 type Context: TypeStr + ?Sized;
128
129 unsafe fn unchecked_ref(value: &Self::Value) -> &Self;
139
140 unsafe fn unchecked(value: Self::Value) -> Self
150 where
151 Self::Value: Sized;
152
153 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 fn is_fine(value: &Self::Value) -> bool {
176 Self::Predicate::check(value)
177 }
178
179 fn get_ref(&self) -> &Self::Value;
181
182 fn get(self) -> Self::Value
184 where
185 Self::Value: Sized;
186
187 fn checked_ref(value: &Self::Value) -> RecoverableRefinementRef<'_, Self>;
194
195 fn checked(value: Self::Value) -> RecoverableRefinement<Self>
202 where
203 Self::Value: Sized,
204 Self: Sized;
205
206 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 pub const unsafe fn unchecked_ref(value: &T) -> &Self {
231 unsafe { transmute(value) }
234 }
235
236 #[allow(clippy::missing_const_for_fn)] 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 pub const fn get_ref_no_assert(&self) -> &T {
259 &self.value
260 }
261
262 pub fn is_fine(value: &T) -> bool {
268 P::check(value)
269 }
270
271 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 pub const unsafe fn unchecked(value: T) -> Self {
297 Self {
298 predicate: PhantomData,
299 context: PhantomData,
300 value,
301 }
302 }
303
304 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 pub fn get_no_assert(self) -> T {
326 self.value
327 }
328
329 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 pub unsafe fn unchecked_default() -> Self {
355 unsafe { Self::unchecked(T::default()) }
356 }
357
358 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
418pub trait Refine {
420 fn refine_ref<R: Refining<Value = Self> + ?Sized>(&self) -> RecoverableRefinementRef<'_, R> {
431 R::checked_ref(self)
432 }
433
434 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 {}