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 SHAPE: &'static Shape = &const {
8        Shape::builder_for_sized::<Self>()
9            .vtable(value_vtable!(ConstTypeId, |f, _opts| write!(
10                f,
11                "{}",
12                Self::SHAPE.type_identifier
13            )))
14            .type_identifier("ConstTypeId")
15            .def(Def::Scalar)
16            .ty(Type::User(UserType::Opaque))
17            .build()
18    };
19}
20
21unsafe impl Facet<'_> for core::any::TypeId {
22    const SHAPE: &'static Shape = &const {
23        Shape::builder_for_sized::<Self>()
24            .vtable(value_vtable!(core::any::TypeId, |f, _opts| write!(
25                f,
26                "{}",
27                Self::SHAPE.type_identifier
28            )))
29            .type_identifier("TypeId")
30            .def(Def::Scalar)
31            .ty(Type::User(UserType::Opaque))
32            .build()
33    };
34}
35
36unsafe impl Facet<'_> for () {
37    const SHAPE: &'static Shape = &const {
38        Shape::builder_for_sized::<Self>()
39            .vtable(value_vtable!((), |f, _opts| write!(f, "()")))
40            .type_identifier("()")
41            .ty(Type::User(UserType::Struct(StructType {
42                repr: Repr::default(),
43                kind: StructKind::Tuple,
44                fields: &[],
45            })))
46            .build()
47    };
48}
49
50unsafe impl<'a, T: ?Sized + 'a> Facet<'a> for core::marker::PhantomData<T> {
51    const SHAPE: &'static Shape = &const {
52        Shape::builder_for_sized::<Self>()
53            // TODO: we might be able to do something with specialization re: the shape of T?
54            .vtable(value_vtable!((), |f, _opts| write!(
55                f,
56                "{}",
57                Self::SHAPE.type_identifier
58            )))
59            .type_identifier("PhantomData")
60            .def(Def::Scalar)
61            .ty(Type::User(UserType::Struct(StructType {
62                repr: Repr::default(),
63                kind: StructKind::Unit,
64                fields: &[],
65            })))
66            .build()
67    };
68}
69
70unsafe impl Facet<'_> for char {
71    const SHAPE: &'static Shape = &const {
72        Shape::builder_for_sized::<Self>()
73            .vtable(value_vtable!(char, |f, _opts| write!(
74                f,
75                "{}",
76                Self::SHAPE.type_identifier
77            )))
78            .type_identifier("char")
79            .def(Def::Scalar)
80            .ty(Type::Primitive(PrimitiveType::Textual(TextualType::Char)))
81            .build()
82    };
83}
84
85unsafe impl Facet<'_> for str {
86    const SHAPE: &'static Shape = &const {
87        Shape::builder_for_unsized::<Self>()
88            .vtable(value_vtable!(str, |f, _opts| write!(
89                f,
90                "{}",
91                Self::SHAPE.type_identifier
92            )))
93            .type_identifier("str")
94            .ty(Type::Primitive(PrimitiveType::Textual(TextualType::Str)))
95            .def(Def::Scalar)
96            .build()
97    };
98}
99
100unsafe impl Facet<'_> for bool {
101    const SHAPE: &'static Shape = &const {
102        Shape::builder_for_sized::<Self>()
103            .vtable(value_vtable!(bool, |f, _opts| write!(
104                f,
105                "{}",
106                Self::SHAPE.type_identifier
107            )))
108            .type_identifier("bool")
109            .def(Def::Scalar)
110            .ty(Type::Primitive(PrimitiveType::Boolean))
111            .build()
112    };
113}
114
115macro_rules! impl_facet_for_integer {
116    ($type:ty) => {
117        unsafe impl<'a> Facet<'a> for $type {
118            const SHAPE: &'static Shape = &const {
119                Shape::builder_for_sized::<Self>()
120                    .vtable(value_vtable!($type, |f, _opts| write!(
121                        f,
122                        "{}",
123                        Self::SHAPE.type_identifier
124                    )))
125                    .type_identifier(stringify!($type))
126                    .ty(Type::Primitive(PrimitiveType::Numeric(
127                        NumericType::Integer {
128                            signed: (1 as $type).checked_neg().is_some(),
129                        },
130                    )))
131                    .def(Def::Scalar)
132                    .build()
133            };
134        }
135
136        unsafe impl<'a> Facet<'a> for NonZero<$type> {
137            const SHAPE: &'static Shape = &const {
138                Shape::builder_for_sized::<Self>()
139                    .vtable({
140                        // Define conversion functions for transparency
141                        unsafe fn try_from<'dst>(
142                            src_ptr: PtrConst<'_>,
143                            src_shape: &'static Shape,
144                            dst: PtrUninit<'dst>,
145                        ) -> Result<PtrMut<'dst>, TryFromError> {
146                            if src_shape == <$type as Facet>::SHAPE {
147                                // Get the inner value and check that it's non-zero
148                                let value = unsafe { *src_ptr.get::<$type>() };
149                                let nz = NonZero::new(value).ok_or_else(|| {
150                                    TryFromError::Generic("value should be non-zero")
151                                })?;
152
153                                // Put the NonZero value into the destination
154                                Ok(unsafe { dst.put(nz) })
155                            } else {
156                                let inner_try_from = <$type as Facet>::SHAPE
157                                    .vtable
158                                    .try_from
159                                    .ok_or(TryFromError::UnsupportedSourceShape {
160                                        src_shape,
161                                        expected: &[<$type as Facet>::SHAPE],
162                                    })?;
163
164                                // fallback to inner's try_from
165                                // This relies on the fact that `dst` is the same size as `NonZero<$type>`
166                                // which should be true because `NonZero` is `repr(transparent)`
167                                let inner_result =
168                                    unsafe { (inner_try_from)(src_ptr, src_shape, dst) };
169                                match inner_result {
170                                    Ok(result) => {
171                                        // After conversion to inner type, wrap as NonZero
172                                        let value = unsafe { *result.get::<$type>() };
173                                        let nz = NonZero::new(value).ok_or_else(|| {
174                                            TryFromError::Generic("value should be non-zero")
175                                        })?;
176                                        Ok(unsafe { dst.put(nz) })
177                                    }
178                                    Err(e) => Err(e),
179                                }
180                            }
181                        }
182
183                        unsafe fn try_into_inner<'dst>(
184                            src_ptr: PtrMut<'_>,
185                            dst: PtrUninit<'dst>,
186                        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
187                            // Get the NonZero value and extract the inner value
188                            let nz = unsafe { *src_ptr.get::<NonZero<$type>>() };
189                            // Put the inner value into the destination
190                            Ok(unsafe { dst.put(nz.get()) })
191                        }
192
193                        unsafe fn try_borrow_inner(
194                            src_ptr: PtrConst<'_>,
195                        ) -> Result<PtrConst<'_>, TryBorrowInnerError> {
196                            // NonZero<T> has the same memory layout as T, so we can return the input pointer directly
197                            Ok(src_ptr)
198                        }
199
200                        let mut vtable = value_vtable!($type, |f, _opts| write!(
201                            f,
202                            "{}<{}>",
203                            Self::SHAPE.type_identifier,
204                            stringify!($type)
205                        ));
206
207                        // Add our new transparency functions
208                        {
209                            vtable.try_from = Some(try_from);
210                            vtable.try_into_inner = Some(try_into_inner);
211                            vtable.try_borrow_inner = Some(try_borrow_inner);
212                        }
213
214                        vtable
215                    })
216                    .type_identifier("NonZero")
217                    .def(Def::Scalar)
218                    .ty(Type::User(UserType::Struct(StructType {
219                        repr: Repr::transparent(),
220                        kind: StructKind::TupleStruct,
221                        fields: &const {
222                            [Field::builder()
223                                .name("0")
224                                // TODO: is it correct to represent $type here, when we, in
225                                // fact, store $type::NonZeroInner.
226                                .shape(|| <$type>::SHAPE)
227                                .offset(0)
228                                .flags(FieldFlags::EMPTY)
229                                .build()]
230                        },
231                    })))
232                    .inner(<$type as Facet>::SHAPE)
233                    .build()
234            };
235        }
236    };
237}
238
239impl_facet_for_integer!(u8);
240impl_facet_for_integer!(i8);
241impl_facet_for_integer!(u16);
242impl_facet_for_integer!(i16);
243impl_facet_for_integer!(u32);
244impl_facet_for_integer!(i32);
245impl_facet_for_integer!(u64);
246impl_facet_for_integer!(i64);
247impl_facet_for_integer!(u128);
248impl_facet_for_integer!(i128);
249impl_facet_for_integer!(usize);
250impl_facet_for_integer!(isize);
251
252unsafe impl Facet<'_> for f32 {
253    const SHAPE: &'static Shape = &const {
254        Shape::builder_for_sized::<Self>()
255            .vtable(value_vtable!(f32, |f, _opts| write!(
256                f,
257                "{}",
258                Self::SHAPE.type_identifier
259            )))
260            .type_identifier("f32")
261            .ty(Type::Primitive(PrimitiveType::Numeric(NumericType::Float)))
262            .def(Def::Scalar)
263            .build()
264    };
265}
266
267unsafe impl Facet<'_> for f64 {
268    const SHAPE: &'static Shape = &const {
269        Shape::builder_for_sized::<Self>()
270            .vtable({
271                let mut vtable =
272                    value_vtable!(f64, |f, _opts| write!(f, "{}", Self::SHAPE.type_identifier));
273
274                {
275                    vtable.try_from = Some(|source, source_shape, dest| {
276                        if source_shape == Self::SHAPE {
277                            return Ok(unsafe { dest.copy_from(source, source_shape)? });
278                        }
279                        if source_shape == u64::SHAPE {
280                            let value: u64 = *unsafe { source.get::<u64>() };
281                            let converted: f64 = value as f64;
282                            return Ok(unsafe { dest.put::<f64>(converted) });
283                        }
284                        if source_shape == i64::SHAPE {
285                            let value: i64 = *unsafe { source.get::<i64>() };
286                            let converted: f64 = value as f64;
287                            return Ok(unsafe { dest.put::<f64>(converted) });
288                        }
289                        if source_shape == f32::SHAPE {
290                            let value: f32 = *unsafe { source.get::<f32>() };
291                            let converted: f64 = value as f64;
292                            return Ok(unsafe { dest.put::<f64>(converted) });
293                        }
294                        Err(TryFromError::UnsupportedSourceShape {
295                            src_shape: source_shape,
296                            expected: &[Self::SHAPE, u64::SHAPE, i64::SHAPE, f32::SHAPE],
297                        })
298                    });
299                }
300
301                vtable
302            })
303            .type_identifier("f64")
304            .ty(Type::Primitive(PrimitiveType::Numeric(NumericType::Float)))
305            .def(Def::Scalar)
306            .build()
307    };
308}
309
310unsafe impl Facet<'_> for core::net::SocketAddr {
311    const SHAPE: &'static Shape = &const {
312        Shape::builder_for_sized::<Self>()
313            .vtable(value_vtable!(core::net::SocketAddr, |f, _opts| write!(
314                f,
315                "{}",
316                Self::SHAPE.type_identifier
317            )))
318            .type_identifier("SocketAddr")
319            .ty(Type::User(UserType::Opaque))
320            .def(Def::Scalar)
321            .build()
322    };
323}
324
325unsafe impl Facet<'_> for core::net::IpAddr {
326    const SHAPE: &'static Shape = &const {
327        Shape::builder_for_sized::<Self>()
328            .vtable(value_vtable!(core::net::IpAddr, |f, _opts| write!(
329                f,
330                "{}",
331                Self::SHAPE.type_identifier
332            )))
333            .type_identifier("IpAddr")
334            .ty(Type::User(UserType::Opaque))
335            .def(Def::Scalar)
336            .build()
337    };
338}
339
340unsafe impl Facet<'_> for core::net::Ipv4Addr {
341    const SHAPE: &'static Shape = &const {
342        Shape::builder_for_sized::<Self>()
343            .vtable(value_vtable!(core::net::Ipv4Addr, |f, _opts| write!(
344                f,
345                "{}",
346                Self::SHAPE.type_identifier
347            )))
348            .type_identifier("Ipv4Addr")
349            .ty(Type::User(UserType::Opaque))
350            .def(Def::Scalar)
351            .build()
352    };
353}
354
355unsafe impl Facet<'_> for core::net::Ipv6Addr {
356    const SHAPE: &'static Shape = &const {
357        Shape::builder_for_sized::<Self>()
358            .vtable(value_vtable!(core::net::Ipv6Addr, |f, _opts| write!(
359                f,
360                "{}",
361                Self::SHAPE.type_identifier
362            )))
363            .type_identifier("Ipv6Addr")
364            .ty(Type::User(UserType::Opaque))
365            .def(Def::Scalar)
366            .build()
367    };
368}