facet_core/impls_core/
scalar.rs

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