LibWeb: Add adblock-rust FFI hooks

Add adblock-rust to a dedicated LibWeb content blocker Rust crate
and expose FFI entry points for creating an engine, matching network
requests, and producing cosmetic CSS. Export a string result type for
returning generated CSS to C++ callers.

Regenerate the Flatpak cargo source list for the new Rust
dependencies.
This commit is contained in:
Andreas Kling 2026-05-23 22:14:22 +02:00 committed by Andreas Kling
parent 6c162d8b5d
commit bcdbdbb5b3
8 changed files with 741 additions and 8 deletions

240
Cargo.lock generated
View file

@ -2,6 +2,41 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "adblock"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6fe7702c798519299bcbe011ff6f1dc9e3aedc1f3171178cddf71e1736bf95"
dependencies = [
"addr",
"arrayvec",
"base64",
"bitflags",
"flatbuffers",
"idna",
"itertools",
"memchr",
"percent-encoding",
"precomputed-hash",
"regex",
"rustc-hash 1.1.0",
"seahash",
"serde",
"serde_json",
"thiserror",
"url",
]
[[package]]
name = "addr"
version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a93b8a41dbe230ad5087cc721f8d41611de654542180586b315d9f4cf6b72bef"
dependencies = [
"psl",
"psl-types",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
@ -79,17 +114,32 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
dependencies = [
"serde_core",
]
[[package]]
name = "bumpalo"
@ -225,7 +275,7 @@ dependencies = [
"hashbrown 0.14.5",
"log",
"regalloc2",
"rustc-hash",
"rustc-hash 2.1.2",
"serde",
"smallvec",
"target-lexicon",
@ -315,6 +365,12 @@ dependencies = [
"syn",
]
[[package]]
name = "either"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
[[package]]
name = "encoding_rs"
version = "0.8.35"
@ -352,12 +408,31 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f"
[[package]]
name = "flatbuffers"
version = "25.12.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3"
dependencies = [
"bitflags",
"rustc_version",
]
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
[[package]]
name = "getrandom"
version = "0.4.2"
@ -481,6 +556,46 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fdcc9ac77c6d74ff5cf6e65ef3181d6af32003b16fce3a77fb451d2f695993"
[[package]]
name = "icu_normalizer"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
dependencies = [
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
[[package]]
name = "icu_properties"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
dependencies = [
"icu_collections",
"icu_locale_core",
"icu_properties_data",
"icu_provider",
"zerotrie",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
[[package]]
name = "icu_provider"
version = "2.2.0"
@ -504,6 +619,27 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "idna"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
dependencies = [
"idna_adapter",
"smallvec",
"utf8_iter",
]
[[package]]
name = "idna_adapter"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
dependencies = [
"icu_normalizer",
"icu_properties",
]
[[package]]
name = "indexmap"
version = "2.13.1"
@ -522,6 +658,15 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.18"
@ -605,6 +750,15 @@ dependencies = [
"target-lexicon",
]
[[package]]
name = "libweb_content_blocker_rust"
version = "0.1.0"
dependencies = [
"adblock",
"cbindgen",
"serde_json",
]
[[package]]
name = "libweb_html_tokenizer"
version = "0.1.0"
@ -685,6 +839,12 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "potential_utf"
version = "0.1.5"
@ -696,6 +856,12 @@ dependencies = [
"zerovec",
]
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "prettyplease"
version = "0.2.37"
@ -715,6 +881,21 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "psl"
version = "2.1.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27fbd4d9b2eb0b6e0cbd654bce70243f460cbc8dc92df6747e3fb911ce1cd4a8"
dependencies = [
"psl-types",
]
[[package]]
name = "psl-types"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
[[package]]
name = "quote"
version = "1.0.45"
@ -740,7 +921,7 @@ dependencies = [
"bumpalo",
"hashbrown 0.15.5",
"log",
"rustc-hash",
"rustc-hash 2.1.2",
"smallvec",
]
@ -773,12 +954,27 @@ version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc-hash"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "1.1.4"
@ -792,6 +988,12 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "semver"
version = "1.0.28"
@ -909,6 +1111,26 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinystr"
version = "0.8.3"
@ -971,6 +1193,18 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "url"
version = "2.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
"serde",
]
[[package]]
name = "utf8_iter"
version = "1.0.4"
@ -1216,6 +1450,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
"zerovec",
]

View file

@ -5,6 +5,7 @@ members = [
"Libraries/LibRegex/Rust",
"Libraries/LibUnicode/Rust",
"Libraries/LibWasm/Rust",
"Libraries/LibWeb/ContentBlocker/Rust",
"Libraries/LibWeb/Rust",
"Libraries/LibWeb/HTML/Parser/Rust",
]

View file

@ -1254,8 +1254,10 @@ ladybird_lib(LibWeb web EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibWeb PRIVATE LibCore LibCompress LibCrypto LibJS LibHTTP LibGfx LibIPC LibRegex LibSyntax LibTextCodec LibUnicode LibMedia LibWasm LibXML LibIDL LibURL LibTLS LibRequests LibGC LibSync LibThreading skia ${ANGLE_TARGETS} SDL3::SDL3 LibXml2::LibXml2)
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libweb_rust FFI_HEADER RustFFI.h)
target_link_libraries(LibWeb PRIVATE libweb_rust)
import_rust_crate(MANIFEST_PATH ContentBlocker/Rust/Cargo.toml CRATE_NAME libweb_content_blocker_rust FFI_HEADER ContentBlockerRustFFI.h)
target_link_libraries(LibWeb PRIVATE libweb_rust libweb_content_blocker_rust)
get_target_property(_libweb_rust_lib libweb_rust IMPORTED_LOCATION)
get_target_property(_libweb_content_blocker_rust_lib libweb_content_blocker_rust IMPORTED_LOCATION)
set_property(SOURCE HTML/Parser/HTMLTokenizer.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libweb_rust_lib})
set_property(SOURCE HTML/Parser/HTMLParser.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libweb_rust_lib})
set_property(SOURCE HTML/Parser/SpeculativeHTMLParser.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libweb_rust_lib})
@ -1266,6 +1268,7 @@ endif()
if(NOT BUILD_SHARED_LIBS)
add_custom_command(TARGET LibWeb POST_BUILD
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:libweb_rust>
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:libweb_content_blocker_rust>
COMMAND ${CMAKE_AR} -qS $<TARGET_FILE:LibWeb> *.o
COMMAND ${CMAKE_RANLIB} $<TARGET_FILE:LibWeb>
COMMAND ${CMAKE_COMMAND} -E remove -f *.o
@ -1274,14 +1277,14 @@ if(NOT BUILD_SHARED_LIBS)
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/rust_merge_tmp)
# POST_BUILD steps don't track inputs, so when libweb_rust.a changes
# POST_BUILD steps don't track inputs, so when a Rust archive changes
# ninja leaves liblagom-web.a alone and the merged archive ends up with
# stale Rust objects. Force both FFI bridge files to depend on the
# Rust archive: when it changes, they recompile, LibWeb re-archives, and
# POST_BUILD re-merges the fresh Rust objects.
get_target_property(_libweb_rust_lib libweb_rust IMPORTED_LOCATION)
# stale Rust objects. Force the C++ FFI bridge files to depend on the
# Rust archives: when they change, LibWeb re-archives, and POST_BUILD
# re-merges the fresh Rust objects.
set_property(SOURCE CSS/Parser/RustTokenizer.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libweb_rust_lib})
set_property(SOURCE HTML/Parser/HTMLEncodingDetection.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libweb_rust_lib})
set_property(SOURCE Loader/ContentBlocker.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libweb_content_blocker_rust_lib})
endif()
if (HAS_FONTCONFIG)

