From 520a7c8ebdeeeb7e16ef88e68c1b5ada8a807275 Mon Sep 17 00:00:00 2001 From: R-Goc Date: Wed, 27 May 2026 20:08:22 +0200 Subject: [PATCH] AK+LibWeb: Centralize FFI helper functions This commit creates a central FFIHelpers.h header which implements common conversions from FFI. --- AK/CMakeLists.txt | 1 + AK/FFIHelpers.cpp | 34 ++++++++++++++ AK/FFIHelpers.h | 25 +++++++++++ Libraries/LibWeb/CSS/Parser/RustTokenizer.cpp | 19 ++------ Libraries/LibWeb/HTML/Parser/HTMLParser.cpp | 44 ++++++------------- .../LibWeb/HTML/Parser/HTMLTokenizer.cpp | 8 +--- .../HTML/Parser/SpeculativeHTMLParser.cpp | 8 +--- 7 files changed, 79 insertions(+), 60 deletions(-) create mode 100644 AK/FFIHelpers.cpp create mode 100644 AK/FFIHelpers.h diff --git a/AK/CMakeLists.txt b/AK/CMakeLists.txt index 65d4a88594..fd328dc18a 100644 --- a/AK/CMakeLists.txt +++ b/AK/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES ConstrainedStream.cpp CountingStream.cpp Error.cpp + FFIHelpers.cpp FlyString.cpp Format.cpp GenericLexer.cpp diff --git a/AK/FFIHelpers.cpp b/AK/FFIHelpers.cpp new file mode 100644 index 0000000000..b20472f61c --- /dev/null +++ b/AK/FFIHelpers.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026-present, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +namespace AK { + +FlyString ffi_fly_string(u8 const* ptr, size_t len) +{ + return MUST(FlyString::from_utf8(ffi_string_view(ptr, len))); +} + +String ffi_string(u8 const* ptr, size_t len) +{ + return MUST(String::from_utf8(ffi_string_view(ptr, len))); +} + +StringView ffi_string_view(u8 const* ptr, size_t len) +{ + // NOTE: A zero length C string is valid + if (ptr == nullptr) + return {}; + return { ptr, len }; +} + +} diff --git a/AK/FFIHelpers.h b/AK/FFIHelpers.h new file mode 100644 index 0000000000..71d6714d4f --- /dev/null +++ b/AK/FFIHelpers.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026-present, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace AK { + +FlyString ffi_fly_string(u8 const* ptr, size_t len); + +String ffi_string(u8 const* ptr, size_t len); + +StringView ffi_string_view(u8 const* ptr, size_t len); + +} + +#ifdef USING_AK_GLOBALLY +using AK::ffi_fly_string; +using AK::ffi_string; +using AK::ffi_string_view; +#endif diff --git a/Libraries/LibWeb/CSS/Parser/RustTokenizer.cpp b/Libraries/LibWeb/CSS/Parser/RustTokenizer.cpp index 8a2a57fc2f..a0e2886184 100644 --- a/Libraries/LibWeb/CSS/Parser/RustTokenizer.cpp +++ b/Libraries/LibWeb/CSS/Parser/RustTokenizer.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -88,20 +89,6 @@ static String decode_and_filter_code_points(StringView input, StringView encodin return builder.to_string_without_validation(); } -static String string_from_ffi_bytes(u8 const* bytes, size_t length) -{ - if (length == 0) - return {}; - return String::from_utf8_without_validation({ bytes, length }); -} - -static FlyString fly_string_from_ffi_bytes(u8 const* bytes, size_t length) -{ - if (length == 0) - return {}; - return FlyString::from_utf8_without_validation({ bytes, length }); -} - static Number::Type css_number_type_from_ffi(FFI::CssNumberType number_type) { switch (number_type) { @@ -122,8 +109,8 @@ static Token::Position position_from_ffi(size_t line, size_t column) Token RustTokenizer::token_from_ffi(FFI::CssToken const& ffi_token) { - auto original_source_text = string_from_ffi_bytes(ffi_token.original_source_ptr, ffi_token.original_source_len); - auto payload = fly_string_from_ffi_bytes(ffi_token.value_ptr, ffi_token.value_len); + auto original_source_text = ffi_string(ffi_token.original_source_ptr, ffi_token.original_source_len); + auto payload = ffi_fly_string(ffi_token.value_ptr, ffi_token.value_len); Token token; switch (ffi_token.token_type) { diff --git a/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index c060a5d498..f60889c041 100644 --- a/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -1732,27 +1733,10 @@ void HTMLParser::abort() m_aborted = true; } -static StringView html_parser_ffi_string_view(u8 const* ptr, size_t len) -{ - if (ptr == nullptr || len == 0) - return {}; - return { ptr, len }; -} - -static FlyString fly_string_from_html_parser_ffi(u8 const* ptr, size_t len) -{ - return MUST(FlyString::from_utf8(html_parser_ffi_string_view(ptr, len))); -} - -static String string_from_html_parser_ffi(u8 const* ptr, size_t len) -{ - return MUST(String::from_utf8(html_parser_ffi_string_view(ptr, len))); -} - extern "C" void ladybird_html_parser_log_parse_error(void* parser, u8 const* message_ptr, size_t message_len) { (void)parser_from_html_parser_ffi(parser); - dbgln_if(HTML_PARSER_DEBUG, "Rust parser parse error: {}", html_parser_ffi_string_view(message_ptr, message_len)); + dbgln_if(HTML_PARSER_DEBUG, "Rust parser parse error: {}", ffi_string_view(message_ptr, message_len)); } extern "C" void ladybird_html_parser_stop_parsing(void* parser) @@ -1784,7 +1768,7 @@ static Optional namespace_from_html_parser_ffi(RustFfiHtmlNamespace n case RustFfiHtmlNamespace::Other: if (namespace_uri_len == 0) return {}; - return fly_string_from_html_parser_ffi(namespace_uri_ptr, namespace_uri_len); + return ffi_fly_string(namespace_uri_ptr, namespace_uri_len); } VERIFY_NOT_REACHED(); } @@ -1896,16 +1880,16 @@ extern "C" size_t ladybird_html_parser_create_document_type(void* parser, u8 con { auto& html_parser = parser_from_html_parser_ffi(parser); auto document_type = html_parser.document().realm().create(html_parser.document()); - document_type->set_name(string_from_html_parser_ffi(name_ptr, name_len)); - document_type->set_public_id(string_from_html_parser_ffi(public_id_ptr, public_id_len)); - document_type->set_system_id(string_from_html_parser_ffi(system_id_ptr, system_id_len)); + document_type->set_name(ffi_string(name_ptr, name_len)); + document_type->set_public_id(ffi_string(public_id_ptr, public_id_len)); + document_type->set_system_id(ffi_string(system_id_ptr, system_id_len)); return reinterpret_cast(document_type.ptr()); } extern "C" size_t ladybird_html_parser_create_comment(void* parser, u8 const* data_ptr, size_t data_len) { auto& html_parser = parser_from_html_parser_ffi(parser); - auto comment = html_parser.document().realm().create(html_parser.document(), Utf16String::from_utf8(string_from_html_parser_ffi(data_ptr, data_len))); + auto comment = html_parser.document().realm().create(html_parser.document(), Utf16String::from_utf8(ffi_string(data_ptr, data_len))); return reinterpret_cast(comment.ptr()); } @@ -1915,7 +1899,7 @@ extern "C" void ladybird_html_parser_insert_text(size_t parent, size_t before, u if (parent_node.is_document()) return; - auto data = Utf16String::from_utf8(string_from_html_parser_ffi(data_ptr, data_len)); + auto data = Utf16String::from_utf8(ffi_string(data_ptr, data_len)); if (before) { auto& before_node = node_from_html_parser_ffi(before); if (auto* previous_text = as_if(before_node.previous_sibling())) { @@ -1939,10 +1923,10 @@ extern "C" void ladybird_html_parser_insert_text(size_t parent, size_t before, u extern "C" void ladybird_html_parser_add_missing_attribute(size_t element, u8 const* local_name_ptr, size_t local_name_len, u8 const* value_ptr, size_t value_len) { auto& dom_element = as(node_from_html_parser_ffi(element)); - auto local_name = fly_string_from_html_parser_ffi(local_name_ptr, local_name_len); + auto local_name = ffi_fly_string(local_name_ptr, local_name_len); if (dom_element.has_attribute(local_name)) return; - dom_element.append_attribute(local_name, string_from_html_parser_ffi(value_ptr, value_len)); + dom_element.append_attribute(local_name, ffi_string(value_ptr, value_len)); } extern "C" void ladybird_html_parser_remove_node(size_t node) @@ -1986,19 +1970,19 @@ extern "C" size_t ladybird_html_parser_parent_node(size_t node) extern "C" size_t ladybird_html_parser_create_element(void* parser, size_t intended_parent, RustFfiHtmlNamespace namespace_, u8 const* namespace_uri_ptr, size_t namespace_uri_len, u8 const* local_name_ptr, size_t local_name_len, RustFfiHtmlParserAttribute const* attributes, size_t attribute_count, bool had_duplicate_attribute, size_t form_element, bool has_template_element_on_stack) { auto& html_parser = parser_from_html_parser_ffi(parser); - auto local_name = fly_string_from_html_parser_ffi(local_name_ptr, local_name_len); + auto local_name = ffi_fly_string(local_name_ptr, local_name_len); auto token = HTMLToken::make_start_tag(local_name); for (size_t i = 0; i < attribute_count; ++i) { auto const& attribute = attributes[i]; Optional prefix; if (attribute.prefix_len != 0) - prefix = fly_string_from_html_parser_ffi(attribute.prefix_ptr, attribute.prefix_len); + prefix = ffi_fly_string(attribute.prefix_ptr, attribute.prefix_len); HTMLToken::Attribute token_attribute; token_attribute.prefix = move(prefix); - token_attribute.local_name = fly_string_from_html_parser_ffi(attribute.local_name_ptr, attribute.local_name_len); + token_attribute.local_name = ffi_fly_string(attribute.local_name_ptr, attribute.local_name_len); token_attribute.namespace_ = attribute_namespace_from_html_parser_ffi(attribute.namespace_); - token_attribute.value = string_from_html_parser_ffi(attribute.value_ptr, attribute.value_len); + token_attribute.value = ffi_string(attribute.value_ptr, attribute.value_len); token.add_attribute(move(token_attribute)); } diff --git a/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp b/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp index 29779aa314..fba54b0f83 100644 --- a/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp +++ b/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -26,13 +27,6 @@ static Vector code_points_from_string(String const& string) return code_points; } -static StringView ffi_string_view(u8 const* ptr, size_t len) -{ - if (ptr == nullptr || len == 0) - return {}; - return { ptr, len }; -} - static RustFfiTokenizerHandle* create_tokenizer_from_utf8(StringView utf8_bytes) { auto* bytes = reinterpret_cast(utf8_bytes.characters_without_null_termination()); diff --git a/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.cpp b/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.cpp index 2b9890d24a..0d71432d5e 100644 --- a/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.cpp +++ b/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -71,13 +72,6 @@ void SpeculativeHTMLParser::run() namespace { -StringView ffi_string_view(u8 const* ptr, size_t len) -{ - if (ptr == nullptr || len == 0) - return {}; - return { ptr, len }; -} - Optional destination_from_preload_scanner(RustFfiPreloadScannerDestination destination) { switch (destination) {