diff --git a/.cargo/config.toml.in b/.cargo/config.toml.in index 65f5255a10c1..7fd98731d576 100644 --- a/.cargo/config.toml.in +++ b/.cargo/config.toml.in @@ -70,9 +70,9 @@ git = "https://github.com/jfkthame/mapped_hyph.git" rev = "eff105f6ad7ec9b79816cfc1985a28e5340ad14b" replace-with = "vendored-sources" -[source."git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94"] +[source."git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a"] git = "https://github.com/mozilla/application-services" -rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" +rev = "d773da92641d92930b7308300e9fc2746a05ce6a" replace-with = "vendored-sources" [source."git+https://github.com/mozilla/audioipc?rev=e6f44a2bd1e57d11dfc737632a9e849077632330"] diff --git a/Cargo.lock b/Cargo.lock index 4b55fc7614ad..806b08b9ce03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -189,6 +189,38 @@ dependencies = [ "libc", ] +[[package]] +name = "askama" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e" +dependencies = [ + "askama_derive", + "askama_escape", +] + +[[package]] +name = "askama_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94" +dependencies = [ + "basic-toml", + "mime", + "mime_guess", + "nom", + "proc-macro2", + "quote", + "serde", + "syn", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + [[package]] name = "async-task" version = "4.3.0" @@ -435,7 +467,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 1.999.999", + "rustc-hash", "shlex", "syn", ] @@ -902,7 +934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "termcolor", - "unicode-width 0.1.999", + "unicode-width", ] [[package]] @@ -1783,7 +1815,7 @@ dependencies = [ [[package]] name = "error-support" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "error-support-macros", "lazy_static", @@ -1795,7 +1827,7 @@ dependencies = [ [[package]] name = "error-support-macros" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "proc-macro2", "quote", @@ -1912,7 +1944,7 @@ dependencies = [ [[package]] name = "firefox-versioning" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "serde_json", "thiserror 1.999.999", @@ -1964,7 +1996,7 @@ dependencies = [ "fluent-syntax", "intl-memoizer", "intl_pluralrules", - "rustc-hash 1.999.999", + "rustc-hash", "self_cell", "smallvec", "unic-langid", @@ -1981,7 +2013,7 @@ dependencies = [ "fluent-bundle", "futures", "once_cell", - "rustc-hash 1.999.999", + "rustc-hash", "unic-langid", ] @@ -2565,9 +2597,9 @@ dependencies = [ [[package]] name = "glean" -version = "64.0.0" +version = "63.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92338cfd9fb34b00c02c6da8e22936b41835eb02ab5462d3d88cc4b6249c35" +checksum = "e2afa6754943cac5243099efd0d26e89cc8e06f1585776ba14ab0c6ee99e1f71" dependencies = [ "crossbeam-channel", "glean-core", @@ -2579,9 +2611,9 @@ dependencies = [ [[package]] name = "glean-core" -version = "64.0.0" +version = "63.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a2cbf41fbb9996b14fc1721b8bd06e669589de05e6efc20a24bab14285623a" +checksum = "53cd53bb7a3b89b17d3989e95dd808b137ff47c504d1d19f14cb0d820cc2f42e" dependencies = [ "android_logger", "bincode", @@ -3211,7 +3243,7 @@ dependencies = [ [[package]] name = "interrupt-support" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "lazy_static", "parking_lot", @@ -3293,9 +3325,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jexl-eval" @@ -3431,7 +3463,7 @@ dependencies = [ "futures", "pin-project-lite", "replace_with", - "rustc-hash 1.999.999", + "rustc-hash", "unic-langid", ] @@ -4488,7 +4520,7 @@ dependencies = [ "indexmap", "log", "num-traits", - "rustc-hash 1.999.999", + "rustc-hash", "serde", "spirv", "strum", @@ -4917,7 +4949,7 @@ checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "payload-support" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "serde", "serde_derive", @@ -5413,7 +5445,7 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "relevancy" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "anyhow", "base64 0.21.999", @@ -5438,7 +5470,7 @@ dependencies = [ [[package]] name = "remote_settings" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "anyhow", "camino", @@ -5483,45 +5515,6 @@ dependencies = [ "cache-padded", ] -[[package]] -name = "rinja" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5" -dependencies = [ - "itoa", - "rinja_derive", -] - -[[package]] -name = "rinja_derive" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d9ed0146aef6e2825f1b1515f074510549efba38d71f4554eec32eb36ba18b" -dependencies = [ - "basic-toml", - "memchr", - "mime", - "mime_guess", - "proc-macro2", - "quote", - "rinja_parser", - "rustc-hash 2.1.1", - "serde", - "syn", -] - -[[package]] -name = "rinja_parser" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f9a866e2e00a7a1fb27e46e9e324a6f7c0e7edc4543cae1d38f4e4a100c610" -dependencies = [ - "memchr", - "nom", - "serde", -] - [[package]] name = "rkv" version = "0.19.0" @@ -5672,16 +5665,9 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc-hash" -version = "1.999.999" -dependencies = [ - "rustc-hash 2.1.1", -] - -[[package]] -name = "rustc-hash" -version = "2.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" @@ -5767,7 +5753,7 @@ dependencies = [ [[package]] name = "search" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "error-support", "firefox-versioning", @@ -6057,7 +6043,7 @@ dependencies = [ [[package]] name = "sql-support" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "interrupt-support", "lazy_static", @@ -6256,7 +6242,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "suggest" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "anyhow", "chrono", @@ -6308,7 +6294,7 @@ dependencies = [ [[package]] name = "sync-guid" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "base64 0.21.999", "rand", @@ -6319,7 +6305,7 @@ dependencies = [ [[package]] name = "sync15" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "anyhow", "error-support", @@ -6359,7 +6345,7 @@ dependencies = [ [[package]] name = "tabs" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "anyhow", "error-support", @@ -6685,7 +6671,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" dependencies = [ - "rustc-hash 1.999.999", + "rustc-hash", ] [[package]] @@ -6703,7 +6689,7 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "types" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "rusqlite", "serde", @@ -6780,22 +6766,15 @@ checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-width" -version = "0.1.999" -dependencies = [ - "unicode-width 0.2.0", -] - -[[package]] -name = "unicode-width" -version = "0.2.0" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "uniffi" -version = "0.29.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba62a57e90f9baed5ad02a71a0870180fa1cc35499093b2d21be2edfb68ec0f7" +checksum = "51ce6280c581045879e11b400bae14686a819df22b97171215d15549efa04ddb" dependencies = [ "anyhow", "cargo_metadata", @@ -6810,12 +6789,12 @@ name = "uniffi-bindgen-gecko-js" version = "0.1.0" dependencies = [ "anyhow", + "askama", "camino", "cargo_metadata", "clap", "extend", "heck", - "rinja", "serde", "textwrap", "toml", @@ -6915,11 +6894,12 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.29.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2242f35214f1e0e3b47c495d340c69f649f9a9ece3a943a29e275686cc884533" +checksum = "5e9f25730c9db2e878521d606f54e921edb719cdd94d735e7f97705d6796d024" dependencies = [ "anyhow", + "askama", "camino", "cargo_metadata", "fs-err", @@ -6928,7 +6908,6 @@ dependencies = [ "heck", "once_cell", "paste", - "rinja", "serde", "textwrap", "toml", @@ -6939,9 +6918,9 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.29.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c887a6c9a2857d8dc2ab0c8d578e8aa4978145b4fd65ed44296341e89aebc3cc" +checksum = "88dba57ac699bd8ec53d6a352c8dd0e479b33f698c5659831bb1e4ce468c07bd" dependencies = [ "anyhow", "camino", @@ -6949,34 +6928,36 @@ dependencies = [ ] [[package]] -name = "uniffi_core" -version = "0.29.0" +name = "uniffi_checksum_derive" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad9fbdeb7ae4daf8d0f7704a3b638c37018eb16bb701e30fa17a2dd3e2d39c1" -dependencies = [ - "anyhow", - "bytes", - "once_cell", - "paste", - "static_assertions", -] - -[[package]] -name = "uniffi_internal_macros" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9dba1d78b9ce429439891089c223478043d52a1c3176a0fcea2b5573a7fcf" +checksum = "d2c801f0f05b06df456a2da4c41b9c2c4fdccc6b9916643c6c67275c4c9e4d07" dependencies = [ "quote", "syn", ] [[package]] -name = "uniffi_macros" -version = "0.29.0" +name = "uniffi_core" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78dd5f8eefba5898b901086f5e7916da67b9a5286a01cc44e910cd75fa37c630" +checksum = "61049e4db6212d0ede80982adf0e1d6fa224e6118387324c5cfbe3083dfb2252" dependencies = [ + "anyhow", + "bytes", + "log", + "once_cell", + "paste", + "static_assertions", +] + +[[package]] +name = "uniffi_macros" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b40fd2249e0c5dcbd2bfa3c263db1ec981f7273dca7f4132bf06a272359a586c" +dependencies = [ + "bincode", "camino", "fs-err", "once_cell", @@ -6990,20 +6971,21 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.29.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5965b1d4ffacef1eaa72fef9c00d2491641e87ad910f6c5859b9c503ddb16a" +checksum = "c9ad57039b4fafdbf77428d74fff40e0908e5a1731e023c19cfe538f6d4a8ed6" dependencies = [ "anyhow", + "bytes", "siphasher", - "uniffi_internal_macros", + "uniffi_checksum_derive", ] [[package]] name = "uniffi_testing" -version = "0.29.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b0f35750a3e1836f10f26e4eceba688748b8a1e94a6ee251c976099d984d4f" +checksum = "21fa171d4d258dc51bbd01893cc9608c1b62273d2f9ea55fb64f639e77824567" dependencies = [ "anyhow", "camino", @@ -7014,13 +6996,14 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.29.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279b82bac9a382c796a0d210bb8354a0b813499b28aa1de046c85d78ca389805" +checksum = "f52299e247419e7e2934bef2f94d7cccb0e6566f3248b1d48b160d8f369a2668" dependencies = [ "anyhow", "textwrap", "uniffi_meta", + "uniffi_testing", "weedle2", ] @@ -7086,7 +7069,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "viaduct" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "ffi-support", "log", @@ -7224,7 +7207,7 @@ dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width 0.1.999", + "unicode-width", "wasm-encoder", ] @@ -7256,7 +7239,7 @@ dependencies = [ [[package]] name = "webext-storage" version = "0.1.0" -source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94" +source = "git+https://github.com/mozilla/application-services?rev=d773da92641d92930b7308300e9fc2746a05ce6a#d773da92641d92930b7308300e9fc2746a05ce6a" dependencies = [ "anyhow", "error-support", @@ -7410,7 +7393,7 @@ dependencies = [ "parking_lot", "profiling", "ron", - "rustc-hash 1.999.999", + "rustc-hash", "serde", "smallvec", "thiserror 2.0.9", diff --git a/Cargo.toml b/Cargo.toml index d16e286be4d5..44dba1782c15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,12 +61,12 @@ rust-version = "1.82.0" [workspace.dependencies] # Shared across multiple UniFFI consumers. -uniffi = "0.29.0" -uniffi_bindgen = "0.29.0" +uniffi = "0.28.2" +uniffi_bindgen = "0.28.2" # Shared across multiple application-services consumers. rusqlite = "0.31.0" # Shared across multiple glean consumers. -glean = "=64.0.0" +glean = "=63.1.0" # Explicitly specify what our profiles use. The opt-level setting here is # a total fiction; see the setup of MOZ_RUST_DEFAULT_FLAGS for what the @@ -176,9 +176,6 @@ goblin = { path = "build/rust/goblin" } # Implement getrandom 0.2 in terms of 0.3 getrandom = { path = "build/rust/getrandom" } -# Patch rustc-hash 1.1.0 to 2.1.1 -rustc-hash = { path = "build/rust/rustc-hash" } - # Patch memoffset from 0.8.0 to 0.9.0 since it's compatible and it avoids duplication memoffset = { path = "build/rust/memoffset" } @@ -220,9 +217,6 @@ rure = { path = "third_party/rust/rure" } # Patch `plist` to work with `indexmap` 2.* plist = { path = "third_party/rust/plist" } -# Patch `unicode-width` 0.1.* to 0.2. -unicode-width = { path = "build/rust/unicode-width" } - # To-be-published changes. unicode-bidi = { git = "https://github.com/servo/unicode-bidi", rev = "ca612daf1c08c53abe07327cb3e6ef6e0a760f0c" } nss-gk-api = { git = "https://github.com/beurdouche/nss-gk-api", rev = "e48a946811ffd64abc78de3ee284957d8d1c0d63" } @@ -247,14 +241,14 @@ malloc_size_of_derive = { path = "xpcom/rust/malloc_size_of_derive" } objc = { git = "https://github.com/glandium/rust-objc", rev = "4de89f5aa9851ceca4d40e7ac1e2759410c04324" } # application-services overrides to make updating them all simpler. -interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -relevancy = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -search = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -sql-support = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -suggest = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -sync15 = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -tabs = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -viaduct = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } -webext-storage = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" } +interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +relevancy = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +search = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +sql-support = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +suggest = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +sync15 = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +tabs = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +viaduct = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } +webext-storage = { git = "https://github.com/mozilla/application-services", rev = "d773da92641d92930b7308300e9fc2746a05ce6a" } allocator-api2 = { path = "third_party/rust/allocator-api2" } diff --git a/build/rust/rustc-hash/Cargo.toml b/build/rust/rustc-hash/Cargo.toml deleted file mode 100644 index 977387a469fd..000000000000 --- a/build/rust/rustc-hash/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "rustc-hash" -version = "1.999.999" -edition = "2018" -license = "Apache-2.0 OR MIT" - -[lib] -path = "lib.rs" - -[dependencies.rustc-hash] -version = "2.1.1" -default-features = false - -[features] -default = ["rustc-hash/default"] -std = ["rustc-hash/std"] -rand = ["rustc-hash/rand"] diff --git a/build/rust/rustc-hash/lib.rs b/build/rust/rustc-hash/lib.rs deleted file mode 100644 index dd0d3cd92fd7..000000000000 --- a/build/rust/rustc-hash/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub use rustc_hash::*; diff --git a/build/rust/unicode-width/Cargo.toml b/build/rust/unicode-width/Cargo.toml deleted file mode 100644 index 91e1341a2f1f..000000000000 --- a/build/rust/unicode-width/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "unicode-width" -version = "0.1.999" -edition = "2018" -license = "MPL-2.0" - -[lib] -path = "lib.rs" - -[dependencies.unicode-width] -version = "0.2.0" -default-features = false - -[features] -default = ["unicode-width/default"] -cjk = ["unicode-width/cjk"] -no_std = ["unicode-width/no_std"] -rustc-dep-of-std = ["unicode-width/rustc-dep-of-std"] diff --git a/build/rust/unicode-width/lib.rs b/build/rust/unicode-width/lib.rs deleted file mode 100644 index 817c98ed5779..000000000000 --- a/build/rust/unicode-width/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -pub use unicode_width::*; diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock index 137abf1f0206..e7fa273f5e5a 100644 --- a/gfx/wr/Cargo.lock +++ b/gfx/wr/Cargo.lock @@ -87,6 +87,38 @@ dependencies = [ "term", ] +[[package]] +name = "askama" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e" +dependencies = [ + "askama_derive", + "askama_escape", +] + +[[package]] +name = "askama_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94" +dependencies = [ + "basic-toml", + "mime", + "mime_guess", + "nom 7.1.1", + "proc-macro2", + "quote", + "serde", + "syn 2.0.25", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + [[package]] name = "atty" version = "0.2.14" @@ -149,7 +181,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash", "shlex", "syn 2.0.25", "which", @@ -253,6 +285,32 @@ name = "camino" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] [[package]] name = "cbitset" @@ -982,9 +1040,9 @@ dependencies = [ [[package]] name = "glean" -version = "64.0.0" +version = "63.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92338cfd9fb34b00c02c6da8e22936b41835eb02ab5462d3d88cc4b6249c35" +checksum = "e2afa6754943cac5243099efd0d26e89cc8e06f1585776ba14ab0c6ee99e1f71" dependencies = [ "crossbeam-channel", "glean-core", @@ -996,9 +1054,9 @@ dependencies = [ [[package]] name = "glean-core" -version = "64.0.0" +version = "63.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a2cbf41fbb9996b14fc1721b8bd06e669589de05e6efc20a24bab14285623a" +checksum = "53cd53bb7a3b89b17d3989e95dd808b137ff47c504d1d19f14cb0d820cc2f42e" dependencies = [ "android_logger", "bincode", @@ -1311,9 +1369,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "jni-sys" @@ -2270,45 +2328,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" -[[package]] -name = "rinja" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5" -dependencies = [ - "itoa", - "rinja_derive", -] - -[[package]] -name = "rinja_derive" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d9ed0146aef6e2825f1b1515f074510549efba38d71f4554eec32eb36ba18b" -dependencies = [ - "basic-toml", - "memchr", - "mime", - "mime_guess", - "proc-macro2", - "quote", - "rinja_parser", - "rustc-hash 2.1.1", - "serde", - "syn 2.0.25", -] - -[[package]] -name = "rinja_parser" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f9a866e2e00a7a1fb27e46e9e324a6f7c0e7edc4543cae1d38f4e4a100c610" -dependencies = [ - "memchr", - "nom 7.1.1", - "serde", -] - [[package]] name = "rkv" version = "0.19.0" @@ -2351,7 +2370,7 @@ dependencies = [ "countme", "hashbrown 0.12.3", "memoffset", - "rustc-hash 1.1.0", + "rustc-hash", "text-size", ] @@ -2361,12 +2380,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustix" version = "0.38.38" @@ -2438,6 +2451,9 @@ name = "semver" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -2828,9 +2844,9 @@ checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "uniffi" -version = "0.29.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba62a57e90f9baed5ad02a71a0870180fa1cc35499093b2d21be2edfb68ec0f7" +checksum = "2db87def739fe4183947f8419d572d1849a4a09355eba4e988a2105cfd0ac6a7" dependencies = [ "anyhow", "uniffi_build", @@ -2840,11 +2856,12 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.29.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2242f35214f1e0e3b47c495d340c69f649f9a9ece3a943a29e275686cc884533" +checksum = "7a112599c9556d1581e4a3d72019a74c2c3e122cc27f4af12577a429c4d5e614" dependencies = [ "anyhow", + "askama", "camino", "fs-err", "glob", @@ -2852,7 +2869,6 @@ dependencies = [ "heck", "once_cell", "paste", - "rinja", "serde", "textwrap 0.16.1", "toml", @@ -2862,9 +2878,9 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.29.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c887a6c9a2857d8dc2ab0c8d578e8aa4978145b4fd65ed44296341e89aebc3cc" +checksum = "e2b12684401d2a8508ca9c72a95bbc45906417e42fc80942abaf033bbf01aa33" dependencies = [ "anyhow", "camino", @@ -2872,34 +2888,37 @@ dependencies = [ ] [[package]] -name = "uniffi_core" -version = "0.29.0" +name = "uniffi_checksum_derive" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad9fbdeb7ae4daf8d0f7704a3b638c37018eb16bb701e30fa17a2dd3e2d39c1" -dependencies = [ - "anyhow", - "bytes", - "once_cell", - "paste", - "static_assertions", -] - -[[package]] -name = "uniffi_internal_macros" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9dba1d78b9ce429439891089c223478043d52a1c3176a0fcea2b5573a7fcf" +checksum = "a22dbe67c1c957ac6e7611bdf605a6218aa86b0eebeb8be58b70ae85ad7d73dc" dependencies = [ "quote", "syn 2.0.25", ] [[package]] -name = "uniffi_macros" -version = "0.29.0" +name = "uniffi_core" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78dd5f8eefba5898b901086f5e7916da67b9a5286a01cc44e910cd75fa37c630" +checksum = "5a0c35aaad30e3a9e6d4fe34e358d64dbc92ee09045b48591b05fc9f12e0905b" dependencies = [ + "anyhow", + "bytes", + "camino", + "log", + "once_cell", + "paste", + "static_assertions", +] + +[[package]] +name = "uniffi_macros" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db66474c5c61b0f7afc3b4995fecf9b72b340daa5ca0ef3da7778d75eb5482ea" +dependencies = [ + "bincode", "camino", "fs-err", "once_cell", @@ -2913,24 +2932,39 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.29.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5965b1d4ffacef1eaa72fef9c00d2491641e87ad910f6c5859b9c503ddb16a" +checksum = "d898893f102e0e39b8bcb7e3d2188f4156ba280db32db9e8af1f122d057e9526" dependencies = [ "anyhow", + "bytes", "siphasher", - "uniffi_internal_macros", + "uniffi_checksum_derive", +] + +[[package]] +name = "uniffi_testing" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6aa4f0cf9d12172d84fc00a35a6c1f3522b526daad05ae739f709f6941b9b6" +dependencies = [ + "anyhow", + "camino", + "cargo_metadata", + "fs-err", + "once_cell", ] [[package]] name = "uniffi_udl" -version = "0.29.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279b82bac9a382c796a0d210bb8354a0b813499b28aa1de046c85d78ca389805" +checksum = "6b044e9c519e0bb51e516ab6f6d8f4f4dcf900ce30d5ad07c03f924e2824f28e" dependencies = [ "anyhow", "textwrap 0.16.1", "uniffi_meta", + "uniffi_testing", "weedle2", ] diff --git a/gfx/wr/Cargo.toml b/gfx/wr/Cargo.toml index 363f20b5b6da..c5efde7d1cf9 100644 --- a/gfx/wr/Cargo.toml +++ b/gfx/wr/Cargo.toml @@ -9,7 +9,7 @@ members = [ resolver = "2" [workspace.dependencies] -glean = "=64.0.0" +glean = "=63.1.0" [profile.release] debug = true diff --git a/gfx/wr/servo-tidy.toml b/gfx/wr/servo-tidy.toml index 1c9890ede045..355cb7d7f565 100644 --- a/gfx/wr/servo-tidy.toml +++ b/gfx/wr/servo-tidy.toml @@ -28,8 +28,6 @@ packages = [ "parking_lot_core", "rand", "rand_core", - # rinja (dependency of uniffi) requires 2.1, rowan requires 1.1 - "rustc-hash", # transition to syn 2 is underway. "syn", "synstructure", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5d73562cb507..2e3dce91ef9e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ android-gradle-plugin = "8.9.1" # Keep lint version in sync lint = "31.9.1" python-envs-plugin = "0.0.31" -mozilla-glean = "64.0.0" +mozilla-glean = "63.1.0" maven-ant-tasks = "2.1.3" jacoco = "0.8.12" okhttp = "4.12.0" diff --git a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/net/ConceptFetchHttpUploader.kt b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/net/ConceptFetchHttpUploader.kt index 2c5b5ab457c6..06947e6d5bad 100644 --- a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/net/ConceptFetchHttpUploader.kt +++ b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/net/ConceptFetchHttpUploader.kt @@ -11,11 +11,8 @@ import mozilla.components.concept.fetch.Header import mozilla.components.concept.fetch.Request import mozilla.components.concept.fetch.toMutableHeaders import mozilla.components.support.base.log.logger.Logger -import mozilla.telemetry.glean.net.CapablePingUploadRequest import mozilla.telemetry.glean.net.HeadersList import mozilla.telemetry.glean.net.HttpStatus -import mozilla.telemetry.glean.net.Incapable -import mozilla.telemetry.glean.net.PingUploadRequest import mozilla.telemetry.glean.net.RecoverableFailure import mozilla.telemetry.glean.net.UploadResult import java.io.IOException @@ -67,12 +64,8 @@ class ConceptFetchHttpUploader( * or faced an unrecoverable error), false if there was a recoverable * error callers can deal with. */ - override fun upload(request: CapablePingUploadRequest): UploadResult { - val req: PingUploadRequest? = request.capable({ capabilities: List -> capabilities.size == 0 }) - if (req == null) { - return Incapable(0) - } - val request = buildRequest(req) + override fun upload(url: String, data: ByteArray, headers: HeadersList): UploadResult { + val request = buildRequest(url, data, headers) return try { performUpload(client.value, request) @@ -83,11 +76,15 @@ class ConceptFetchHttpUploader( } @VisibleForTesting(otherwise = PRIVATE) - internal fun buildRequest(request: PingUploadRequest): Request { - val conceptHeaders = request.headers.map { (name, value) -> Header(name, value) }.toMutableHeaders() + internal fun buildRequest( + url: String, + data: ByteArray, + headers: HeadersList, + ): Request { + val conceptHeaders = headers.map { (name, value) -> Header(name, value) }.toMutableHeaders() return Request( - url = request.url, + url = url, method = Request.Method.POST, connectTimeout = Pair(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS), readTimeout = Pair(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS), @@ -96,7 +93,7 @@ class ConceptFetchHttpUploader( // offer a better API to do that, so we nuke all cookies going to our telemetry // endpoint. cookiePolicy = Request.CookiePolicy.OMIT, - body = Request.Body(request.data.inputStream()), + body = Request.Body(data.inputStream()), private = usePrivateRequest, conservative = true, ) diff --git a/mobile/android/android-components/components/service/glean/src/test/java/mozilla/components/service/glean/net/ConceptFetchHttpUploaderTest.kt b/mobile/android/android-components/components/service/glean/src/test/java/mozilla/components/service/glean/net/ConceptFetchHttpUploaderTest.kt index b27310a2bce5..48d0d6c3a4e4 100644 --- a/mobile/android/android-components/components/service/glean/src/test/java/mozilla/components/service/glean/net/ConceptFetchHttpUploaderTest.kt +++ b/mobile/android/android-components/components/service/glean/src/test/java/mozilla/components/service/glean/net/ConceptFetchHttpUploaderTest.kt @@ -13,9 +13,7 @@ import mozilla.components.support.test.any import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.mock import mozilla.telemetry.glean.config.Configuration -import mozilla.telemetry.glean.net.CapablePingUploadRequest import mozilla.telemetry.glean.net.HttpStatus -import mozilla.telemetry.glean.net.PingUploadRequest import mozilla.telemetry.glean.net.RecoverableFailure import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse @@ -61,8 +59,7 @@ class ConceptFetchHttpUploaderTest { val uploader = spy(ConceptFetchHttpUploader(lazy { HttpURLConnectionClient() })) - val uploadRequest = PingUploadRequest(url = testPath, data = testPing.toByteArray(), emptyMap(), emptyList()) - val request = uploader.buildRequest(uploadRequest) + val request = uploader.buildRequest(testPath, testPing.toByteArray(), emptyMap()) assertEquals( Pair(ConceptFetchHttpUploader.DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS), @@ -88,8 +85,7 @@ class ConceptFetchHttpUploaderTest { ) val uploader = ConceptFetchHttpUploader(lazy { mockClient }) - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = testPath, data = testPing.toByteArray(), expectedHeaders, emptyList())) - uploader.upload(uploadRequest) + uploader.upload(testPath, testPing.toByteArray(), expectedHeaders) val requestCaptor = argumentCaptor() verify(mockClient).fetch(requestCaptor.capture()) @@ -106,8 +102,7 @@ class ConceptFetchHttpUploaderTest { val uploader = spy(ConceptFetchHttpUploader(lazy { HttpURLConnectionClient() })) - val uploadRequest = PingUploadRequest(url = testPath, data = testPing.toByteArray(), emptyMap(), emptyList()) - val request = uploader.buildRequest(uploadRequest) + val request = uploader.buildRequest(testPath, testPing.toByteArray(), emptyMap()) assertEquals(request.cookiePolicy, Request.CookiePolicy.OMIT) } @@ -126,8 +121,7 @@ class ConceptFetchHttpUploaderTest { val uploader = spy(ConceptFetchHttpUploader(lazy { mockClient })) - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = testPath, data = testPing.toByteArray(), emptyMap(), emptyList())) - assertEquals(HttpStatus(200), uploader.upload(uploadRequest)) + assertEquals(HttpStatus(200), uploader.upload(testPath, testPing.toByteArray(), emptyMap())) } @Test @@ -145,8 +139,7 @@ class ConceptFetchHttpUploaderTest { val uploader = spy(ConceptFetchHttpUploader(lazy { mockClient })) - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = testPath, data = testPing.toByteArray(), emptyMap(), emptyList())) - assertEquals(HttpStatus(responseCode), uploader.upload(uploadRequest)) + assertEquals(HttpStatus(responseCode), uploader.upload(testPath, testPing.toByteArray(), emptyMap())) } } @@ -165,8 +158,7 @@ class ConceptFetchHttpUploaderTest { val uploader = spy(ConceptFetchHttpUploader(lazy { mockClient })) - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = testPath, data = testPing.toByteArray(), emptyMap(), emptyList())) - assertEquals(HttpStatus(responseCode), uploader.upload(uploadRequest)) + assertEquals(HttpStatus(responseCode), uploader.upload(testPath, testPing.toByteArray(), emptyMap())) } } @@ -185,8 +177,7 @@ class ConceptFetchHttpUploaderTest { val uploader = spy(ConceptFetchHttpUploader(lazy { mockClient })) - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = testPath, data = testPing.toByteArray(), emptyMap(), emptyList())) - assertEquals(HttpStatus(responseCode), uploader.upload(uploadRequest)) + assertEquals(HttpStatus(responseCode), uploader.upload(testPath, testPing.toByteArray(), emptyMap())) } } @@ -197,8 +188,7 @@ class ConceptFetchHttpUploaderTest { val client = ConceptFetchHttpUploader(lazy { HttpURLConnectionClient() }) val submissionUrl = "http://" + server.hostName + ":" + server.port + testPath - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = submissionUrl, data = testPing.toByteArray(), mapOf("test" to "header"), emptyList())) - assertEquals(HttpStatus(200), client.upload(uploadRequest)) + assertEquals(HttpStatus(200), client.upload(submissionUrl, testPing.toByteArray(), mapOf("test" to "header"))) val request = server.takeRequest() assertEquals(testPath, request.path) @@ -216,8 +206,7 @@ class ConceptFetchHttpUploaderTest { val client = ConceptFetchHttpUploader(lazy { HttpURLConnectionClient() }) val submissionUrl = "http://" + server.hostName + ":" + server.port + testPath - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = submissionUrl, data = testPing.toByteArray(), mapOf("test" to "header"), emptyList())) - assertEquals(HttpStatus(200), client.upload(uploadRequest)) + assertEquals(HttpStatus(200), client.upload(submissionUrl, testPing.toByteArray(), mapOf("test" to "header"))) val request = server.takeRequest() assertEquals(testPath, request.path) @@ -236,8 +225,7 @@ class ConceptFetchHttpUploaderTest { val client = ConceptFetchHttpUploader(lazy { OkHttpClient() }) val submissionUrl = "http://" + server.hostName + ":" + server.port + testPath - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = submissionUrl, data = testPing.toByteArray(), mapOf("test" to "header"), emptyList())) - assertEquals(HttpStatus(200), client.upload(uploadRequest)) + assertEquals(HttpStatus(200), client.upload(submissionUrl, testPing.toByteArray(), mapOf("test" to "header"))) val request = server.takeRequest() assertEquals(testPath, request.path) @@ -286,8 +274,7 @@ class ConceptFetchHttpUploaderTest { // Trigger the connection. val client = ConceptFetchHttpUploader(lazy { HttpURLConnectionClient() }) val submissionUrl = testConfig.serverEndpoint + testPath - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = submissionUrl, data = testPing.toByteArray(), emptyMap(), emptyList())) - assertEquals(HttpStatus(200), client.upload(uploadRequest)) + assertEquals(HttpStatus(200), client.upload(submissionUrl, testPing.toByteArray(), emptyMap())) val request = server.takeRequest() assertEquals(testPath, request.path) @@ -311,8 +298,7 @@ class ConceptFetchHttpUploaderTest { // And IOException during upload is a failed upload that we should retry. The client should // return false in this case. - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = "path", data = "ping".toByteArray(), emptyMap(), emptyList())) - assertEquals(RecoverableFailure(0), uploader.upload(uploadRequest)) + assertEquals(RecoverableFailure(0), uploader.upload("path", "ping".toByteArray(), emptyMap())) } @Test @@ -325,8 +311,7 @@ class ConceptFetchHttpUploaderTest { assertFalse(uploader.client.isInitialized()) // After calling upload, the client must get instantiated. - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = "path", data = "ping".toByteArray(), emptyMap(), emptyList())) - uploader.upload(uploadRequest) + uploader.upload("path", "ping".toByteArray(), emptyMap()) assertTrue(uploader.client.isInitialized()) } @@ -344,8 +329,7 @@ class ConceptFetchHttpUploaderTest { ) val uploader = ConceptFetchHttpUploader(lazy { mockClient }, true) - val uploadRequest = CapablePingUploadRequest(PingUploadRequest(url = "path", data = "ping".toByteArray(), expectedHeaders, emptyList())) - uploader.upload(uploadRequest) + uploader.upload(testPath, testPing.toByteArray(), expectedHeaders) val captor = argumentCaptor() diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt b/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt index ab4337a4b1be..f00387822598 100644 --- a/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt +++ b/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // These lines are generated by android-components/automation/application-services-nightly-bump.py -val VERSION = "138.20250327164940" +val VERSION = "138.20250325050356" val CHANNEL = ApplicationServicesChannel.NIGHTLY object ApplicationServicesConfig { diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml b/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml index 731e2d60aca4..058bde214b89 100644 --- a/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml +++ b/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml @@ -31,11 +31,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: 8e84c588a5cc2686973c5026ecd240d6275d7e94 (2025-03-27T16:49:40). + release: 093c4f261a91b2a7d6f52da4f79bef19f61456fb (2025-03-25T05:03:56). # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: 8e84c588a5cc2686973c5026ecd240d6275d7e94 + revision: 093c4f261a91b2a7d6f52da4f79bef19f61456fb # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ diff --git a/python/sites/mach.txt b/python/sites/mach.txt index d213369aa7fc..6e3db1c848f7 100644 --- a/python/sites/mach.txt +++ b/python/sites/mach.txt @@ -104,7 +104,7 @@ vendored:third_party/python/wheel vendored:third_party/python/zipp # glean-sdk may not be installable if a wheel isn't available # and it has to be built from source. -pypi-optional:glean-sdk==64.0.0:telemetry will not be collected +pypi-optional:glean-sdk==63.1.0:telemetry will not be collected # Mach gracefully handles the case where `psutil` is unavailable. # We aren't (yet) able to pin packages in automation, so we have to # support down to the oldest locally-installed version (5.4.2). diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index 4c4d85ee2b48..5f1c993baf44 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -531,13 +531,6 @@ start = "2023-06-21" end = "2026-02-01" notes = "Maintained by the Glean and Application Services teams" -[[wildcard-audits.uniffi_internal_macros]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 111105 -start = "2025-03-18" -end = "2026-03-25" - [[wildcard-audits.uniffi_macros]] who = "Ben Dean-Kawamura " criteria = "safe-to-deploy" @@ -6311,6 +6304,12 @@ non-1-byte-aligned type, however right now that is not the case (submitted https://github.com/zip-rs/zip2/issues/198). """ +[[audits.zlib-rs]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.2.1 -> 0.2.1@git:4aa430ccb77537d0d60dab8db993ca51bb1194c5" +importable = false + [[trusted.aho-corasick]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 9a0130747757..d507a95ed1ba 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -297,6 +297,14 @@ criteria = "safe-to-deploy" version = "0.2.0" criteria = "safe-to-deploy" +[[exemptions.askama_derive]] +version = "0.11.2" +criteria = "safe-to-deploy" + +[[exemptions.askama_escape]] +version = "0.10.3" +criteria = "safe-to-deploy" + [[exemptions.async-task]] version = "4.0.3" criteria = "safe-to-deploy" @@ -518,6 +526,10 @@ criteria = "safe-to-deploy" version = "0.10.3" criteria = "safe-to-deploy" +[[exemptions.khronos-egl]] +version = "4.1.0" +criteria = "safe-to-deploy" + [[exemptions.khronos_api]] version = "3.1.0" criteria = "safe-to-deploy" @@ -630,6 +642,10 @@ criteria = "safe-to-deploy" version = "1.2.3" criteria = "safe-to-deploy" +[[exemptions.rand]] +version = "0.8.5" +criteria = "safe-to-deploy" + [[exemptions.remove_dir_all]] version = "0.5.3" criteria = "safe-to-deploy" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index bdaaaaef168e..c754509e2e1c 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -258,15 +258,15 @@ user-login = "jrmuizel" user-name = "Jeff Muizelaar" [[publisher.glean]] -version = "64.0.0" -when = "2025-03-18" +version = "63.1.0" +when = "2025-01-30" user-id = 48 user-login = "badboy" user-name = "Jan-Erik Rediger" [[publisher.glean-core]] -version = "64.0.0" -when = "2025-03-18" +version = "63.1.0" +when = "2025-01-30" user-id = 48 user-login = "badboy" user-name = "Jan-Erik Rediger" @@ -335,8 +335,8 @@ user-login = "carllerche" user-name = "Carl Lerche" [[publisher.itoa]] -version = "1.0.11" -when = "2024-03-26" +version = "1.0.5" +when = "2022-12-17" user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" @@ -704,63 +704,63 @@ user-login = "dtolnay" user-name = "David Tolnay" [[publisher.unicode-width]] -version = "0.2.0" -when = "2024-09-19" +version = "0.1.10" +when = "2022-09-13" user-id = 1139 user-login = "Manishearth" user-name = "Manish Goregaokar" [[publisher.uniffi]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_bindgen]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_build]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" +user-id = 127697 +user-login = "bendk" + +[[publisher.uniffi_checksum_derive]] +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_core]] -version = "0.29.0" -when = "2025-02-06" -user-id = 127697 -user-login = "bendk" - -[[publisher.uniffi_internal_macros]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_macros]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_meta]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_testing]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" [[publisher.uniffi_udl]] -version = "0.29.0" -when = "2025-02-06" +version = "0.28.2" +when = "2024-10-08" user-id = 127697 user-login = "bendk" @@ -1203,11 +1203,6 @@ crate is broadly used throughout the ecosystem and does not contain anything suspicious. """ -[[audits.bytecode-alliance.audits.itoa]] -who = "Dan Gohman " -criteria = "safe-to-deploy" -delta = "1.0.11 -> 1.0.14" - [[audits.bytecode-alliance.audits.jobserver]] who = "Alex Crichton " criteria = "safe-to-deploy" @@ -1550,13 +1545,6 @@ criteria = "safe-to-run" version = "0.14.20" aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" -[[audits.google.audits.itoa]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "1.0.14 -> 1.0.15" -notes = "Only minor rustdoc changes." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - [[audits.google.audits.nom]] who = "danakj@chromium.org" criteria = "safe-to-deploy" @@ -1611,15 +1599,6 @@ Config-related changes in `test_size.rs`. """ aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" -[[audits.google.audits.rand]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "0.8.5" -notes = """ -For more detailed unsafe review notes please see https://crrev.com/c/6362797 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - [[audits.google.audits.rustversion]] who = "Lukasz Anforowicz " criteria = "safe-to-deploy" @@ -1971,14 +1950,6 @@ who = "Ameer Ghani " criteria = "safe-to-deploy" delta = "0.4.1 -> 0.4.2" -[[audits.mozilla.wildcard-audits.uniffi_internal_macros]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -user-id = 127697 # bendk -start = "2025-02-06" -end = "2026-03-14" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - [[audits.mozilla.wildcard-audits.weedle2]] who = "Jan-Erik Rediger " criteria = "safe-to-deploy" @@ -1997,6 +1968,20 @@ end = "2025-08-05" notes = "Maintained by me" aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" +[[audits.mozilla.audits.askama]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "0.11.1 -> 0.12.0" +notes = "No new unsafe usage, mostly dependency updates and smaller API changes" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.askama_derive]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "0.11.2 -> 0.12.1" +notes = "Dependency updates, a new toml dependency and some API changes. No unsafe use." +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + [[audits.mozilla.audits.basic-toml]] who = "Jan-Erik Rediger " criteria = "safe-to-deploy" diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/AUTHORS.md b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/AUTHORS.md similarity index 100% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/AUTHORS.md rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/AUTHORS.md diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/LICENSE b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/LICENSE similarity index 100% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/LICENSE rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/LICENSE diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/METADATA b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/METADATA similarity index 99% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/METADATA rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/METADATA index d85a935efa81..f25f155908a6 100644 --- a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/METADATA +++ b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: glean_parser -Version: 17.0.1 +Version: 16.2.0 Summary: Parser tools for Mozilla's Glean telemetry Home-page: https://github.com/mozilla/glean_parser Author: The Glean Team @@ -79,14 +79,6 @@ $ glean_parser check < ping.json ## Unreleased -## 17.0.1 - -- BUGFIX: Fix missing `ping_arg` "`uploader_capabilities`" in util.py ([#786](https://github.com/mozilla/glean_parser/pull/786)) - -## 17.0.0 - -- BREAKING CHANGE: Support `uploader_capabilities` for pings ([bug 1920732](https://bugzilla.mozilla.org/show_bug.cgi?id=1920732)) - ## 16.2.0 - New lint: error when there are metrics whose names are too similar ([bug 1934099](https://bugzilla.mozilla.org/show_bug.cgi?id=1934099)) diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/RECORD b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/RECORD similarity index 79% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/RECORD rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/RECORD index f5c5be12b7d9..5e5a6212f1d1 100644 --- a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/RECORD +++ b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/RECORD @@ -10,7 +10,7 @@ glean_parser/lint.py,sha256=ktdkR2GjR0wuR4IpLTiZ-q17vI4dk_Nebp4XU3pqzsk,21103 glean_parser/markdown.py,sha256=GkCr1CrV6mnRQseT6FO1-JJ7Eup8X3lxUfRMBTxXpe4,9066 glean_parser/metrics.py,sha256=3_ERPI63CsH_QvXVKNBVKIQTv4KWir2SfSbtn6J8a9Q,15842 glean_parser/parser.py,sha256=3bJwUGYhnzIHYJ7UBdO63Oi0_n1_Twvr2IOUUe_koME,18132 -glean_parser/pings.py,sha256=l4hKmnKigS46vlHFI4aWueKVHcZQL36QfhK0VC8OiFA,3924 +glean_parser/pings.py,sha256=xUgAunjluLbdLtcSQiUL6HDO5aLYM75MAoIT9H8-lOY,3729 glean_parser/python_server.py,sha256=ERpYcbSwF19xKFagxX0mZAvlR1y6D7Ah5DSvW8LipCY,4791 glean_parser/ruby_server.py,sha256=e5lkfcLQAUMUBQDCjqNU82LkdUzT5x-G6HOnsUInbsU,5190 glean_parser/rust.py,sha256=u1IeluyxFj6NrZZrBQwwa0nWz0TABv93lYxVBx0aN3I,7334 @@ -19,12 +19,12 @@ glean_parser/swift.py,sha256=paUzF6tItdktFwIQYCKsYpqXfn8zxR2coU_jMYrmwlc,8957 glean_parser/tags.py,sha256=bemKYvcbMO4JrghiNSe-A4BNNDtx_FlUPkgrPPJy84Y,1391 glean_parser/translate.py,sha256=itObn41X63koLYjdppLiywIFzPWDvPEx7C13efWpDSE,8444 glean_parser/translation_options.py,sha256=Lxzr6G7MP0tC_ZYlZXftS4j0SLiqO-5mGVTEc7ggXis,2037 -glean_parser/util.py,sha256=yTx_-Q8w8rNNSZ_xbno0B90WR7pZZptG2bUWU0sCHZk,16580 +glean_parser/util.py,sha256=YigUFMhzbXucNx3_bU-SAFWSnnyKS73pQWMBqxRGNn8,16551 glean_parser/validate_ping.py,sha256=0TNvILH6dtzJDys3W8Kqorw6kk03me73OCUDtpoHcXU,2118 glean_parser/schemas/metrics.1-0-0.schema.yaml,sha256=cND3cvi6iBfPUVmtfIBQfGJV9AALpbvN7nu8E33_J-o,19566 glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=ieFMxezBuySCvUorx8eGqXRUcoeTql4Z9FxkbkG9XFQ,26715 glean_parser/schemas/pings.1-0-0.schema.yaml,sha256=hwCnsKpEysmrmVp-QHGBArEkVY3vaU1rVsxlTwhAzws,4315 -glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=FQBsEt8Eg_ypBUnhJ1THZWXIgtuiYfyXcp_J9pGJUnE,7001 +glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=5k_OKfNkxHed4j1kMFGkxW1yDpvkqst-Vogig_W_JJU,6420 glean_parser/schemas/tags.1-0-0.schema.yaml,sha256=OGXIJlvvVW1vaqB_NVZnwKeZ-sLlfH57vjBSHbj6DNI,1231 glean_parser/templates/data_review.jinja2,sha256=jeYU29T1zLSyu9fKBBFu5BFPfIw8_hmOUXw8RXhRXK8,3287 glean_parser/templates/go_server.jinja2,sha256=t9ZS5AF5JwoVExkSxDoRQdBoTQv1bchJ7oTRB9eP5FI,9241 @@ -37,13 +37,13 @@ glean_parser/templates/markdown.jinja2,sha256=vAHHGGm28HRDPd3zO_wQMAUZIuxE9uQ7hl glean_parser/templates/python_server.jinja2,sha256=gu2C1rkn760IqBCG2SWaK7o32T1ify94wDEsudLPUg8,7260 glean_parser/templates/qmldir.jinja2,sha256=m6IGsp-tgTiOfQ7VN8XW6GqX0gJqJkt3B6Pkaul6FVo,156 glean_parser/templates/ruby_server.jinja2,sha256=B0pbuld3j_0s7uMjoaCo8_6ehJUZeTXZlZZ9QRS4J_8,6252 -glean_parser/templates/rust.jinja2,sha256=hX8p5HXQNEeVz_sF6SDIyUNus6CcaCG9KWLl6uQLiOU,7285 +glean_parser/templates/rust.jinja2,sha256=mdYEsldHLMb2Hkzly-NJzkFINg7qMZo7MjDI_2ZqS3U,7247 glean_parser/templates/rust_server.jinja2,sha256=JJdeU5jiWx9aWpF0qiXIYztJ14OQKxV3VFdAbCrtR_0,12841 -glean_parser/templates/swift.jinja2,sha256=L_JpwGLVzmOf1FYLoCzFu_RnGTExCIDup7iR1tWzD3o,6912 -glean_parser-17.0.1.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455 -glean_parser-17.0.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725 -glean_parser-17.0.1.dist-info/METADATA,sha256=fX3p807Z0tgo8pjTGNX4Fxw3gPXT6dJrW_Cw7lnAE_4,36761 -glean_parser-17.0.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91 -glean_parser-17.0.1.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68 -glean_parser-17.0.1.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13 -glean_parser-17.0.1.dist-info/RECORD,, +glean_parser/templates/swift.jinja2,sha256=EAenC__ReGA2A4tn-ui3n849PVHxE5IndXUivXDh8AU,6841 +glean_parser-16.2.0.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455 +glean_parser-16.2.0.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725 +glean_parser-16.2.0.dist-info/METADATA,sha256=rY8wmuwWXN1DnL3-VguHQr08H2WUoNlzvPgrfYIkVkU,36477 +glean_parser-16.2.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91 +glean_parser-16.2.0.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68 +glean_parser-16.2.0.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13 +glean_parser-16.2.0.dist-info/RECORD,, diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/WHEEL b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/WHEEL similarity index 100% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/WHEEL rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/WHEEL diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/entry_points.txt b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/entry_points.txt similarity index 100% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/entry_points.txt rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/entry_points.txt diff --git a/third_party/python/glean_parser/glean_parser-17.0.1.dist-info/top_level.txt b/third_party/python/glean_parser/glean_parser-16.2.0.dist-info/top_level.txt similarity index 100% rename from third_party/python/glean_parser/glean_parser-17.0.1.dist-info/top_level.txt rename to third_party/python/glean_parser/glean_parser-16.2.0.dist-info/top_level.txt diff --git a/third_party/python/glean_parser/glean_parser/pings.py b/third_party/python/glean_parser/glean_parser/pings.py index 5091940332df..f773c4ef9e8c 100644 --- a/third_party/python/glean_parser/glean_parser/pings.py +++ b/third_party/python/glean_parser/glean_parser/pings.py @@ -26,7 +26,6 @@ class Ping: notification_emails: List[str], metadata: Optional[Dict] = None, data_reviews: Optional[List[str]] = None, - uploader_capabilities: Optional[List[str]] = None, include_client_id: bool = False, send_if_empty: bool = False, reasons: Optional[Dict[str, str]] = None, @@ -58,9 +57,6 @@ class Ping: if data_reviews is None: data_reviews = [] self.data_reviews = data_reviews - if not uploader_capabilities: - uploader_capabilities = [] - self.uploader_capabilities = uploader_capabilities self.include_client_id = include_client_id self.send_if_empty = send_if_empty if reasons is None: diff --git a/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml b/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml index 8b45b7b773dd..91d1efc44192 100644 --- a/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml +++ b/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml @@ -127,21 +127,6 @@ additionalProperties: only takes effect when `metadata.include_info_sections` is `true`. type: boolean - uploader_capabilities: - title: Uploader Capabilities - description: | - **Optional.** - - An optional list of capability strings that the ping uploader must be - capable of supporting in order to upload this ping. - These are supplied exactly as defined (including order) to the uploader - every time upload is attempted for this ping. - The uploader must only attempt upload if it satisfies the supplied - capabilities. If not, it must refuse to upload the ping. - type: [array, "null"] - items: - type: string - send_if_empty: title: Send if empty description: | diff --git a/third_party/python/glean_parser/glean_parser/templates/rust.jinja2 b/third_party/python/glean_parser/glean_parser/templates/rust.jinja2 index d209c6ccabcc..59ff21cd1134 100644 --- a/third_party/python/glean_parser/glean_parser/templates/rust.jinja2 +++ b/third_party/python/glean_parser/glean_parser/templates/rust.jinja2 @@ -97,7 +97,7 @@ CommonMetricData { /// {{ obj.description|wordwrap() | replace('\n', '\n/// ') }} #[rustfmt::skip] pub static {{ obj.name|snake_case }}: ::glean::private::__export::Lazy<::glean::private::PingType> = - ::glean::private::__export::Lazy::new(|| ::glean::private::PingType::new("{{ obj.name }}", {{ obj.include_client_id|rust }}, {{ obj.send_if_empty|rust }}, {{ obj.precise_timestamps|rust }}, {{ obj.include_info_sections|rust }}, {{ obj.enabled|rust }}, {{ obj.schedules_pings|rust }}, {{ obj.reason_codes|rust }}, {{ obj.follows_collection_enabled|rust }}, {{ obj.uploader_capabilities|rust }})); + ::glean::private::__export::Lazy::new(|| ::glean::private::PingType::new("{{ obj.name }}", {{ obj.include_client_id|rust }}, {{ obj.send_if_empty|rust }}, {{ obj.precise_timestamps|rust }}, {{ obj.include_info_sections|rust }}, {{ obj.enabled|rust }}, {{ obj.schedules_pings|rust }}, {{ obj.reason_codes|rust }}, {{ obj.follows_collection_enabled|rust }})); {% endfor %} {% else %} pub mod {{ category.name|snake_case }} { diff --git a/third_party/python/glean_parser/glean_parser/templates/swift.jinja2 b/third_party/python/glean_parser/glean_parser/templates/swift.jinja2 index ea079f28cd6a..6dc364d4cd7c 100644 --- a/third_party/python/glean_parser/glean_parser/templates/swift.jinja2 +++ b/third_party/python/glean_parser/glean_parser/templates/swift.jinja2 @@ -144,8 +144,7 @@ extension {{ namespace }} { enabled: {{obj.enabled|swift}}, schedulesPings: {{obj.schedules_pings|swift}}, reasonCodes: {{obj.reason_codes|swift}}, - followsCollectionEnabled: {{obj.follows_collection_enabled|swift}}, - uploaderCapabilities: {{obj.uploader_capabilities|swift}} + followsCollectionEnabled: {{obj.follows_collection_enabled|swift}} ) {% endfor %} diff --git a/third_party/python/glean_parser/glean_parser/util.py b/third_party/python/glean_parser/glean_parser/util.py index 561b3932d979..88d624dd10e2 100644 --- a/third_party/python/glean_parser/glean_parser/util.py +++ b/third_party/python/glean_parser/glean_parser/util.py @@ -546,7 +546,6 @@ ping_args = [ "schedules_pings", "reason_codes", "follows_collection_enabled", - "uploader_capabilities", ] diff --git a/third_party/python/pyproject.toml b/third_party/python/pyproject.toml index 489a71851a3f..cef837bb0726 100644 --- a/third_party/python/pyproject.toml +++ b/third_party/python/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "filelock~=3.6", "fluent-migrate==0.13.2", "fluent-syntax==0.19.0", - "glean-parser==17.0.1", + "glean-parser==16.2.0", "importlib-metadata==6.0.0", # Required for compatibility with Flask >= 2 in tools/tryselect/selectors/chooser "jinja2==3.1.2", diff --git a/third_party/python/requirements.txt b/third_party/python/requirements.txt index 0b98e3099cc5..5b668c5429cc 100644 --- a/third_party/python/requirements.txt +++ b/third_party/python/requirements.txt @@ -358,9 +358,9 @@ gitignorant==0.3.1 \ giturlparse==0.12.0 \ --hash=sha256:c0fff7c21acc435491b1779566e038757a205c1ffdcb47e4f81ea52ad8c3859a \ --hash=sha256:412b74f2855f1da2fefa89fd8dde62df48476077a72fc19b62039554d27360eb -glean-parser==17.0.1 \ - --hash=sha256:764a3b5aaa22d6100100d97a6ce58515687f4e0d06660180024e3101a507f580 \ - --hash=sha256:922b75be353461875802a50dfd052215414dbc2965d153b95ff31d85081c40b7 +glean-parser==16.2.0 \ + --hash=sha256:4f6794b41b6e69cbceaee2a5b835a74cdfe443d1fbf4e2656ac40ba72cc27458 \ + --hash=sha256:dc521d87b6d9c04f2006509be0aa2cdf0e923338521d9acad221d4e23caaace8 idna==3.10 \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 diff --git a/third_party/python/uv.lock b/third_party/python/uv.lock index 506c752a66fa..c6880d1bebbd 100644 --- a/third_party/python/uv.lock +++ b/third_party/python/uv.lock @@ -598,7 +598,7 @@ wheels = [ [[package]] name = "glean-parser" -version = "17.0.1" +version = "16.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -608,9 +608,9 @@ dependencies = [ { name = "platformdirs" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/fd/895160c0fbc1ced0803bd19a2c2473f537efd8e6afa38aae2af12d5535b9/glean_parser-17.0.1.tar.gz", hash = "sha256:764a3b5aaa22d6100100d97a6ce58515687f4e0d06660180024e3101a507f580", size = 290273 } +sdist = { url = "https://files.pythonhosted.org/packages/88/74/c9d3ca070ca08399b5ee32d4f85adab9fe95faf44785655fbd283c20f4cb/glean_parser-16.2.0.tar.gz", hash = "sha256:4f6794b41b6e69cbceaee2a5b835a74cdfe443d1fbf4e2656ac40ba72cc27458", size = 289721 } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/02/dcc2f155ef74fb2c83d51b7170236f4648adb49f645bac4e5786dc3ac77c/glean_parser-17.0.1-py3-none-any.whl", hash = "sha256:922b75be353461875802a50dfd052215414dbc2965d153b95ff31d85081c40b7", size = 124106 }, + { url = "https://files.pythonhosted.org/packages/7c/2b/b7cedca86929673c89f4350e257ab720a6ea014a684b99c2814ad279b716/glean_parser-16.2.0-py3-none-any.whl", hash = "sha256:dc521d87b6d9c04f2006509be0aa2cdf0e923338521d9acad221d4e23caaace8", size = 123785 }, ] [[package]] @@ -925,7 +925,7 @@ requires-dist = [ { name = "filelock", specifier = "~=3.6" }, { name = "fluent-migrate", specifier = "==0.13.2" }, { name = "fluent-syntax", specifier = "==0.19.0" }, - { name = "glean-parser", specifier = "==17.0.1" }, + { name = "glean-parser", specifier = "==16.2.0" }, { name = "importlib-metadata", specifier = "==6.0.0" }, { name = "jinja2", specifier = "==3.1.2" }, { name = "jsmin", specifier = "==3.0.0" }, diff --git a/third_party/python/uv.lock.hash b/third_party/python/uv.lock.hash index 54259ca4172b..c69b48504c75 100644 --- a/third_party/python/uv.lock.hash +++ b/third_party/python/uv.lock.hash @@ -1 +1 @@ -6811e7a47781ee2d8b491fa59de0ad7a40375d04beeab0f203d5e423f0db5e48 \ No newline at end of file +dafec412f602d87682118ce75e91a25ed9ad9d9841b6667a3e9727dad246839b \ No newline at end of file diff --git a/third_party/rust/askama/.cargo-checksum.json b/third_party/rust/askama/.cargo-checksum.json new file mode 100644 index 000000000000..889c533360bb --- /dev/null +++ b/third_party/rust/askama/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"fbab611fc3ba2204942300a534b4f030460f33b0606fa50b9ad08ea567ba81e8","LICENSE-APACHE":"87cb0d734c723c083e51c825930ff42bce28596b52dee15567f6b28f19c195e3","LICENSE-MIT":"df20e0180764bf5bd76f74d47bc9e8c0069a666401629c390003a1d5eba99c92","README.md":"6a4430cf614ff9d36ba01463a8f94085ed4b0889fd719793fa914568247acce2","src/error.rs":"1e3f8020092469090f314f60685c077347e730a88222dfdaa38aaf2396507532","src/filters/json.rs":"dccd0a3f1017da9f6cd9650bd39eb1670f4a9833d2f0968614cd8cd65d18a9dd","src/filters/mod.rs":"903d09599e62f56657b00b2aa577c9d2f963348dd12a1029e90e68549f78b1db","src/filters/yaml.rs":"4e641bedbe3666b334836fb6603fe7f718f7e90d8e33419acca624f50a580c3f","src/helpers.rs":"76e0422acd4ccba7b1735d6ab7622a93f6ec5a2fa89531111d877266784d5334","src/lib.rs":"3a6e4d0b3aadc7c391cbe59416504a719406303726122779281a3af1a7ad76a4"},"package":"47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e"} \ No newline at end of file diff --git a/third_party/rust/askama/Cargo.toml b/third_party/rust/askama/Cargo.toml new file mode 100644 index 000000000000..15129d2dd260 --- /dev/null +++ b/third_party/rust/askama/Cargo.toml @@ -0,0 +1,126 @@ +# 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.58" +name = "askama" +version = "0.12.0" +description = "Type-safe, compiled Jinja-like templates for Rust" +homepage = "https://github.com/djc/askama" +documentation = "https://docs.rs/askama" +readme = "README.md" +keywords = [ + "markup", + "template", + "jinja2", + "html", +] +categories = ["template-engine"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/djc/askama" +resolver = "1" + +[package.metadata.docs.rs] +features = [ + "config", + "humansize", + "num-traits", + "serde-json", + "serde-yaml", +] + +[dependencies.askama_derive] +version = "0.12.0" + +[dependencies.askama_escape] +version = "0.10.3" + +[dependencies.comrak] +version = "0.16" +optional = true +default-features = false + +[dependencies.dep_humansize] +version = "2" +optional = true +package = "humansize" + +[dependencies.dep_num_traits] +version = "0.2.6" +optional = true +package = "num-traits" + +[dependencies.percent-encoding] +version = "2.1.0" +optional = true + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[dependencies.serde_json] +version = "1.0" +optional = true + +[dependencies.serde_yaml] +version = "0.9" +optional = true + +[features] +config = ["askama_derive/config"] +default = [ + "config", + "humansize", + "num-traits", + "urlencode", +] +humansize = [ + "askama_derive/humansize", + "dep_humansize", +] +markdown = [ + "askama_derive/markdown", + "comrak", +] +mime = [] +mime_guess = [] +num-traits = [ + "askama_derive/num-traits", + "dep_num_traits", +] +serde-json = [ + "askama_derive/serde-json", + "askama_escape/json", + "serde", + "serde_json", +] +serde-yaml = [ + "askama_derive/serde-yaml", + "serde", + "serde_yaml", +] +urlencode = [ + "askama_derive/urlencode", + "percent-encoding", +] +with-actix-web = ["askama_derive/with-actix-web"] +with-axum = ["askama_derive/with-axum"] +with-gotham = ["askama_derive/with-gotham"] +with-hyper = ["askama_derive/with-hyper"] +with-mendes = ["askama_derive/with-mendes"] +with-rocket = ["askama_derive/with-rocket"] +with-tide = ["askama_derive/with-tide"] +with-warp = ["askama_derive/with-warp"] + +[badges.maintenance] +status = "actively-developed" diff --git a/third_party/rust/rinja/LICENSE-APACHE b/third_party/rust/askama/LICENSE-APACHE similarity index 100% rename from third_party/rust/rinja/LICENSE-APACHE rename to third_party/rust/askama/LICENSE-APACHE diff --git a/third_party/rust/rinja/LICENSE-MIT b/third_party/rust/askama/LICENSE-MIT similarity index 100% rename from third_party/rust/rinja/LICENSE-MIT rename to third_party/rust/askama/LICENSE-MIT diff --git a/third_party/rust/askama/README.md b/third_party/rust/askama/README.md new file mode 100644 index 000000000000..9055004f066e --- /dev/null +++ b/third_party/rust/askama/README.md @@ -0,0 +1,96 @@ +# Askama + +[![Documentation](https://docs.rs/askama/badge.svg)](https://docs.rs/askama/) +[![Latest version](https://img.shields.io/crates/v/askama.svg)](https://crates.io/crates/askama) +[![Build Status](https://github.com/djc/askama/workflows/CI/badge.svg)](https://github.com/djc/askama/actions?query=workflow%3ACI) +[![Chat](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/djc/askama) + +Askama implements a template rendering engine based on [Jinja](https://jinja.palletsprojects.com/). +It generates Rust code from your templates at compile time +based on a user-defined `struct` to hold the template's context. +See below for an example, or read [the book][docs]. + +**"Pretty exciting. I would love to use this already."** -- +[Armin Ronacher][mitsuhiko], creator of Jinja + +All feedback welcome. Feel free to file bugs, requests for documentation and +any other feedback to the [issue tracker][issues] or [tweet me][twitter]. + +Askama was created by and is maintained by Dirkjan Ochtman. If you are in a +position to support ongoing maintenance and further development or use it +in a for-profit context, please consider supporting my open source work on +[Patreon][patreon]. + +### Feature highlights + +* Construct templates using a familiar, easy-to-use syntax +* Benefit from the safety provided by Rust's type system +* Template code is compiled into your crate for [optimal performance][benchmarks] +* Optional built-in support for Actix, Axum, Gotham, Mendes, Rocket, tide, and warp web frameworks +* Debugging features to assist you in template development +* Templates must be valid UTF-8 and produce UTF-8 when rendered +* IDE support available in [JetBrains products](https://plugins.jetbrains.com/plugin/16591-askama-template-support) +* Works on stable Rust + +### Supported in templates + +* Template inheritance +* Loops, if/else statements and include support +* Macro support +* Variables (no mutability allowed) +* Some built-in filters, and the ability to use your own +* Whitespace suppressing with '-' markers +* Opt-out HTML escaping +* Syntax customization + +[docs]: https://djc.github.io/askama/ +[fafhrd91]: https://github.com/fafhrd91 +[mitsuhiko]: http://lucumr.pocoo.org/ +[issues]: https://github.com/djc/askama/issues +[twitter]: https://twitter.com/djco/ +[patreon]: https://www.patreon.com/dochtman +[benchmarks]: https://github.com/djc/template-benchmarks-rs + + +How to get started +------------------ + +First, add the following to your crate's `Cargo.toml`: + +```toml +# in section [dependencies] +askama = "0.11.2" + +``` + +Now create a directory called `templates` in your crate root. +In it, create a file called `hello.html`, containing the following: + +``` +Hello, {{ name }}! +``` + +In any Rust file inside your crate, add the following: + +```rust +use askama::Template; // bring trait in scope + +#[derive(Template)] // this will generate the code... +#[template(path = "hello.html")] // using the template in this path, relative + // to the `templates` dir in the crate root +struct HelloTemplate<'a> { // the name of the struct can be anything + name: &'a str, // the field name should match the variable name + // in your template +} + +fn main() { + let hello = HelloTemplate { name: "world" }; // instantiate your struct + println!("{}", hello.render().unwrap()); // then render it. +} +``` + +You should now be able to compile and run this code. + +Review the [test cases] for more examples. + +[test cases]: https://github.com/djc/askama/tree/main/testing diff --git a/third_party/rust/rinja/src/error.rs b/third_party/rust/askama/src/error.rs similarity index 67% rename from third_party/rust/rinja/src/error.rs rename to third_party/rust/askama/src/error.rs index e0648394420b..406b1485a798 100644 --- a/third_party/rust/rinja/src/error.rs +++ b/third_party/rust/askama/src/error.rs @@ -1,10 +1,8 @@ -use std::convert::Infallible; use std::fmt::{self, Display}; -/// The [`Result`](std::result::Result) type with [`Error`] as default error type -pub type Result = std::result::Result; +pub type Result = ::std::result::Result; -/// rinja error type +/// askama error type /// /// # Feature Interaction /// @@ -23,25 +21,34 @@ pub type Result = std::result::Result; /// using a adapter the benefits `failure` would /// bring to this crate are small, which is why /// `std::error::Error` was used. +/// #[non_exhaustive] #[derive(Debug)] pub enum Error { /// formatting error - Fmt, + Fmt(fmt::Error), + /// an error raised by using `?` in a template Custom(Box), + /// json conversion error #[cfg(feature = "serde_json")] - Json(serde_json::Error), + Json(::serde_json::Error), + + /// yaml conversion error + #[cfg(feature = "serde_yaml")] + Yaml(::serde_yaml::Error), } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match *self { - Error::Fmt => None, + Error::Fmt(ref err) => Some(err), Error::Custom(ref err) => Some(err.as_ref()), #[cfg(feature = "serde_json")] Error::Json(ref err) => Some(err), + #[cfg(feature = "serde_yaml")] + Error::Yaml(ref err) => Some(err), } } } @@ -49,33 +56,33 @@ impl std::error::Error for Error { impl Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Error::Fmt => write!(formatter, "formatting error"), + Error::Fmt(err) => write!(formatter, "formatting error: {err}"), Error::Custom(err) => write!(formatter, "{err}"), #[cfg(feature = "serde_json")] Error::Json(err) => write!(formatter, "json conversion error: {err}"), + #[cfg(feature = "serde_yaml")] + Error::Yaml(err) => write!(formatter, "yaml conversion error: {}", err), } } } impl From for Error { - #[inline] - fn from(_: fmt::Error) -> Self { - Error::Fmt + fn from(err: fmt::Error) -> Self { + Error::Fmt(err) } } #[cfg(feature = "serde_json")] -impl From for Error { - #[inline] - fn from(err: serde_json::Error) -> Self { +impl From<::serde_json::Error> for Error { + fn from(err: ::serde_json::Error) -> Self { Error::Json(err) } } -impl From for Error { - #[inline] - fn from(value: Infallible) -> Self { - match value {} +#[cfg(feature = "serde_yaml")] +impl From<::serde_yaml::Error> for Error { + fn from(err: ::serde_yaml::Error) -> Self { + Error::Yaml(err) } } @@ -83,7 +90,6 @@ impl From for Error { mod tests { use super::Error; - #[allow(dead_code)] trait AssertSendSyncStatic: Send + Sync + 'static {} impl AssertSendSyncStatic for Error {} } diff --git a/third_party/rust/askama/src/filters/json.rs b/third_party/rust/askama/src/filters/json.rs new file mode 100644 index 000000000000..809be91b0c80 --- /dev/null +++ b/third_party/rust/askama/src/filters/json.rs @@ -0,0 +1,44 @@ +use crate::error::{Error, Result}; +use askama_escape::JsonEscapeBuffer; +use serde::Serialize; +use serde_json::to_writer_pretty; + +/// Serialize to JSON (requires `json` feature) +/// +/// The generated string does not contain ampersands `&`, chevrons `< >`, or apostrophes `'`. +/// To use it in a ` +/// ``` +/// +/// To use it in HTML attributes, you can either use it in quotation marks `"{{data|json}}"` as is, +/// or in apostrophes with the (optional) safe filter `'{{data|json|safe}}'`. +/// In HTML texts the output of e.g. `
{{data|json|safe}}
` is safe, too. +pub fn json(s: S) -> Result { + let mut writer = JsonEscapeBuffer::new(); + to_writer_pretty(&mut writer, &s).map_err(Error::from)?; + Ok(writer.finish()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_json() { + assert_eq!(json(true).unwrap(), "true"); + assert_eq!(json("foo").unwrap(), r#""foo""#); + assert_eq!(json(true).unwrap(), "true"); + assert_eq!(json("foo").unwrap(), r#""foo""#); + assert_eq!( + json(vec!["foo", "bar"]).unwrap(), + r#"[ + "foo", + "bar" +]"# + ); + } +} diff --git a/third_party/rust/askama/src/filters/mod.rs b/third_party/rust/askama/src/filters/mod.rs new file mode 100644 index 000000000000..f76a463c5d98 --- /dev/null +++ b/third_party/rust/askama/src/filters/mod.rs @@ -0,0 +1,640 @@ +//! Module for built-in filter functions +//! +//! Contains all the built-in filter functions for use in templates. +//! You can define your own filters, as well. +//! For more information, read the [book](https://djc.github.io/askama/filters.html). +#![allow(clippy::trivially_copy_pass_by_ref)] + +use std::fmt::{self, Write}; + +#[cfg(feature = "serde-json")] +mod json; +#[cfg(feature = "serde-json")] +pub use self::json::json; + +#[cfg(feature = "serde-yaml")] +mod yaml; +#[cfg(feature = "serde-yaml")] +pub use self::yaml::yaml; + +#[allow(unused_imports)] +use crate::error::Error::Fmt; +use askama_escape::{Escaper, MarkupDisplay}; +#[cfg(feature = "humansize")] +use dep_humansize::{format_size_i, ToF64, DECIMAL}; +#[cfg(feature = "num-traits")] +use dep_num_traits::{cast::NumCast, Signed}; +#[cfg(feature = "percent-encoding")] +use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC}; + +use super::Result; + +#[cfg(feature = "percent-encoding")] +// Urlencode char encoding set. Only the characters in the unreserved set don't +// have any special purpose in any part of a URI and can be safely left +// unencoded as specified in https://tools.ietf.org/html/rfc3986.html#section-2.3 +const URLENCODE_STRICT_SET: &AsciiSet = &NON_ALPHANUMERIC + .remove(b'_') + .remove(b'.') + .remove(b'-') + .remove(b'~'); + +#[cfg(feature = "percent-encoding")] +// Same as URLENCODE_STRICT_SET, but preserves forward slashes for encoding paths +const URLENCODE_SET: &AsciiSet = &URLENCODE_STRICT_SET.remove(b'/'); + +/// Marks a string (or other `Display` type) as safe +/// +/// Use this is you want to allow markup in an expression, or if you know +/// that the expression's contents don't need to be escaped. +/// +/// Askama will automatically insert the first (`Escaper`) argument, +/// so this filter only takes a single argument of any type that implements +/// `Display`. +pub fn safe(e: E, v: T) -> Result> +where + E: Escaper, + T: fmt::Display, +{ + Ok(MarkupDisplay::new_safe(v, e)) +} + +/// Escapes strings according to the escape mode. +/// +/// Askama will automatically insert the first (`Escaper`) argument, +/// so this filter only takes a single argument of any type that implements +/// `Display`. +/// +/// It is possible to optionally specify an escaper other than the default for +/// the template's extension, like `{{ val|escape("txt") }}`. +pub fn escape(e: E, v: T) -> Result> +where + E: Escaper, + T: fmt::Display, +{ + Ok(MarkupDisplay::new_unsafe(v, e)) +} + +#[cfg(feature = "humansize")] +/// Returns adequate string representation (in KB, ..) of number of bytes +pub fn filesizeformat(b: &(impl ToF64 + Copy)) -> Result { + Ok(format_size_i(*b, DECIMAL)) +} + +#[cfg(feature = "percent-encoding")] +/// Percent-encodes the argument for safe use in URI; does not encode `/`. +/// +/// This should be safe for all parts of URI (paths segments, query keys, query +/// values). In the rare case that the server can't deal with forward slashes in +/// the query string, use [`urlencode_strict`], which encodes them as well. +/// +/// Encodes all characters except ASCII letters, digits, and `_.-~/`. In other +/// words, encodes all characters which are not in the unreserved set, +/// as specified by [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.3), +/// with the exception of `/`. +/// +/// ```none,ignore +/// Station +/// Page +/// ``` +/// +/// To encode `/` as well, see [`urlencode_strict`](./fn.urlencode_strict.html). +/// +/// [`urlencode_strict`]: ./fn.urlencode_strict.html +pub fn urlencode(s: T) -> Result { + let s = s.to_string(); + Ok(utf8_percent_encode(&s, URLENCODE_SET).to_string()) +} + +#[cfg(feature = "percent-encoding")] +/// Percent-encodes the argument for safe use in URI; encodes `/`. +/// +/// Use this filter for encoding query keys and values in the rare case that +/// the server can't process them unencoded. +/// +/// Encodes all characters except ASCII letters, digits, and `_.-~`. In other +/// words, encodes all characters which are not in the unreserved set, +/// as specified by [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.3). +/// +/// ```none,ignore +/// Page +/// ``` +/// +/// If you want to preserve `/`, see [`urlencode`](./fn.urlencode.html). +pub fn urlencode_strict(s: T) -> Result { + let s = s.to_string(); + Ok(utf8_percent_encode(&s, URLENCODE_STRICT_SET).to_string()) +} + +/// Formats arguments according to the specified format +/// +/// The *second* argument to this filter must be a string literal (as in normal +/// Rust). The two arguments are passed through to the `format!()` +/// [macro](https://doc.rust-lang.org/stable/std/macro.format.html) by +/// the Askama code generator, but the order is swapped to support filter +/// composition. +/// +/// ```ignore +/// {{ value | fmt("{:?}") }} +/// ``` +/// +/// Compare with [format](./fn.format.html). +pub fn fmt() {} + +/// Formats arguments according to the specified format +/// +/// The first argument to this filter must be a string literal (as in normal +/// Rust). All arguments are passed through to the `format!()` +/// [macro](https://doc.rust-lang.org/stable/std/macro.format.html) by +/// the Askama code generator. +/// +/// ```ignore +/// {{ "{:?}{:?}" | format(value, other_value) }} +/// ``` +/// +/// Compare with [fmt](./fn.fmt.html). +pub fn format() {} + +/// Replaces line breaks in plain text with appropriate HTML +/// +/// A single newline becomes an HTML line break `
` and a new line +/// followed by a blank line becomes a paragraph break `

