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:
parent
6c162d8b5d
commit
bcdbdbb5b3
8 changed files with 741 additions and 8 deletions
240
Cargo.lock
generated
240
Cargo.lock
generated
|
|
@ -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",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
19
Libraries/LibWeb/ContentBlocker/Rust/Cargo.toml
Normal file
19
Libraries/LibWeb/ContentBlocker/Rust/Cargo.toml
Normal 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
|
||||
40
Libraries/LibWeb/ContentBlocker/Rust/build.rs
Normal file
40
Libraries/LibWeb/ContentBlocker/Rust/build.rs
Normal 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(())
|
||||
}
|
||||
26
Libraries/LibWeb/ContentBlocker/Rust/cbindgen.toml
Normal file
26
Libraries/LibWeb/ContentBlocker/Rust/cbindgen.toml
Normal 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"
|
||||
216
Libraries/LibWeb/ContentBlocker/Rust/src/lib.rs
Normal file
216
Libraries/LibWeb/ContentBlocker/Rust/src/lib.rs
Normal 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)) });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in a new issue