float_pigment_css/parser/
hooks.rs

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