View file

@ -0,0 +1,19 @@
[package]
name = "libweb_content_blocker_rust"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["staticlib"]
# After changing dependencies, regenerate the Flatpak sources:
# python3 Meta/CMake/flatpak/generate-cargo-sources.py
[dependencies]
adblock = "0.12.5"
serde_json = "1.0"
[build-dependencies]
cbindgen = "0.29"
[lints]
workspace = true

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
use std::env;
use std::error::Error;
use std::path::PathBuf;
fn main() -> Result<(), Box<dyn Error>> {
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
let out_dir = PathBuf::from(env::var("OUT_DIR")?);
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=cbindgen.toml");
println!("cargo:rerun-if-env-changed=FFI_OUTPUT_DIR");
println!("cargo:rerun-if-changed=src");
let ffi_out_dir = env::var("FFI_OUTPUT_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| out_dir.clone());
cbindgen::generate(manifest_dir).map_or_else(
|error| match error {
cbindgen::Error::ParseSyntaxError { .. } => {}
other => panic!("{other:?}"),
},
|bindings| {
let header_path = out_dir.join("ContentBlockerRustFFI.h");
bindings.write_to_file(&header_path);
if ffi_out_dir != out_dir {
bindings.write_to_file(ffi_out_dir.join("ContentBlockerRustFFI.h"));
}
},
);
Ok(())
}

View file

@ -0,0 +1,26 @@
language = "C++"
header = """/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/"""
pragma_once = true
include_version = true
namespaces = ["Web", "ContentBlocking", "FFI"]
line_length = 120
tab_width = 4
no_includes = true
sys_includes = ["stdint.h", "stddef.h"]
usize_is_size_t = true
[parse]
parse_deps = false
[parse.expand]
all_features = false
[export]
include = ["ContentBlockerString"]
[export.mangle]
rename_types = "PascalCase"

View file

@ -0,0 +1,216 @@
/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
use std::ffi::c_void;
use std::panic::{AssertUnwindSafe, catch_unwind};
#[repr(C)]
pub struct ContentBlockerString {
data: *mut u8,
length: usize,
}
fn abort_on_panic<F: FnOnce() -> R, R>(f: F) -> R {
match catch_unwind(AssertUnwindSafe(f)) {
Ok(result) => result,
Err(payload) => {
let message = if let Some(message) = payload.downcast_ref::<&str>() {
(*message).to_string()
} else if let Some(message) = payload.downcast_ref::<String>() {
message.clone()
} else {
"unknown panic".to_string()
};
eprintln!("Rust panic at FFI boundary: {message}");
std::process::abort();
}
}
}
unsafe fn bytes_from_raw<'a>(bytes: *const u8, len: usize) -> Option<&'a [u8]> {
if len == 0 {
return Some(&[]);
}
if bytes.is_null() {
return None;
}
Some(unsafe { std::slice::from_raw_parts(bytes, len) })
}
unsafe fn string_from_raw<'a>(bytes: *const u8, len: usize) -> Option<&'a str> {
let bytes = unsafe { bytes_from_raw(bytes, len)? };
std::str::from_utf8(bytes).ok()
}
unsafe fn engine_from_raw<'a>(engine: *const c_void) -> Option<&'a adblock::engine::Engine> {
if engine.is_null() {
return None;
}
Some(unsafe { &*engine.cast::<adblock::engine::Engine>() })
}
fn string_to_ffi(string: String) -> ContentBlockerString {
if string.is_empty() {
return ContentBlockerString {
data: std::ptr::null_mut(),
length: 0,
};
}
let bytes = Box::leak(string.into_bytes().into_boxed_slice());
let data = bytes.as_mut_ptr();
let length = bytes.len();
ContentBlockerString { data, length }
}
fn cosmetic_css_for_url(
engine: &adblock::engine::Engine,
url: &str,
classes: impl IntoIterator<Item = impl AsRef<str>>,
ids: impl IntoIterator<Item = impl AsRef<str>>,
) -> String {
let resources = engine.url_cosmetic_resources(url);
let mut selectors = resources.hide_selectors;
if !resources.generichide {
selectors.extend(engine.hidden_class_id_selectors(classes, ids, &resources.exceptions));
}
let mut selector_styles: Vec<_> = selectors
.into_iter()
.map(|selector| (selector, "display: none !important".to_string()))
.collect();
for action in resources.procedural_actions {
let Ok(filter) = serde_json::from_str::<adblock::cosmetic_filter_cache::ProceduralOrActionFilter>(&action)
else {
continue;
};
if let Some((selector, style)) = filter.as_css() {
selector_styles.push((selector, style));
}
}
selector_styles.sort_unstable();
selector_styles.dedup();
let mut css = String::new();
for (selector, style) in selector_styles {
css.push_str(&selector);
css.push_str(" { ");
css.push_str(&style);
if !style.trim_end().ends_with(';') {
css.push(';');
}
css.push_str(" }\n");
}
css
}
/// # Safety
/// - `rules` and `rules_len` must point to a valid UTF-8 string
/// - The returned pointer must be freed with `rust_content_blocker_free`
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_content_blocker_create(rules: *const u8, rules_len: usize) -> *mut c_void {
abort_on_panic(|| {
let Some(rules) = (unsafe { string_from_raw(rules, rules_len) }) else {
return std::ptr::null_mut();
};
let engine = adblock::engine::Engine::from_rules(rules.lines(), adblock::lists::ParseOptions::default());
Box::into_raw(Box::new(engine)).cast()
})
}
/// # Safety
/// - `engine` must be null or a valid pointer returned by `rust_content_blocker_create`
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_content_blocker_free(engine: *mut c_void) {
abort_on_panic(|| {
if !engine.is_null() {
drop(unsafe { Box::from_raw(engine.cast::<adblock::engine::Engine>()) });
}
});
}
/// # Safety
/// - `engine` must be null or a valid pointer returned by `rust_content_blocker_create`
/// - String pointers and lengths must point to valid UTF-8 strings
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_content_blocker_matches(
engine: *const c_void,
url: *const u8,
url_len: usize,
source_url: *const u8,
source_url_len: usize,
request_type: *const u8,
request_type_len: usize,
) -> bool {
abort_on_panic(|| {
let Some(engine) = (unsafe { engine_from_raw(engine) }) else {
return false;
};
let Some(url) = (unsafe { string_from_raw(url, url_len) }) else {
return false;
};
let Some(source_url) = (unsafe { string_from_raw(source_url, source_url_len) }) else {
return false;
};
let Some(request_type) = (unsafe { string_from_raw(request_type, request_type_len) }) else {
return false;
};
let Ok(request) = adblock::request::Request::new(url, source_url, request_type) else {
return false;
};
engine.check_network_request(&request).matched
})
}
/// # Safety
/// - `engine` must be null or a valid pointer returned by `rust_content_blocker_create`
/// - String pointers and lengths must point to valid UTF-8 strings
/// - The returned string must be freed with `rust_content_blocker_free_string`
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_content_blocker_cosmetic_css(
engine: *const c_void,
url: *const u8,
url_len: usize,
classes: *const u8,
classes_len: usize,
ids: *const u8,
ids_len: usize,
) -> ContentBlockerString {
abort_on_panic(|| {
let Some(engine) = (unsafe { engine_from_raw(engine) }) else {
return string_to_ffi(String::new());
};
let Some(url) = (unsafe { string_from_raw(url, url_len) }) else {
return string_to_ffi(String::new());
};
let Some(classes) = (unsafe { string_from_raw(classes, classes_len) }) else {
return string_to_ffi(String::new());
};
let Some(ids) = (unsafe { string_from_raw(ids, ids_len) }) else {
return string_to_ffi(String::new());
};
string_to_ffi(cosmetic_css_for_url(engine, url, classes.lines(), ids.lines()))
})
}
/// # Safety
/// - `data` and `length` must match a string returned by `rust_content_blocker_cosmetic_css`
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_content_blocker_free_string(data: *mut u8, length: usize) {
abort_on_panic(|| {
if !data.is_null() {
drop(unsafe { Box::from_raw(std::ptr::slice_from_raw_parts_mut(data, length)) });
}
});
}

View file

@ -5,6 +5,20 @@
"tag": "v0.5.1",
"dest": "corrosion"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/adblock/adblock-0.12.5.crate",
"sha256": "db6fe7702c798519299bcbe011ff6f1dc9e3aedc1f3171178cddf71e1736bf95",
"dest": "cargo/vendor/adblock-0.12.5"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/addr/addr-0.15.6.crate",
"sha256": "a93b8a41dbe230ad5087cc721f8d41611de654542180586b315d9f4cf6b72bef",
"dest": "cargo/vendor/addr-0.15.6"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -68,6 +82,13 @@
"sha256": "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1",
"dest": "cargo/vendor/arbitrary-1.4.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/arrayvec/arrayvec-0.7.6.crate",
"sha256": "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50",
"dest": "cargo/vendor/arrayvec-0.7.6"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -75,6 +96,13 @@
"sha256": "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8",
"dest": "cargo/vendor/autocfg-1.5.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/base64/base64-0.22.1.crate",
"sha256": "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6",
"dest": "cargo/vendor/base64-0.22.1"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -236,6 +264,13 @@
"sha256": "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0",
"dest": "cargo/vendor/displaydoc-0.2.5"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/either/either-1.16.0.crate",
"sha256": "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e",
"dest": "cargo/vendor/either-1.16.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -271,6 +306,13 @@
"sha256": "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f",
"dest": "cargo/vendor/fastrand-2.4.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/flatbuffers/flatbuffers-25.12.19.crate",
"sha256": "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3",
"dest": "cargo/vendor/flatbuffers-25.12.19"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -278,6 +320,13 @@
"sha256": "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2",
"dest": "cargo/vendor/foldhash-0.1.5"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/form_urlencoded/form_urlencoded-1.2.2.crate",
"sha256": "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf",
"dest": "cargo/vendor/form_urlencoded-1.2.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -362,6 +411,34 @@
"sha256": "d5fdcc9ac77c6d74ff5cf6e65ef3181d6af32003b16fce3a77fb451d2f695993",
"dest": "cargo/vendor/icu_locale_data-2.2.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_normalizer/icu_normalizer-2.2.0.crate",
"sha256": "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4",
"dest": "cargo/vendor/icu_normalizer-2.2.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_normalizer_data/icu_normalizer_data-2.2.0.crate",
"sha256": "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38",
"dest": "cargo/vendor/icu_normalizer_data-2.2.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_properties/icu_properties-2.2.0.crate",
"sha256": "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de",
"dest": "cargo/vendor/icu_properties-2.2.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/icu_properties_data/icu_properties_data-2.2.0.crate",
"sha256": "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14",
"dest": "cargo/vendor/icu_properties_data-2.2.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -376,6 +453,20 @@
"sha256": "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954",
"dest": "cargo/vendor/id-arena-2.3.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/idna/idna-1.1.0.crate",
"sha256": "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de",
"dest": "cargo/vendor/idna-1.1.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/idna_adapter/idna_adapter-1.2.2.crate",
"sha256": "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714",
"dest": "cargo/vendor/idna_adapter-1.2.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -390,6 +481,13 @@
"sha256": "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695",
"dest": "cargo/vendor/is_terminal_polyfill-1.70.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/itertools/itertools-0.13.0.crate",
"sha256": "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186",
"dest": "cargo/vendor/itertools-0.13.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -488,6 +586,13 @@
"sha256": "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe",
"dest": "cargo/vendor/once_cell_polyfill-1.70.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/percent-encoding/percent-encoding-2.3.2.crate",
"sha256": "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220",
"dest": "cargo/vendor/percent-encoding-2.3.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -495,6 +600,13 @@
"sha256": "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564",
"dest": "cargo/vendor/potential_utf-0.1.5"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/precomputed-hash/precomputed-hash-0.1.1.crate",
"sha256": "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c",
"dest": "cargo/vendor/precomputed-hash-0.1.1"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -509,6 +621,20 @@
"sha256": "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934",
"dest": "cargo/vendor/proc-macro2-1.0.106"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/psl/psl-2.1.210.crate",
"sha256": "27fbd4d9b2eb0b6e0cbd654bce70243f460cbc8dc92df6747e3fb911ce1cd4a8",
"dest": "cargo/vendor/psl-2.1.210"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/psl-types/psl-types-2.0.11.crate",
"sha256": "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac",
"dest": "cargo/vendor/psl-types-2.0.11"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -551,6 +677,13 @@
"sha256": "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a",
"dest": "cargo/vendor/regex-syntax-0.8.10"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/rustc-hash/rustc-hash-1.1.0.crate",
"sha256": "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2",
"dest": "cargo/vendor/rustc-hash-1.1.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -558,6 +691,13 @@
"sha256": "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe",
"dest": "cargo/vendor/rustc-hash-2.1.2"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/rustc_version/rustc_version-0.4.1.crate",
"sha256": "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92",
"dest": "cargo/vendor/rustc_version-0.4.1"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -565,6 +705,13 @@
"sha256": "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190",
"dest": "cargo/vendor/rustix-1.1.4"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/seahash/seahash-4.1.0.crate",
"sha256": "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b",
"dest": "cargo/vendor/seahash-4.1.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -656,6 +803,20 @@
"sha256": "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd",
"dest": "cargo/vendor/tempfile-3.27.0"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/thiserror/thiserror-1.0.69.crate",
"sha256": "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52",
"dest": "cargo/vendor/thiserror-1.0.69"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/thiserror-impl/thiserror-impl-1.0.69.crate",
"sha256": "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1",
"dest": "cargo/vendor/thiserror-impl-1.0.69"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -705,6 +866,13 @@
"sha256": "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853",
"dest": "cargo/vendor/unicode-xid-0.2.6"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/url/url-2.5.8.crate",
"sha256": "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed",
"dest": "cargo/vendor/url-2.5.8"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@ -897,6 +1065,8 @@
{
"type": "shell",
"commands": [
"echo '{\"files\": {}, \"package\": \"db6fe7702c798519299bcbe011ff6f1dc9e3aedc1f3171178cddf71e1736bf95\"}' > cargo/vendor/adblock-0.12.5/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"a93b8a41dbe230ad5087cc721f8d41611de654542180586b315d9f4cf6b72bef\"}' > cargo/vendor/addr-0.15.6/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301\"}' > cargo/vendor/aho-corasick-1.1.4/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923\"}' > cargo/vendor/allocator-api2-0.2.21/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d\"}' > cargo/vendor/anstream-1.0.0/.cargo-checksum.json",
@ -906,7 +1076,9 @@
"echo '{\"files\": {}, \"package\": \"291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d\"}' > cargo/vendor/anstyle-wincon-3.0.11/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c\"}' > cargo/vendor/anyhow-1.0.102/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1\"}' > cargo/vendor/arbitrary-1.4.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50\"}' > cargo/vendor/arrayvec-0.7.6/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8\"}' > cargo/vendor/autocfg-1.5.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6\"}' > cargo/vendor/base64-0.22.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af\"}' > cargo/vendor/bitflags-2.11.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb\"}' > cargo/vendor/bumpalo-3.20.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"5abbd6eeda6885048d357edc66748eea6e0268e3dd11f326fff5bd248d779c26\"}' > cargo/vendor/calendrical_calculations-0.2.4/.cargo-checksum.json",
@ -930,12 +1102,15 @@
"echo '{\"files\": {}, \"package\": \"4d55612bebcf16ff7306c8a6f5bdb6d45662b8aa1ee058ecce8807ad87db719b\"}' > cargo/vendor/cranelift-module-0.116.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"b8dee82f3f1f2c4cba9177f1cc5e350fe98764379bcd29340caa7b01f85076c7\"}' > cargo/vendor/cranelift-native-0.116.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0\"}' > cargo/vendor/displaydoc-0.2.5/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e\"}' > cargo/vendor/either-1.16.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3\"}' > cargo/vendor/encoding_rs-0.8.35/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f\"}' > cargo/vendor/equivalent-1.0.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb\"}' > cargo/vendor/errno-0.3.14/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649\"}' > cargo/vendor/fallible-iterator-0.3.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f\"}' > cargo/vendor/fastrand-2.4.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3\"}' > cargo/vendor/flatbuffers-25.12.19/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2\"}' > cargo/vendor/foldhash-0.1.5/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf\"}' > cargo/vendor/form_urlencoded-1.2.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555\"}' > cargo/vendor/getrandom-0.4.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f\"}' > cargo/vendor/gimli-0.31.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1\"}' > cargo/vendor/hashbrown-0.14.5/.cargo-checksum.json",
@ -948,10 +1123,17 @@
"echo '{\"files\": {}, \"package\": \"d5a396343c7208121dc86e35623d3dfe19814a7613cfd14964994cdc9c9a2e26\"}' > cargo/vendor/icu_locale-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29\"}' > cargo/vendor/icu_locale_core-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"d5fdcc9ac77c6d74ff5cf6e65ef3181d6af32003b16fce3a77fb451d2f695993\"}' > cargo/vendor/icu_locale_data-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4\"}' > cargo/vendor/icu_normalizer-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38\"}' > cargo/vendor/icu_normalizer_data-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de\"}' > cargo/vendor/icu_properties-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14\"}' > cargo/vendor/icu_properties_data-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421\"}' > cargo/vendor/icu_provider-2.2.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954\"}' > cargo/vendor/id-arena-2.3.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de\"}' > cargo/vendor/idna-1.1.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714\"}' > cargo/vendor/idna_adapter-1.2.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff\"}' > cargo/vendor/indexmap-2.13.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695\"}' > cargo/vendor/is_terminal_polyfill-1.70.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186\"}' > cargo/vendor/itertools-0.13.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682\"}' > cargo/vendor/itoa-1.0.18/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"2ceaf4c6c48465bead8cb6a0b7c4ee0c86ecbb31239032b9c66ab9a08d2f3ee1\"}' > cargo/vendor/ixdtf-0.6.5/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2\"}' > cargo/vendor/leb128fmt-0.1.0/.cargo-checksum.json",
@ -966,17 +1148,24 @@
"echo '{\"files\": {}, \"package\": \"071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841\"}' > cargo/vendor/num-traits-0.2.19/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50\"}' > cargo/vendor/once_cell-1.21.4/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe\"}' > cargo/vendor/once_cell_polyfill-1.70.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220\"}' > cargo/vendor/percent-encoding-2.3.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564\"}' > cargo/vendor/potential_utf-0.1.5/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c\"}' > cargo/vendor/precomputed-hash-0.1.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b\"}' > cargo/vendor/prettyplease-0.2.37/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934\"}' > cargo/vendor/proc-macro2-1.0.106/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"27fbd4d9b2eb0b6e0cbd654bce70243f460cbc8dc92df6747e3fb911ce1cd4a8\"}' > cargo/vendor/psl-2.1.210/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac\"}' > cargo/vendor/psl-types-2.0.11/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924\"}' > cargo/vendor/quote-1.0.45/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf\"}' > cargo/vendor/r-efi-6.0.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"dc06e6b318142614e4a48bc725abbf08ff166694835c43c9dae5a9009704639a\"}' > cargo/vendor/regalloc2-0.11.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276\"}' > cargo/vendor/regex-1.12.3/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f\"}' > cargo/vendor/regex-automata-0.4.14/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a\"}' > cargo/vendor/regex-syntax-0.8.10/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2\"}' > cargo/vendor/rustc-hash-1.1.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe\"}' > cargo/vendor/rustc-hash-2.1.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92\"}' > cargo/vendor/rustc_version-0.4.1/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190\"}' > cargo/vendor/rustix-1.1.4/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b\"}' > cargo/vendor/seahash-4.1.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd\"}' > cargo/vendor/semver-1.0.28/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e\"}' > cargo/vendor/serde-1.0.228/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad\"}' > cargo/vendor/serde_core-1.0.228/.cargo-checksum.json",
@ -990,6 +1179,8 @@
"echo '{\"files\": {}, \"package\": \"728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2\"}' > cargo/vendor/synstructure-0.13.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca\"}' > cargo/vendor/target-lexicon-0.13.5/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd\"}' > cargo/vendor/tempfile-3.27.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52\"}' > cargo/vendor/thiserror-1.0.69/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1\"}' > cargo/vendor/thiserror-impl-1.0.69/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d\"}' > cargo/vendor/tinystr-0.8.3/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863\"}' > cargo/vendor/toml-0.9.12+spec-1.1.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347\"}' > cargo/vendor/toml_datetime-0.7.5+spec-1.1.0/.cargo-checksum.json",
@ -997,6 +1188,7 @@
"echo '{\"files\": {}, \"package\": \"756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db\"}' > cargo/vendor/toml_writer-1.1.1+spec-1.1.0/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75\"}' > cargo/vendor/unicode-ident-1.0.24/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853\"}' > cargo/vendor/unicode-xid-0.2.6/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed\"}' > cargo/vendor/url-2.5.8/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be\"}' > cargo/vendor/utf8_iter-1.0.4/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821\"}' > cargo/vendor/utf8parse-0.2.2/.cargo-checksum.json",
"echo '{\"files\": {}, \"package\": \"9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5\"}' > cargo/vendor/wasip2-1.0.2+wasi-0.2.9/.cargo-checksum.json",