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                parse_bytes: None,
59                try_from: None,
60                try_into_inner: None,
61                try_borrow_inner: None,
62                partial_eq: None,
63                partial_cmp: None,
64                cmp: None,
65            }
66        }
67
68        const fn build_type_ops<Idx>() -> TypeOpsIndirect {
69            TypeOpsIndirect {
70                drop_in_place: range_drop::<Idx>,
71                default_in_place: None,
72                clone_into: None,
73                is_truthy: None,
74            }
75        }
76
77        ShapeBuilder::for_sized::<core::ops::Range<Idx>>("Range")
78            .ty(Type::User(UserType::Struct(StructType {
79                kind: crate::StructKind::Struct,
80                repr: crate::Repr::default(),
81                fields: &const {
82                    [
83                        FieldBuilder::new(
84                            "start",
85                            crate::shape_of::<Idx>,
86                            core::mem::offset_of!(core::ops::Range<Idx>, start),
87                        )
88                        .build(),
89                        FieldBuilder::new(
90                            "end",
91                            crate::shape_of::<Idx>,
92                            core::mem::offset_of!(core::ops::Range<Idx>, end),
93                        )
94                        .build(),
95                    ]
96                },
97            })))
98            .def(Def::Scalar)
99            .type_params(&[TypeParam {
100                name: "Idx",
101                shape: Idx::SHAPE,
102            }])
103            .vtable_indirect(&const { build_vtable::<Idx>() })
104            .type_ops_indirect(&const { build_type_ops::<Idx>() })
105            .build()
106    };
107}