float_pigment_css/parser/
hooks.rs

1//! Parser hooks can be used to attach some compilation information.
2
3use alloc::vec::Vec;
4
5#[cfg(feature = "ffi")]
6use core::ffi::{c_char, CStr};
7
8use cssparser::SourceLocation;
9
10use super::{Warning, WarningKind};
11
12#[cfg(feature = "ffi")]
13use crate::ffi::{FfiResult, NullPtr};
14
15use crate::property::Property;
16
17/// A `context` for current sompilation step.
18pub struct ParserHooksContext<'a> {
19    pub(super) warnings: &'a mut Vec<Warning>,
20    pub(super) start_loc: SourceLocation,
21    pub(super) end_loc: SourceLocation,
22}
23
24impl<'a> ParserHooksContext<'a> {
25    /// Generate a new warning in the current location.
26    pub fn generate_warning(&mut self, message: &str) {
27        let start = self.start_loc;
28        let end = self.end_loc;
29        self.warnings.push(Warning {
30            kind: WarningKind::HooksGenerated,
31            message: message.into(),
32            start_line: start.line,
33            start_col: start.column,
34            end_line: end.line,
35            end_col: end.column,
36        })
37    }
38}
39
40/// A list of hooks that can be implemented.
41pub trait Hooks {
42    /// Trigger once whenever a property has been parsed.
43    fn parsed_property(&mut self, _ctx: &mut ParserHooksContext, _p: &mut Property) {}
44}
45
46/// The C FFI for `ParserHooksContext`.
47#[cfg(feature = "ffi")]
48#[repr(C)]
49pub struct CParserHooksContext {
50    inner: *mut (),
51}
52
53#[cfg(feature = "ffi")]
54impl CParserHooksContext {
55    /// The C FFI for `ParserHooksContext::generate_warning`.
56    ///
57    /// # Safety
58    ///
59    /// The message should be a valid C string.
60    #[no_mangle]
61    pub unsafe extern "C" fn generate_warning(
62        &mut self,
63        message: *const c_char,
64    ) -> FfiResult<NullPtr> {
65        use crate::check_null;
66        use crate::ffi::FfiErrorCode;
67        use core::ptr::null;
68        check_null!(message, FfiErrorCode::StrNullPointer, null());
69        let message = CStr::from_ptr(message).to_string_lossy();
70        let ctx = &mut *(self.inner as *mut ParserHooksContext);
71        ctx.generate_warning(&message);
72        FfiResult::ok(null())
73    }
74}
75
76/// The C FFI for `ParserHooks`.
77#[cfg(feature = "ffi")]
78#[repr(C)]
79pub struct CParserHooks {
80    parsed_property: extern "C" fn(CParserHooksContext, *mut Property),
81}
82
83#[cfg(feature = "ffi")]
84impl Hooks for CParserHooks {
85    fn parsed_property(&mut self, ctx: &mut ParserHooksContext, p: &mut Property) {
86        let ctx = CParserHooksContext {
87            inner: ctx as *mut _ as *mut (),
88        };
89        let f = &mut self.parsed_property;
90        f(ctx, p);
91    }
92}