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