facet_core/impls_core/
scalar.rs

1use crate::value_vtable;
2use crate::*;
3use core::num::NonZero;
4use typeid::ConstTypeId;
5
6unsafe impl Facet<'_> for ConstTypeId {
7    const VTABLE: &'static ValueVTable =
8        &const { value_vtable!(ConstTypeId, |f, _opts| write!(f, "ConstTypeId")) };
9
10    const SHAPE: &'static Shape = &const {
11        Shape::builder_for_sized::<Self>()
12            .def(Def::Scalar(
13                ScalarDef::builder()
14                    .affinity(ScalarAffinity::opaque().build())
15                    .build(),
16            ))
17            .ty(Type::User(UserType::Struct(StructType {
18                repr: Repr::c(),
19                kind: StructKind::Struct,
20                fields: &const { [field_in_type!(ConstTypeId, type_id_fn)] },
21            })))
22            .build()
23    };
24}
25
26unsafe impl Facet<'_> for core::any::TypeId {
27    const VTABLE: &'static ValueVTable =
28        &const { value_vtable!(core::any::TypeId, |f, _opts| write!(f, "TypeId")) };
29
30    const SHAPE: &'static Shape = &const {
31        Shape::builder_for_sized::<Self>()
32            .def(Def::Scalar(
33                ScalarDef::builder()
34                    .affinity(ScalarAffinity::opaque().build())
35                    .build(),
36            ))
37            .ty(Type::User(UserType::Opaque))
38            .build()
39    };
40}
41
42unsafe impl Facet<'_> for () {
43    const VTABLE: &'static ValueVTable = &const { value_vtable!((), |f, _opts| write!(f, "()")) };
44
45    const SHAPE: &'static Shape = &const {
46        Shape::builder_for_sized::<Self>()
47            .def(Def::Scalar(
48                ScalarDef::builder()
49                    .affinity(ScalarAffinity::empty().build())
50                    .build(),
51            ))
52            .ty(Type::Sequence(SequenceType::Tuple(TupleType {
53                fields: &[],
54            })))
55            .build()
56    };
57}
58
59unsafe impl<'a, T: ?Sized + 'a> Facet<'a> for core::marker::PhantomData<T> {
60    // TODO: we might be able to do something with specialization re: the shape of T?
61    const VTABLE: &'static ValueVTable =
62        &const { value_vtable!((), |f, _opts| write!(f, "PhantomData")) };
63
64    const SHAPE: &'static Shape = &const {
65        Shape::builder_for_sized::<Self>()
66            .def(Def::Scalar(
67                ScalarDef::builder()
68                    .affinity(ScalarAffinity::empty().build())
69                    .build(),
70            ))
71            .ty(Type::User(UserType::Struct(StructType {
72                repr: Repr::default(),
73                kind: StructKind::Unit,
74                fields: &[],
75            })))
76            .build()
77    };
78}
79
80unsafe impl Facet<'_> for char {
81    const VTABLE: &'static ValueVTable =
82        &const { value_vtable!(char, |f, _opts| write!(f, "char")) };
83
84    const SHAPE: &'static Shape = &const {
85        Shape::builder_for_sized::<Self>()
86            .def(Def::Scalar(
87                ScalarDef::builder()
88                    .affinity(ScalarAffinity::char().build())
89                    .build(),
90            ))
91            .ty(Type::Primitive(PrimitiveType::Textual(TextualType::Char)))
92            .build()
93    };
94}
95
96unsafe impl Facet<'_> for str {
97    // Intentionally &str, since str is a DST.
98    const VTABLE: &'static ValueVTable =
99        &const { value_vtable!(&str, |f, _opts| write!(f, "str")) };
100
101    const SHAPE: &'static Shape = &const {
102        Shape::builder_for_unsized::<Self>()
103            .ty(Type::Primitive(PrimitiveType::Textual(TextualType::Str)))
104            .def(Def::Scalar(
105                ScalarDef::builder()
106                    .affinity(ScalarAffinity::string().build())
107                    .build(),
108            ))
109            .build()
110    };
111}
112
113unsafe impl Facet<'_> for bool {
114    const VTABLE: &'static ValueVTable =
115        &const { value_vtable!(bool, |f, _opts| write!(f, "bool")) };
116
117    const SHAPE: &'static Shape = &const {
118        Shape::builder_for_sized::<Self>()
119            .def(Def::Scalar(
120                ScalarDef::builder()
121                    .affinity(ScalarAffinity::boolean().build())
122                    .build(),
123            ))
124            .ty(Type::Primitive(PrimitiveType::Boolean))
125            .build()
126    };
127}
128
129macro_rules! impl_facet_for_integer {
130    ($type:ty, $affinity:expr, $nz_affinity:expr) => {
131        unsafe impl<'a> Facet<'a> for $type {
132            const VTABLE: &'static ValueVTable = &const {
133                let mut vtable =
134                    value_vtable!($type, |f, _opts| write!(f, "{}", stringify!($type)));
135
136                vtable.try_from = Some(|source, source_shape, dest| {
137                    if source_shape == Self::SHAPE {
138                        return Ok(unsafe { dest.copy_from(source, source_shape)? });
139                    }
140                    if source_shape == u64::SHAPE {
141                        let value: u64 = *unsafe { source.get::<u64>() };
142                        match <$type>::try_from(value) {
143                            Ok(converted) => {
144                                return Ok(unsafe { dest.put::<$type>(converted) });
145                            }
146                            Err(_) => {
147                                return Err(TryFromError::Generic("conversion from u64 failed"));
148                            }
149                        }
150                    }
151                    if source_shape == u32::SHAPE {
152                        let value: u32 = *unsafe { source.get::<u32>() };
153                        let value: u64 = value as u64;
154                        match <$type>::try_from(value) {
155                            Ok(converted) => {
156                                return Ok(unsafe { dest.put::<$type>(converted) });
157                            }
158                            Err(_) => {
159                                return Err(TryFromError::Generic("conversion from u32 failed"));
160                            }
161                        }
162                    }
163                    if source_shape == u16::SHAPE {
164                        let value: u16 = *unsafe { source.get::<u16>() };
165                        let value: u64 = value as u64;
166                        match <$type>::try_from(value) {
167                            Ok(converted) => {
168                                return Ok(unsafe { dest.put::<$type>(converted) });
169                            }
170                            Err(_) => {
171                                return Err(TryFromError::Generic("conversion from u16 failed"));
172                            }
173                        }
174                    }
175                    if source_shape == u8::SHAPE {
176                        let value: u8 = *unsafe { source.get::<u8>() };
177                        let value: u64 = value as u64;
178                        match <$type>::try_from(value) {
179                            Ok(converted) => {
180                                return Ok(unsafe { dest.put::<$type>(converted) });
181                            }
182                            Err(_) => {
183                                return Err(TryFromError::Generic("conversion from u8 failed"));
184                            }
185                        }
186                    }
187                    if source_shape == i64::SHAPE {
188                        let value: i64 = *unsafe { source.get::<i64>() };
189                        match <$type>::try_from(value) {
190                            Ok(converted) => {
191                                return Ok(unsafe { dest.put::<$type>(converted) });
192                            }
193                            Err(_) => {
194                                return Err(TryFromError::Generic("conversion from i64 failed"));
195                            }
196                        }
197                    }
198                    if source_shape == i32::SHAPE {
199                        let value: i32 = *unsafe { source.get::<i32>() };
200                        let value: i64 = value as i64;
201                        match <$type>::try_from(value) {
202                            Ok(converted) => {
203                                return Ok(unsafe { dest.put::<$type>(converted) });
204                            }
205                            Err(_) => {
206                                return Err(TryFromError::Generic("conversion from i32 failed"));
207                            }
208                        }
209                    }
210                    if source_shape == i16::SHAPE {
211                        let value: i16 = *unsafe { source.get::<i16>() };
212                        let value: i64 = value as i64;
213                        match <$type>::try_from(value) {
214                            Ok(converted) => {
215                                return Ok(unsafe { dest.put::<$type>(converted) });
216                            }
217                            Err(_) => {
218                                return Err(TryFromError::Generic("conversion from i16 failed"));
219                            }
220                        }
221                    }
222                    if source_shape == i8::SHAPE {
223                        let value: i8 = *unsafe { source.get::<i8>() };
224                        let value: i64 = value as i64;
225                        match <$type>::try_from(value) {
226                            Ok(converted) => {
227                                return Ok(unsafe { dest.put::<$type>(converted) });
228                            }
229                            Err(_) => {
230                                return Err(TryFromError::Generic("conversion from i8 failed"));
231                            }
232                        }
233                    }
234                    if source_shape == f64::SHAPE {
235                        let value: f64 = *unsafe { source.get::<f64>() };
236                        let value = value as i64;
237                        match <$type>::try_from(value) {
238                            Ok(converted) => {
239                                return Ok(unsafe { dest.put::<$type>(converted) });
240                            }
241                            Err(_) => {
242                                return Err(TryFromError::Generic("conversion from f64 failed"));
243                            }
244                        }
245                    }
246                    if source_shape == f32::SHAPE {
247                        let value: f32 = *unsafe { source.get::<f32>() };
248                        let value = value as i64;
249                        match <$type>::try_from(value) {
250                            Ok(converted) => {
251                                return Ok(unsafe { dest.put::<$type>(converted) });
252                            }
253                            Err(_) => {
254                                return Err(TryFromError::Generic("conversion from f32 failed"));
255                            }
256                        }
257                    }
258                    Err(TryFromError::UnsupportedSourceShape {
259                        src_shape: source_shape,
260                        expected: &[Self::SHAPE, u64::SHAPE, i64::SHAPE, f64::SHAPE],
261                    })
262                });
263
264                vtable
265            };
266
267            const SHAPE: &'static Shape = &const {
268                Shape::builder_for_sized::<Self>()
269                    .ty(Type::Primitive(PrimitiveType::Numeric(
270                        NumericType::Integer {
271                            signed: (1 as $type).checked_neg().is_some(),
272                        },
273                    )))
274                    .def(Def::Scalar(
275                        ScalarDef::builder().affinity($affinity).build(),
276                    ))
277                    .build()
278            };
279        }
280
281        unsafe impl<'a> Facet<'a> for NonZero<$type> {
282            const VTABLE: &'static ValueVTable = &const {
283                // Define conversion functions for transparency
284                unsafe fn try_from<'dst>(
285                    src_ptr: PtrConst<'_>,
286                    src_shape: &'static Shape,
287                    dst: PtrUninit<'dst>,
288                ) -> Result<PtrMut<'dst>, TryFromError> {
289                    if src_shape == <$type as Facet>::SHAPE {
290                        // Get the inner value and check that it's non-zero
291                        let value = unsafe { *src_ptr.get::<$type>() };
292                        let nz = NonZero::new(value)
293                            .ok_or_else(|| TryFromError::Generic("value should be non-zero"))?;
294
295                        // Put the NonZero value into the destination
296                        Ok(unsafe { dst.put(nz) })
297                    } else {
298                        let inner_try_from = <$type as Facet>::SHAPE.vtable.try_from.ok_or(
299                            TryFromError::UnsupportedSourceShape {
300                                src_shape,
301                                expected: &[<$type as Facet>::SHAPE],
302                            },
303                        )?;
304
305                        // fallback to inner's try_from
306                        // This relies on the fact that `dst` is the same size as `NonZero<$type>`
307                        // which should be true because `NonZero` is `repr(transparent)`
308                        let inner_result = unsafe { (inner_try_from)(src_ptr, src_shape, dst) };
309                        match inner_result {
310                            Ok(result) => {
311                                // After conversion to inner type, wrap as NonZero
312                                let value = unsafe { *result.get::<$type>() };
313                                let nz = NonZero::new(value).ok_or_else(|| {
314                                    TryFromError::Generic("value should be non-zero")
315                                })?;
316                                Ok(unsafe { dst.put(nz) })
317                            }
318                            Err(e) => Err(e),
319                        }
320                    }
321                }
322
323                unsafe fn try_into_inner<'dst>(
324                    src_ptr: PtrMut<'_>,
325                    dst: PtrUninit<'dst>,
326                ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
327                    // Get the NonZero value and extract the inner value
328                    let nz = unsafe { *src_ptr.get::<NonZero<$type>>() };
329                    // Put the inner value into the destination
330                    Ok(unsafe { dst.put(nz.get()) })
331                }
332
333                unsafe fn try_borrow_inner(
334                    src_ptr: PtrConst<'_>,
335                ) -> Result<PtrConst<'_>, TryBorrowInnerError> {
336                    // NonZero<T> has the same memory layout as T, so we can return the input pointer directly
337                    Ok(src_ptr)
338                }
339
340                let mut vtable = value_vtable!($type, |f, _opts| write!(
341                    f,
342                    "NonZero<{}>",
343                    stringify!($type)
344                ));
345
346                // Keep existing try_from for compatibility
347                vtable.try_from = Some(|source, source_shape, dest| {
348                    if source_shape == Self::SHAPE {
349                        return Ok(unsafe { dest.copy_from(source, source_shape)? });
350                    }
351                    if source_shape == <$type>::SHAPE {
352                        let value: $type = *unsafe { source.get::<$type>() };
353                        let nz = NonZero::new(value)
354                            .ok_or_else(|| TryFromError::Generic("value must be non-zero"))?;
355                        return Ok(unsafe { dest.put::<NonZero<$type>>(nz) });
356                    }
357                    Err(TryFromError::UnsupportedSourceShape {
358                        src_shape: source_shape,
359                        expected: &[Self::SHAPE, <$type>::SHAPE],
360                    })
361                });
362
363                // Add our new transparency functions
364                vtable.try_from = Some(try_from);
365                vtable.try_into_inner = Some(try_into_inner);
366                vtable.try_borrow_inner = Some(try_borrow_inner);
367
368                vtable
369            };
370
371            const SHAPE: &'static Shape = &const {
372                // Function to return inner type's shape
373                fn inner_shape() -> &'static Shape {
374                    <$type as Facet>::SHAPE
375                }
376
377                Shape::builder_for_sized::<Self>()
378                    .def(Def::Scalar(
379                        ScalarDef::builder().affinity($nz_affinity).build(),
380                    ))
381                    .ty(Type::User(UserType::Struct(StructType {
382                        repr: Repr::transparent(),
383                        kind: StructKind::TupleStruct,
384                        fields: &const {
385                            [Field::builder()
386                                .name("0")
387                                // TODO: is it correct to represent $type here, when we, in
388                                // fact, store $type::NonZeroInner.
389                                .shape(<$type>::SHAPE)
390                                .offset(0)
391                                .flags(FieldFlags::EMPTY)
392                                .build()]
393                        },
394                    })))
395                    .inner(inner_shape)
396                    .build()
397            };
398        }
399    };
400}
401
402static MIN_U8: u8 = u8::MIN;
403static MAX_U8: u8 = u8::MAX;
404static MIN_NZ_U8: NonZero<u8> = NonZero::<u8>::MIN;
405static MAX_NZ_U8: NonZero<u8> = NonZero::<u8>::MAX;
406
407static MIN_I8: i8 = i8::MIN;
408static MAX_I8: i8 = i8::MAX;
409static MIN_NZ_I8: NonZero<i8> = NonZero::<i8>::MIN;
410static MAX_NZ_I8: NonZero<i8> = NonZero::<i8>::MAX;
411
412static MIN_U16: u16 = u16::MIN;
413static MAX_U16: u16 = u16::MAX;
414static MIN_NZ_U16: NonZero<u16> = NonZero::<u16>::MIN;
415static MAX_NZ_U16: NonZero<u16> = NonZero::<u16>::MAX;
416
417static MIN_I16: i16 = i16::MIN;
418static MAX_I16: i16 = i16::MAX;
419static MIN_NZ_I16: NonZero<i16> = NonZero::<i16>::MIN;
420static MAX_NZ_I16: NonZero<i16> = NonZero::<i16>::MAX;
421
422static MIN_U32: u32 = u32::MIN;
423static MAX_U32: u32 = u32::MAX;
424static MIN_NZ_U32: NonZero<u32> = NonZero::<u32>::MIN;
425static MAX_NZ_U32: NonZero<u32> = NonZero::<u32>::MAX;
426
427static MIN_I32: i32 = i32::MIN;
428static MAX_I32: i32 = i32::MAX;
429static MIN_NZ_I32: NonZero<i32> = NonZero::<i32>::MIN;
430static MAX_NZ_I32: NonZero<i32> = NonZero::<i32>::MAX;
431
432static MIN_U64: u64 = u64::MIN;
433static MAX_U64: u64 = u64::MAX;
434static MIN_NZ_U64: NonZero<u64> = NonZero::<u64>::MIN;
435static MAX_NZ_U64: NonZero<u64> = NonZero::<u64>::MAX;
436
437static MIN_I64: i64 = i64::MIN;
438static MAX_I64: i64 = i64::MAX;
439static MIN_NZ_I64: NonZero<i64> = NonZero::<i64>::MIN;
440static MAX_NZ_I64: NonZero<i64> = NonZero::<i64>::MAX;
441
442static MIN_U128: u128 = u128::MIN;
443static MAX_U128: u128 = u128::MAX;
444static MIN_NZ_U128: NonZero<u128> = NonZero::<u128>::MIN;
445static MAX_NZ_U128: NonZero<u128> = NonZero::<u128>::MAX;
446
447static MIN_I128: i128 = i128::MIN;
448static MAX_I128: i128 = i128::MAX;
449static MIN_NZ_I128: NonZero<i128> = NonZero::<i128>::MIN;
450static MAX_NZ_I128: NonZero<i128> = NonZero::<i128>::MAX;
451
452static MIN_USIZE: usize = usize::MIN;
453static MAX_USIZE: usize = usize::MAX;
454static MIN_NZ_USIZE: NonZero<usize> = NonZero::<usize>::MIN;
455static MAX_NZ_USIZE: NonZero<usize> = NonZero::<usize>::MAX;
456
457static MIN_ISIZE: isize = isize::MIN;
458static MAX_ISIZE: isize = isize::MAX;
459static MIN_NZ_ISIZE: NonZero<isize> = NonZero::<isize>::MIN;
460static MAX_NZ_ISIZE: NonZero<isize> = NonZero::<isize>::MAX;
461
462impl_facet_for_integer!(
463    u8,
464    ScalarAffinity::number()
465        .unsigned_integer(8)
466        .min(PtrConst::new(&raw const MIN_U8))
467        .max(PtrConst::new(&raw const MAX_U8))
468        .build(),
469    ScalarAffinity::number()
470        .unsigned_integer(8)
471        .min(PtrConst::new(&raw const MIN_NZ_U8))
472        .max(PtrConst::new(&raw const MAX_NZ_U8))
473        .build()
474);
475
476impl_facet_for_integer!(
477    i8,
478    ScalarAffinity::number()
479        .signed_integer(8)
480        .min(PtrConst::new(&raw const MIN_I8))
481        .max(PtrConst::new(&raw const MAX_I8))
482        .build(),
483    ScalarAffinity::number()
484        .signed_integer(8)
485        .min(PtrConst::new(&raw const MIN_NZ_I8))
486        .max(PtrConst::new(&raw const MAX_NZ_I8))
487        .build()
488);
489
490impl_facet_for_integer!(
491    u16,
492    ScalarAffinity::number()
493        .unsigned_integer(16)
494        .min(PtrConst::new(&raw const MIN_U16))
495        .max(PtrConst::new(&raw const MAX_U16))
496        .build(),
497    ScalarAffinity::number()
498        .unsigned_integer(16)
499        .min(PtrConst::new(&raw const MIN_NZ_U16))
500        .max(PtrConst::new(&raw const MAX_NZ_U16))
501        .build()
502);
503
504impl_facet_for_integer!(
505    i16,
506    ScalarAffinity::number()
507        .signed_integer(16)
508        .min(PtrConst::new(&raw const MIN_I16))
509        .max(PtrConst::new(&raw const MAX_I16))
510        .build(),
511    ScalarAffinity::number()
512        .signed_integer(16)
513        .min(PtrConst::new(&raw const MIN_NZ_I16))
514        .max(PtrConst::new(&raw const MAX_NZ_I16))
515        .build()
516);
517
518impl_facet_for_integer!(
519    u32,
520    ScalarAffinity::number()
521        .unsigned_integer(32)
522        .min(PtrConst::new(&raw const MIN_U32))
523        .max(PtrConst::new(&raw const MAX_U32))
524        .build(),
525    ScalarAffinity::number()
526        .unsigned_integer(32)
527        .min(PtrConst::new(&raw const MIN_NZ_U32))
528        .max(PtrConst::new(&raw const MAX_NZ_U32))
529        .build()
530);
531
532impl_facet_for_integer!(
533    i32,
534    ScalarAffinity::number()
535        .signed_integer(32)
536        .min(PtrConst::new(&raw const MIN_I32))
537        .max(PtrConst::new(&raw const MAX_I32))
538        .build(),
539    ScalarAffinity::number()
540        .signed_integer(32)
541        .min(PtrConst::new(&raw const MIN_NZ_I32))
542        .max(PtrConst::new(&raw const MAX_NZ_I32))
543        .build()
544);
545
546impl_facet_for_integer!(
547    u64,
548    ScalarAffinity::number()
549        .unsigned_integer(64)
550        .min(PtrConst::new(&raw const MIN_U64))
551        .max(PtrConst::new(&raw const MAX_U64))
552        .build(),
553    ScalarAffinity::number()
554        .unsigned_integer(64)
555        .min(PtrConst::new(&raw const MIN_NZ_U64))
556        .max(PtrConst::new(&raw const MAX_NZ_U64))
557        .build()
558);
559
560impl_facet_for_integer!(
561    i64,
562    ScalarAffinity::number()
563        .signed_integer(64)
564        .min(PtrConst::new(&raw const MIN_I64))
565        .max(PtrConst::new(&raw const MAX_I64))
566        .build(),
567    ScalarAffinity::number()
568        .signed_integer(64)
569        .min(PtrConst::new(&raw const MIN_NZ_I64))
570        .max(PtrConst::new(&raw const MAX_NZ_I64))
571        .build()
572);
573
574impl_facet_for_integer!(
575    u128,
576    ScalarAffinity::number()
577        .unsigned_integer(128)
578        .min(PtrConst::new(&raw const MIN_U128))
579        .max(PtrConst::new(&raw const MAX_U128))
580        .build(),
581    ScalarAffinity::number()
582        .unsigned_integer(128)
583        .min(PtrConst::new(&raw const MIN_NZ_U128))
584        .max(PtrConst::new(&raw const MAX_NZ_U128))
585        .build()
586);
587
588impl_facet_for_integer!(
589    i128,
590    ScalarAffinity::number()
591        .signed_integer(128)
592        .min(PtrConst::new(&raw const MIN_I128))
593        .max(PtrConst::new(&raw const MAX_I128))
594        .build(),
595    ScalarAffinity::number()
596        .signed_integer(128)
597        .min(PtrConst::new(&raw const MIN_NZ_I128))
598        .max(PtrConst::new(&raw const MAX_NZ_I128))
599        .build()
600);
601
602impl_facet_for_integer!(
603    usize,
604    ScalarAffinity::number()
605        .unsigned_integer(core::mem::size_of::<usize>() * 8)
606        .min(PtrConst::new(&raw const MIN_USIZE))
607        .max(PtrConst::new(&raw const MAX_USIZE))
608        .build(),
609    ScalarAffinity::number()
610        .unsigned_integer(core::mem::size_of::<usize>() * 8)
611        .min(PtrConst::new(&raw const MIN_NZ_USIZE))
612        .max(PtrConst::new(&raw const MAX_NZ_USIZE))
613        .build()
614);
615
616impl_facet_for_integer!(
617    isize,
618    ScalarAffinity::number()
619        .signed_integer(core::mem::size_of::<isize>() * 8)
620        .min(PtrConst::new(&raw const MIN_ISIZE))
621        .max(PtrConst::new(&raw const MAX_ISIZE))
622        .build(),
623    ScalarAffinity::number()
624        .signed_integer(core::mem::size_of::<isize>() * 8)
625        .min(PtrConst::new(&raw const MIN_NZ_ISIZE))
626        .max(PtrConst::new(&raw const MAX_NZ_ISIZE))
627        .build()
628);
629
630// Constants for f32
631static MIN_F32: f32 = f32::MIN;
632static MAX_F32: f32 = f32::MAX;
633static POSITIVE_INFINITY_F32: f32 = f32::INFINITY;
634static NEGATIVE_INFINITY_F32: f32 = f32::NEG_INFINITY;
635static NAN_F32: f32 = f32::NAN;
636static POSITIVE_ZERO_F32: f32 = 0.0f32;
637static NEGATIVE_ZERO_F32: f32 = -0.0f32;
638static EPSILON_F32: f32 = f32::EPSILON;
639
640// Constants for f64
641static MIN_F64: f64 = f64::MIN;
642static MAX_F64: f64 = f64::MAX;
643static POSITIVE_INFINITY_F64: f64 = f64::INFINITY;
644static NEGATIVE_INFINITY_F64: f64 = f64::NEG_INFINITY;
645static NAN_F64: f64 = f64::NAN;
646static POSITIVE_ZERO_F64: f64 = 0.0f64;
647static NEGATIVE_ZERO_F64: f64 = -0.0f64;
648static EPSILON_F64: f64 = f64::EPSILON;
649
650unsafe impl Facet<'_> for f32 {
651    const VTABLE: &'static ValueVTable = &const {
652        let mut vtable = value_vtable!(f32, |f, _opts| write!(f, "f32"));
653
654        vtable.try_from = Some(|source, source_shape, dest| {
655            if source_shape == Self::SHAPE {
656                return Ok(unsafe { dest.copy_from(source, source_shape)? });
657            }
658            if source_shape == u64::SHAPE {
659                let value: u64 = *unsafe { source.get::<u64>() };
660                let converted: f32 = value as f32;
661                return Ok(unsafe { dest.put::<f32>(converted) });
662            }
663            if source_shape == i64::SHAPE {
664                let value: i64 = *unsafe { source.get::<i64>() };
665                let converted: f32 = value as f32;
666                return Ok(unsafe { dest.put::<f32>(converted) });
667            }
668            if source_shape == f64::SHAPE {
669                let value: f64 = *unsafe { source.get::<f64>() };
670                let converted: f32 = value as f32;
671                return Ok(unsafe { dest.put::<f32>(converted) });
672            }
673            Err(TryFromError::UnsupportedSourceShape {
674                src_shape: source_shape,
675                expected: &[Self::SHAPE, u64::SHAPE, i64::SHAPE, f64::SHAPE],
676            })
677        });
678
679        vtable
680    };
681
682    const SHAPE: &'static Shape = &const {
683        Shape::builder_for_sized::<Self>()
684            .ty(Type::Primitive(PrimitiveType::Numeric(NumericType::Float)))
685            .def(Def::Scalar(
686                ScalarDef::builder()
687                    .affinity(
688                        ScalarAffinity::number()
689                            .float(1, 8, f32::MANTISSA_DIGITS as usize - 1, false)
690                            .min(PtrConst::new(&raw const MIN_F32))
691                            .max(PtrConst::new(&raw const MAX_F32))
692                            .positive_infinity(PtrConst::new(&raw const POSITIVE_INFINITY_F32))
693                            .negative_infinity(PtrConst::new(&raw const NEGATIVE_INFINITY_F32))
694                            .nan_sample(PtrConst::new(&raw const NAN_F32))
695                            .positive_zero(PtrConst::new(&raw const POSITIVE_ZERO_F32))
696                            .negative_zero(PtrConst::new(&raw const NEGATIVE_ZERO_F32))
697                            .epsilon(PtrConst::new(&raw const EPSILON_F32))
698                            .build(),
699                    )
700                    .build(),
701            ))
702            .build()
703    };
704}
705
706unsafe impl Facet<'_> for f64 {
707    const VTABLE: &'static ValueVTable = &const {
708        let mut vtable = value_vtable!(f64, |f, _opts| write!(f, "f64"));
709
710        vtable.try_from = Some(|source, source_shape, dest| {
711            if source_shape == Self::SHAPE {
712                return Ok(unsafe { dest.copy_from(source, source_shape)? });
713            }
714            if source_shape == u64::SHAPE {
715                let value: u64 = *unsafe { source.get::<u64>() };
716                let converted: f64 = value as f64;
717                return Ok(unsafe { dest.put::<f64>(converted) });
718            }
719            if source_shape == i64::SHAPE {
720                let value: i64 = *unsafe { source.get::<i64>() };
721                let converted: f64 = value as f64;
722                return Ok(unsafe { dest.put::<f64>(converted) });
723            }
724            if source_shape == f32::SHAPE {
725                let value: f32 = *unsafe { source.get::<f32>() };
726                let converted: f64 = value as f64;
727                return Ok(unsafe { dest.put::<f64>(converted) });
728            }
729            Err(TryFromError::UnsupportedSourceShape {
730                src_shape: source_shape,
731                expected: &[Self::SHAPE, u64::SHAPE, i64::SHAPE, f32::SHAPE],
732            })
733        });
734
735        vtable
736    };
737
738    const SHAPE: &'static Shape = &const {
739        Shape::builder_for_sized::<Self>()
740            .ty(Type::Primitive(PrimitiveType::Numeric(NumericType::Float)))
741            .def(Def::Scalar(
742                ScalarDef::builder()
743                    .affinity(
744                        ScalarAffinity::number()
745                            .float(1, 11, f64::MANTISSA_DIGITS as usize - 1, false)
746                            .min(PtrConst::new(&raw const MIN_F64))
747                            .max(PtrConst::new(&raw const MAX_F64))
748                            .positive_infinity(PtrConst::new(&raw const POSITIVE_INFINITY_F64))
749                            .negative_infinity(PtrConst::new(&raw const NEGATIVE_INFINITY_F64))
750                            .nan_sample(PtrConst::new(&raw const NAN_F64))
751                            .positive_zero(PtrConst::new(&raw const POSITIVE_ZERO_F64))
752                            .negative_zero(PtrConst::new(&raw const NEGATIVE_ZERO_F64))
753                            .epsilon(PtrConst::new(&raw const EPSILON_F64))
754                            .build(),
755                    )
756                    .build(),
757            ))
758            .build()
759    };
760}
761
762unsafe impl Facet<'_> for core::net::SocketAddr {
763    const VTABLE: &'static ValueVTable =
764        &const { value_vtable!(core::net::SocketAddr, |f, _opts| write!(f, "SocketAddr")) };
765
766    const SHAPE: &'static Shape = &const {
767        Shape::builder_for_sized::<Self>()
768            .ty(Type::User(UserType::Opaque))
769            .def(Def::Scalar(
770                ScalarDef::builder()
771                    .affinity(ScalarAffinity::socket_addr().build())
772                    .build(),
773            ))
774            .build()
775    };
776}
777
778unsafe impl Facet<'_> for core::net::IpAddr {
779    const VTABLE: &'static ValueVTable =
780        &const { value_vtable!(core::net::IpAddr, |f, _opts| write!(f, "IpAddr")) };
781
782    const SHAPE: &'static Shape = &const {
783        Shape::builder_for_sized::<Self>()
784            .ty(Type::User(UserType::Opaque))
785            .def(Def::Scalar(
786                ScalarDef::builder()
787                    .affinity(ScalarAffinity::ip_addr().build())
788                    .build(),
789            ))
790            .build()
791    };
792}
793
794unsafe impl Facet<'_> for core::net::Ipv4Addr {
795    const VTABLE: &'static ValueVTable =
796        &const { value_vtable!(core::net::Ipv4Addr, |f, _opts| write!(f, "Ipv4Addr")) };
797
798    const SHAPE: &'static Shape = &const {
799        Shape::builder_for_sized::<Self>()
800            .ty(Type::User(UserType::Opaque))
801            .def(Def::Scalar(
802                ScalarDef::builder()
803                    .affinity(ScalarAffinity::ip_addr().build())
804                    .build(),
805            ))
806            .build()
807    };
808}
809
810unsafe impl Facet<'_> for core::net::Ipv6Addr {
811    const VTABLE: &'static ValueVTable =
812        &const { value_vtable!(core::net::Ipv6Addr, |f, _opts| write!(f, "Ipv6Addr")) };
813
814    const SHAPE: &'static Shape = &const {
815        Shape::builder_for_sized::<Self>()
816            .ty(Type::User(UserType::Opaque))
817            .def(Def::Scalar(
818                ScalarDef::builder()
819                    .affinity(ScalarAffinity::ip_addr().build())
820                    .build(),
821            ))
822            .build()
823    };
824}