`. +pub fn linebreaks(s: T) -> Result { + let s = s.to_string(); + let linebroken = s.replace("\n\n", "

").replace('\n', "
"); + + Ok(format!("

{linebroken}

")) +} + +/// Converts all newlines in a piece of plain text to HTML line breaks +pub fn linebreaksbr(s: T) -> Result { + let s = s.to_string(); + Ok(s.replace('\n', "
")) +} + +/// Replaces only paragraph breaks in plain text with appropriate HTML +/// +/// A new line followed by a blank line becomes a paragraph break `

`. +/// Paragraph tags only wrap content; empty paragraphs are removed. +/// No `
` tags are added. +pub fn paragraphbreaks(s: T) -> Result { + let s = s.to_string(); + let linebroken = s.replace("\n\n", "

").replace("

", ""); + + Ok(format!("

{linebroken}

")) +} + +/// Converts to lowercase +pub fn lower(s: T) -> Result { + let s = s.to_string(); + Ok(s.to_lowercase()) +} + +/// Alias for the `lower()` filter +pub fn lowercase(s: T) -> Result { + lower(s) +} + +/// Converts to uppercase +pub fn upper(s: T) -> Result { + let s = s.to_string(); + Ok(s.to_uppercase()) +} + +/// Alias for the `upper()` filter +pub fn uppercase(s: T) -> Result { + upper(s) +} + +/// Strip leading and trailing whitespace +pub fn trim(s: T) -> Result { + let s = s.to_string(); + Ok(s.trim().to_owned()) +} + +/// Limit string length, appends '...' if truncated +pub fn truncate(s: T, len: usize) -> Result { + let mut s = s.to_string(); + if s.len() > len { + let mut real_len = len; + while !s.is_char_boundary(real_len) { + real_len += 1; + } + s.truncate(real_len); + s.push_str("..."); + } + Ok(s) +} + +/// Indent lines with `width` spaces +pub fn indent(s: T, width: usize) -> Result { + let s = s.to_string(); + + let mut indented = String::new(); + + for (i, c) in s.char_indices() { + indented.push(c); + + if c == '\n' && i < s.len() - 1 { + for _ in 0..width { + indented.push(' '); + } + } + } + + Ok(indented) +} + +#[cfg(feature = "num-traits")] +/// Casts number to f64 +pub fn into_f64(number: T) -> Result +where + T: NumCast, +{ + number.to_f64().ok_or(Fmt(fmt::Error)) +} + +#[cfg(feature = "num-traits")] +/// Casts number to isize +pub fn into_isize(number: T) -> Result +where + T: NumCast, +{ + number.to_isize().ok_or(Fmt(fmt::Error)) +} + +/// Joins iterable into a string separated by provided argument +pub fn join(input: I, separator: S) -> Result +where + T: fmt::Display, + I: Iterator, + S: AsRef, +{ + let separator: &str = separator.as_ref(); + + let mut rv = String::new(); + + for (num, item) in input.enumerate() { + if num > 0 { + rv.push_str(separator); + } + + write!(rv, "{item}")?; + } + + Ok(rv) +} + +#[cfg(feature = "num-traits")] +/// Absolute value +pub fn abs(number: T) -> Result +where + T: Signed, +{ + Ok(number.abs()) +} + +/// Capitalize a value. The first character will be uppercase, all others lowercase. +pub fn capitalize(s: T) -> Result { + let s = s.to_string(); + match s.chars().next() { + Some(c) => { + let mut replacement: String = c.to_uppercase().collect(); + replacement.push_str(&s[c.len_utf8()..].to_lowercase()); + Ok(replacement) + } + _ => Ok(s), + } +} + +/// Centers the value in a field of a given width +pub fn center(src: &dyn fmt::Display, dst_len: usize) -> Result { + let src = src.to_string(); + let len = src.len(); + + if dst_len <= len { + Ok(src) + } else { + let diff = dst_len - len; + let mid = diff / 2; + let r = diff % 2; + let mut buf = String::with_capacity(dst_len); + + for _ in 0..mid { + buf.push(' '); + } + + buf.push_str(&src); + + for _ in 0..mid + r { + buf.push(' '); + } + + Ok(buf) + } +} + +/// Count the words in that string +pub fn wordcount(s: T) -> Result { + let s = s.to_string(); + + Ok(s.split_whitespace().count()) +} + +#[cfg(feature = "markdown")] +pub fn markdown( + e: E, + s: S, + options: Option<&comrak::ComrakOptions>, +) -> Result> +where + E: Escaper, + S: AsRef, +{ + use comrak::{ + markdown_to_html, ComrakExtensionOptions, ComrakOptions, ComrakParseOptions, + ComrakRenderOptions, ListStyleType, + }; + + const DEFAULT_OPTIONS: ComrakOptions = ComrakOptions { + extension: ComrakExtensionOptions { + strikethrough: true, + tagfilter: true, + table: true, + autolink: true, + // default: + tasklist: false, + superscript: false, + header_ids: None, + footnotes: false, + description_lists: false, + front_matter_delimiter: None, + }, + parse: ComrakParseOptions { + // default: + smart: false, + default_info_string: None, + relaxed_tasklist_matching: false, + }, + render: ComrakRenderOptions { + unsafe_: false, + escape: true, + // default: + hardbreaks: false, + github_pre_lang: false, + width: 0, + list_style: ListStyleType::Dash, + }, + }; + + let s = markdown_to_html(s.as_ref(), options.unwrap_or(&DEFAULT_OPTIONS)); + Ok(MarkupDisplay::new_safe(s, e)) +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "num-traits")] + use std::f64::INFINITY; + + #[cfg(feature = "humansize")] + #[test] + fn test_filesizeformat() { + assert_eq!(filesizeformat(&0).unwrap(), "0 B"); + assert_eq!(filesizeformat(&999u64).unwrap(), "999 B"); + assert_eq!(filesizeformat(&1000i32).unwrap(), "1 kB"); + assert_eq!(filesizeformat(&1023).unwrap(), "1.02 kB"); + assert_eq!(filesizeformat(&1024usize).unwrap(), "1.02 kB"); + } + + #[cfg(feature = "percent-encoding")] + #[test] + fn test_urlencoding() { + // Unreserved (https://tools.ietf.org/html/rfc3986.html#section-2.3) + // alpha / digit + assert_eq!(urlencode("AZaz09").unwrap(), "AZaz09"); + assert_eq!(urlencode_strict("AZaz09").unwrap(), "AZaz09"); + // other + assert_eq!(urlencode("_.-~").unwrap(), "_.-~"); + assert_eq!(urlencode_strict("_.-~").unwrap(), "_.-~"); + + // Reserved (https://tools.ietf.org/html/rfc3986.html#section-2.2) + // gen-delims + assert_eq!(urlencode(":/?#[]@").unwrap(), "%3A/%3F%23%5B%5D%40"); + assert_eq!( + urlencode_strict(":/?#[]@").unwrap(), + "%3A%2F%3F%23%5B%5D%40" + ); + // sub-delims + assert_eq!( + urlencode("!$&'()*+,;=").unwrap(), + "%21%24%26%27%28%29%2A%2B%2C%3B%3D" + ); + assert_eq!( + urlencode_strict("!$&'()*+,;=").unwrap(), + "%21%24%26%27%28%29%2A%2B%2C%3B%3D" + ); + + // Other + assert_eq!( + urlencode("žŠďŤňĚáÉóŮ").unwrap(), + "%C5%BE%C5%A0%C4%8F%C5%A4%C5%88%C4%9A%C3%A1%C3%89%C3%B3%C5%AE" + ); + assert_eq!( + urlencode_strict("žŠďŤňĚáÉóŮ").unwrap(), + "%C5%BE%C5%A0%C4%8F%C5%A4%C5%88%C4%9A%C3%A1%C3%89%C3%B3%C5%AE" + ); + + // Ferris + assert_eq!(urlencode("🦀").unwrap(), "%F0%9F%A6%80"); + assert_eq!(urlencode_strict("🦀").unwrap(), "%F0%9F%A6%80"); + } + + #[test] + fn test_linebreaks() { + assert_eq!( + linebreaks("Foo\nBar Baz").unwrap(), + "

Foo
Bar Baz

" + ); + assert_eq!( + linebreaks("Foo\nBar\n\nBaz").unwrap(), + "

Foo
Bar

Baz

" + ); + } + + #[test] + fn test_linebreaksbr() { + assert_eq!(linebreaksbr("Foo\nBar").unwrap(), "Foo
Bar"); + assert_eq!( + linebreaksbr("Foo\nBar\n\nBaz").unwrap(), + "Foo
Bar

Baz" + ); + } + + #[test] + fn test_paragraphbreaks() { + assert_eq!( + paragraphbreaks("Foo\nBar Baz").unwrap(), + "

Foo\nBar Baz

" + ); + assert_eq!( + paragraphbreaks("Foo\nBar\n\nBaz").unwrap(), + "

Foo\nBar

Baz

" + ); + assert_eq!( + paragraphbreaks("Foo\n\n\n\n\nBar\n\nBaz").unwrap(), + "

Foo

\nBar

Baz

" + ); + } + + #[test] + fn test_lower() { + assert_eq!(lower("Foo").unwrap(), "foo"); + assert_eq!(lower("FOO").unwrap(), "foo"); + assert_eq!(lower("FooBar").unwrap(), "foobar"); + assert_eq!(lower("foo").unwrap(), "foo"); + } + + #[test] + fn test_upper() { + assert_eq!(upper("Foo").unwrap(), "FOO"); + assert_eq!(upper("FOO").unwrap(), "FOO"); + assert_eq!(upper("FooBar").unwrap(), "FOOBAR"); + assert_eq!(upper("foo").unwrap(), "FOO"); + } + + #[test] + fn test_trim() { + assert_eq!(trim(" Hello\tworld\t").unwrap(), "Hello\tworld"); + } + + #[test] + fn test_truncate() { + assert_eq!(truncate("hello", 2).unwrap(), "he..."); + let a = String::from("您好"); + assert_eq!(a.len(), 6); + assert_eq!(String::from("您").len(), 3); + assert_eq!(truncate("您好", 1).unwrap(), "您..."); + assert_eq!(truncate("您好", 2).unwrap(), "您..."); + assert_eq!(truncate("您好", 3).unwrap(), "您..."); + assert_eq!(truncate("您好", 4).unwrap(), "您好..."); + assert_eq!(truncate("您好", 6).unwrap(), "您好"); + assert_eq!(truncate("您好", 7).unwrap(), "您好"); + let s = String::from("🤚a🤚"); + assert_eq!(s.len(), 9); + assert_eq!(String::from("🤚").len(), 4); + assert_eq!(truncate("🤚a🤚", 1).unwrap(), "🤚..."); + assert_eq!(truncate("🤚a🤚", 2).unwrap(), "🤚..."); + assert_eq!(truncate("🤚a🤚", 3).unwrap(), "🤚..."); + assert_eq!(truncate("🤚a🤚", 4).unwrap(), "🤚..."); + assert_eq!(truncate("🤚a🤚", 5).unwrap(), "🤚a..."); + assert_eq!(truncate("🤚a🤚", 6).unwrap(), "🤚a🤚..."); + assert_eq!(truncate("🤚a🤚", 9).unwrap(), "🤚a🤚"); + assert_eq!(truncate("🤚a🤚", 10).unwrap(), "🤚a🤚"); + } + + #[test] + fn test_indent() { + assert_eq!(indent("hello", 2).unwrap(), "hello"); + assert_eq!(indent("hello\n", 2).unwrap(), "hello\n"); + assert_eq!(indent("hello\nfoo", 2).unwrap(), "hello\n foo"); + assert_eq!( + indent("hello\nfoo\n bar", 4).unwrap(), + "hello\n foo\n bar" + ); + } + + #[cfg(feature = "num-traits")] + #[test] + #[allow(clippy::float_cmp)] + fn test_into_f64() { + assert_eq!(into_f64(1).unwrap(), 1.0_f64); + assert_eq!(into_f64(1.9).unwrap(), 1.9_f64); + assert_eq!(into_f64(-1.9).unwrap(), -1.9_f64); + assert_eq!(into_f64(INFINITY as f32).unwrap(), INFINITY); + assert_eq!(into_f64(-INFINITY as f32).unwrap(), -INFINITY); + } + + #[cfg(feature = "num-traits")] + #[test] + fn test_into_isize() { + assert_eq!(into_isize(1).unwrap(), 1_isize); + assert_eq!(into_isize(1.9).unwrap(), 1_isize); + assert_eq!(into_isize(-1.9).unwrap(), -1_isize); + assert_eq!(into_isize(1.5_f64).unwrap(), 1_isize); + assert_eq!(into_isize(-1.5_f64).unwrap(), -1_isize); + match into_isize(INFINITY) { + Err(Fmt(fmt::Error)) => {} + _ => panic!("Should return error of type Err(Fmt(fmt::Error))"), + }; + } + + #[allow(clippy::needless_borrow)] + #[test] + fn test_join() { + assert_eq!( + join((&["hello", "world"]).iter(), ", ").unwrap(), + "hello, world" + ); + assert_eq!(join((&["hello"]).iter(), ", ").unwrap(), "hello"); + + let empty: &[&str] = &[]; + assert_eq!(join(empty.iter(), ", ").unwrap(), ""); + + let input: Vec = vec!["foo".into(), "bar".into(), "bazz".into()]; + assert_eq!(join(input.iter(), ":").unwrap(), "foo:bar:bazz"); + + let input: &[String] = &["foo".into(), "bar".into()]; + assert_eq!(join(input.iter(), ":").unwrap(), "foo:bar"); + + let real: String = "blah".into(); + let input: Vec<&str> = vec![&real]; + assert_eq!(join(input.iter(), ";").unwrap(), "blah"); + + assert_eq!( + join((&&&&&["foo", "bar"]).iter(), ", ").unwrap(), + "foo, bar" + ); + } + + #[cfg(feature = "num-traits")] + #[test] + #[allow(clippy::float_cmp)] + fn test_abs() { + assert_eq!(abs(1).unwrap(), 1); + assert_eq!(abs(-1).unwrap(), 1); + assert_eq!(abs(1.0).unwrap(), 1.0); + assert_eq!(abs(-1.0).unwrap(), 1.0); + assert_eq!(abs(1.0_f64).unwrap(), 1.0_f64); + assert_eq!(abs(-1.0_f64).unwrap(), 1.0_f64); + } + + #[test] + fn test_capitalize() { + assert_eq!(capitalize("foo").unwrap(), "Foo".to_string()); + assert_eq!(capitalize("f").unwrap(), "F".to_string()); + assert_eq!(capitalize("fO").unwrap(), "Fo".to_string()); + assert_eq!(capitalize("").unwrap(), "".to_string()); + assert_eq!(capitalize("FoO").unwrap(), "Foo".to_string()); + assert_eq!(capitalize("foO BAR").unwrap(), "Foo bar".to_string()); + assert_eq!(capitalize("äØÄÅÖ").unwrap(), "Äøäåö".to_string()); + assert_eq!(capitalize("ß").unwrap(), "SS".to_string()); + assert_eq!(capitalize("ßß").unwrap(), "SSß".to_string()); + } + + #[test] + fn test_center() { + assert_eq!(center(&"f", 3).unwrap(), " f ".to_string()); + assert_eq!(center(&"f", 4).unwrap(), " f ".to_string()); + assert_eq!(center(&"foo", 1).unwrap(), "foo".to_string()); + assert_eq!(center(&"foo bar", 8).unwrap(), "foo bar ".to_string()); + } + + #[test] + fn test_wordcount() { + assert_eq!(wordcount("").unwrap(), 0); + assert_eq!(wordcount(" \n\t").unwrap(), 0); + assert_eq!(wordcount("foo").unwrap(), 1); + assert_eq!(wordcount("foo bar").unwrap(), 2); + } +} diff --git a/third_party/rust/askama/src/filters/yaml.rs b/third_party/rust/askama/src/filters/yaml.rs new file mode 100644 index 000000000000..9f4c8021ce7c --- /dev/null +++ b/third_party/rust/askama/src/filters/yaml.rs @@ -0,0 +1,34 @@ +use crate::error::{Error, Result}; +use askama_escape::{Escaper, MarkupDisplay}; +use serde::Serialize; + +/// Serialize to YAML (requires `serde_yaml` feature) +/// +/// ## Errors +/// +/// This will panic if `S`'s implementation of `Serialize` decides to fail, +/// or if `T` contains a map with non-string keys. +pub fn yaml(e: E, s: S) -> Result> { + match serde_yaml::to_string(&s) { + Ok(s) => Ok(MarkupDisplay::new_safe(s, e)), + Err(e) => Err(Error::from(e)), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use askama_escape::Html; + + #[test] + fn test_yaml() { + assert_eq!(yaml(Html, true).unwrap().to_string(), "true\n"); + assert_eq!(yaml(Html, "foo").unwrap().to_string(), "foo\n"); + assert_eq!(yaml(Html, true).unwrap().to_string(), "true\n"); + assert_eq!(yaml(Html, "foo").unwrap().to_string(), "foo\n"); + assert_eq!( + yaml(Html, &vec!["foo", "bar"]).unwrap().to_string(), + "- foo\n- bar\n" + ); + } +} diff --git a/third_party/rust/askama/src/helpers.rs b/third_party/rust/askama/src/helpers.rs new file mode 100644 index 000000000000..79a1ada20691 --- /dev/null +++ b/third_party/rust/askama/src/helpers.rs @@ -0,0 +1,48 @@ +use std::iter::{Enumerate, Peekable}; + +pub struct TemplateLoop +where + I: Iterator, +{ + iter: Peekable>, +} + +impl TemplateLoop +where + I: Iterator, +{ + #[inline] + pub fn new(iter: I) -> Self { + TemplateLoop { + iter: iter.enumerate().peekable(), + } + } +} + +impl Iterator for TemplateLoop +where + I: Iterator, +{ + type Item = (::Item, LoopItem); + + #[inline] + fn next(&mut self) -> Option<(::Item, LoopItem)> { + self.iter.next().map(|(index, item)| { + ( + item, + LoopItem { + index, + first: index == 0, + last: self.iter.peek().is_none(), + }, + ) + }) + } +} + +#[derive(Copy, Clone)] +pub struct LoopItem { + pub index: usize, + pub first: bool, + pub last: bool, +} diff --git a/third_party/rust/askama/src/lib.rs b/third_party/rust/askama/src/lib.rs new file mode 100644 index 000000000000..17085b5d6322 --- /dev/null +++ b/third_party/rust/askama/src/lib.rs @@ -0,0 +1,219 @@ +//! Askama implements a type-safe compiler for Jinja-like templates. +//! It lets you write templates in a Jinja-like syntax, +//! which are linked to a `struct` defining the template context. +//! This is done using a custom derive implementation (implemented +//! in [`askama_derive`](https://crates.io/crates/askama_derive)). +//! +//! For feature highlights and a quick start, please review the +//! [README](https://github.com/djc/askama/blob/main/README.md). +//! +//! The primary documentation for this crate now lives in +//! [the book](https://djc.github.io/askama/). +//! +//! # Creating Askama templates +//! +//! An Askama template is a `struct` definition which provides the template +//! context combined with a UTF-8 encoded text file (or inline source, see +//! below). Askama can be used to generate any kind of text-based format. +//! The template file's extension may be used to provide content type hints. +//! +//! A template consists of **text contents**, which are passed through as-is, +//! **expressions**, which get replaced with content while being rendered, and +//! **tags**, which control the template's logic. +//! The template syntax is very similar to [Jinja](http://jinja.pocoo.org/), +//! as well as Jinja-derivatives like [Twig](http://twig.sensiolabs.org/) or +//! [Tera](https://github.com/Keats/tera). +//! +//! ## The `template()` attribute +//! +//! Askama works by generating one or more trait implementations for any +//! `struct` type decorated with the `#[derive(Template)]` attribute. The +//! code generation process takes some options that can be specified through +//! the `template()` attribute. The following sub-attributes are currently +//! recognized: +//! +//! * `path` (as `path = "foo.html"`): sets the path to the template file. The +//! path is interpreted as relative to the configured template directories +//! (by default, this is a `templates` directory next to your `Cargo.toml`). +//! The file name extension is used to infer an escape mode (see below). In +//! web framework integrations, the path's extension may also be used to +//! infer the content type of the resulting response. +//! Cannot be used together with `source`. +//! * `source` (as `source = "{{ foo }}"`): directly sets the template source. +//! This can be useful for test cases or short templates. The generated path +//! is undefined, which generally makes it impossible to refer to this +//! template from other templates. If `source` is specified, `ext` must also +//! be specified (see below). Cannot be used together with `path`. +//! * `ext` (as `ext = "txt"`): lets you specify the content type as a file +//! extension. This is used to infer an escape mode (see below), and some +//! web framework integrations use it to determine the content type. +//! Cannot be used together with `path`. +//! * `print` (as `print = "code"`): enable debugging by printing nothing +//! (`none`), the parsed syntax tree (`ast`), the generated code (`code`) +//! or `all` for both. The requested data will be printed to stdout at +//! compile time. +//! * `escape` (as `escape = "none"`): override the template's extension used for +//! the purpose of determining the escaper for this template. See the section +//! on configuring custom escapers for more information. +//! * `syntax` (as `syntax = "foo"`): set the syntax name for a parser defined +//! in the configuration file. The default syntax , "default", is the one +//! provided by Askama. + +#![forbid(unsafe_code)] +#![deny(elided_lifetimes_in_paths)] +#![deny(unreachable_pub)] + +mod error; +pub mod filters; +pub mod helpers; + +use std::fmt; + +pub use askama_derive::Template; +pub use askama_escape::{Html, MarkupDisplay, Text}; + +#[doc(hidden)] +pub use crate as shared; +pub use crate::error::{Error, Result}; + +/// Main `Template` trait; implementations are generally derived +/// +/// If you need an object-safe template, use [`DynTemplate`]. +pub trait Template: fmt::Display { + /// Helper method which allocates a new `String` and renders into it + fn render(&self) -> Result { + let mut buf = String::with_capacity(Self::SIZE_HINT); + self.render_into(&mut buf)?; + Ok(buf) + } + + /// Renders the template to the given `writer` fmt buffer + fn render_into(&self, writer: &mut (impl std::fmt::Write + ?Sized)) -> Result<()>; + + /// Renders the template to the given `writer` io buffer + #[inline] + fn write_into(&self, writer: &mut (impl std::io::Write + ?Sized)) -> std::io::Result<()> { + writer.write_fmt(format_args!("{self}")) + } + + /// The template's extension, if provided + const EXTENSION: Option<&'static str>; + + /// Provides a conservative estimate of the expanded length of the rendered template + const SIZE_HINT: usize; + + /// The MIME type (Content-Type) of the data that gets rendered by this Template + const MIME_TYPE: &'static str; +} + +/// Object-safe wrapper trait around [`Template`] implementers +/// +/// This trades reduced performance (mostly due to writing into `dyn Write`) for object safety. +pub trait DynTemplate { + /// Helper method which allocates a new `String` and renders into it + fn dyn_render(&self) -> Result; + + /// Renders the template to the given `writer` fmt buffer + fn dyn_render_into(&self, writer: &mut dyn std::fmt::Write) -> Result<()>; + + /// Renders the template to the given `writer` io buffer + fn dyn_write_into(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()>; + + /// Helper function to inspect the template's extension + fn extension(&self) -> Option<&'static str>; + + /// Provides a conservative estimate of the expanded length of the rendered template + fn size_hint(&self) -> usize; + + /// The MIME type (Content-Type) of the data that gets rendered by this Template + fn mime_type(&self) -> &'static str; +} + +impl DynTemplate for T { + fn dyn_render(&self) -> Result { + ::render(self) + } + + fn dyn_render_into(&self, writer: &mut dyn std::fmt::Write) -> Result<()> { + ::render_into(self, writer) + } + + #[inline] + fn dyn_write_into(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> { + writer.write_fmt(format_args!("{self}")) + } + + fn extension(&self) -> Option<&'static str> { + Self::EXTENSION + } + + fn size_hint(&self) -> usize { + Self::SIZE_HINT + } + + fn mime_type(&self) -> &'static str { + Self::MIME_TYPE + } +} + +impl fmt::Display for dyn DynTemplate { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.dyn_render_into(f).map_err(|_| ::std::fmt::Error {}) + } +} + +#[cfg(test)] +mod tests { + use std::fmt; + + use super::*; + use crate::{DynTemplate, Template}; + + #[test] + fn dyn_template() { + struct Test; + impl Template for Test { + fn render_into(&self, writer: &mut (impl std::fmt::Write + ?Sized)) -> Result<()> { + Ok(writer.write_str("test")?) + } + + const EXTENSION: Option<&'static str> = Some("txt"); + + const SIZE_HINT: usize = 4; + + const MIME_TYPE: &'static str = "text/plain; charset=utf-8"; + } + + impl fmt::Display for Test { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.render_into(f).map_err(|_| fmt::Error {}) + } + } + + fn render(t: &dyn DynTemplate) -> String { + t.dyn_render().unwrap() + } + + let test = &Test as &dyn DynTemplate; + + assert_eq!(render(test), "test"); + + assert_eq!(test.to_string(), "test"); + + assert_eq!(format!("{test}"), "test"); + + let mut vec = Vec::new(); + test.dyn_write_into(&mut vec).unwrap(); + assert_eq!(vec, vec![b't', b'e', b's', b't']); + } +} + +/// Old build script helper to rebuild crates if contained templates have changed +/// +/// This function is now deprecated and does nothing. +#[deprecated( + since = "0.8.1", + note = "file-level dependency tracking is handled automatically without build script" +)] +pub fn rerun_if_templates_changed() {} diff --git a/third_party/rust/askama_derive/.cargo-checksum.json b/third_party/rust/askama_derive/.cargo-checksum.json new file mode 100644 index 000000000000..7c28fca6fef0 --- /dev/null +++ b/third_party/rust/askama_derive/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"f293fbc41371fb46f5b68775b158d8da37c09453dc9356ee8e97fce3d1021b2d","LICENSE-APACHE":"87cb0d734c723c083e51c825930ff42bce28596b52dee15567f6b28f19c195e3","LICENSE-MIT":"df20e0180764bf5bd76f74d47bc9e8c0069a666401629c390003a1d5eba99c92","README.md":"dd3e4e203eeca91219fd57c0ca1f92b413176f406df19568d0fe33d7905123e4","src/config.rs":"de4202804d32cc4da044ed41140ef987056f44116b1bbfac53001e07133e52b9","src/generator.rs":"4fec224dd261bc96a63b831f0692a62d9f8d19566377b39dd69bc0f3de4ab033","src/heritage.rs":"fceb0ac86034b8eb902212f9a78a6fb7d19688c3ccdb117099f15933073bf7bb","src/input.rs":"53afae3f73e2b52d83d73c1b38893677992a5ee04927e8b905198b742b1546ae","src/lib.rs":"003e91569575b72a9587796c82c9f9c0e5e9f3dc8db6b659735cf58f68504b76","src/parser/expr.rs":"3b8178398a293910df161ddd769d2efc7ae8dff03e7313f033149a38a6d81983","src/parser/mod.rs":"3afc065cdc69dc1498ddf9a04a77f56d807ed14653828918d36529a441fb6c48","src/parser/node.rs":"c5437e2525e245b6fcd358696f3607c50ef82cf649a66b6bef7816232c3220fa","src/parser/tests.rs":"81fb02f8cab87c93575fdb6b7d6e9cae6fa3b69173f5f5a76d214f5316ca66ca","templates/a.html":"b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c","templates/b.html":"7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730","templates/sub/b.html":"7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730","templates/sub/c.html":"bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c","templates/sub/sub1/d.html":"86b0c5a1e2b73b08fd54c727f4458649ed9fe3ad1b6e8ac9460c070113509a1e"},"package":"c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94"} \ No newline at end of file diff --git a/third_party/rust/askama_derive/Cargo.toml b/third_party/rust/askama_derive/Cargo.toml new file mode 100644 index 000000000000..d780c24c6a6d --- /dev/null +++ b/third_party/rust/askama_derive/Cargo.toml @@ -0,0 +1,72 @@ +# 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.58" +name = "askama_derive" +version = "0.12.1" +description = "Procedural macro package for Askama" +homepage = "https://github.com/djc/askama" +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/djc/askama" +resolver = "1" + +[lib] +proc-macro = true + +[dependencies.basic-toml] +version = "0.1.1" +optional = true + +[dependencies.mime] +version = "0.3" + +[dependencies.mime_guess] +version = "2" + +[dependencies.nom] +version = "7" + +[dependencies.proc-macro2] +version = "1" + +[dependencies.quote] +version = "1" + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[dependencies.syn] +version = "2" + +[features] +config = [ + "serde", + "basic-toml", +] +humansize = [] +markdown = [] +num-traits = [] +serde-json = [] +serde-yaml = [] +urlencode = [] +with-actix-web = [] +with-axum = [] +with-gotham = [] +with-hyper = [] +with-mendes = [] +with-rocket = [] +with-tide = [] +with-warp = [] diff --git a/third_party/rust/rinja_derive/LICENSE-APACHE b/third_party/rust/askama_derive/LICENSE-APACHE similarity index 100% rename from third_party/rust/rinja_derive/LICENSE-APACHE rename to third_party/rust/askama_derive/LICENSE-APACHE diff --git a/third_party/rust/rinja_derive/LICENSE-MIT b/third_party/rust/askama_derive/LICENSE-MIT similarity index 100% rename from third_party/rust/rinja_derive/LICENSE-MIT rename to third_party/rust/askama_derive/LICENSE-MIT diff --git a/third_party/rust/askama_derive/README.md b/third_party/rust/askama_derive/README.md new file mode 100644 index 000000000000..e27f1107d1f9 --- /dev/null +++ b/third_party/rust/askama_derive/README.md @@ -0,0 +1,9 @@ +# askama_derive: procedural macros for the Askama templating engine + +[![Documentation](https://docs.rs/askama_derive/badge.svg)](https://docs.rs/askama_derive/) +[![Latest version](https://img.shields.io/crates/v/askama_derive.svg)](https://crates.io/crates/askama_derive) +[![Build Status](https://github.com/djc/askama/workflows/CI/badge.svg)](https://github.com/djc/askama/actions?query=workflow%3ACI) +[![Chat](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/djc/askama) + +This crate contains the procedural macros used by the +[Askama](https://github.com/djc/askama) templating engine. diff --git a/third_party/rust/askama_derive/src/config.rs b/third_party/rust/askama_derive/src/config.rs new file mode 100644 index 000000000000..cf22a720f0ea --- /dev/null +++ b/third_party/rust/askama_derive/src/config.rs @@ -0,0 +1,582 @@ +use std::collections::{BTreeMap, HashSet}; +use std::convert::TryFrom; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +#[cfg(feature = "serde")] +use serde::Deserialize; + +use crate::CompileError; + +#[derive(Debug)] +pub(crate) struct Config<'a> { + pub(crate) dirs: Vec, + pub(crate) syntaxes: BTreeMap>, + pub(crate) default_syntax: &'a str, + pub(crate) escapers: Vec<(HashSet, String)>, + pub(crate) whitespace: WhitespaceHandling, +} + +impl<'a> Config<'a> { + pub(crate) fn new( + s: &'a str, + template_whitespace: Option<&String>, + ) -> std::result::Result, CompileError> { + let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let default_dirs = vec![root.join("templates")]; + + let mut syntaxes = BTreeMap::new(); + syntaxes.insert(DEFAULT_SYNTAX_NAME.to_string(), Syntax::default()); + + let raw = if s.is_empty() { + RawConfig::default() + } else { + RawConfig::from_toml_str(s)? + }; + + let (dirs, default_syntax, mut whitespace) = match raw.general { + Some(General { + dirs, + default_syntax, + whitespace, + }) => ( + dirs.map_or(default_dirs, |v| { + v.into_iter().map(|dir| root.join(dir)).collect() + }), + default_syntax.unwrap_or(DEFAULT_SYNTAX_NAME), + whitespace, + ), + None => ( + default_dirs, + DEFAULT_SYNTAX_NAME, + WhitespaceHandling::default(), + ), + }; + if let Some(template_whitespace) = template_whitespace { + whitespace = match template_whitespace.as_str() { + "suppress" => WhitespaceHandling::Suppress, + "minimize" => WhitespaceHandling::Minimize, + "preserve" => WhitespaceHandling::Preserve, + s => return Err(format!("invalid value for `whitespace`: \"{s}\"").into()), + }; + } + + if let Some(raw_syntaxes) = raw.syntax { + for raw_s in raw_syntaxes { + let name = raw_s.name; + + if syntaxes + .insert(name.to_string(), Syntax::try_from(raw_s)?) + .is_some() + { + return Err(format!("syntax \"{name}\" is already defined").into()); + } + } + } + + if !syntaxes.contains_key(default_syntax) { + return Err(format!("default syntax \"{default_syntax}\" not found").into()); + } + + let mut escapers = Vec::new(); + if let Some(configured) = raw.escaper { + for escaper in configured { + escapers.push(( + escaper + .extensions + .iter() + .map(|ext| (*ext).to_string()) + .collect(), + escaper.path.to_string(), + )); + } + } + for (extensions, path) in DEFAULT_ESCAPERS { + escapers.push((str_set(extensions), (*path).to_string())); + } + + Ok(Config { + dirs, + syntaxes, + default_syntax, + escapers, + whitespace, + }) + } + + pub(crate) fn find_template( + &self, + path: &str, + start_at: Option<&Path>, + ) -> std::result::Result { + if let Some(root) = start_at { + let relative = root.with_file_name(path); + if relative.exists() { + return Ok(relative); + } + } + + for dir in &self.dirs { + let rooted = dir.join(path); + if rooted.exists() { + return Ok(rooted); + } + } + + Err(format!( + "template {:?} not found in directories {:?}", + path, self.dirs + ) + .into()) + } +} + +#[derive(Debug)] +pub(crate) struct Syntax<'a> { + pub(crate) block_start: &'a str, + pub(crate) block_end: &'a str, + pub(crate) expr_start: &'a str, + pub(crate) expr_end: &'a str, + pub(crate) comment_start: &'a str, + pub(crate) comment_end: &'a str, +} + +impl Default for Syntax<'static> { + fn default() -> Self { + Self { + block_start: "{%", + block_end: "%}", + expr_start: "{{", + expr_end: "}}", + comment_start: "{#", + comment_end: "#}", + } + } +} + +impl<'a> TryFrom> for Syntax<'a> { + type Error = CompileError; + + fn try_from(raw: RawSyntax<'a>) -> std::result::Result { + let default = Syntax::default(); + let syntax = Self { + block_start: raw.block_start.unwrap_or(default.block_start), + block_end: raw.block_end.unwrap_or(default.block_end), + expr_start: raw.expr_start.unwrap_or(default.expr_start), + expr_end: raw.expr_end.unwrap_or(default.expr_end), + comment_start: raw.comment_start.unwrap_or(default.comment_start), + comment_end: raw.comment_end.unwrap_or(default.comment_end), + }; + + if syntax.block_start.len() != 2 + || syntax.block_end.len() != 2 + || syntax.expr_start.len() != 2 + || syntax.expr_end.len() != 2 + || syntax.comment_start.len() != 2 + || syntax.comment_end.len() != 2 + { + return Err("length of delimiters must be two".into()); + } + + let bs = syntax.block_start.as_bytes()[0]; + let be = syntax.block_start.as_bytes()[1]; + let cs = syntax.comment_start.as_bytes()[0]; + let ce = syntax.comment_start.as_bytes()[1]; + let es = syntax.expr_start.as_bytes()[0]; + let ee = syntax.expr_start.as_bytes()[1]; + if !((bs == cs && bs == es) || (be == ce && be == ee)) { + return Err(format!("bad delimiters block_start: {}, comment_start: {}, expr_start: {}, needs one of the two characters in common", syntax.block_start, syntax.comment_start, syntax.expr_start).into()); + } + + Ok(syntax) + } +} + +#[cfg_attr(feature = "serde", derive(Deserialize))] +#[derive(Default)] +struct RawConfig<'a> { + #[cfg_attr(feature = "serde", serde(borrow))] + general: Option>, + syntax: Option>>, + escaper: Option>>, +} + +impl RawConfig<'_> { + #[cfg(feature = "config")] + fn from_toml_str(s: &str) -> std::result::Result, CompileError> { + basic_toml::from_str(s) + .map_err(|e| format!("invalid TOML in {CONFIG_FILE_NAME}: {e}").into()) + } + + #[cfg(not(feature = "config"))] + fn from_toml_str(_: &str) -> std::result::Result, CompileError> { + Err("TOML support not available".into()) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "serde", derive(Deserialize))] +#[cfg_attr(feature = "serde", serde(field_identifier, rename_all = "lowercase"))] +pub(crate) enum WhitespaceHandling { + /// The default behaviour. It will leave the whitespace characters "as is". + Preserve, + /// It'll remove all the whitespace characters before and after the jinja block. + Suppress, + /// It'll remove all the whitespace characters except one before and after the jinja blocks. + /// If there is a newline character, the preserved character in the trimmed characters, it will + /// the one preserved. + Minimize, +} + +impl Default for WhitespaceHandling { + fn default() -> Self { + WhitespaceHandling::Preserve + } +} + +#[cfg_attr(feature = "serde", derive(Deserialize))] +struct General<'a> { + #[cfg_attr(feature = "serde", serde(borrow))] + dirs: Option>, + default_syntax: Option<&'a str>, + #[cfg_attr(feature = "serde", serde(default))] + whitespace: WhitespaceHandling, +} + +#[cfg_attr(feature = "serde", derive(Deserialize))] +struct RawSyntax<'a> { + name: &'a str, + block_start: Option<&'a str>, + block_end: Option<&'a str>, + expr_start: Option<&'a str>, + expr_end: Option<&'a str>, + comment_start: Option<&'a str>, + comment_end: Option<&'a str>, +} + +#[cfg_attr(feature = "serde", derive(Deserialize))] +struct RawEscaper<'a> { + path: &'a str, + extensions: Vec<&'a str>, +} + +pub(crate) fn read_config_file( + config_path: Option<&str>, +) -> std::result::Result { + let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let filename = match config_path { + Some(config_path) => root.join(config_path), + None => root.join(CONFIG_FILE_NAME), + }; + + if filename.exists() { + fs::read_to_string(&filename) + .map_err(|_| format!("unable to read {:?}", filename.to_str().unwrap()).into()) + } else if config_path.is_some() { + Err(format!("`{}` does not exist", root.display()).into()) + } else { + Ok("".to_string()) + } +} + +fn str_set(vals: &[T]) -> HashSet +where + T: ToString, +{ + vals.iter().map(|s| s.to_string()).collect() +} + +#[allow(clippy::match_wild_err_arm)] +pub(crate) fn get_template_source(tpl_path: &Path) -> std::result::Result { + match fs::read_to_string(tpl_path) { + Err(_) => Err(format!( + "unable to open template file '{}'", + tpl_path.to_str().unwrap() + ) + .into()), + Ok(mut source) => { + if source.ends_with('\n') { + let _ = source.pop(); + } + Ok(source) + } + } +} + +static CONFIG_FILE_NAME: &str = "askama.toml"; +static DEFAULT_SYNTAX_NAME: &str = "default"; +static DEFAULT_ESCAPERS: &[(&[&str], &str)] = &[ + (&["html", "htm", "xml"], "::askama::Html"), + (&["md", "none", "txt", "yml", ""], "::askama::Text"), + (&["j2", "jinja", "jinja2"], "::askama::Html"), +]; + +#[cfg(test)] +mod tests { + use std::env; + use std::path::{Path, PathBuf}; + + use super::*; + + #[test] + fn get_source() { + let path = Config::new("", None) + .and_then(|config| config.find_template("b.html", None)) + .unwrap(); + assert_eq!(get_template_source(&path).unwrap(), "bar"); + } + + #[test] + fn test_default_config() { + let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + root.push("templates"); + let config = Config::new("", None).unwrap(); + assert_eq!(config.dirs, vec![root]); + } + + #[cfg(feature = "config")] + #[test] + fn test_config_dirs() { + let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + root.push("tpl"); + let config = Config::new("[general]\ndirs = [\"tpl\"]", None).unwrap(); + assert_eq!(config.dirs, vec![root]); + } + + fn assert_eq_rooted(actual: &Path, expected: &str) { + let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + root.push("templates"); + let mut inner = PathBuf::new(); + inner.push(expected); + assert_eq!(actual.strip_prefix(root).unwrap(), inner); + } + + #[test] + fn find_absolute() { + let config = Config::new("", None).unwrap(); + let root = config.find_template("a.html", None).unwrap(); + let path = config.find_template("sub/b.html", Some(&root)).unwrap(); + assert_eq_rooted(&path, "sub/b.html"); + } + + #[test] + #[should_panic] + fn find_relative_nonexistent() { + let config = Config::new("", None).unwrap(); + let root = config.find_template("a.html", None).unwrap(); + config.find_template("c.html", Some(&root)).unwrap(); + } + + #[test] + fn find_relative() { + let config = Config::new("", None).unwrap(); + let root = config.find_template("sub/b.html", None).unwrap(); + let path = config.find_template("c.html", Some(&root)).unwrap(); + assert_eq_rooted(&path, "sub/c.html"); + } + + #[test] + fn find_relative_sub() { + let config = Config::new("", None).unwrap(); + let root = config.find_template("sub/b.html", None).unwrap(); + let path = config.find_template("sub1/d.html", Some(&root)).unwrap(); + assert_eq_rooted(&path, "sub/sub1/d.html"); + } + + #[cfg(feature = "config")] + #[test] + fn add_syntax() { + let raw_config = r#" + [general] + default_syntax = "foo" + + [[syntax]] + name = "foo" + block_start = "{<" + + [[syntax]] + name = "bar" + expr_start = "{!" + "#; + + let default_syntax = Syntax::default(); + let config = Config::new(raw_config, None).unwrap(); + assert_eq!(config.default_syntax, "foo"); + + let foo = config.syntaxes.get("foo").unwrap(); + assert_eq!(foo.block_start, "{<"); + assert_eq!(foo.block_end, default_syntax.block_end); + assert_eq!(foo.expr_start, default_syntax.expr_start); + assert_eq!(foo.expr_end, default_syntax.expr_end); + assert_eq!(foo.comment_start, default_syntax.comment_start); + assert_eq!(foo.comment_end, default_syntax.comment_end); + + let bar = config.syntaxes.get("bar").unwrap(); + assert_eq!(bar.block_start, default_syntax.block_start); + assert_eq!(bar.block_end, default_syntax.block_end); + assert_eq!(bar.expr_start, "{!"); + assert_eq!(bar.expr_end, default_syntax.expr_end); + assert_eq!(bar.comment_start, default_syntax.comment_start); + assert_eq!(bar.comment_end, default_syntax.comment_end); + } + + #[cfg(feature = "config")] + #[test] + fn add_syntax_two() { + let raw_config = r#" + syntax = [{ name = "foo", block_start = "{<" }, + { name = "bar", expr_start = "{!" } ] + + [general] + default_syntax = "foo" + "#; + + let default_syntax = Syntax::default(); + let config = Config::new(raw_config, None).unwrap(); + assert_eq!(config.default_syntax, "foo"); + + let foo = config.syntaxes.get("foo").unwrap(); + assert_eq!(foo.block_start, "{<"); + assert_eq!(foo.block_end, default_syntax.block_end); + assert_eq!(foo.expr_start, default_syntax.expr_start); + assert_eq!(foo.expr_end, default_syntax.expr_end); + assert_eq!(foo.comment_start, default_syntax.comment_start); + assert_eq!(foo.comment_end, default_syntax.comment_end); + + let bar = config.syntaxes.get("bar").unwrap(); + assert_eq!(bar.block_start, default_syntax.block_start); + assert_eq!(bar.block_end, default_syntax.block_end); + assert_eq!(bar.expr_start, "{!"); + assert_eq!(bar.expr_end, default_syntax.expr_end); + assert_eq!(bar.comment_start, default_syntax.comment_start); + assert_eq!(bar.comment_end, default_syntax.comment_end); + } + + #[cfg(feature = "toml")] + #[should_panic] + #[test] + fn use_default_at_syntax_name() { + let raw_config = r#" + syntax = [{ name = "default" }] + "#; + + let _config = Config::new(raw_config, None).unwrap(); + } + + #[cfg(feature = "toml")] + #[should_panic] + #[test] + fn duplicated_syntax_name_on_list() { + let raw_config = r#" + syntax = [{ name = "foo", block_start = "~<" }, + { name = "foo", block_start = "%%" } ] + "#; + + let _config = Config::new(raw_config, None).unwrap(); + } + + #[cfg(feature = "toml")] + #[should_panic] + #[test] + fn is_not_exist_default_syntax() { + let raw_config = r#" + [general] + default_syntax = "foo" + "#; + + let _config = Config::new(raw_config, None).unwrap(); + } + + #[cfg(feature = "config")] + #[test] + fn escape_modes() { + let config = Config::new( + r#" + [[escaper]] + path = "::askama::Js" + extensions = ["js"] + "#, + None, + ) + .unwrap(); + assert_eq!( + config.escapers, + vec![ + (str_set(&["js"]), "::askama::Js".into()), + (str_set(&["html", "htm", "xml"]), "::askama::Html".into()), + ( + str_set(&["md", "none", "txt", "yml", ""]), + "::askama::Text".into() + ), + (str_set(&["j2", "jinja", "jinja2"]), "::askama::Html".into()), + ] + ); + } + + #[cfg(feature = "config")] + #[test] + fn test_whitespace_parsing() { + let config = Config::new( + r#" + [general] + whitespace = "suppress" + "#, + None, + ) + .unwrap(); + assert_eq!(config.whitespace, WhitespaceHandling::Suppress); + + let config = Config::new(r#""#, None).unwrap(); + assert_eq!(config.whitespace, WhitespaceHandling::Preserve); + + let config = Config::new( + r#" + [general] + whitespace = "preserve" + "#, + None, + ) + .unwrap(); + assert_eq!(config.whitespace, WhitespaceHandling::Preserve); + + let config = Config::new( + r#" + [general] + whitespace = "minimize" + "#, + None, + ) + .unwrap(); + assert_eq!(config.whitespace, WhitespaceHandling::Minimize); + } + + #[cfg(feature = "toml")] + #[test] + fn test_whitespace_in_template() { + // Checking that template arguments have precedence over general configuration. + // So in here, in the template arguments, there is `whitespace = "minimize"` so + // the `WhitespaceHandling` should be `Minimize` as well. + let config = Config::new( + r#" + [general] + whitespace = "suppress" + "#, + Some(&"minimize".to_owned()), + ) + .unwrap(); + assert_eq!(config.whitespace, WhitespaceHandling::Minimize); + + let config = Config::new(r#""#, Some(&"minimize".to_owned())).unwrap(); + assert_eq!(config.whitespace, WhitespaceHandling::Minimize); + } + + #[test] + fn test_config_whitespace_error() { + let config = Config::new(r#""#, Some(&"trim".to_owned())); + if let Err(err) = config { + assert_eq!(err.msg, "invalid value for `whitespace`: \"trim\""); + } else { + panic!("Config::new should have return an error"); + } + } +} diff --git a/third_party/rust/askama_derive/src/generator.rs b/third_party/rust/askama_derive/src/generator.rs new file mode 100644 index 000000000000..05b3fc32454f --- /dev/null +++ b/third_party/rust/askama_derive/src/generator.rs @@ -0,0 +1,2171 @@ +use crate::config::{get_template_source, read_config_file, Config, WhitespaceHandling}; +use crate::heritage::{Context, Heritage}; +use crate::input::{Print, Source, TemplateInput}; +use crate::parser::{parse, Cond, CondTest, Expr, Loop, Node, Target, When, Whitespace, Ws}; +use crate::CompileError; + +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use syn::punctuated::Punctuated; + +use std::collections::hash_map::{Entry, HashMap}; +use std::path::{Path, PathBuf}; +use std::{cmp, hash, mem, str}; + +/// The actual implementation for askama_derive::Template +pub(crate) fn derive_template(input: TokenStream) -> TokenStream { + let ast: syn::DeriveInput = syn::parse(input).unwrap(); + match build_template(&ast) { + Ok(source) => source.parse().unwrap(), + Err(e) => e.into_compile_error(), + } +} + +/// Takes a `syn::DeriveInput` and generates source code for it +/// +/// Reads the metadata from the `template()` attribute to get the template +/// metadata, then fetches the source from the filesystem. The source is +/// parsed, and the parse tree is fed to the code generator. Will print +/// the parse tree and/or generated source according to the `print` key's +/// value as passed to the `template()` attribute. +fn build_template(ast: &syn::DeriveInput) -> Result { + let template_args = TemplateArgs::new(ast)?; + let config_toml = read_config_file(template_args.config_path.as_deref())?; + let config = Config::new(&config_toml, template_args.whitespace.as_ref())?; + let input = TemplateInput::new(ast, &config, template_args)?; + let source: String = match input.source { + Source::Source(ref s) => s.clone(), + Source::Path(_) => get_template_source(&input.path)?, + }; + + let mut sources = HashMap::new(); + find_used_templates(&input, &mut sources, source)?; + + let mut parsed = HashMap::new(); + for (path, src) in &sources { + parsed.insert(path.as_path(), parse(src, input.syntax)?); + } + + let mut contexts = HashMap::new(); + for (path, nodes) in &parsed { + contexts.insert(*path, Context::new(input.config, path, nodes)?); + } + + let ctx = &contexts[input.path.as_path()]; + let heritage = if !ctx.blocks.is_empty() || ctx.extends.is_some() { + Some(Heritage::new(ctx, &contexts)) + } else { + None + }; + + if input.print == Print::Ast || input.print == Print::All { + eprintln!("{:?}", parsed[input.path.as_path()]); + } + + let code = Generator::new( + &input, + &contexts, + heritage.as_ref(), + MapChain::new(), + config.whitespace, + ) + .build(&contexts[input.path.as_path()])?; + if input.print == Print::Code || input.print == Print::All { + eprintln!("{code}"); + } + Ok(code) +} + +#[derive(Default)] +pub(crate) struct TemplateArgs { + pub(crate) source: Option, + pub(crate) print: Print, + pub(crate) escaping: Option, + pub(crate) ext: Option, + pub(crate) syntax: Option, + pub(crate) config_path: Option, + pub(crate) whitespace: Option, +} + +impl TemplateArgs { + fn new(ast: &'_ syn::DeriveInput) -> Result { + // Check that an attribute called `template()` exists once and that it is + // the proper type (list). + let mut template_args = None; + for attr in &ast.attrs { + if !attr.path().is_ident("template") { + continue; + } + + match attr.parse_args_with(Punctuated::::parse_terminated) { + Ok(args) if template_args.is_none() => template_args = Some(args), + Ok(_) => return Err("duplicated 'template' attribute".into()), + Err(e) => return Err(format!("unable to parse template arguments: {e}").into()), + }; + } + + let template_args = + template_args.ok_or_else(|| CompileError::from("no attribute 'template' found"))?; + + let mut args = Self::default(); + // Loop over the meta attributes and find everything that we + // understand. Return a CompileError if something is not right. + // `source` contains an enum that can represent `path` or `source`. + for item in template_args { + let pair = match item { + syn::Meta::NameValue(pair) => pair, + _ => { + return Err(format!( + "unsupported attribute argument {:?}", + item.to_token_stream() + ) + .into()) + } + }; + + let ident = match pair.path.get_ident() { + Some(ident) => ident, + None => unreachable!("not possible in syn::Meta::NameValue(…)"), + }; + + let value = match pair.value { + syn::Expr::Lit(lit) => lit, + syn::Expr::Group(group) => match *group.expr { + syn::Expr::Lit(lit) => lit, + _ => { + return Err(format!("unsupported argument value type for {ident:?}").into()) + } + }, + _ => return Err(format!("unsupported argument value type for {ident:?}").into()), + }; + + if ident == "path" { + if let syn::Lit::Str(s) = value.lit { + if args.source.is_some() { + return Err("must specify 'source' or 'path', not both".into()); + } + args.source = Some(Source::Path(s.value())); + } else { + return Err("template path must be string literal".into()); + } + } else if ident == "source" { + if let syn::Lit::Str(s) = value.lit { + if args.source.is_some() { + return Err("must specify 'source' or 'path', not both".into()); + } + args.source = Some(Source::Source(s.value())); + } else { + return Err("template source must be string literal".into()); + } + } else if ident == "print" { + if let syn::Lit::Str(s) = value.lit { + args.print = s.value().parse()?; + } else { + return Err("print value must be string literal".into()); + } + } else if ident == "escape" { + if let syn::Lit::Str(s) = value.lit { + args.escaping = Some(s.value()); + } else { + return Err("escape value must be string literal".into()); + } + } else if ident == "ext" { + if let syn::Lit::Str(s) = value.lit { + args.ext = Some(s.value()); + } else { + return Err("ext value must be string literal".into()); + } + } else if ident == "syntax" { + if let syn::Lit::Str(s) = value.lit { + args.syntax = Some(s.value()) + } else { + return Err("syntax value must be string literal".into()); + } + } else if ident == "config" { + if let syn::Lit::Str(s) = value.lit { + args.config_path = Some(s.value()) + } else { + return Err("config value must be string literal".into()); + } + } else if ident == "whitespace" { + if let syn::Lit::Str(s) = value.lit { + args.whitespace = Some(s.value()) + } else { + return Err("whitespace value must be string literal".into()); + } + } else { + return Err(format!("unsupported attribute key {ident:?} found").into()); + } + } + + Ok(args) + } +} + +fn find_used_templates( + input: &TemplateInput<'_>, + map: &mut HashMap, + source: String, +) -> Result<(), CompileError> { + let mut dependency_graph = Vec::new(); + let mut check = vec![(input.path.clone(), source)]; + while let Some((path, source)) = check.pop() { + for n in parse(&source, input.syntax)? { + match n { + Node::Extends(extends) => { + let extends = input.config.find_template(extends, Some(&path))?; + let dependency_path = (path.clone(), extends.clone()); + if dependency_graph.contains(&dependency_path) { + return Err(format!( + "cyclic dependency in graph {:#?}", + dependency_graph + .iter() + .map(|e| format!("{:#?} --> {:#?}", e.0, e.1)) + .collect::>() + ) + .into()); + } + dependency_graph.push(dependency_path); + let source = get_template_source(&extends)?; + check.push((extends, source)); + } + Node::Import(_, import, _) => { + let import = input.config.find_template(import, Some(&path))?; + let source = get_template_source(&import)?; + check.push((import, source)); + } + _ => {} + } + } + map.insert(path, source); + } + Ok(()) +} + +struct Generator<'a> { + // The template input state: original struct AST and attributes + input: &'a TemplateInput<'a>, + // All contexts, keyed by the package-relative template path + contexts: &'a HashMap<&'a Path, Context<'a>>, + // The heritage contains references to blocks and their ancestry + heritage: Option<&'a Heritage<'a>>, + // Variables accessible directly from the current scope (not redirected to context) + locals: MapChain<'a, &'a str, LocalMeta>, + // Suffix whitespace from the previous literal. Will be flushed to the + // output buffer unless suppressed by whitespace suppression on the next + // non-literal. + next_ws: Option<&'a str>, + // Whitespace suppression from the previous non-literal. Will be used to + // determine whether to flush prefix whitespace from the next literal. + skip_ws: WhitespaceHandling, + // If currently in a block, this will contain the name of a potential parent block + super_block: Option<(&'a str, usize)>, + // buffer for writable + buf_writable: Vec>, + // Counter for write! hash named arguments + named: usize, + // If set to `suppress`, the whitespace characters will be removed by default unless `+` is + // used. + whitespace: WhitespaceHandling, +} + +impl<'a> Generator<'a> { + fn new<'n>( + input: &'n TemplateInput<'_>, + contexts: &'n HashMap<&'n Path, Context<'n>>, + heritage: Option<&'n Heritage<'_>>, + locals: MapChain<'n, &'n str, LocalMeta>, + whitespace: WhitespaceHandling, + ) -> Generator<'n> { + Generator { + input, + contexts, + heritage, + locals, + next_ws: None, + skip_ws: WhitespaceHandling::Preserve, + super_block: None, + buf_writable: vec![], + named: 0, + whitespace, + } + } + + fn child(&mut self) -> Generator<'_> { + let locals = MapChain::with_parent(&self.locals); + Self::new( + self.input, + self.contexts, + self.heritage, + locals, + self.whitespace, + ) + } + + // Takes a Context and generates the relevant implementations. + fn build(mut self, ctx: &'a Context<'_>) -> Result { + let mut buf = Buffer::new(0); + + self.impl_template(ctx, &mut buf)?; + self.impl_display(&mut buf)?; + + #[cfg(feature = "with-actix-web")] + self.impl_actix_web_responder(&mut buf)?; + #[cfg(feature = "with-axum")] + self.impl_axum_into_response(&mut buf)?; + #[cfg(feature = "with-gotham")] + self.impl_gotham_into_response(&mut buf)?; + #[cfg(feature = "with-hyper")] + self.impl_hyper_into_response(&mut buf)?; + #[cfg(feature = "with-mendes")] + self.impl_mendes_responder(&mut buf)?; + #[cfg(feature = "with-rocket")] + self.impl_rocket_responder(&mut buf)?; + #[cfg(feature = "with-tide")] + self.impl_tide_integrations(&mut buf)?; + #[cfg(feature = "with-warp")] + self.impl_warp_reply(&mut buf)?; + + Ok(buf.buf) + } + + // Implement `Template` for the given context struct. + fn impl_template( + &mut self, + ctx: &'a Context<'_>, + buf: &mut Buffer, + ) -> Result<(), CompileError> { + self.write_header(buf, "::askama::Template", None)?; + buf.writeln( + "fn render_into(&self, writer: &mut (impl ::std::fmt::Write + ?Sized)) -> \ + ::askama::Result<()> {", + )?; + + // Make sure the compiler understands that the generated code depends on the template files. + for path in self.contexts.keys() { + // Skip the fake path of templates defined in rust source. + let path_is_valid = match self.input.source { + Source::Path(_) => true, + Source::Source(_) => path != &self.input.path, + }; + if path_is_valid { + let path = path.to_str().unwrap(); + buf.writeln( + "e! { + include_bytes!(#path); + } + .to_string(), + )?; + } + } + + let size_hint = if let Some(heritage) = self.heritage { + self.handle(heritage.root, heritage.root.nodes, buf, AstLevel::Top) + } else { + self.handle(ctx, ctx.nodes, buf, AstLevel::Top) + }?; + + self.flush_ws(Ws(None, None)); + buf.writeln("::askama::Result::Ok(())")?; + buf.writeln("}")?; + + buf.writeln("const EXTENSION: ::std::option::Option<&'static ::std::primitive::str> = ")?; + buf.writeln(&format!("{:?}", self.input.extension()))?; + buf.writeln(";")?; + + buf.writeln("const SIZE_HINT: ::std::primitive::usize = ")?; + buf.writeln(&format!("{size_hint}"))?; + buf.writeln(";")?; + + buf.writeln("const MIME_TYPE: &'static ::std::primitive::str = ")?; + buf.writeln(&format!("{:?}", &self.input.mime_type))?; + buf.writeln(";")?; + + buf.writeln("}")?; + Ok(()) + } + + // Implement `Display` for the given context struct. + fn impl_display(&mut self, buf: &mut Buffer) -> Result<(), CompileError> { + self.write_header(buf, "::std::fmt::Display", None)?; + buf.writeln("#[inline]")?; + buf.writeln("fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {")?; + buf.writeln("::askama::Template::render_into(self, f).map_err(|_| ::std::fmt::Error {})")?; + buf.writeln("}")?; + buf.writeln("}") + } + + // Implement Actix-web's `Responder`. + #[cfg(feature = "with-actix-web")] + fn impl_actix_web_responder(&mut self, buf: &mut Buffer) -> Result<(), CompileError> { + self.write_header(buf, "::askama_actix::actix_web::Responder", None)?; + buf.writeln("type Body = ::askama_actix::actix_web::body::BoxBody;")?; + buf.writeln("#[inline]")?; + buf.writeln( + "fn respond_to(self, _req: &::askama_actix::actix_web::HttpRequest) \ + -> ::askama_actix::actix_web::HttpResponse {", + )?; + buf.writeln("::to_response(&self)")?; + buf.writeln("}")?; + buf.writeln("}") + } + + // Implement Axum's `IntoResponse`. + #[cfg(feature = "with-axum")] + fn impl_axum_into_response(&mut self, buf: &mut Buffer) -> Result<(), CompileError> { + self.write_header(buf, "::askama_axum::IntoResponse", None)?; + buf.writeln("#[inline]")?; + buf.writeln( + "fn into_response(self)\ + -> ::askama_axum::Response {", + )?; + buf.writeln("::askama_axum::into_response(&self)")?; + buf.writeln("}")?; + buf.writeln("}") + } + + // Implement gotham's `IntoResponse`. + #[cfg(feature = "with-gotham")] + fn impl_gotham_into_response(&mut self, buf: &mut Buffer) -> Result<(), CompileError> { + self.write_header(buf, "::askama_gotham::IntoResponse", None)?; + buf.writeln("#[inline]")?; + buf.writeln( + "fn into_response(self, _state: &::askama_gotham::State)\ + -> ::askama_gotham::Response<::askama_gotham::Body> {", + )?; + buf.writeln("::askama_gotham::respond(&self)")?; + buf.writeln("}")?; + buf.writeln("}") + } + + // Implement `From