diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/prost | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/prost')
| -rw-r--r-- | vendor/prost/.cargo-checksum.json | 1 | ||||
| -rw-r--r-- | vendor/prost/Cargo.lock | 787 | ||||
| -rw-r--r-- | vendor/prost/Cargo.toml | 75 | ||||
| -rw-r--r-- | vendor/prost/LICENSE | 201 | ||||
| -rw-r--r-- | vendor/prost/README.md | 507 | ||||
| -rw-r--r-- | vendor/prost/benches/varint.rs | 99 | ||||
| -rw-r--r-- | vendor/prost/src/encoding.rs | 1428 | ||||
| -rw-r--r-- | vendor/prost/src/encoding/length_delimiter.rs | 53 | ||||
| -rw-r--r-- | vendor/prost/src/encoding/varint.rs | 274 | ||||
| -rw-r--r-- | vendor/prost/src/encoding/wire_type.rs | 49 | ||||
| -rw-r--r-- | vendor/prost/src/error.rs | 180 | ||||
| -rw-r--r-- | vendor/prost/src/lib.rs | 42 | ||||
| -rw-r--r-- | vendor/prost/src/message.rs | 187 | ||||
| -rw-r--r-- | vendor/prost/src/name.rs | 34 | ||||
| -rw-r--r-- | vendor/prost/src/types.rs | 570 |
15 files changed, 4487 insertions, 0 deletions
diff --git a/vendor/prost/.cargo-checksum.json b/vendor/prost/.cargo-checksum.json new file mode 100644 index 00000000..cc2868d6 --- /dev/null +++ b/vendor/prost/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"9873018da9575867e7e8656161d370bf3ed9d0b3d335491dbf0c3d4f45fe691f","Cargo.toml":"2519990bf4b36f0aa5594ae64c76503520091683f0cfda22f6c847ab06797c5a","LICENSE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","README.md":"436225c24c3e878a2bc9f2b9b2b3cc7b39073866b7a7b4faf80d3e197becdd73","benches/varint.rs":"94f8949ac90218017cbf66e5d12de10604d20bc844a988531b2a8e1c0d14affb","src/encoding.rs":"1d02e973675eca9f07c8b0244d772ba7e06273ca77c5a580af108f23ad1d5174","src/encoding/length_delimiter.rs":"70749756af605a924ccde31ce4690c0e45dff0d936aee42c5aae152d342d8b99","src/encoding/varint.rs":"3d58f41e04abea61ef797fe3337934a4521136464cf8c1e3ecf2acc7e0b5e181","src/encoding/wire_type.rs":"b41c05db9db77f952cffd2ac85bd23bb951556b9384c9160a303fdf98a7c89c5","src/error.rs":"0b081316425f4d4d9dce7c7e640a0494edfea96e5d3938ef8238c2461dc40b24","src/lib.rs":"dbefebf38d29872e9b03d5340761cb064868329439bcbd305141b272e8619344","src/message.rs":"2e365d186e9bfcc4e1c4c7174a0b16d5925758d70b61584df1548f01ddd219d4","src/name.rs":"4524233d6c1a85ca55ce54d9740e72ecbb05714b558e8a77346c0a125a2e5320","src/types.rs":"4c73041aa3ad7daad9f82ac484ae728dc6f712cc6c3da2aa6514b6428002e0d1"},"package":"2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"}
\ No newline at end of file diff --git a/vendor/prost/Cargo.lock b/vendor/prost/Cargo.lock new file mode 100644 index 00000000..ae3533f0 --- /dev/null +++ b/vendor/prost/Cargo.lock @@ -0,0 +1,787 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.5.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "prost" +version = "0.13.5" +dependencies = [ + "bytes", + "criterion", + "proptest", + "prost-derive", + "rand 0.9.0", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.0", + "zerocopy 0.8.17", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.17", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustix" +version = "0.38.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +dependencies = [ + "zerocopy-derive 0.8.17", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/vendor/prost/Cargo.toml b/vendor/prost/Cargo.toml new file mode 100644 index 00000000..8f88d5eb --- /dev/null +++ b/vendor/prost/Cargo.toml @@ -0,0 +1,75 @@ +# 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.71.1" +name = "prost" +version = "0.13.5" +authors = [ + "Dan Burkert <dan@danburkert.com>", + "Lucio Franco <luciofranco14@gmail.com>", + "Casper Meijn <casper@meijn.net>", + "Tokio Contributors <team@tokio.rs>", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A Protocol Buffers implementation for the Rust Language." +readme = "README.md" +keywords = [ + "protobuf", + "serialization", +] +categories = ["encoding"] +license = "Apache-2.0" +repository = "https://github.com/tokio-rs/prost" + +[features] +default = [ + "derive", + "std", +] +derive = ["dep:prost-derive"] +no-recursion-limit = [] +prost-derive = ["derive"] +std = [] + +[lib] +name = "prost" +path = "src/lib.rs" +bench = false + +[[bench]] +name = "varint" +path = "benches/varint.rs" +harness = false + +[dependencies.bytes] +version = "1" +default-features = false + +[dependencies.prost-derive] +version = "0.13.5" +optional = true + +[dev-dependencies.criterion] +version = "0.5" +default-features = false + +[dev-dependencies.proptest] +version = "1" + +[dev-dependencies.rand] +version = "0.9" diff --git a/vendor/prost/LICENSE b/vendor/prost/LICENSE new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/vendor/prost/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/prost/README.md b/vendor/prost/README.md new file mode 100644 index 00000000..69959b3b --- /dev/null +++ b/vendor/prost/README.md @@ -0,0 +1,507 @@ +[](https://github.com/tokio-rs/prost/actions/workflows/ci.yml?query=branch%3Amaster) +[](https://docs.rs/prost/) +[](https://crates.io/crates/prost) +[](https://deps.rs/repo/github/tokio-rs/prost) +[](https://discord.gg/tokio) + +# *PROST!* + +`prost` is a [Protocol Buffers](https://developers.google.com/protocol-buffers/) +implementation for the [Rust Language](https://www.rust-lang.org/). `prost` +generates simple, idiomatic Rust code from `proto2` and `proto3` files. + +Compared to other Protocol Buffers implementations, `prost` + +* Generates simple, idiomatic, and readable Rust types by taking advantage of + Rust `derive` attributes. +* Retains comments from `.proto` files in generated Rust code. +* Allows existing Rust types (not generated from a `.proto`) to be serialized + and deserialized by adding attributes. +* Uses the [`bytes::{Buf, BufMut}`](https://github.com/carllerche/bytes) + abstractions for serialization instead of `std::io::{Read, Write}`. +* Respects the Protobuf `package` specifier when organizing generated code + into Rust modules. +* Preserves unknown enum values during deserialization. +* Does not include support for runtime reflection or message descriptors. + +## Using `prost` in a Cargo Project + +First, add `prost` and its public dependencies to your `Cargo.toml`: + +```ignore +[dependencies] +prost = "0.13" +# Only necessary if using Protobuf well-known types: +prost-types = "0.13" +``` + +The recommended way to add `.proto` compilation to a Cargo project is to use the +`prost-build` library. See the [`prost-build` documentation][prost-build] for +more details and examples. + +See the [snazzy repository][snazzy] for a simple start-to-finish example. + +[prost-build]: https://docs.rs/prost-build/latest/prost_build/ +[snazzy]: https://github.com/danburkert/snazzy + +### MSRV + +`prost` follows the `tokio-rs` project's MSRV model and supports 1.70. For more +information on the tokio msrv policy you can check it out [here][tokio msrv] + +[tokio msrv]: https://github.com/tokio-rs/tokio/#supported-rust-versions + +## Generated Code + +`prost` generates Rust code from source `.proto` files using the `proto2` or +`proto3` syntax. `prost`'s goal is to make the generated code as simple as +possible. + +### `protoc` + +With `prost-build` v0.11 release, `protoc` will be required to invoke +`compile_protos` (unless `skip_protoc` is enabled). Prost will no longer provide +bundled `protoc` or attempt to compile `protoc` for users. For install +instructions for `protoc`, please check out the [protobuf install] instructions. + +[protobuf install]: https://github.com/protocolbuffers/protobuf#protobuf-compiler-installation + + +### Packages + +Prost can now generate code for `.proto` files that don't have a package spec. +`prost` will translate the Protobuf package into +a Rust module. For example, given the `package` specifier: + +[package]: https://developers.google.com/protocol-buffers/docs/proto#packages + +```protobuf,ignore +package foo.bar; +``` + +All Rust types generated from the file will be in the `foo::bar` module. + +### Messages + +Given a simple message declaration: + +```protobuf,ignore +// Sample message. +message Foo { +} +``` + +`prost` will generate the following Rust struct: + +```rust,ignore +/// Sample message. +#[derive(Clone, Debug, PartialEq, Message)] +pub struct Foo { +} +``` + +### Fields + +Fields in Protobuf messages are translated into Rust as public struct fields of the +corresponding type. + +#### Scalar Values + +Scalar value types are converted as follows: + +| Protobuf Type | Rust Type | +| --- | --- | +| `double` | `f64` | +| `float` | `f32` | +| `int32` | `i32` | +| `int64` | `i64` | +| `uint32` | `u32` | +| `uint64` | `u64` | +| `sint32` | `i32` | +| `sint64` | `i64` | +| `fixed32` | `u32` | +| `fixed64` | `u64` | +| `sfixed32` | `i32` | +| `sfixed64` | `i64` | +| `bool` | `bool` | +| `string` | `String` | +| `bytes` | `Vec<u8>` | + +#### Enumerations + +All `.proto` enumeration types convert to the Rust `i32` type. Additionally, +each enumeration type gets a corresponding Rust `enum` type. For example, this +`proto` enum: + +```protobuf,ignore +enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; +} +``` + +gets this corresponding Rust enum [^1]: + +```rust,ignore +pub enum PhoneType { + Mobile = 0, + Home = 1, + Work = 2, +} +``` + +[^1]: Annotations have been elided for clarity. See below for a full example. + +You can convert a `PhoneType` value to an `i32` by doing: + +```rust,ignore +PhoneType::Mobile as i32 +``` + +The `#[derive(::prost::Enumeration)]` annotation added to the generated +`PhoneType` adds these associated functions to the type: + +```rust,ignore +impl PhoneType { + pub fn is_valid(value: i32) -> bool { ... } + #[deprecated] + pub fn from_i32(value: i32) -> Option<PhoneType> { ... } +} +``` + +It also adds an `impl TryFrom<i32> for PhoneType`, so you can convert an `i32` to its corresponding `PhoneType` value by doing, +for example: + +```rust,ignore +let phone_type = 2i32; + +match PhoneType::try_from(phone_type) { + Ok(PhoneType::Mobile) => ..., + Ok(PhoneType::Home) => ..., + Ok(PhoneType::Work) => ..., + Err(_) => ..., +} +``` + +Additionally, wherever a `proto` enum is used as a field in a `Message`, the +message will have 'accessor' methods to get/set the value of the field as the +Rust enum type. For instance, this proto `PhoneNumber` message that has a field +named `type` of type `PhoneType`: + +```protobuf,ignore +message PhoneNumber { + string number = 1; + PhoneType type = 2; +} +``` + +will become the following Rust type [^2] with methods `type` and `set_type`: + +```rust,ignore +pub struct PhoneNumber { + pub number: String, + pub r#type: i32, // the `r#` is needed because `type` is a Rust keyword +} + +impl PhoneNumber { + pub fn r#type(&self) -> PhoneType { ... } + pub fn set_type(&mut self, value: PhoneType) { ... } +} +``` + +Note that the getter methods will return the Rust enum's default value if the +field has an invalid `i32` value. + +The `enum` type isn't used directly as a field, because the Protobuf spec +mandates that enumerations values are 'open', and decoding unrecognized +enumeration values must be possible. + +[^2]: Annotations have been elided for clarity. See below for a full example. + +#### Field Modifiers + +Protobuf scalar value and enumeration message fields can have a modifier +depending on the Protobuf version. Modifiers change the corresponding type of +the Rust field: + +| `.proto` Version | Modifier | Rust Type | +| --- | --- | --- | +| `proto2` | `optional` | `Option<T>` | +| `proto2` | `required` | `T` | +| `proto3` | default | `T` for scalar types, `Option<T>` otherwise | +| `proto3` | `optional` | `Option<T>` | +| `proto2`/`proto3` | `repeated` | `Vec<T>` | + +Note that in `proto3` the default representation for all user-defined message +types is `Option<T>`, and for scalar types just `T` (during decoding, a missing +value is populated by `T::default()`). If you need a witness of the presence of +a scalar type `T`, use the `optional` modifier to enforce an `Option<T>` +representation in the generated Rust struct. + +#### Map Fields + +Map fields are converted to a Rust `HashMap` with key and value type converted +from the Protobuf key and value types. + +#### Message Fields + +Message fields are converted to the corresponding struct type. The table of +field modifiers above applies to message fields, except that `proto3` message +fields without a modifier (the default) will be wrapped in an `Option`. +Typically message fields are unboxed. `prost` will automatically box a message +field if the field type and the parent type are recursively nested in order to +avoid an infinite sized struct. + +#### Oneof Fields + +Oneof fields convert to a Rust enum. Protobuf `oneof`s types are not named, so +`prost` uses the name of the `oneof` field for the resulting Rust enum, and +defines the enum in a module under the struct. For example, a `proto3` message +such as: + +```protobuf,ignore +message Foo { + oneof widget { + int32 quux = 1; + string bar = 2; + } +} +``` + +generates the following Rust[^3]: + +```rust,ignore +pub struct Foo { + pub widget: Option<foo::Widget>, +} +pub mod foo { + pub enum Widget { + Quux(i32), + Bar(String), + } +} +``` + +`oneof` fields are always wrapped in an `Option`. + +[^3]: Annotations have been elided for clarity. See below for a full example. + +### Services + +`prost-build` allows a custom code-generator to be used for processing `service` +definitions. This can be used to output Rust traits according to an +application's specific needs. + +### Generated Code Example + +Example `.proto` file: + +```protobuf,ignore +syntax = "proto3"; +package tutorial; + +message Person { + string name = 1; + int32 id = 2; // Unique ID number for this person. + string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + string number = 1; + PhoneType type = 2; + } + + repeated PhoneNumber phones = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person people = 1; +} +``` + +and the generated Rust code (`tutorial.rs`): + +```rust,ignore +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Person { + #[prost(string, tag="1")] + pub name: ::prost::alloc::string::String, + /// Unique ID number for this person. + #[prost(int32, tag="2")] + pub id: i32, + #[prost(string, tag="3")] + pub email: ::prost::alloc::string::String, + #[prost(message, repeated, tag="4")] + pub phones: ::prost::alloc::vec::Vec<person::PhoneNumber>, +} +/// Nested message and enum types in `Person`. +pub mod person { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct PhoneNumber { + #[prost(string, tag="1")] + pub number: ::prost::alloc::string::String, + #[prost(enumeration="PhoneType", tag="2")] + pub r#type: i32, + } + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum PhoneType { + Mobile = 0, + Home = 1, + Work = 2, + } +} +/// Our address book file is just one of these. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AddressBook { + #[prost(message, repeated, tag="1")] + pub people: ::prost::alloc::vec::Vec<Person>, +} +``` + +## Accessing the `protoc` `FileDescriptorSet` + +The `prost_build::Config::file_descriptor_set_path` option can be used to emit a file descriptor set +during the build & code generation step. When used in conjunction with the `std::include_bytes` +macro and the `prost_types::FileDescriptorSet` type, applications and libraries using Prost can +implement introspection capabilities requiring details from the original `.proto` files. + +## Using `prost` in a `no_std` Crate + +`prost` is compatible with `no_std` crates. To enable `no_std` support, disable +the `std` features in `prost` and `prost-types`: + +```ignore +[dependencies] +prost = { version = "0.13.5", default-features = false, features = ["prost-derive"] } +# Only necessary if using Protobuf well-known types: +prost-types = { version = "0.13.5", default-features = false } +``` + +Additionally, configure `prost-build` to output `BTreeMap`s instead of `HashMap`s +for all Protobuf `map` fields in your `build.rs`: + +```rust,ignore +let mut config = prost_build::Config::new(); +config.btree_map(&["."]); +``` + +When using edition 2015, it may be necessary to add an `extern crate core;` +directive to the crate which includes `prost`-generated code. + +## Serializing Existing Types + +`prost` uses a custom derive macro to handle encoding and decoding types, which +means that if your existing Rust type is compatible with Protobuf types, you can +serialize and deserialize it by adding the appropriate derive and field +annotations. + +Currently the best documentation on adding annotations is to look at the +generated code examples above. + +### Tag Inference for Existing Types + +Prost automatically infers tags for the struct. + +Fields are tagged sequentially in the order they +are specified, starting with `1`. + +You may skip tags which have been reserved, or where there are gaps between +sequentially occurring tag values by specifying the tag number to skip to with +the `tag` attribute on the first field after the gap. The following fields will +be tagged sequentially starting from the next number. + +```rust,ignore +use prost; +use prost::{Enumeration, Message}; + +#[derive(Clone, PartialEq, Message)] +struct Person { + #[prost(string, tag = "1")] + pub id: String, // tag=1 + // NOTE: Old "name" field has been removed + // pub name: String, // tag=2 (Removed) + #[prost(string, tag = "6")] + pub given_name: String, // tag=6 + #[prost(string)] + pub family_name: String, // tag=7 + #[prost(string)] + pub formatted_name: String, // tag=8 + #[prost(uint32, tag = "3")] + pub age: u32, // tag=3 + #[prost(uint32)] + pub height: u32, // tag=4 + #[prost(enumeration = "Gender")] + pub gender: i32, // tag=5 + // NOTE: Skip to less commonly occurring fields + #[prost(string, tag = "16")] + pub name_prefix: String, // tag=16 (eg. mr/mrs/ms) + #[prost(string)] + pub name_suffix: String, // tag=17 (eg. jr/esq) + #[prost(string)] + pub maiden_name: String, // tag=18 +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Enumeration)] +pub enum Gender { + Unknown = 0, + Female = 1, + Male = 2, +} +``` + +## Nix + +The prost project maintains flakes support for local development. Once you have +nix and nix flakes setup you can just run `nix develop` to get a shell +configured with the required dependencies to compile the whole project. + +## Feature Flags +- `std`: Enable integration with standard library. Disable this feature for `no_std` support. This feature is enabled by default. +- `derive`: Enable integration with `prost-derive`. Disable this feature to reduce compile times. This feature is enabled by default. +- `prost-derive`: Deprecated. Alias for `derive` feature. +- `no-recursion-limit`: Disable the recursion limit. The recursion limit is 100 and cannot be customized. + +## FAQ + +1. **Could `prost` be implemented as a serializer for [Serde](https://serde.rs/)?** + + Probably not, however I would like to hear from a Serde expert on the matter. + There are two complications with trying to serialize Protobuf messages with + Serde: + + - Protobuf fields require a numbered tag, and currently there appears to be no + mechanism suitable for this in `serde`. + - The mapping of Protobuf type to Rust type is not 1-to-1. As a result, + trait-based approaches to dispatching don't work very well. Example: six + different Protobuf field types correspond to a Rust `Vec<i32>`: `repeated + int32`, `repeated sint32`, `repeated sfixed32`, and their packed + counterparts. + + But it is possible to place `serde` derive tags onto the generated types, so + the same structure can support both `prost` and `Serde`. + +2. **I get errors when trying to run `cargo test` on MacOS** + + If the errors are about missing `autoreconf` or similar, you can probably fix + them by running + + ```ignore + brew install automake + brew install libtool + ``` + +## License + +`prost` is distributed under the terms of the Apache License (Version 2.0). + +See [LICENSE](https://github.com/tokio-rs/prost/blob/master/LICENSE) for details. + +Copyright 2022 Dan Burkert & Tokio Contributors diff --git a/vendor/prost/benches/varint.rs b/vendor/prost/benches/varint.rs new file mode 100644 index 00000000..b09dc21c --- /dev/null +++ b/vendor/prost/benches/varint.rs @@ -0,0 +1,99 @@ +use std::mem; + +use bytes::Buf; +use criterion::{Criterion, Throughput}; +use prost::encoding::varint::{decode_varint, encode_varint, encoded_len_varint}; +use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; + +fn benchmark_varint(criterion: &mut Criterion, name: &str, mut values: Vec<u64>) { + // Shuffle the values in a stable order. + values.shuffle(&mut StdRng::seed_from_u64(0)); + let name = format!("varint/{}", name); + + let encoded_len = values + .iter() + .cloned() + .map(encoded_len_varint) + .sum::<usize>() as u64; + let decoded_len = (values.len() * mem::size_of::<u64>()) as u64; + + criterion + .benchmark_group(&name) + .bench_function("encode", { + let encode_values = values.clone(); + move |b| { + let mut buf = Vec::<u8>::with_capacity(encode_values.len() * 10); + b.iter(|| { + buf.clear(); + for &value in &encode_values { + encode_varint(value, &mut buf); + } + criterion::black_box(&buf); + }) + } + }) + .throughput(Throughput::Bytes(encoded_len)); + + criterion + .benchmark_group(&name) + .bench_function("decode", { + let decode_values = values.clone(); + + move |b| { + let mut buf = Vec::with_capacity(decode_values.len() * 10); + for &value in &decode_values { + encode_varint(value, &mut buf); + } + + b.iter(|| { + let mut buf = &mut buf.as_slice(); + while buf.has_remaining() { + let result = decode_varint(&mut buf); + debug_assert!(result.is_ok()); + criterion::black_box(&result); + } + }) + } + }) + .throughput(Throughput::Bytes(decoded_len)); + + criterion + .benchmark_group(&name) + .bench_function("encoded_len", move |b| { + b.iter(|| { + let mut sum = 0; + for &value in &values { + sum += encoded_len_varint(value); + } + criterion::black_box(sum); + }) + }) + .throughput(Throughput::Bytes(decoded_len)); +} + +fn main() { + let mut criterion = Criterion::default().configure_from_args(); + + // Benchmark encoding and decoding 100 small (1 byte) varints. + benchmark_varint(&mut criterion, "small", (0..100).collect()); + + // Benchmark encoding and decoding 100 medium (5 byte) varints. + benchmark_varint(&mut criterion, "medium", (1 << 28..).take(100).collect()); + + // Benchmark encoding and decoding 100 large (10 byte) varints. + benchmark_varint(&mut criterion, "large", (1 << 63..).take(100).collect()); + + // Benchmark encoding and decoding 100 varints of mixed width (average 5.5 bytes). + benchmark_varint( + &mut criterion, + "mixed", + (0..10) + .flat_map(move |width| { + let exponent = width * 7; + (0..10).map(move |offset| offset + (1 << exponent)) + }) + .collect(), + ); + + criterion.final_summary(); +} diff --git a/vendor/prost/src/encoding.rs b/vendor/prost/src/encoding.rs new file mode 100644 index 00000000..8fd7cbf0 --- /dev/null +++ b/vendor/prost/src/encoding.rs @@ -0,0 +1,1428 @@ +//! Utility functions and types for encoding and decoding Protobuf types. +//! +//! Meant to be used only from `Message` implementations. + +#![allow(clippy::implicit_hasher, clippy::ptr_arg)] + +use alloc::collections::BTreeMap; +use alloc::format; +use alloc::string::String; +use alloc::vec::Vec; +use core::mem; +use core::str; + +use ::bytes::{Buf, BufMut, Bytes}; + +use crate::DecodeError; +use crate::Message; + +pub mod varint; +pub use varint::{decode_varint, encode_varint, encoded_len_varint}; + +pub mod length_delimiter; +pub use length_delimiter::{ + decode_length_delimiter, encode_length_delimiter, length_delimiter_len, +}; + +pub mod wire_type; +pub use wire_type::{check_wire_type, WireType}; + +/// Additional information passed to every decode/merge function. +/// +/// The context should be passed by value and can be freely cloned. When passing +/// to a function which is decoding a nested object, then use `enter_recursion`. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "no-recursion-limit", derive(Default))] +pub struct DecodeContext { + /// How many times we can recurse in the current decode stack before we hit + /// the recursion limit. + /// + /// The recursion limit is defined by `RECURSION_LIMIT` and cannot be + /// customized. The recursion limit can be ignored by building the Prost + /// crate with the `no-recursion-limit` feature. + #[cfg(not(feature = "no-recursion-limit"))] + recurse_count: u32, +} + +#[cfg(not(feature = "no-recursion-limit"))] +impl Default for DecodeContext { + #[inline] + fn default() -> DecodeContext { + DecodeContext { + recurse_count: crate::RECURSION_LIMIT, + } + } +} + +impl DecodeContext { + /// Call this function before recursively decoding. + /// + /// There is no `exit` function since this function creates a new `DecodeContext` + /// to be used at the next level of recursion. Continue to use the old context + // at the previous level of recursion. + #[cfg(not(feature = "no-recursion-limit"))] + #[inline] + pub(crate) fn enter_recursion(&self) -> DecodeContext { + DecodeContext { + recurse_count: self.recurse_count - 1, + } + } + + #[cfg(feature = "no-recursion-limit")] + #[inline] + pub(crate) fn enter_recursion(&self) -> DecodeContext { + DecodeContext {} + } + + /// Checks whether the recursion limit has been reached in the stack of + /// decodes described by the `DecodeContext` at `self.ctx`. + /// + /// Returns `Ok<()>` if it is ok to continue recursing. + /// Returns `Err<DecodeError>` if the recursion limit has been reached. + #[cfg(not(feature = "no-recursion-limit"))] + #[inline] + pub(crate) fn limit_reached(&self) -> Result<(), DecodeError> { + if self.recurse_count == 0 { + Err(DecodeError::new("recursion limit reached")) + } else { + Ok(()) + } + } + + #[cfg(feature = "no-recursion-limit")] + #[inline] + #[allow(clippy::unnecessary_wraps)] // needed in other features + pub(crate) fn limit_reached(&self) -> Result<(), DecodeError> { + Ok(()) + } +} + +pub const MIN_TAG: u32 = 1; +pub const MAX_TAG: u32 = (1 << 29) - 1; + +/// Encodes a Protobuf field key, which consists of a wire type designator and +/// the field tag. +#[inline] +pub fn encode_key(tag: u32, wire_type: WireType, buf: &mut impl BufMut) { + debug_assert!((MIN_TAG..=MAX_TAG).contains(&tag)); + let key = (tag << 3) | wire_type as u32; + encode_varint(u64::from(key), buf); +} + +/// Decodes a Protobuf field key, which consists of a wire type designator and +/// the field tag. +#[inline(always)] +pub fn decode_key(buf: &mut impl Buf) -> Result<(u32, WireType), DecodeError> { + let key = decode_varint(buf)?; + if key > u64::from(u32::MAX) { + return Err(DecodeError::new(format!("invalid key value: {}", key))); + } + let wire_type = WireType::try_from(key & 0x07)?; + let tag = key as u32 >> 3; + + if tag < MIN_TAG { + return Err(DecodeError::new("invalid tag value: 0")); + } + + Ok((tag, wire_type)) +} + +/// Returns the width of an encoded Protobuf field key with the given tag. +/// The returned width will be between 1 and 5 bytes (inclusive). +#[inline] +pub const fn key_len(tag: u32) -> usize { + encoded_len_varint((tag << 3) as u64) +} + +/// Helper function which abstracts reading a length delimiter prefix followed +/// by decoding values until the length of bytes is exhausted. +pub fn merge_loop<T, M, B>( + value: &mut T, + buf: &mut B, + ctx: DecodeContext, + mut merge: M, +) -> Result<(), DecodeError> +where + M: FnMut(&mut T, &mut B, DecodeContext) -> Result<(), DecodeError>, + B: Buf, +{ + let len = decode_varint(buf)?; + let remaining = buf.remaining(); + if len > remaining as u64 { + return Err(DecodeError::new("buffer underflow")); + } + + let limit = remaining - len as usize; + while buf.remaining() > limit { + merge(value, buf, ctx.clone())?; + } + + if buf.remaining() != limit { + return Err(DecodeError::new("delimited length exceeded")); + } + Ok(()) +} + +pub fn skip_field( + wire_type: WireType, + tag: u32, + buf: &mut impl Buf, + ctx: DecodeContext, +) -> Result<(), DecodeError> { + ctx.limit_reached()?; + let len = match wire_type { + WireType::Varint => decode_varint(buf).map(|_| 0)?, + WireType::ThirtyTwoBit => 4, + WireType::SixtyFourBit => 8, + WireType::LengthDelimited => decode_varint(buf)?, + WireType::StartGroup => loop { + let (inner_tag, inner_wire_type) = decode_key(buf)?; + match inner_wire_type { + WireType::EndGroup => { + if inner_tag != tag { + return Err(DecodeError::new("unexpected end group tag")); + } + break 0; + } + _ => skip_field(inner_wire_type, inner_tag, buf, ctx.enter_recursion())?, + } + }, + WireType::EndGroup => return Err(DecodeError::new("unexpected end group tag")), + }; + + if len > buf.remaining() as u64 { + return Err(DecodeError::new("buffer underflow")); + } + + buf.advance(len as usize); + Ok(()) +} + +/// Helper macro which emits an `encode_repeated` function for the type. +macro_rules! encode_repeated { + ($ty:ty) => { + pub fn encode_repeated(tag: u32, values: &[$ty], buf: &mut impl BufMut) { + for value in values { + encode(tag, value, buf); + } + } + }; +} + +/// Helper macro which emits a `merge_repeated` function for the numeric type. +macro_rules! merge_repeated_numeric { + ($ty:ty, + $wire_type:expr, + $merge:ident, + $merge_repeated:ident) => { + pub fn $merge_repeated( + wire_type: WireType, + values: &mut Vec<$ty>, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if wire_type == WireType::LengthDelimited { + // Packed. + merge_loop(values, buf, ctx, |values, buf, ctx| { + let mut value = Default::default(); + $merge($wire_type, &mut value, buf, ctx)?; + values.push(value); + Ok(()) + }) + } else { + // Unpacked. + check_wire_type($wire_type, wire_type)?; + let mut value = Default::default(); + $merge(wire_type, &mut value, buf, ctx)?; + values.push(value); + Ok(()) + } + } + }; +} + +/// Macro which emits a module containing a set of encoding functions for a +/// variable width numeric type. +macro_rules! varint { + ($ty:ty, + $proto_ty:ident) => ( + varint!($ty, + $proto_ty, + to_uint64(value) { *value as u64 }, + from_uint64(value) { value as $ty }); + ); + + ($ty:ty, + $proto_ty:ident, + to_uint64($to_uint64_value:ident) $to_uint64:expr, + from_uint64($from_uint64_value:ident) $from_uint64:expr) => ( + + pub mod $proto_ty { + use crate::encoding::*; + + pub fn encode(tag: u32, $to_uint64_value: &$ty, buf: &mut impl BufMut) { + encode_key(tag, WireType::Varint, buf); + encode_varint($to_uint64, buf); + } + + pub fn merge(wire_type: WireType, value: &mut $ty, buf: &mut impl Buf, _ctx: DecodeContext) -> Result<(), DecodeError> { + check_wire_type(WireType::Varint, wire_type)?; + let $from_uint64_value = decode_varint(buf)?; + *value = $from_uint64; + Ok(()) + } + + encode_repeated!($ty); + + pub fn encode_packed(tag: u32, values: &[$ty], buf: &mut impl BufMut) { + if values.is_empty() { return; } + + encode_key(tag, WireType::LengthDelimited, buf); + let len: usize = values.iter().map(|$to_uint64_value| { + encoded_len_varint($to_uint64) + }).sum(); + encode_varint(len as u64, buf); + + for $to_uint64_value in values { + encode_varint($to_uint64, buf); + } + } + + merge_repeated_numeric!($ty, WireType::Varint, merge, merge_repeated); + + #[inline] + pub fn encoded_len(tag: u32, $to_uint64_value: &$ty) -> usize { + key_len(tag) + encoded_len_varint($to_uint64) + } + + #[inline] + pub fn encoded_len_repeated(tag: u32, values: &[$ty]) -> usize { + key_len(tag) * values.len() + values.iter().map(|$to_uint64_value| { + encoded_len_varint($to_uint64) + }).sum::<usize>() + } + + #[inline] + pub fn encoded_len_packed(tag: u32, values: &[$ty]) -> usize { + if values.is_empty() { + 0 + } else { + let len = values.iter() + .map(|$to_uint64_value| encoded_len_varint($to_uint64)) + .sum::<usize>(); + key_len(tag) + encoded_len_varint(len as u64) + len + } + } + + #[cfg(test)] + mod test { + use proptest::prelude::*; + + use crate::encoding::$proto_ty::*; + use crate::encoding::test::{ + check_collection_type, + check_type, + }; + + proptest! { + #[test] + fn check(value: $ty, tag in MIN_TAG..=MAX_TAG) { + check_type(value, tag, WireType::Varint, + encode, merge, encoded_len)?; + } + #[test] + fn check_repeated(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) { + check_collection_type(value, tag, WireType::Varint, + encode_repeated, merge_repeated, + encoded_len_repeated)?; + } + #[test] + fn check_packed(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) { + check_type(value, tag, WireType::LengthDelimited, + encode_packed, merge_repeated, + encoded_len_packed)?; + } + } + } + } + + ); +} +varint!(bool, bool, + to_uint64(value) u64::from(*value), + from_uint64(value) value != 0); +varint!(i32, int32); +varint!(i64, int64); +varint!(u32, uint32); +varint!(u64, uint64); +varint!(i32, sint32, +to_uint64(value) { + ((value << 1) ^ (value >> 31)) as u32 as u64 +}, +from_uint64(value) { + let value = value as u32; + ((value >> 1) as i32) ^ (-((value & 1) as i32)) +}); +varint!(i64, sint64, +to_uint64(value) { + ((value << 1) ^ (value >> 63)) as u64 +}, +from_uint64(value) { + ((value >> 1) as i64) ^ (-((value & 1) as i64)) +}); + +/// Macro which emits a module containing a set of encoding functions for a +/// fixed width numeric type. +macro_rules! fixed_width { + ($ty:ty, + $width:expr, + $wire_type:expr, + $proto_ty:ident, + $put:ident, + $get:ident) => { + pub mod $proto_ty { + use crate::encoding::*; + + pub fn encode(tag: u32, value: &$ty, buf: &mut impl BufMut) { + encode_key(tag, $wire_type, buf); + buf.$put(*value); + } + + pub fn merge( + wire_type: WireType, + value: &mut $ty, + buf: &mut impl Buf, + _ctx: DecodeContext, + ) -> Result<(), DecodeError> { + check_wire_type($wire_type, wire_type)?; + if buf.remaining() < $width { + return Err(DecodeError::new("buffer underflow")); + } + *value = buf.$get(); + Ok(()) + } + + encode_repeated!($ty); + + pub fn encode_packed(tag: u32, values: &[$ty], buf: &mut impl BufMut) { + if values.is_empty() { + return; + } + + encode_key(tag, WireType::LengthDelimited, buf); + let len = values.len() as u64 * $width; + encode_varint(len as u64, buf); + + for value in values { + buf.$put(*value); + } + } + + merge_repeated_numeric!($ty, $wire_type, merge, merge_repeated); + + #[inline] + pub fn encoded_len(tag: u32, _: &$ty) -> usize { + key_len(tag) + $width + } + + #[inline] + pub fn encoded_len_repeated(tag: u32, values: &[$ty]) -> usize { + (key_len(tag) + $width) * values.len() + } + + #[inline] + pub fn encoded_len_packed(tag: u32, values: &[$ty]) -> usize { + if values.is_empty() { + 0 + } else { + let len = $width * values.len(); + key_len(tag) + encoded_len_varint(len as u64) + len + } + } + + #[cfg(test)] + mod test { + use proptest::prelude::*; + + use super::super::test::{check_collection_type, check_type}; + use super::*; + + proptest! { + #[test] + fn check(value: $ty, tag in MIN_TAG..=MAX_TAG) { + check_type(value, tag, $wire_type, + encode, merge, encoded_len)?; + } + #[test] + fn check_repeated(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) { + check_collection_type(value, tag, $wire_type, + encode_repeated, merge_repeated, + encoded_len_repeated)?; + } + #[test] + fn check_packed(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) { + check_type(value, tag, WireType::LengthDelimited, + encode_packed, merge_repeated, + encoded_len_packed)?; + } + } + } + } + }; +} +fixed_width!( + f32, + 4, + WireType::ThirtyTwoBit, + float, + put_f32_le, + get_f32_le +); +fixed_width!( + f64, + 8, + WireType::SixtyFourBit, + double, + put_f64_le, + get_f64_le +); +fixed_width!( + u32, + 4, + WireType::ThirtyTwoBit, + fixed32, + put_u32_le, + get_u32_le +); +fixed_width!( + u64, + 8, + WireType::SixtyFourBit, + fixed64, + put_u64_le, + get_u64_le +); +fixed_width!( + i32, + 4, + WireType::ThirtyTwoBit, + sfixed32, + put_i32_le, + get_i32_le +); +fixed_width!( + i64, + 8, + WireType::SixtyFourBit, + sfixed64, + put_i64_le, + get_i64_le +); + +/// Macro which emits encoding functions for a length-delimited type. +macro_rules! length_delimited { + ($ty:ty) => { + encode_repeated!($ty); + + pub fn merge_repeated( + wire_type: WireType, + values: &mut Vec<$ty>, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + check_wire_type(WireType::LengthDelimited, wire_type)?; + let mut value = Default::default(); + merge(wire_type, &mut value, buf, ctx)?; + values.push(value); + Ok(()) + } + + #[inline] + pub fn encoded_len(tag: u32, value: &$ty) -> usize { + key_len(tag) + encoded_len_varint(value.len() as u64) + value.len() + } + + #[inline] + pub fn encoded_len_repeated(tag: u32, values: &[$ty]) -> usize { + key_len(tag) * values.len() + + values + .iter() + .map(|value| encoded_len_varint(value.len() as u64) + value.len()) + .sum::<usize>() + } + }; +} + +pub mod string { + use super::*; + + pub fn encode(tag: u32, value: &String, buf: &mut impl BufMut) { + encode_key(tag, WireType::LengthDelimited, buf); + encode_varint(value.len() as u64, buf); + buf.put_slice(value.as_bytes()); + } + + pub fn merge( + wire_type: WireType, + value: &mut String, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + // ## Unsafety + // + // `string::merge` reuses `bytes::merge`, with an additional check of utf-8 + // well-formedness. If the utf-8 is not well-formed, or if any other error occurs, then the + // string is cleared, so as to avoid leaking a string field with invalid data. + // + // This implementation uses the unsafe `String::as_mut_vec` method instead of the safe + // alternative of temporarily swapping an empty `String` into the field, because it results + // in up to 10% better performance on the protobuf message decoding benchmarks. + // + // It's required when using `String::as_mut_vec` that invalid utf-8 data not be leaked into + // the backing `String`. To enforce this, even in the event of a panic in `bytes::merge` or + // in the buf implementation, a drop guard is used. + unsafe { + struct DropGuard<'a>(&'a mut Vec<u8>); + impl Drop for DropGuard<'_> { + #[inline] + fn drop(&mut self) { + self.0.clear(); + } + } + + let drop_guard = DropGuard(value.as_mut_vec()); + bytes::merge_one_copy(wire_type, drop_guard.0, buf, ctx)?; + match str::from_utf8(drop_guard.0) { + Ok(_) => { + // Success; do not clear the bytes. + mem::forget(drop_guard); + Ok(()) + } + Err(_) => Err(DecodeError::new( + "invalid string value: data is not UTF-8 encoded", + )), + } + } + } + + length_delimited!(String); + + #[cfg(test)] + mod test { + use proptest::prelude::*; + + use super::super::test::{check_collection_type, check_type}; + use super::*; + + proptest! { + #[test] + fn check(value: String, tag in MIN_TAG..=MAX_TAG) { + super::test::check_type(value, tag, WireType::LengthDelimited, + encode, merge, encoded_len)?; + } + #[test] + fn check_repeated(value: Vec<String>, tag in MIN_TAG..=MAX_TAG) { + super::test::check_collection_type(value, tag, WireType::LengthDelimited, + encode_repeated, merge_repeated, + encoded_len_repeated)?; + } + } + } +} + +pub trait BytesAdapter: sealed::BytesAdapter {} + +mod sealed { + use super::{Buf, BufMut}; + + pub trait BytesAdapter: Default + Sized + 'static { + fn len(&self) -> usize; + + /// Replace contents of this buffer with the contents of another buffer. + fn replace_with(&mut self, buf: impl Buf); + + /// Appends this buffer to the (contents of) other buffer. + fn append_to(&self, buf: &mut impl BufMut); + + fn is_empty(&self) -> bool { + self.len() == 0 + } + } +} + +impl BytesAdapter for Bytes {} + +impl sealed::BytesAdapter for Bytes { + fn len(&self) -> usize { + Buf::remaining(self) + } + + fn replace_with(&mut self, mut buf: impl Buf) { + *self = buf.copy_to_bytes(buf.remaining()); + } + + fn append_to(&self, buf: &mut impl BufMut) { + buf.put(self.clone()) + } +} + +impl BytesAdapter for Vec<u8> {} + +impl sealed::BytesAdapter for Vec<u8> { + fn len(&self) -> usize { + Vec::len(self) + } + + fn replace_with(&mut self, buf: impl Buf) { + self.clear(); + self.reserve(buf.remaining()); + self.put(buf); + } + + fn append_to(&self, buf: &mut impl BufMut) { + buf.put(self.as_slice()) + } +} + +pub mod bytes { + use super::*; + + pub fn encode(tag: u32, value: &impl BytesAdapter, buf: &mut impl BufMut) { + encode_key(tag, WireType::LengthDelimited, buf); + encode_varint(value.len() as u64, buf); + value.append_to(buf); + } + + pub fn merge( + wire_type: WireType, + value: &mut impl BytesAdapter, + buf: &mut impl Buf, + _ctx: DecodeContext, + ) -> Result<(), DecodeError> { + check_wire_type(WireType::LengthDelimited, wire_type)?; + let len = decode_varint(buf)?; + if len > buf.remaining() as u64 { + return Err(DecodeError::new("buffer underflow")); + } + let len = len as usize; + + // Clear the existing value. This follows from the following rule in the encoding guide[1]: + // + // > Normally, an encoded message would never have more than one instance of a non-repeated + // > field. However, parsers are expected to handle the case in which they do. For numeric + // > types and strings, if the same field appears multiple times, the parser accepts the + // > last value it sees. + // + // [1]: https://developers.google.com/protocol-buffers/docs/encoding#optional + // + // This is intended for A and B both being Bytes so it is zero-copy. + // Some combinations of A and B types may cause a double-copy, + // in which case merge_one_copy() should be used instead. + value.replace_with(buf.copy_to_bytes(len)); + Ok(()) + } + + pub(super) fn merge_one_copy( + wire_type: WireType, + value: &mut impl BytesAdapter, + buf: &mut impl Buf, + _ctx: DecodeContext, + ) -> Result<(), DecodeError> { + check_wire_type(WireType::LengthDelimited, wire_type)?; + let len = decode_varint(buf)?; + if len > buf.remaining() as u64 { + return Err(DecodeError::new("buffer underflow")); + } + let len = len as usize; + + // If we must copy, make sure to copy only once. + value.replace_with(buf.take(len)); + Ok(()) + } + + length_delimited!(impl BytesAdapter); + + #[cfg(test)] + mod test { + use proptest::prelude::*; + + use super::super::test::{check_collection_type, check_type}; + use super::*; + + proptest! { + #[test] + fn check_vec(value: Vec<u8>, tag in MIN_TAG..=MAX_TAG) { + super::test::check_type::<Vec<u8>, Vec<u8>>(value, tag, WireType::LengthDelimited, + encode, merge, encoded_len)?; + } + + #[test] + fn check_bytes(value: Vec<u8>, tag in MIN_TAG..=MAX_TAG) { + let value = Bytes::from(value); + super::test::check_type::<Bytes, Bytes>(value, tag, WireType::LengthDelimited, + encode, merge, encoded_len)?; + } + + #[test] + fn check_repeated_vec(value: Vec<Vec<u8>>, tag in MIN_TAG..=MAX_TAG) { + super::test::check_collection_type(value, tag, WireType::LengthDelimited, + encode_repeated, merge_repeated, + encoded_len_repeated)?; + } + + #[test] + fn check_repeated_bytes(value: Vec<Vec<u8>>, tag in MIN_TAG..=MAX_TAG) { + let value = value.into_iter().map(Bytes::from).collect(); + super::test::check_collection_type(value, tag, WireType::LengthDelimited, + encode_repeated, merge_repeated, + encoded_len_repeated)?; + } + } + } +} + +pub mod message { + use super::*; + + pub fn encode<M>(tag: u32, msg: &M, buf: &mut impl BufMut) + where + M: Message, + { + encode_key(tag, WireType::LengthDelimited, buf); + encode_varint(msg.encoded_len() as u64, buf); + msg.encode_raw(buf); + } + + pub fn merge<M, B>( + wire_type: WireType, + msg: &mut M, + buf: &mut B, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + M: Message, + B: Buf, + { + check_wire_type(WireType::LengthDelimited, wire_type)?; + ctx.limit_reached()?; + merge_loop( + msg, + buf, + ctx.enter_recursion(), + |msg: &mut M, buf: &mut B, ctx| { + let (tag, wire_type) = decode_key(buf)?; + msg.merge_field(tag, wire_type, buf, ctx) + }, + ) + } + + pub fn encode_repeated<M>(tag: u32, messages: &[M], buf: &mut impl BufMut) + where + M: Message, + { + for msg in messages { + encode(tag, msg, buf); + } + } + + pub fn merge_repeated<M>( + wire_type: WireType, + messages: &mut Vec<M>, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + M: Message + Default, + { + check_wire_type(WireType::LengthDelimited, wire_type)?; + let mut msg = M::default(); + merge(WireType::LengthDelimited, &mut msg, buf, ctx)?; + messages.push(msg); + Ok(()) + } + + #[inline] + pub fn encoded_len<M>(tag: u32, msg: &M) -> usize + where + M: Message, + { + let len = msg.encoded_len(); + key_len(tag) + encoded_len_varint(len as u64) + len + } + + #[inline] + pub fn encoded_len_repeated<M>(tag: u32, messages: &[M]) -> usize + where + M: Message, + { + key_len(tag) * messages.len() + + messages + .iter() + .map(Message::encoded_len) + .map(|len| len + encoded_len_varint(len as u64)) + .sum::<usize>() + } +} + +pub mod group { + use super::*; + + pub fn encode<M>(tag: u32, msg: &M, buf: &mut impl BufMut) + where + M: Message, + { + encode_key(tag, WireType::StartGroup, buf); + msg.encode_raw(buf); + encode_key(tag, WireType::EndGroup, buf); + } + + pub fn merge<M>( + tag: u32, + wire_type: WireType, + msg: &mut M, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + M: Message, + { + check_wire_type(WireType::StartGroup, wire_type)?; + + ctx.limit_reached()?; + loop { + let (field_tag, field_wire_type) = decode_key(buf)?; + if field_wire_type == WireType::EndGroup { + if field_tag != tag { + return Err(DecodeError::new("unexpected end group tag")); + } + return Ok(()); + } + + M::merge_field(msg, field_tag, field_wire_type, buf, ctx.enter_recursion())?; + } + } + + pub fn encode_repeated<M>(tag: u32, messages: &[M], buf: &mut impl BufMut) + where + M: Message, + { + for msg in messages { + encode(tag, msg, buf); + } + } + + pub fn merge_repeated<M>( + tag: u32, + wire_type: WireType, + messages: &mut Vec<M>, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + M: Message + Default, + { + check_wire_type(WireType::StartGroup, wire_type)?; + let mut msg = M::default(); + merge(tag, WireType::StartGroup, &mut msg, buf, ctx)?; + messages.push(msg); + Ok(()) + } + + #[inline] + pub fn encoded_len<M>(tag: u32, msg: &M) -> usize + where + M: Message, + { + 2 * key_len(tag) + msg.encoded_len() + } + + #[inline] + pub fn encoded_len_repeated<M>(tag: u32, messages: &[M]) -> usize + where + M: Message, + { + 2 * key_len(tag) * messages.len() + messages.iter().map(Message::encoded_len).sum::<usize>() + } +} + +/// Rust doesn't have a `Map` trait, so macros are currently the best way to be +/// generic over `HashMap` and `BTreeMap`. +macro_rules! map { + ($map_ty:ident) => { + use crate::encoding::*; + use core::hash::Hash; + + /// Generic protobuf map encode function. + pub fn encode<K, V, B, KE, KL, VE, VL>( + key_encode: KE, + key_encoded_len: KL, + val_encode: VE, + val_encoded_len: VL, + tag: u32, + values: &$map_ty<K, V>, + buf: &mut B, + ) where + K: Default + Eq + Hash + Ord, + V: Default + PartialEq, + B: BufMut, + KE: Fn(u32, &K, &mut B), + KL: Fn(u32, &K) -> usize, + VE: Fn(u32, &V, &mut B), + VL: Fn(u32, &V) -> usize, + { + encode_with_default( + key_encode, + key_encoded_len, + val_encode, + val_encoded_len, + &V::default(), + tag, + values, + buf, + ) + } + + /// Generic protobuf map merge function. + pub fn merge<K, V, B, KM, VM>( + key_merge: KM, + val_merge: VM, + values: &mut $map_ty<K, V>, + buf: &mut B, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + K: Default + Eq + Hash + Ord, + V: Default, + B: Buf, + KM: Fn(WireType, &mut K, &mut B, DecodeContext) -> Result<(), DecodeError>, + VM: Fn(WireType, &mut V, &mut B, DecodeContext) -> Result<(), DecodeError>, + { + merge_with_default(key_merge, val_merge, V::default(), values, buf, ctx) + } + + /// Generic protobuf map encode function. + pub fn encoded_len<K, V, KL, VL>( + key_encoded_len: KL, + val_encoded_len: VL, + tag: u32, + values: &$map_ty<K, V>, + ) -> usize + where + K: Default + Eq + Hash + Ord, + V: Default + PartialEq, + KL: Fn(u32, &K) -> usize, + VL: Fn(u32, &V) -> usize, + { + encoded_len_with_default(key_encoded_len, val_encoded_len, &V::default(), tag, values) + } + + /// Generic protobuf map encode function with an overridden value default. + /// + /// This is necessary because enumeration values can have a default value other + /// than 0 in proto2. + pub fn encode_with_default<K, V, B, KE, KL, VE, VL>( + key_encode: KE, + key_encoded_len: KL, + val_encode: VE, + val_encoded_len: VL, + val_default: &V, + tag: u32, + values: &$map_ty<K, V>, + buf: &mut B, + ) where + K: Default + Eq + Hash + Ord, + V: PartialEq, + B: BufMut, + KE: Fn(u32, &K, &mut B), + KL: Fn(u32, &K) -> usize, + VE: Fn(u32, &V, &mut B), + VL: Fn(u32, &V) -> usize, + { + for (key, val) in values.iter() { + let skip_key = key == &K::default(); + let skip_val = val == val_default; + + let len = (if skip_key { 0 } else { key_encoded_len(1, key) }) + + (if skip_val { 0 } else { val_encoded_len(2, val) }); + + encode_key(tag, WireType::LengthDelimited, buf); + encode_varint(len as u64, buf); + if !skip_key { + key_encode(1, key, buf); + } + if !skip_val { + val_encode(2, val, buf); + } + } + } + + /// Generic protobuf map merge function with an overridden value default. + /// + /// This is necessary because enumeration values can have a default value other + /// than 0 in proto2. + pub fn merge_with_default<K, V, B, KM, VM>( + key_merge: KM, + val_merge: VM, + val_default: V, + values: &mut $map_ty<K, V>, + buf: &mut B, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + K: Default + Eq + Hash + Ord, + B: Buf, + KM: Fn(WireType, &mut K, &mut B, DecodeContext) -> Result<(), DecodeError>, + VM: Fn(WireType, &mut V, &mut B, DecodeContext) -> Result<(), DecodeError>, + { + let mut key = Default::default(); + let mut val = val_default; + ctx.limit_reached()?; + merge_loop( + &mut (&mut key, &mut val), + buf, + ctx.enter_recursion(), + |&mut (ref mut key, ref mut val), buf, ctx| { + let (tag, wire_type) = decode_key(buf)?; + match tag { + 1 => key_merge(wire_type, key, buf, ctx), + 2 => val_merge(wire_type, val, buf, ctx), + _ => skip_field(wire_type, tag, buf, ctx), + } + }, + )?; + values.insert(key, val); + + Ok(()) + } + + /// Generic protobuf map encode function with an overridden value default. + /// + /// This is necessary because enumeration values can have a default value other + /// than 0 in proto2. + pub fn encoded_len_with_default<K, V, KL, VL>( + key_encoded_len: KL, + val_encoded_len: VL, + val_default: &V, + tag: u32, + values: &$map_ty<K, V>, + ) -> usize + where + K: Default + Eq + Hash + Ord, + V: PartialEq, + KL: Fn(u32, &K) -> usize, + VL: Fn(u32, &V) -> usize, + { + key_len(tag) * values.len() + + values + .iter() + .map(|(key, val)| { + let len = (if key == &K::default() { + 0 + } else { + key_encoded_len(1, key) + }) + (if val == val_default { + 0 + } else { + val_encoded_len(2, val) + }); + encoded_len_varint(len as u64) + len + }) + .sum::<usize>() + } + }; +} + +#[cfg(feature = "std")] +pub mod hash_map { + use std::collections::HashMap; + map!(HashMap); +} + +pub mod btree_map { + map!(BTreeMap); +} + +#[cfg(test)] +mod test { + #[cfg(not(feature = "std"))] + use alloc::string::ToString; + use core::borrow::Borrow; + use core::fmt::Debug; + + use ::bytes::BytesMut; + use proptest::{prelude::*, test_runner::TestCaseResult}; + + use super::*; + + pub fn check_type<T, B>( + value: T, + tag: u32, + wire_type: WireType, + encode: fn(u32, &B, &mut BytesMut), + merge: fn(WireType, &mut T, &mut Bytes, DecodeContext) -> Result<(), DecodeError>, + encoded_len: fn(u32, &B) -> usize, + ) -> TestCaseResult + where + T: Debug + Default + PartialEq + Borrow<B>, + B: ?Sized, + { + prop_assume!((MIN_TAG..=MAX_TAG).contains(&tag)); + + let expected_len = encoded_len(tag, value.borrow()); + + let mut buf = BytesMut::with_capacity(expected_len); + encode(tag, value.borrow(), &mut buf); + + let mut buf = buf.freeze(); + + prop_assert_eq!( + buf.remaining(), + expected_len, + "encoded_len wrong; expected: {}, actual: {}", + expected_len, + buf.remaining() + ); + + if !buf.has_remaining() { + // Short circuit for empty packed values. + return Ok(()); + } + + let (decoded_tag, decoded_wire_type) = + decode_key(&mut buf).map_err(|error| TestCaseError::fail(error.to_string()))?; + prop_assert_eq!( + tag, + decoded_tag, + "decoded tag does not match; expected: {}, actual: {}", + tag, + decoded_tag + ); + + prop_assert_eq!( + wire_type, + decoded_wire_type, + "decoded wire type does not match; expected: {:?}, actual: {:?}", + wire_type, + decoded_wire_type, + ); + + match wire_type { + WireType::SixtyFourBit if buf.remaining() != 8 => Err(TestCaseError::fail(format!( + "64bit wire type illegal remaining: {}, tag: {}", + buf.remaining(), + tag + ))), + WireType::ThirtyTwoBit if buf.remaining() != 4 => Err(TestCaseError::fail(format!( + "32bit wire type illegal remaining: {}, tag: {}", + buf.remaining(), + tag + ))), + _ => Ok(()), + }?; + + let mut roundtrip_value = T::default(); + merge( + wire_type, + &mut roundtrip_value, + &mut buf, + DecodeContext::default(), + ) + .map_err(|error| TestCaseError::fail(error.to_string()))?; + + prop_assert!( + !buf.has_remaining(), + "expected buffer to be empty, remaining: {}", + buf.remaining() + ); + + prop_assert_eq!(value, roundtrip_value); + + Ok(()) + } + + pub fn check_collection_type<T, B, E, M, L>( + value: T, + tag: u32, + wire_type: WireType, + encode: E, + mut merge: M, + encoded_len: L, + ) -> TestCaseResult + where + T: Debug + Default + PartialEq + Borrow<B>, + B: ?Sized, + E: FnOnce(u32, &B, &mut BytesMut), + M: FnMut(WireType, &mut T, &mut Bytes, DecodeContext) -> Result<(), DecodeError>, + L: FnOnce(u32, &B) -> usize, + { + prop_assume!((MIN_TAG..=MAX_TAG).contains(&tag)); + + let expected_len = encoded_len(tag, value.borrow()); + + let mut buf = BytesMut::with_capacity(expected_len); + encode(tag, value.borrow(), &mut buf); + + let mut buf = buf.freeze(); + + prop_assert_eq!( + buf.remaining(), + expected_len, + "encoded_len wrong; expected: {}, actual: {}", + expected_len, + buf.remaining() + ); + + let mut roundtrip_value = Default::default(); + while buf.has_remaining() { + let (decoded_tag, decoded_wire_type) = + decode_key(&mut buf).map_err(|error| TestCaseError::fail(error.to_string()))?; + + prop_assert_eq!( + tag, + decoded_tag, + "decoded tag does not match; expected: {}, actual: {}", + tag, + decoded_tag + ); + + prop_assert_eq!( + wire_type, + decoded_wire_type, + "decoded wire type does not match; expected: {:?}, actual: {:?}", + wire_type, + decoded_wire_type + ); + + merge( + wire_type, + &mut roundtrip_value, + &mut buf, + DecodeContext::default(), + ) + .map_err(|error| TestCaseError::fail(error.to_string()))?; + } + + prop_assert_eq!(value, roundtrip_value); + + Ok(()) + } + + #[test] + fn string_merge_invalid_utf8() { + let mut s = String::new(); + let buf = b"\x02\x80\x80"; + + let r = string::merge( + WireType::LengthDelimited, + &mut s, + &mut &buf[..], + DecodeContext::default(), + ); + r.expect_err("must be an error"); + assert!(s.is_empty()); + } + + /// This big bowl o' macro soup generates an encoding property test for each combination of map + /// type, scalar map key, and value type. + /// TODO: these tests take a long time to compile, can this be improved? + #[cfg(feature = "std")] + macro_rules! map_tests { + (keys: $keys:tt, + vals: $vals:tt) => { + mod hash_map { + map_tests!(@private HashMap, hash_map, $keys, $vals); + } + mod btree_map { + map_tests!(@private BTreeMap, btree_map, $keys, $vals); + } + }; + + (@private $map_type:ident, + $mod_name:ident, + [$(($key_ty:ty, $key_proto:ident)),*], + $vals:tt) => { + $( + mod $key_proto { + use std::collections::$map_type; + + use proptest::prelude::*; + + use crate::encoding::*; + use crate::encoding::test::check_collection_type; + + map_tests!(@private $map_type, $mod_name, ($key_ty, $key_proto), $vals); + } + )* + }; + + (@private $map_type:ident, + $mod_name:ident, + ($key_ty:ty, $key_proto:ident), + [$(($val_ty:ty, $val_proto:ident)),*]) => { + $( + proptest! { + #[test] + fn $val_proto(values: $map_type<$key_ty, $val_ty>, tag in MIN_TAG..=MAX_TAG) { + check_collection_type(values, tag, WireType::LengthDelimited, + |tag, values, buf| { + $mod_name::encode($key_proto::encode, + $key_proto::encoded_len, + $val_proto::encode, + $val_proto::encoded_len, + tag, + values, + buf) + }, + |wire_type, values, buf, ctx| { + check_wire_type(WireType::LengthDelimited, wire_type)?; + $mod_name::merge($key_proto::merge, + $val_proto::merge, + values, + buf, + ctx) + }, + |tag, values| { + $mod_name::encoded_len($key_proto::encoded_len, + $val_proto::encoded_len, + tag, + values) + })?; + } + } + )* + }; + } + + #[cfg(feature = "std")] + map_tests!(keys: [ + (i32, int32), + (i64, int64), + (u32, uint32), + (u64, uint64), + (i32, sint32), + (i64, sint64), + (u32, fixed32), + (u64, fixed64), + (i32, sfixed32), + (i64, sfixed64), + (bool, bool), + (String, string) + ], + vals: [ + (f32, float), + (f64, double), + (i32, int32), + (i64, int64), + (u32, uint32), + (u64, uint64), + (i32, sint32), + (i64, sint64), + (u32, fixed32), + (u64, fixed64), + (i32, sfixed32), + (i64, sfixed64), + (bool, bool), + (String, string), + (Vec<u8>, bytes) + ]); +} diff --git a/vendor/prost/src/encoding/length_delimiter.rs b/vendor/prost/src/encoding/length_delimiter.rs new file mode 100644 index 00000000..6aa7e4cb --- /dev/null +++ b/vendor/prost/src/encoding/length_delimiter.rs @@ -0,0 +1,53 @@ +pub use crate::error::{DecodeError, EncodeError, UnknownEnumValue}; +pub use crate::message::Message; +pub use crate::name::Name; + +use bytes::{Buf, BufMut}; + +use crate::encoding::varint::{decode_varint, encode_varint, encoded_len_varint}; + +/// Encodes a length delimiter to the buffer. +/// +/// See [Message.encode_length_delimited] for more info. +/// +/// An error will be returned if the buffer does not have sufficient capacity to encode the +/// delimiter. +pub fn encode_length_delimiter(length: usize, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let length = length as u64; + let required = encoded_len_varint(length); + let remaining = buf.remaining_mut(); + if required > remaining { + return Err(EncodeError::new(required, remaining)); + } + encode_varint(length, buf); + Ok(()) +} + +/// Returns the encoded length of a length delimiter. +/// +/// Applications may use this method to ensure sufficient buffer capacity before calling +/// `encode_length_delimiter`. The returned size will be between 1 and 10, inclusive. +pub fn length_delimiter_len(length: usize) -> usize { + encoded_len_varint(length as u64) +} + +/// Decodes a length delimiter from the buffer. +/// +/// This method allows the length delimiter to be decoded independently of the message, when the +/// message is encoded with [Message.encode_length_delimited]. +/// +/// An error may be returned in two cases: +/// +/// * If the supplied buffer contains fewer than 10 bytes, then an error indicates that more +/// input is required to decode the full delimiter. +/// * If the supplied buffer contains 10 bytes or more, then the buffer contains an invalid +/// delimiter, and typically the buffer should be considered corrupt. +pub fn decode_length_delimiter(mut buf: impl Buf) -> Result<usize, DecodeError> { + let length = decode_varint(&mut buf)?; + if length > usize::MAX as u64 { + return Err(DecodeError::new( + "length delimiter exceeds maximum usize value", + )); + } + Ok(length as usize) +} diff --git a/vendor/prost/src/encoding/varint.rs b/vendor/prost/src/encoding/varint.rs new file mode 100644 index 00000000..372b2165 --- /dev/null +++ b/vendor/prost/src/encoding/varint.rs @@ -0,0 +1,274 @@ +use core::cmp::min; +use core::num::NonZeroU64; + +use ::bytes::{Buf, BufMut}; + +use crate::DecodeError; + +/// Encodes an integer value into LEB128 variable length format, and writes it to the buffer. +/// The buffer must have enough remaining space (maximum 10 bytes). +#[inline] +pub fn encode_varint(mut value: u64, buf: &mut impl BufMut) { + // Varints are never more than 10 bytes + for _ in 0..10 { + if value < 0x80 { + buf.put_u8(value as u8); + break; + } else { + buf.put_u8(((value & 0x7F) | 0x80) as u8); + value >>= 7; + } + } +} + +/// Returns the encoded length of the value in LEB128 variable length format. +/// The returned value will be between 1 and 10, inclusive. +#[inline] +pub const fn encoded_len_varint(value: u64) -> usize { + // Based on [VarintSize64][1]. + // [1]: https://github.com/protocolbuffers/protobuf/blob/v28.3/src/google/protobuf/io/coded_stream.h#L1744-L1756 + // Safety: value | 1 is non-zero. + let log2value = unsafe { NonZeroU64::new_unchecked(value | 1) }.ilog2(); + ((log2value * 9 + (64 + 9)) / 64) as usize +} + +/// Decodes a LEB128-encoded variable length integer from the buffer. +#[inline] +pub fn decode_varint(buf: &mut impl Buf) -> Result<u64, DecodeError> { + let bytes = buf.chunk(); + let len = bytes.len(); + if len == 0 { + return Err(DecodeError::new("invalid varint")); + } + + let byte = bytes[0]; + if byte < 0x80 { + buf.advance(1); + Ok(u64::from(byte)) + } else if len > 10 || bytes[len - 1] < 0x80 { + let (value, advance) = decode_varint_slice(bytes)?; + buf.advance(advance); + Ok(value) + } else { + decode_varint_slow(buf) + } +} + +/// Decodes a LEB128-encoded variable length integer from the slice, returning the value and the +/// number of bytes read. +/// +/// Based loosely on [`ReadVarint64FromArray`][1] with a varint overflow check from +/// [`ConsumeVarint`][2]. +/// +/// ## Safety +/// +/// The caller must ensure that `bytes` is non-empty and either `bytes.len() >= 10` or the last +/// element in bytes is < `0x80`. +/// +/// [1]: https://github.com/google/protobuf/blob/3.3.x/src/google/protobuf/io/coded_stream.cc#L365-L406 +/// [2]: https://github.com/protocolbuffers/protobuf-go/blob/v1.27.1/encoding/protowire/wire.go#L358 +#[inline] +fn decode_varint_slice(bytes: &[u8]) -> Result<(u64, usize), DecodeError> { + // Fully unrolled varint decoding loop. Splitting into 32-bit pieces gives better performance. + + // Use assertions to ensure memory safety, but it should always be optimized after inline. + assert!(!bytes.is_empty()); + assert!(bytes.len() > 10 || bytes[bytes.len() - 1] < 0x80); + + let mut b: u8 = unsafe { *bytes.get_unchecked(0) }; + let mut part0: u32 = u32::from(b); + if b < 0x80 { + return Ok((u64::from(part0), 1)); + }; + part0 -= 0x80; + b = unsafe { *bytes.get_unchecked(1) }; + part0 += u32::from(b) << 7; + if b < 0x80 { + return Ok((u64::from(part0), 2)); + }; + part0 -= 0x80 << 7; + b = unsafe { *bytes.get_unchecked(2) }; + part0 += u32::from(b) << 14; + if b < 0x80 { + return Ok((u64::from(part0), 3)); + }; + part0 -= 0x80 << 14; + b = unsafe { *bytes.get_unchecked(3) }; + part0 += u32::from(b) << 21; + if b < 0x80 { + return Ok((u64::from(part0), 4)); + }; + part0 -= 0x80 << 21; + let value = u64::from(part0); + + b = unsafe { *bytes.get_unchecked(4) }; + let mut part1: u32 = u32::from(b); + if b < 0x80 { + return Ok((value + (u64::from(part1) << 28), 5)); + }; + part1 -= 0x80; + b = unsafe { *bytes.get_unchecked(5) }; + part1 += u32::from(b) << 7; + if b < 0x80 { + return Ok((value + (u64::from(part1) << 28), 6)); + }; + part1 -= 0x80 << 7; + b = unsafe { *bytes.get_unchecked(6) }; + part1 += u32::from(b) << 14; + if b < 0x80 { + return Ok((value + (u64::from(part1) << 28), 7)); + }; + part1 -= 0x80 << 14; + b = unsafe { *bytes.get_unchecked(7) }; + part1 += u32::from(b) << 21; + if b < 0x80 { + return Ok((value + (u64::from(part1) << 28), 8)); + }; + part1 -= 0x80 << 21; + let value = value + ((u64::from(part1)) << 28); + + b = unsafe { *bytes.get_unchecked(8) }; + let mut part2: u32 = u32::from(b); + if b < 0x80 { + return Ok((value + (u64::from(part2) << 56), 9)); + }; + part2 -= 0x80; + b = unsafe { *bytes.get_unchecked(9) }; + part2 += u32::from(b) << 7; + // Check for u64::MAX overflow. See [`ConsumeVarint`][1] for details. + // [1]: https://github.com/protocolbuffers/protobuf-go/blob/v1.27.1/encoding/protowire/wire.go#L358 + if b < 0x02 { + return Ok((value + (u64::from(part2) << 56), 10)); + }; + + // We have overrun the maximum size of a varint (10 bytes) or the final byte caused an overflow. + // Assume the data is corrupt. + Err(DecodeError::new("invalid varint")) +} + +/// Decodes a LEB128-encoded variable length integer from the buffer, advancing the buffer as +/// necessary. +/// +/// Contains a varint overflow check from [`ConsumeVarint`][1]. +/// +/// [1]: https://github.com/protocolbuffers/protobuf-go/blob/v1.27.1/encoding/protowire/wire.go#L358 +#[inline(never)] +#[cold] +fn decode_varint_slow(buf: &mut impl Buf) -> Result<u64, DecodeError> { + let mut value = 0; + for count in 0..min(10, buf.remaining()) { + let byte = buf.get_u8(); + value |= u64::from(byte & 0x7F) << (count * 7); + if byte <= 0x7F { + // Check for u64::MAX overflow. See [`ConsumeVarint`][1] for details. + // [1]: https://github.com/protocolbuffers/protobuf-go/blob/v1.27.1/encoding/protowire/wire.go#L358 + if count == 9 && byte >= 0x02 { + return Err(DecodeError::new("invalid varint")); + } else { + return Ok(value); + } + } + } + + Err(DecodeError::new("invalid varint")) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn varint() { + fn check(value: u64, encoded: &[u8]) { + // Small buffer. + let mut buf = Vec::with_capacity(1); + encode_varint(value, &mut buf); + assert_eq!(buf, encoded); + + // Large buffer. + let mut buf = Vec::with_capacity(100); + encode_varint(value, &mut buf); + assert_eq!(buf, encoded); + + assert_eq!(encoded_len_varint(value), encoded.len()); + + // See: https://github.com/tokio-rs/prost/pull/1008 for copying reasoning. + let mut encoded_copy = encoded; + let roundtrip_value = decode_varint(&mut encoded_copy).expect("decoding failed"); + assert_eq!(value, roundtrip_value); + + let mut encoded_copy = encoded; + let roundtrip_value = + decode_varint_slow(&mut encoded_copy).expect("slow decoding failed"); + assert_eq!(value, roundtrip_value); + } + + check(2u64.pow(0) - 1, &[0x00]); + check(2u64.pow(0), &[0x01]); + + check(2u64.pow(7) - 1, &[0x7F]); + check(2u64.pow(7), &[0x80, 0x01]); + check(300, &[0xAC, 0x02]); + + check(2u64.pow(14) - 1, &[0xFF, 0x7F]); + check(2u64.pow(14), &[0x80, 0x80, 0x01]); + + check(2u64.pow(21) - 1, &[0xFF, 0xFF, 0x7F]); + check(2u64.pow(21), &[0x80, 0x80, 0x80, 0x01]); + + check(2u64.pow(28) - 1, &[0xFF, 0xFF, 0xFF, 0x7F]); + check(2u64.pow(28), &[0x80, 0x80, 0x80, 0x80, 0x01]); + + check(2u64.pow(35) - 1, &[0xFF, 0xFF, 0xFF, 0xFF, 0x7F]); + check(2u64.pow(35), &[0x80, 0x80, 0x80, 0x80, 0x80, 0x01]); + + check(2u64.pow(42) - 1, &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]); + check(2u64.pow(42), &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01]); + + check( + 2u64.pow(49) - 1, + &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], + ); + check( + 2u64.pow(49), + &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01], + ); + + check( + 2u64.pow(56) - 1, + &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], + ); + check( + 2u64.pow(56), + &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01], + ); + + check( + 2u64.pow(63) - 1, + &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], + ); + check( + 2u64.pow(63), + &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01], + ); + + check( + u64::MAX, + &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01], + ); + } + + const U64_MAX_PLUS_ONE: &[u8] = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02]; + + #[test] + fn varint_overflow() { + let mut copy = U64_MAX_PLUS_ONE; + decode_varint(&mut copy).expect_err("decoding u64::MAX + 1 succeeded"); + } + + #[test] + fn variant_slow_overflow() { + let mut copy = U64_MAX_PLUS_ONE; + decode_varint_slow(&mut copy).expect_err("slow decoding u64::MAX + 1 succeeded"); + } +} diff --git a/vendor/prost/src/encoding/wire_type.rs b/vendor/prost/src/encoding/wire_type.rs new file mode 100644 index 00000000..74a857a2 --- /dev/null +++ b/vendor/prost/src/encoding/wire_type.rs @@ -0,0 +1,49 @@ +use crate::DecodeError; +use alloc::format; + +/// Represent the wire type for protobuf encoding. +/// +/// The integer value is equvilant with the encoded value. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u8)] +pub enum WireType { + Varint = 0, + SixtyFourBit = 1, + LengthDelimited = 2, + StartGroup = 3, + EndGroup = 4, + ThirtyTwoBit = 5, +} + +impl TryFrom<u64> for WireType { + type Error = DecodeError; + + #[inline] + fn try_from(value: u64) -> Result<Self, Self::Error> { + match value { + 0 => Ok(WireType::Varint), + 1 => Ok(WireType::SixtyFourBit), + 2 => Ok(WireType::LengthDelimited), + 3 => Ok(WireType::StartGroup), + 4 => Ok(WireType::EndGroup), + 5 => Ok(WireType::ThirtyTwoBit), + _ => Err(DecodeError::new(format!( + "invalid wire type value: {}", + value + ))), + } + } +} + +/// Checks that the expected wire type matches the actual wire type, +/// or returns an error result. +#[inline] +pub fn check_wire_type(expected: WireType, actual: WireType) -> Result<(), DecodeError> { + if expected != actual { + return Err(DecodeError::new(format!( + "invalid wire type: {:?} (expected {:?})", + actual, expected + ))); + } + Ok(()) +} diff --git a/vendor/prost/src/error.rs b/vendor/prost/src/error.rs new file mode 100644 index 00000000..b4617859 --- /dev/null +++ b/vendor/prost/src/error.rs @@ -0,0 +1,180 @@ +//! Protobuf encoding and decoding errors. + +use alloc::borrow::Cow; +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +use core::fmt; + +/// A Protobuf message decoding error. +/// +/// `DecodeError` indicates that the input buffer does not contain a valid +/// Protobuf message. The error details should be considered 'best effort': in +/// general it is not possible to exactly pinpoint why data is malformed. +#[derive(Clone, PartialEq, Eq)] +pub struct DecodeError { + inner: Box<Inner>, +} + +#[derive(Clone, PartialEq, Eq)] +struct Inner { + /// A 'best effort' root cause description. + description: Cow<'static, str>, + /// A stack of (message, field) name pairs, which identify the specific + /// message type and field where decoding failed. The stack contains an + /// entry per level of nesting. + stack: Vec<(&'static str, &'static str)>, +} + +impl DecodeError { + /// Creates a new `DecodeError` with a 'best effort' root cause description. + /// + /// Meant to be used only by `Message` implementations. + #[doc(hidden)] + #[cold] + pub fn new(description: impl Into<Cow<'static, str>>) -> DecodeError { + DecodeError { + inner: Box::new(Inner { + description: description.into(), + stack: Vec::new(), + }), + } + } + + /// Pushes a (message, field) name location pair on to the location stack. + /// + /// Meant to be used only by `Message` implementations. + #[doc(hidden)] + pub fn push(&mut self, message: &'static str, field: &'static str) { + self.inner.stack.push((message, field)); + } +} + +impl fmt::Debug for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DecodeError") + .field("description", &self.inner.description) + .field("stack", &self.inner.stack) + .finish() + } +} + +impl fmt::Display for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("failed to decode Protobuf message: ")?; + for &(message, field) in &self.inner.stack { + write!(f, "{}.{}: ", message, field)?; + } + f.write_str(&self.inner.description) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeError {} + +#[cfg(feature = "std")] +impl From<DecodeError> for std::io::Error { + fn from(error: DecodeError) -> std::io::Error { + std::io::Error::new(std::io::ErrorKind::InvalidData, error) + } +} + +/// A Protobuf message encoding error. +/// +/// `EncodeError` always indicates that a message failed to encode because the +/// provided buffer had insufficient capacity. Message encoding is otherwise +/// infallible. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct EncodeError { + required: usize, + remaining: usize, +} + +impl EncodeError { + /// Creates a new `EncodeError`. + pub(crate) fn new(required: usize, remaining: usize) -> EncodeError { + EncodeError { + required, + remaining, + } + } + + /// Returns the required buffer capacity to encode the message. + pub fn required_capacity(&self) -> usize { + self.required + } + + /// Returns the remaining length in the provided buffer at the time of encoding. + pub fn remaining(&self) -> usize { + self.remaining + } +} + +impl fmt::Display for EncodeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "failed to encode Protobuf message; insufficient buffer capacity (required: {}, remaining: {})", + self.required, self.remaining + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for EncodeError {} + +#[cfg(feature = "std")] +impl From<EncodeError> for std::io::Error { + fn from(error: EncodeError) -> std::io::Error { + std::io::Error::new(std::io::ErrorKind::InvalidInput, error) + } +} + +/// An error indicating that an unknown enumeration value was encountered. +/// +/// The Protobuf spec mandates that enumeration value sets are ‘open’, so this +/// error's value represents an integer value unrecognized by the +/// presently used enum definition. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct UnknownEnumValue(pub i32); + +impl fmt::Display for UnknownEnumValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "unknown enumeration value {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnknownEnumValue {} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_push() { + let mut decode_error = DecodeError::new("something failed"); + decode_error.push("Foo bad", "bar.foo"); + decode_error.push("Baz bad", "bar.baz"); + + assert_eq!( + decode_error.to_string(), + "failed to decode Protobuf message: Foo bad.bar.foo: Baz bad.bar.baz: something failed" + ); + } + + #[cfg(feature = "std")] + #[test] + fn test_into_std_io_error() { + let decode_error = DecodeError::new("something failed"); + let std_io_error = std::io::Error::from(decode_error); + + assert_eq!(std_io_error.kind(), std::io::ErrorKind::InvalidData); + assert_eq!( + std_io_error.to_string(), + "failed to decode Protobuf message: something failed" + ); + } +} diff --git a/vendor/prost/src/lib.rs b/vendor/prost/src/lib.rs new file mode 100644 index 00000000..8f9df5bb --- /dev/null +++ b/vendor/prost/src/lib.rs @@ -0,0 +1,42 @@ +#![doc(html_root_url = "https://docs.rs/prost/0.13.5")] +#![cfg_attr(not(feature = "std"), no_std)] +#![doc = include_str!("../README.md")] + +// Re-export the alloc crate for use within derived code. +#[doc(hidden)] +pub extern crate alloc; + +// Re-export the bytes crate for use within derived code. +pub use bytes; + +mod error; +mod message; +mod name; +mod types; + +#[doc(hidden)] +pub mod encoding; + +pub use crate::encoding::length_delimiter::{ + decode_length_delimiter, encode_length_delimiter, length_delimiter_len, +}; +pub use crate::error::{DecodeError, EncodeError, UnknownEnumValue}; +pub use crate::message::Message; +pub use crate::name::Name; + +// See `encoding::DecodeContext` for more info. +// 100 is the default recursion limit in the C++ implementation. +#[cfg(not(feature = "no-recursion-limit"))] +const RECURSION_LIMIT: u32 = 100; + +// Re-export #[derive(Message, Enumeration, Oneof)]. +// Based on serde's equivalent re-export [1], but enabled by default. +// +// [1]: https://github.com/serde-rs/serde/blob/v1.0.89/serde/src/lib.rs#L245-L256 +#[cfg(feature = "derive")] +#[allow(unused_imports)] +#[macro_use] +extern crate prost_derive; +#[cfg(feature = "derive")] +#[doc(hidden)] +pub use prost_derive::*; diff --git a/vendor/prost/src/message.rs b/vendor/prost/src/message.rs new file mode 100644 index 00000000..ee33eecd --- /dev/null +++ b/vendor/prost/src/message.rs @@ -0,0 +1,187 @@ +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +use core::fmt::Debug; + +use bytes::{Buf, BufMut}; + +use crate::encoding::varint::{encode_varint, encoded_len_varint}; +use crate::encoding::wire_type::WireType; +use crate::encoding::{decode_key, message, DecodeContext}; +use crate::DecodeError; +use crate::EncodeError; + +/// A Protocol Buffers message. +pub trait Message: Debug + Send + Sync { + /// Encodes the message to a buffer. + /// + /// This method will panic if the buffer has insufficient capacity. + /// + /// Meant to be used only by `Message` implementations. + #[doc(hidden)] + fn encode_raw(&self, buf: &mut impl BufMut) + where + Self: Sized; + + /// Decodes a field from a buffer, and merges it into `self`. + /// + /// Meant to be used only by `Message` implementations. + #[doc(hidden)] + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> + where + Self: Sized; + + /// Returns the encoded length of the message without a length delimiter. + fn encoded_len(&self) -> usize; + + /// Encodes the message to a buffer. + /// + /// An error will be returned if the buffer does not have sufficient capacity. + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> + where + Self: Sized, + { + let required = self.encoded_len(); + let remaining = buf.remaining_mut(); + if required > remaining { + return Err(EncodeError::new(required, remaining)); + } + + self.encode_raw(buf); + Ok(()) + } + + /// Encodes the message to a newly allocated buffer. + fn encode_to_vec(&self) -> Vec<u8> + where + Self: Sized, + { + let mut buf = Vec::with_capacity(self.encoded_len()); + + self.encode_raw(&mut buf); + buf + } + + /// Encodes the message with a length-delimiter to a buffer. + /// + /// An error will be returned if the buffer does not have sufficient capacity. + fn encode_length_delimited(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> + where + Self: Sized, + { + let len = self.encoded_len(); + let required = len + encoded_len_varint(len as u64); + let remaining = buf.remaining_mut(); + if required > remaining { + return Err(EncodeError::new(required, remaining)); + } + encode_varint(len as u64, buf); + self.encode_raw(buf); + Ok(()) + } + + /// Encodes the message with a length-delimiter to a newly allocated buffer. + fn encode_length_delimited_to_vec(&self) -> Vec<u8> + where + Self: Sized, + { + let len = self.encoded_len(); + let mut buf = Vec::with_capacity(len + encoded_len_varint(len as u64)); + + encode_varint(len as u64, &mut buf); + self.encode_raw(&mut buf); + buf + } + + /// Decodes an instance of the message from a buffer. + /// + /// The entire buffer will be consumed. + fn decode(mut buf: impl Buf) -> Result<Self, DecodeError> + where + Self: Default, + { + let mut message = Self::default(); + Self::merge(&mut message, &mut buf).map(|_| message) + } + + /// Decodes a length-delimited instance of the message from the buffer. + fn decode_length_delimited(buf: impl Buf) -> Result<Self, DecodeError> + where + Self: Default, + { + let mut message = Self::default(); + message.merge_length_delimited(buf)?; + Ok(message) + } + + /// Decodes an instance of the message from a buffer, and merges it into `self`. + /// + /// The entire buffer will be consumed. + fn merge(&mut self, mut buf: impl Buf) -> Result<(), DecodeError> + where + Self: Sized, + { + let ctx = DecodeContext::default(); + while buf.has_remaining() { + let (tag, wire_type) = decode_key(&mut buf)?; + self.merge_field(tag, wire_type, &mut buf, ctx.clone())?; + } + Ok(()) + } + + /// Decodes a length-delimited instance of the message from buffer, and + /// merges it into `self`. + fn merge_length_delimited(&mut self, mut buf: impl Buf) -> Result<(), DecodeError> + where + Self: Sized, + { + message::merge( + WireType::LengthDelimited, + self, + &mut buf, + DecodeContext::default(), + ) + } + + /// Clears the message, resetting all fields to their default. + fn clear(&mut self); +} + +impl<M> Message for Box<M> +where + M: Message, +{ + fn encode_raw(&self, buf: &mut impl BufMut) { + (**self).encode_raw(buf) + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + (**self).merge_field(tag, wire_type, buf, ctx) + } + fn encoded_len(&self) -> usize { + (**self).encoded_len() + } + fn clear(&mut self) { + (**self).clear() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const _MESSAGE_IS_OBJECT_SAFE: Option<&dyn Message> = None; +} diff --git a/vendor/prost/src/name.rs b/vendor/prost/src/name.rs new file mode 100644 index 00000000..1b5b4a28 --- /dev/null +++ b/vendor/prost/src/name.rs @@ -0,0 +1,34 @@ +//! Support for associating type name information with a [`Message`]. + +use crate::Message; + +#[cfg(not(feature = "std"))] +use alloc::{format, string::String}; + +/// Associate a type name with a [`Message`] type. +pub trait Name: Message { + /// Simple name for this [`Message`]. + /// This name is the same as it appears in the source .proto file, e.g. `FooBar`. + const NAME: &'static str; + + /// Package name this message type is contained in. They are domain-like + /// and delimited by `.`, e.g. `google.protobuf`. + const PACKAGE: &'static str; + + /// Fully-qualified unique name for this [`Message`]. + /// It's prefixed with the package name and names of any parent messages, + /// e.g. `google.rpc.BadRequest.FieldViolation`. + /// By default, this is the package name followed by the message name. + /// Fully-qualified names must be unique within a domain of Type URLs. + fn full_name() -> String { + format!("{}.{}", Self::PACKAGE, Self::NAME) + } + + /// Type URL for this [`Message`], which by default is the full name with a + /// leading slash, but may also include a leading domain name, e.g. + /// `type.googleapis.com/google.profile.Person`. + /// This can be used when serializing into the `google.protobuf.Any` type. + fn type_url() -> String { + format!("/{}", Self::full_name()) + } +} diff --git a/vendor/prost/src/types.rs b/vendor/prost/src/types.rs new file mode 100644 index 00000000..8300a710 --- /dev/null +++ b/vendor/prost/src/types.rs @@ -0,0 +1,570 @@ +//! Protocol Buffers well-known wrapper types. +//! +//! This module provides implementations of `Message` for Rust standard library types which +//! correspond to a Protobuf well-known wrapper type. The remaining well-known types are defined in +//! the `prost-types` crate in order to avoid a cyclic dependency between `prost` and +//! `prost-build`. + +use alloc::format; +use alloc::string::String; +use alloc::vec::Vec; + +use ::bytes::{Buf, BufMut, Bytes}; + +use crate::encoding::wire_type::WireType; +use crate::{ + encoding::{ + bool, bytes, double, float, int32, int64, skip_field, string, uint32, uint64, DecodeContext, + }, + DecodeError, Message, Name, +}; + +/// `google.protobuf.BoolValue` +impl Message for bool { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self { + bool::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + bool::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self { + 2 + } else { + 0 + } + } + fn clear(&mut self) { + *self = false; + } +} + +/// `google.protobuf.BoolValue` +impl Name for bool { + const NAME: &'static str = "BoolValue"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.UInt32Value` +impl Message for u32 { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self != 0 { + uint32::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + uint32::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self != 0 { + uint32::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + *self = 0; + } +} + +/// `google.protobuf.UInt32Value` +impl Name for u32 { + const NAME: &'static str = "UInt32Value"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.UInt64Value` +impl Message for u64 { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self != 0 { + uint64::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + uint64::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self != 0 { + uint64::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + *self = 0; + } +} + +/// `google.protobuf.UInt64Value` +impl Name for u64 { + const NAME: &'static str = "UInt64Value"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.Int32Value` +impl Message for i32 { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self != 0 { + int32::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + int32::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self != 0 { + int32::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + *self = 0; + } +} + +/// `google.protobuf.Int32Value` +impl Name for i32 { + const NAME: &'static str = "Int32Value"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.Int64Value` +impl Message for i64 { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self != 0 { + int64::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + int64::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self != 0 { + int64::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + *self = 0; + } +} + +/// `google.protobuf.Int64Value` +impl Name for i64 { + const NAME: &'static str = "Int64Value"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.FloatValue` +impl Message for f32 { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self != 0.0 { + float::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + float::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self != 0.0 { + float::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + *self = 0.0; + } +} + +/// `google.protobuf.FloatValue` +impl Name for f32 { + const NAME: &'static str = "FloatValue"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.DoubleValue` +impl Message for f64 { + fn encode_raw(&self, buf: &mut impl BufMut) { + if *self != 0.0 { + double::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + double::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if *self != 0.0 { + double::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + *self = 0.0; + } +} + +/// `google.protobuf.DoubleValue` +impl Name for f64 { + const NAME: &'static str = "DoubleValue"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.StringValue` +impl Message for String { + fn encode_raw(&self, buf: &mut impl BufMut) { + if !self.is_empty() { + string::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + string::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if !self.is_empty() { + string::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + self.clear(); + } +} + +/// `google.protobuf.StringValue` +impl Name for String { + const NAME: &'static str = "StringValue"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.BytesValue` +impl Message for Vec<u8> { + fn encode_raw(&self, buf: &mut impl BufMut) { + if !self.is_empty() { + bytes::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + bytes::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if !self.is_empty() { + bytes::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + self.clear(); + } +} + +/// `google.protobuf.BytesValue` +impl Name for Vec<u8> { + const NAME: &'static str = "BytesValue"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.BytesValue` +impl Message for Bytes { + fn encode_raw(&self, buf: &mut impl BufMut) { + if !self.is_empty() { + bytes::encode(1, self, buf) + } + } + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + if tag == 1 { + bytes::merge(wire_type, self, buf, ctx) + } else { + skip_field(wire_type, tag, buf, ctx) + } + } + fn encoded_len(&self) -> usize { + if !self.is_empty() { + bytes::encoded_len(1, self) + } else { + 0 + } + } + fn clear(&mut self) { + self.clear(); + } +} + +/// `google.protobuf.BytesValue` +impl Name for Bytes { + const NAME: &'static str = "BytesValue"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// `google.protobuf.Empty` +impl Message for () { + fn encode_raw(&self, _buf: &mut impl BufMut) {} + fn merge_field( + &mut self, + tag: u32, + wire_type: WireType, + buf: &mut impl Buf, + ctx: DecodeContext, + ) -> Result<(), DecodeError> { + skip_field(wire_type, tag, buf, ctx) + } + fn encoded_len(&self) -> usize { + 0 + } + fn clear(&mut self) {} +} + +/// `google.protobuf.Empty` +impl Name for () { + const NAME: &'static str = "Empty"; + const PACKAGE: &'static str = "google.protobuf"; + + fn type_url() -> String { + googleapis_type_url_for::<Self>() + } +} + +/// Compute the type URL for the given `google.protobuf` type, using `type.googleapis.com` as the +/// authority for the URL. +fn googleapis_type_url_for<T: Name>() -> String { + format!("type.googleapis.com/{}.{}", T::PACKAGE, T::NAME) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_impl_name() { + assert_eq!("BoolValue", bool::NAME); + assert_eq!("google.protobuf", bool::PACKAGE); + assert_eq!("google.protobuf.BoolValue", bool::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.BoolValue", + bool::type_url() + ); + + assert_eq!("UInt32Value", u32::NAME); + assert_eq!("google.protobuf", u32::PACKAGE); + assert_eq!("google.protobuf.UInt32Value", u32::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.UInt32Value", + u32::type_url() + ); + + assert_eq!("UInt64Value", u64::NAME); + assert_eq!("google.protobuf", u64::PACKAGE); + assert_eq!("google.protobuf.UInt64Value", u64::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.UInt64Value", + u64::type_url() + ); + + assert_eq!("Int32Value", i32::NAME); + assert_eq!("google.protobuf", i32::PACKAGE); + assert_eq!("google.protobuf.Int32Value", i32::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.Int32Value", + i32::type_url() + ); + + assert_eq!("Int64Value", i64::NAME); + assert_eq!("google.protobuf", i64::PACKAGE); + assert_eq!("google.protobuf.Int64Value", i64::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.Int64Value", + i64::type_url() + ); + + assert_eq!("FloatValue", f32::NAME); + assert_eq!("google.protobuf", f32::PACKAGE); + assert_eq!("google.protobuf.FloatValue", f32::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.FloatValue", + f32::type_url() + ); + + assert_eq!("DoubleValue", f64::NAME); + assert_eq!("google.protobuf", f64::PACKAGE); + assert_eq!("google.protobuf.DoubleValue", f64::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.DoubleValue", + f64::type_url() + ); + + assert_eq!("StringValue", String::NAME); + assert_eq!("google.protobuf", String::PACKAGE); + assert_eq!("google.protobuf.StringValue", String::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.StringValue", + String::type_url() + ); + + assert_eq!("BytesValue", Vec::<u8>::NAME); + assert_eq!("google.protobuf", Vec::<u8>::PACKAGE); + assert_eq!("google.protobuf.BytesValue", Vec::<u8>::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.BytesValue", + Vec::<u8>::type_url() + ); + + assert_eq!("BytesValue", Bytes::NAME); + assert_eq!("google.protobuf", Bytes::PACKAGE); + assert_eq!("google.protobuf.BytesValue", Bytes::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.BytesValue", + Bytes::type_url() + ); + + assert_eq!("Empty", <()>::NAME); + assert_eq!("google.protobuf", <()>::PACKAGE); + assert_eq!("google.protobuf.Empty", <()>::full_name()); + assert_eq!( + "type.googleapis.com/google.protobuf.Empty", + <()>::type_url() + ); + } +} |
