facet_core/impls_alloc/
string.rs

1use crate::{Def, Facet, Shape, Type, UserType, ValueVTable, value_vtable};
2use alloc::string::ToString;
3
4#[cfg(feature = "alloc")]
5unsafe impl Facet<'_> for alloc::string::String {
6    const VTABLE: &'static ValueVTable = &const {
7        let mut vtable = value_vtable!(alloc::string::String, |f, _opts| write!(
8            f,
9            "{}",
10            Self::SHAPE.type_identifier
11        ));
12
13        let vtable_sized = vtable.sized_mut().unwrap();
14        vtable_sized.parse = || {
15            Some(|s, target| {
16                // For String, parsing from a string is just copying the string
17                Ok(unsafe { target.put(s.to_string()) })
18            })
19        };
20
21        vtable
22    };
23
24    const SHAPE: &'static Shape = &const {
25        Shape::builder_for_sized::<Self>()
26            .def(Def::Scalar)
27            .type_identifier("String")
28            .ty(Type::User(UserType::Opaque))
29            .build()
30    };
31}
32
33unsafe impl<'a> Facet<'a> for alloc::borrow::Cow<'a, str> {
34    const VTABLE: &'static ValueVTable = &const {
35        value_vtable!(alloc::borrow::Cow<'_, str>, |f, _opts| write!(
36            f,
37            "Cow<'_, str>"
38        ))
39    };
40
41    const SHAPE: &'static Shape = &const {
42        Shape::builder_for_sized::<Self>()
43            .def(Def::Scalar)
44            .type_identifier("Cow")
45            .ty(Type::User(UserType::Opaque))
46            .build()
47    };
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::Facet;
53    use crate::ptr::PtrUninit;
54    use alloc::string::String;
55
56    #[test]
57    fn test_string_has_parse() {
58        // Check that String has a parse function in its vtable
59        let shape = String::SHAPE;
60        assert!(
61            shape.vtable.has_parse(),
62            "String should have parse function"
63        );
64    }
65
66    #[test]
67    fn test_string_parse() {
68        // Test that we can parse a string into a String
69        let shape = String::SHAPE;
70        let parse_fn = (shape.vtable.sized().unwrap().parse)().unwrap();
71
72        // Allocate memory for the String
73        let layout = shape.layout.sized_layout().unwrap();
74        let ptr = unsafe { alloc::alloc::alloc(layout) };
75        let uninit = PtrUninit::new(ptr);
76
77        // Parse the string
78        let result = unsafe { parse_fn("hello world", uninit) };
79        assert!(result.is_ok());
80
81        // Get the parsed value
82        let ptr_mut = result.unwrap();
83        let parsed = unsafe { ptr_mut.get::<String>() };
84        assert_eq!(parsed, &String::from("hello world"));
85
86        // Clean up
87        unsafe {
88            ptr_mut.drop_in_place::<String>();
89            alloc::alloc::dealloc(ptr, layout);
90        }
91    }
92}