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<'static> = &const {
11        Shape::builder_for_sized::<Self>()
12            .def(Def::Scalar(
13                ScalarDef::builder()
14                    .affinity(&const { 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<'static> = &const {
31        Shape::builder_for_sized::<Self>()
32            .def(Def::Scalar(
33                ScalarDef::builder()
34                    .affinity(&const { 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<'static> = &const {
46        Shape::builder_for_sized::<Self>()
47            .def(Def::Scalar(
48                ScalarDef::builder()
49                    .affinity(&const { 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<'static> = &const {
65        Shape::builder_for_sized::<Self>()
66            .def(Def::Scalar(
67                ScalarDef::builder()
68                    .affinity(&const { 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<'static> = &const {
85        Shape::builder_for_sized::<Self>()
86            .def(Def::Scalar(
87                ScalarDef::builder()
88                    .affinity(&const { 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<'static> = &const {
102        Shape::builder_for_unsized::<Self>()
103            .ty(Type::Primitive(PrimitiveType::Textual(TextualType::Str)))
104            .def(Def::Scalar(
105                ScalarDef::builder()
106                    .affinity(&const { 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<'static> = &const {
118        Shape::builder_for_sized::<Self>()
119            .def(Def::Scalar(
120                ScalarDef::builder()
121                    .affinity(&const { 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<'static> = &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<'shape, 'dst>(
285                    src_ptr: PtrConst<'_>,
286                    src_shape: &'shape Shape<'shape>,
287                    dst: PtrUninit<'dst>,
288                ) -> Result<PtrMut<'dst>, TryFromError<'shape>> {
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                // Add our new transparency functions
347                vtable.try_from = Some(try_from);
348                vtable.try_into_inner = Some(try_into_inner);
349                vtable.try_borrow_inner = Some(try_borrow_inner);
350
351                vtable
352            };
353
354            const SHAPE: &'static Shape<'static> = &const {
355                // Function to return inner type's shape
356                fn inner_shape() -> &'static Shape<'static> {
357                    <$type as Facet>::SHAPE
358                }
359
360                Shape::builder_for_sized::<Self>()
361                    .def(Def::Scalar(
362                        ScalarDef::builder().affinity($nz_affinity).build(),
363                    ))
364                    .ty(Type::User(UserType::Struct(StructType {
365                        repr: Repr::transparent(),
366                        kind: StructKind::TupleStruct,
367                        fields: &const {
368                            [Field::builder()
369                                .name("0")
370                                // TODO: is it correct to represent $type here, when we, in
371                                // fact, store $type::NonZeroInner.
372                                .shape(<$type>::SHAPE)
373                                .offset(0)
374                                .flags(FieldFlags::EMPTY)
375                                .build()]
376                        },
377                    })))
378                    .inner(inner_shape)
379                    .build()
380            };
381        }
382    };
383}
384
385static MIN_U8: u8 = u8::MIN;
386static MAX_U8: u8 = u8::MAX;
387static MIN_NZ_U8: NonZero<u8> = NonZero::<u8>::MIN;
388static MAX_NZ_U8: NonZero<u8> = NonZero::<u8>::MAX;
389
390static MIN_I8: i8 = i8::MIN;
391static MAX_I8: i8 = i8::MAX;
392static MIN_NZ_I8: NonZero<i8> = NonZero::<i8>::MIN;
393static MAX_NZ_I8: NonZero<i8> = NonZero::<i8>::MAX;
394
395static MIN_U16: u16 = u16::MIN;
396static MAX_U16: u16 = u16::MAX;
397static MIN_NZ_U16: NonZero<u16> = NonZero::<u16>::MIN;
398static MAX_NZ_U16: NonZero<u16> = NonZero::<u16>::MAX;
399
400static MIN_I16: i16 = i16::MIN;
401static MAX_I16: i16 = i16::MAX;
402static MIN_NZ_I16: NonZero<i16> = NonZero::<i16>::MIN;
403static MAX_NZ_I16: NonZero<i16> = NonZero::<i16>::MAX;
404
405static MIN_U32: u32 = u32::MIN;
406static MAX_U32: u32 = u32::MAX;
407static MIN_NZ_U32: NonZero<u32> = NonZero::<u32>::MIN;
408static MAX_NZ_U32: NonZero<u32> = NonZero::<u32>::MAX;
409
410static MIN_I32: i32 = i32::MIN;
411static MAX_I32: i32 = i32::MAX;
412static MIN_NZ_I32: NonZero<i32> = NonZero::<i32>::MIN;
413static MAX_NZ_I32: NonZero<i32> = NonZero::<i32>::MAX;
414
415static MIN_U64: u64 = u64::MIN;
416static MAX_U64: u64 = u64::MAX;
417static MIN_NZ_U64: NonZero<u64> = NonZero::<u64>::MIN;
418static MAX_NZ_U64: NonZero<u64> = NonZero::<u64>::MAX;
419
420static MIN_I64: i64 = i64::MIN;
421static MAX_I64: i64 = i64::MAX;
422static MIN_NZ_I64: NonZero<i64> = NonZero::<i64>::MIN;
423static MAX_NZ_I64: NonZero<i64> = NonZero::<i64>::MAX;
424
425static MIN_U128: u128 = u128::MIN;
426static MAX_U128: u128 = u128::MAX;
427static MIN_NZ_U128: NonZero<u128> = NonZero::<u128>::MIN;
428static MAX_NZ_U128: NonZero<u128> = NonZero::<u128>::MAX;
429
430static MIN_I128: i128 = i128::MIN;
431static MAX_I128: i128 = i128::MAX;
432static MIN_NZ_I128: NonZero<i128> = NonZero::<i128>::MIN;
433static MAX_NZ_I128: NonZero<i128> = NonZero::<i128>::MAX;
434
435static MIN_USIZE: usize = usize::MIN;
436static MAX_USIZE: usize = usize::MAX;
437static MIN_NZ_USIZE: NonZero<usize> = NonZero::<usize>::MIN;
438static MAX_NZ_USIZE: NonZero<usize> = NonZero::<usize>::MAX;
439
440static MIN_ISIZE: isize = isize::MIN;
441static MAX_ISIZE: isize = isize::MAX;
442static MIN_NZ_ISIZE: NonZero<isize> = NonZero::<isize>::MIN;
443static MAX_NZ_ISIZE: NonZero<isize> = NonZero::<isize>::MAX;
444
445impl_facet_for_integer!(
446    u8,
447    &const {
448        ScalarAffinity::number()
449            .unsigned_integer(8)
450            .min(PtrConst::new(&raw const MIN_U8))
451            .max(PtrConst::new(&raw const MAX_U8))
452            .build()
453    },
454    &const {
455        ScalarAffinity::number()
456            .unsigned_integer(8)
457            .min(PtrConst::new(&raw const MIN_NZ_U8))
458            .max(PtrConst::new(&raw const MAX_NZ_U8))
459            .build()
460    }
461);
462
463impl_facet_for_integer!(
464    i8,
465    &const {
466        ScalarAffinity::number()
467            .signed_integer(8)
468            .min(PtrConst::new(&raw const MIN_I8))
469            .max(PtrConst::new(&raw const MAX_I8))
470            .build()
471    },
472    &const {
473        ScalarAffinity::number()
474            .signed_integer(8)
475            .min(PtrConst::new(&raw const MIN_NZ_I8))
476            .max(PtrConst::new(&raw const MAX_NZ_I8))
477            .build()
478    }
479);
480
481impl_facet_for_integer!(
482    u16,
483    &const {
484        ScalarAffinity::number()
485            .unsigned_integer(16)
486            .min(PtrConst::new(&raw const MIN_U16))
487            .max(PtrConst::new(&raw const MAX_U16))
488            .build()
489    },
490    &const {
491        ScalarAffinity::number()
492            .unsigned_integer(16)
493            .min(PtrConst::new(&raw const MIN_NZ_U16))
494            .max(PtrConst::new(&raw const MAX_NZ_U16))
495            .build()
496    }
497);
498
499impl_facet_for_integer!(
500    i16,
501    &const {
502        ScalarAffinity::number()
503            .signed_integer(16)
504            .min(PtrConst::new(&raw const MIN_I16))
505            .max(PtrConst::new(&raw const MAX_I16))
506            .build()
507    },
508    &const {
509        ScalarAffinity::number()
510            .signed_integer(16)
511            .min(PtrConst::new(&raw const MIN_NZ_I16))
512            .max(PtrConst::new(&raw const MAX_NZ_I16))
513            .build()
514    }
515);
516
517impl_facet_for_integer!(
518    u32,
519    &const {
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    },
526    &const {
527        ScalarAffinity::number()
528            .unsigned_integer(32)
529            .min(PtrConst::new(&raw const MIN_NZ_U32))
530            .max(PtrConst::new(&raw const MAX_NZ_U32))
531            .build()
532    }
533);
534
535impl_facet_for_integer!(
536    i32,
537    &const {
538        ScalarAffinity::number()
539            .signed_integer(32)
540            .min(PtrConst::new(&raw const MIN_I32))
541            .max(PtrConst::new(&raw const MAX_I32))
542            .build()
543    },
544    &const {
545        ScalarAffinity::number()
546            .signed_integer(32)
547            .min(PtrConst::new(&raw const MIN_NZ_I32))
548            .max(PtrConst::new(&raw const MAX_NZ_I32))
549            .build()
550    }
551);
552
553impl_facet_for_integer!(
554    u64,
555    &const {
556        ScalarAffinity::number()
557            .unsigned_integer(64)
558            .min(PtrConst::new(&raw const MIN_U64))
559            .max(PtrConst::new(&raw const MAX_U64))
560            .build()
561    },
562    &const {
563        ScalarAffinity::number()
564            .unsigned_integer(64)
565            .min(PtrConst::new(&raw const MIN_NZ_U64))
566            .max(PtrConst::new(&raw const MAX_NZ_U64))
567            .build()
568    }
569);
570
571impl_facet_for_integer!(
572    i64,
573    &const {
574        ScalarAffinity::number()
575            .signed_integer(64)
576            .min(PtrConst::new(&raw const MIN_I64))
577            .max(PtrConst::new(&raw const MAX_I64))
578            .build()
579    },
580    &const {
581        ScalarAffinity::number()
582            .signed_integer(64)
583            .min(PtrConst::new(&raw const MIN_NZ_I64))
584            .max(PtrConst::new(&raw const MAX_NZ_I64))
585            .build()
586    }
587);
588
589impl_facet_for_integer!(
590    u128,
591    &const {
592        ScalarAffinity::number()
593            .unsigned_integer(128)
594            .min(PtrConst::new(&raw const MIN_U128))
595            .max(PtrConst::new(&raw const MAX_U128))
596            .build()
597    },
598    &const {
599        ScalarAffinity::number()
600            .unsigned_integer(128)
601            .min(PtrConst::new(&raw const MIN_NZ_U128))
602            .max(PtrConst::new(&raw const MAX_NZ_U128))
603            .build()
604    }
605);
606
607impl_facet_for_integer!(
608    i128,
609    &const {
610        ScalarAffinity::number()
611            .signed_integer(128)
612            .min(PtrConst::new(&raw const MIN_I128))
613            .max(PtrConst::new(&raw const MAX_I128))
614            .build()
615    },
616    &const {
617        ScalarAffinity::number()
618            .signed_integer(128)
619            .min(PtrConst::new(&raw const MIN_NZ_I128))
620            .max(PtrConst::new(&raw const MAX_NZ_I128))
621            .build()
622    }
623);
624
625impl_facet_for_integer!(
626    usize,
627    &const {
628        ScalarAffinity::number()
629            .unsigned_integer(core::mem::size_of::<usize>() * 8)
630            .min(PtrConst::new(&raw const MIN_USIZE))
631            .max(PtrConst::new(&raw const MAX_USIZE))
632            .build()
633    },
634    &const {
635        ScalarAffinity::number()
636            .unsigned_integer(core::mem::size_of::<usize>() * 8)
637            .min(PtrConst::new(&raw const MIN_NZ_USIZE))
638            .max(PtrConst::new(&raw const MAX_NZ_USIZE))
639            .build()
640    }
641);
642
643impl_facet_for_integer!(
644    isize,
645    &const {
646        ScalarAffinity::number()
647            .signed_integer(core::mem::size_of::<isize>() * 8)
648            .min(PtrConst::new(&raw const MIN_ISIZE))
649            .max(PtrConst::new(&raw const MAX_ISIZE))
650            .build()
651    },
652    &const {
653        ScalarAffinity::number()
654            .signed_integer(core::mem::size_of::<isize>() * 8)
655            .min(PtrConst::new(&raw const MIN_NZ_ISIZE))
656            .max(PtrConst::new(&raw const MAX_NZ_ISIZE))
657            .build()
658    }
659);
660// Constants for f32
661static MIN_F32: f32 = f32::MIN;
662static MAX_F32: f32 = f32::MAX;
663static POSITIVE_INFINITY_F32: f32 = f32::INFINITY;
664static NEGATIVE_INFINITY_F32: f32 = f32::NEG_INFINITY;
665static NAN_F32: f32 = f32::NAN;
666static POSITIVE_ZERO_F32: f32 = 0.0f32;
667static NEGATIVE_ZERO_F32: f32 = -0.0f32;
668static EPSILON_F32: f32 = f32::EPSILON;
669
670// Constants for f64
671static MIN_F64: f64 = f64::MIN;
672static MAX_F64: f64 = f64::MAX;
673static POSITIVE_INFINITY_F64: f64 = f64::INFINITY;
674static NEGATIVE_INFINITY_F64: f64 = f64::NEG_INFINITY;
675static NAN_F64: f64 = f64::NAN;
676static POSITIVE_ZERO_F64: f64 = 0.0f64;
677static NEGATIVE_ZERO_F64: f64 = -0.0f64;
678static EPSILON_F64: f64 = f64::EPSILON;
679
680unsafe impl Facet<'_> for f32 {
681    const VTABLE: &'static ValueVTable = &const {
682        let mut vtable = value_vtable!(f32, |f, _opts| write!(f, "f32"));
683
684        vtable.try_from = Some(|source, source_shape, dest| {
685            if source_shape == Self::SHAPE {
686                return Ok(unsafe { dest.copy_from(source, source_shape)? });
687            }
688            if source_shape == u64::SHAPE {
689                let value: u64 = *unsafe { source.get::<u64>() };
690                let converted: f32 = value as f32;
691                return Ok(unsafe { dest.put::<f32>(converted) });
692            }
693            if source_shape == i64::SHAPE {
694                let value: i64 = *unsafe { source.get::<i64>() };
695                let converted: f32 = value as f32;
696                return Ok(unsafe { dest.put::<f32>(converted) });
697            }
698            if source_shape == f64::SHAPE {
699                let value: f64 = *unsafe { source.get::<f64>() };
700                let converted: f32 = value as f32;
701                return Ok(unsafe { dest.put::<f32>(converted) });
702            }
703            Err(TryFromError::UnsupportedSourceShape {
704                src_shape: source_shape,
705                expected: &[Self::SHAPE, u64::SHAPE, i64::SHAPE, f64::SHAPE],
706            })
707        });
708
709        vtable
710    };
711
712    const SHAPE: &'static Shape<'static> = &const {
713        Shape::builder_for_sized::<Self>()
714            .ty(Type::Primitive(PrimitiveType::Numeric(NumericType::Float)))
715            .def(Def::Scalar(
716                ScalarDef::builder()
717                    .affinity(
718                        &const {
719                            ScalarAffinity::number()
720                                .float(1, 8, f32::MANTISSA_DIGITS as usize - 1, false)
721                                .min(PtrConst::new(&raw const MIN_F32))
722                                .max(PtrConst::new(&raw const MAX_F32))
723                                .positive_infinity(PtrConst::new(&raw const POSITIVE_INFINITY_F32))
724                                .negative_infinity(PtrConst::new(&raw const NEGATIVE_INFINITY_F32))
725                                .nan_sample(PtrConst::new(&raw const NAN_F32))
726                                .positive_zero(PtrConst::new(&raw const POSITIVE_ZERO_F32))
727                                .negative_zero(PtrConst::new(&raw const NEGATIVE_ZERO_F32))
728                                .epsilon(PtrConst::new(&raw const EPSILON_F32))
729                                .build()
730                        },
731                    )
732                    .build(),
733            ))
734            .build()
735    };
736}
737
738unsafe impl Facet<'_> for f64 {
739    const VTABLE: &'static ValueVTable = &const {
740        let mut vtable = value_vtable!(f64, |f, _opts| write!(f, "f64"));
741
742        vtable.try_from = Some(|source, source_shape, dest| {
743            if source_shape == Self::SHAPE {
744                return Ok(unsafe { dest.copy_from(source, source_shape)? });
745            }
746            if source_shape == u64::SHAPE {
747                let value: u64 = *unsafe { source.get::<u64>() };
748                let converted: f64 = value as f64;
749                return Ok(unsafe { dest.put::<f64>(converted) });
750            }
751            if source_shape == i64::SHAPE {
752                let value: i64 = *unsafe { source.get::<i64>() };
753                let converted: f64 = value as f64;
754                return Ok(unsafe { dest.put::<f64>(converted) });
755            }
756            if source_shape == f32::SHAPE {
757                let value: f32 = *unsafe { source.get::<f32>() };
758                let converted: f64 = value as f64;
759                return Ok(unsafe { dest.put::<f64>(converted) });
760            }
761            Err(TryFromError::UnsupportedSourceShape {
762                src_shape: source_shape,
763                expected: &[Self::SHAPE, u64::SHAPE, i64::SHAPE, f32::SHAPE],
764            })
765        });
766
767        vtable
768    };
769
770    const SHAPE: &'static Shape<'static> = &const {
771        Shape::builder_for_sized::<Self>()
772            .ty(Type::Primitive(PrimitiveType::Numeric(NumericType::Float)))
773            .def(Def::Scalar(
774                ScalarDef::builder()
775                    .affinity(
776                        &const {
777                            ScalarAffinity::number()
778                                .float(1, 11, f64::MANTISSA_DIGITS as usize - 1, false)
779                                .min(PtrConst::new(&raw const MIN_F64))
780                                .max(PtrConst::new(&raw const MAX_F64))
781                                .positive_infinity(PtrConst::new(&raw const POSITIVE_INFINITY_F64))
782                                .negative_infinity(PtrConst::new(&raw const NEGATIVE_INFINITY_F64))
783                                .nan_sample(PtrConst::new(&raw const NAN_F64))
784                                .positive_zero(PtrConst::new(&raw const POSITIVE_ZERO_F64))
785                                .negative_zero(PtrConst::new(&raw const NEGATIVE_ZERO_F64))
786                                .epsilon(PtrConst::new(&raw const EPSILON_F64))
787                                .build()
788                        },
789                    )
790                    .build(),
791            ))
792            .build()
793    };
794}
795
796unsafe impl Facet<'_> for core::net::SocketAddr {
797    const VTABLE: &'static ValueVTable =
798        &const { value_vtable!(core::net::SocketAddr, |f, _opts| write!(f, "SocketAddr")) };
799
800    const SHAPE: &'static Shape<'static> = &const {
801        Shape::builder_for_sized::<Self>()
802            .ty(Type::User(UserType::Opaque))
803            .def(Def::Scalar(
804                ScalarDef::builder()
805                    .affinity(&const { ScalarAffinity::socket_addr().build() })
806                    .build(),
807            ))
808            .build()
809    };
810}
811
812unsafe impl Facet<'_> for core::net::IpAddr {
813    const VTABLE: &'static ValueVTable =
814        &const { value_vtable!(core::net::IpAddr, |f, _opts| write!(f, "IpAddr")) };
815
816    const SHAPE: &'static Shape<'static> = &const {
817        Shape::builder_for_sized::<Self>()
818            .ty(Type::User(UserType::Opaque))
819            .def(Def::Scalar(
820                ScalarDef::builder()
821                    .affinity(&const { ScalarAffinity::ip_addr().build() })
822                    .build(),
823            ))
824            .build()
825    };
826}
827
828unsafe impl Facet<'_> for core::net::Ipv4Addr {
829    const VTABLE: &'static ValueVTable =
830        &const { value_vtable!(core::net::Ipv4Addr, |f, _opts| write!(f, "Ipv4Addr")) };
831
832    const SHAPE: &'static Shape<'static> = &const {
833        Shape::builder_for_sized::<Self>()
834            .ty(Type::User(UserType::Opaque))
835            .def(Def::Scalar(
836                ScalarDef::builder()
837                    .affinity(&const { ScalarAffinity::ip_addr().build() })
838                    .build(),
839            ))
840            .build()
841    };
842}
843
844unsafe impl Facet<'_> for core::net::Ipv6Addr {
845    const VTABLE: &'static ValueVTable =
846        &const { value_vtable!(core::net::Ipv6Addr, |f, _opts| write!(f, "Ipv6Addr")) };
847
848    const SHAPE: &'static Shape<'static> = &const {
849        Shape::builder_for_sized::<Self>()
850            .ty(Type::User(UserType::Opaque))
851            .def(Def::Scalar(
852                ScalarDef::builder()
853                    .affinity(&const { ScalarAffinity::ip_addr().build() })
854                    .build(),
855            ))
856            .build()
857    };
858}