diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd6263e..f8a0faf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,16 +12,23 @@ permissions: jobs: main: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: filter: tree:0 fetch-depth: 0 - - uses: jetli/wasm-pack-action@v0.4.0 + - uses: dtolnay/rust-toolchain@stable with: - version: 0.13.1 + target: wasm32-unknown-unknown + + # Install cargo-binstall + - run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash + + - run: cargo binstall wasm-bindgen-cli@0.2.100 --no-confirm + - run: cargo binstall wasm-pack@0.13.1 --no-confirm + - run: cargo binstall wasm-opt@0.116.1 --no-confirm - uses: pnpm/action-setup@v4 name: Install pnpm @@ -42,9 +49,8 @@ jobs: - run: pnpm install --frozen-lockfile + - run: pnpx playwright install --with-deps + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud # - run: pnpm exec nx-cloud record -- echo Hello World - - run: pnpm exec nx run-many -t lint test build - # Nx Cloud recommends fixes for failures to help you get CI green faster. Learn more: https://nx.dev/ci/features/self-healing-ci - - run: pnpm exec nx fix-ci - if: always() + - run: pnpm exec nx run-many -t lint test build --projects=tag:lib diff --git a/Cargo.lock b/Cargo.lock index 3fb94e1..d732896 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,143 +2,3990 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "abnf" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "087113bd50d9adce24850eed5d0476c7d199d532fce8fab5173650331e09033a" +dependencies = [ + "abnf-core", + "nom", +] + +[[package]] +name = "abnf-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d" +dependencies = [ + "nom", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "asn1-rs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "async-generic" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf3728566eefa873833159754f5732fb0951d3649e6e5b891cc70d56dd41673" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "atree" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "132573478eb9ff973c6f75d0ed425ac12da77d266506483345f46743ecc83a98" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bcder" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ffdaa8c6398acd07176317eb6c1f9082869dd1cc3fee7c72c6354866b928cc" +dependencies = [ + "bytes", + "smallvec", +] + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "bitvec-nom2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d988fcc40055ceaa85edc55875a08f8abd29018582647fd82ad6128dba14a5f0" +dependencies = [ + "bitvec", + "nom", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "btree-range-map" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be5c9672446d3800bcbcaabaeba121fe22f1fb25700c4562b22faf76d377c33" +dependencies = [ + "btree-slab", + "cc-traits", + "range-traits", + "serde", + "slab", +] + +[[package]] +name = "btree-slab" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2b56d3029f075c4fa892428a098425b86cef5c89ae54073137ece416aef13c" +dependencies = [ + "cc-traits", + "slab", + "smallvec", +] + [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteordered" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf2cd9424f5ff404aba1959c835cbc448ee8b689b870a9981c76c0fd46280e6" +dependencies = [ + "byteorder", +] + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "c2pa" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd38bff182cf3b5d9744ee89bf3ba460f52994550d84e4529e51ef990cc7391" +dependencies = [ + "asn1-rs", + "async-generic", + "async-recursion", + "async-trait", + "atree", + "base64 0.22.1", + "bcder", + "byteorder", + "byteordered", + "bytes", + "chrono", + "ciborium", + "config", + "console_log", + "const-hex", + "const-oid", + "conv", + "coset", + "der", + "ecdsa", + "ed25519-dalek", + "env_logger", + "extfmt", + "getrandom 0.2.16", + "hex", + "hex-literal", + "id3", + "img-parts", + "iref", + "jfifdump", + "js-sys", + "lazy_static", + "log", + "lopdf", + "memchr", + "mp4", + "nom", + "non-empty-string", + "nonempty-collections", + "num-bigint-dig", + "p256", + "p384", + "p521", + "pem", + "pkcs1", + "pkcs8", + "png_pong", + "quick-xml", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.9.3", + "range-set", + "rasn", + "rasn-cms", + "rasn-ocsp", + "rasn-pkix", + "regex", + "reqwest", + "riff", + "ring", + "rsa", + "serde", + "serde-transcode", + "serde-wasm-bindgen", + "serde_bytes", + "serde_cbor", + "serde_derive", + "serde_json", + "serde_with", + "sha1", + "sha2", + "spki", + "static-iref", + "tempfile", + "thiserror 2.0.12", + "treeline", + "ureq", + "url", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "windows-core", + "wstd", + "x509-certificate", + "x509-parser", + "zeroize", + "zip", +] + +[[package]] +name = "c2pa-wasm" +version = "0.1.0" +dependencies = [ + "async-trait", + "c2pa", + "console_error_panic_hook", + "console_log", + "js-sys", + "log", + "thiserror 2.0.12", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "web-sys", +] + +[[package]] +name = "cc" +version = "1.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +dependencies = [ + "shlex", +] + +[[package]] +name = "cc-traits" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060303ef31ef4a522737e1b1ab68c67916f2a787bb2f4f54f383279adba962b5" +dependencies = [ + "slab", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half 2.6.0", +] + +[[package]] +name = "config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +dependencies = [ + "json5", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "const-hex" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e22e0ed40b96a48d3db274f72fd365bd78f67af39b6bbd47e8a15e1c6207ff" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "conv" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" +dependencies = [ + "custom_derive", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "coset" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8cc80f631f8307b887faca24dcc3abc427cd0367f6eb6188f6e8f5b7ad8fb" +dependencies = [ + "ciborium", + "ciborium-io", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "custom_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.104", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "delegate" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082a24a9967533dc5d743c602157637116fc1b52806d694a5a45e6f32567fcdd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "sha2", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2", + "signature", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "extfmt" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a48fe53466ab1f4ea6303bf9d7a0ca8060778590f09fd6c3304cc817aeb9935d" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "humantime" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.2", +] + +[[package]] +name = "hyper-util" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.0", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id3" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872718dfcd3a6f4601a3fb413365ee5e1d3ec050316ff79e690c98658a6738ef" +dependencies = [ + "bitflags", + "byteorder", + "flate2", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "img-parts" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4e24cfdc6f897b582508e3c382eaf5378076898f80500a80d10d761ae85e90" +dependencies = [ + "bytes", + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", + "serde", +] + +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iref" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374372d9ca7331cec26f307b12552554849143e6b2077be3553576aa9aa8258c" +dependencies = [ + "iref-core", +] + +[[package]] +name = "iref-core" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10559a0d518effd4f2cee107f40f83acf8583dcd3e6760b9b60293b0d2c2a70" +dependencies = [ + "pct-str", + "serde", + "smallvec", + "static-regular-grammar", + "thiserror 1.0.69", +] + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.59.0", +] + +[[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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jfifdump" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68cf72bc7b75b6615ffd06bfe6840f3c57e7e4ea615558a2a452f458ebf5551e" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "lopdf" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c8e1b6184b1b32ea5f72f572ebdc40e5da1d2921fa469947ff7c480ad1f85a" +dependencies = [ + "chrono", + "encoding_rs", + "flate2", + "itoa", + "linked-hash-map", + "log", + "md5", + "nom", + "rayon", + "time", + "weezl", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "mp4" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9ef834d5ed55e494a2ae350220314dc4aacd1c43a9498b00e320e0ea352a5c3" +dependencies = [ + "byteorder", + "bytes", + "num-rational", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "non-empty-string" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cf0f4060e345ae505219853da9ca1150564158a648a6aa6a528f0d5794bb33" +dependencies = [ + "delegate", + "serde", +] + +[[package]] +name = "nonempty-collections" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e216d0e8cf9d54fa66e5780f6e1d5dc96d1c1b3c25aeba3b6758548bcbbd8b9d" +dependencies = [ + "serde", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "serde", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core 0.6.4", + "sha2", +] + +[[package]] +name = "parsenic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c695d2b8bcf1dd62a5173a9c43e6ebbe9261701c002f9b462fc9690c144bb61" +dependencies = [ + "traitful", +] + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pct-str" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf1bdcc492c285a50bed60860dfa00b50baf1f60c73c7d6b435b01a2a11fd6ff" +dependencies = [ + "thiserror 1.0.69", + "utf8-decode", +] + +[[package]] +name = "pem" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +dependencies = [ + "base64 0.22.1", + "serde", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +dependencies = [ + "memchr", + "thiserror 2.0.12", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "pest_meta" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +dependencies = [ + "pest", + "sha2", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pix" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6574ffbea793ab0c9a9b09ae99831f1513fdd7732b12aca4c7182c46dc3bc9f" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "png_pong" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a767b8b17e388cb7f1e74cf3c2ebce14e6b7ae123fa27150889a353fd9eb981f" +dependencies = [ + "miniz_oxide", + "parsenic", + "pix", + "simd-adler32", + "traitful", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" +dependencies = [ + "bitflags", + "lazy_static", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "unarray", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.5.10", + "thiserror 2.0.12", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.12", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "range-set" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714bc4849c399f77ab82177e9b4f012e02f3a7d6191023e016334edde5b21050" +dependencies = [ + "num-traits", + "smallvec", +] + +[[package]] +name = "range-traits" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20581732dd76fa913c7dff1a2412b714afe3573e94d41c34719de73337cc8ab" + +[[package]] +name = "rasn" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7863f4e3d3cbbe0d3a427aa48447c42b5a74a579cbfa7afa63735b0c10879c44" +dependencies = [ + "bitvec", + "bitvec-nom2", + "bytes", + "chrono", + "either", + "nom", + "num-bigint", + "num-integer", + "num-traits", + "once_cell", + "rasn-derive", + "serde_json", + "snafu", + "xml-no-std", +] + +[[package]] +name = "rasn-cms" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffab95fefca87ed16fa9501141bebd99643f51d46c7e19f3c0a2c321ae5c27d2" +dependencies = [ + "rasn", + "rasn-pkix", +] + +[[package]] +name = "rasn-derive" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a16f695759320ec969864fe5e7aa8e2a9c5665469565b100b8c8c1a36cd5484" +dependencies = [ + "proc-macro2", + "rasn-derive-impl", + "syn 2.0.104", +] + +[[package]] +name = "rasn-derive-impl" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14454245fd76215b830d083b6b6c6842047e50cb7ee73ce1e769d4b099c89fd" +dependencies = [ + "either", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.104", + "uuid", +] + +[[package]] +name = "rasn-ocsp" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5252a65c8d5c8435420db5417b6a881f907c75a394c5f88cd392118f273ddc55" +dependencies = [ + "rasn", + "rasn-pkix", +] + +[[package]] +name = "rasn-pkix" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c902bfc1add6e7471323cdb879fe6a3c3122b1cb0247937c0940b28e2334252" +dependencies = [ + "rasn", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 1.0.2", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "riff" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c601484456988d75017d86700d3743b949c21cdc7399f940c75e34680d185c5" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags", + "serde", + "serde_derive", +] + +[[package]] +name = "rsa" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rust-ini" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.23.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069a8df149a16b1a12dcc31497c3396a173844be3cac4bd40c9e7671fef96671" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-transcode" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590c0e25c2a5bb6e85bf5c1bce768ceb86b316e7a01bdf07d2cb4ec2271990e2" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_bytes" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half 1.8.3", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "serde_json" +version = "1.0.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +dependencies = [ + "indexmap 2.10.0", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.10.0", + "schemars 0.9.0", + "schemars 1.0.4", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "snafu" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320b01e011bf8d5d7a4a4a4be966d9160968935849c83b918827f6a435e7f627" +dependencies = [ + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static-iref" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cc4068497ae43896d41174586dcdc2153a1af2c82856fb308bfaaddc28e5549" +dependencies = [ + "iref", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "static-regular-grammar" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4a6c40247579acfbb138c3cd7de3dab113ab4ac6227f1b7de7d626ee667957" +dependencies = [ + "abnf", + "btree-range-map", + "ciborium", + "hex_fmt", + "indoc", + "proc-macro-error", + "proc-macro2", + "quote", + "serde", + "sha2", + "syn 2.0.104", + "thiserror 1.0.69", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom 0.2.16", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[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 2.0.104", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "time" +version = "0.3.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" + +[[package]] +name = "time-macros" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "pin-project-lite", + "slab", + "socket2 0.6.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap 2.10.0", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "traitful" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d856e22ead1fb79b9fc3cec63300086f680924f2f7b0e2701f6835a28b9c4425" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "treeline" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "url", + "webpki-roots 0.26.11", +] + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8-decode" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca61eb27fa339aa08826a29f03e87b99b4d8f0fc2255306fd266bb1b6a9de498" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" +dependencies = [ + "getrandom 0.2.16", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] -name = "cfg-if" -version = "1.0.1" +name = "wasm-bindgen-test" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" +dependencies = [ + "js-sys", + "minicov", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] [[package]] -name = "console_error_panic_hook" -version = "0.1.7" +name = "wasm-bindgen-test-macro" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" dependencies = [ - "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", "wasm-bindgen", ] [[package]] -name = "log" -version = "0.4.27" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] -name = "once_cell" -version = "1.21.3" +name = "webpki-roots" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.2", +] [[package]] -name = "proc-macro2" -version = "1.0.95" +name = "webpki-roots" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ - "unicode-ident", + "rustls-pki-types", ] [[package]] -name = "quote" -version = "1.0.40" +name = "weezl" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "rustversion" -version = "1.0.21" +name = "windows-interface" +version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] [[package]] -name = "syn" -version = "2.0.104" +name = "windows-link" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wstd" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6515b13373b9dfbbe62e4426972253a15b74d93b1e2e95f92bbb2801c239a1d3" +dependencies = [ + "futures-core", + "http", + "itoa", + "pin-project-lite", + "serde", + "serde_json", + "slab", + "wasi 0.14.2+wasi-0.2.4", + "wstd-macro", +] + +[[package]] +name = "wstd-macro" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d1758ed5cdf081802c60bc000a9cb90db8bcdf140fa8a7251a22b32af37d7b" +dependencies = [ + "quote", + "syn 2.0.104", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-certificate" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b9f8bcae7c1f36479821ae826d75050c60ce55146fd86d3553ed2573e2762" +dependencies = [ + "bcder", + "bytes", + "chrono", + "der", + "hex", + "pem", + "ring", + "signature", + "spki", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "x509-parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "xml-no-std" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd223bc94c615fc02bf2f4bbc22a4a9bfe489c2add3ec10b1038df3aca44cac7" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn 2.0.104", + "synstructure", ] [[package]] -name = "unicode-ident" -version = "1.0.18" +name = "zerocopy" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] [[package]] -name = "wasm" -version = "0.1.0" +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ - "console_error_panic_hook", - "wasm-bindgen", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "zerofrom" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "zerofrom-derive", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "zerofrom-derive" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ - "bumpalo", - "log", "proc-macro2", "quote", - "syn", - "wasm-bindgen-shared", + "syn 2.0.104", + "synstructure", ] [[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ + "proc-macro2", "quote", - "wasm-bindgen-macro-support", + "syn 2.0.104", ] [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", + "syn 2.0.104", ] [[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" +name = "zip" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "12598812502ed0105f607f941c386f43d441e00148fce9dec3ca5ffb0bde9308" dependencies = [ - "unicode-ident", + "arbitrary", + "crc32fast", + "indexmap 2.10.0", + "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index b892a9a..2c525da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,9 @@ [workspace] resolver = '2' members = [ - 'packages/wasm', + 'packages/c2pa-wasm', ] [profile.release] +opt-level = "s" lto = true diff --git a/eslint.config.mjs b/eslint.config.mjs index 0eeb392..e0ee6a7 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,4 +1,14 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + import nx from '@nx/eslint-plugin'; +import headers from 'eslint-plugin-headers'; export default [ { @@ -49,6 +59,30 @@ export default [ '**/*.mjs', ], // Override or add rules here - rules: {}, + rules: { + 'headers/header-format': [ + 'error', + { + source: 'string', + content: [ + 'Copyright (year) Adobe', + 'All Rights Reserved.', + '', + 'NOTICE: Adobe permits you to use, modify, and distribute this file in', + 'accordance with the terms of the Adobe license agreement accompanying', + 'it.', + ].join('\n'), + patterns: { + year: { + pattern: '\\d{4}', + defaultValue: new Date().getFullYear().toString(), + }, + }, + }, + ], + }, + plugins: { + headers, + }, }, ]; diff --git a/nx.json b/nx.json index d961ed2..03a72a2 100644 --- a/nx.json +++ b/nx.json @@ -12,7 +12,6 @@ ], "sharedGlobals": ["{workspaceRoot}/.github/workflows/ci.yml"] }, - "nxCloudId": "6881413b0e4a9139ff67b78b", "plugins": [ { "plugin": "@nx/js/typescript", @@ -59,5 +58,13 @@ "dependsOn": ["^build"], "inputs": ["production", "^production"] } + }, + "generators": { + "@nx/web:application": { + "style": "css", + "linter": "eslint", + "unitTestRunner": "none", + "e2eTestRunner": "none" + } } } diff --git a/package.json b/package.json index 5a88030..427d1d9 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@vitest/ui": "^3.0.0", "eslint": "^9.8.0", "eslint-config-prettier": "^10.0.0", + "eslint-plugin-headers": "^1.3.3", "jiti": "2.4.2", "jsdom": "~22.1.0", "jsonc-eslint-parser": "^2.1.0", @@ -32,10 +33,8 @@ "typescript-eslint": "^8.29.0", "vite": "^6.0.0", "vite-plugin-dts": "~4.5.0", - "vitest": "^3.0.0" - }, - "packageManager": "pnpm@10.14.0-0+sha512.2cd47a0cbf5f1d1de7693a88307a0ede5be94e0d3b34853d800ee775efbea0650cb562b77605ec80bc8d925f5cd27c4dfe8bb04d3a0b76090784c664450d32d6", - "dependencies": { + "vitest": "^3.0.0", "@nx/devkit": "21.3.5" - } + }, + "packageManager": "pnpm@10.15.0" } diff --git a/packages/browser/README.md b/packages/browser/README.md deleted file mode 100644 index 1190897..0000000 --- a/packages/browser/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# browser - -This library was generated with [Nx](https://nx.dev). - -## Building - -Run `nx build browser` to build the library. - -## Running unit tests - -Run `nx test browser` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts deleted file mode 100644 index fc769dd..0000000 --- a/packages/browser/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './lib/browser.js'; diff --git a/packages/browser/src/lib/browser.spec.ts b/packages/browser/src/lib/browser.spec.ts deleted file mode 100644 index 3cc68c6..0000000 --- a/packages/browser/src/lib/browser.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { foobar } from './browser.js'; - -describe('browser', () => { - it('should work', async () => { - expect(await foobar()).toEqual('foobarfoobar'); - }); -}); diff --git a/packages/browser/src/lib/browser.ts b/packages/browser/src/lib/browser.ts deleted file mode 100644 index 4678c0c..0000000 --- a/packages/browser/src/lib/browser.ts +++ /dev/null @@ -1,6 +0,0 @@ -import init, { foobar as wasmFoobar } from '@contentauth/wasm'; - -export async function foobar(): Promise { - await init(); - return 'foobar' + wasmFoobar(); -} diff --git a/packages/browser/vite.config.ts b/packages/browser/vite.config.ts deleted file mode 100644 index da21ff3..0000000 --- a/packages/browser/vite.config.ts +++ /dev/null @@ -1,55 +0,0 @@ -/// -import { defineConfig } from 'vite'; -import dts from 'vite-plugin-dts'; -import * as path from 'path'; - -export default defineConfig(() => ({ - root: __dirname, - cacheDir: '../../node_modules/.vite/packages/browser', - plugins: [ - dts({ - entryRoot: 'src', - tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'), - }), - ], - // Uncomment this if you are using workers. - // worker: { - // plugins: [ nxViteTsPaths() ], - // }, - // Configuration for building your library. - // See: https://vitejs.dev/guide/build.html#library-mode - build: { - outDir: './dist', - emptyOutDir: true, - reportCompressedSize: true, - commonjsOptions: { - transformMixedEsModules: true, - }, - lib: { - // Could also be a dictionary or array of multiple entry points. - entry: 'src/index.ts', - name: '@contentauth/browser', - fileName: 'index', - // Change this to the formats you want to support. - // Don't forget to update your package.json as well. - formats: ['es' as const], - }, - rollupOptions: { - // External packages that should not be bundled into your library. - external: [], - }, - }, - test: { - watch: false, - globals: true, - include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - browser: { - enabled: true, - provider: 'playwright', - // https://vitest.dev/guide/browser/playwright - instances: [ - { browser: 'chromium' }, - ], - }, - }, -})); diff --git a/packages/browser/vitest-example/HelloWorld.test.ts b/packages/browser/vitest-example/HelloWorld.test.ts deleted file mode 100644 index db2a72d..0000000 --- a/packages/browser/vitest-example/HelloWorld.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { expect, test } from 'vitest' -import { getByText } from '@testing-library/dom' -import HelloWorld from './HelloWorld.js' - -test('renders name', () => { - const parent = HelloWorld({ name: 'Vitest' }) - document.body.appendChild(parent) - - const element = getByText(parent, 'Hello Vitest!') - expect(element).toBeInTheDocument() -}) diff --git a/packages/browser/vitest-example/HelloWorld.ts b/packages/browser/vitest-example/HelloWorld.ts deleted file mode 100644 index 614f357..0000000 --- a/packages/browser/vitest-example/HelloWorld.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default function HelloWorld({ name }: { name: string }): HTMLDivElement { - const parent = document.createElement('div') - - const h1 = document.createElement('h1') - h1.textContent = 'Hello ' + name + '!' - parent.appendChild(h1) - - return parent -} diff --git a/packages/wasm/.gitignore b/packages/c2pa-wasm/.gitignore similarity index 74% rename from packages/wasm/.gitignore rename to packages/c2pa-wasm/.gitignore index 4e30131..ae5938f 100644 --- a/packages/wasm/.gitignore +++ b/packages/c2pa-wasm/.gitignore @@ -3,4 +3,3 @@ Cargo.lock bin/ pkg/ -wasm-pack.log diff --git a/packages/wasm/Cargo.toml b/packages/c2pa-wasm/Cargo.toml similarity index 56% rename from packages/wasm/Cargo.toml rename to packages/c2pa-wasm/Cargo.toml index f454499..8f254b0 100644 --- a/packages/wasm/Cargo.toml +++ b/packages/c2pa-wasm/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "wasm" +name = "c2pa-wasm" version = "0.1.0" authors = ["Eli Mensch "] edition = "2021" @@ -18,7 +18,21 @@ wasm-bindgen = "0.2.100" # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for # code size when deploying. console_error_panic_hook = { version = "0.1.7", optional = true } +console_log = { version = "1.0.0", features = ["color"] } +log = "0.4.27" +js-sys = "0.3.77" +wasm-bindgen-futures = "0.4.50" +c2pa = { version = "0.58.0", features = ["pdf", "rust_native_crypto"], default-features = false } +async-trait = "0.1.88" +thiserror = "2.0.12" -[profile.release] -# Tell `rustc` to optimize for small code size. -opt-level = "s" +[dependencies.web-sys] +version = "0.3.77" +features = [ + 'console', + 'Blob', + 'FileReaderSync', +] + +[dev-dependencies] +wasm-bindgen-test = "0.3.50" diff --git a/packages/c2pa-wasm/package.json b/packages/c2pa-wasm/package.json new file mode 100644 index 0000000..859fac3 --- /dev/null +++ b/packages/c2pa-wasm/package.json @@ -0,0 +1,22 @@ +{ + "name": "@contentauth/c2pa-wasm", + "version": "0.0.1", + "private": true, + "type": "module", + "module": "./pkg/c2pa.js", + "types": "./pkg/c2pa.d.ts", + "files": [ + "pkg/**/*" + ], + "exports": { + ".": { + "types": "./pkg/c2pa.d.ts", + "import": "./pkg/c2pa.js", + "default": "./pkg/c2pa.js" + }, + "./c2pa.wasm": "./pkg/c2pa_bg.wasm", + "./package.json": "./package.json", + "./assets/c2pa_bg.wasm": "./pkg/c2pa_bg.wasm", + "./assets/c2pa_bg.wasm.d.ts": "./pkg/c2pa_bg.wasm.d.ts" + } +} \ No newline at end of file diff --git a/packages/wasm/project.json b/packages/c2pa-wasm/project.json similarity index 73% rename from packages/wasm/project.json rename to packages/c2pa-wasm/project.json index 1d23c9d..952c89a 100644 --- a/packages/wasm/project.json +++ b/packages/c2pa-wasm/project.json @@ -1,11 +1,13 @@ { - "name": "wasm", + "name": "c2pa-wasm", "$schema": "../../node_modules/nx/schemas/project-schema.json", + "tags": ["lib"], "projectType": "library", - "sourceRoot": "packages/wasm/src", + "sourceRoot": "packages/c2pa-wasm/src", "targets": { "build": { - "executor": "nx-wasm-pack:build", + "cache": true, + "executor": "nx-wasm-bindgen:build", "outputs": ["{options.target-dir}"], "options": { "project-dir": "{projectRoot}" @@ -13,10 +15,10 @@ }, "test": { "cache": true, - "executor": "@monodon/rust:test", + "executor": "nx-wasm-bindgen:test", "outputs": ["{options.target-dir}"], "options": { - "target-dir": "dist/target/wasm" + "project-dir": "{projectRoot}" }, "configurations": { "production": { @@ -32,6 +34,5 @@ "target-dir": "dist/target/wasm" } } - }, - "tags": [] + } } diff --git a/packages/c2pa-wasm/src/error.rs b/packages/c2pa-wasm/src/error.rs new file mode 100644 index 0000000..318ef24 --- /dev/null +++ b/packages/c2pa-wasm/src/error.rs @@ -0,0 +1,31 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +use std::error::Error; + +use js_sys::Error as JsError; + +#[derive(thiserror::Error, Debug)] +pub enum WasmError { + #[error(transparent)] + C2pa(#[from] c2pa::Error), + + #[error(transparent)] + Other(Box), +} + +impl WasmError { + pub(crate) fn other(e: impl Error + 'static) -> Self { + WasmError::Other(Box::new(e)) + } +} + +impl From for JsError { + fn from(value: WasmError) -> Self { + JsError::new(&format!("{:?}", value)) + } +} diff --git a/packages/c2pa-wasm/src/lib.rs b/packages/c2pa-wasm/src/lib.rs new file mode 100644 index 0000000..06e13f0 --- /dev/null +++ b/packages/c2pa-wasm/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +#![deny(missing_docs)] + +//! A wrapper around c2pa-rs that provides the API "building blocks" for c2pa-web via `wasm-bindgen`. + +use wasm_bindgen::prelude::*; + +mod error; + +/// Contains functions to create types usable by c2pa-rs from JS types. +pub mod stream; + +/// Exposes a reader API to JS via wasm-bindgen. +pub mod wasm_reader; + +/// Provides a JS interface for loading c2pa-rs settings. +pub mod settings; + +/// Called when the WASM binary is initialized. +#[wasm_bindgen(start)] +pub fn run() { + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); +} diff --git a/packages/c2pa-wasm/src/settings.rs b/packages/c2pa-wasm/src/settings.rs new file mode 100644 index 0000000..52279bd --- /dev/null +++ b/packages/c2pa-wasm/src/settings.rs @@ -0,0 +1,16 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +use wasm_bindgen::prelude::*; + +/// Accepts a JSON-serialized string to be loaded as c2pa-rs settings. +#[wasm_bindgen(js_name = loadSettings)] +pub fn load_settings(settings: &str) -> Result<(), js_sys::Error> { + c2pa::settings::load_settings_from_str(settings, "json").unwrap(); + + Ok(()) +} diff --git a/packages/c2pa-wasm/src/stream/blob_stream.rs b/packages/c2pa-wasm/src/stream/blob_stream.rs new file mode 100644 index 0000000..711b38a --- /dev/null +++ b/packages/c2pa-wasm/src/stream/blob_stream.rs @@ -0,0 +1,183 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +use std::{ + cmp::min, + io::{Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom}, +}; + +use js_sys::Uint8Array; +use web_sys::{Blob, FileReaderSync}; + +/// Wraps a JS-space Blob and a byte offset to support the implementation of Read + Seek. +pub struct BlobStream<'a> { + offset: usize, + blob: &'a Blob, +} + +impl<'a> BlobStream<'a> { + /// Create a new BlobStream from a `web_sys::Blob`. + pub fn new(blob: &'a Blob) -> Self { + Self { offset: 0, blob } + } +} + +impl Read for BlobStream<'_> { + fn read(&mut self, buf: &mut [u8]) -> IoResult { + let mut slice: &[u8] = &get_vec_u8_from_blob(self.blob, self.offset, buf.len())?; + let bytes_read = slice.read(buf)?; + self.offset += bytes_read; + Ok(bytes_read) + } +} + +fn get_vec_u8_from_blob(blob: &Blob, offset: usize, len: usize) -> IoResult> { + let end = min(blob.size() as usize, offset + len); + let slice = blob + .slice_with_f64_and_f64(offset as f64, end as f64) + .map_err(|err| { + IoError::new( + IoErrorKind::Other, + format!("Failed to create slice from blob. Details: {:?}", err), + ) + })?; + + let reader_sync = FileReaderSync::new().map_err(|err| { + IoError::new( + IoErrorKind::Other, + format!( + "Failed to create FileReaderSync on blob slice. Details: {:?}", + err + ), + ) + })?; + + let slice_u8array = reader_sync + .read_as_array_buffer(&slice) + .map(|array_buffer| Uint8Array::new(&array_buffer)) + .map_err(|err| { + IoError::new( + IoErrorKind::Other, + format!("Failed to read blob slice. Details: {:?}", err), + ) + })?; + + let mut buf = vec![0; slice_u8array.byte_length() as usize]; + slice_u8array.copy_to(&mut buf); + + Ok(buf) +} + +impl Seek for BlobStream<'_> { + fn seek(&mut self, pos: SeekFrom) -> std::io::Result { + match pos { + SeekFrom::Start(offset) => { + self.offset = offset as usize; + } + SeekFrom::End(offset) => { + self.offset = (self.blob.size() as i64 + offset) as usize; + } + SeekFrom::Current(offset) => { + self.offset = (self.offset as i64 + offset) as usize; + } + } + + Ok(self.offset as u64) + } +} + +// SAFETY: WASM is single-threaded. +unsafe impl Send for BlobStream<'_> {} + +#[cfg(test)] +mod tests { + use js_sys::Array; + use wasm_bindgen_test::wasm_bindgen_test; + + use super::*; + + wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + + #[wasm_bindgen_test] + fn test_read_in_sequence() { + let blob = blob_from_vec(vec![0, 1, 2, 3]); + + let mut stream = BlobStream::new(&blob); + + let mut buf = vec![0; 2]; + let bytes_read = stream.read(&mut buf).unwrap(); + + assert_eq!(buf, vec![0, 1]); + assert_eq!(bytes_read, 2); + + let mut next_buf = vec![0; 2]; + let next_bytes_read = stream.read(&mut next_buf).unwrap(); + + assert_eq!(next_buf, vec![2, 3]); + assert_eq!(next_bytes_read, 2); + } + + #[wasm_bindgen_test] + fn test_read_into_oversize_buffer() { + let blob = blob_from_vec(vec![0, 1, 2, 3]); + + let mut stream = BlobStream::new(&blob); + + let mut buf = vec![0; 6]; + let bytes_read = stream.read(&mut buf).unwrap(); + + assert_eq!(buf, vec![0, 1, 2, 3, 0, 0]); + assert_eq!(bytes_read, 4); + } + + #[wasm_bindgen_test] + fn test_read_and_seek() { + let blob = blob_from_vec(vec![0, 1, 2, 3]); + + let mut stream = BlobStream::new(&blob); + + stream.seek(SeekFrom::Start(2)).unwrap(); + let mut buf = vec![0; 2]; + stream.read(&mut buf).unwrap(); + + assert_eq!(buf, vec![2, 3]); + + stream.seek(SeekFrom::Current(-4)).unwrap(); + let mut next_buf = vec![0; 2]; + stream.read(&mut next_buf).unwrap(); + + assert_eq!(next_buf, vec![0, 1]); + + stream.seek(SeekFrom::End(-2)).unwrap(); + let mut final_buf = vec![0; 2]; + stream.read(&mut final_buf).unwrap(); + + assert_eq!(final_buf, vec![2, 3]); + } + + #[wasm_bindgen_test] + fn test_seek_past_end_and_read() { + let blob = blob_from_vec(vec![0, 1, 2, 3]); + + let mut stream = BlobStream::new(&blob); + + stream.seek(SeekFrom::Start(10)).unwrap(); + let mut buf = vec![0; 2]; + let bytes_read = stream.read(&mut buf).unwrap(); + + assert_eq!(buf, vec![0, 0]); + assert_eq!(bytes_read, 0) + } + + fn blob_from_vec(vec: Vec) -> Blob { + let u8array = Uint8Array::from(vec.as_slice()); + let parts = Array::new(); + parts.push(&u8array); + + Blob::new_with_u8_array_sequence(&parts).unwrap() + } +} diff --git a/packages/c2pa-wasm/src/stream/mod.rs b/packages/c2pa-wasm/src/stream/mod.rs new file mode 100644 index 0000000..d4203bb --- /dev/null +++ b/packages/c2pa-wasm/src/stream/mod.rs @@ -0,0 +1,10 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +mod blob_stream; + +pub use blob_stream::BlobStream; diff --git a/packages/c2pa-wasm/src/wasm_reader.rs b/packages/c2pa-wasm/src/wasm_reader.rs new file mode 100644 index 0000000..fd70d50 --- /dev/null +++ b/packages/c2pa-wasm/src/wasm_reader.rs @@ -0,0 +1,106 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +use std::io::{Cursor, Read, Seek}; + +use c2pa::{identity::validator::CawgValidator, Reader}; +use js_sys::{ArrayBuffer, Error as JsError, Uint8Array}; +use wasm_bindgen::prelude::*; +use web_sys::Blob; + +use crate::{error::WasmError, stream::BlobStream}; + +/// Wraps a `c2pa::Reader`. +#[wasm_bindgen] +pub struct WasmReader { + reader: Reader, +} + +#[wasm_bindgen] +impl WasmReader { + /// Attempts to create a new `WasmReader` from an asset format and `Blob` of the asset's bytes. + #[wasm_bindgen(js_name = fromBlob)] + pub async fn from_blob(format: &str, blob: &Blob) -> Result { + let stream = BlobStream::new(blob); + WasmReader::from_stream(format, stream).await + } + + async fn from_stream( + format: &str, + stream: impl Read + Seek + Send, + ) -> Result { + let mut reader = Reader::from_stream_async(format, stream) + .await + .map_err(WasmError::from)?; + + // This will be removed once CawgValidation is rolled into the reader + reader + .post_validate_async(&CawgValidator {}) + .await + .map_err(WasmError::other)?; + + Ok(WasmReader { reader }) + } + + /// Attempts to create a new `WasmReader` from an asset format, a `Blob` of the bytes of the initial segment, and a fragment `Blob`. + #[wasm_bindgen(js_name = fromBlobFragment)] + pub async fn from_blob_fragment( + format: &str, + init: &Blob, + fragment: &Blob, + ) -> Result { + let init_stream = BlobStream::new(init); + let fragment_stream = BlobStream::new(fragment); + + WasmReader::from_stream_fragment(format, init_stream, fragment_stream).await + } + + async fn from_stream_fragment( + format: &str, + init: impl Read + Seek + Send, + fragment: impl Read + Seek + Send, + ) -> Result { + let mut reader = Reader::from_fragment_async(format, init, fragment) + .await + .map_err(WasmError::other)?; + + // This will be removed once CawgValidation is rolled into the reader + reader + .post_validate_async(&CawgValidator {}) + .await + .map_err(WasmError::other)?; + + Ok(WasmReader { reader }) + } + + /// Returns a JSON representation of the asset's manifest store. + #[wasm_bindgen] + pub fn json(&self) -> String { + self.reader.json() + } + + /// Returns the label of the asset's active manifest. + #[wasm_bindgen(js_name = activeLabel)] + pub fn active_label(&self) -> Option { + self.reader.active_label().map(|val| val.to_owned()) + } + + /// Accepts a URI reference to a binary object in the resource store and returns a `js_sys::ArrayBuffer` containing the resource's bytes. + #[wasm_bindgen(js_name = resourceToBuffer)] + pub fn resource_to_buffer(&self, uri: &str) -> Result { + let mut data = Vec::new(); + let mut stream = Cursor::new(data); + self.reader + .resource_to_stream(uri, &mut stream) + .map_err(WasmError::from)?; + data = stream.into_inner(); + let data_len: u32 = data.len().try_into().map_err(WasmError::other)?; + let uint8array = Uint8Array::new_with_length(data_len); + uint8array.copy_from(&data); + Ok(uint8array.buffer()) + } +} diff --git a/packages/c2pa-web/README.md b/packages/c2pa-web/README.md new file mode 100644 index 0000000..c8553f3 --- /dev/null +++ b/packages/c2pa-web/README.md @@ -0,0 +1,11 @@ +# c2pa-web + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build c2pa-web` to build the library. + +## Running unit tests + +Run `nx test c2pa-web` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/packages/browser/eslint.config.mjs b/packages/c2pa-web/eslint.config.mjs similarity index 68% rename from packages/browser/eslint.config.mjs rename to packages/c2pa-web/eslint.config.mjs index 68e70dc..a33e24f 100644 --- a/packages/browser/eslint.config.mjs +++ b/packages/c2pa-web/eslint.config.mjs @@ -1,3 +1,11 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ import baseConfig from '../../eslint.config.mjs'; export default [ diff --git a/packages/browser/package-lock.json b/packages/c2pa-web/package-lock.json similarity index 99% rename from packages/browser/package-lock.json rename to packages/c2pa-web/package-lock.json index 1eeb328..87388ec 100644 --- a/packages/browser/package-lock.json +++ b/packages/c2pa-web/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@contentauth/browser", + "name": "@contentauth/c2pa-web", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@contentauth/browser", + "name": "@contentauth/c2pa-web", "version": "0.0.1", "devDependencies": { "@nx/plugin": "^21.3.5" diff --git a/packages/browser/package.json b/packages/c2pa-web/package.json similarity index 68% rename from packages/browser/package.json rename to packages/c2pa-web/package.json index 1688e78..1774bd6 100644 --- a/packages/browser/package.json +++ b/packages/c2pa-web/package.json @@ -1,9 +1,7 @@ { - "name": "@contentauth/browser", + "name": "@contentauth/c2pa-web", "version": "0.0.1", - "private": true, "type": "module", - "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { @@ -16,10 +14,13 @@ } }, "dependencies": { - "@contentauth/wasm": "workspace:*" + "@contentauth/c2pa-wasm": "workspace:*" }, "devDependencies": { + "@playwright/test": "^1.55.0", + "@types/ssri": "^7.1.5", "@vitest/browser": "^3.2.4", - "playwright": "^1.54.1" - } + "rimraf": "^6.0.1" + }, + "scripts": {} } diff --git a/packages/c2pa-web/project.json b/packages/c2pa-web/project.json new file mode 100644 index 0000000..789f4be --- /dev/null +++ b/packages/c2pa-web/project.json @@ -0,0 +1,7 @@ +{ + "name": "c2pa-web", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "tags": ["lib"], + "projectType": "library", + "sourceRoot": "packages/c2pa-web/src" +} \ No newline at end of file diff --git a/packages/c2pa-web/src/index.ts b/packages/c2pa-web/src/index.ts new file mode 100644 index 0000000..9ac266b --- /dev/null +++ b/packages/c2pa-web/src/index.ts @@ -0,0 +1,15 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export * from './lib/c2pa.js'; +export { + isSupportedReaderFormat, + READER_SUPPORTED_FORMATS, +} from './lib/supportedFormats.js'; +export { type Settings } from './lib/settings.js'; diff --git a/packages/c2pa-web/src/lib/c2pa.spec.ts b/packages/c2pa-web/src/lib/c2pa.spec.ts new file mode 100644 index 0000000..0ca615d --- /dev/null +++ b/packages/c2pa-web/src/lib/c2pa.spec.ts @@ -0,0 +1,166 @@ + +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { describe, expect, test } from 'vitest'; +import { createC2pa } from './c2pa.js'; +import { Settings } from './settings.js'; +import wasmSrc from '@contentauth/c2pa-wasm/assets/c2pa_bg.wasm?url'; + +import C_with_CAWG_data from '../../test/fixtures/assets/C_with_CAWG_data.jpg'; +import C_with_CAWG_data_thumbnail from '../../test/fixtures/assets/C_with_CAWG_data_thumbnail.jpg'; +import C_with_CAWG_data_ManifestStore from '../../test/fixtures/assets/C_with_CAWG_data.json' with { type: "json" }; +import C_with_CAWG_data_trusted_ManifestStore from '../../test/fixtures/assets/C_with_CAWG_data_trusted.json' with { type: "json" }; +import C_with_CAWG_data_untrusted_ManifestStore from '../../test/fixtures/assets/C_with_CAWG_data_untrusted.json' with { type: "json" }; +import no_alg from '../../test/fixtures/assets/no_alg.jpg'; +import dashinit from '../../test/fixtures/assets/dashinit.mp4'; +import dash1 from '../../test/fixtures/assets/dash1.m4s?url'; +import dashinit_ManifestStore from '../../test/fixtures/assets/dashinit.json' with { type: "json" }; + +import anchor_correct from '../../test/fixtures/trust/anchor-correct.pem?raw'; +import anchor_incorrect from '../../test/fixtures/trust/anchor-incorrect.pem?raw'; + +describe('c2pa', () => { + describe('reader', () => { + test('should work when created from a blob', async () => { + const c2pa = await createC2pa({ wasmSrc }); + + const blob = await getBlobForAsset(C_with_CAWG_data); + + const reader = await c2pa.reader.fromBlob(blob.type, blob) + + const manifestStore = await reader.manifestStore(); + + expect(manifestStore).toEqual(C_with_CAWG_data_ManifestStore); + + await reader.free(); + }); + + test('should return an embedded thumbnail', async () => { + const c2pa = await createC2pa({ wasmSrc }); + + const blob = await getBlobForAsset(C_with_CAWG_data); + + const reader = await c2pa.reader.fromBlob(blob.type, blob) + + const manifestStore = await reader.manifestStore(); + + const activeManifest = + manifestStore.manifests[manifestStore.active_manifest]; + const thumbnailId = activeManifest.thumbnail.identifier; + + const thumbnailBuffer = await reader.resourceToBuffer(thumbnailId); + const thumbnail = new Uint8Array(thumbnailBuffer!); + + const thumbnailBlob = await getBlobForAsset( + C_with_CAWG_data_thumbnail + ); + + const expectedThumbnailBuffer = await thumbnailBlob.arrayBuffer(); + + const expectedThumbnail = new Uint8Array(expectedThumbnailBuffer); + + expect(thumbnail).toEqual(expectedThumbnail); + + await reader.free(); + }); + + test('should report c2pa-rs errors correctly', async () => { + const c2pa = await createC2pa({ wasmSrc }); + + const blob = await getBlobForAsset(no_alg); + + const readerPromise = c2pa.reader.fromBlob(blob.type, blob); + + await expect(readerPromise).rejects.toThrowError('C2pa(UnknownAlgorithm)'); + }); + + test('should report a trusted asset when when configured to verify trust', async () => { + const settings: Settings = { + trust: { + trustAnchors: anchor_correct, + }, + verify: { + verifyTrust: true + } + } + + const c2pa = await createC2pa({ wasmSrc, settings }); + + const blob = await getBlobForAsset(C_with_CAWG_data); + + const reader = await c2pa.reader.fromBlob(blob.type, blob); + + const manifestStore = await reader.manifestStore(); + + expect(manifestStore).toEqual(C_with_CAWG_data_trusted_ManifestStore); + + await reader.free(); + }); + + test('should report an untrusted asset when configured to verify trust', async () => { + const settings: Settings = { + trust: { + trustAnchors: anchor_incorrect, + }, + verify: { + verifyTrust: true + } + } + + const c2pa = await createC2pa({ wasmSrc, settings }); + + const blob = await getBlobForAsset(C_with_CAWG_data); + + const reader = await c2pa.reader.fromBlob(blob.type, blob); + + const manifestStore = await reader.manifestStore(); + + expect(manifestStore).toEqual(C_with_CAWG_data_untrusted_ManifestStore); + + await reader.free(); + }); + + test('should work when created from an initial segment and fragment', async () => { + const c2pa = await createC2pa({ wasmSrc }); + + const initBlob = await getBlobForAsset(dashinit); + const fragmentBlob = await getBlobForAsset(dash1); + + const reader = await c2pa.reader.fromBlobFragment(initBlob.type, initBlob, fragmentBlob); + + const manifestStore = await reader.manifestStore(); + + expect(manifestStore).toEqual(dashinit_ManifestStore); + + await reader.free(); + }); + + // TODO: can this test be written to track the status of the underlying object instead of checking for an error? + test('should be freeable', async () => { + const c2pa = await createC2pa({ wasmSrc }); + + const blob = await getBlobForAsset(C_with_CAWG_data); + + const reader = await c2pa.reader.fromBlob(blob.type, blob); + + await reader.free(); + + await expect(reader.manifestStore()).rejects.toThrowError(); + }); + }); +}); + + +async function getBlobForAsset(src: string): Promise { + const response = await fetch(src); + const blob = await response.blob(); + + return blob; +} diff --git a/packages/c2pa-web/src/lib/c2pa.ts b/packages/c2pa-web/src/lib/c2pa.ts new file mode 100644 index 0000000..c2dc06d --- /dev/null +++ b/packages/c2pa-web/src/lib/c2pa.ts @@ -0,0 +1,65 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ +import { createWorkerManager } from './worker/workerManager.js'; +import { createReaderFactory, ReaderFactory } from './reader.js'; +import { WASM_SRI } from '@contentauth/c2pa-wasm'; +import { Settings, settingsToWasmJson } from './settings.js'; + +export interface Config { + /** + * URL to fetch the WASM binary or an already-instantiated WASM module. + */ + wasmSrc: string | WebAssembly.Module; + + /** + * Settings for the SDK. + */ + settings?: Settings; +} + +interface C2paSdk { + reader: ReaderFactory; + dispose: () => void; +} + +/** + * Creates a new instance of c2pa-web by setting up a web worker and preparing a WASM binary. + * + * @param config - SDK configuration object. + * @returns An object providing access to factory methods for creating new reader objects. + * + * @example Creating a new SDK instance and reader: + * ``` + * const c2pa = await createC2pa({ wasmSrc: 'url/hosting/wasm/binary' }); + * + * const reader = await c2pa.reader.fromBlob(imageBlob.type, imageBlob); + * ``` + */ +export async function createC2pa(config: Config): Promise { + const { wasmSrc, settings } = config; + + const wasm = + typeof wasmSrc === 'string' ? await fetchAndCompileWasm(wasmSrc) : wasmSrc; + + const settingsString = settings ? settingsToWasmJson(settings) : undefined; + + const worker = await createWorkerManager({ wasm, settingsString }); + + return { + reader: createReaderFactory(worker), + dispose: worker.terminate, + }; +} + +async function fetchAndCompileWasm(src: string) { + const response = await fetch(src, { integrity: WASM_SRI }); + const wasm = await WebAssembly.compileStreaming(response); + + return wasm; +} diff --git a/packages/c2pa-web/src/lib/error.ts b/packages/c2pa-web/src/lib/error.ts new file mode 100644 index 0000000..2041ef0 --- /dev/null +++ b/packages/c2pa-web/src/lib/error.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { MAX_SIZE_IN_BYTES } from './reader.js'; + +export class AssetTooLargeError extends Error { + constructor(size: number) { + super( + `The provided asset was too large. Size: ${size} bytes. Maximum: ${MAX_SIZE_IN_BYTES}.` + ); + this.name = 'AssetTooLargeError'; + } +} + +export class UnsupportedFormatError extends Error { + constructor(format: string) { + super(`Unsupported format: ${format}.`); + this.name = 'UnsupportedFormatError'; + } +} diff --git a/packages/c2pa-web/src/lib/reader.ts b/packages/c2pa-web/src/lib/reader.ts new file mode 100644 index 0000000..b8d22b1 --- /dev/null +++ b/packages/c2pa-web/src/lib/reader.ts @@ -0,0 +1,150 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { AssetTooLargeError, UnsupportedFormatError } from './error.js'; +import { isSupportedReaderFormat } from './supportedFormats.js'; +import type { WorkerManager } from './worker/workerManager.js'; + +// 1 GB +export const MAX_SIZE_IN_BYTES = 10 ** 9; + +export interface ReaderFactory { + /** + * Create a Reader from an asset's format and a blob of its bytes. + * + * @param format Asset format + * @param blob Blob of asset bytes + * @returns An object that provides methods for reading C2PA data from the provided asset. + */ + fromBlob: (format: string, blob: Blob) => Promise; + + fromBlobFragment: ( + format: string, + init: Blob, + fragment: Blob + ) => Promise; +} + +export interface Reader { + /** + * @returns The asset's full manifest store containing all its manifests, validation statuses, and the URI of the active manifest. + */ + manifestStore: () => Promise; + + /** + * @returns The label of the active manifest. + */ + activeLabel: () => Promise; + + /** + * Resolves a URI reference to a binary object (e.g. a thumbnail) in the resource store. + * + * @param uri URI of the binary object to resolve. + * @returns An array buffer of the resource's bytes. + */ + resourceToBuffer: (uri: string) => Promise; + + /** + * Dispose of this Reader, freeing the memory it occupied and preventing further use. Call this whenever the Reader is no longer needed. + */ + free: () => Promise; +} + +/** + * + * @param worker - Worker (via WorkerManager) to be associated with this reader factory + * @returns Object containing reader creation methods + */ +export function createReaderFactory(worker: WorkerManager): ReaderFactory { + const registry = new FinalizationRegistry((id) => { + worker.execute({ method: 'reader_free', args: [id] }); + }); + + return { + async fromBlob(format: string, blob: Blob): Promise { + if (!isSupportedReaderFormat(format)) { + throw new UnsupportedFormatError(format); + } + + if (blob.size > MAX_SIZE_IN_BYTES) { + throw new AssetTooLargeError(blob.size); + } + + const readerId = await worker.execute({ + method: 'reader_fromBlob', + args: [format, blob], + }); + + const unregisterToken = Symbol(readerId); + const reader = createReader(worker, readerId, () => { + registry.unregister(unregisterToken); + }); + registry.register(reader, readerId, unregisterToken); + + return reader; + }, + + async fromBlobFragment(format: string, init: Blob, fragment: Blob) { + if (!isSupportedReaderFormat(format)) { + throw new UnsupportedFormatError(format); + } + + if (init.size > MAX_SIZE_IN_BYTES) { + throw new AssetTooLargeError(init.size); + } + + const readerId = await worker.execute({ + method: 'reader_fromBlobFragment', + args: [format, init, fragment], + }); + + const unregisterToken = Symbol(readerId); + const reader = createReader(worker, readerId, () => { + registry.unregister(unregisterToken); + }); + registry.register(reader, readerId, unregisterToken); + + return reader; + }, + }; +} + +function createReader( + worker: WorkerManager, + id: number, + onFree: () => void +): Reader { + return { + // TODO: manifest type + async manifestStore(): Promise { + const json = await worker.execute({ method: 'reader_json', args: [id] }); + + const manifestStore = JSON.parse(json); + + return manifestStore; + }, + async activeLabel(): Promise { + const label = await worker.execute({ + method: 'reader_activeLabel', + args: [id], + }); + return label; + }, + async resourceToBuffer(uri: string): Promise { + return worker.execute({ + method: 'reader_resourceToBuffer', + args: [id, uri], + }); + }, + async free(): Promise { + onFree(); + return worker.execute({ method: 'reader_free', args: [id] }); + }, + }; +} diff --git a/packages/c2pa-web/src/lib/settings.ts b/packages/c2pa-web/src/lib/settings.ts new file mode 100644 index 0000000..feb7365 --- /dev/null +++ b/packages/c2pa-web/src/lib/settings.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export interface Settings { + trust?: TrustSettings; + verify?: VerifySettings; +} + +interface TrustSettings { + userAnchors?: string; + trustAnchors?: string; + trustConfig?: string; + allowedList?: string; +} + +interface VerifySettings { + verifyTrust?: boolean; +} + +type SettingsObjectType = { + [k: string]: string | boolean | SettingsObjectType; +}; + +/** + * Converts a settings object to a JSON string of the structure expected by c2pa-rs. + */ +export function settingsToWasmJson(settings: Settings) { + return JSON.stringify(snakeCaseify(settings as SettingsObjectType)); +} + +function snakeCaseify(object: SettingsObjectType): SettingsObjectType { + const formattedObject = Object.entries(object).reduce( + (formattedObject, [key, val]) => { + formattedObject[snakeCase(key)] = + typeof val === 'object' ? snakeCaseify(val) : val; + return formattedObject; + }, + {} as SettingsObjectType + ); + + return formattedObject; +} + +function snakeCase(str: string): string { + return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`); +} diff --git a/packages/c2pa-web/src/lib/supportedFormats.ts b/packages/c2pa-web/src/lib/supportedFormats.ts new file mode 100644 index 0000000..350e982 --- /dev/null +++ b/packages/c2pa-web/src/lib/supportedFormats.ts @@ -0,0 +1,72 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export const READER_SUPPORTED_FORMATS = [ + 'jpg', + 'video/mp4', + 'image/heif', + 'video/x-msvideo', + 'pdf', + 'image/png', + 'application/c2pa', + 'video/quicktime', + 'video/avi', + 'image/gif', + 'application/xml', + 'text/xml', + 'application/xhtml+xml', + 'tiff', + 'audio/wave', + 'mp4', + 'image/avif', + 'image/dng', + 'png', + 'dng', + 'image/svg+xml', + 'image/heic', + 'application/mp4', + 'image/x-nikon-nef', + 'video/msvideo', + 'tif', + 'wav', + 'xml', + 'audio/vnd.wave', + 'xhtml', + 'gif', + 'application/x-troff-msvideo', + 'webp', + 'heic', + 'application/pdf', + 'audio/mpeg', + 'application/x-c2pa-manifest-store', + 'jpeg', + 'image/x-adobe-dng', + 'audio/wav', + 'mp3', + 'mov', + 'image/tiff', + 'audio/mp4', + 'application/svg+xml', + 'arw', + 'c2pa', + 'svg', + 'avi', + 'audio/x-wav', + 'm4a', + 'image/x-sony-arw', + 'image/jpeg', + 'avif', + 'image/webp', + 'nef', + 'heif', +]; + +export function isSupportedReaderFormat(format: string): boolean { + return READER_SUPPORTED_FORMATS.includes(format); +} diff --git a/packages/c2pa-web/src/lib/worker.ts b/packages/c2pa-web/src/lib/worker.ts new file mode 100644 index 0000000..cbb35ef --- /dev/null +++ b/packages/c2pa-web/src/lib/worker.ts @@ -0,0 +1,77 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +/// + +import { WasmReader, initSync, loadSettings } from '@contentauth/c2pa-wasm'; +import { + setupWorker, + WorkerFunctions, + WorkerResponse, +} from './worker/setupWorker.js'; +import { createWorkerObjectMap } from './worker/workerObjectMap.js'; + +const readerMap = createWorkerObjectMap(); + +const workerFunctions = { + async initWorker(module: WebAssembly.Module, settings?: string) { + initSync(module); + + if (settings) { + loadSettings(settings); + } + }, + + // Reader creation methods + async reader_fromBlob( + format: string, + blob: Blob + ): Promise> { + const reader = await WasmReader.fromBlob(format, blob); + const readerId = readerMap.add(reader); + return { data: readerId }; + }, + + async reader_fromBlobFragment( + format: string, + init: Blob, + fragment: Blob + ): Promise> { + const reader = await WasmReader.fromBlobFragment(format, init, fragment); + const readerId = readerMap.add(reader); + return { data: readerId }; + }, + + // Reader object methods + reader_json(readerId: number): WorkerResponse { + const reader = readerMap.get(readerId); + return { data: reader.json() }; + }, + reader_activeLabel(readerId: number): WorkerResponse { + const reader = readerMap.get(readerId); + return { data: reader.activeLabel() ?? null }; + }, + reader_resourceToBuffer( + readerId: number, + uri: string + ): WorkerResponse { + const reader = readerMap.get(readerId); + const buffer = reader.resourceToBuffer(uri); + return { data: buffer, transfer: [buffer] }; + }, + reader_free(readerId: number) { + const reader = readerMap.get(readerId); + reader.free(); + readerMap.remove(readerId); + }, +} satisfies WorkerFunctions; + +export type WorkerDefinition = typeof workerFunctions; + +setupWorker(workerFunctions); diff --git a/packages/c2pa-web/src/lib/worker/setupWorker.ts b/packages/c2pa-web/src/lib/worker/setupWorker.ts new file mode 100644 index 0000000..a65b6b3 --- /dev/null +++ b/packages/c2pa-web/src/lib/worker/setupWorker.ts @@ -0,0 +1,53 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { postError, postSuccess } from './workerResponse.js'; + +export interface WorkerRequest { + method: T; + args: K; + transfer?: Transferable[]; +} + +type WorkerRequestPayload = Omit, 'transfer'>; + +export interface WorkerResponse { + data: T; + transfer?: Transferable[]; +} + +export type WorkerFunctions = Record< + string, + ( + ...args: any[] + ) => void | Promise | WorkerResponse | Promise> +>; + +/** + * Prepares a worker with a list of functions to expose via postMessage and an initialization function + * + * @param functions Map of functions keyed by name + * @param init Initialization function to be called once when the worker is set up + */ +export function setupWorker(functions: WorkerFunctions) { + onmessage = async (e: MessageEvent) => { + try { + const { args, method } = e.data; + const result = await functions[method](...args); + + if (result?.data !== undefined) { + postSuccess(result.data, result.transfer); + } else { + postSuccess(); + } + } catch (e) { + postError(e); + } + }; +} diff --git a/packages/c2pa-web/src/lib/worker/workerManager.ts b/packages/c2pa-web/src/lib/worker/workerManager.ts new file mode 100644 index 0000000..03cef60 --- /dev/null +++ b/packages/c2pa-web/src/lib/worker/workerManager.ts @@ -0,0 +1,64 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { WorkerDefinition } from '../worker.js'; +import Worker from '../worker?worker&inline'; +import { WorkerRequest, WorkerResponse } from './setupWorker.js'; +import { handleWorkerResponse } from './workerResponse.js'; + +export interface WorkerManager { + execute: ( + request: WorkerRequest> + ) => Promise< + Awaited> extends WorkerResponse + ? Data + : Awaited> + >; + terminate: () => void; +} + +export interface CreateWorkerManagerConfig { + wasm: WebAssembly.Module; + settingsString?: string; +} + +/** + * Creates a new web worker and performs initialization steps: + * - Compile WASM + * - Load settings (if provided) + * + * @param config - configuration object + * @returns Facade providing convenient control over worker functions + */ +export async function createWorkerManager( + config: CreateWorkerManagerConfig +): Promise { + const { wasm, settingsString } = config; + + const worker = new Worker(); + + const execute: WorkerManager['execute'] = (request) => { + return new Promise((resolve, reject) => { + handleWorkerResponse(worker, { + onSuccess: (data) => resolve(data), + onError: (error) => reject(error), + }); + + const { method, args, transfer } = request; + worker.postMessage({ method, args }, transfer ?? []); + }); + }; + + await execute({ method: 'initWorker', args: [wasm, settingsString] }); + + return { + execute, + terminate: () => worker.terminate(), + }; +} diff --git a/packages/c2pa-web/src/lib/worker/workerObjectMap.ts b/packages/c2pa-web/src/lib/worker/workerObjectMap.ts new file mode 100644 index 0000000..4bba281 --- /dev/null +++ b/packages/c2pa-web/src/lib/worker/workerObjectMap.ts @@ -0,0 +1,35 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export function createWorkerObjectMap() { + let objId = 0; + const objectMap = new Map(); + + return { + add(object: T): number { + const id = objId++; + objectMap.set(id, object); + return id; + }, + + get(id: number): T { + const maybeObject = objectMap.get(id); + + if (!maybeObject) { + throw new Error('Attempted to use an object that has been freed'); + } + + return maybeObject; + }, + + remove(id: number): boolean { + return objectMap.delete(id); + }, + }; +} diff --git a/packages/c2pa-web/src/lib/worker/workerResponse.ts b/packages/c2pa-web/src/lib/worker/workerResponse.ts new file mode 100644 index 0000000..4be38e9 --- /dev/null +++ b/packages/c2pa-web/src/lib/worker/workerResponse.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export function postSuccess(payload?: any, transfer?: Transferable[]): void { + const responseObject = { + type: 'success', + ...(payload !== undefined ? { payload } : {}), + }; + + postMessage(responseObject, transfer ?? []); +} + +export function postError(error: unknown): void { + postMessage({ type: 'error', error }); +} + +export interface ResponseHandlers { + onSuccess: (data?: any) => void; + onError: (error?: any) => void; +} + +export function handleWorkerResponse( + worker: Worker, + responseHandlers: ResponseHandlers +) { + worker.onmessage = (event) => { + const { data } = event; + + if (data.type === 'success') { + responseHandlers.onSuccess(data?.payload); + } else { + responseHandlers.onError(data?.error); + } + }; + + // @TODO: should these have their own error handlers? + worker.onerror = (event) => { + responseHandlers.onError(event.error); + }; + + worker.onmessageerror = (event) => { + responseHandlers.onError(event.data); + }; +} diff --git a/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data.jpg b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data.jpg new file mode 100644 index 0000000..dd93c44 Binary files /dev/null and b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data.jpg differ diff --git a/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data.json b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data.json new file mode 100644 index 0000000..3dfaad9 --- /dev/null +++ b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data.json @@ -0,0 +1,144 @@ +{ + "active_manifest": "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d", + "manifests": { + "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d": { + "claim_generator_info": [ + { + "name": "c2pa cawg test", + "version": "0.58.0", + "org.contentauth.c2pa_rs": "0.58.0" + } + ], + "title": "C_with_CAWG_data.jpg", + "instance_id": "xmp:iid:855872d9-5358-497e-b7b4-afca591277e1", + "thumbnail": { + "format": "image/jpeg", + "identifier": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.thumbnail.claim" + }, + "ingredients": [], + "assertions": [ + { + "label": "c2pa.actions.v2", + "data": { + "actions": [ + { + "action": "c2pa.created", + "digitalSourceType": " http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture" + } + ], + "allActionsIncluded": true + } + }, + { + "label": "cawg.training-mining", + "data": { + "entries": { + "cawg.ai_inference": { + "use": "notAllowed" + }, + "cawg.ai_generative_training": { + "use": "notAllowed" + } + } + } + }, + { + "label": "cawg.identity", + "data": { + "signer_payload": { + "referenced_assertions": [ + { + "url": "self#jumbf=c2pa.assertions/cawg.training-mining", + "hash": "rBBgURB+/0Bc2Uk3+blNpYTGQTxOwzXQ2xhjA3gsqI4=" + }, + { + "url": "self#jumbf=c2pa.assertions/c2pa.hash.data", + "hash": "sASozh9KFSkW+cyMI0Pw5KYoD2qn7MkUEq9jUUhe/sM=" + } + ], + "sig_type": "cawg.x509.cose" + }, + "signature_info": { + "alg": "Ed25519", + "issuer": "C2PA Test Signing Cert", + "cert_serial_number": "638838410810235485828984295321338730070538954823", + "revocation_status": true + } + } + } + ], + "signature_info": { + "alg": "Es256", + "issuer": "C2PA Test Signing Cert", + "cert_serial_number": "640229841392226413189608867977836244731148734950", + "time": "2025-07-29T23:13:49+00:00" + }, + "label": "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d" + } + }, + "validation_results": { + "activeManifest": { + "success": [ + { + "code": "timeStamp.validated", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "timestamp message digest matched: DigiCert SHA256 RSA4096 Timestamp Responder 2025 1" + }, + { + "code": "claimSignature.insideValidity", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "claim signature valid" + }, + { + "code": "claimSignature.validated", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "claim signature valid" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.thumbnail.claim", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.thumbnail.claim" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.actions.v2", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.actions.v2" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.hash.data", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.hash.data" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.training-mining", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/cawg.training-mining" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.identity", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/cawg.identity" + }, + { + "code": "assertion.dataHash.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.hash.data", + "explanation": "data hash valid" + }, + { + "code": "cawg.identity.well-formed", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.identity", + "explanation": "CAWG X.509 identity signature valid" + } + ], + "informational": [ + { + "code": "timeStamp.untrusted", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "timestamp cert untrusted: DigiCert SHA256 RSA4096 Timestamp Responder 2025 1" + } + ], + "failure": [] + } + }, + "validation_state": "Valid" +} \ No newline at end of file diff --git a/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_thumbnail.jpg b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_thumbnail.jpg new file mode 100644 index 0000000..3b9c282 Binary files /dev/null and b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_thumbnail.jpg differ diff --git a/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_trusted.json b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_trusted.json new file mode 100644 index 0000000..aa5f89a --- /dev/null +++ b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_trusted.json @@ -0,0 +1,149 @@ +{ + "active_manifest": "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d", + "manifests": { + "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d": { + "assertions": [ + { + "data": { + "actions": [ + { + "action": "c2pa.created", + "digitalSourceType": " http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture" + } + ], + "allActionsIncluded": true + }, + "label": "c2pa.actions.v2" + }, + { + "data": { + "entries": { + "cawg.ai_generative_training": { + "use": "notAllowed" + }, + "cawg.ai_inference": { + "use": "notAllowed" + } + } + }, + "label": "cawg.training-mining" + }, + { + "data": { + "signature_info": { + "alg": "Ed25519", + "cert_serial_number": "638838410810235485828984295321338730070538954823", + "issuer": "C2PA Test Signing Cert", + "revocation_status": true + }, + "signer_payload": { + "referenced_assertions": [ + { + "hash": "rBBgURB+/0Bc2Uk3+blNpYTGQTxOwzXQ2xhjA3gsqI4=", + "url": "self#jumbf=c2pa.assertions/cawg.training-mining" + }, + { + "hash": "sASozh9KFSkW+cyMI0Pw5KYoD2qn7MkUEq9jUUhe/sM=", + "url": "self#jumbf=c2pa.assertions/c2pa.hash.data" + } + ], + "sig_type": "cawg.x509.cose" + } + }, + "label": "cawg.identity" + } + ], + "claim_generator_info": [ + { + "name": "c2pa cawg test", + "org.contentauth.c2pa_rs": "0.58.0", + "version": "0.58.0" + } + ], + "ingredients": [], + "instance_id": "xmp:iid:855872d9-5358-497e-b7b4-afca591277e1", + "label": "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d", + "signature_info": { + "alg": "Es256", + "cert_serial_number": "640229841392226413189608867977836244731148734950", + "issuer": "C2PA Test Signing Cert", + "time": "2025-07-29T23:13:49+00:00" + }, + "thumbnail": { + "format": "image/jpeg", + "identifier": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.thumbnail.claim" + }, + "title": "C_with_CAWG_data.jpg" + } + }, + "validation_results": { + "activeManifest": { + "failure": [], + "informational": [ + { + "code": "timeStamp.untrusted", + "explanation": "timestamp cert untrusted: DigiCert SHA256 RSA4096 Timestamp Responder 2025 1", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature" + } + ], + "success": [ + { + "code": "timeStamp.validated", + "explanation": "timestamp message digest matched: DigiCert SHA256 RSA4096 Timestamp Responder 2025 1", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature" + }, + { + "code": "signingCredential.trusted", + "explanation": "signing certificate trusted, found in System trust anchors", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature" + }, + { + "code": "claimSignature.insideValidity", + "explanation": "claim signature valid", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature" + }, + { + "code": "claimSignature.validated", + "explanation": "claim signature valid", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature" + }, + { + "code": "assertion.hashedURI.match", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.thumbnail.claim", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.thumbnail.claim" + }, + { + "code": "assertion.hashedURI.match", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.actions.v2", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.actions.v2" + }, + { + "code": "assertion.hashedURI.match", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.hash.data", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.hash.data" + }, + { + "code": "assertion.hashedURI.match", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/cawg.training-mining", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.training-mining" + }, + { + "code": "assertion.hashedURI.match", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/cawg.identity", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.identity" + }, + { + "code": "assertion.dataHash.match", + "explanation": "data hash valid", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.hash.data" + }, + { + "code": "cawg.identity.well-formed", + "explanation": "CAWG X.509 identity signature valid", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.identity" + } + ] + } + }, + "validation_state": "Trusted" +} \ No newline at end of file diff --git a/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_untrusted.json b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_untrusted.json new file mode 100644 index 0000000..1fb8088 --- /dev/null +++ b/packages/c2pa-web/test/fixtures/assets/C_with_CAWG_data_untrusted.json @@ -0,0 +1,157 @@ +{ + "active_manifest": "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d", + "manifests": { + "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d": { + "claim_generator_info": [ + { + "name": "c2pa cawg test", + "version": "0.58.0", + "org.contentauth.c2pa_rs": "0.58.0" + } + ], + "title": "C_with_CAWG_data.jpg", + "instance_id": "xmp:iid:855872d9-5358-497e-b7b4-afca591277e1", + "thumbnail": { + "format": "image/jpeg", + "identifier": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.thumbnail.claim" + }, + "ingredients": [], + "assertions": [ + { + "label": "c2pa.actions.v2", + "data": { + "actions": [ + { + "action": "c2pa.created", + "digitalSourceType": " http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture" + } + ], + "allActionsIncluded": true + } + }, + { + "label": "cawg.training-mining", + "data": { + "entries": { + "cawg.ai_inference": { + "use": "notAllowed" + }, + "cawg.ai_generative_training": { + "use": "notAllowed" + } + } + } + }, + { + "label": "cawg.identity", + "data": { + "signer_payload": { + "referenced_assertions": [ + { + "url": "self#jumbf=c2pa.assertions/cawg.training-mining", + "hash": "rBBgURB+/0Bc2Uk3+blNpYTGQTxOwzXQ2xhjA3gsqI4=" + }, + { + "url": "self#jumbf=c2pa.assertions/c2pa.hash.data", + "hash": "sASozh9KFSkW+cyMI0Pw5KYoD2qn7MkUEq9jUUhe/sM=" + } + ], + "sig_type": "cawg.x509.cose" + }, + "signature_info": { + "alg": "Ed25519", + "issuer": "C2PA Test Signing Cert", + "cert_serial_number": "638838410810235485828984295321338730070538954823", + "revocation_status": true + } + } + } + ], + "signature_info": { + "alg": "Es256", + "issuer": "C2PA Test Signing Cert", + "cert_serial_number": "640229841392226413189608867977836244731148734950", + "time": "2025-07-29T23:13:49+00:00" + }, + "label": "urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d" + } + }, + "validation_status": [ + { + "code": "signingCredential.untrusted", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "signing certificate untrusted" + }, + { + "code": "claimSignature.mismatch", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "claim signature is not valid" + } + ], + "validation_results": { + "activeManifest": { + "success": [ + { + "code": "timeStamp.validated", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "timestamp message digest matched: DigiCert SHA256 RSA4096 Timestamp Responder 2025 1" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.thumbnail.claim", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.thumbnail.claim" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.actions.v2", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.actions.v2" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.hash.data", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/c2pa.hash.data" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.training-mining", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/cawg.training-mining" + }, + { + "code": "assertion.hashedURI.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.identity", + "explanation": "hashed uri matched: self#jumbf=c2pa.assertions/cawg.identity" + }, + { + "code": "assertion.dataHash.match", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/c2pa.hash.data", + "explanation": "data hash valid" + }, + { + "code": "cawg.identity.well-formed", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.assertions/cawg.identity", + "explanation": "CAWG X.509 identity signature valid" + } + ], + "informational": [ + { + "code": "timeStamp.untrusted", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "timestamp cert untrusted: DigiCert SHA256 RSA4096 Timestamp Responder 2025 1" + } + ], + "failure": [ + { + "code": "signingCredential.untrusted", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "signing certificate untrusted" + }, + { + "code": "claimSignature.mismatch", + "url": "self#jumbf=/c2pa/urn:c2pa:822f2ec0-ef27-4d95-88b4-74586c12873d/c2pa.signature", + "explanation": "claim signature is not valid" + } + ] + } + }, + "validation_state": "Invalid" +} \ No newline at end of file diff --git a/packages/c2pa-web/test/fixtures/assets/dash1.m4s b/packages/c2pa-web/test/fixtures/assets/dash1.m4s new file mode 100644 index 0000000..1a9a996 Binary files /dev/null and b/packages/c2pa-web/test/fixtures/assets/dash1.m4s differ diff --git a/packages/c2pa-web/test/fixtures/assets/dashinit.json b/packages/c2pa-web/test/fixtures/assets/dashinit.json new file mode 100644 index 0000000..03ca4e3 --- /dev/null +++ b/packages/c2pa-web/test/fixtures/assets/dashinit.json @@ -0,0 +1,184 @@ +{ + "active_manifest": "contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D", + "manifests": { + "contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D": { + "assertions": [ + { + "data": { + "alg": "sha256", + "exclusions": [ + { + "xpath": "/ftyp" + }, + { + "data": [ + { + "offset": 8, + "value": "2P7D1hsOSDySl1goh37EgQ==" + } + ], + "xpath": "/uuid" + }, + { + "xpath": "/mfra" + } + ], + "merkle": [ + { + "alg": "sha256", + "count": 11, + "hashes": [ + [ + 32, + 27, + 124, + 253, + 19, + 16, + 238, + 99, + 19, + 245, + 165, + 233, + 110, + 225, + 224, + 222, + 161, + 102, + 0, + 71, + 38, + 206, + 73, + 77, + 223, + 1, + 107, + 162, + 104, + 32, + 243, + 9 + ], + [ + 192, + 181, + 181, + 219, + 136, + 29, + 104, + 246, + 176, + 186, + 209, + 51, + 55, + 131, + 205, + 169, + 239, + 127, + 116, + 236, + 64, + 87, + 223, + 54, + 112, + 105, + 28, + 230, + 157, + 81, + 34, + 38 + ], + [ + 153, + 235, + 245, + 57, + 193, + 14, + 6, + 251, + 138, + 167, + 158, + 186, + 20, + 9, + 28, + 207, + 137, + 31, + 115, + 195, + 30, + 109, + 233, + 70, + 144, + 84, + 8, + 59, + 16, + 37, + 141, + 201 + ] + ], + "initHash": "I06fNAlptpr/4DcJZ/wIMRgd0bb6qygVCrodNQhhvbI=", + "localId": 1, + "uniqueId": 1 + } + ] + }, + "label": "c2pa.hash.bmff.v2" + } + ], + "claim_generator": "drmprovenancemanifestbuilder/1.0", + "claim_generator_info": [ + { + "name": "Test provenance manaifest builder" + } + ], + "format": "video/mp4", + "ingredients": [], + "instance_id": "1.0", + "label": "contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D", + "signature_info": { + "alg": "Es256", + "cert_serial_number": "231582073800106855458784768030131201943489567163", + "issuer": "Media Publisher Company" + } + } + }, + "validation_results": { + "activeManifest": { + "failure": [], + "informational": [], + "success": [ + { + "code": "claimSignature.insideValidity", + "explanation": "claim signature valid", + "url": "self#jumbf=/c2pa/contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D/c2pa.signature" + }, + { + "code": "claimSignature.validated", + "explanation": "claim signature valid", + "url": "self#jumbf=/c2pa/contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D/c2pa.signature" + }, + { + "code": "assertion.hashedURI.match", + "explanation": "hashed uri matched: self#jumbf=c2pa/contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D/c2pa.assertions/c2pa.hash.bmff.v2", + "url": "self#jumbf=c2pa/contoso:urn:uuid:FA0E000D-FA0E-000D-FA0E-000DFA0E000D/c2pa.assertions/c2pa.hash.bmff.v2" + } + ] + } + }, + "validation_state": "Valid" +} \ No newline at end of file diff --git a/packages/c2pa-web/test/fixtures/assets/dashinit.mp4 b/packages/c2pa-web/test/fixtures/assets/dashinit.mp4 new file mode 100644 index 0000000..b1f703a Binary files /dev/null and b/packages/c2pa-web/test/fixtures/assets/dashinit.mp4 differ diff --git a/packages/c2pa-web/test/fixtures/assets/no_alg.jpg b/packages/c2pa-web/test/fixtures/assets/no_alg.jpg new file mode 100644 index 0000000..3587ed5 Binary files /dev/null and b/packages/c2pa-web/test/fixtures/assets/no_alg.jpg differ diff --git a/packages/c2pa-web/test/fixtures/trust/anchor-correct.pem b/packages/c2pa-web/test/fixtures/trust/anchor-correct.pem new file mode 100644 index 0000000..2a8e580 --- /dev/null +++ b/packages/c2pa-web/test/fixtures/trust/anchor-correct.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUzCCAfmgAwIBAgIUdmkq4byvgk2FSnddHqB2yjoD68gwCgYIKoZIzj0EAwIw +dzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTb21ld2hlcmUx +GjAYBgNVBAoMEUMyUEEgVGVzdCBSb290IENBMRkwFwYDVQQLDBBGT1IgVEVTVElO +R19PTkxZMRAwDgYDVQQDDAdSb290IENBMB4XDTIyMDYxMDE4NDY0MFoXDTMyMDYw +NzE4NDY0MFowdzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlT +b21ld2hlcmUxGjAYBgNVBAoMEUMyUEEgVGVzdCBSb290IENBMRkwFwYDVQQLDBBG +T1IgVEVTVElOR19PTkxZMRAwDgYDVQQDDAdSb290IENBMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEre/KpcWwGEHt+mD4xso3xotRnRx2IEsMoYwVIKI7iEJrDEye +PcvJuBywA0qiMw2yvAvGOzW/fqUTu1jABrFIk6NjMGEwHQYDVR0OBBYEFF6ZuIbh +eBvZVxVadQBStikOy6iMMB8GA1UdIwQYMBaAFF6ZuIbheBvZVxVadQBStikOy6iM +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0gA +MEUCIHBC1xLwkCWSGhVXFlSnQBx9cGZivXzCbt8BuwRqPSUoAiEAteZQDk685yh9 +jgOTkp4H8oAmM1As+qlkRK2b+CHAQ3k= +-----END CERTIFICATE----- diff --git a/packages/c2pa-web/test/fixtures/trust/anchor-incorrect.pem b/packages/c2pa-web/test/fixtures/trust/anchor-incorrect.pem new file mode 100644 index 0000000..9c9bf93 --- /dev/null +++ b/packages/c2pa-web/test/fixtures/trust/anchor-incorrect.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICkTCCAhagAwIBAgIUIngKvNC/BMF3TRIafgweprIbGgAwCgYIKoZIzj0EAwMw +dzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTb21ld2hlcmUx +GjAYBgNVBAoMEUMyUEEgVGVzdCBSb290IENBMRkwFwYDVQQLDBBGT1IgVEVTVElO +R19PTkxZMRAwDgYDVQQDDAdSb290IENBMB4XDTIyMDYxMDE4NDY0MFoXDTMyMDYw +NzE4NDY0MFowdzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlT +b21ld2hlcmUxGjAYBgNVBAoMEUMyUEEgVGVzdCBSb290IENBMRkwFwYDVQQLDBBG +T1IgVEVTVElOR19PTkxZMRAwDgYDVQQDDAdSb290IENBMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAEX3FzSTnCcEAP3wteNaiy4GZzZ+ABd2Y7gJpfyZf3kkCuX/I3psFq +QBRvb3/FEBaDT4VbDNlZ0WLwtw5d3PI42Zufgpxemgfjf31d8H51eU3/IfAz5AFX +y/OarhObHgVvo2MwYTAdBgNVHQ4EFgQUe+FK5t6/bQGIcGY6kkeIKTX/bJ0wHwYD +VR0jBBgwFoAUe+FK5t6/bQGIcGY6kkeIKTX/bJ0wDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaQAwZgIxAPOgmJbVdhDh9KlgQXqE +FzHiCt347JG4strk22MXzOgxQ0LnXStIh+viC3S1INzuBgIxAI1jiUBX/V7Gg0y6 +Y/p6a63Xp2w+ia7vlUaUBWsR3ex9NNSTPLNoDkoTCSDOE2O20w== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/packages/browser/tsconfig.json b/packages/c2pa-web/tsconfig.json similarity index 100% rename from packages/browser/tsconfig.json rename to packages/c2pa-web/tsconfig.json diff --git a/packages/browser/tsconfig.lib.json b/packages/c2pa-web/tsconfig.lib.json similarity index 91% rename from packages/browser/tsconfig.lib.json rename to packages/c2pa-web/tsconfig.lib.json index e9e008f..c2cd988 100644 --- a/packages/browser/tsconfig.lib.json +++ b/packages/c2pa-web/tsconfig.lib.json @@ -7,7 +7,8 @@ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo", "emitDeclarationOnly": true, "forceConsistentCasingInFileNames": true, - "types": ["node", "vite/client"] + "types": ["vite/client"], + "lib": ["DOM", "ES2023"] }, "include": ["src/**/*.ts"], "references": [], diff --git a/packages/browser/tsconfig.spec.json b/packages/c2pa-web/tsconfig.spec.json similarity index 80% rename from packages/browser/tsconfig.spec.json rename to packages/c2pa-web/tsconfig.spec.json index c695608..b934fae 100644 --- a/packages/browser/tsconfig.spec.json +++ b/packages/c2pa-web/tsconfig.spec.json @@ -3,14 +3,14 @@ "compilerOptions": { "outDir": "./out-tsc/vitest", "types": [ - "vitest/globals", "vitest/importMeta", "vite/client", - "node", "vitest", "@vitest/browser/providers/playwright" ], - "forceConsistentCasingInFileNames": true + "lib": ["DOM", "ES2023"], + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, }, "include": [ "vite.config.ts", @@ -25,7 +25,8 @@ "src/**/*.spec.js", "src/**/*.test.jsx", "src/**/*.spec.jsx", - "src/**/*.d.ts" + "src/**/*.d.ts", + "test/**/*.json" ], "references": [ { diff --git a/packages/c2pa-web/vite.config.ts b/packages/c2pa-web/vite.config.ts new file mode 100644 index 0000000..b3a06af --- /dev/null +++ b/packages/c2pa-web/vite.config.ts @@ -0,0 +1,91 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ +import { defineConfig, Plugin } from 'vite'; +import dts from 'vite-plugin-dts'; +import { workspaceRoot } from '@nx/devkit'; +import { rimrafSync } from 'rimraf'; +import { join } from 'path'; +import { mkdirSync, linkSync } from 'fs'; +export default defineConfig(() => ({ + root: __dirname, + cacheDir: '../../node_modules/.vite/packages/web', + plugins: [ + dts({ + entryRoot: 'src', + tsconfigPath: join(__dirname, 'tsconfig.lib.json'), + }), + createBuildPlugin(), + ], + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + outDir: './dist', + emptyOutDir: false, // Done in our custom plugin so we can correctly create the "resources" folder + reportCompressedSize: true, + commonjsOptions: { + transformMixedEsModules: true, + }, + lib: { + entry: 'src/index.ts', + name: '@contentauth/c2pa-web', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es' as const], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: [], + }, + }, + server: { + fs: { + deny: [], + }, + }, + test: { + watch: false, + include: ['{src,test}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + browser: { + headless: true, + enabled: true, + provider: 'playwright', + // https://vitest.dev/guide/browser/playwright + instances: [{ browser: 'chromium' }], + screenshotFailures: false, + }, + }, +})); + +/** + * This plugin has two responsibilities: + * 1. Clears the output directory (Vite's default emptyOutDir behavior will delete the files copied in step 2) + * 2. Links the WASM resources into the output directory so they can be packaged with the published library + */ +function createBuildPlugin(): Plugin { + return { + name: 'contentauth-web-build', + buildStart: () => { + const wasmPackageName = 'c2pa-wasm'; + const wasmResourceName = 'c2pa_bg.wasm'; + const wasmPackagePath = join(workspaceRoot, 'packages', wasmPackageName); + const wasmOutDir = join(wasmPackagePath, 'pkg'); + const wasmResourcePath = join(wasmOutDir, wasmResourceName); + + const pkgOutDir = join(__dirname, 'dist'); + const pkgResourceDir = join(pkgOutDir, 'resources'); + const pkgResourcePath = join(pkgResourceDir, wasmResourceName); + + rimrafSync(pkgOutDir); + + mkdirSync(pkgResourceDir, { recursive: true }); + linkSync(wasmResourcePath, pkgResourcePath); + }, + }; +} diff --git a/packages/wasm/package.json b/packages/wasm/package.json deleted file mode 100644 index 8f57329..0000000 --- a/packages/wasm/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@contentauth/wasm", - "version": "0.0.1", - "private": true, - "type": "module", - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "pkg/**/*" - ], - "exports": { - "./package.json": "./package.json", - ".": "./pkg/wasm.js", - "./assets/test.wasm": "./pkg/wasm_bg.wasm", - "./assets/test.wasm.d.ts": "./pkg/wasm_bg.wasm.d.ts" - }, - "dependencies": {} -} \ No newline at end of file diff --git a/packages/wasm/src/lib.rs b/packages/wasm/src/lib.rs deleted file mode 100644 index 1c3f531..0000000 --- a/packages/wasm/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -pub fn foobar() -> String { - String::from("foobar") -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d357e3b..cff9f19 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,10 +7,6 @@ settings: importers: .: - dependencies: - '@nx/devkit': - specifier: 21.3.5 - version: 21.3.5(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) devDependencies: '@eslint/js': specifier: ^9.8.0 @@ -18,6 +14,9 @@ importers: '@monodon/rust': specifier: ^2.3.0 version: 2.3.0(@napi-rs/cli@3.0.3(@emnapi/runtime@1.4.5)(@types/node@18.16.9))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) + '@nx/devkit': + specifier: 21.3.5 + version: 21.3.5(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) '@nx/eslint': specifier: 21.3.5 version: 21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.31.0(jiti@2.4.2))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) @@ -32,7 +31,7 @@ importers: version: 21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.31.0(jiti@2.4.2))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17)))(typescript@5.8.3) '@nx/vite': specifier: 21.3.5 - version: 21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))(vitest@3.2.4) + version: 21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(vitest@3.2.4) '@nx/web': specifier: 21.3.5 version: 21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) @@ -63,6 +62,9 @@ importers: eslint-config-prettier: specifier: ^10.0.0 version: 10.1.8(eslint@9.31.0(jiti@2.4.2)) + eslint-plugin-headers: + specifier: ^1.3.3 + version: 1.3.3(eslint@9.31.0(jiti@2.4.2)) jiti: specifier: 2.4.2 version: 2.4.2 @@ -89,37 +91,64 @@ importers: version: 8.38.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) vite: specifier: ^6.0.0 - version: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) + version: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) vite-plugin-dts: specifier: ~4.5.0 - version: 4.5.4(@types/node@18.16.9)(rollup@4.45.1)(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0)) + version: 4.5.4(@types/node@18.16.9)(rollup@4.45.1)(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0)) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(yaml@2.8.0) + version: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0) + + packages/c2pa-wasm: {} - packages/browser: + packages/c2pa-web: dependencies: - '@contentauth/wasm': + '@contentauth/c2pa-wasm': specifier: workspace:* - version: link:../wasm + version: link:../c2pa-wasm devDependencies: + '@playwright/test': + specifier: ^1.55.0 + version: 1.55.0 + '@types/ssri': + specifier: ^7.1.5 + version: 7.1.5 '@vitest/browser': specifier: ^3.2.4 - version: 3.2.4(playwright@1.54.1)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))(vitest@3.2.4) - playwright: - specifier: ^1.54.1 - version: 1.54.1 + version: 3.2.4(playwright@1.55.0)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(vitest@3.2.4) + rimraf: + specifier: ^6.0.1 + version: 6.0.1 - packages/wasm: {} - - tools/nx-wasm-pack: + tools/nx-wasm-bindgen: dependencies: '@nx/devkit': specifier: 21.3.5 version: 21.3.5(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 + '@types/ssri': + specifier: ^7.1.5 + version: 7.1.5 + ssri: + specifier: ^12.0.0 + version: 12.0.0 tslib: specifier: ^2.3.0 version: 2.8.1 + zx: + specifier: ^8.8.0 + version: 8.8.0 + + tools/testbed: + dependencies: + '@contentauth/c2pa-wasm': + specifier: workspace:* + version: link:../../packages/c2pa-wasm + '@contentauth/c2pa-web': + specifier: workspace:* + version: link:../../packages/c2pa-web packages: @@ -1088,6 +1117,14 @@ packages: '@types/node': optional: true + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1180,6 +1217,9 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} + '@jridgewell/sourcemap-codec@1.5.4': resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} @@ -1818,6 +1858,11 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@playwright/test@1.55.0': + resolution: {integrity: sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==} + engines: {node: '>=18'} + hasBin: true + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -2128,6 +2173,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} @@ -2143,12 +2191,18 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + '@types/node@18.16.9': resolution: {integrity: sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + '@types/ssri@7.1.5': + resolution: {integrity: sha512-odD/56S3B51liILSk5aXJlnYt99S6Rt9EFDDqGtJM26rKHApHcwyU/UoYHrzKkdkHMAIquGWCuHtQTbes+FRQw==} + '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -2796,6 +2850,9 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@6.2.1: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} @@ -3024,6 +3081,12 @@ packages: peerDependencies: eslint: '>=7.0.0' + eslint-plugin-headers@1.3.3: + resolution: {integrity: sha512-VzZY4+cGRoR5HpALLARH+ibIjB6a2w12/cFEayORHXMRHMzDnweSjpmvxyzX3rsSIVCg01zmvepB7Tnmaj4kGQ==} + engines: {node: ^16.0.0 || >= 18.0.0} + peerDependencies: + eslint: '>=7' + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3291,6 +3354,11 @@ packages: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true + glob@11.0.3: + resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} + engines: {node: 20 || >=22} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -3505,6 +3573,10 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} + jake@10.9.2: resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} engines: {node: '>=10'} @@ -3747,6 +3819,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.1.0: + resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3811,6 +3887,10 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + minimatch@10.0.3: + resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} + engines: {node: 20 || >=22} + minimatch@3.0.8: resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} @@ -4009,6 +4089,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -4047,13 +4131,13 @@ packages: pkg-types@2.2.0: resolution: {integrity: sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==} - playwright-core@1.54.1: - resolution: {integrity: sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==} + playwright-core@1.55.0: + resolution: {integrity: sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==} engines: {node: '>=18'} hasBin: true - playwright@1.54.1: - resolution: {integrity: sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==} + playwright@1.55.0: + resolution: {integrity: sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==} engines: {node: '>=18'} hasBin: true @@ -4187,6 +4271,11 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + rollup@4.45.1: resolution: {integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -4314,6 +4403,10 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + ssri@12.0.0: + resolution: {integrity: sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==} + engines: {node: ^18.17.0 || >=20.5.0} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -4406,6 +4499,11 @@ packages: tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + terser@5.43.1: + resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} + engines: {node: '>=10'} + hasBin: true + test-exclude@6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} @@ -4805,6 +4903,11 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} + zx@8.8.0: + resolution: {integrity: sha512-v0VZXgSHusDvTtZROno3Ws8xkE1uNSSwH/yF8Fm+ZwBrYhr+bRNNpsnTJ32eR/t6umc7lAz5WqdP800ugW9zFA==} + engines: {node: '>= 12.17.0'} + hasBin: true + snapshots: '@ampproject/remapping@2.3.0': @@ -5862,6 +5965,12 @@ snapshots: optionalDependencies: '@types/node': 18.16.9 + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -6031,6 +6140,12 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/source-map@0.3.10': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + optional: true + '@jridgewell/sourcemap-codec@1.5.4': {} '@jridgewell/trace-mapping@0.3.29': @@ -6616,7 +6731,7 @@ snapshots: - typescript - verdaccio - '@nx/vite@21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))(vitest@3.2.4)': + '@nx/vite@21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(vitest@3.2.4)': dependencies: '@nx/devkit': 21.3.5(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) '@nx/js': 21.3.5(@babel/traverse@7.28.0)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))(nx@21.3.5(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)(typescript@5.8.3))(@swc/core@1.5.29(@swc/helpers@0.5.17))) @@ -6627,8 +6742,8 @@ snapshots: picomatch: 4.0.2 semver: 7.7.2 tsconfig-paths: 4.2.0 - vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) - vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(yaml@2.8.0) + vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) + vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6743,6 +6858,10 @@ snapshots: '@pkgr/core@0.2.9': {} + '@playwright/test@1.55.0': + dependencies: + playwright: 1.55.0 + '@polka/url@1.0.0-next.29': {} '@rollup/pluginutils@5.2.0(rollup@4.45.1)': @@ -7028,6 +7147,11 @@ snapshots: '@types/estree@1.0.8': {} + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 18.16.9 + '@types/http-cache-semantics@4.0.4': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -7042,10 +7166,18 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 18.16.9 + '@types/node@18.16.9': {} '@types/parse-json@4.0.2': {} + '@types/ssri@7.1.5': + dependencies: + '@types/node': 18.16.9 + '@types/stack-utils@2.0.3': {} '@types/yargs-parser@21.0.3': {} @@ -7208,19 +7340,19 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitest/browser@3.2.4(playwright@1.54.1)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))(vitest@3.2.4)': + '@vitest/browser@3.2.4(playwright@1.55.0)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(vitest@3.2.4)': dependencies: '@testing-library/dom': 10.4.0 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0)) '@vitest/utils': 3.2.4 magic-string: 0.30.17 sirv: 3.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(yaml@2.8.0) + vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0) ws: 8.18.3 optionalDependencies: - playwright: 1.54.1 + playwright: 1.55.0 transitivePeerDependencies: - bufferutil - msw @@ -7242,9 +7374,9 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(yaml@2.8.0) + vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0) optionalDependencies: - '@vitest/browser': 3.2.4(playwright@1.54.1)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))(vitest@3.2.4) + '@vitest/browser': 3.2.4(playwright@1.55.0)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(vitest@3.2.4) transitivePeerDependencies: - supports-color @@ -7256,13 +7388,13 @@ snapshots: chai: 5.2.1 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) '@vitest/pretty-format@3.2.4': dependencies: @@ -7293,7 +7425,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(yaml@2.8.0) + vitest: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: @@ -7813,6 +7945,9 @@ snapshots: dependencies: delayed-stream: 1.0.0 + commander@2.20.3: + optional: true + commander@6.2.1: {} commander@8.3.0: {} @@ -8014,6 +8149,10 @@ snapshots: dependencies: eslint: 9.31.0(jiti@2.4.2) + eslint-plugin-headers@1.3.3(eslint@9.31.0(jiti@2.4.2)): + dependencies: + eslint: 9.31.0(jiti@2.4.2) + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -8317,6 +8456,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@11.0.3: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.1 + minimatch: 10.0.3 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -8538,6 +8686,10 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@4.1.1: + dependencies: + '@isaacs/cliui': 8.0.2 + jake@10.9.2: dependencies: async: 3.2.6 @@ -8945,6 +9097,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.1.0: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -8998,6 +9152,10 @@ snapshots: mimic-response@4.0.0: {} + minimatch@10.0.3: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + minimatch@3.0.8: dependencies: brace-expansion: 1.1.12 @@ -9221,6 +9379,11 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-scurry@2.0.0: + dependencies: + lru-cache: 11.1.0 + minipass: 7.1.2 + path-type@4.0.0: {} pathe@2.0.3: {} @@ -9253,11 +9416,11 @@ snapshots: exsolve: 1.0.7 pathe: 2.0.3 - playwright-core@1.54.1: {} + playwright-core@1.55.0: {} - playwright@1.54.1: + playwright@1.55.0: dependencies: - playwright-core: 1.54.1 + playwright-core: 1.55.0 optionalDependencies: fsevents: 2.3.2 @@ -9376,6 +9539,11 @@ snapshots: reusify@1.1.0: {} + rimraf@6.0.1: + dependencies: + glob: 11.0.3 + package-json-from-dist: 1.0.1 + rollup@4.45.1: dependencies: '@types/estree': 1.0.8 @@ -9517,6 +9685,10 @@ snapshots: sprintf-js@1.0.3: {} + ssri@12.0.0: + dependencies: + minipass: 7.1.2 + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -9614,6 +9786,14 @@ snapshots: fast-fifo: 1.3.2 streamx: 2.22.1 + terser@5.43.1: + dependencies: + '@jridgewell/source-map': 0.3.10 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + optional: true + test-exclude@6.0.0: dependencies: '@istanbuljs/schema': 0.1.3 @@ -9799,13 +9979,13 @@ snapshots: validate-npm-package-name@5.0.1: {} - vite-node@3.2.4(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0): + vite-node@3.2.4(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -9820,7 +10000,7 @@ snapshots: - tsx - yaml - vite-plugin-dts@4.5.4(@types/node@18.16.9)(rollup@4.45.1)(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0)): + vite-plugin-dts@4.5.4(@types/node@18.16.9)(rollup@4.45.1)(typescript@5.8.3)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0)): dependencies: '@microsoft/api-extractor': 7.52.8(@types/node@18.16.9) '@rollup/pluginutils': 5.2.0(rollup@4.45.1) @@ -9833,13 +10013,13 @@ snapshots: magic-string: 0.30.17 typescript: 5.8.3 optionalDependencies: - vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0): + vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0): dependencies: esbuild: 0.25.8 fdir: 6.4.6(picomatch@4.0.2) @@ -9851,13 +10031,14 @@ snapshots: '@types/node': 18.16.9 fsevents: 2.3.3 jiti: 2.4.2 + terser: 5.43.1 yaml: 2.8.0 - vitest@3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(yaml@2.8.0): + vitest@3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -9875,12 +10056,12 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) - vite-node: 3.2.4(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 18.16.9 - '@vitest/browser': 3.2.4(playwright@1.54.1)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(yaml@2.8.0))(vitest@3.2.4) + '@vitest/browser': 3.2.4(playwright@1.55.0)(vite@6.3.5(@types/node@18.16.9)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(vitest@3.2.4) '@vitest/ui': 3.2.4(vitest@3.2.4) jsdom: 22.1.0 transitivePeerDependencies: @@ -10000,3 +10181,5 @@ snapshots: yocto-queue@1.2.1: {} yoctocolors-cjs@2.1.2: {} + + zx@8.8.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 37770b6..2562c12 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,5 +4,6 @@ packages: onlyBuiltDependencies: - '@swc/core' + - esbuild - nx - unrs-resolver diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..afc317d --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +group_imports = "StdExternalCrate" \ No newline at end of file diff --git a/tools/nx-wasm-bindgen/README.md b/tools/nx-wasm-bindgen/README.md new file mode 100644 index 0000000..83557c7 --- /dev/null +++ b/tools/nx-wasm-bindgen/README.md @@ -0,0 +1,11 @@ +# nx-wasm-bindgen + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build nx-wasm-bindgen` to build the library. + +## Running unit tests + +Run `nx test nx-wasm-bindgen` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/tools/nx-wasm-pack/eslint.config.mjs b/tools/nx-wasm-bindgen/eslint.config.mjs similarity index 72% rename from tools/nx-wasm-pack/eslint.config.mjs rename to tools/nx-wasm-bindgen/eslint.config.mjs index 03ea26d..0b6073b 100644 --- a/tools/nx-wasm-pack/eslint.config.mjs +++ b/tools/nx-wasm-bindgen/eslint.config.mjs @@ -1,3 +1,12 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + import baseConfig from '../../eslint.config.mjs'; export default [ @@ -8,6 +17,7 @@ export default [ '@nx/dependency-checks': [ 'error', { + checkObsoleteDependencies: false, ignoredFiles: [ '{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}', '{projectRoot}/vite.config.{js,ts,mjs,mts}', diff --git a/tools/nx-wasm-bindgen/executors.json b/tools/nx-wasm-bindgen/executors.json new file mode 100644 index 0000000..3e324f2 --- /dev/null +++ b/tools/nx-wasm-bindgen/executors.json @@ -0,0 +1,14 @@ +{ + "executors": { + "build": { + "implementation": "./src/executors/build/executor", + "schema": "./src/executors/build/schema.json", + "description": "Build a project with wasm-bindgen" + }, + "test": { + "implementation": "./dist/executors/test/executor", + "schema": "./dist/executors/test/schema.json", + "description": "Test a project with wasm-bindgen-test" + } + } +} diff --git a/tools/nx-wasm-pack/package.json b/tools/nx-wasm-bindgen/package.json similarity index 62% rename from tools/nx-wasm-pack/package.json rename to tools/nx-wasm-bindgen/package.json index f436ad3..6fea78e 100644 --- a/tools/nx-wasm-pack/package.json +++ b/tools/nx-wasm-bindgen/package.json @@ -1,7 +1,8 @@ { - "name": "nx-wasm-pack", + "name": "nx-wasm-bindgen", "version": "0.0.1", "private": true, + "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", @@ -14,6 +15,9 @@ "default": "./dist/index.js" } }, + "scripts": { + "test": "echo \"No tests to run\" && exit 0" + }, "nx": { "targets": { "build": { @@ -22,19 +26,19 @@ "{options.outputPath}" ], "options": { - "outputPath": "tools/nx-wasm-pack/dist", - "main": "tools/nx-wasm-pack/src/index.ts", - "tsConfig": "tools/nx-wasm-pack/tsconfig.lib.json", - "rootDir": "tools/nx-wasm-pack/src", + "outputPath": "tools/nx-wasm-bindgen/dist", + "main": "tools/nx-wasm-bindgen/src/index.ts", + "tsConfig": "tools/nx-wasm-bindgen/tsconfig.lib.json", + "rootDir": "tools/nx-wasm-bindgen/src", "generatePackageJson": false, "assets": [ { - "input": "./tools/nx-wasm-pack/src", + "input": "./tools/nx-wasm-bindgen/src", "glob": "**/!(*.ts)", "output": "." }, { - "input": "./tools/nx-wasm-pack/src", + "input": "./tools/nx-wasm-bindgen/src", "glob": "**/*.d.ts", "output": "." } @@ -45,7 +49,11 @@ }, "dependencies": { "@nx/devkit": "21.3.5", - "tslib": "^2.3.0" + "@types/fs-extra": "^11.0.4", + "@types/ssri": "^7.1.5", + "ssri": "^12.0.0", + "tslib": "^2.3.0", + "zx": "^8.8.0" }, "executors": "./executors.json", "files": [ diff --git a/tools/nx-wasm-bindgen/src/executors/build/executor.ts b/tools/nx-wasm-bindgen/src/executors/build/executor.ts new file mode 100644 index 0000000..b4b22e8 --- /dev/null +++ b/tools/nx-wasm-bindgen/src/executors/build/executor.ts @@ -0,0 +1,84 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { PromiseExecutor } from '@nx/devkit'; +import { BuildExecutorSchema } from './schema.js'; +import { fromStream } from 'ssri'; +import { $, path, fs } from 'zx'; + +const runExecutor: PromiseExecutor = async ( + options, + context +) => { + const projectPath = path.join(context.root, options['project-dir']); + const outputWasmName = 'c2pa'; + const $$ = $({ cwd: projectPath }); + + const cargoOutDir = path.join( + context.root, + 'dist', + 'target', + 'wasm32-unknown-unknown' + ); + + await fs.remove(cargoOutDir); + + try { + // Run cargo build + await $$`cargo build --release --target wasm32-unknown-unknown`; + + const formattedProjectName = context.projectName?.replace('-', '_'); + + const cargoOutput = path.join( + context.root, + `dist/target/wasm32-unknown-unknown/release/${formattedProjectName}.wasm` + ); + + const outDir = path.join(projectPath, 'pkg'); + + // Clean output directory + await fs.remove(outDir); + + // Run wasm-bindgen on cargo build output + await $$`wasm-bindgen ${cargoOutput} --out-dir ${outDir} --out-name ${outputWasmName} --target web --omit-default-module-path`; + + // Run wasm-opt on wasm-bindgen output, optimizing for size + const wasmOptInput = path.join(outDir, `${outputWasmName}_bg.wasm`); + + await $$`wasm-opt ${wasmOptInput} -o ${wasmOptInput} -Oz`; + + // Compute SRI integrity and append it to wasm-bindgen's JS output and .d.ts as an exported const + const wasmFileStream = fs.createReadStream(wasmOptInput); + const integrityData = await fromStream(wasmFileStream); + const integrityString = JSON.stringify(integrityData.toString()); + + const javascriptOutput = path.join(outDir, `${outputWasmName}.js`); + + await fs.appendFile( + javascriptOutput, + `export const WASM_SRI = ${integrityString};` + ); + + const dtsOutput = path.join(outDir, `${outputWasmName}.d.ts`); + + await fs.appendFile(dtsOutput, 'export declare const WASM_SRI: string;'); + + return { + success: true, + }; + } catch (error) { + console.error('Error building release:', error); + + return { + success: false, + }; + } +}; + +export default runExecutor; diff --git a/tools/nx-wasm-bindgen/src/executors/build/schema.d.ts b/tools/nx-wasm-bindgen/src/executors/build/schema.d.ts new file mode 100644 index 0000000..b9058a8 --- /dev/null +++ b/tools/nx-wasm-bindgen/src/executors/build/schema.d.ts @@ -0,0 +1,12 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export interface BuildExecutorSchema { + 'project-dir': string; +} diff --git a/tools/nx-wasm-pack/src/executors/build/schema.json b/tools/nx-wasm-bindgen/src/executors/build/schema.json similarity index 64% rename from tools/nx-wasm-pack/src/executors/build/schema.json rename to tools/nx-wasm-bindgen/src/executors/build/schema.json index dc694da..e227e69 100644 --- a/tools/nx-wasm-pack/src/executors/build/schema.json +++ b/tools/nx-wasm-bindgen/src/executors/build/schema.json @@ -8,15 +8,6 @@ "project-dir": { "type": "string", "description": "Directory of project" - }, - "profile": { - "type": "string", - "enum": [ - "dev", - "profiling", - "release" - ], - "default": "release" } }, "required": ["project-dir"] diff --git a/tools/nx-wasm-bindgen/src/executors/test/executor.ts b/tools/nx-wasm-bindgen/src/executors/test/executor.ts new file mode 100644 index 0000000..6303b0e --- /dev/null +++ b/tools/nx-wasm-bindgen/src/executors/test/executor.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { PromiseExecutor } from '@nx/devkit'; +import { TestExecutorSchema } from './schema.js'; +import { $, path, ProcessOutput } from 'zx'; + +const runExecutor: PromiseExecutor = async ( + options, + context +) => { + const projectPath = path.join(context.root, options['project-dir']); + const $$ = $({ cwd: projectPath }); + + try { + await $$`wasm-pack test --headless --chrome`; + + return { + success: true, + }; + } catch (e: unknown) { + if (e instanceof ProcessOutput) { + console.error(e.stdout); + } else { + console.error('Error running tests', e); + } + + return { + success: false, + }; + } +}; + +export default runExecutor; diff --git a/tools/nx-wasm-bindgen/src/executors/test/schema.d.ts b/tools/nx-wasm-bindgen/src/executors/test/schema.d.ts new file mode 100644 index 0000000..62db116 --- /dev/null +++ b/tools/nx-wasm-bindgen/src/executors/test/schema.d.ts @@ -0,0 +1,12 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +export interface TestExecutorSchema { + 'project-dir': string; +} diff --git a/tools/nx-wasm-bindgen/src/executors/test/schema.json b/tools/nx-wasm-bindgen/src/executors/test/schema.json new file mode 100644 index 0000000..b54a6b9 --- /dev/null +++ b/tools/nx-wasm-bindgen/src/executors/test/schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/schema", + "version": 2, + "title": "Test executor", + "description": "", + "type": "object", + "properties": { + "project-dir": { + "type": "string", + "description": "Directory of project" + } + }, + "required": ["project-dir"] +} diff --git a/tools/nx-wasm-pack/tsconfig.json b/tools/nx-wasm-bindgen/tsconfig.json similarity index 100% rename from tools/nx-wasm-pack/tsconfig.json rename to tools/nx-wasm-bindgen/tsconfig.json diff --git a/tools/nx-wasm-pack/tsconfig.lib.json b/tools/nx-wasm-bindgen/tsconfig.lib.json similarity index 100% rename from tools/nx-wasm-pack/tsconfig.lib.json rename to tools/nx-wasm-bindgen/tsconfig.lib.json diff --git a/tools/nx-wasm-pack/tsconfig.spec.json b/tools/nx-wasm-bindgen/tsconfig.spec.json similarity index 100% rename from tools/nx-wasm-pack/tsconfig.spec.json rename to tools/nx-wasm-bindgen/tsconfig.spec.json diff --git a/tools/nx-wasm-pack/vite.config.ts b/tools/nx-wasm-bindgen/vite.config.ts similarity index 59% rename from tools/nx-wasm-pack/vite.config.ts rename to tools/nx-wasm-bindgen/vite.config.ts index c4fd257..057efdd 100644 --- a/tools/nx-wasm-pack/vite.config.ts +++ b/tools/nx-wasm-bindgen/vite.config.ts @@ -1,13 +1,17 @@ -import { defineConfig } from 'vite'; +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ +import { defineConfig } from 'vite'; export default defineConfig(() => ({ root: __dirname, - cacheDir: '../../node_modules/.vite/tools/nx-wasm-pack', + cacheDir: '../../node_modules/.vite/tools/nx-wasm-bindgen', plugins: [], - // Uncomment this if you are using workers. - // worker: { - // plugins: [ nxViteTsPaths() ], - // }, test: { watch: false, globals: true, diff --git a/tools/nx-wasm-pack/README.md b/tools/nx-wasm-pack/README.md deleted file mode 100644 index a2ba96d..0000000 --- a/tools/nx-wasm-pack/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# nx-wasm-pack - -This library was generated with [Nx](https://nx.dev). - -## Building - -Run `nx build nx-wasm-pack` to build the library. - -## Running unit tests - -Run `nx test nx-wasm-pack` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/tools/nx-wasm-pack/executors.json b/tools/nx-wasm-pack/executors.json deleted file mode 100644 index 776f365..0000000 --- a/tools/nx-wasm-pack/executors.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "executors": { - "build": { - "implementation": "./src/executors/build/executor", - "schema": "./src/executors/build/schema.json", - "description": "Build a project with wasm-pack" - } - } -} diff --git a/tools/nx-wasm-pack/src/executors/build/executor.spec.ts b/tools/nx-wasm-pack/src/executors/build/executor.spec.ts deleted file mode 100644 index 2c83939..0000000 --- a/tools/nx-wasm-pack/src/executors/build/executor.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ExecutorContext } from '@nx/devkit'; - -import { BuildExecutorSchema } from './schema'; -import executor from './executor'; - -const options: BuildExecutorSchema = { - "project-dir": '.', -}; -const context: ExecutorContext = { - root: '', - cwd: process.cwd(), - isVerbose: false, - projectGraph: { - nodes: {}, - dependencies: {}, - }, - projectsConfigurations: { - projects: {}, - version: 2, - }, - nxJsonConfiguration: {}, -}; - -describe('Build Executor', () => { - it('can run', async () => { - const output = await executor(options, context); - expect(output.success).toBe(true); - }); -}); diff --git a/tools/nx-wasm-pack/src/executors/build/executor.ts b/tools/nx-wasm-pack/src/executors/build/executor.ts deleted file mode 100644 index 1f871d8..0000000 --- a/tools/nx-wasm-pack/src/executors/build/executor.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { execSync } from 'node:child_process'; -import { PromiseExecutor } from '@nx/devkit'; -import { BuildExecutorSchema } from './schema'; -import { join } from 'path'; - -const runExecutor: PromiseExecutor = async (options, context) => { - console.log('Executor ran for Build', options); - - const projectPath = join(context.root, options['project-dir']) - - try { - execSync('wasm-pack build --release --target web --scope contentauth', { cwd: projectPath }) - - return { - success: true - } - } catch (error) { - console.error('Error building release:', error); - - return { - success: false, - }; - } -}; - -export default runExecutor; \ No newline at end of file diff --git a/tools/nx-wasm-pack/src/executors/build/schema.d.ts b/tools/nx-wasm-pack/src/executors/build/schema.d.ts deleted file mode 100644 index f6b378c..0000000 --- a/tools/nx-wasm-pack/src/executors/build/schema.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface BuildExecutorSchema { - 'project-dir': string; - profile?: 'dev' | 'profiling' | 'release'; -} diff --git a/tools/nx-wasm-pack/src/index.ts b/tools/nx-wasm-pack/src/index.ts deleted file mode 100644 index e69de29..0000000 diff --git a/tools/testbed/eslint.config.mjs b/tools/testbed/eslint.config.mjs new file mode 100644 index 0000000..a0edfe9 --- /dev/null +++ b/tools/testbed/eslint.config.mjs @@ -0,0 +1,12 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import baseConfig from '../../eslint.config.mjs'; + +export default [...baseConfig]; diff --git a/tools/testbed/index.html b/tools/testbed/index.html new file mode 100644 index 0000000..2a46690 --- /dev/null +++ b/tools/testbed/index.html @@ -0,0 +1,21 @@ + + + + + Testbed + + + + + + + + +
+
+ Drop an image + Results are in the browser console +
+
+ + diff --git a/tools/testbed/package.json b/tools/testbed/package.json new file mode 100644 index 0000000..a3ed858 --- /dev/null +++ b/tools/testbed/package.json @@ -0,0 +1,10 @@ +{ + "name": "testbed", + "version": "0.0.1", + "private": true, + "type": "module", + "dependencies": { + "@contentauth/c2pa-web": "workspace:*", + "@contentauth/c2pa-wasm": "workspace:*" + } +} diff --git a/tools/testbed/public/favicon.ico b/tools/testbed/public/favicon.ico new file mode 100644 index 0000000..317ebcb Binary files /dev/null and b/tools/testbed/public/favicon.ico differ diff --git a/tools/testbed/src/main.ts b/tools/testbed/src/main.ts new file mode 100644 index 0000000..5f3192b --- /dev/null +++ b/tools/testbed/src/main.ts @@ -0,0 +1,60 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { createC2pa } from '@contentauth/c2pa-web'; +import wasmSrc from '@contentauth/c2pa-wasm/assets/c2pa_bg.wasm?url'; + +const c2pa = await createC2pa({ wasmSrc }); + +const dropzone = document.getElementById('drop-zone'); + +dropzone?.addEventListener('dragenter', () => { + dropzone.classList.add('active'); +}); + +dropzone?.addEventListener('dragleave', () => { + dropzone.classList.remove('active'); +}); + +dropzone?.addEventListener('dragover', (e) => { + e.preventDefault(); +}); + +dropzone?.addEventListener('drop', (e) => { + dropzone.classList.remove('active'); + + if (e.dataTransfer?.items) { + [...e.dataTransfer.items].forEach(async (item) => { + if (item.kind === 'file') { + const file = item.getAsFile(); + + if (!file) { + throw new Error('Could not get item as file'); + } + + try { + const start = performance.now(); + + const reader = await c2pa.reader.fromBlob(file.type, file); + const manifestStore = await reader.manifestStore(); + + const end = performance.now(); + + console.log(manifestStore); + console.log(`Took ${Math.round(end - start)}ms`); + + await reader.free(); + } catch (e) { + console.log('caught error', e); + } + } + }); + } + e.preventDefault(); +}); diff --git a/tools/testbed/src/styles.css b/tools/testbed/src/styles.css new file mode 100644 index 0000000..44284e6 --- /dev/null +++ b/tools/testbed/src/styles.css @@ -0,0 +1,41 @@ +body { + margin: 0; + font-family: sans-serif; +} + +.wrapper { + height: 100vh; + padding: 20px; + box-sizing: border-box; +} + +#drop-zone { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + width: 100%; + background-color: #f8f8f8; + height:100%; + border-width: 4px; + border-style: dashed; + border-color: #b1b1b1; + border-radius: 20px; +} + +#drop-zone.active { + border-style: solid; + background-color: #e6e6e6; + border-color: #909090; +} + +.title { + font-size: 28px; + color: #222222; +} + +.subtitle { + padding-top: 4px; + color: #464646; + /* font-size: 16px; */ +} \ No newline at end of file diff --git a/tools/testbed/tsconfig.app.json b/tools/testbed/tsconfig.app.json new file mode 100644 index 0000000..48a15c7 --- /dev/null +++ b/tools/testbed/tsconfig.app.json @@ -0,0 +1,25 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "rootDir": "src", + "types": ["node", "vite/client"], + "tsBuildInfoFile": "dist/tsconfig.app.tsbuildinfo" + }, + "exclude": [ + "out-tsc", + "dist", + "src/**/*.spec.ts", + "src/**/*.test.ts", + "eslint.config.js", + "eslint.config.cjs", + "eslint.config.mjs" + ], + "include": ["src/**/*.ts"], + "references": [ + { + "path": "../../packages/c2pa-web/tsconfig.lib.json" + } + ] +} diff --git a/tools/testbed/tsconfig.json b/tools/testbed/tsconfig.json new file mode 100644 index 0000000..2cc0dee --- /dev/null +++ b/tools/testbed/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "../../packages/c2pa-web" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/tools/testbed/vite.config.ts b/tools/testbed/vite.config.ts new file mode 100644 index 0000000..a92e40d --- /dev/null +++ b/tools/testbed/vite.config.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import { defineConfig } from 'vite'; + +export default defineConfig(() => ({ + root: __dirname, + cacheDir: '../../node_modules/.vite/tools/testbed', + server: { + port: 4200, + host: 'localhost', + }, + preview: { + port: 4300, + host: 'localhost', + }, + plugins: [], + build: { + outDir: './dist', + emptyOutDir: true, + reportCompressedSize: true, + target: 'esnext', + commonjsOptions: { + transformMixedEsModules: true, + }, + }, +})); diff --git a/tsconfig.base.json b/tsconfig.base.json index 8084832..c847389 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -5,7 +5,7 @@ "emitDeclarationOnly": true, "importHelpers": true, "isolatedModules": true, - "lib": ["es2022"], + "lib": ["ES2023"], "module": "nodenext", "moduleResolution": "nodenext", "noEmitOnError": true, @@ -15,7 +15,7 @@ "noUnusedLocals": true, "skipLibCheck": true, "strict": true, - "target": "es2022", + "target": "ES2023", "customConditions": ["development"] } } diff --git a/tsconfig.json b/tsconfig.json index 76289be..8e99e17 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,10 +4,13 @@ "files": [], "references": [ { - "path": "./packages/browser" + "path": "./tools/nx-wasm-bindgen" }, { - "path": "./tools/nx-wasm-pack" + "path": "./tools/testbed" + }, + { + "path": "./packages/c2pa-web" } ] } diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 883c608..571d1e3 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -1,3 +1,12 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + export default [ '**/vite.config.{mjs,js,ts,mts}', '**/vitest.config.{mjs,js,ts,mts}',