diff --git a/float-pigment-css-macro/src/style_syntax.rs b/float-pigment-css-macro/src/style_syntax.rs index 103f2ba..4403943 100644 --- a/float-pigment-css-macro/src/style_syntax.rs +++ b/float-pigment-css-macro/src/style_syntax.rs @@ -894,13 +894,13 @@ impl ToTokens for StyleSyntaxDefinition { writeln!(&mut style_doc, "| ---- | ---- | ---- |").unwrap(); let table_list_a = supported_properties .iter() - .filter(|x| !x.name.as_ref().unwrap().starts_with("-")); + .filter(|x| !x.name.as_ref().unwrap().starts_with('-')); let table_list_b = supported_properties .iter() - .filter(|x| x.name.as_ref().unwrap().starts_with("-")); + .filter(|x| x.name.as_ref().unwrap().starts_with('-')); for x in table_list_a.chain(table_list_b) { let name = x.name.as_ref().unwrap(); - let non_standard = name.starts_with("-"); + let non_standard = name.starts_with('-'); let name_col = if non_standard { format!("*`{}`*", name) } else { diff --git a/float-pigment-css/float_pigment_css.h b/float-pigment-css/float_pigment_css.h index 26eb317..8f525c9 100644 --- a/float-pigment-css/float_pigment_css.h +++ b/float-pigment-css/float_pigment_css.h @@ -89,6 +89,28 @@ enum class ContainKeyword { Paint, }; +enum class FfiErrorCode { + None, + ThisNullPointer, + PathNullPointer, + PrefixNullPointer, + SourceNullPointer, + BufferNullPointer, + ExprPtrNullPointer, + StrNullPointer, + InlineStyleTextNullPointer, + InlineRuleNullPointer, + StyleTextNullPointer, + SelectorTextNullPointer, + InvalidPath, + JsonNullPointer, + ArrayNullPointer, + SelectorNullPointer, + StyleSheetNullPointer, + MapNullPointer, + Unknown, +}; + enum class FontDisplay { Auto, Block, @@ -265,6 +287,14 @@ enum class WarningKind : uint32_t { InvalidEnvDefaultValue, }; +using NullPtr = const void*; + +template +struct FfiResult { + T value; + FfiErrorCode err; +}; + struct StrRef { size_t offset; size_t len; @@ -286,10 +316,6 @@ struct Warning { uint32_t end_col; }; -struct CParserHooksContext { - void *inner; -}; - template struct Box { T *ptr; @@ -9007,143 +9033,141 @@ struct StyleSheet { }; }; -struct StyleSheetImportIndexPtr { - void *ptr; - void *map; -}; +using RawMutPtr = void*; -struct StyleSheetResourcePtr { - void *ptr; +struct CParserHooksContext { + void *inner; }; struct CParserHooks { void (*parsed_property)(CParserHooksContext, Property*); }; +using CustomPropertyGetter = const char*(*)(void *map, const char *name); + +using CustomPropertySetter = void(*)(void *map, const char *name, const char *value); + extern "C" { -void array_str_ref_free(Array *x); +FfiResult FPArrayStrRefFree(Array *x); -void array_warning_free(Array *warnings); +FfiResult FPArrayWarningFree(Array *warnings); -void buffer_free(uint8_t *buffer_ptr, size_t buffer_len); +FfiResult FPBufferFree(uint8_t *buffer_ptr, size_t buffer_len); -StrRef *css_parser_version(); +FfiResult FPCssParserVersion(); -void generate_warning(CParserHooksContext *self, const char *message); +FfiResult FPInlineStyleFree(InlineRule *inline_rule); -void inline_style_free(InlineRule *inline_rule); +FfiResult FPParseColorFromString(const char *source); -ColorValue parse_color_from_string(const char *source); +FfiResult FPParseInlineStyle(const char *inline_style_text_ptr, + Array **warnings); -InlineRule *parse_inline_style(const char *inline_style_text_ptr, Array **warnings); +FfiResult FPParseSelectorFromString(const char *selector_text_ptr); -Selector *parse_selector_from_string(const char *selector_text_ptr); +FfiResult FPParseStyleSheetFromString(const char *style_text_ptr); -StyleSheet *parse_style_sheet_from_string(const char *style_text_ptr); +FfiResult FPSelectorFree(Selector *selector); -void selector_free(Selector *selector); +FfiResult FPStrFree(const char *ptr); -void str_free(const char *ptr); +FfiResult FPStyleSheetBincodeVersion(uint8_t *buffer_ptr, size_t buffer_len); -size_t str_len(const StrRef *self); +FfiResult FPStyleSheetFree(StyleSheet *style_sheet); -const uint8_t *str_ptr(const StrRef *self); +FfiResult FPStyleSheetImportIndexAddBincode(RawMutPtr this_, + const char *path, + uint8_t *buffer_ptr, + size_t buffer_len, + void (*drop_fn)(RawMutPtr), + RawMutPtr drop_args, + Array **warnings); -StrRef *style_sheet_bincode_version(uint8_t *buffer_ptr, size_t buffer_len); +FfiResult FPStyleSheetImportIndexDeserializeBincode(uint8_t *buffer_ptr, + size_t buffer_len, + void (*drop_fn)(RawMutPtr), + RawMutPtr drop_args); -void style_sheet_free(StyleSheet *style_sheet); +FfiResult FPStyleSheetImportIndexDeserializeJson(const char *json); -void style_sheet_import_index_add_bincode(StyleSheetImportIndexPtr *this_, - const char *path, - uint8_t *buffer_ptr, - size_t buffer_len, - void (*drop_fn)(void*), - void *drop_args, - Array **warnings); +FfiResult FPStyleSheetImportIndexFree(RawMutPtr this_); -StyleSheetImportIndexPtr style_sheet_import_index_deserialize_bincode(uint8_t *buffer_ptr, - size_t buffer_len, - void (*drop_fn)(void*), - void *drop_args); +FfiResult FPStyleSheetImportIndexGetStyleSheet(RawMutPtr this_, const char *path); -StyleSheetImportIndexPtr style_sheet_import_index_deserialize_json(const char *json); +FfiResult*> FPStyleSheetImportIndexListDependencies(RawMutPtr this_, + const char *path); -void style_sheet_import_index_free(StyleSheetImportIndexPtr *this_); +FfiResult*> FPStyleSheetImportIndexListDependency(RawMutPtr this_, const char *path); -StyleSheet *style_sheet_import_index_get_style_sheet(StyleSheetImportIndexPtr *this_, - const StrRef *path); +FfiResult FPStyleSheetImportIndexMergeBincode(RawMutPtr this_, + uint8_t *buffer_ptr, + size_t buffer_len, + void (*drop_fn)(void*), + void *drop_args); -Array *style_sheet_import_index_list_dependencies(StyleSheetImportIndexPtr *this_, - const char *path); +FfiResult FPStyleSheetImportIndexNew(); -Array *style_sheet_import_index_list_dependency(StyleSheetImportIndexPtr *this_, - const char *path); +FfiResult*> FPStyleSheetImportIndexQueryAndMarkDependencies(RawMutPtr this_, + const char *path); -void style_sheet_import_index_merge_bincode(StyleSheetImportIndexPtr *this_, - uint8_t *buffer_ptr, - size_t buffer_len, - void (*drop_fn)(void*), - void *drop_args); +FfiResult FPStyleSheetImportIndexRemoveBincode(RawMutPtr this_, const char *path); -StyleSheetImportIndexPtr style_sheet_import_index_new(); +FfiResult FPStyleSheetImportIndexSerializeBincode(RawMutPtr this_, + size_t *ret_buffer_len); -Array *style_sheet_import_index_query_and_mark_dependencies(StyleSheetImportIndexPtr *this_, - const char *path); +FfiResult FPStyleSheetImportIndexSerializeJson(RawMutPtr this_, size_t *ret_buffer_len); -void style_sheet_import_index_remove_bincode(StyleSheetImportIndexPtr *this_, const char *path); +FfiResult FPStyleSheetResourceAddBincode(RawMutPtr this_, + const char *path, + uint8_t *buffer_ptr, + size_t buffer_len, + void (*drop_fn)(RawMutPtr), + RawMutPtr drop_args, + Array **warnings); -uint8_t *style_sheet_import_index_serialize_bincode(StyleSheetImportIndexPtr *this_, - size_t *ret_buffer_len); +FfiResult FPStyleSheetResourceAddSource(RawMutPtr this_, + const char *path, + const char *source, + Array **warnings); -uint8_t *style_sheet_import_index_serialize_json(StyleSheetImportIndexPtr *this_, - size_t *ret_buffer_len); +FfiResult FPStyleSheetResourceAddSourceWithHooks(RawMutPtr this_, + CParserHooks hooks, + const char *path, + const char *source, + Array **warnings); -void style_sheet_resource_add_bincode(StyleSheetResourcePtr *this_, - const char *path, - uint8_t *buffer_ptr, - size_t buffer_len, - void (*drop_fn)(void*), - void *drop_args, - Array **warnings); +FfiResult FPStyleSheetResourceAddTagNamePrefix(RawMutPtr this_, + const char *path, + const char *prefix); -void style_sheet_resource_add_source(StyleSheetResourcePtr *this_, - const char *path, - const char *source, - Array **warnings); +FfiResult*> FPStyleSheetResourceDirectDependencies(RawMutPtr this_, const char *path); -void style_sheet_resource_add_source_with_hooks(StyleSheetResourcePtr *this_, - CParserHooks hooks, - const char *path, - const char *source, - Array **warnings); +FfiResult FPStyleSheetResourceFree(RawMutPtr this_); -void style_sheet_resource_add_tag_name_prefix(StyleSheetResourcePtr *this_, - const char *path, - const char *prefix); +FfiResult FPStyleSheetResourceGenerateImportIndex(RawMutPtr this_); -Array *style_sheet_resource_direct_dependencies(StyleSheetResourcePtr *this_, - const char *path); +FfiResult FPStyleSheetResourceNew(); -void style_sheet_resource_free(StyleSheetResourcePtr *this_); +FfiResult FPStyleSheetResourceSerializeBincode(RawMutPtr this_, + const char *path, + size_t *ret_buffer_len); -StyleSheetImportIndexPtr style_sheet_resource_generate_import_index(StyleSheetResourcePtr *this_); +FfiResult FPStyleSheetResourceSerializeJson(RawMutPtr this_, + const char *path, + size_t *ret_buffer_len); -StyleSheetResourcePtr style_sheet_resource_new(); +FfiResult FPSubstituteVariable(const char *expr_ptr, + RawMutPtr map, + CustomPropertyGetter getter, + CustomPropertySetter setter); -uint8_t *style_sheet_resource_serialize_bincode(StyleSheetResourcePtr *this_, - const char *path, - size_t *ret_buffer_len); +FfiResult generate_warning(CParserHooksContext *self, const char *message); -uint8_t *style_sheet_resource_serialize_json(StyleSheetResourcePtr *this_, - const char *path, - size_t *ret_buffer_len); +size_t str_len(const StrRef *self); -const char *substitute_variable(const char *expr_ptr, - void *map, - CustomPropertyGetter getter, - CustomPropertySetter setter); +const uint8_t *str_ptr(const StrRef *self); } // extern "C" diff --git a/float-pigment-css/src/ffi.rs b/float-pigment-css/src/ffi.rs index f0159dd..2f8c40a 100644 --- a/float-pigment-css/src/ffi.rs +++ b/float-pigment-css/src/ffi.rs @@ -8,10 +8,8 @@ use alloc::{ vec::Vec, }; use bit_set::BitSet; -use core::{ - ffi::{c_char, CStr}, - ptr::null, -}; +use core::ffi::{c_char, CStr}; +use core::ptr::{null, null_mut}; use hashbrown::HashMap; use crate::parser::parse_color_to_rgba; @@ -19,11 +17,14 @@ use crate::property::{Property, PropertyMeta}; use crate::sheet::borrow::{InlineRule, Selector}; use crate::typing::ImportantBitSet; +use crate::group; +use crate::parser; use crate::parser::property_value::var::{ CustomPropertyContext, CustomPropertyGetter, CustomPropertySetter, }; - -use super::{group::drop_css_extension, *}; +use crate::sheet; +use group::drop_css_extension; +use group::StyleSheetImportIndex as StyleSheetImportIndexImpl; use parser::Warning; use sheet::borrow::{Array, StyleSheet}; use sheet::str_store::StrRef; @@ -31,120 +32,326 @@ use sheet::str_store::StrRef; #[cfg(feature = "deserialize")] use sheet::borrow::de_static_ref_zero_copy_env; +#[macro_export] +macro_rules! check_null { + ($arg:expr, $error:expr, $default:expr) => { + if $arg.is_null() { + return FfiResult::error($error, $default); + } + }; +} + +#[macro_export] +macro_rules! raw_ptr_as_mut_ref { + ($from:expr, $type:ty) => { + &mut *($from as *mut $type) + }; +} + +pub type RawMutPtr = *mut (); + +pub type NullPtr = *const (); + +#[repr(C)] +pub enum FfiErrorCode { + None, + ThisNullPointer, + PathNullPointer, + PrefixNullPointer, + SourceNullPointer, + BufferNullPointer, + ExprPtrNullPointer, + StrNullPointer, + InlineStyleTextNullPointer, + InlineRuleNullPointer, + StyleTextNullPointer, + SelectorTextNullPointer, + InvalidPath, + JsonNullPointer, + ArrayNullPointer, + SelectorNullPointer, + StyleSheetNullPointer, + MapNullPointer, + Unknown, +} + #[repr(C)] -pub struct StyleSheetResourcePtr { - ptr: *mut (), +pub struct FfiResult { + pub value: T, + pub err: FfiErrorCode, +} + +impl FfiResult { + pub fn ok(value: T) -> Self { + Self { + value, + err: FfiErrorCode::None, + } + } + pub fn error(err: FfiErrorCode, default: T) -> Self { + Self { + value: default, + err, + } + } } + /// # Safety /// -#[no_mangle] -pub unsafe extern "C" fn style_sheet_resource_new() -> StyleSheetResourcePtr { - let res = Box::into_raw(Box::new(group::StyleSheetResource::new())); - StyleSheetResourcePtr { - ptr: res as *mut (), - } +/// Create a new style sheet resource. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// * `source` - C string pointer to the CSS source content (UTF-8 encoded) +/// * `warnings` - Optional output parameter to receive warnings array pointer +/// +/// # Examples +/// +/// ```c +/// FfiResult result = FPStyleSheetResourceNew(); +/// if (result.err != FfiErrorCode::None) { +/// // handle error +/// } +/// RawMutPtr resource = result.value; +/// ``` +/// +#[export_name = "FPStyleSheetResourceNew"] +pub unsafe extern "C" fn style_sheet_resource_new() -> FfiResult { + FfiResult::ok(Box::into_raw(Box::new(group::StyleSheetResource::new())) as RawMutPtr) } + /// # Safety /// -#[no_mangle] -pub unsafe extern "C" fn style_sheet_resource_free(this: &mut StyleSheetResourcePtr) { - drop(Box::from_raw(this.ptr as *mut StyleSheetResource)); - this.ptr = core::ptr::null_mut(); +/// Free the style sheet resource. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// +/// # Examples +/// +/// ```c +/// FfiResult result = FPStyleSheetResourceFree(resource); +/// if (result.err != FfiErrorCode::None) { +/// // handle error +/// } +/// ``` +/// +#[export_name = "FPStyleSheetResourceFree"] +pub unsafe extern "C" fn style_sheet_resource_free(this: RawMutPtr) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + drop(Box::from_raw(this as *mut group::StyleSheetResource)); + FfiResult::ok(null()) } + /// # Safety +/// Add a tag name prefix to the resource. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the stylesheet path (UTF-8 encoded) +/// * `prefix` - C string pointer to the prefix to add to the tag name (UTF-8 encoded) /// -#[no_mangle] +/// # Examples +/// +/// ```c +/// FfiResult result = FPStyleSheetResourceAddTagNamePrefix(resource, path, prefix); +/// if (result.err != FfiErrorCode::None) { +/// // handle error +/// } +/// ``` +/// +#[export_name = "FPStyleSheetResourceAddTagNamePrefix"] pub unsafe extern "C" fn style_sheet_resource_add_tag_name_prefix( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, path: *const c_char, prefix: *const c_char, -) { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + check_null!(path, FfiErrorCode::PathNullPointer, null()); + check_null!(prefix, FfiErrorCode::PrefixNullPointer, null()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let path = CStr::from_ptr(path).to_string_lossy(); let prefix = CStr::from_ptr(prefix).to_string_lossy(); res.add_tag_name_prefix(&path, &prefix); + FfiResult::ok(null()) } + /// # Safety +/// Serialize the specified style sheet to the JSON format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the stylesheet path (UTF-8 encoded) +/// * `ret_buffer_len` - Pointer to a variable to store the length of the serialized data +/// +/// # Examples +/// +/// ```c +/// FfiResult result = FPStyleSheetResourceSerializeJson(resource, path, &mut buffer_len); +/// if (result.err != FfiErrorCode::None) { +/// // handle error +/// } +/// ``` /// #[cfg(all(feature = "serialize", feature = "serialize_json"))] -#[no_mangle] +#[export_name = "FPStyleSheetResourceSerializeJson"] pub unsafe extern "C" fn style_sheet_resource_serialize_json( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, path: *const c_char, ret_buffer_len: &mut usize, -) -> *mut u8 { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult<*mut u8> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let path = CStr::from_ptr(path).to_string_lossy(); let serial = res.serialize_json(&path).unwrap_or_default(); *ret_buffer_len = serial.len(); let ret = Box::into_raw(serial.into_boxed_str()); - ret as *mut u8 + FfiResult::ok(ret as *mut u8) } + /// # Safety /// +/// Serialize the specified style sheet to the binary format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the stylesheet path (UTF-8 encoded) +/// * `ret_buffer_len` - Pointer to a variable to store the length of the serialized data +/// +/// # Examples +/// +/// ```c +/// FfiResult result = FPStyleSheetResourceSerializeBincode(resource, path, &mut buffer_len); +/// if (result.err != FfiErrorCode::None) { +/// // handle error +/// } +/// ``` +/// #[cfg(feature = "serialize")] -#[no_mangle] +#[export_name = "FPStyleSheetResourceSerializeBincode"] pub unsafe extern "C" fn style_sheet_resource_serialize_bincode( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, path: *const c_char, ret_buffer_len: &mut usize, -) -> *mut u8 { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult<*mut u8> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let path = CStr::from_ptr(path).to_string_lossy(); let serial = res.serialize_bincode(&path).unwrap_or_default(); *ret_buffer_len = serial.len(); let ret = Box::into_raw(serial.into_boxed_slice()); - ret as *mut u8 + FfiResult::ok(ret as *mut u8) } /// # Safety /// -#[no_mangle] +/// Add a style sheet to the resource manager. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// * `source` - C string pointer to the CSS source content (UTF-8 encoded) +/// * `warnings` - Optional output parameter to receive warnings array pointer +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetResourceAddSource(resource, path, source, &mut warnings); +/// ``` +/// +#[export_name = "FPStyleSheetResourceAddSource"] pub unsafe extern "C" fn style_sheet_resource_add_source( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, path: *const c_char, source: *const c_char, warnings: *mut *mut Array, -) { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + check_null!(path, FfiErrorCode::PathNullPointer, null()); + check_null!(source, FfiErrorCode::SourceNullPointer, null()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let path = CStr::from_ptr(path).to_string_lossy(); let source = CStr::from_ptr(source).to_string_lossy(); let w = res.add_source(&path, &source); if !warnings.is_null() { *warnings = Box::into_raw(Box::new(w.into())); } + FfiResult::ok(null()) } + /// # Safety /// -#[no_mangle] +/// Add a style sheet to the resource manager with hooks. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `hooks` - A parser hooks +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// * `source` - C string pointer to the CSS source content (UTF-8 encoded) +/// * `warnings` - Optional output parameter to receive warnings array pointer +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetResourceAddSourceWithHooks(resource, hooks, path, source, &mut warnings); +/// ``` +/// +#[export_name = "FPStyleSheetResourceAddSourceWithHooks"] pub unsafe extern "C" fn style_sheet_resource_add_source_with_hooks( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, hooks: parser::hooks::CParserHooks, path: *const c_char, source: *const c_char, warnings: *mut *mut Array, -) { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + check_null!(path, FfiErrorCode::PathNullPointer, null()); + check_null!(source, FfiErrorCode::SourceNullPointer, null()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let path = CStr::from_ptr(path).to_string_lossy(); let source = CStr::from_ptr(source).to_string_lossy(); let w = res.add_source_with_hooks(&path, &source, Some(Box::new(hooks))); if !warnings.is_null() { *warnings = Box::into_raw(Box::new(w.into())); } + FfiResult::ok(null()) } + /// # Safety +/// Add a style sheet to the resource manager from binary format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the stylesheet path (UTF-8 encoded) +/// * `buffer_ptr` - Pointer to the buffer to store the serialized data +/// * `buffer_len` - Length of the buffer +/// * `drop_fn` - Optional drop function +/// * `drop_args` - Pointer to the drop argument +/// * `warnings` - Optional output parameter to receive warnings array pointer +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetResourceAddBincode(resource, path, buffer_ptr, buffer_len, drop_fn, drop_args, &mut warnings); +/// ``` /// #[cfg(feature = "deserialize")] -#[no_mangle] +#[export_name = "FPStyleSheetResourceAddBincode"] pub unsafe extern "C" fn style_sheet_resource_add_bincode( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, path: *const c_char, buffer_ptr: *mut u8, buffer_len: usize, - drop_fn: Option, - drop_args: *mut (), + drop_fn: Option, + drop_args: RawMutPtr, warnings: *mut *mut Array, -) { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + check_null!(path, FfiErrorCode::PathNullPointer, null()); + check_null!(buffer_ptr, FfiErrorCode::BufferNullPointer, null()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let bincode: *mut [u8] = core::slice::from_raw_parts_mut(buffer_ptr, buffer_len); let path = CStr::from_ptr(path).to_string_lossy(); let w = res.add_bincode_zero_copy(&path, bincode, move || { @@ -155,121 +362,238 @@ pub unsafe extern "C" fn style_sheet_resource_add_bincode( if !warnings.is_null() { *warnings = Box::into_raw(Box::new(w.into())); } + FfiResult::ok(null()) } + /// # Safety +/// Get the direct dependencies of the specified style sheet. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// * `path` - C string pointer to the stylesheet path (UTF-8 encoded) /// -#[no_mangle] +/// # Examples +/// +/// ```c +/// FPStyleSheetResourceDirectDependencies(resource, path); +/// ``` +/// +#[export_name = "FPStyleSheetResourceDirectDependencies"] pub unsafe extern "C" fn style_sheet_resource_direct_dependencies( - this: &mut StyleSheetResourcePtr, + this: RawMutPtr, path: *const c_char, -) -> *mut Array { - let res = &mut *(this.ptr as *mut StyleSheetResource); +) -> FfiResult<*mut Array> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); let path = CStr::from_ptr(path).to_string_lossy(); let deps = res.direct_dependencies(&path); let deps: Vec<_> = deps.into_iter().map(StrRef::from).collect(); - Box::into_raw(Box::new(deps.into())) + FfiResult::ok(Box::into_raw(Box::new(deps.into()))) } + /// # Safety /// -#[no_mangle] +/// Generate the import index of the resource. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetResource`] instance +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetResourceGenerateImportIndex(resource); +/// ``` +/// +#[export_name = "FPStyleSheetResourceGenerateImportIndex"] pub unsafe extern "C" fn style_sheet_resource_generate_import_index( - this: &mut StyleSheetResourcePtr, -) -> StyleSheetImportIndexPtr { - let res = &mut *(this.ptr as *mut StyleSheetResource); - let ii = Box::into_raw(Box::new(res.generate_import_indexes())); - let style_sheet_map: Box = Box::default(); - StyleSheetImportIndexPtr { - ptr: ii as *mut (), - map: Box::into_raw(style_sheet_map) as *mut _, - } + this: RawMutPtr, +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + let res = raw_ptr_as_mut_ref!(this, group::StyleSheetResource); + FfiResult::ok( + StyleSheetImportIndex { + inner: res.generate_import_indexes(), + map: StyleSheetMap::default(), + } + .into_raw(), + ) } type StyleSheetMap = HashMap; -#[repr(C)] -pub struct StyleSheetImportIndexPtr { - ptr: *mut (), - map: *mut (), +struct StyleSheetImportIndex { + inner: StyleSheetImportIndexImpl, + map: StyleSheetMap, +} + +impl StyleSheetImportIndex { + fn into_raw(self) -> RawMutPtr { + Box::into_raw(Box::new(self)) as RawMutPtr + } } + /// # Safety +/// Create a new style sheet import index. /// -#[no_mangle] -pub unsafe extern "C" fn style_sheet_import_index_new() -> StyleSheetImportIndexPtr { - let ii = Box::into_raw(Box::new(StyleSheetImportIndex::new())); - let style_sheet_map: Box = Box::default(); - StyleSheetImportIndexPtr { - ptr: ii as *mut (), - map: Box::into_raw(style_sheet_map) as *mut _, - } +/// # Examples +/// +/// ```c +/// RawMutPtr import_index = FPStyleSheetImportIndexNew(); +/// ``` +/// +#[export_name = "FPStyleSheetImportIndexNew"] +pub unsafe extern "C" fn style_sheet_import_index_new() -> FfiResult { + FfiResult::ok( + StyleSheetImportIndex { + inner: StyleSheetImportIndexImpl::new(), + map: StyleSheetMap::default(), + } + .into_raw(), + ) } + /// # Safety +/// Free the style sheet import index. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexFree(import_index); +/// ``` /// -#[no_mangle] -pub unsafe extern "C" fn style_sheet_import_index_free(this: &mut StyleSheetImportIndexPtr) { - drop(Box::from_raw(this.ptr as *mut StyleSheetImportIndex)); - this.ptr = core::ptr::null_mut(); - drop(Box::from_raw(this.map as *mut StyleSheetMap)); - this.map = core::ptr::null_mut(); +#[export_name = "FPStyleSheetImportIndexFree"] +pub unsafe extern "C" fn style_sheet_import_index_free(this: RawMutPtr) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + drop(Box::from_raw(this as *mut StyleSheetImportIndex)); + FfiResult::ok(null()) } + /// # Safety +/// Query and mark the dependencies of the specified style sheet. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// +/// # Examples /// -#[no_mangle] +/// ```c +/// FPStyleSheetImportIndexQueryAndMarkDependencies(import_index, path); +/// ``` +/// +#[export_name = "FPStyleSheetImportIndexQueryAndMarkDependencies"] pub unsafe extern "C" fn style_sheet_import_index_query_and_mark_dependencies( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, path: *const c_char, -) -> *mut Array { - let ii = &mut *(this.ptr as *mut StyleSheetImportIndex); +) -> FfiResult<*mut Array> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); let path = CStr::from_ptr(path).to_string_lossy(); - let deps = ii.query_and_mark_dependencies(&path); + let deps = style_sheet_import_index + .inner + .query_and_mark_dependencies(&path); let deps: Vec<_> = deps.into_iter().map(StrRef::from).collect(); - Box::into_raw(Box::new(deps.into())) + FfiResult::ok(Box::into_raw(Box::new(deps.into()))) } + /// # Safety +/// List the dependencies of the specified style sheet. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) /// -#[no_mangle] +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexListDependencies(import_index, path); +/// ``` +/// +#[export_name = "FPStyleSheetImportIndexListDependencies"] pub unsafe extern "C" fn style_sheet_import_index_list_dependencies( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, path: *const c_char, -) -> *mut Array { - let ii = &mut *(this.ptr as *mut StyleSheetImportIndex); +) -> FfiResult<*mut Array> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); let path = CStr::from_ptr(path).to_string_lossy(); - let deps = ii.list_dependencies(&path, true); + let deps = style_sheet_import_index + .inner + .list_dependencies(&path, true); let deps: Vec<_> = deps.into_iter().map(StrRef::from).collect(); - Box::into_raw(Box::new(deps.into())) + FfiResult::ok(Box::into_raw(Box::new(deps.into()))) } + /// # Safety +/// List the dependency of the specified style sheet. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexListDependency(import_index, path); +/// ``` /// -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexListDependency"] pub unsafe extern "C" fn style_sheet_import_index_list_dependency( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, path: *const c_char, -) -> *mut Array { - if path.is_null() { - panic!("style_sheet_import_index_list_dependency: path is null!") - } - let ii = &mut *(this.ptr as *mut StyleSheetImportIndex); +) -> FfiResult<*mut Array> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); let path = CStr::from_ptr(path).to_string_lossy(); - let deps = ii.list_dependencies(&path, false); + let deps = style_sheet_import_index + .inner + .list_dependencies(&path, false); let deps: Vec<_> = deps.into_iter().map(StrRef::from).collect(); - Box::into_raw(Box::new(deps.into())) + FfiResult::ok(Box::into_raw(Box::new(deps.into()))) } + /// # Safety +/// Add a style sheet to the import index from binary format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// * `buffer_ptr` - Pointer to the buffer to store the serialized data +/// * `buffer_len` - Length of the buffer +/// * `drop_fn` - Optional drop function +/// * `drop_args` - Pointer to the drop argument +/// * `warnings` - Optional output parameter to receive warnings array pointer +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexAddBincode(import_index, path, buffer_ptr, buffer_len, drop_fn, drop_args, &mut warnings); +/// ``` /// #[cfg(feature = "deserialize")] -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexAddBincode"] pub unsafe extern "C" fn style_sheet_import_index_add_bincode( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, path: *const c_char, buffer_ptr: *mut u8, buffer_len: usize, - drop_fn: Option, - drop_args: *mut (), + drop_fn: Option, + drop_args: RawMutPtr, warnings: *mut *mut Array, -) { +) -> FfiResult { use float_pigment_consistent_bincode::Options; use parser::WarningKind; + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + check_null!(buffer_ptr, FfiErrorCode::BufferNullPointer, null_mut()); let path = CStr::from_ptr(path).to_string_lossy(); - let path: &str = &path; let sheet = de_static_ref_zero_copy_env( core::slice::from_raw_parts_mut(buffer_ptr, buffer_len), |s| { @@ -304,149 +628,305 @@ pub unsafe extern "C" fn style_sheet_import_index_add_bincode( } }, ); - let path = drop_css_extension(path).into(); - let map = &mut *(this.map as *mut StyleSheetMap); - map.insert(path, sheet); + let path = drop_css_extension(&path).into(); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); + style_sheet_import_index.map.insert(path, sheet); + FfiResult::ok(null()) } + /// # Safety +/// Remove a style sheet from the style sheet import index. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// +/// # Examples /// -#[no_mangle] +/// ```c +/// FPStyleSheetImportIndexRemoveBincode(import_index, path); +/// ``` +/// +#[export_name = "FPStyleSheetImportIndexRemoveBincode"] pub unsafe extern "C" fn style_sheet_import_index_remove_bincode( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, path: *const c_char, -) { +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + check_null!(path, FfiErrorCode::PathNullPointer, null()); let path = CStr::from_ptr(path).to_string_lossy(); - let path: &str = &path; - let path = drop_css_extension(path); - let map = &mut *(this.map as *mut StyleSheetMap); - map.remove(path); + let path = drop_css_extension(&path); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); + style_sheet_import_index.map.remove(path); + FfiResult::ok(null()) } /// # Safety +/// Get the style sheet from the style sheet import index. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `path` - C string pointer to the style sheet path (UTF-8 encoded) +/// +/// # Examples /// -#[no_mangle] +/// ```c +/// FPStyleSheetImportIndexGetStyleSheet(import_index, path); +/// ``` +/// +#[export_name = "FPStyleSheetImportIndexGetStyleSheet"] pub unsafe extern "C" fn style_sheet_import_index_get_style_sheet( - this: &mut StyleSheetImportIndexPtr, - path: *const StrRef, -) -> *mut StyleSheet { - let path = (*path).as_str(); - let path = drop_css_extension(path); - let map = &mut *(this.map as *mut StyleSheetMap); - match map.get_mut(path) { - None => core::ptr::null_mut(), - Some(x) => x as *mut _, + this: RawMutPtr, + path: *const c_char, +) -> FfiResult<*mut StyleSheet> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + check_null!(path, FfiErrorCode::PathNullPointer, null_mut()); + let path = CStr::from_ptr(path).to_string_lossy(); + let path = drop_css_extension(&path); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); + match style_sheet_import_index.map.get_mut(path) { + None => FfiResult::error(FfiErrorCode::InvalidPath, null_mut()), + Some(x) => FfiResult::ok(x as *mut StyleSheet), } } /// # Safety +/// Serialize the style sheet import index to the JSON format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `ret_buffer_len` - Pointer to a variable to store the length of the serialized data +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexSerializeJson(import_index, &buffer_len); +/// ``` /// #[cfg(all(feature = "serialize", feature = "serialize_json"))] -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexSerializeJson"] pub unsafe extern "C" fn style_sheet_import_index_serialize_json( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, ret_buffer_len: &mut usize, -) -> *mut u8 { - let ii = &mut *(this.ptr as *mut StyleSheetImportIndex); - let serial = ii.serialize_json(); +) -> FfiResult<*mut u8> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); + let serial = style_sheet_import_index.inner.serialize_json(); *ret_buffer_len = serial.len(); let ret = Box::into_raw(serial.into_boxed_str()); - ret as *mut u8 + FfiResult::ok(ret as *mut u8) } /// # Safety +/// Serialize the style sheet import index to the binary format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `ret_buffer_len` - Pointer to a variable to store the length of the serialized data +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexSerializeBincode(import_index, &buffer_len); +/// ``` /// #[cfg(feature = "serialize")] -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexSerializeBincode"] pub unsafe extern "C" fn style_sheet_import_index_serialize_bincode( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, ret_buffer_len: &mut usize, -) -> *mut u8 { - let ii = &mut *(this.ptr as *mut StyleSheetImportIndex); - let serial = ii.serialize_bincode(); +) -> FfiResult<*mut u8> { + check_null!(this, FfiErrorCode::ThisNullPointer, null_mut()); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); + let serial = style_sheet_import_index.inner.serialize_bincode(); *ret_buffer_len = serial.len(); let ret = Box::into_raw(serial.into_boxed_slice()); - ret as *mut u8 + FfiResult::ok(ret as *mut u8) } /// # Safety +/// Deserialize the style sheet import index from the JSON format. +/// +/// # Arguments +/// * `json` - C string pointer to the JSON data +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexDeserializeJson(json, &import_index); +/// ``` /// #[cfg(all(feature = "deserialize", feature = "deserialize_json"))] -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexDeserializeJson"] pub unsafe extern "C" fn style_sheet_import_index_deserialize_json( json: *const c_char, -) -> StyleSheetImportIndexPtr { +) -> FfiResult { + check_null!(json, FfiErrorCode::JsonNullPointer, null_mut()); let json = CStr::from_ptr(json).to_string_lossy(); - let ii = StyleSheetImportIndex::deserialize_json(&json); - let ii = Box::into_raw(Box::new(ii)); - StyleSheetImportIndexPtr { - ptr: ii as *mut (), - map: Box::into_raw(Box::new(StyleSheetMap::default())) as *mut _, - } + FfiResult::ok( + StyleSheetImportIndex { + inner: StyleSheetImportIndexImpl::deserialize_json(&json), + map: StyleSheetMap::default(), + } + .into_raw(), + ) } /// # Safety +/// Deserialize the style sheet import index from the binary format. +/// +/// # Arguments +/// * `buffer_ptr` - Pointer to the binary data +/// * `buffer_len` - Length of the binary data +/// * `drop_fn` - Optional drop function +/// * `drop_args` - Pointer to the drop argument +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexDeserializeBincode(buffer_ptr, buffer_len, drop_fn, drop_args); +/// ``` /// #[cfg(feature = "deserialize")] -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexDeserializeBincode"] pub unsafe extern "C" fn style_sheet_import_index_deserialize_bincode( buffer_ptr: *mut u8, buffer_len: usize, - drop_fn: Option, - drop_args: *mut (), -) -> StyleSheetImportIndexPtr { + drop_fn: Option, + drop_args: RawMutPtr, +) -> FfiResult { + check_null!(buffer_ptr, FfiErrorCode::BufferNullPointer, null_mut()); let bincode: *mut [u8] = core::slice::from_raw_parts_mut(buffer_ptr, buffer_len); - let ii = StyleSheetImportIndex::deserialize_bincode_zero_copy(bincode, move || { - if let Some(drop_fn) = drop_fn { - drop_fn(drop_args); + FfiResult::ok( + StyleSheetImportIndex { + inner: StyleSheetImportIndexImpl::deserialize_bincode_zero_copy(bincode, move || { + if let Some(drop_fn) = drop_fn { + drop_fn(drop_args); + } + }), + map: StyleSheetMap::default(), } - }); - let ii = Box::into_raw(Box::new(ii)); - let style_sheet_map: Box = Box::default(); - StyleSheetImportIndexPtr { - ptr: ii as *mut (), - map: Box::into_raw(style_sheet_map) as *mut _, - } + .into_raw(), + ) } /// # Safety +/// Merge the style sheet import index from binary format. +/// +/// # Arguments +/// * `this` - A raw pointer to a [`StyleSheetImportIndex`] instance +/// * `buffer_ptr` - Pointer to the binary data +/// * `buffer_len` - Length of the binary data +/// * `drop_fn` - Optional drop function +/// * `drop_args` - Pointer to the drop argument +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetImportIndexMergeBincode(import_index, buffer_ptr, buffer_len, drop_fn, drop_args); +/// ``` /// #[cfg(feature = "deserialize")] -#[no_mangle] +#[export_name = "FPStyleSheetImportIndexMergeBincode"] pub unsafe extern "C" fn style_sheet_import_index_merge_bincode( - this: &mut StyleSheetImportIndexPtr, + this: RawMutPtr, buffer_ptr: *mut u8, buffer_len: usize, drop_fn: Option, drop_args: *mut (), -) { - let ii = &mut *(this.ptr as *mut StyleSheetImportIndex); +) -> FfiResult { + check_null!(this, FfiErrorCode::ThisNullPointer, null()); + check_null!(buffer_ptr, FfiErrorCode::BufferNullPointer, null()); + let style_sheet_import_index = raw_ptr_as_mut_ref!(this, StyleSheetImportIndex); let bincode: *mut [u8] = core::slice::from_raw_parts_mut(buffer_ptr, buffer_len); - ii.merge_bincode_zero_copy(bincode, move || { - if let Some(drop_fn) = drop_fn { - drop_fn(drop_args); - } - }); + style_sheet_import_index + .inner + .merge_bincode_zero_copy(bincode, move || { + if let Some(drop_fn) = drop_fn { + drop_fn(drop_args); + } + }); + FfiResult::ok(null()) } + /// # Safety +/// Free the buffer. +/// +/// # Arguments +/// * `buffer_ptr` - Pointer to the buffer +/// * `buffer_len` - Length of the buffer +/// +/// # Examples +/// +/// ```c +/// FPBufferFree(buffer_ptr, buffer_len); +/// ``` /// -#[no_mangle] -pub unsafe extern "C" fn buffer_free(buffer_ptr: *mut u8, buffer_len: usize) { +#[export_name = "FPBufferFree"] +pub unsafe extern "C" fn buffer_free(buffer_ptr: *mut u8, buffer_len: usize) -> FfiResult { + check_null!(buffer_ptr, FfiErrorCode::BufferNullPointer, null()); let x: *mut [u8] = core::slice::from_raw_parts_mut(buffer_ptr, buffer_len); drop(Box::from_raw(x)); + FfiResult::ok(null()) } + /// # Safety +/// Free the array of string references. +/// +/// # Arguments +/// * `x` - Pointer to the array of string references +/// +/// # Examples /// -#[no_mangle] -pub unsafe extern "C" fn array_str_ref_free(x: *mut Array) { +/// ```c +/// FPArrayStrRefFree(x); +/// ``` +/// +#[export_name = "FPArrayStrRefFree"] +pub unsafe extern "C" fn array_str_ref_free(x: *mut Array) -> FfiResult { + check_null!(x, FfiErrorCode::ArrayNullPointer, null()); drop(Box::from_raw(x)); + FfiResult::ok(null()) } + /// # Safety +/// Free the array of warnings. +/// +/// # Arguments +/// * `warnings` - Pointer to the array of warnings /// -#[no_mangle] -pub unsafe extern "C" fn array_warning_free(warnings: *mut Array) { +/// # Examples +/// +/// ```c +/// FPArrayWarningFree(warnings); +/// ``` +/// +#[export_name = "FPArrayWarningFree"] +pub unsafe extern "C" fn array_warning_free( + warnings: *mut Array, +) -> FfiResult { + check_null!(warnings, FfiErrorCode::ArrayNullPointer, null()); drop(Box::from_raw(warnings)); + FfiResult::ok(null()) } + /// # Safety +/// Parse the inline style from the string. +/// +/// # Arguments +/// * `inline_style_text_ptr` - Pointer to the inline style text +/// * `warnings` - Optional output parameter to receive warnings array pointer /// -#[no_mangle] +/// # Examples +/// +/// ```c +/// FPParseInlineStyle(inline_style_text_ptr, warnings); +/// ``` +/// +#[export_name = "FPParseInlineStyle"] pub unsafe extern "C" fn parse_inline_style( inline_style_text_ptr: *const c_char, warnings: *mut *mut Array, -) -> *mut InlineRule { +) -> FfiResult<*mut InlineRule> { + check_null!( + inline_style_text_ptr, + FfiErrorCode::InlineStyleTextNullPointer, + null_mut() + ); let inline_style_text = CStr::from_ptr(inline_style_text_ptr).to_string_lossy(); let (prop, w) = parser::parse_inline_style(&inline_style_text, parser::StyleParsingDebugMode::None); @@ -474,56 +954,140 @@ pub unsafe extern "C" fn parse_inline_style( ImportantBitSet::Array(important.into_bit_vec().to_bytes().into()) }; let inline_rule = InlineRule::new(properties, important); - Box::into_raw(Box::new(inline_rule)) + FfiResult::ok(Box::into_raw(Box::new(inline_rule))) } + /// # Safety +/// Free the inline style. +/// +/// # Arguments +/// * `inline_rule` - Pointer to the inline style +/// +/// # Examples /// -#[no_mangle] -pub unsafe extern "C" fn inline_style_free(inline_rule: *mut InlineRule) { +/// ```c +/// FPInlineStyleFree(inline_rule); +/// ``` +/// +#[export_name = "FPInlineStyleFree"] +pub unsafe extern "C" fn inline_style_free(inline_rule: *mut InlineRule) -> FfiResult { + check_null!(inline_rule, FfiErrorCode::InlineRuleNullPointer, null()); drop(Box::from_raw(inline_rule)); + FfiResult::ok(null()) } + /// # Safety +/// Parse the style sheet from the string. +/// +/// # Arguments +/// * `style_text_ptr` - Pointer to the style sheet text /// -#[no_mangle] +/// # Examples +/// +/// ```c +/// FPStyleSheetFromString(style_text_ptr); +/// ``` +/// +#[export_name = "FPParseStyleSheetFromString"] pub unsafe extern "C" fn parse_style_sheet_from_string( style_text_ptr: *const c_char, -) -> *mut StyleSheet { +) -> FfiResult<*mut StyleSheet> { + check_null!( + style_text_ptr, + FfiErrorCode::StyleTextNullPointer, + null_mut() + ); let style_text = CStr::from_ptr(style_text_ptr).to_string_lossy(); let (compiled_style_sheet, _) = parser::parse_style_sheet("string", &style_text); let style_sheet = StyleSheet::from_sheet(&compiled_style_sheet); - Box::into_raw(Box::new(style_sheet)) + FfiResult::ok(Box::into_raw(Box::new(style_sheet))) } + /// # Safety +/// Parse the selector from the string. +/// +/// # Arguments +/// * `selector_text_ptr` - Pointer to the selector text +/// +/// # Examples /// -#[no_mangle] +/// ```c +/// FPParseSelectorFromString(selector_text_ptr); +/// ``` +/// +#[export_name = "FPParseSelectorFromString"] pub unsafe extern "C" fn parse_selector_from_string( selector_text_ptr: *const c_char, -) -> *mut Selector { +) -> FfiResult<*mut Selector> { + check_null!( + selector_text_ptr, + FfiErrorCode::SelectorTextNullPointer, + null_mut() + ); let selector_text = CStr::from_ptr(selector_text_ptr).to_string_lossy(); let selector = Selector::from_string(&selector_text); - Box::into_raw(Box::new(selector)) + FfiResult::ok(Box::into_raw(Box::new(selector))) } + /// # Safety +/// Free the selector. +/// +/// # Arguments +/// * `selector` - Pointer to the selector +/// +/// # Examples +/// +/// ```c +/// FPSelectorFree(selector); +/// ``` /// -#[no_mangle] -pub unsafe extern "C" fn selector_free(selector: *mut Selector) { +#[export_name = "FPSelectorFree"] +pub unsafe extern "C" fn selector_free(selector: *mut Selector) -> FfiResult { + check_null!(selector, FfiErrorCode::SelectorNullPointer, null()); drop(Box::from_raw(selector)); + FfiResult::ok(null()) } + /// # Safety +/// Free the style sheet. +/// +/// # Arguments +/// * `style_sheet` - Pointer to the style sheet +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetFree(style_sheet); +/// ``` /// -#[no_mangle] -pub unsafe extern "C" fn style_sheet_free(style_sheet: *mut StyleSheet) { +#[export_name = "FPStyleSheetFree"] +pub unsafe extern "C" fn style_sheet_free(style_sheet: *mut StyleSheet) -> FfiResult { + check_null!(style_sheet, FfiErrorCode::StyleSheetNullPointer, null()); drop(Box::from_raw(style_sheet)); + FfiResult::ok(null()) } + /// # Safety +/// Get the version of the style sheet in the binary format. +/// +/// # Arguments +/// * `buffer_ptr` - Pointer to the buffer +/// * `buffer_len` - Length of the buffer +/// +/// # Examples +/// +/// ```c +/// FPStyleSheetBincodeVersion(buffer_ptr, buffer_len); +/// ``` /// #[cfg(feature = "deserialize")] -#[no_mangle] +#[export_name = "FPStyleSheetBincodeVersion"] pub unsafe extern "C" fn style_sheet_bincode_version( buffer_ptr: *mut u8, buffer_len: usize, -) -> *mut StrRef { +) -> FfiResult<*mut StrRef> { use float_pigment_consistent_bincode::Options; + check_null!(buffer_ptr, FfiErrorCode::BufferNullPointer, null_mut()); let sheet = de_static_ref_zero_copy_env( core::slice::from_raw_parts_mut(buffer_ptr, buffer_len), |s| { @@ -553,58 +1117,110 @@ pub unsafe extern "C" fn style_sheet_bincode_version( StyleSheet::V1(v1) => v1.version, _ => Box::new("unknown version".into()), }; - Box::into_raw(version) + FfiResult::ok(Box::into_raw(version)) } + /// # Safety +/// Get the version of the CSS parser. +/// +/// # Examples /// -#[no_mangle] -pub unsafe extern "C" fn css_parser_version() -> *mut StrRef { +/// ```c +/// FPCssParserVersion(); +/// ``` +#[export_name = "FPCssParserVersion"] +pub unsafe extern "C" fn css_parser_version() -> FfiResult<*mut StrRef> { let version = env!("CARGO_PKG_VERSION").to_string().into(); - Box::into_raw(Box::new(version)) + FfiResult::ok(Box::into_raw(Box::new(version))) } #[repr(C)] -#[derive(Debug)] +#[derive(Debug, Default)] pub struct ColorValue { red: u8, green: u8, blue: u8, alpha: u8, } + /// # Safety +/// Parse the color from the string. +/// +/// # Arguments +/// * `source` - Pointer to the source string +/// +/// # Examples /// -#[no_mangle] -pub unsafe extern "C" fn parse_color_from_string(source: *const c_char) -> ColorValue { +/// ```c +/// FPParseColorFromString(source); +/// ``` +/// +#[export_name = "FPParseColorFromString"] +pub unsafe extern "C" fn parse_color_from_string(source: *const c_char) -> FfiResult { + check_null!( + source, + FfiErrorCode::SourceNullPointer, + ColorValue::default() + ); let source = CStr::from_ptr(source).to_string_lossy(); let ret = parse_color_to_rgba(&source); - ColorValue { + FfiResult::ok(ColorValue { red: ret.0, green: ret.1, blue: ret.2, alpha: ret.3, - } + }) } /// # Safety +/// Substitute the variable in the expression. +/// +/// # Arguments +/// * `expr_ptr` - Pointer to the expression +/// * `map` - Pointer to the map +/// * `getter` - Custom property getter +/// * `setter` - Custom property setter +/// +/// # Examples +/// +/// ```c +/// FPSubstituteVariable(expr_ptr, map, getter, setter); +/// ``` /// -#[no_mangle] +#[export_name = "FPSubstituteVariable"] pub unsafe extern "C" fn substitute_variable( expr_ptr: *const c_char, - map: *mut (), + map: RawMutPtr, getter: CustomPropertyGetter, setter: CustomPropertySetter, -) -> *const c_char { +) -> FfiResult<*const c_char> { + check_null!(expr_ptr, FfiErrorCode::ExprPtrNullPointer, null()); + check_null!(map, FfiErrorCode::MapNullPointer, null()); let expr = CStr::from_ptr(expr_ptr).to_string_lossy(); let context = CustomPropertyContext::create(map, getter, setter); if let Some(ret) = parser::property_value::var::substitute_variable(&expr, &context) { - CString::new(ret).expect("CString new error").into_raw() - } else { - null() + if let Ok(r) = CString::new(ret) { + return FfiResult::ok(r.into_raw()); + } } + FfiResult::ok(null()) } + /// # Safety +/// Free the string. +/// +/// # Arguments +/// * `ptr` - Pointer to the string +/// +/// # Examples +/// +/// ```c +/// FPStrFree(ptr); +/// ``` /// -#[no_mangle] -pub unsafe extern "C" fn str_free(ptr: *const c_char) { - drop(CString::from_raw(ptr as *mut _)); +#[export_name = "FPStrFree"] +pub unsafe extern "C" fn str_free(ptr: *const c_char) -> FfiResult { + check_null!(ptr, FfiErrorCode::StrNullPointer, null()); + drop(CString::from_raw(ptr as *mut c_char)); + FfiResult::ok(null()) } diff --git a/float-pigment-css/src/parser/hooks.rs b/float-pigment-css/src/parser/hooks.rs index 26e33d8..1bca936 100644 --- a/float-pigment-css/src/parser/hooks.rs +++ b/float-pigment-css/src/parser/hooks.rs @@ -1,12 +1,17 @@ //! Parser hooks can be used to attach some compilation information. use alloc::vec::Vec; + #[cfg(feature = "ffi")] use core::ffi::{c_char, CStr}; use cssparser::SourceLocation; use super::{Warning, WarningKind}; + +#[cfg(feature = "ffi")] +use crate::ffi::{FfiResult, NullPtr}; + use crate::property::Property; /// A `context` for current sompilation step. @@ -53,10 +58,18 @@ impl CParserHooksContext { /// /// The message should be a valid C string. #[no_mangle] - pub unsafe extern "C" fn generate_warning(&mut self, message: *const c_char) { + pub unsafe extern "C" fn generate_warning( + &mut self, + message: *const c_char, + ) -> FfiResult { + use crate::check_null; + use crate::ffi::FfiErrorCode; + use core::ptr::null; + check_null!(message, FfiErrorCode::StrNullPointer, null()); let message = CStr::from_ptr(message).to_string_lossy(); let ctx = &mut *(self.inner as *mut ParserHooksContext); ctx.generate_warning(&message); + FfiResult::ok(null()) } } diff --git a/float-pigment-css/src/path.rs b/float-pigment-css/src/path.rs index 8c035b1..d538dab 100644 --- a/float-pigment-css/src/path.rs +++ b/float-pigment-css/src/path.rs @@ -3,7 +3,7 @@ use alloc::string::String; pub(crate) fn resolve(base: &str, rel: &str) -> String { let mut slices = vec![]; let mut extra_parent_count = 0; - let from_root = base.starts_with("/") || rel.starts_with("/"); + let from_root = base.starts_with('/') || rel.starts_with('/'); let main = if let Some(rel) = rel.strip_prefix('/') { rel } else { diff --git a/float-pigment-css/src/sheet/mod.rs b/float-pigment-css/src/sheet/mod.rs index c354b50..5aceb71 100644 --- a/float-pigment-css/src/sheet/mod.rs +++ b/float-pigment-css/src/sheet/mod.rs @@ -130,7 +130,7 @@ impl CompiledStyleSheet { let m = match media.clone() { None => parent_media.clone(), Some(mut m) => { - Rc::make_mut(&mut m).parent = parent_media.clone(); + Rc::make_mut(&mut m).parent.clone_from(&parent_media); Some(m) } }; diff --git a/float-pigment-css/tests/serde.rs b/float-pigment-css/tests/serde.rs index 402aef2..0871ec6 100644 --- a/float-pigment-css/tests/serde.rs +++ b/float-pigment-css/tests/serde.rs @@ -22,7 +22,7 @@ fn for_each_serialize_format(s: &str, mut f: impl FnMut(StyleSheetGroup)) { let mut ssg = StyleSheetGroup::new(); let buf = compile_style_sheet_to_json("", s); let mut resource = StyleSheetResource::new(); - resource.add_json("", buf); + resource.add_json("", &buf); ssg.append_from_resource(&resource, "", None); f(ssg); } diff --git a/float-pigment-forest/src/ffi.rs b/float-pigment-forest/src/ffi.rs index ebac911..b5c357a 100644 --- a/float-pigment-forest/src/ffi.rs +++ b/float-pigment-forest/src/ffi.rs @@ -432,9 +432,9 @@ pub unsafe extern "C" fn NodeClearMeasureFunc(node: NodePtr) { /// # Safety /// #[no_mangle] -pub unsafe extern "C" fn NodeHasMeasureFunc(node: NodePtr) { +pub unsafe extern "C" fn NodeHasMeasureFunc(node: NodePtr) -> bool { let node = &*(node.ptr as *mut Node); - node.has_measure_func(); + node.has_measure_func() } /// # Safety