• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 20059345204

09 Dec 2025 09:57AM UTC coverage: 58.683% (-0.4%) from 59.082%
20059345204

push

github

fasterthanlime
Refactor VTable system: Direct/Indirect styles, OxRef/OxMut, builder patterns

Major architectural refactor of the facet vtable system for better code sharing
and reduced binary bloat.

- Remove ThinPtr/WidePtr in favor of PtrConst<'a>/PtrMut<'a>/PtrUninit<'a>
- Add OxRef<'a>/OxMut<'a> - shaped pointers bundling ptr + shape
- Add Ox<'a> enum for ownership tracking (like Cow for shaped pointers)

- VTableDirect: for concrete types, uses raw *const ()/*mut (), returns T directly
- VTableIndirect: for generic containers, uses OxRef/OxMut, returns Option<T>
- VTableErased enum wraps both styles
- Shape::call_* helpers dispatch to either style transparently

- vtable_direct! macro for sized types with compile-time known traits
- VTableIndirect::builder() for generic containers with runtime dispatch
- All container vtables (Array, Option, Result, List, Map, Set) use builders
- No more positional arguments - named builder methods only

- Hash trait is generic over H: Hasher, can't store directly in vtable
- HashProxy type-erases the hasher for vtable storage
- Enables hash support without wrapper function bloat

- impls_core/impls_alloc/impls_std -> impls/core/alloc/std/crates
- New internal/ module for facet's own types (Shape, Def, etc.)
- Cleaner separation of concerns

- Copy, Send, Sync, Eq, Unpin stored as bitflags on Shape
- Set via ShapeBuilder methods: .copy(), .send(), .sync(), .eq()

- ThinPtr -> *const () or PtrConst<'a>
- WidePtr -> OxRef<'a> or OxMut<'a>
- vtable_ref! -> vtable_direct! or VTableIndirect::builder()
- ValueVTable -> VTableDirect or VTableIndirect
- Closures in vtables -> named fn items

WIP: Some impl modules still need migration to new API.

4092 of 8007 new or added lines in 112 files covered. (51.11%)

117 existing lines in 26 files now uncovered.

26173 of 44601 relevant lines covered (58.68%)

635.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/facet-core/src/impls/alloc/string.rs
1
use crate::{
2
    Def, Facet, Shape, ShapeBuilder, Type, TypeOpsDirect, UserType, VTableDirect, type_ops_direct,
3
    vtable_direct,
4
};
5

6
// TypeOps lifted out - shared static
7
static STRING_TYPE_OPS: TypeOpsDirect = type_ops_direct!(alloc::string::String => Default, Clone);
8

9
unsafe impl Facet<'_> for alloc::string::String {
10
    // String implements: Display, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, FromStr
11
    const SHAPE: &'static Shape = &const {
12
        const VTABLE: VTableDirect = vtable_direct!(alloc::string::String =>
13
            FromStr,
14
            Display,
15
            Debug,
16
            Hash,
17
            PartialEq,
18
            PartialOrd,
19
            Ord,
20
        );
21

22
        ShapeBuilder::for_sized::<alloc::string::String>("String")
23
            .ty(Type::User(UserType::Opaque))
24
            .def(Def::Scalar)
25
            .vtable_direct(&VTABLE)
26
            .type_ops_direct(&STRING_TYPE_OPS)
27
            .eq()
28
            .send()
29
            .sync()
30
            .build()
31
    };
32
}
33

34
#[cfg(test)]
35
mod tests {
36
    use core::ptr::NonNull;
37

38
    use crate::Facet;
39
    use alloc::string::String;
40

41
    #[test]
42
    fn test_string_has_parse() {
1✔
43
        // Check that String has a parse function in its vtable
44
        let shape = String::SHAPE;
1✔
45
        assert!(
1✔
46
            shape.vtable.has_parse(),
1✔
47
            "String should have parse function"
48
        );
49
    }
1✔
50

51
    #[test]
52
    fn test_string_parse() {
1✔
53
        // Test that we can parse a string into a String
54
        let shape = String::SHAPE;
1✔
55

56
        // Allocate memory for the String
57
        let layout = shape.layout.sized_layout().unwrap();
1✔
58
        let ptr = unsafe { alloc::alloc::alloc(layout) };
1✔
59
        let Some(ptr) = NonNull::new(ptr) else {
1✔
NEW
60
            alloc::alloc::handle_alloc_error(layout)
×
61
        };
62
        let ptr_mut = crate::PtrMut::new(ptr.as_ptr());
1✔
63

64
        // Parse the string using the new API
65
        let result = unsafe { shape.call_parse("hello world", ptr_mut) };
1✔
66
        assert!(result.is_some(), "String should have parse function");
1✔
67
        assert!(result.unwrap().is_ok());
1✔
68

69
        // Get the parsed value
70
        let parsed = unsafe { ptr_mut.get::<String>() };
1✔
71
        assert_eq!(parsed, &String::from("hello world"));
1✔
72

73
        // Clean up
74
        unsafe {
1✔
75
            shape.call_drop_in_place(ptr_mut).unwrap();
1✔
76
            alloc::alloc::dealloc(ptr.as_ptr(), layout);
1✔
77
        }
1✔
78
    }
1✔
79
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc