chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"bb4b208d21ba2d17b8633caf9f9e4f9bf2ff6eb9abb9032ef4e8e17051fdb732","Cargo.lock":"86a0a3386510e03ee5484c6324bc691e8901845f1cd4f5647eda7a3db4791e1f","Cargo.toml":"6664f62d0bc39281f4cf2f00e06cd411b58fcd72e7322c03717826cbfaf1c5ac","Cargo.toml.orig":"e3db027d4f122862fae26b3784f482deeebf6796371b046d6130708e08dae36f","README.md":"13ad7caf9d57e5a3d011191deaf7546873e416e22cb1b065dd93158e9e9c4fa3","src/add_metadata.rs":"1f57919c702a1bcc51dfb0e004e90a29c24c34bb116419a8f4ae2bdf03103c2f","src/clap.rs":"77a90ff37ec630449d01cd9737d548b5e535477c013c7009afa0afdd54fd3e37","src/dependencies.rs":"0c782112c81e75ad60ece0c6ee1e9e857895ad6e03bf4025443e78fd7e22b128","src/lib.rs":"f239fa9868ffad85b111a692e073992afe5120b0c7711901068d8d7f25c944bc","src/metadata.rs":"4f29110aad8e9806b0a0bfa8af69910d5595b5a0ad88151ea88b9c9f7207d114","src/names/component.rs":"cfb11264b992a7521e7dfc8d2100638ce73f81e52fdbdd03d47951a0c84aa8ea","src/names/mod.rs":"1a382017f050e7c69e30e221642a651734f4c62d4cf558b9aea0a41c4baf45c3","src/names/module.rs":"fbedb1b19536436beafba99bee411326fe1ecf990eab839d923e8aa6f772df2c","src/oci_annotations/authors.rs":"241d116ecc7ec20e3c67cb8e9edb00ef98feab4af4a87f4f00b1f21bc3e8d1f2","src/oci_annotations/description.rs":"0823d64f48a16d306427409860d599e005a2132733d4d1448fd8b7dee8db7930","src/oci_annotations/homepage.rs":"306858e24ec2737f202ea10f0fc7b2e6f52c5aecda6a40690e50164aea8eb849","src/oci_annotations/licenses.rs":"2c8aca896e6e398329499ccb47c43947ab89e6cd4bd6a2739fad80118df45881","src/oci_annotations/mod.rs":"63c113ee81f3699de0c1b8e711105ae5cdbf0c2a768ef2c13f00db9a7ad9c97e","src/oci_annotations/revision.rs":"7c682a86df16d9350fdd066d1d1d946ded735616363fbb75790a45c919cece0d","src/oci_annotations/source.rs":"0a9594a1958ab0d7e1f247fb5f69790e3901291bf88906c1fcf3c1ca7c7d95c3","src/oci_annotations/version.rs":"61e2ac4bdc88022b9e37a78188e5bd4e926e8d5f4c5e24615f5abcdb6c1b4ef1","src/payload.rs":"98d833abcb42dd4128a5821a3e87afce24d86fd3f7292ec5b93a9ce914260f10","src/producers.rs":"648b9966528fb5200589290ac4cf539588f9c20e904944be014e9a7525228e47","src/rewrite.rs":"734a193c686f5095ce01f08ffbbe3e2b84ddcc4feb51480ae4ebb5cdab4dd145","src/utils.rs":"f9ab51676c27125ee65202bb373b48fa4b9176f09aeeb0d1a320f7eb73f6781c","tests/component.rs":"e799d95305a9b0cfcf1b50ff3392c319648cba67c1f304db945d8d5361ef4321","tests/module.rs":"d03ec86363514f0a29d008bff40a29f4d8a1c171a8601aed6e733250694c56fd"},"package":"bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"}

View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "d4e317f22c3bace76cb3205003bcc34b4929037d"
},
"path_in_vcs": "crates/wasm-metadata"
}

769
vendor/wasm-metadata/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,769 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "anstream"
version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "auditable-serde"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5"
dependencies = [
"semver",
"serde",
"serde_json",
"topological-sort",
]
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "cfg-if"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "clap"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[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 = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[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 = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [
"foldhash",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "icu_collections"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
dependencies = [
"displaydoc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
[[package]]
name = "icu_properties"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
dependencies = [
"icu_normalizer",
"icu_properties",
]
[[package]]
name = "indexmap"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
"hashbrown",
"serde",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "leb128fmt"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "litemap"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[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 = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "semver"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.222"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aab69e3f5be1836a1fe0aca0b286e5a5b38f262d6c9e8acd2247818751fcc8fb"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.222"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f8ebec5eea07db7df9342aa712db2138f019d9ab3454a60a680579a6f841b80"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.222"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5f61630fe26d0ff555e6c37dc445ab2f15871c8a11ace3cf471b3195d3e4f49"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "spdx"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58b69356da67e2fc1f542c71ea7e654a361a79c938e4424392ecf4fa065d2193"
dependencies = [
"smallvec",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[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 = "synstructure"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinystr"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [
"displaydoc",
"zerovec",
]
[[package]]
name = "topological-sort"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[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 = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasm-encoder"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
dependencies = [
"leb128fmt",
"wasmparser",
]
[[package]]
name = "wasm-metadata"
version = "0.244.0"
dependencies = [
"anyhow",
"auditable-serde",
"clap",
"flate2",
"indexmap",
"serde",
"serde_derive",
"serde_json",
"spdx",
"url",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags",
"hashbrown",
"indexmap",
"semver",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[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_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[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_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[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_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "yoke"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zerofrom"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zerovec"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

152
vendor/wasm-metadata/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,152 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.81.0"
name = "wasm-metadata"
version = "0.244.0"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Read and manipulate WebAssembly metadata"
readme = "README.md"
license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT"
repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-metadata"
[features]
default = [
"oci",
"serde",
]
oci = [
"dep:auditable-serde",
"dep:flate2",
"dep:url",
"dep:spdx",
"dep:serde_json",
"serde",
]
serde = [
"dep:serde_derive",
"dep:serde",
]
[lib]
name = "wasm_metadata"
path = "src/lib.rs"
[[test]]
name = "component"
path = "tests/component.rs"
[[test]]
name = "module"
path = "tests/module.rs"
[dependencies.anyhow]
version = "1.0.58"
[dependencies.auditable-serde]
version = "0.8.0"
optional = true
[dependencies.clap]
version = "4.0.0"
features = ["derive"]
optional = true
[dependencies.flate2]
version = "1.1.0"
optional = true
[dependencies.indexmap]
version = "2.7.0"
features = ["serde"]
default-features = false
[dependencies.serde]
version = "1.0.166"
features = ["alloc"]
optional = true
default-features = false
[dependencies.serde_derive]
version = "1.0.166"
optional = true
[dependencies.serde_json]
version = "1"
optional = true
[dependencies.spdx]
version = "0.10.1"
optional = true
[dependencies.url]
version = "2.0.0"
optional = true
[dependencies.wasm-encoder]
version = "0.244.0"
features = [
"std",
"component-model",
]
default-features = false
[dependencies.wasmparser]
version = "0.244.0"
features = [
"simd",
"std",
"component-model",
"hash-collections",
]
default-features = false
[lints.clippy]
clone_on_copy = "warn"
manual_strip = "warn"
map_clone = "warn"
uninlined_format_args = "warn"
unnecessary_cast = "warn"
unnecessary_fallible_conversions = "warn"
unnecessary_mut_passed = "warn"
unnecessary_to_owned = "warn"
[lints.clippy.all]
level = "allow"
priority = -1
[lints.rust]
deprecated-safe-2024 = "warn"
keyword_idents_2024 = "warn"
missing-unsafe-on-extern = "warn"
rust-2024-guarded-string-incompatible-syntax = "warn"
rust-2024-incompatible-pat = "warn"
rust-2024-prelude-collisions = "warn"
unsafe-attr-outside-unsafe = "warn"
unsafe-op-in-unsafe-fn = "warn"
unsafe_code = "deny"
unstable_features = "warn"
unused-lifetimes = "warn"
unused-macro-rules = "warn"
unused_extern_crates = "warn"
unused_import_braces = "warn"
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ["cfg(fuzzing)"]

27
vendor/wasm-metadata/README.md vendored Normal file
View File

@@ -0,0 +1,27 @@
<div align="center">
<h1><code>wasm-metadata</code></h1>
<strong>A <a href="https://bytecodealliance.org/">Bytecode Alliance</a> project</strong>
<p><strong>Read and manipulate WebAssembly metadata.</strong></p>
<p>
<a href="https://crates.io/crates/wasm-metadata"><img src="https://img.shields.io/crates/v/wasm-metadata.svg?style=flat-square" alt="Crates.io version" /></a>
<a href="https://crates.io/crates/wasm-metadata"><img src="https://img.shields.io/crates/d/wasm-metadata.svg?style=flat-square" alt="Download" /></a>
<a href="https://docs.rs/wasm-metadata/"><img src="https://img.shields.io/static/v1?label=docs&message=wasm-metadata&color=blue&style=flat-square" alt="docs.rs docs" /></a>
</p>
</div>
## Installation
```sh
$ cargo add wasm-metadata
```
# License
This project is licensed under the Apache 2.0 license with the LLVM exception.
See [LICENSE](LICENSE) for more details.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be licensed as above, without any additional terms or conditions.

View File

@@ -0,0 +1,91 @@
use crate::{Producers, rewrite_wasm};
use anyhow::Result;
use std::fmt::Debug;
/// Add metadata (module name, producers) to a WebAssembly file.
///
/// Supports both core WebAssembly modules and components. In components,
/// metadata will be added to the outermost component.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct AddMetadata {
/// Add a module or component name to the names section
pub name: AddMetadataField<String>,
/// Add a programming language to the producers section
pub language: Vec<(String, String)>,
/// Add a tool and its version to the producers section
pub processed_by: Vec<(String, String)>,
/// Add an SDK and its version to the producers section
pub sdk: Vec<(String, String)>,
/// Contact details of the people or organization responsible,
/// encoded as a freeform string.
#[cfg(feature = "oci")]
pub authors: AddMetadataField<crate::Authors>,
/// A human-readable description of the binary
#[cfg(feature = "oci")]
pub description: AddMetadataField<crate::Description>,
/// License(s) under which contained software is distributed as an SPDX License Expression.
#[cfg(feature = "oci")]
pub licenses: AddMetadataField<crate::Licenses>,
/// URL to get source code for building the image
#[cfg(feature = "oci")]
pub source: AddMetadataField<crate::Source>,
/// URL to find more information on the binary
#[cfg(feature = "oci")]
pub homepage: AddMetadataField<crate::Homepage>,
/// Source control revision identifier for the packaged software.
#[cfg(feature = "oci")]
pub revision: AddMetadataField<crate::Revision>,
/// Version of the packaged software
#[cfg(feature = "oci")]
pub version: AddMetadataField<crate::Version>,
}
impl AddMetadata {
/// Process a WebAssembly binary. Supports both core WebAssembly modules, and WebAssembly
/// components. The module and component will have, at very least, an empty name and producers
/// section created.
pub fn to_wasm(&self, input: &[u8]) -> Result<Vec<u8>> {
let add_producers = Producers::from_meta(self);
rewrite_wasm(self, &add_producers, input)
}
}
/// Defines how to modify a field of the component/module metadata
#[derive(Debug, Clone)]
pub enum AddMetadataField<T: Debug + Clone> {
/// Keep the existing value of the field
Keep,
/// Remove the existing value of the field
Clear,
/// Set the field to a new value
Set(T),
}
impl<T: Debug + Clone> AddMetadataField<T> {
/// Returns true if the field should be cleared
pub fn is_clear(&self) -> bool {
matches!(self, Self::Clear)
}
/// Returns true if the field should be kept
pub fn is_keep(&self) -> bool {
matches!(self, Self::Keep)
}
}
impl<T: Debug + Clone> Default for AddMetadataField<T> {
fn default() -> Self {
Self::Keep
}
}

169
vendor/wasm-metadata/src/clap.rs vendored Normal file
View File

@@ -0,0 +1,169 @@
use crate::AddMetadata;
use std::fmt::Debug;
/// Add metadata (module name, producers) to a WebAssembly file.
///
/// Supports both core WebAssembly modules and components. In components,
/// metadata will be added to the outermost component.
#[derive(clap::Parser, Debug, Clone, Default)]
#[non_exhaustive]
pub struct AddMetadataOpts {
/// Add a module or component name to the names section
#[clap(long, value_name = "NAME", conflicts_with = "clear_name")]
pub name: Option<String>,
/// Remove a module or component name from the names section
#[clap(long, conflicts_with = "name")]
pub clear_name: bool,
/// Add a programming language to the producers section
#[clap(long, value_parser = parse_key_value, value_name = "NAME=VERSION")]
pub language: Vec<(String, String)>,
/// Add a tool and its version to the producers section
#[clap(long = "processed-by", value_parser = parse_key_value, value_name="NAME=VERSION")]
pub processed_by: Vec<(String, String)>,
/// Add an SDK and its version to the producers section
#[clap(long, value_parser = parse_key_value, value_name="NAME=VERSION")]
pub sdk: Vec<(String, String)>,
/// Contact details of the people or organization responsible,
/// encoded as a freeform string.
#[clap(long, value_name = "NAME", conflicts_with = "clear_authors")]
#[cfg(feature = "oci")]
pub authors: Option<crate::Authors>,
/// Remove authors from the metadata
#[clap(long, conflicts_with = "authors")]
#[cfg(feature = "oci")]
pub clear_authors: bool,
/// A human-readable description of the binary
#[clap(long, value_name = "NAME", conflicts_with = "clear_description")]
#[cfg(feature = "oci")]
pub description: Option<crate::Description>,
/// Remove description from the metadata
#[clap(long, conflicts_with = "description")]
#[cfg(feature = "oci")]
pub clear_description: bool,
/// License(s) under which contained software is distributed as an SPDX License Expression.
#[clap(long, value_name = "NAME", conflicts_with = "clear_licenses")]
#[cfg(feature = "oci")]
pub licenses: Option<crate::Licenses>,
/// Remove licenses from the metadata
#[clap(long, conflicts_with = "licenses")]
#[cfg(feature = "oci")]
pub clear_licenses: bool,
/// URL to get source code for building the image
#[clap(long, value_name = "NAME", conflicts_with = "clear_source")]
#[cfg(feature = "oci")]
pub source: Option<crate::Source>,
/// Remove source from the metadata
#[clap(long, conflicts_with = "source")]
#[cfg(feature = "oci")]
pub clear_source: bool,
/// URL to find more information on the binary
#[clap(long, value_name = "NAME", conflicts_with = "clear_homepage")]
#[cfg(feature = "oci")]
pub homepage: Option<crate::Homepage>,
/// Remove homepage from the metadata
#[clap(long, conflicts_with = "homepage")]
#[cfg(feature = "oci")]
pub clear_homepage: bool,
/// Source control revision identifier for the packaged software.
#[clap(long, value_name = "NAME", conflicts_with = "clear_revision")]
#[cfg(feature = "oci")]
pub revision: Option<crate::Revision>,
/// Remove revision from the metadata
#[clap(long, conflicts_with = "revision")]
#[cfg(feature = "oci")]
pub clear_revision: bool,
/// Version of the packaged software
#[clap(long, value_name = "NAME", conflicts_with = "clear_version")]
#[cfg(feature = "oci")]
pub version: Option<crate::Version>,
/// Remove version from the metadata
#[clap(long, conflicts_with = "version")]
#[cfg(feature = "oci")]
pub clear_version: bool,
}
pub(crate) fn parse_key_value(s: &str) -> anyhow::Result<(String, String)> {
s.split_once('=')
.map(|(k, v)| (k.to_owned(), v.to_owned()))
.ok_or_else(|| anyhow::anyhow!("expected KEY=VALUE"))
}
impl From<AddMetadataOpts> for AddMetadata {
fn from(value: AddMetadataOpts) -> Self {
let mut add = AddMetadata::default();
if let Some(name) = value.name {
add.name = crate::AddMetadataField::Set(name);
} else if value.clear_name {
add.name = crate::AddMetadataField::Clear;
}
add.language = value.language;
add.processed_by = value.processed_by;
add.sdk = value.sdk;
#[cfg(feature = "oci")]
{
if let Some(authors) = value.authors {
add.authors = crate::AddMetadataField::Set(authors);
} else if value.clear_authors {
add.authors = crate::AddMetadataField::Clear;
}
if let Some(description) = value.description {
add.description = crate::AddMetadataField::Set(description);
} else if value.clear_description {
add.description = crate::AddMetadataField::Clear;
}
if let Some(licenses) = value.licenses {
add.licenses = crate::AddMetadataField::Set(licenses);
} else if value.clear_licenses {
add.licenses = crate::AddMetadataField::Clear;
}
if let Some(source) = value.source {
add.source = crate::AddMetadataField::Set(source);
} else if value.clear_source {
add.source = crate::AddMetadataField::Clear;
}
if let Some(homepage) = value.homepage {
add.homepage = crate::AddMetadataField::Set(homepage);
} else if value.clear_homepage {
add.homepage = crate::AddMetadataField::Clear;
}
if let Some(revision) = value.revision {
add.revision = crate::AddMetadataField::Set(revision);
} else if value.clear_revision {
add.revision = crate::AddMetadataField::Clear;
}
if let Some(version) = value.version {
add.version = crate::AddMetadataField::Set(version);
} else if value.clear_version {
add.version = crate::AddMetadataField::Clear;
}
}
add
}
}

142
vendor/wasm-metadata/src/dependencies.rs vendored Normal file
View File

@@ -0,0 +1,142 @@
use std::fmt::{self, Display};
use std::io::{Read, read_to_string};
use std::str::FromStr;
use anyhow::{Result, ensure};
use auditable_serde::VersionInfo;
use flate2::Compression;
use flate2::read::{ZlibDecoder, ZlibEncoder};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// Human-readable description of the binary
#[derive(Debug, Clone, PartialEq)]
pub struct Dependencies {
version_info: VersionInfo,
custom_section: CustomSection<'static>,
}
impl Dependencies {
/// Parse an `description` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == ".dep-v0",
"The `dependencies` custom section should have a name of '.dep-v0'"
);
let decompressed_data = read_to_string(ZlibDecoder::new(reader.data()))?;
let dependency_tree = auditable_serde::VersionInfo::from_str(&decompressed_data)?;
Ok(Self {
version_info: dependency_tree,
custom_section: CustomSection {
name: ".dep-v0".into(),
data: reader.data().to_owned().into(),
},
})
}
/// Create a new instance of `Dependencies`.
pub fn new(dependency_tree: auditable_serde::VersionInfo) -> Self {
let data = serde_json::to_string(&dependency_tree).unwrap();
let mut ret_vec = Vec::new();
let mut encoder = ZlibEncoder::new(data.as_bytes(), Compression::fast());
encoder.read_to_end(&mut ret_vec).unwrap();
Self {
version_info: dependency_tree,
custom_section: CustomSection {
name: ".dep-v0".into(),
data: ret_vec.into(),
},
}
}
/// Provides access to the version information stored in the object
pub fn version_info(&self) -> &VersionInfo {
&self.version_info
}
}
impl Serialize for Dependencies {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Dependencies {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
// let data = String::from_utf8(self.0.data.to_vec()).unwrap();
let data = serde_json::to_string(&self.version_info).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Dependencies {
fn id(&self) -> u8 {
ComponentSection::id(&self.custom_section)
}
}
impl Section for Dependencies {
fn id(&self) -> u8 {
Section::id(&self.custom_section)
}
}
impl Encode for Dependencies {
fn encode(&self, sink: &mut Vec<u8>) {
self.custom_section.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use auditable_serde::{Source, VersionInfo};
use std::str::FromStr;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let json_str = r#"{"packages":[{"name":"adler","version":"0.2.3","source":"registry"}]}"#;
let info = VersionInfo::from_str(json_str).unwrap();
assert_eq!(&info.packages[0].name, "adler");
let mut component = Component::new();
component.section(&Dependencies::new(info));
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let dependencies = Dependencies::parse_custom_section(&reader).unwrap();
assert_eq!(dependencies.to_string(), json_str);
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let json_str = r#"{"packages":[{"name":"adler","version":"0.2.3","source":"registry"}]}"#;
let info = VersionInfo::from_str(json_str).unwrap();
let dependencies = Dependencies::new(info);
assert_eq!(dependencies.version_info().packages[0].name, "adler");
assert_eq!(
dependencies.version_info().packages[0].version.to_string(),
"0.2.3"
);
assert_eq!(
dependencies.version_info().packages[0].source,
Source::Registry,
);
}
}

83
vendor/wasm-metadata/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,83 @@
//! Read and manipulate WebAssembly metadata
//!
//! # Examples
//!
//! **Read metadata from a Wasm binary**
//!
//! ```no_run
//! # #![allow(unused)]
//! # fn main() -> Result<(), anyhow::Error> {
//! use wasm_metadata::Payload;
//! use std::fs;
//!
//! let wasm = fs::read("program.wasm")?;
//! let metadata = Payload::from_binary(&wasm)?.metadata();
//! # Ok(()) }
//! ```
//!
//! **Add metadata to a Wasm binary**
//!
//! ```no_run
//! # #![allow(unused)]
//! # fn main() -> Result<(), anyhow::Error> {
//! use wasm_metadata::*;
//! use std::fs;
//!
//! let wasm = fs::read("program.wasm")?;
//!
//! let mut add = AddMetadata ::default();
//! add.name = AddMetadataField::Set("program".to_owned());
//! add.language = vec![("tunalang".to_owned(), "1.0.0".to_owned())];
//! add.processed_by = vec![("chashu-tools".to_owned(), "1.0.1".to_owned())];
//! add.sdk = vec![];
//! add.authors = AddMetadataField::Set(Authors::new("Chashu Cat"));
//! add.description = AddMetadataField::Set(Description::new("Chashu likes tuna"));
//! add.licenses = AddMetadataField::Set(Licenses::new("Apache-2.0 WITH LLVM-exception")?);
//! add.source = AddMetadataField::Set(Source::new("https://github.com/chashu/chashu-tools")?);
//! add.homepage = AddMetadataField::Set(Homepage::new("https://github.com/chashu/chashu-tools")?);
//! add.revision = AddMetadataField::Set(Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
//! add.version = AddMetadataField::Set(Version::new("1.0.0"));
//!
//! let wasm = add.to_wasm(&wasm)?;
//! fs::write("program.wasm", &wasm)?;
//! # Ok(()) }
//! ```
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(missing_debug_implementations, missing_docs)]
pub use add_metadata::{AddMetadata, AddMetadataField};
pub use names::{ComponentNames, ModuleNames};
pub use producers::{Producers, ProducersField};
pub(crate) use rewrite::rewrite_wasm;
mod add_metadata;
#[cfg(feature = "clap")]
mod clap;
mod names;
mod producers;
mod rewrite;
pub(crate) mod utils;
#[cfg(feature = "oci")]
mod dependencies;
#[cfg(feature = "oci")]
pub use dependencies::Dependencies;
#[cfg(feature = "oci")]
mod oci_annotations;
#[cfg(feature = "oci")]
pub use oci_annotations::{Authors, Description, Homepage, Licenses, Revision, Source, Version};
#[cfg(feature = "oci")]
mod metadata;
#[cfg(feature = "oci")]
pub use metadata::Metadata;
#[cfg(feature = "oci")]
mod payload;
#[cfg(feature = "oci")]
pub use payload::Payload;
#[cfg(feature = "clap")]
pub use clap::AddMetadataOpts;

34
vendor/wasm-metadata/src/metadata.rs vendored Normal file
View File

@@ -0,0 +1,34 @@
use serde_derive::Serialize;
use std::ops::Range;
use crate::{
Authors, Dependencies, Description, Homepage, Licenses, Producers, Revision, Source, Version,
};
/// Metadata associated with a Wasm Component or Module
#[derive(Debug, Serialize, Default)]
#[serde(rename_all = "lowercase")]
pub struct Metadata {
/// The component name, if any. Found in the component-name section.
pub name: Option<String>,
/// The component's producers section, if any.
pub producers: Option<Producers>,
/// The component's authors section, if any.
pub authors: Option<Authors>,
/// Human-readable description of the binary
pub description: Option<Description>,
/// License(s) under which contained software is distributed as an SPDX License Expression.
pub licenses: Option<Licenses>,
/// URL to get source code for building the image
pub source: Option<Source>,
/// URL to find more information on the binary
pub homepage: Option<Homepage>,
/// Source control revision identifier for the packaged software.
pub revision: Option<Revision>,
/// Version of the packaged software
pub version: Option<Version>,
/// Byte range of the module in the parent binary
pub range: Range<usize>,
/// Dependencies of the component
pub dependencies: Option<Dependencies>,
}

View File

@@ -0,0 +1,107 @@
use std::fmt::{self, Debug};
use anyhow::Result;
use wasm_encoder::Encode;
use wasmparser::{BinaryReader, ComponentNameSectionReader};
use crate::utils::name_map;
/// Helper for rewriting a component's component-name section with a new component name.
pub struct ComponentNames<'a> {
component_name: Option<String>,
names: Vec<wasmparser::ComponentName<'a>>,
}
impl<'a> Debug for ComponentNames<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ComponentNames")
.field("component_name", &self.component_name)
.finish_non_exhaustive()
}
}
impl<'a> ComponentNames<'a> {
/// Create an empty component-name section.
pub fn empty() -> Self {
ComponentNames {
component_name: None,
names: Vec::new(),
}
}
/// Read a component-name section from a WebAssembly binary. Records the component name, as
/// well as all other component name fields for later serialization.
pub fn from_bytes(bytes: &'a [u8], offset: usize) -> Result<ComponentNames<'a>> {
let reader = BinaryReader::new(bytes, offset);
let section = ComponentNameSectionReader::new(reader);
let mut s = Self::empty();
for name in section.into_iter() {
let name = name?;
match name {
wasmparser::ComponentName::Component { name, .. } => {
s.component_name = Some(name.to_owned())
}
_ => s.names.push(name),
}
}
Ok(s)
}
/// Set component name according to [`AddMetadata`]
pub(crate) fn from_name(name: &Option<String>) -> Self {
let mut s = Self::empty();
s.component_name = name.clone();
s
}
/// Merge with another section
pub(crate) fn merge(&mut self, other: &Self) {
if other.component_name.is_some() {
self.component_name = other.component_name.clone();
}
self.names.extend_from_slice(&other.names);
}
/// Set component name
pub fn set_name(&mut self, name: &str) {
self.component_name = Some(name.to_owned())
}
/// Get component name
pub fn get_name(&self) -> Option<&String> {
self.component_name.as_ref()
}
/// Serialize into [`wasm_encoder::ComponentNameSection`]
pub(crate) fn section(&self) -> Result<wasm_encoder::ComponentNameSection> {
let mut section = wasm_encoder::ComponentNameSection::new();
if let Some(component_name) = &self.component_name {
section.component(&component_name);
}
for n in self.names.iter() {
match n {
wasmparser::ComponentName::Component { .. } => unreachable!(),
wasmparser::ComponentName::CoreFuncs(m) => section.core_funcs(&name_map(&m)?),
wasmparser::ComponentName::CoreGlobals(m) => section.core_globals(&name_map(&m)?),
wasmparser::ComponentName::CoreMemories(m) => section.core_memories(&name_map(&m)?),
wasmparser::ComponentName::CoreTables(m) => section.core_tables(&name_map(&m)?),
wasmparser::ComponentName::CoreTags(m) => section.core_tags(&name_map(&m)?),
wasmparser::ComponentName::CoreModules(m) => section.core_modules(&name_map(&m)?),
wasmparser::ComponentName::CoreInstances(m) => {
section.core_instances(&name_map(&m)?)
}
wasmparser::ComponentName::CoreTypes(m) => section.core_types(&name_map(&m)?),
wasmparser::ComponentName::Types(m) => section.types(&name_map(&m)?),
wasmparser::ComponentName::Instances(m) => section.instances(&name_map(&m)?),
wasmparser::ComponentName::Components(m) => section.components(&name_map(&m)?),
wasmparser::ComponentName::Funcs(m) => section.funcs(&name_map(&m)?),
wasmparser::ComponentName::Values(m) => section.values(&name_map(&m)?),
wasmparser::ComponentName::Unknown { .. } => {} // wasm-encoder doesn't support it
}
}
Ok(section)
}
/// Serialize into the raw bytes of a wasm custom section.
pub fn raw_custom_section(&self) -> Result<Vec<u8>> {
let mut ret = Vec::new();
self.section()?.encode(&mut ret);
Ok(ret)
}
}

5
vendor/wasm-metadata/src/names/mod.rs vendored Normal file
View File

@@ -0,0 +1,5 @@
mod component;
mod module;
pub use component::ComponentNames;
pub use module::ModuleNames;

101
vendor/wasm-metadata/src/names/module.rs vendored Normal file
View File

@@ -0,0 +1,101 @@
use std::fmt::{self, Debug};
use anyhow::Result;
use wasm_encoder::Encode;
use wasmparser::{BinaryReader, NameSectionReader};
use crate::utils::{indirect_name_map, name_map};
/// Helper for rewriting a module's name section with a new module name.
pub struct ModuleNames<'a> {
module_name: Option<String>,
names: Vec<wasmparser::Name<'a>>,
}
impl<'a> Debug for ModuleNames<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ModuleNames")
.field("module_name", &self.module_name)
.finish_non_exhaustive()
}
}
impl<'a> ModuleNames<'a> {
/// Create an empty name section.
pub fn empty() -> Self {
ModuleNames {
module_name: None,
names: Vec::new(),
}
}
/// Read a name section from a WebAssembly binary. Records the module name, and all other
/// contents of name section, for later serialization.
pub fn from_bytes(bytes: &'a [u8], offset: usize) -> Result<ModuleNames<'a>> {
let reader = BinaryReader::new(bytes, offset);
let section = NameSectionReader::new(reader);
let mut s = Self::empty();
for name in section.into_iter() {
let name = name?;
match name {
wasmparser::Name::Module { name, .. } => s.module_name = Some(name.to_owned()),
_ => s.names.push(name),
}
}
Ok(s)
}
/// Update module section according to [`AddMetadata`]
pub(crate) fn from_name(name: &Option<String>) -> Self {
let mut s = Self::empty();
s.module_name = name.clone();
s
}
/// Merge with another section
pub(crate) fn merge(&mut self, other: &Self) {
if other.module_name.is_some() {
self.module_name = other.module_name.clone();
}
self.names.extend_from_slice(&other.names);
}
/// Set module name
pub fn set_name(&mut self, name: &str) {
self.module_name = Some(name.to_owned())
}
/// Get module name
pub fn get_name(&self) -> Option<&String> {
self.module_name.as_ref()
}
/// Serialize into [`wasm_encoder::NameSection`].
pub(crate) fn section(&self) -> Result<wasm_encoder::NameSection> {
let mut section = wasm_encoder::NameSection::new();
if let Some(module_name) = &self.module_name {
section.module(&module_name);
}
for n in self.names.iter() {
match n {
wasmparser::Name::Module { .. } => unreachable!(),
wasmparser::Name::Function(m) => section.functions(&name_map(&m)?),
wasmparser::Name::Local(m) => section.locals(&indirect_name_map(&m)?),
wasmparser::Name::Label(m) => section.labels(&indirect_name_map(&m)?),
wasmparser::Name::Type(m) => section.types(&name_map(&m)?),
wasmparser::Name::Table(m) => section.tables(&name_map(&m)?),
wasmparser::Name::Memory(m) => section.memories(&name_map(&m)?),
wasmparser::Name::Global(m) => section.globals(&name_map(&m)?),
wasmparser::Name::Element(m) => section.elements(&name_map(&m)?),
wasmparser::Name::Data(m) => section.data(&name_map(&m)?),
wasmparser::Name::Field(m) => section.fields(&indirect_name_map(&m)?),
wasmparser::Name::Tag(m) => section.tags(&name_map(&m)?),
wasmparser::Name::Unknown { .. } => {} // wasm-encoder doesn't support it
}
}
Ok(section)
}
/// Serialize into the raw bytes of a wasm custom section.
pub fn raw_custom_section(&self) -> Result<Vec<u8>> {
let mut ret = Vec::new();
self.section()?.encode(&mut ret);
Ok(ret)
}
}

View File

@@ -0,0 +1,111 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// Contact details of the people or organization responsible,
/// encoded as a freeform string.
#[derive(Debug, Clone, PartialEq)]
pub struct Authors(CustomSection<'static>);
impl Authors {
/// Create a new instance of `Authors`.
pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
Self(CustomSection {
name: "authors".into(),
data: match s.into() {
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
Cow::Owned(s) => Cow::Owned(s.into()),
},
})
}
/// Parse an `authors` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "authors",
"The `authors` custom section should have a name of 'authors'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Ok(Self::new(data))
}
}
impl FromStr for Authors {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new(s.to_owned()))
}
}
impl Serialize for Authors {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Authors {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Authors {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Authors {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Authors {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component.section(&Authors::new("Nori Cat"));
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let authors = Authors::parse_custom_section(&reader).unwrap();
assert_eq!(authors.to_string(), "Nori Cat");
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let authors = Authors::new("Chashu Cat");
let json = serde_json::to_string(&authors).unwrap();
assert_eq!(r#""Chashu Cat""#, json);
}
}

View File

@@ -0,0 +1,110 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// Human-readable description of the binary
#[derive(Debug, Clone, PartialEq)]
pub struct Description(CustomSection<'static>);
impl Description {
/// Create a new instance of `Desrciption`.
pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
Self(CustomSection {
name: "description".into(),
data: match s.into() {
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
Cow::Owned(s) => Cow::Owned(s.into()),
},
})
}
/// Parse an `description` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "description",
"The `description` custom section should have a name of 'description'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Ok(Self::new(data))
}
}
impl FromStr for Description {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new(s.to_owned()))
}
}
impl Serialize for Description {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Description {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Description {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Description {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Description {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component.section(&Description::new("Nori likes chicken"));
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let description = Description::parse_custom_section(&reader).unwrap();
assert_eq!(description.to_string(), "Nori likes chicken");
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let description = Description::new("Chashu likes tuna");
let json = serde_json::to_string(&description).unwrap();
assert_eq!(r#""Chashu likes tuna""#, json);
}
}

View File

@@ -0,0 +1,118 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use url::Url;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// URL to find more information on the binary
#[derive(Debug, Clone, PartialEq)]
pub struct Homepage(CustomSection<'static>);
impl Homepage {
/// Create a new instance of `Homepage`.
pub fn new(s: &str) -> Result<Self> {
Ok(Url::parse(s)?.into())
}
/// Parse a `homepage` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "homepage",
"The `homepage` custom section should have a name of 'homepage'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Self::new(&data)
}
}
impl FromStr for Homepage {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::new(s)
}
}
impl From<Url> for Homepage {
fn from(expression: Url) -> Self {
Self(CustomSection {
name: "homepage".into(),
data: Cow::Owned(expression.to_string().into_bytes()),
})
}
}
impl Serialize for Homepage {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Homepage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Homepage {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Homepage {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Homepage {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component
.section(&Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap());
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let description = Homepage::parse_custom_section(&reader).unwrap();
assert_eq!(
description.to_string(),
"https://github.com/bytecodealliance/wasm-tools"
);
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let description = Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap();
let json = serde_json::to_string(&description).unwrap();
assert_eq!(r#""https://github.com/bytecodealliance/wasm-tools""#, json);
}
}

View File

@@ -0,0 +1,122 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// License(s) under which contained software is distributed as an SPDX License Expression.
#[derive(Debug, Clone, PartialEq)]
pub struct Licenses(CustomSection<'static>);
impl Licenses {
/// Create a new instance of `Licenses`.
pub fn new(s: &str) -> Result<Self> {
Ok(spdx::Expression::parse(s)?.into())
}
/// Parse a `licenses` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "licenses",
"The `licenses` custom section should have a name of 'license'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Self::new(&data)
}
}
impl FromStr for Licenses {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::new(s)
}
}
impl From<spdx::Expression> for Licenses {
fn from(expression: spdx::Expression) -> Self {
Self(CustomSection {
name: "licenses".into(),
data: Cow::Owned(expression.to_string().into_bytes()),
})
}
}
impl Serialize for Licenses {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Licenses {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Licenses {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Licenses {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Licenses {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component.section(
&Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap(),
);
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let description = Licenses::parse_custom_section(&reader).unwrap();
assert_eq!(
description.to_string(),
"Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT"
);
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let description =
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap();
let json = serde_json::to_string(&description).unwrap();
assert_eq!(
r#""Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT""#,
json
);
}
}

View File

@@ -0,0 +1,32 @@
//! Annotations following the [OCI Annotations Spec].
//!
//! The fields of these annotations are encoded into custom sections of
//! component binaries, and are explicitly compatible with the OCI Annotations
//! Spec. That enables Compontents to be encoded to OCI and back without needing
//! to perform any additional parsing. This greatly simplifies adding metadata to
//! component registries, since language-native component toolchains can encode them
//! directly into components. Which in turn can be picked up by Component-to-OCI
//! tooling to take those annotations and display them in a way that registries can
//! understand.
//!
//! For the files in this submodule that means we want to be explicitly
//! compatible with the OCI Annotations specification. Any deviation in our
//! parsing rules from the spec should be considered a bug we have to fix.
//!
//! [OCI Annotations Spec]: https://specs.opencontainers.org/image-spec/annotations/
pub use authors::Authors;
pub use description::Description;
pub use homepage::Homepage;
pub use licenses::Licenses;
pub use revision::Revision;
pub use source::Source;
pub use version::Version;
mod authors;
mod description;
mod homepage;
mod licenses;
mod revision;
mod source;
mod version;

View File

@@ -0,0 +1,113 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// Source control revision identifier for the packaged software.
#[derive(Debug, Clone, PartialEq)]
pub struct Revision(CustomSection<'static>);
impl Revision {
/// Create a new instance of `Desrciption`.
pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
Self(CustomSection {
name: "revision".into(),
data: match s.into() {
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
Cow::Owned(s) => Cow::Owned(s.into()),
},
})
}
/// Parse an `revision` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "revision",
"The `revision` custom section should have a name of 'revision'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Ok(Self::new(data))
}
}
impl FromStr for Revision {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new(s.to_owned()))
}
}
impl Serialize for Revision {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Revision {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Revision {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Revision {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Revision {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component.section(&Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let revision = Revision::parse_custom_section(&reader).unwrap();
assert_eq!(
revision.to_string(),
"de978e17a80c1118f606fce919ba9b7d5a04a5ad"
);
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let revision = Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad");
let json = serde_json::to_string(&revision).unwrap();
assert_eq!(r#""de978e17a80c1118f606fce919ba9b7d5a04a5ad""#, json);
}
}

View File

@@ -0,0 +1,117 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use url::Url;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// URL to get source code for building the image
#[derive(Debug, Clone, PartialEq)]
pub struct Source(CustomSection<'static>);
impl Source {
/// Create a new instance of `Source`.
pub fn new(s: &str) -> Result<Self> {
Ok(Url::parse(s)?.into())
}
/// Parse a `source` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "source",
"The `source` custom section should have a name of 'source'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Self::new(&data)
}
}
impl FromStr for Source {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::new(s)
}
}
impl From<Url> for Source {
fn from(expression: Url) -> Self {
Self(CustomSection {
name: "source".into(),
data: Cow::Owned(expression.to_string().into_bytes()),
})
}
}
impl Serialize for Source {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Source {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Source {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Source {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Source {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component.section(&Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap());
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let description = Source::parse_custom_section(&reader).unwrap();
assert_eq!(
description.to_string(),
"https://github.com/bytecodealliance/wasm-tools"
);
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let description = Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap();
let json = serde_json::to_string(&description).unwrap();
assert_eq!(r#""https://github.com/bytecodealliance/wasm-tools""#, json);
}
}

View File

@@ -0,0 +1,110 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;
use anyhow::{Error, Result, ensure};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;
/// Version of the packaged software
#[derive(Debug, Clone, PartialEq)]
pub struct Version(CustomSection<'static>);
impl Version {
/// Create a new instance of `Desrciption`.
pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
Self(CustomSection {
name: "version".into(),
data: match s.into() {
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
Cow::Owned(s) => Cow::Owned(s.into()),
},
})
}
/// Parse an `version` custom section from a wasm binary.
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
reader.name() == "version",
"The `version` custom section should have a name of 'version'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Ok(Self::new(data))
}
}
impl FromStr for Version {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new(s.to_owned()))
}
}
impl Serialize for Version {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}
impl ComponentSection for Version {
fn id(&self) -> u8 {
ComponentSection::id(&self.0)
}
}
impl Section for Version {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}
impl Encode for Version {
fn encode(&self, sink: &mut Vec<u8>) {
self.0.encode(sink);
}
}
#[cfg(test)]
mod test {
use super::*;
use wasm_encoder::Component;
use wasmparser::Payload;
#[test]
fn roundtrip() {
let mut component = Component::new();
component.section(&Version::new("1.0.0"));
let component = component.finish();
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let version = Version::parse_custom_section(&reader).unwrap();
assert_eq!(version.to_string(), "1.0.0");
parsed = true;
}
}
assert!(parsed);
}
#[test]
fn serialize() {
let version = Version::new("1.0.0");
let json = serde_json::to_string(&version).unwrap();
assert_eq!(r#""1.0.0""#, json);
}
}

215
vendor/wasm-metadata/src/payload.rs vendored Normal file
View File

@@ -0,0 +1,215 @@
use std::ops::Range;
use anyhow::Result;
use serde_derive::Serialize;
use wasmparser::{KnownCustom, Parser, Payload::*};
use crate::{
Authors, ComponentNames, Description, Homepage, Licenses, Metadata, ModuleNames, Producers,
Revision, Source,
};
/// Data representing either a Wasm Component or module
///
/// Each payload has additional [`Metadata`] associated with it,
/// but if it's a Component it may have also additional `Payloads` associated
/// with it.
#[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Payload {
/// A representation of a Wasm Component
Component {
/// The metadata associated with the Component
metadata: Metadata,
/// The metadata of nested Components or Modules
children: Vec<Payload>,
},
/// A representation of a Wasm Module
Module(Metadata),
}
impl Payload {
/// Parse metadata from a WebAssembly binary. Supports both core WebAssembly modules, and
/// WebAssembly components.
pub fn from_binary(input: &[u8]) -> Result<Self> {
let mut output = Vec::new();
for payload in Parser::new(0).parse_all(&input) {
match payload? {
Version { encoding, .. } => {
if output.is_empty() {
match encoding {
wasmparser::Encoding::Module => {
output.push(Self::empty_module(0..input.len()))
}
wasmparser::Encoding::Component => {
output.push(Self::empty_component(0..input.len()))
}
}
}
}
ModuleSection {
unchecked_range: range,
..
} => output.push(Self::empty_module(range)),
ComponentSection {
unchecked_range: range,
..
} => output.push(Self::empty_component(range)),
End { .. } => {
let finished = output.pop().expect("non-empty metadata stack");
if output.is_empty() {
return Ok(finished);
} else {
output.last_mut().unwrap().push_child(finished);
}
}
CustomSection(c) => match c.as_known() {
KnownCustom::Name(_) => {
let names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
if let Some(name) = names.get_name() {
output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut()
.name = Some(name.clone());
}
}
KnownCustom::ComponentName(_) => {
let names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
if let Some(name) = names.get_name() {
output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut()
.name = Some(name.clone());
}
}
KnownCustom::Producers(_) => {
let producers = Producers::from_bytes(c.data(), c.data_offset())?;
output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut()
.producers = Some(producers);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "authors" => {
let a = Authors::parse_custom_section(&c)?;
let Metadata { authors, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*authors = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "description" => {
let a = Description::parse_custom_section(&c)?;
let Metadata { description, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*description = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "licenses" => {
let a = Licenses::parse_custom_section(&c)?;
let Metadata { licenses, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*licenses = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "source" => {
let a = Source::parse_custom_section(&c)?;
let Metadata { source, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*source = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "homepage" => {
let a = Homepage::parse_custom_section(&c)?;
let Metadata { homepage, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*homepage = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "revision" => {
let a = Revision::parse_custom_section(&c)?;
let Metadata { revision, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*revision = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "version" => {
let a = crate::Version::parse_custom_section(&c)?;
let Metadata { version, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*version = Some(a);
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == ".dep-v0" => {
let a = crate::Dependencies::parse_custom_section(&c)?;
let Metadata { dependencies, .. } = output
.last_mut()
.expect("non-empty metadata stack")
.metadata_mut();
*dependencies = Some(a);
}
_ => {}
},
_ => {}
}
}
Err(anyhow::anyhow!(
"malformed wasm binary, should have reached end"
))
}
/// Get a reference te the metadata
pub fn metadata(&self) -> &Metadata {
match self {
Payload::Component { metadata, .. } => metadata,
Payload::Module(metadata) => metadata,
}
}
/// Get a mutable reference te the metadata
pub fn metadata_mut(&mut self) -> &mut Metadata {
match self {
Payload::Component { metadata, .. } => metadata,
Payload::Module(metadata) => metadata,
}
}
fn empty_component(range: Range<usize>) -> Self {
let mut this = Self::Component {
metadata: Metadata::default(),
children: vec![],
};
this.metadata_mut().range = range;
this
}
fn empty_module(range: Range<usize>) -> Self {
let mut this = Self::Module(Metadata::default());
this.metadata_mut().range = range;
this
}
fn push_child(&mut self, child: Self) {
match self {
Self::Module { .. } => panic!("module shouldnt have children"),
Self::Component { children, .. } => children.push(child),
}
}
}

254
vendor/wasm-metadata/src/producers.rs vendored Normal file
View File

@@ -0,0 +1,254 @@
use anyhow::Result;
use indexmap::{IndexMap, map::Entry};
use wasm_encoder::Encode;
use wasmparser::{BinaryReader, KnownCustom, Parser, ProducersSectionReader};
use crate::{AddMetadata, rewrite_wasm};
/// A representation of a WebAssembly producers section.
///
/// Spec: <https://github.com/WebAssembly/tool-conventions/blob/main/ProducersSection.md>
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde_derive::Serialize))]
pub struct Producers(
#[cfg_attr(
feature = "serde",
serde(serialize_with = "indexmap::map::serde_seq::serialize")
)]
IndexMap<String, IndexMap<String, String>>,
);
impl Default for Producers {
fn default() -> Self {
Self::empty()
}
}
impl Producers {
/// Creates an empty producers section
pub fn empty() -> Self {
Producers(IndexMap::new())
}
/// Indicates if section is empty
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Read the producers section from a Wasm binary. Supports both core
/// Modules and Components. In the component case, only returns the
/// producers section in the outer component, ignoring all interior
/// components and modules.
pub fn from_wasm(bytes: &[u8]) -> Result<Option<Self>> {
let mut depth = 0;
for payload in Parser::new(0).parse_all(bytes) {
let payload = payload?;
use wasmparser::Payload::*;
match payload {
ModuleSection { .. } | ComponentSection { .. } => depth += 1,
End { .. } => depth -= 1,
CustomSection(c) if depth == 0 => {
if let KnownCustom::Producers(_) = c.as_known() {
let producers = Self::from_bytes(c.data(), c.data_offset())?;
return Ok(Some(producers));
}
}
_ => {}
}
}
Ok(None)
}
/// Read the producers section from a Wasm binary.
pub fn from_bytes(bytes: &[u8], offset: usize) -> Result<Self> {
let reader = BinaryReader::new(bytes, offset);
let section = ProducersSectionReader::new(reader)?;
let mut fields = IndexMap::new();
for field in section.into_iter() {
let field = field?;
let mut values = IndexMap::new();
for value in field.values.into_iter() {
let value = value?;
values.insert(value.name.to_owned(), value.version.to_owned());
}
fields.insert(field.name.to_owned(), values);
}
Ok(Producers(fields))
}
/// Add a name & version value to a field.
///
/// The spec says expected field names are "language", "processed-by", and "sdk".
/// The version value should be left blank for languages.
pub fn add(&mut self, field: &str, name: &str, version: &str) {
match self.0.entry(field.to_string()) {
Entry::Occupied(e) => {
e.into_mut().insert(name.to_owned(), version.to_owned());
}
Entry::Vacant(e) => {
let mut m = IndexMap::new();
m.insert(name.to_owned(), version.to_owned());
e.insert(m);
}
}
}
/// Add all values found in another `Producers` section. Values in `other` take
/// precedence.
pub fn merge(&mut self, other: &Self) {
for (field, values) in other.iter() {
for (name, version) in values.iter() {
self.add(field, name, version);
}
}
}
/// Get the contents of a field
pub fn get<'a>(&'a self, field: &str) -> Option<ProducersField<'a>> {
self.0.get(&field.to_owned()).map(ProducersField)
}
/// Iterate through all fields
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a String, ProducersField<'a>)> + 'a {
self.0
.iter()
.map(|(name, field)| (name, ProducersField(field)))
}
/// Construct the fields specified by [`AddMetadata`]
pub(crate) fn from_meta(add: &AddMetadata) -> Self {
let mut s = Self::empty();
for (lang, version) in add.language.iter() {
s.add("language", &lang, &version);
}
for (name, version) in add.processed_by.iter() {
s.add("processed-by", &name, &version);
}
for (name, version) in add.sdk.iter() {
s.add("sdk", &name, &version);
}
s
}
/// Serialize into [`wasm_encoder::ProducersSection`].
pub(crate) fn section(&self) -> wasm_encoder::ProducersSection {
let mut section = wasm_encoder::ProducersSection::new();
for (fieldname, fieldvalues) in self.0.iter() {
let mut field = wasm_encoder::ProducersField::new();
for (name, version) in fieldvalues {
field.value(&name, &version);
}
section.field(&fieldname, &field);
}
section
}
/// Serialize into the raw bytes of a wasm custom section.
pub fn raw_custom_section(&self) -> Vec<u8> {
let mut ret = Vec::new();
self.section().encode(&mut ret);
ret
}
/// Merge into an existing wasm module. Rewrites the module with this producers section
/// merged into its existing one, or adds this producers section if none is present.
pub fn add_to_wasm(&self, input: &[u8]) -> Result<Vec<u8>> {
rewrite_wasm(&Default::default(), self, input)
}
}
/// Contents of a producers field
#[derive(Debug)]
pub struct ProducersField<'a>(&'a IndexMap<String, String>);
impl<'a> ProducersField<'a> {
/// Get the version associated with a name in the field
pub fn get(&self, name: &str) -> Option<&'a String> {
self.0.get(&name.to_owned())
}
/// Iterate through all name-version pairs in the field
pub fn iter(&self) -> impl Iterator<Item = (&'a String, &'a String)> + 'a {
self.0.iter()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{Metadata, Payload};
use wasm_encoder::Module;
#[test]
fn producers_empty_module() {
let module = Module::new().finish();
let mut producers = Producers::empty();
producers.add("language", "bar", "");
producers.add("processed-by", "baz", "1.0");
let module = producers.add_to_wasm(&module).unwrap();
match Payload::from_binary(&module).unwrap() {
Payload::Module(Metadata {
name, producers, ..
}) => {
assert_eq!(name, None);
let producers = producers.expect("some producers");
assert_eq!(producers.get("language").unwrap().get("bar").unwrap(), "");
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"1.0"
);
}
_ => panic!("metadata should be module"),
}
}
#[test]
fn producers_add_another_field() {
let module = Module::new().finish();
let mut producers = Producers::empty();
producers.add("language", "bar", "");
producers.add("processed-by", "baz", "1.0");
let module = producers.add_to_wasm(&module).unwrap();
let mut producers = Producers::empty();
producers.add("language", "waaat", "");
let module = producers.add_to_wasm(&module).unwrap();
match Payload::from_binary(&module).unwrap() {
Payload::Module(Metadata {
name, producers, ..
}) => {
assert_eq!(name, None);
let producers = producers.expect("some producers");
assert_eq!(producers.get("language").unwrap().get("bar").unwrap(), "");
assert_eq!(producers.get("language").unwrap().get("waaat").unwrap(), "");
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"1.0"
);
}
_ => panic!("metadata should be module"),
}
}
#[test]
fn producers_overwrite_field() {
let module = Module::new().finish();
let mut producers = Producers::empty();
producers.add("processed-by", "baz", "1.0");
let module = producers.add_to_wasm(&module).unwrap();
let mut producers = Producers::empty();
producers.add("processed-by", "baz", "420");
let module = producers.add_to_wasm(&module).unwrap();
match Payload::from_binary(&module).unwrap() {
Payload::Module(Metadata { producers, .. }) => {
let producers = producers.expect("some producers");
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"420"
);
}
_ => panic!("metadata should be module"),
}
}
}

224
vendor/wasm-metadata/src/rewrite.rs vendored Normal file
View File

@@ -0,0 +1,224 @@
use crate::add_metadata::AddMetadataField;
use crate::{AddMetadata, ComponentNames, ModuleNames, Producers};
use anyhow::Result;
use std::mem;
use wasm_encoder::ComponentSection as _;
use wasm_encoder::{ComponentSectionId, Encode, Section};
use wasmparser::{KnownCustom, Parser, Payload::*};
pub(crate) fn rewrite_wasm(
metadata: &AddMetadata,
add_producers: &Producers,
input: &[u8],
) -> Result<Vec<u8>> {
let mut producers_found = false;
let mut names_found = false;
let mut stack = Vec::new();
let mut output = Vec::new();
for payload in Parser::new(0).parse_all(&input) {
let payload = payload?;
// Track nesting depth, so that we don't mess with inner producer sections:
match payload {
Version { encoding, .. } => {
output.extend_from_slice(match encoding {
wasmparser::Encoding::Component => &wasm_encoder::Component::HEADER,
wasmparser::Encoding::Module => &wasm_encoder::Module::HEADER,
});
}
ModuleSection { .. } | ComponentSection { .. } => {
stack.push(mem::take(&mut output));
continue;
}
End { .. } => {
let mut parent = match stack.pop() {
Some(c) => c,
None => break,
};
if output.starts_with(&wasm_encoder::Component::HEADER) {
parent.push(ComponentSectionId::Component as u8);
output.encode(&mut parent);
} else {
parent.push(ComponentSectionId::CoreModule as u8);
output.encode(&mut parent);
}
output = parent;
}
_ => {}
}
// Only rewrite the outermost custom sections
if let CustomSection(c) = &payload {
if stack.len() == 0 {
match c.as_known() {
KnownCustom::Producers(_) => {
producers_found = true;
let mut producers = Producers::from_bytes(c.data(), c.data_offset())?;
// Add to the section according to the command line flags:
producers.merge(&add_producers);
// Encode into output:
producers.section().append_to(&mut output);
continue;
}
KnownCustom::Name(_) => {
names_found = true;
let mut names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
match &metadata.name {
AddMetadataField::Keep => {}
AddMetadataField::Set(name) => {
names.merge(&ModuleNames::from_name(&Some(name.clone())));
}
AddMetadataField::Clear => {
names = ModuleNames::empty();
}
};
names.section()?.as_custom().append_to(&mut output);
continue;
}
KnownCustom::ComponentName(_) => {
names_found = true;
let mut names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
match &metadata.name {
AddMetadataField::Keep => {}
AddMetadataField::Set(name) => {
names.merge(&ComponentNames::from_name(&Some(name.clone())));
}
AddMetadataField::Clear => {
names = ComponentNames::empty();
}
};
names.section()?.as_custom().append_to(&mut output);
continue;
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "authors" => {
if metadata.authors.is_keep() {
let authors = crate::Authors::parse_custom_section(c)?;
authors.append_to(&mut output);
continue;
} else if metadata.authors.is_clear() {
continue;
}
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "description" => {
if metadata.description.is_keep() {
let description = crate::Description::parse_custom_section(c)?;
description.append_to(&mut output);
continue;
} else if metadata.description.is_clear() {
continue;
}
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "licenses" => {
if metadata.licenses.is_keep() {
let licenses = crate::Licenses::parse_custom_section(c)?;
licenses.append_to(&mut output);
continue;
} else if metadata.licenses.is_clear() {
continue;
}
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "source" => {
if metadata.source.is_keep() {
let source = crate::Source::parse_custom_section(c)?;
source.append_to(&mut output);
continue;
} else if metadata.source.is_clear() {
continue;
}
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "homepage" => {
if metadata.homepage.is_keep() {
let homepage = crate::Homepage::parse_custom_section(c)?;
homepage.append_to(&mut output);
continue;
} else if metadata.homepage.is_clear() {
continue;
}
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "revision" => {
if metadata.revision.is_keep() {
let revision = crate::Revision::parse_custom_section(c)?;
revision.append_to(&mut output);
continue;
} else if metadata.revision.is_clear() {
continue;
}
}
#[cfg(feature = "oci")]
KnownCustom::Unknown if c.name() == "version" => {
if metadata.version.is_keep() {
let version = crate::Version::parse_custom_section(c)?;
version.append_to(&mut output);
continue;
} else if metadata.version.is_clear() {
continue;
}
}
_ => {}
}
}
}
// All other sections get passed through unmodified:
if let Some((id, range)) = payload.as_section() {
wasm_encoder::RawSection {
id,
data: &input[range],
}
.append_to(&mut output);
}
}
if !names_found {
if let AddMetadataField::Set(name) = &metadata.name {
if output.starts_with(&wasm_encoder::Component::HEADER) {
let names = ComponentNames::from_name(&Some(name.clone()));
names.section()?.append_to_component(&mut output);
} else {
let names = ModuleNames::from_name(&Some(name.clone()));
names.section()?.append_to(&mut output)
}
}
}
if !producers_found && !add_producers.is_empty() {
let mut producers = Producers::empty();
// Add to the section according to the command line flags:
producers.merge(add_producers);
// Encode into output:
producers.section().append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(authors) = &metadata.authors {
authors.append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(description) = &metadata.description {
description.append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(licenses) = &metadata.licenses {
licenses.append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(source) = &metadata.source {
source.append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(homepage) = &metadata.homepage {
homepage.append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(revision) = &metadata.revision {
revision.append_to(&mut output);
}
#[cfg(feature = "oci")]
if let AddMetadataField::Set(version) = &metadata.version {
version.append_to(&mut output);
}
Ok(output)
}

21
vendor/wasm-metadata/src/utils.rs vendored Normal file
View File

@@ -0,0 +1,21 @@
use anyhow::Result;
pub(crate) fn name_map(map: &wasmparser::NameMap<'_>) -> Result<wasm_encoder::NameMap> {
let mut out = wasm_encoder::NameMap::new();
for m in map.clone().into_iter() {
let m = m?;
out.append(m.index, m.name);
}
Ok(out)
}
pub(crate) fn indirect_name_map(
map: &wasmparser::IndirectNameMap<'_>,
) -> Result<wasm_encoder::IndirectNameMap> {
let mut out = wasm_encoder::IndirectNameMap::new();
for m in map.clone().into_iter() {
let m = m?;
out.append(m.index, &name_map(&m.names)?);
}
Ok(out)
}

View File

@@ -0,0 +1 @@
{"name":"wasm-metadata","vers":"0.244.0","deps":[{"name":"anyhow","req":"^1.0.58","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"auditable-serde","req":"^0.8.0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"clap","req":"^4.0.0","features":["derive"],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"flate2","req":"^1.1.0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"indexmap","req":"^2.7.0","features":["serde"],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"serde","req":"^1.0.166","features":["alloc"],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"serde_derive","req":"^1.0.166","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"serde_json","req":"^1","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"spdx","req":"^0.10.1","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"url","req":"^2.0.0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"wasm-encoder","req":"^0.244.0","features":["std","component-model"],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"wasmparser","req":"^0.244.0","features":["simd","std","component-model","hash-collections"],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false}],"features":{"default":["oci","serde"],"oci":["dep:auditable-serde","dep:flate2","dep:url","dep:spdx","dep:serde_json","serde"],"serde":["dep:serde_derive","dep:serde"]},"features2":null,"cksum":"442ba6047af1ca18176107a47e2a1aac37e9885293a2db4525f2795cd13a171d","yanked":null,"links":null,"rust_version":null,"v":2}

Binary file not shown.

310
vendor/wasm-metadata/tests/component.rs vendored Normal file
View File

@@ -0,0 +1,310 @@
use std::{str::FromStr, vec};
use auditable_serde::VersionInfo;
use wasm_encoder::{Component, Module};
use wasm_metadata::*;
#[test]
fn add_to_empty_component() {
let mut add = AddMetadata::default();
add.name = AddMetadataField::Set("foo".to_owned());
add.language = vec![("bar".to_owned(), "1.0".to_owned())];
add.processed_by = vec![("baz".to_owned(), "1.0".to_owned())];
add.sdk = vec![];
add.authors = AddMetadataField::Set(Authors::new("Chashu Cat"));
add.description = AddMetadataField::Set(Description::new("Chashu likes tuna"));
add.licenses = AddMetadataField::Set(
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap(),
);
add.source = AddMetadataField::Set(
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add.homepage = AddMetadataField::Set(
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add.revision = AddMetadataField::Set(Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
add.version = AddMetadataField::Set(Version::new("1.0.0"));
let json_str = r#"{"packages":[{"name":"adler","version":"0.2.3","source":"registry"}]}"#;
let info = VersionInfo::from_str(json_str).unwrap();
let mut component = Component::new();
component.section(&Dependencies::new(info.clone()));
let component = component.finish();
let component = add.to_wasm(&component).unwrap();
match Payload::from_binary(&component).unwrap() {
Payload::Component {
children,
metadata:
Metadata {
name,
producers,
authors,
description,
licenses,
source,
range,
homepage,
revision,
version,
dependencies,
},
} => {
assert!(children.is_empty());
assert_eq!(name, Some("foo".to_owned()));
let producers = producers.expect("some producers");
assert_eq!(
producers.get("language").unwrap().get("bar").unwrap(),
"1.0"
);
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"1.0"
);
assert_eq!(authors.unwrap(), Authors::new("Chashu Cat"));
assert_eq!(description.unwrap(), Description::new("Chashu likes tuna"));
assert_eq!(
licenses.unwrap(),
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap()
);
assert_eq!(
source.unwrap(),
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
assert_eq!(
homepage.unwrap(),
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
assert_eq!(
revision.unwrap(),
Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad")
);
assert_eq!(version.unwrap(), Version::new("1.0.0"));
assert_eq!(dependencies.unwrap().version_info(), &info,);
assert_eq!(range.start, 0);
assert_eq!(range.end, 465);
}
_ => panic!("metadata should be component"),
}
}
#[test]
fn add_to_nested_component() {
// Create the same old module, stick some metadata into it
let mut add = AddMetadata::default();
add.name = AddMetadataField::Set("foo".to_owned());
add.language = vec![("bar".to_owned(), "1.0".to_owned())];
add.processed_by = vec![("baz".to_owned(), "1.0".to_owned())];
add.sdk = vec![];
add.authors = AddMetadataField::Set(Authors::new("Chashu Cat"));
add.description = AddMetadataField::Set(Description::new("Chashu likes tuna"));
add.licenses = AddMetadataField::Set(
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap(),
);
add.source = AddMetadataField::Set(
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add.homepage = AddMetadataField::Set(
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add.revision = AddMetadataField::Set(Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
add.version = AddMetadataField::Set(Version::new("1.0.0"));
let json_str = r#"{"packages":[{"name":"adler","version":"0.2.3","source":"registry"}]}"#;
let info = VersionInfo::from_str(json_str).unwrap();
let mut component = Module::new();
component.section(&Dependencies::new(info.clone()));
let module = component.finish();
let module = add.to_wasm(&module).unwrap();
// Stick that module inside a component.
let mut component = wasm_encoder::Component::new();
component.section(&wasm_encoder::RawSection {
id: wasm_encoder::ComponentSectionId::CoreModule.into(),
data: &module,
});
let component = component.finish();
// Add some different metadata to the component.
let mut add = AddMetadata::default();
add.name = AddMetadataField::Set("gussie".to_owned());
add.sdk = vec![("willa".to_owned(), "sparky".to_owned())];
let component = add.to_wasm(&component).unwrap();
match Payload::from_binary(&component).unwrap() {
Payload::Component {
children,
metadata: Metadata {
name, producers, ..
},
} => {
// Check that the component metadata is in the component
assert_eq!(name, Some("gussie".to_owned()));
let producers = producers.as_ref().expect("some producers");
assert_eq!(
producers.get("sdk").unwrap().get("willa").unwrap(),
&"sparky".to_owned()
);
// Check that there is a single child with the metadata set for the module
assert_eq!(children.len(), 1);
match children.get(0).unwrap() {
Payload::Module(Metadata {
name,
producers,
authors,
licenses,
source,
range,
description,
homepage,
revision,
version,
dependencies,
}) => {
assert_eq!(name, &Some("foo".to_owned()));
let producers = producers.as_ref().expect("some producers");
assert_eq!(
producers.get("language").unwrap().get("bar").unwrap(),
"1.0"
);
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"1.0"
);
assert_eq!(authors, &Some(Authors::new("Chashu Cat")));
assert_eq!(description, &Some(Description::new("Chashu likes tuna")));
assert_eq!(
licenses,
&Some(
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT")
.unwrap()
)
);
assert_eq!(
source,
&Some(
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap()
),
);
assert_eq!(
homepage,
&Some(
Homepage::new("https://github.com/bytecodealliance/wasm-tools")
.unwrap()
),
);
assert_eq!(
revision,
&Some(Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"))
);
assert_eq!(version, &Some(Version::new("1.0.0")));
assert_eq!(dependencies.as_ref().unwrap().version_info(), &info);
assert_eq!(range.start, 11);
assert_eq!(range.end, 466);
}
_ => panic!("child is a module"),
}
}
_ => panic!("root should be component"),
}
}
#[test]
fn add_then_clear_fields() {
let mut add1 = AddMetadata::default();
add1.name = AddMetadataField::Set("foo".to_owned());
add1.language = vec![("bar".to_owned(), "1.0".to_owned())];
add1.processed_by = vec![("baz".to_owned(), "1.0".to_owned())];
add1.sdk = vec![];
add1.authors = AddMetadataField::Set(Authors::new("Chashu Cat"));
add1.description = AddMetadataField::Set(Description::new("Chashu likes tuna"));
add1.licenses = AddMetadataField::Set(
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap(),
);
add1.source = AddMetadataField::Set(
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add1.homepage = AddMetadataField::Set(
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add1.revision =
AddMetadataField::Set(Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
add1.version = AddMetadataField::Set(Version::new("1.0.0"));
let json_str = r#"{"packages":[{"name":"adler","version":"0.2.3","source":"registry"}]}"#;
let info = VersionInfo::from_str(json_str).unwrap();
let mut component1 = Component::new();
component1.section(&Dependencies::new(info.clone()));
let component1 = component1.finish();
let component1 = add1.to_wasm(&component1).unwrap();
let mut add2 = AddMetadata::default();
add2.name = AddMetadataField::Clear;
add2.version = AddMetadataField::Clear;
add2.description = AddMetadataField::Set(Description::new("Chashu likes something else"));
add2.revision = AddMetadataField::Clear;
let component2 = add2.to_wasm(&component1).unwrap();
match Payload::from_binary(&component2).unwrap() {
Payload::Component {
children,
metadata:
Metadata {
name,
producers,
authors,
description,
licenses,
source,
range,
homepage,
revision,
version,
dependencies,
},
} => {
assert!(children.is_empty());
assert_eq!(name, None);
let producers = producers.expect("some producers");
assert_eq!(
producers.get("language").unwrap().get("bar").unwrap(),
"1.0"
);
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"1.0"
);
assert_eq!(authors.unwrap(), Authors::new("Chashu Cat"));
assert_eq!(
description.unwrap(),
Description::new("Chashu likes something else")
);
assert_eq!(
licenses.unwrap(),
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap()
);
assert_eq!(
source.unwrap(),
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
assert_eq!(
homepage.unwrap(),
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
assert_eq!(revision, None);
assert_eq!(version, None);
assert_eq!(dependencies.unwrap().version_info(), &info,);
assert_eq!(range.start, 0);
assert_eq!(range.end, 434);
}
_ => panic!("metadata should be component"),
}
}

86
vendor/wasm-metadata/tests/module.rs vendored Normal file
View File

@@ -0,0 +1,86 @@
use std::{str::FromStr, vec};
use auditable_serde::VersionInfo;
use wasm_encoder::Module;
use wasm_metadata::*;
#[test]
fn add_to_empty_module() {
let mut add = AddMetadata::default();
add.name = AddMetadataField::Set("foo".to_owned());
add.language = vec![("bar".to_owned(), "1.0".to_owned())];
add.processed_by = vec![("baz".to_owned(), "1.0".to_owned())];
add.sdk = vec![];
add.authors = AddMetadataField::Set(Authors::new("Chashu Cat"));
add.description = AddMetadataField::Set(Description::new("Chashu likes tuna"));
add.licenses = AddMetadataField::Set(
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap(),
);
add.source = AddMetadataField::Set(
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add.homepage = AddMetadataField::Set(
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
add.revision = AddMetadataField::Set(Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
add.version = AddMetadataField::Set(Version::new("1.0.0"));
let json_str = r#"{"packages":[{"name":"adler","version":"0.2.3","source":"registry"}]}"#;
let info = VersionInfo::from_str(json_str).unwrap();
let mut component = Module::new();
component.section(&Dependencies::new(info.clone()));
let module = component.finish();
let module = add.to_wasm(&module).unwrap();
match Payload::from_binary(&module).unwrap() {
Payload::Module(Metadata {
name,
producers,
authors,
licenses,
source,
range,
description,
homepage,
revision,
version,
dependencies,
}) => {
assert_eq!(name, Some("foo".to_owned()));
let producers = producers.expect("some producers");
assert_eq!(
producers.get("language").unwrap().get("bar").unwrap(),
"1.0"
);
assert_eq!(
producers.get("processed-by").unwrap().get("baz").unwrap(),
"1.0"
);
assert_eq!(authors.unwrap(), Authors::new("Chashu Cat"));
assert_eq!(description.unwrap(), Description::new("Chashu likes tuna"));
assert_eq!(
licenses.unwrap(),
Licenses::new("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT").unwrap()
);
assert_eq!(
source.unwrap(),
Source::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
assert_eq!(
homepage.unwrap(),
Homepage::new("https://github.com/bytecodealliance/wasm-tools").unwrap(),
);
assert_eq!(
revision.unwrap(),
Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad")
);
assert_eq!(version.unwrap(), Version::new("1.0.0"));
assert_eq!(dependencies.unwrap().version_info(), &info,);
assert_eq!(range.start, 0);
assert_eq!(range.end, 455);
}
_ => panic!("metadata should be module"),
}
}