facet_core/impls/core/
ops.rs

1use crate::{
2    Def, Facet, FieldBuilder, OxPtrConst, OxPtrMut, Shape, ShapeBuilder, StructType, Type,
3    TypeOpsIndirect, TypeParam, UserType, VTableIndirect,
4};
5
6/// Debug for `Range<Idx>`
7unsafe fn range_debug<Idx>(
8    ox: OxPtrConst,
9    f: &mut core::fmt::Formatter<'_>,
10) -> Option<core::fmt::Result> {
11    let this = unsafe { ox.get::<core::ops::Range<Idx>>() };
12
13    Some((|| {
14        let fields = match &ox.shape().ty {
15            Type::User(UserType::Struct(s)) => &s.fields,
16            _ => return Err(core::fmt::Error),
17        };
18
19        let start_shape = fields[0].shape.get();
20        let end_shape = fields[1].shape.get();
21
22        let start_ptr = crate::PtrConst::new(&this.start);
23        if let Some(result) = unsafe { start_shape.call_debug(start_ptr, f) } {
24            result?;
25        } else {
26            return Err(core::fmt::Error);
27        }
28
29        write!(f, "..")?;
30
31        let end_ptr = crate::PtrConst::new(&this.end);
32        if let Some(result) = unsafe { end_shape.call_debug(end_ptr, f) } {
33            result?;
34        } else {
35            return Err(core::fmt::Error);
36        }
37
38        Ok(())
39    })())
40}
41
42/// Drop for `Range<Idx>`
43unsafe fn range_drop<Idx>(ox: OxPtrMut) {
44    unsafe {
45        core::ptr::drop_in_place(ox.ptr().as_byte_ptr() as *mut core::ops::Range<Idx>);
46    }
47}
48
49unsafe impl<'a, Idx: Facet<'a>> Facet<'a> for core::ops::Range<Idx> {
50    const SHAPE: &'static Shape = &const {
51        const fn build_vtable<Idx>() -> VTableIndirect {
52            VTableIndirect {
53                display: None,
54                debug: Some(range_debug::<Idx>),
55                hash: None,
56                invariants: None,
57                parse: None,
58                try_from: None,
59                try_into_inner: None,
60                try_borrow_inner: None,
61                partial_eq: None,
62                partial_cmp: None,
63                cmp: None,
64            }
65        }
66
67        const fn build_type_ops<Idx>() -> TypeOpsIndirect {
68            TypeOpsIndirect {
69                drop_in_place: range_drop::<Idx>,
70                default_in_place: None,
71                clone_into: None,
72                is_truthy: None,
73            }
74        }
75
76        ShapeBuilder::for_sized::<core::ops::Range<Idx>>("Range")
77            .ty(Type::User(UserType::Struct(StructType {
78                kind: crate::StructKind::Struct,
79                repr: crate::Repr::default(),
80                fields: &const {
81                    [
82                        FieldBuilder::new(
83                            "start",
84                            crate::shape_of::<Idx>,
85                            core::mem::offset_of!(core::ops::Range<Idx>, start),
86                        )
87                        .build(),
88                        FieldBuilder::new(
89                            "end",
90                            crate::shape_of::<Idx>,
91                            core::mem::offset_of!(core::ops::Range<Idx>, end),
92                        )
93                        .build(),
94                    ]
95                },
96            })))
97            .def(Def::Scalar)
98            .type_params(&[TypeParam {
99                name: "Idx",
100                shape: Idx::SHAPE,
101            }])
102            .vtable_indirect(&const { build_vtable::<Idx>() })
103            .type_ops_indirect(&const { build_type_ops::<Idx>() })
104            .build()
105    };
106}