facet_dom/
raw_markup.rs

1//! Raw markup capture type.
2
3use std::ops::Deref;
4
5use facet_core::{OxPtrConst, OxPtrUninit, ParseError, PtrConst, TryFromOutcome, VTableIndirect};
6
7/// A string containing raw markup captured verbatim from the source.
8///
9/// When deserializing, if the parser supports raw capture, the entire
10/// element (including tags) is captured as-is instead of being parsed.
11#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
12pub struct RawMarkup(pub String);
13
14unsafe fn display_raw_markup(
15    source: OxPtrConst,
16    f: &mut core::fmt::Formatter<'_>,
17) -> Option<core::fmt::Result> {
18    let rm = unsafe { source.get::<RawMarkup>() };
19    Some(write!(f, "{}", rm.0))
20}
21
22unsafe fn try_from_raw_markup(
23    target: OxPtrUninit,
24    src_shape: &'static facet_core::Shape,
25    src: PtrConst,
26) -> TryFromOutcome {
27    // Handle &str
28    if src_shape.id == <&str as facet_core::Facet>::SHAPE.id {
29        let s: &str = unsafe { src.get::<&str>() };
30        unsafe { target.put(RawMarkup(s.to_owned())) };
31        TryFromOutcome::Converted
32    }
33    // Handle String
34    else if src_shape.id == <String as facet_core::Facet>::SHAPE.id {
35        let s = unsafe { src.read::<String>() };
36        unsafe { target.put(RawMarkup(s)) };
37        TryFromOutcome::Converted
38    } else {
39        TryFromOutcome::Unsupported
40    }
41}
42
43unsafe fn parse_raw_markup(s: &str, target: OxPtrUninit) -> Option<Result<(), ParseError>> {
44    unsafe { target.put(RawMarkup(s.to_owned())) };
45    Some(Ok(()))
46}
47
48const RAW_MARKUP_VTABLE: VTableIndirect = VTableIndirect {
49    display: Some(display_raw_markup),
50    try_from: Some(try_from_raw_markup),
51    parse: Some(parse_raw_markup),
52    ..VTableIndirect::EMPTY
53};
54
55impl RawMarkup {
56    /// Create new RawMarkup from a string.
57    pub fn new(s: impl Into<String>) -> Self {
58        Self(s.into())
59    }
60
61    /// Get the raw markup as a string slice.
62    pub fn as_str(&self) -> &str {
63        &self.0
64    }
65
66    /// Consume and return the inner String.
67    pub fn into_inner(self) -> String {
68        self.0
69    }
70}
71
72impl Deref for RawMarkup {
73    type Target = str;
74    fn deref(&self) -> &Self::Target {
75        &self.0
76    }
77}
78
79impl From<String> for RawMarkup {
80    fn from(s: String) -> Self {
81        Self(s)
82    }
83}
84
85impl From<&str> for RawMarkup {
86    fn from(s: &str) -> Self {
87        Self(s.to_owned())
88    }
89}
90
91impl std::fmt::Display for RawMarkup {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        self.0.fmt(f)
94    }
95}
96
97// Facet impl - scalar with vtable for string conversion
98unsafe impl facet_core::Facet<'_> for RawMarkup {
99    const SHAPE: &'static facet_core::Shape = &const {
100        facet_core::ShapeBuilder::for_sized::<RawMarkup>("RawMarkup")
101            .def(facet_core::Def::Scalar)
102            .vtable_indirect(&RAW_MARKUP_VTABLE)
103            .inner(<String as facet_core::Facet>::SHAPE)
104            .build()
105    };
106}
107
108/// Check if a shape is the RawMarkup type.
109pub fn is_raw_markup(shape: &facet_core::Shape) -> bool {
110    // Just check the type name - module path is set by macro
111    shape.type_identifier == "RawMarkup"
112}