prost-reflect-0.15.0/.cargo_vcs_info.json0000644000000001530000000000100137070ustar { "git": { "sha1": "a9aa70acf981dde70593d67e2138ec884d81a34d" }, "path_in_vcs": "prost-reflect" }prost-reflect-0.15.0/Cargo.lock0000644000000563140000000000100116740ustar # 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 = "anyhow" version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "beef" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bstr" version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "console" version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", "libc", "once_cell", "windows-sys 0.59.0", ] [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fixedbitset" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[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.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "insta" version = "1.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50259abbaa67d11d2bcafc7ba1d094ed7a0c70e3ce893f0d0997f73558cb3084" dependencies = [ "console", "linked-hash-map", "once_cell", "pin-project", "serde", "similar", ] [[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.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[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.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "log" version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "logos" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab6f536c1af4c7cc81edf73da1f8029896e7e1e16a219ef09b184e76a296f3db" dependencies = [ "logos-derive", ] [[package]] name = "logos-codegen" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "189bbfd0b61330abea797e5e9276408f2edbe4f822d7ad08685d67419aafb34e" dependencies = [ "beef", "fnv", "lazy_static", "proc-macro2", "quote", "regex-syntax", "rustc_version", "syn", ] [[package]] name = "logos-derive" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebfe8e1a19049ddbfccbd14ac834b215e11b85b90bab0c2dba7c7b92fb5d5cba" dependencies = [ "logos-codegen", ] [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miette" version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484" dependencies = [ "cfg-if", "miette-derive", "thiserror", "unicode-width", ] [[package]] name = "miette-derive" version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "multimap" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "ordered-float" version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ "num-traits", ] [[package]] name = "petgraph" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "pin-project" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "prettyplease" version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bit-set", "bit-vec", "bitflags", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", "regex-syntax", "rusty-fork", "tempfile", "unarray", ] [[package]] name = "prost" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", "prost-derive", ] [[package]] name = "prost-build" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ "heck", "itertools", "log", "multimap", "once_cell", "petgraph", "prettyplease", "prost", "prost-types", "regex", "syn", "tempfile", ] [[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 = "prost-reflect" version = "0.15.0" dependencies = [ "base64", "insta", "logos", "miette", "once_cell", "proptest", "prost", "prost-build", "prost-reflect-derive", "prost-types", "serde", "serde-value", "serde_json", "serde_yaml", "similar-asserts", ] [[package]] name = "prost-reflect-derive" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f9e9c69a80ab4bc26209fc9de4d2dfd12f26e26590cba0bc975bd4f81f4e94c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "prost-types" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ "prost", ] [[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.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[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", ] [[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_xorshift" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ "rand_core", ] [[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 = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" 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.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde-value" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ "ordered-float", "serde", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_yaml" version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap", "itoa", "ryu", "serde", "unsafe-libyaml", ] [[package]] name = "similar" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" dependencies = [ "bstr", "unicode-segmentation", ] [[package]] name = "similar-asserts" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b441962c817e33508847a22bd82f03a30cff43642dc2fae8b050566121eb9a" dependencies = [ "console", "serde", "similar", ] [[package]] name = "syn" version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tempfile" version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ "fastrand", "getrandom 0.3.2", "once_cell", "rustix", "windows-sys 0.52.0", ] [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "unarray" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-segmentation" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unsafe-libyaml" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "wait-timeout" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" dependencies = [ "libc", ] [[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.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[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.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] [[package]] name = "zerocopy" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", "syn", ] prost-reflect-0.15.0/Cargo.toml0000644000000101500000000000100117030ustar # 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.74.0" name = "prost-reflect" version = "0.15.0" authors = ["Andrew Hickman "] build = false exclude = [ "**/tests.rs", "proptest-regressions", "src/file_descriptor_set.bin", "src/doctest.proto", "tests", "doc/*.bin", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "A protobuf library extending prost with reflection support and dynamic messages." documentation = "https://docs.rs/prost-reflect" readme = "README.md" keywords = [ "protobuf", "serialization", "json", ] categories = ["encoding"] license = "MIT OR Apache-2.0" repository = "https://github.com/andrewhickman/prost-reflect" [package.metadata.docs.rs] all-features = true rustdoc-args = [ "--cfg", "docsrs", ] [package.metadata.release] pre-release-commit-message = "(cargo-release) {{crate_name}} version {{version}}" sign-tag = true tag-name = "{{version}}" [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "../README.md" replace = "https://deps.rs/crate/prost-reflect/{{version}}/status.svg" search = 'https://deps\.rs/crate/prost-reflect/.*?/status.svg' [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "../README.tpl" replace = "https://deps.rs/crate/prost-reflect/{{version}}/status.svg" search = 'https://deps\.rs/crate/prost-reflect/.*?/status.svg' [[package.metadata.release.pre-release-replacements]] file = "../README.md" min = 1 replace = "https://docs.rs/prost-reflect/{{version}}/prost_reflect" search = 'https://docs\.rs/prost-reflect/.*?/prost_reflect' [[package.metadata.release.pre-release-replacements]] file = "../README.tpl" min = 1 replace = "https://docs.rs/prost-reflect/{{version}}/prost_reflect" search = 'https://docs\.rs/prost-reflect/.*?/prost_reflect' [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "src/lib.rs" replace = 'html_root_url = "https://docs.rs/prost-reflect/{{version}}/"' search = 'html_root_url = "https://docs.rs/prost-reflect/.*?/"' [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "../CHANGELOG.md" replace = """ ## [Unreleased] ## [{{version}}] - {{date}}""" search = '## \[Unreleased\]' [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "../CHANGELOG.md" replace = """ [Unreleased]: https://github.com/andrewhickman/prost-reflect/compare/{{version}}...HEAD [{{version}}]: https://github.com/andrewhickman/prost-reflect/compare/{{prev_version}}...{{version}}""" search = '\[Unreleased\]: https://github\.com/andrewhickman/prost-reflect/compare/.*?...HEAD' [features] derive = ["dep:prost-reflect-derive"] miette = ["dep:miette"] serde = [ "dep:serde", "dep:base64", "dep:serde-value", ] text-format = ["dep:logos"] [lib] name = "prost_reflect" path = "src/lib.rs" [dependencies.base64] version = "0.22.0" optional = true [dependencies.logos] version = "0.15.0" optional = true [dependencies.miette] version = "7.0.0" optional = true [dependencies.prost] version = "0.13.0" [dependencies.prost-reflect-derive] version = "0.15.0" optional = true [dependencies.prost-types] version = "0.13.0" [dependencies.serde] version = "1.0.132" optional = true [dependencies.serde-value] version = "0.7.0" optional = true [dev-dependencies.insta] version = "1.23.0" features = ["yaml"] [dev-dependencies.once_cell] version = "1.13.0" [dev-dependencies.proptest] version = "1.0.0" [dev-dependencies.prost-build] version = "0.13.0" [dev-dependencies.serde_json] version = "1.0.106" [dev-dependencies.serde_yaml] version = "0.9.25" [dev-dependencies.similar-asserts] version = "1.4.2" features = ["serde"] prost-reflect-0.15.0/Cargo.toml.orig000064400000000000000000000066631046102023000154020ustar 00000000000000[package] name = "prost-reflect" description = "A protobuf library extending prost with reflection support and dynamic messages." keywords = ["protobuf", "serialization", "json"] categories = ["encoding"] version = "0.15.0" authors = ["Andrew Hickman "] repository = "https://github.com/andrewhickman/prost-reflect" documentation = "https://docs.rs/prost-reflect" license = "MIT OR Apache-2.0" readme = "../README.md" edition = "2021" rust-version = "1.74.0" exclude = [ "**/tests.rs", "proptest-regressions", "src/file_descriptor_set.bin", "src/doctest.proto", "tests", "doc/*.bin", ] [[test]] name = "main" path = "tests/main.rs" required-features = ["serde", "miette", "text-format"] [features] derive = ["dep:prost-reflect-derive"] serde = ["dep:serde", "dep:base64", "dep:serde-value"] text-format = ["dep:logos"] miette = ["dep:miette"] [dependencies] base64 = { version = "0.22.0", optional = true } logos = { version = "0.15.0", optional = true } miette = { version = "7.0.0", optional = true } prost = "0.13.0" prost-reflect-derive = { path = '../prost-reflect-derive', version = "0.15.0", optional = true } prost-types = "0.13.0" serde-value = { version = "0.7.0", optional = true } serde = { version = "1.0.132", optional = true } [dev-dependencies] insta = { version = "1.23.0", features = ["yaml"] } once_cell = "1.13.0" proptest = "1.0.0" prost-build = "0.13.0" prost-reflect-build = { path = "../prost-reflect-build" } serde_json = "1.0.106" serde_yaml = "0.9.25" similar-asserts = { version = "1.4.2", features = ["serde"] } [package.metadata.release] tag-name = "{{version}}" sign-tag = true pre-release-commit-message = "(cargo-release) {{crate_name}} version {{version}}" [[package.metadata.release.pre-release-replacements]] file = "../README.md" search = "https://deps\\.rs/crate/prost-reflect/.*?/status.svg" replace = "https://deps.rs/crate/prost-reflect/{{version}}/status.svg" exactly = 1 [[package.metadata.release.pre-release-replacements]] file = "../README.tpl" search = "https://deps\\.rs/crate/prost-reflect/.*?/status.svg" replace = "https://deps.rs/crate/prost-reflect/{{version}}/status.svg" exactly = 1 [[package.metadata.release.pre-release-replacements]] file = "../README.md" search = "https://docs\\.rs/prost-reflect/.*?/prost_reflect" replace = "https://docs.rs/prost-reflect/{{version}}/prost_reflect" min = 1 [[package.metadata.release.pre-release-replacements]] file = "../README.tpl" search = "https://docs\\.rs/prost-reflect/.*?/prost_reflect" replace = "https://docs.rs/prost-reflect/{{version}}/prost_reflect" min = 1 [[package.metadata.release.pre-release-replacements]] file = "src/lib.rs" search = "html_root_url = \"https://docs.rs/prost-reflect/.*?/\"" replace = "html_root_url = \"https://docs.rs/prost-reflect/{{version}}/\"" exactly = 1 [[package.metadata.release.pre-release-replacements]] file = "../CHANGELOG.md" search = "## \\[Unreleased\\]" replace = "## [Unreleased]\n\n## [{{version}}] - {{date}}" exactly = 1 [[package.metadata.release.pre-release-replacements]] file = "../CHANGELOG.md" search = "\\[Unreleased\\]: https://github\\.com/andrewhickman/prost-reflect/compare/.*?...HEAD" replace = "[Unreleased]: https://github.com/andrewhickman/prost-reflect/compare/{{version}}...HEAD\n[{{version}}]: https://github.com/andrewhickman/prost-reflect/compare/{{prev_version}}...{{version}}" exactly = 1 [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] prost-reflect-0.15.0/LICENSE-APACHE000064400000000000000000000000211046102023000144150ustar 00000000000000../LICENSE-APACHEprost-reflect-0.15.0/LICENSE-MIT000064400000000000000000000000161046102023000141310ustar 00000000000000../LICENSE-MITprost-reflect-0.15.0/README.md000064400000000000000000000150271046102023000137640ustar 00000000000000[![crates.io](https://img.shields.io/crates/v/prost-reflect.svg)](https://crates.io/crates/prost-reflect/) [![docs.rs](https://docs.rs/prost-reflect/badge.svg)](https://docs.rs/prost-reflect/) [![deps.rs](https://deps.rs/crate/prost-reflect/0.15.0/status.svg)](https://deps.rs/crate/prost-reflect) ![MSRV](https://img.shields.io/badge/rustc-1.64+-blue.svg) [![Continuous integration](https://github.com/andrewhickman/prost-reflect/actions/workflows/ci.yml/badge.svg)](https://github.com/andrewhickman/prost-reflect/actions/workflows/ci.yml) [![codecov.io](https://codecov.io/gh/andrewhickman/prost-reflect/branch/main/graph/badge.svg?token=E2OITYXO7M)](https://codecov.io/gh/andrewhickman/prost-reflect) ![Apache 2.0 OR MIT licensed](https://img.shields.io/badge/license-Apache2.0%2FMIT-blue.svg) # prost-reflect A protobuf library extending [`prost`](https://crates.io/crates/prost) with reflection support and dynamic messages. ## Usage This crate provides support for dynamic protobuf messages. These are useful when the protobuf type definition is not known ahead of time. The main entry points into the API of this crate are: - [`DescriptorPool`] wraps a [`FileDescriptorSet`][prost_types::FileDescriptorSet] output by the protobuf compiler to provide an API for inspecting type definitions. - [`DynamicMessage`] provides encoding, decoding and reflection of an arbitrary protobuf message definition described by a [`MessageDescriptor`]. ### Example - decoding `DynamicMessage` does not implement [`Default`] since it needs a message descriptor to function. To decode a protobuf byte stream into an instance of this type, use [`DynamicMessage::decode`] to create a default value for the `MessageDescriptor` instance and merge into it: ```rust use prost::Message; use prost_types::FileDescriptorSet; use prost_reflect::{DynamicMessage, DescriptorPool, Value}; let pool = DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap(); let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01".as_ref()).unwrap(); assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); ``` ### Example - JSON mapping When the `serde` feature is enabled, `DynamicMessage` can be deserialized to and from the [canonical JSON mapping](https://developers.google.com/protocol-buffers/docs/proto3#json) defined for protobuf messages. ```rust use prost::Message; use prost_reflect::{DynamicMessage, DescriptorPool, Value}; use serde_json::de::Deserializer; let pool = DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap(); let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); let json = r#"{ "foo": 150 }"#; let mut deserializer = Deserializer::from_str(json); let dynamic_message = DynamicMessage::deserialize(message_descriptor, &mut deserializer).unwrap(); deserializer.end().unwrap(); assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); ``` ### Example - implementing `ReflectMessage` The [`ReflectMessage`] trait provides a `.descriptor()` method to get type information for a message. It is implemented for `DynamicMessage` and the well-known-types provided by [`prost-types`](https://docs.rs/prost-types/0.10.0/prost_types). When the `derive` feature is enabled, it can be derived for [`Message`][prost::Message] implementations. The derive macro takes the following parameters: | Name | Value | |-----------------|-------| | descriptor_pool | An expression that resolves to a [`DescriptorPool`] containing the message type. The descriptor should be cached to avoid re-building it. Either this or `file_descriptor_pool_bytes` must be set | | file_descriptor_pool_bytes | An expression that resolves to an implementation of `Buf` containing an encoded file descriptor set. This will be automatically added to the global descriptor pool the first time `ReflectMessage::descriptor()` is called. | | message_name | The full name of the message, used to look it up within [`DescriptorPool`]. | ```rust use prost::Message; use prost_reflect::{DescriptorPool, ReflectMessage}; use once_cell::sync::Lazy; static DESCRIPTOR_POOL: Lazy = Lazy::new(|| DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap()); #[derive(Message, ReflectMessage)] #[prost_reflect(descriptor_pool = "DESCRIPTOR_POOL", message_name = "package.MyMessage")] pub struct MyMessage {} let message = MyMessage {}; assert_eq!(message.descriptor().full_name(), "package.MyMessage"); ``` If you are using `prost-build`, the [`prost-reflect-build`](https://crates.io/crates/prost-reflect-build) crate provides helpers to generate `ReflectMessage` implementations: ```rust,no_run prost_reflect_build::Builder::new() .compile_protos(&["src/package.proto"], &["src"]) .unwrap(); ``` ## Minimum Supported Rust Version Rust **1.74** or higher. The minimum supported Rust version may be changed in the future, but it will be done with a minor version bump. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ## Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [`DescriptorPool`]: https://docs.rs/prost-reflect/0.15.0/prost_reflect/struct.DescriptorPool.html [`DynamicMessage`]: https://docs.rs/prost-reflect/0.15.0/prost_reflect/struct.DynamicMessage.html [`MessageDescriptor`]: https://docs.rs/prost-reflect/0.15.0/prost_reflect/struct.MessageDescriptor.html [`MessageDescriptor`]: https://docs.rs/prost-reflect/0.15.0/prost_reflect/struct.MessageDescriptor.html [`DynamicMessage::decode`]: https://docs.rs/prost-reflect/0.15.0/prost_reflect/struct.DynamicMessage.html#method.decode [`ReflectMessage`]: https://docs.rs/prost-reflect/0.15.0/prost_reflect/trait.ReflectMessage.html [`Default`]: https://doc.rust-lang.org/stable/core/default/trait.Default.html [prost::Message]: https://docs.rs/prost/latest/prost/trait.Message.html [prost_types::FileDescriptorSet]: https://docs.rs/prost-types/latest/prost_types/struct.FileDescriptorSet.html prost-reflect-0.15.0/doc/decoding.md000064400000000000000000000014241046102023000153440ustar 00000000000000`DynamicMessage` does not implement [`Default`] since it needs a message descriptor to function. To decode a protobuf byte stream into an instance of this type, use [`DynamicMessage::decode`] to create a default value for the `MessageDescriptor` instance and merge into it: ```rust use prost::Message; use prost_types::FileDescriptorSet; use prost_reflect::{DynamicMessage, DescriptorPool, Value}; let pool = DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap(); let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01".as_ref()).unwrap(); assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); ```prost-reflect-0.15.0/doc/intro.md000064400000000000000000000010051046102023000147160ustar 00000000000000This crate provides support for dynamic protobuf messages. These are useful when the protobuf type definition is not known ahead of time. The main entry points into the API of this crate are: - [`DescriptorPool`] wraps a [`FileDescriptorSet`][prost_types::FileDescriptorSet] output by the protobuf compiler to provide an API for inspecting type definitions. - [`DynamicMessage`] provides encoding, decoding and reflection of an arbitrary protobuf message definition described by a [`MessageDescriptor`].prost-reflect-0.15.0/doc/json.md000064400000000000000000000015061046102023000145420ustar 00000000000000When the `serde` feature is enabled, `DynamicMessage` can be deserialized to and from the [canonical JSON mapping](https://developers.google.com/protocol-buffers/docs/proto3#json) defined for protobuf messages. ```rust use prost::Message; use prost_reflect::{DynamicMessage, DescriptorPool, Value}; use serde_json::de::Deserializer; let pool = DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap(); let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); let json = r#"{ "foo": 150 }"#; let mut deserializer = Deserializer::from_str(json); let dynamic_message = DynamicMessage::deserialize(message_descriptor, &mut deserializer).unwrap(); deserializer.end().unwrap(); assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); ```prost-reflect-0.15.0/doc/reflect.md000064400000000000000000000035121046102023000152140ustar 00000000000000The [`ReflectMessage`] trait provides a `.descriptor()` method to get type information for a message. It is implemented for `DynamicMessage` and the well-known-types provided by [`prost-types`](https://docs.rs/prost-types/0.10.0/prost_types). When the `derive` feature is enabled, it can be derived for [`Message`][prost::Message] implementations. The derive macro takes the following parameters: | Name | Value | |-----------------|-------| | descriptor_pool | An expression that resolves to a [`DescriptorPool`] containing the message type. The descriptor should be cached to avoid re-building it. Either this or `file_descriptor_pool_bytes` must be set | | file_descriptor_pool_bytes | An expression that resolves to an implementation of `Buf` containing an encoded file descriptor set. This will be automatically added to the global descriptor pool the first time `ReflectMessage::descriptor()` is called. | | message_name | The full name of the message, used to look it up within [`DescriptorPool`]. | ```rust use prost::Message; use prost_reflect::{DescriptorPool, ReflectMessage}; use once_cell::sync::Lazy; static DESCRIPTOR_POOL: Lazy = Lazy::new(|| DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap()); #[derive(Message, ReflectMessage)] #[prost_reflect(descriptor_pool = "DESCRIPTOR_POOL", message_name = "package.MyMessage")] pub struct MyMessage {} let message = MyMessage {}; assert_eq!(message.descriptor().full_name(), "package.MyMessage"); ``` If you are using `prost-build`, the [`prost-reflect-build`](https://crates.io/crates/prost-reflect-build) crate provides helpers to generate `ReflectMessage` implementations: ```rust,no_run prost_reflect_build::Builder::new() .compile_protos(&["src/package.proto"], &["src"]) .unwrap(); ```prost-reflect-0.15.0/src/descriptor/api.rs000064400000000000000000002155251046102023000165760ustar 00000000000000use std::{ borrow::Cow, fmt, iter, ops::{Range, RangeInclusive}, sync::Arc, }; use prost::{ bytes::{Buf, BufMut}, encoding::{self, WireType}, DecodeError, EncodeError, Message, }; use prost_types::{ DescriptorProto, EnumDescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto, FileDescriptorProto, FileDescriptorSet, MethodDescriptorProto, OneofDescriptorProto, ServiceDescriptorProto, }; use crate::{ descriptor::{ error::DescriptorErrorKind, find_enum_proto, find_message_proto, tag, to_index, types::{self, Options}, Definition, DefinitionKind, DescriptorIndex, EnumDescriptorInner, EnumValueDescriptorInner, ExtensionDescriptorInner, FieldDescriptorInner, FileDescriptorInner, KindIndex, MessageDescriptorInner, MethodDescriptorInner, OneofDescriptorInner, ServiceDescriptorInner, MAP_ENTRY_KEY_NUMBER, MAP_ENTRY_VALUE_NUMBER, }, Cardinality, DescriptorError, DescriptorPool, DynamicMessage, EnumDescriptor, EnumValueDescriptor, ExtensionDescriptor, FieldDescriptor, FileDescriptor, Kind, MessageDescriptor, MethodDescriptor, OneofDescriptor, ServiceDescriptor, Syntax, Value, }; impl fmt::Debug for Syntax { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Syntax::Proto2 => write!(f, "proto2"), Syntax::Proto3 => write!(f, "proto3"), } } } impl Kind { fn new(pool: &DescriptorPool, kind: KindIndex) -> Self { match kind { KindIndex::Double => Kind::Double, KindIndex::Float => Kind::Float, KindIndex::Int64 => Kind::Int64, KindIndex::Uint64 => Kind::Uint64, KindIndex::Int32 => Kind::Int32, KindIndex::Fixed64 => Kind::Fixed64, KindIndex::Fixed32 => Kind::Fixed32, KindIndex::Bool => Kind::Bool, KindIndex::String => Kind::String, KindIndex::Bytes => Kind::Bytes, KindIndex::Uint32 => Kind::Uint32, KindIndex::Sfixed32 => Kind::Sfixed32, KindIndex::Sfixed64 => Kind::Sfixed64, KindIndex::Sint32 => Kind::Sint32, KindIndex::Sint64 => Kind::Sint64, KindIndex::Message(index) | KindIndex::Group(index) => { Kind::Message(MessageDescriptor { pool: pool.clone(), index, }) } KindIndex::Enum(index) => Kind::Enum(EnumDescriptor { pool: pool.clone(), index, }), } } /// Gets a reference to the [`MessageDescriptor`] if this is a message type, /// or `None` otherwise. pub fn as_message(&self) -> Option<&MessageDescriptor> { match self { Kind::Message(desc) => Some(desc), _ => None, } } /// Gets a reference to the [`EnumDescriptor`] if this is an enum type, /// or `None` otherwise. pub fn as_enum(&self) -> Option<&EnumDescriptor> { match self { Kind::Enum(desc) => Some(desc), _ => None, } } /// Returns the [`WireType`] used to encode this type. /// /// Note: The [`Kind::Message`] returns [` WireType::LengthDelimited`], /// as [groups are deprecated](https://protobuf.dev/programming-guides/encoding/#groups). pub fn wire_type(&self) -> WireType { match self { Kind::Double | Kind::Fixed64 | Kind::Sfixed64 => WireType::SixtyFourBit, Kind::Float | Kind::Fixed32 | Kind::Sfixed32 => WireType::ThirtyTwoBit, Kind::Enum(_) | Kind::Int32 | Kind::Int64 | Kind::Uint32 | Kind::Uint64 | Kind::Sint32 | Kind::Sint64 | Kind::Bool => WireType::Varint, Kind::String | Kind::Bytes | Kind::Message(_) => WireType::LengthDelimited, } } } impl fmt::Debug for Kind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Double => write!(f, "double"), Self::Float => write!(f, "float"), Self::Int32 => write!(f, "int32"), Self::Int64 => write!(f, "int64"), Self::Uint32 => write!(f, "uint32"), Self::Uint64 => write!(f, "uint64"), Self::Sint32 => write!(f, "sint32"), Self::Sint64 => write!(f, "sint64"), Self::Fixed32 => write!(f, "fixed32"), Self::Fixed64 => write!(f, "fixed64"), Self::Sfixed32 => write!(f, "sfixed32"), Self::Sfixed64 => write!(f, "sfixed64"), Self::Bool => write!(f, "bool"), Self::String => write!(f, "string"), Self::Bytes => write!(f, "bytes"), Self::Message(m) => write!(f, "{}", m.full_name()), Self::Enum(e) => write!(f, "{}", e.full_name()), } } } impl DescriptorPool { /// Creates a new, empty [`DescriptorPool`]. /// /// For the common case of creating a `DescriptorPool` from a single [`FileDescriptorSet`], see /// [`DescriptorPool::from_file_descriptor_set`] or [`DescriptorPool::decode`]. pub fn new() -> Self { DescriptorPool::default() } /// Creates a [`DescriptorPool`] from a [`FileDescriptorSet`]. /// /// A file descriptor set may be generated by running the protobuf compiler with the /// `--descriptor_set_out` flag. If you are using [`prost-build`](https://crates.io/crates/prost-build), /// then [`Config::file_descriptor_set_path`](https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method..file_descriptor_set_path) /// is a convenient way to generate it as part of your build. pub fn from_file_descriptor_set( file_descriptor_set: FileDescriptorSet, ) -> Result { let mut pool = DescriptorPool::new(); pool.add_file_descriptor_set(file_descriptor_set)?; Ok(pool) } /// Decodes and adds a set of file descriptors to the pool. /// /// A file descriptor set may be generated by running the protobuf compiler with the /// `--descriptor_set_out` flag. If you are using [`prost-build`](https://crates.io/crates/prost-build), /// then [`Config::file_descriptor_set_path`](https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method..file_descriptor_set_path) /// is a convenient way to generate it as part of your build. /// /// Unlike when using [`DescriptorPool::from_file_descriptor_set`], any extension options /// defined in the file descriptors are preserved. /// /// # Errors /// /// Returns an error if the given bytes are not a valid protobuf-encoded file descriptor set, or if the descriptor set itself /// is invalid. When using a file descriptor set generated by the protobuf compiler, this method will always succeed. pub fn decode(bytes: B) -> Result where B: Buf, { let file_descriptor_set = types::FileDescriptorSet::decode(bytes).map_err(|err| { DescriptorError::new(vec![DescriptorErrorKind::DecodeFileDescriptorSet { err }]) })?; let mut pool = DescriptorPool::new(); pool.build_files(file_descriptor_set.file.into_iter())?; Ok(pool) } /// Adds a new [`FileDescriptorSet`] to this [`DescriptorPool`]. /// /// A file descriptor set may be generated by running the protobuf compiler with the /// `--descriptor_set_out` flag. If you are using [`prost-build`](https://crates.io/crates/prost-build), /// then [`Config::file_descriptor_set_path`](https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method..file_descriptor_set_path) /// is a convenient way to generate it as part of your build. /// /// Any duplicates of files already in the pool will be skipped. Note this may cause issues when trying to add two different versions of a file with the same name. /// /// # Errors /// /// Returns an error if the descriptor set is invalid, for example if it references types not yet added /// to the pool. When using a file descriptor set generated by the protobuf compiler, this method will /// always succeed. pub fn add_file_descriptor_set( &mut self, file_descriptor_set: FileDescriptorSet, ) -> Result<(), DescriptorError> { self.add_file_descriptor_protos(file_descriptor_set.file) } /// Adds a collection of file descriptors to this pool. /// /// The file descriptors may be provided in any order, however all types referenced must be defined /// either in one of the files provided, or in a file previously added to the pool. /// /// Any duplicates of files already in the pool will be skipped. Note this may cause issues when trying to add two different versions of a file with the same name. /// /// # Errors /// /// Returns an error if any of the given file descriptor is invalid, for example if they reference /// types not yet added to the pool. pub fn add_file_descriptor_protos(&mut self, files: I) -> Result<(), DescriptorError> where I: IntoIterator, { self.build_files( files .into_iter() .map(types::FileDescriptorProto::from_prost), ) } /// Add a single file descriptor to the pool. /// /// All types referenced by the file must be defined either in the file itself, or in a file /// previously added to the pool. /// /// If the file is a duplicate of a file already in the pool, it will be skipped. Note this may cause issues when trying to add two different versions of a file with the same name. /// /// # Errors /// /// Returns an error if the given file descriptor is invalid, for example if it references types not yet added /// to the pool. pub fn add_file_descriptor_proto( &mut self, file: FileDescriptorProto, ) -> Result<(), DescriptorError> { self.add_file_descriptor_protos(iter::once(file)) } /// Decode and add a single file descriptor to the pool. /// /// All types referenced by the file must be defined either in the file itself, or in a file /// previously added to the pool. /// /// Unlike when using [`add_file_descriptor_proto()`][DescriptorPool::add_file_descriptor_proto], any extension options /// defined in the file descriptor are preserved. /// /// If the file is a duplicate of a file already in the pool, it will be skipped. Note this may cause issues when trying to add two different versions of a file with the same name. /// /// # Errors /// /// Returns an error if the given bytes are not a valid protobuf-encoded file descriptor, or if the file descriptor itself /// is invalid, for example if it references types not yet added to the pool. pub fn decode_file_descriptor_proto(&mut self, bytes: B) -> Result<(), DescriptorError> where B: Buf, { let file = types::FileDescriptorProto::decode(bytes).map_err(|err| { DescriptorError::new(vec![DescriptorErrorKind::DecodeFileDescriptorSet { err }]) })?; self.build_files(iter::once(file)) } /// Decode and add a set of file descriptors to the pool. /// /// A file descriptor set may be generated by running the protobuf compiler with the /// `--descriptor_set_out` flag. If you are using [`prost-build`](https://crates.io/crates/prost-build), /// then [`Config::file_descriptor_set_path`](https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method..file_descriptor_set_path) /// is a convenient way to generate it as part of your build. /// /// Unlike when using [`add_file_descriptor_set()`][DescriptorPool::add_file_descriptor_set], any extension options /// defined in the file descriptors are preserved. /// /// Any duplicates of files already in the pool will be skipped. Note this may cause issues when trying to add two different versions of a file with the same name. /// /// # Errors /// /// Returns an error if the given bytes are not a valid protobuf-encoded file descriptor set, or if the descriptor set itself /// is invalid. When using a file descriptor set generated by the protobuf compiler, this method will always succeed. pub fn decode_file_descriptor_set(&mut self, bytes: B) -> Result<(), DescriptorError> where B: Buf, { let file = types::FileDescriptorSet::decode(bytes).map_err(|err| { DescriptorError::new(vec![DescriptorErrorKind::DecodeFileDescriptorSet { err }]) })?; self.build_files(file.file) } /// Gets an iterator over the file descriptors added to this pool. pub fn files(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner.files).map(|index| FileDescriptor { pool: self.clone(), index, }) } /// Gets a file descriptor by its name, or `None` if no such file has been added. pub fn get_file_by_name(&self, name: &str) -> Option { if let Some(&index) = self.inner.file_names.get(name) { Some(FileDescriptor { pool: self.clone(), index, }) } else { None } } /// Gets a iterator over the raw [`FileDescriptorProto`] instances wrapped by this [`DescriptorPool`]. pub fn file_descriptor_protos( &self, ) -> impl ExactSizeIterator + '_ { indices(&self.inner.files).map(|index| &self.inner.files[index as usize].prost) } /// Encodes the files contained within this [`DescriptorPool`] to their byte representation. /// /// The encoded message is equivalent to a [`FileDescriptorSet`], however also includes /// any extension options that were defined. pub fn encode(&self, buf: B) -> Result<(), EncodeError> where B: BufMut, { use prost::encoding::{encoded_len_varint, DecodeContext}; struct FileDescriptorSet<'a> { files: &'a [FileDescriptorInner], } impl fmt::Debug for FileDescriptorSet<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FileDescriptorSet").finish_non_exhaustive() } } impl Message for FileDescriptorSet<'_> { fn encode_raw(&self, buf: &mut impl BufMut) where Self: Sized, { for file in self.files { encoding::message::encode( tag::file_descriptor_set::FILE as u32, &file.raw, buf, ); } } fn encoded_len(&self) -> usize { encoding::key_len(tag::file_descriptor_set::FILE as u32) * self.files.len() + self .files .iter() .map(|f| &f.raw) .map(Message::encoded_len) .map(|len| len + encoded_len_varint(len as u64)) .sum::() } fn merge_field( &mut self, _: u32, _: WireType, _: &mut impl Buf, _: DecodeContext, ) -> Result<(), DecodeError> where Self: Sized, { unimplemented!() } fn clear(&mut self) { unimplemented!() } } let mut buf = buf; FileDescriptorSet { files: &self.inner.files, } .encode(&mut buf) } /// Encodes the files contained within this [`DescriptorPool`] to a newly allocated buffer. /// /// The encoded message is equivalent to a [`FileDescriptorSet`], however also includes /// any extension options that were defined. pub fn encode_to_vec(&self) -> Vec { let mut buf = Vec::new(); self.encode(&mut buf).expect("vec should have capacity"); buf } /// Gets an iterator over the services defined in these protobuf files. pub fn services(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner.services).map(|index| ServiceDescriptor { pool: self.clone(), index, }) } /// Gets an iterator over all message types defined in these protobuf files. /// /// The iterator includes nested messages defined in another message. pub fn all_messages(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner.messages).map(|index| MessageDescriptor { pool: self.clone(), index, }) } /// Gets an iterator over all enum types defined in these protobuf files. /// /// The iterator includes nested enums defined in another message. pub fn all_enums(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner.enums).map(|index| EnumDescriptor { pool: self.clone(), index, }) } /// Gets an iterator over all extension fields defined in these protobuf files. /// /// The iterator includes nested extension fields defined in another message. pub fn all_extensions(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner.extensions).map(|index| ExtensionDescriptor { pool: self.clone(), index, }) } /// Gets a [`MessageDescriptor`] by its fully qualified name, for example `my.package.MessageName`. pub fn get_message_by_name(&self, name: &str) -> Option { match self.inner.get_by_name(name) { Some(&Definition { kind: DefinitionKind::Message(index), .. }) => Some(MessageDescriptor { pool: self.clone(), index, }), _ => None, } } /// Gets an [`EnumDescriptor`] by its fully qualified name, for example `my.package.EnumName`. pub fn get_enum_by_name(&self, name: &str) -> Option { match self.inner.get_by_name(name) { Some(&Definition { kind: DefinitionKind::Enum(index), .. }) => Some(EnumDescriptor { pool: self.clone(), index, }), _ => None, } } /// Gets an [`ExtensionDescriptor`] by its fully qualified name, for example `my.package.my_extension`. pub fn get_extension_by_name(&self, name: &str) -> Option { match self.inner.get_by_name(name) { Some(&Definition { kind: DefinitionKind::Extension(index), .. }) => Some(ExtensionDescriptor { pool: self.clone(), index, }), _ => None, } } /// Gets an [`ServiceDescriptor`] by its fully qualified name, for example `my.package.MyService`. pub fn get_service_by_name(&self, name: &str) -> Option { match self.inner.get_by_name(name) { Some(&Definition { kind: DefinitionKind::Service(index), .. }) => Some(ServiceDescriptor { pool: self.clone(), index, }), _ => None, } } } impl fmt::Debug for DescriptorPool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("DescriptorPool") .field("files", &debug_fmt_iter(self.files())) .field("services", &debug_fmt_iter(self.services())) .field("all_messages", &debug_fmt_iter(self.all_messages())) .field("all_enums", &debug_fmt_iter(self.all_enums())) .field("all_extensions", &debug_fmt_iter(self.all_extensions())) .finish() } } impl PartialEq for DescriptorPool { fn eq(&self, other: &Self) -> bool { Arc::ptr_eq(&self.inner, &other.inner) } } impl Eq for DescriptorPool {} impl FileDescriptor { /// Create a new [`FileDescriptor`] referencing the file at `index` within the given [`DescriptorPool`]. /// /// # Panics /// /// Panics if `index` is out-of-bounds. pub fn new(descriptor_pool: DescriptorPool, index: usize) -> Self { debug_assert!(index < descriptor_pool.files().len()); FileDescriptor { pool: descriptor_pool, index: to_index(index), } } /// Gets a reference to the [`DescriptorPool`] this file is included in. pub fn parent_pool(&self) -> &DescriptorPool { &self.pool } /// Gets the unique name of this file relative to the root of the source tree, /// e.g. `path/to/my_package.proto`. pub fn name(&self) -> &str { self.inner().prost.name() } /// Gets the name of the package specifier for a file, e.g. `my.package`. /// /// If no package name is set, an empty string is returned. pub fn package_name(&self) -> &str { self.inner().prost.package() } /// Gets the index of this file within the parent [`DescriptorPool`]. pub fn index(&self) -> usize { self.index as usize } /// Gets the syntax of this protobuf file. pub fn syntax(&self) -> Syntax { self.inner().syntax } /// Gets the dependencies of this file. /// /// This corresponds to the [`FileDescriptorProto::dependency`] field. pub fn dependencies(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); self.file_descriptor_proto() .dependency .iter() .map(|name| pool.get_file_by_name(name).expect("file not found")) } /// Gets the public dependencies of this file. /// /// This corresponds to the [`FileDescriptorProto::public_dependency`] field. pub fn public_dependencies(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let raw = self.file_descriptor_proto(); raw.public_dependency.iter().map(|&index| { pool.get_file_by_name(&raw.dependency[index as usize]) .expect("file not found") }) } /// Gets the top-level message types defined within this file. /// /// This does not include nested messages defined within another message. pub fn messages(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let raw_file = self.file_descriptor_proto(); raw_file.message_type.iter().map(move |raw_message| { pool.get_message_by_name(join_name(raw_file.package(), raw_message.name()).as_ref()) .expect("message not found") }) } /// Gets the top-level enum types defined within this file. /// /// This does not include nested enums defined within another message. pub fn enums(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let raw_file = self.file_descriptor_proto(); raw_file.enum_type.iter().map(move |raw_enum| { pool.get_enum_by_name(join_name(raw_file.package(), raw_enum.name()).as_ref()) .expect("enum not found") }) } /// Gets the top-level extension fields defined within this file. /// /// This does not include nested extensions defined within another message. pub fn extensions(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let raw_file = self.file_descriptor_proto(); raw_file.extension.iter().map(move |raw_extension| { pool.get_extension_by_name(join_name(raw_file.package(), raw_extension.name()).as_ref()) .expect("extension not found") }) } /// Gets the services defined within this file. pub fn services(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let raw_file = self.file_descriptor_proto(); raw_file.service.iter().map(move |raw_service| { pool.get_service_by_name(join_name(raw_file.package(), raw_service.name()).as_ref()) .expect("service not found") }) } /// Gets a reference to the raw [`FileDescriptorProto`] wrapped by this [`FileDescriptor`]. pub fn file_descriptor_proto(&self) -> &FileDescriptorProto { &self.inner().prost } /// Encodes this file descriptor to its byte representation. /// /// The encoded message is equivalent to a [`FileDescriptorProto`], however also includes /// any extension options that were defined. pub fn encode(&self, buf: B) -> Result<(), EncodeError> where B: BufMut, { let mut buf = buf; self.inner().raw.encode(&mut buf) } /// Encodes this file descriptor to a newly allocated buffer. /// /// The encoded message is equivalent to a [`FileDescriptorProto`], however also includes /// any extension options that were defined. pub fn encode_to_vec(&self) -> Vec { let mut buf = Vec::new(); self.encode(&mut buf).expect("vec should have capacity"); buf } /// Decodes the options defined for this [`FileDescriptor`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.FileOptions", &self.inner().raw.options, ) } fn inner(&self) -> &FileDescriptorInner { &self.pool.inner.files[self.index as usize] } } impl fmt::Debug for FileDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FileDescriptor") .field("name", &self.name()) .field("package_name", &self.package_name()) .finish() } } impl MessageDescriptor { /// Gets a reference to the [`DescriptorPool`] this message is defined in. pub fn parent_pool(&self) -> &DescriptorPool { &self.pool } /// Gets the [`FileDescriptor`] this message is defined in. pub fn parent_file(&self) -> FileDescriptor { FileDescriptor { pool: self.pool.clone(), index: self.inner().id.file, } } /// Gets the parent message type if this message type is nested inside a another message, or `None` otherwise pub fn parent_message(&self) -> Option { self.inner().parent.map(|index| MessageDescriptor { pool: self.pool.clone(), index, }) } /// Gets the short name of the message type, e.g. `MyMessage`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the message type, e.g. `my.package.MyMessage`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the name of the package this message type is defined in, e.g. `my.package`. /// /// If no package name is set, an empty string is returned. pub fn package_name(&self) -> &str { self.raw_file().package() } /// Gets the path where this message is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[4, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the [`FileDescriptorProto`] in which this message is defined. pub fn parent_file_descriptor_proto(&self) -> &FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].prost } /// Gets a reference to the raw [`DescriptorProto`] wrapped by this [`MessageDescriptor`]. pub fn descriptor_proto(&self) -> &DescriptorProto { find_message_proto_prost(self.parent_file_descriptor_proto(), self.path()) } /// Decodes the options defined for this [`MessageDescriptor`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.MessageOptions", &self.raw().options, ) } /// Gets an iterator yielding a [`FieldDescriptor`] for each field defined in this message. pub fn fields(&self) -> impl ExactSizeIterator + '_ { self.inner() .field_numbers .values() .map(|&index| FieldDescriptor { message: self.clone(), index, }) } pub(crate) fn fields_in_index_order( &self, ) -> impl ExactSizeIterator + '_ { self.inner() .fields .iter() .enumerate() .map(|(index, _)| FieldDescriptor { message: self.clone(), index: index as u32, }) } /// Gets an iterator yielding a [`OneofDescriptor`] for each oneof field defined in this message. pub fn oneofs(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner().oneofs).map(|index| OneofDescriptor { message: self.clone(), index, }) } /// Gets the nested message types defined within this message. pub fn child_messages(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let namespace = self.full_name(); let raw_message = self.descriptor_proto(); raw_message.nested_type.iter().map(move |raw_message| { pool.get_message_by_name(join_name(namespace, raw_message.name()).as_ref()) .expect("message not found") }) } /// Gets the nested enum types defined within this message. pub fn child_enums(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let namespace = self.full_name(); let raw_message = self.descriptor_proto(); raw_message.enum_type.iter().map(move |raw_enum| { pool.get_enum_by_name(join_name(namespace, raw_enum.name()).as_ref()) .expect("enum not found") }) } /// Gets the nested extension fields defined within this message. /// /// Note this only returns extensions defined nested within this message. See /// [`MessageDescriptor::extensions`] to get fields defined anywhere that extend this message. pub fn child_extensions(&self) -> impl ExactSizeIterator + '_ { let pool = self.parent_pool(); let namespace = self.full_name(); let raw_message = self.descriptor_proto(); raw_message.extension.iter().map(move |raw_extension| { pool.get_extension_by_name(join_name(namespace, raw_extension.name()).as_ref()) .expect("extension not found") }) } /// Gets an iterator over all extensions to this message defined in the parent [`DescriptorPool`]. /// /// Note this iterates over extension fields defined anywhere which extend this message. See /// [`MessageDescriptor::child_extensions`] to just get extensions defined nested within this message. pub fn extensions(&self) -> impl ExactSizeIterator + '_ { self.inner() .extensions .iter() .map(|&index| ExtensionDescriptor { pool: self.parent_pool().clone(), index, }) } /// Gets a [`FieldDescriptor`] with the given number, or `None` if no such field exists. pub fn get_field(&self, number: u32) -> Option { self.inner() .field_numbers .get(&number) .map(|&index| FieldDescriptor { message: self.clone(), index, }) } /// Gets a [`FieldDescriptor`] with the given name, or `None` if no such field exists. pub fn get_field_by_name(&self, name: &str) -> Option { self.inner() .field_names .get(name) .map(|&index| FieldDescriptor { message: self.clone(), index, }) } /// Gets a [`FieldDescriptor`] with the given JSON name, or `None` if no such field exists. pub fn get_field_by_json_name(&self, json_name: &str) -> Option { self.inner() .field_json_names .get(json_name) .map(|&index| FieldDescriptor { message: self.clone(), index, }) } /// Returns `true` if this is an auto-generated message type to /// represent the entry type for a map field. // /// If this method returns `true`, [`fields`][Self::fields] is guaranteed to /// yield the following two fields: /// /// * A "key" field with a field number of 1 /// * A "value" field with a field number of 2 /// /// See [`map_entry_key_field`][MessageDescriptor::map_entry_key_field] and /// [`map_entry_value_field`][MessageDescriptor::map_entry_value_field] for more a convenient way /// to get these fields. pub fn is_map_entry(&self) -> bool { self.raw() .options .as_ref() .map(|o| o.value.map_entry()) .unwrap_or(false) } /// If this is a [map entry](MessageDescriptor::is_map_entry), returns a [`FieldDescriptor`] for the key. /// /// # Panics /// /// This method may panic if [`is_map_entry`][MessageDescriptor::is_map_entry] returns `false`. pub fn map_entry_key_field(&self) -> FieldDescriptor { debug_assert!(self.is_map_entry()); self.get_field(MAP_ENTRY_KEY_NUMBER) .expect("map entry should have key field") } /// If this is a [map entry](MessageDescriptor::is_map_entry), returns a [`FieldDescriptor`] for the value. /// /// # Panics /// /// This method may panic if [`is_map_entry`][MessageDescriptor::is_map_entry] returns `false`. pub fn map_entry_value_field(&self) -> FieldDescriptor { debug_assert!(self.is_map_entry()); self.get_field(MAP_ENTRY_VALUE_NUMBER) .expect("map entry should have value field") } /// Gets an iterator over reserved field number ranges in this message. pub fn reserved_ranges(&self) -> impl ExactSizeIterator> + '_ { self.raw() .reserved_range .iter() .map(|n| (n.start() as u32)..(n.end() as u32)) } /// Gets an iterator over reserved field names in this message. pub fn reserved_names(&self) -> impl ExactSizeIterator + '_ { self.raw().reserved_name.iter().map(|n| n.as_ref()) } /// Gets an iterator over extension field number ranges in this message. pub fn extension_ranges(&self) -> impl ExactSizeIterator> + '_ { self.raw() .extension_range .iter() .map(|n| (n.start() as u32)..(n.end() as u32)) } /// Gets an extension to this message by its number, or `None` if no such extension exists. pub fn get_extension(&self, number: u32) -> Option { self.extensions().find(|ext| ext.number() == number) } /// Gets an extension to this message by its full name (e.g. `my.package.my_extension`), or `None` if no such extension exists. pub fn get_extension_by_full_name(&self, name: &str) -> Option { self.extensions().find(|ext| ext.full_name() == name) } /// Gets an extension to this message by its JSON name (e.g. `[my.package.my_extension]`), or `None` if no such extension exists. pub fn get_extension_by_json_name(&self, name: &str) -> Option { self.extensions().find(|ext| ext.json_name() == name) } fn inner(&self) -> &MessageDescriptorInner { &self.pool.inner.messages[self.index as usize] } fn raw(&self) -> &types::DescriptorProto { find_message_proto(self.raw_file(), self.path()) } fn raw_file(&self) -> &types::FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].raw } } impl fmt::Debug for MessageDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MessageDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("is_map_entry", &self.is_map_entry()) .field("fields", &debug_fmt_iter(self.fields())) .field("oneofs", &debug_fmt_iter(self.oneofs())) .finish() } } impl FieldDescriptor { /// Gets a reference to the [`DescriptorPool`] this field is defined in. pub fn parent_pool(&self) -> &DescriptorPool { self.message.parent_pool() } /// Gets the [`FileDescriptor`] this field is defined in. pub fn parent_file(&self) -> FileDescriptor { self.message.parent_file() } /// Gets a reference to the [`MessageDescriptor`] this field is defined in. pub fn parent_message(&self) -> &MessageDescriptor { &self.message } /// Gets the short name of the message type, e.g. `my_field`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the message field, e.g. `my.package.MyMessage.my_field`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the path where this message field is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[4, 0, 2, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the raw [`FieldDescriptorProto`] wrapped by this [`FieldDescriptor`]. pub fn field_descriptor_proto(&self) -> &FieldDescriptorProto { &self.parent_message().descriptor_proto().field[*self.path().last().unwrap() as usize] } /// Decodes the options defined for this [`FieldDescriptor`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.FieldOptions", &self.raw().options, ) } /// Gets the unique number for this message field. pub fn number(&self) -> u32 { self.inner().number } /// Gets the name used for JSON serialization. /// /// This is usually the camel-cased form of the field name, unless /// another value is set in the proto file. pub fn json_name(&self) -> &str { &self.inner().json_name } /// Whether this field is encoded using the proto2 group encoding. pub fn is_group(&self) -> bool { matches!(self.inner().kind, KindIndex::Group(_)) } /// Whether this field is a list type. /// /// Equivalent to checking that the cardinality is `Repeated` and that /// [`is_map`][Self::is_map] returns `false`. pub fn is_list(&self) -> bool { self.cardinality() == Cardinality::Repeated && !self.is_map() } /// Whether this field is a map type. /// /// Equivalent to checking that the cardinality is `Repeated` and that /// the field type is a message where [`is_map_entry`][MessageDescriptor::is_map_entry] /// returns `true`. pub fn is_map(&self) -> bool { self.cardinality() == Cardinality::Repeated && match self.kind() { Kind::Message(message) => message.is_map_entry(), _ => false, } } /// Whether this field is a list encoded using [packed encoding](https://developers.google.com/protocol-buffers/docs/encoding#packed). pub fn is_packed(&self) -> bool { self.inner().is_packed } /// The cardinality of this field. pub fn cardinality(&self) -> Cardinality { self.inner().cardinality } /// Whether this field supports distinguishing between an unpopulated field and /// the default value. /// /// For proto2 messages this returns `true` for all non-repeated fields. /// For proto3 this returns `true` for message fields, and fields contained /// in a `oneof`. pub fn supports_presence(&self) -> bool { self.inner().supports_presence } /// Gets the [`Kind`] of this field. pub fn kind(&self) -> Kind { Kind::new(self.parent_pool(), self.inner().kind) } /// Gets a [`OneofDescriptor`] representing the oneof containing this field, /// or `None` if this field is not contained in a oneof. pub fn containing_oneof(&self) -> Option { self.inner().oneof.map(|index| OneofDescriptor { message: self.message.clone(), index, }) } pub(crate) fn default_value(&self) -> Option<&Value> { self.inner().default.as_ref() } pub(crate) fn is_packable(&self) -> bool { self.inner().kind.is_packable() } fn inner(&self) -> &FieldDescriptorInner { &self.message.inner().fields[self.index as usize] } fn raw(&self) -> &types::FieldDescriptorProto { &self.message.raw().field[self.index as usize] } } impl fmt::Debug for FieldDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FieldDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("json_name", &self.json_name()) .field("number", &self.number()) .field("kind", &self.kind()) .field("cardinality", &self.cardinality()) .field( "containing_oneof", &self.containing_oneof().map(|o| o.name().to_owned()), ) .field("default_value", &self.default_value()) .field("is_group", &self.is_group()) .field("is_list", &self.is_list()) .field("is_map", &self.is_map()) .field("is_packed", &self.is_packed()) .field("supports_presence", &self.supports_presence()) .finish() } } impl ExtensionDescriptor { /// Gets a reference to the [`DescriptorPool`] this extension field is defined in. pub fn parent_pool(&self) -> &DescriptorPool { &self.pool } /// Gets the [`FileDescriptor`] this extension field is defined in. pub fn parent_file(&self) -> FileDescriptor { FileDescriptor { pool: self.pool.clone(), index: self.inner().id.file, } } /// Gets the parent message type if this extension is defined within another message, or `None` otherwise. /// /// Note this just corresponds to where the extension is defined in the proto file. See [`containing_message`][ExtensionDescriptor::containing_message] /// for the message this field extends. pub fn parent_message(&self) -> Option { self.inner().parent.map(|index| MessageDescriptor { pool: self.pool.clone(), index, }) } /// Gets the short name of the extension field type, e.g. `my_extension`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the extension field, e.g. `my.package.ParentMessage.my_extension`. /// /// Note this includes the name of the parent message if any, not the message this field extends. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the name of the package this extension field is defined in, e.g. `my.package`. /// /// If no package name is set, an empty string is returned. pub fn package_name(&self) -> &str { self.raw_file().package() } /// Gets the path where this extension field is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[7, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the [`FileDescriptorProto`] in which this extension is defined. pub fn parent_file_descriptor_proto(&self) -> &FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].prost } /// Gets a reference to the raw [`FieldDescriptorProto`] wrapped by this [`ExtensionDescriptor`]. pub fn field_descriptor_proto(&self) -> &FieldDescriptorProto { let file = self.parent_file_descriptor_proto(); let path = self.path(); debug_assert_ne!(path.len(), 0); debug_assert_eq!(path.len() % 2, 0); if path.len() == 2 { debug_assert_eq!(path[0], tag::file::EXTENSION); &file.extension[path[1] as usize] } else { let message = find_message_proto_prost(file, &path[..path.len() - 2]); debug_assert_eq!(path[path.len() - 2], tag::message::EXTENSION); &message.extension[path[path.len() - 1] as usize] } } /// Decodes the options defined for this [`ExtensionDescriptor`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.FieldOptions", &self.raw().options, ) } /// Gets the number for this extension field. pub fn number(&self) -> u32 { self.inner().number } /// Gets the name used for JSON serialization of this extension field, e.g. `[my.package.ParentMessage.my_field]`. pub fn json_name(&self) -> &str { &self.inner().json_name } /// Whether this field is encoded using the proto2 group encoding. pub fn is_group(&self) -> bool { matches!(self.inner().kind, KindIndex::Group(_)) } /// Whether this field is a list type. /// /// Equivalent to checking that the cardinality is `Repeated` and that /// [`is_map`][Self::is_map] returns `false`. pub fn is_list(&self) -> bool { self.cardinality() == Cardinality::Repeated && !self.is_map() } /// Whether this field is a map type. /// /// Equivalent to checking that the cardinality is `Repeated` and that /// the field type is a message where [`is_map_entry`][MessageDescriptor::is_map_entry] /// returns `true`. pub fn is_map(&self) -> bool { self.cardinality() == Cardinality::Repeated && match self.kind() { Kind::Message(message) => message.is_map_entry(), _ => false, } } /// Whether this field is a list encoded using [packed encoding](https://developers.google.com/protocol-buffers/docs/encoding#packed). pub fn is_packed(&self) -> bool { self.inner().is_packed } /// The cardinality of this field. pub fn cardinality(&self) -> Cardinality { self.inner().cardinality } /// Whether this extension supports distinguishing between an unpopulated field and /// the default value. /// /// This is equivalent to `cardinality() != Cardinality::Repeated` pub fn supports_presence(&self) -> bool { self.cardinality() != Cardinality::Repeated } /// Gets the [`Kind`] of this field. pub fn kind(&self) -> Kind { Kind::new(&self.pool, self.inner().kind) } /// Gets the containing message that this field extends. pub fn containing_message(&self) -> MessageDescriptor { MessageDescriptor { pool: self.pool.clone(), index: self.inner().extendee, } } pub(crate) fn default_value(&self) -> Option<&Value> { self.inner().default.as_ref() } pub(crate) fn is_packable(&self) -> bool { self.inner().kind.is_packable() } fn inner(&self) -> &ExtensionDescriptorInner { &self.pool.inner.extensions[self.index as usize] } fn raw(&self) -> &types::FieldDescriptorProto { let file = self.raw_file(); let path = self.path(); debug_assert_ne!(path.len(), 0); debug_assert_eq!(path.len() % 2, 0); if path.len() == 2 { debug_assert_eq!(path[0], tag::file::EXTENSION); &file.extension[path[1] as usize] } else { let message = find_message_proto(file, &path[..path.len() - 2]); debug_assert_eq!(path[path.len() - 2], tag::message::EXTENSION); &message.extension[path[path.len() - 1] as usize] } } fn raw_file(&self) -> &types::FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].raw } } impl fmt::Debug for ExtensionDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ExtensionDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("json_name", &self.json_name()) .field("number", &self.number()) .field("kind", &self.kind()) .field("cardinality", &self.cardinality()) .field( "containing_message", &self.containing_message().name().to_owned(), ) .field("default_value", &self.default_value()) .field("is_group", &self.is_group()) .field("is_list", &self.is_list()) .field("is_map", &self.is_map()) .field("is_packed", &self.is_packed()) .field("supports_presence", &self.supports_presence()) .finish() } } impl EnumDescriptor { /// Gets a reference to the [`DescriptorPool`] this enum type is defined in. pub fn parent_pool(&self) -> &DescriptorPool { &self.pool } /// Gets the [`FileDescriptor`] this enum type is defined in. pub fn parent_file(&self) -> FileDescriptor { FileDescriptor { pool: self.pool.clone(), index: self.inner().id.file, } } /// Gets the parent message type if this enum type is nested inside a another message, or `None` otherwise pub fn parent_message(&self) -> Option { self.inner().parent.map(|index| MessageDescriptor { pool: self.pool.clone(), index, }) } /// Gets the short name of the enum type, e.g. `MyEnum`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the enum, e.g. `my.package.MyEnum`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the name of the package this enum type is defined in, e.g. `my.package`. /// /// If no package name is set, an empty string is returned. pub fn package_name(&self) -> &str { self.raw_file().package() } /// Gets the path where this enum type is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[5, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the [`FileDescriptorProto`] in which this enum is defined. pub fn parent_file_descriptor_proto(&self) -> &FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].prost } /// Gets a reference to the raw [`EnumDescriptorProto`] wrapped by this [`EnumDescriptor`]. pub fn enum_descriptor_proto(&self) -> &EnumDescriptorProto { let file = self.parent_file_descriptor_proto(); let path = self.path(); debug_assert_ne!(path.len(), 0); debug_assert_eq!(path.len() % 2, 0); if path.len() == 2 { debug_assert_eq!(path[0], tag::file::ENUM_TYPE); &file.enum_type[path[1] as usize] } else { let message = find_message_proto_prost(file, &path[..path.len() - 2]); debug_assert_eq!(path[path.len() - 2], tag::message::ENUM_TYPE); &message.enum_type[path[path.len() - 1] as usize] } } /// Decodes the options defined for this [`EnumDescriptor`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.EnumOptions", &self.raw().options, ) } /// Gets the default value for the enum type. pub fn default_value(&self) -> EnumValueDescriptor { EnumValueDescriptor { parent: self.clone(), index: 0, } } /// Gets a [`EnumValueDescriptor`] for the enum value with the given name, or `None` if no such value exists. pub fn get_value_by_name(&self, name: &str) -> Option { self.inner() .value_names .get(name) .map(|&index| EnumValueDescriptor { parent: self.clone(), index, }) } /// Gets a [`EnumValueDescriptor`] for the enum value with the given number, or `None` if no such value exists. /// /// If the enum is defined with the `allow_alias` option and has multiple values with the given number, it is /// unspecified which one will be returned. pub fn get_value(&self, number: i32) -> Option { self.inner() .value_numbers .binary_search_by(|(l, _)| l.cmp(&number)) .ok() .map(|index| EnumValueDescriptor { parent: self.clone(), index: self.inner().value_numbers[index].1, }) } /// Gets an iterator yielding a [`EnumValueDescriptor`] for each value in this enum. pub fn values(&self) -> impl ExactSizeIterator + '_ { self.inner() .value_numbers .iter() .map(|&(_, index)| EnumValueDescriptor { parent: self.clone(), index, }) } /// Gets an iterator over reserved value number ranges in this enum. pub fn reserved_ranges(&self) -> impl ExactSizeIterator> + '_ { self.raw() .reserved_range .iter() .map(|n| n.start()..=n.end()) } /// Gets an iterator over reserved value names in this enum. pub fn reserved_names(&self) -> impl ExactSizeIterator + '_ { self.raw().reserved_name.iter().map(|n| n.as_ref()) } fn inner(&self) -> &EnumDescriptorInner { &self.pool.inner.enums[self.index as usize] } fn raw(&self) -> &types::EnumDescriptorProto { find_enum_proto(self.raw_file(), self.path()) } fn raw_file(&self) -> &types::FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].raw } } impl fmt::Debug for EnumDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("EnumDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("default_value", &self.default_value()) .field("values", &debug_fmt_iter(self.values())) .finish() } } impl EnumValueDescriptor { /// Gets a reference to the [`DescriptorPool`] this enum value is defined in. pub fn parent_pool(&self) -> &DescriptorPool { self.parent.parent_pool() } /// Gets the [`FileDescriptor`] this enum value is defined in. pub fn parent_file(&self) -> FileDescriptor { self.parent.parent_file() } /// Gets a reference to the [`EnumDescriptor`] this enum value is defined in. pub fn parent_enum(&self) -> &EnumDescriptor { &self.parent } /// Gets the short name of the enum value, e.g. `MY_VALUE`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the enum value, e.g. `my.package.MY_VALUE`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the path where this enum value is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[5, 0, 2, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the raw [`EnumValueDescriptorProto`] wrapped by this [`EnumValueDescriptor`]. pub fn enum_value_descriptor_proto(&self) -> &EnumValueDescriptorProto { &self.parent.enum_descriptor_proto().value[self.index as usize] } /// Decodes the options defined for this [`EnumValueDescriptor`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.EnumValueOptions", &self.raw().options, ) } /// Gets the number representing this enum value. pub fn number(&self) -> i32 { self.inner().number } fn inner(&self) -> &EnumValueDescriptorInner { &self.parent.inner().values[self.index as usize] } fn raw(&self) -> &types::EnumValueDescriptorProto { &self.parent.raw().value[self.index as usize] } } impl fmt::Debug for EnumValueDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("EnumValueDescriptor") .field("name", &self.number()) .field("full_name", &self.full_name()) .field("number", &self.number()) .finish() } } impl OneofDescriptor { /// Gets a reference to the [`DescriptorPool`] this oneof is defined in. pub fn parent_pool(&self) -> &DescriptorPool { self.message.parent_pool() } /// Gets the [`FileDescriptor`] this oneof is defined in. pub fn parent_file(&self) -> FileDescriptor { self.message.parent_file() } /// Gets a reference to the [`MessageDescriptor`] this oneof is defined in. pub fn parent_message(&self) -> &MessageDescriptor { &self.message } /// Gets the short name of the oneof, e.g. `my_oneof`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the oneof, e.g. `my.package.MyMessage.my_oneof`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the path where this oneof is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[4, 0, 8, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the raw [`OneofDescriptorProto`] wrapped by this [`OneofDescriptor`]. pub fn oneof_descriptor_proto(&self) -> &OneofDescriptorProto { &self.message.descriptor_proto().oneof_decl[self.index as usize] } /// Decodes the options defined for this [`OneofDescriptorProto`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.OneofOptions", &self.raw().options, ) } /// Gets an iterator yielding a [`FieldDescriptor`] for each field of the parent message this oneof contains. pub fn fields(&self) -> impl ExactSizeIterator + '_ { self.inner().fields.iter().map(|&index| FieldDescriptor { message: self.parent_message().clone(), index, }) } fn inner(&self) -> &OneofDescriptorInner { &self.message.inner().oneofs[self.index as usize] } fn raw(&self) -> &types::OneofDescriptorProto { &self.message.raw().oneof_decl[self.index as usize] } } impl fmt::Debug for OneofDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OneofDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("fields", &debug_fmt_iter(self.fields())) .finish() } } impl ServiceDescriptor { /// Create a new [`ServiceDescriptor`] referencing the service at `index` within the given [`DescriptorPool`]. /// /// # Panics /// /// Panics if `index` is out-of-bounds. pub fn new(pool: DescriptorPool, index: usize) -> Self { debug_assert!(index < pool.services().len()); ServiceDescriptor { pool, index: to_index(index), } } /// Returns the index of this [`ServiceDescriptor`] within the parent [`DescriptorPool`]. pub fn index(&self) -> usize { self.index as usize } /// Gets a reference to the [`DescriptorPool`] this service is defined in. pub fn parent_pool(&self) -> &DescriptorPool { &self.pool } /// Gets the [`FileDescriptor`] this service is defined in. pub fn parent_file(&self) -> FileDescriptor { FileDescriptor { pool: self.pool.clone(), index: self.inner().id.file, } } /// Gets the short name of the service, e.g. `MyService`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the service, e.g. `my.package.Service`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the name of the package this service is defined in, e.g. `my.package`. /// /// If no package name is set, an empty string is returned. pub fn package_name(&self) -> &str { self.raw_file().package() } /// Gets the path where this service is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[6, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the [`FileDescriptorProto`] in which this service is defined. pub fn parent_file_descriptor_proto(&self) -> &FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].prost } /// Gets a reference to the raw [`ServiceDescriptorProto`] wrapped by this [`ServiceDescriptor`]. pub fn service_descriptor_proto(&self) -> &ServiceDescriptorProto { let path = self.path(); debug_assert!(!path.is_empty()); &self.parent_file_descriptor_proto().service[*path.last().unwrap() as usize] } /// Decodes the options defined for this [`ServiceDescriptorProto`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.ServiceOptions", &self.raw().options, ) } /// Gets an iterator yielding a [`MethodDescriptor`] for each method defined in this service. pub fn methods(&self) -> impl ExactSizeIterator + '_ { indices(&self.inner().methods).map(|index| MethodDescriptor { service: self.clone(), index, }) } fn inner(&self) -> &ServiceDescriptorInner { &self.pool.inner.services[self.index as usize] } fn raw(&self) -> &types::ServiceDescriptorProto { let path = self.path(); debug_assert!(!path.is_empty()); &self.raw_file().service[*path.last().unwrap() as usize] } fn raw_file(&self) -> &types::FileDescriptorProto { &self.pool.inner.files[self.inner().id.file as usize].raw } } impl fmt::Debug for ServiceDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ServiceDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("index", &self.index()) .field("methods", &debug_fmt_iter(self.methods())) .finish() } } impl MethodDescriptor { /// Create a new [`MethodDescriptor`] referencing the method at `index` within the [`ServiceDescriptor`]. /// /// # Panics /// /// Panics if `index` is out-of-bounds. pub fn new(service: ServiceDescriptor, index: usize) -> Self { debug_assert!(index < service.methods().len()); MethodDescriptor { service, index: to_index(index), } } /// Gets the index of the method within the parent [`ServiceDescriptor`]. pub fn index(&self) -> usize { self.index as usize } /// Gets a reference to the [`ServiceDescriptor`] this method is defined in. pub fn parent_service(&self) -> &ServiceDescriptor { &self.service } /// Gets a reference to the [`DescriptorPool`] this method is defined in. pub fn parent_pool(&self) -> &DescriptorPool { self.service.parent_pool() } /// Gets the [`FileDescriptor`] this method is defined in. pub fn parent_file(&self) -> FileDescriptor { self.service.parent_file() } /// Gets the short name of the method, e.g. `method`. pub fn name(&self) -> &str { self.inner().id.name() } /// Gets the full name of the method, e.g. `my.package.MyService.my_method`. pub fn full_name(&self) -> &str { self.inner().id.full_name() } /// Gets the path where this method is defined within the [`FileDescriptorProto`][FileDescriptorProto], e.g. `[6, 0, 2, 0]`. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> &[i32] { &self.inner().id.path } /// Gets a reference to the raw [`MethodDescriptorProto`] wrapped by this [`MethodDescriptor`]. pub fn method_descriptor_proto(&self) -> &MethodDescriptorProto { &self.service.service_descriptor_proto().method[self.index as usize] } /// Decodes the options defined for this [`MethodDescriptorProto`], including any extension options. pub fn options(&self) -> DynamicMessage { decode_options( self.parent_pool(), "google.protobuf.MethodOptions", &self.raw().options, ) } /// Gets the [`MessageDescriptor`] for the input type of this method. pub fn input(&self) -> MessageDescriptor { MessageDescriptor { pool: self.parent_pool().clone(), index: self.inner().input, } } /// Gets the [`MessageDescriptor`] for the output type of this method. pub fn output(&self) -> MessageDescriptor { MessageDescriptor { pool: self.parent_pool().clone(), index: self.inner().output, } } /// Returns `true` if the client streams multiple messages. pub fn is_client_streaming(&self) -> bool { self.raw().client_streaming() } /// Returns `true` if the server streams multiple messages. pub fn is_server_streaming(&self) -> bool { self.raw().server_streaming() } fn inner(&self) -> &MethodDescriptorInner { &self.service.inner().methods[self.index as usize] } fn raw(&self) -> &types::MethodDescriptorProto { &self.service.raw().method[self.index as usize] } } impl fmt::Debug for MethodDescriptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MethodDescriptor") .field("name", &self.name()) .field("full_name", &self.full_name()) .field("index", &self.index()) .field("input", &self.input()) .field("output", &self.output()) .field("is_client_streaming", &self.is_client_streaming()) .field("is_server_streaming", &self.is_server_streaming()) .finish() } } fn debug_fmt_iter(i: I) -> impl fmt::Debug where I: Iterator, I::Item: fmt::Debug, { struct Wrapper(Vec); impl fmt::Debug for Wrapper where T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(&self.0).finish() } } Wrapper(i.collect()) } #[allow(clippy::ptr_arg)] fn indices(f: &Vec) -> Range { 0..to_index(f.len()) } fn join_name<'a>(namespace: &str, name: &'a str) -> Cow<'a, str> { if namespace.is_empty() { Cow::Borrowed(name) } else { Cow::Owned(format!("{}.{}", namespace, name)) } } fn decode_options( pool: &DescriptorPool, name: &str, option: &Option>, ) -> DynamicMessage { let message_desc = pool .get_message_by_name(name) .unwrap_or_else(|| DescriptorPool::global().get_message_by_name(name).unwrap()); let bytes = option .as_ref() .map(|o| o.encoded.as_slice()) .unwrap_or_default(); DynamicMessage::decode(message_desc, bytes).unwrap() } fn find_message_proto_prost<'a>( file: &'a FileDescriptorProto, path: &[i32], ) -> &'a DescriptorProto { debug_assert_ne!(path.len(), 0); debug_assert_eq!(path.len() % 2, 0); let mut message: Option<&'a DescriptorProto> = None; for part in path.chunks(2) { match part[0] { tag::file::MESSAGE_TYPE => message = Some(&file.message_type[part[1] as usize]), tag::message::NESTED_TYPE => { message = Some(&message.unwrap().nested_type[part[1] as usize]) } _ => panic!("invalid message path"), } } message.unwrap() } prost-reflect-0.15.0/src/descriptor/build/mod.rs000064400000000000000000000327351046102023000177030ustar 00000000000000mod names; mod options; mod resolve; mod visit; use core::fmt; use std::{ borrow::Cow, collections::{HashMap, HashSet}, iter, sync::Arc, }; use crate::{ descriptor::{ error::{DescriptorErrorKind, Label}, to_index, types::FileDescriptorProto, Definition, DefinitionKind, DescriptorPoolInner, EnumIndex, ExtensionIndex, FileDescriptorInner, FileIndex, MessageIndex, ServiceIndex, }, DescriptorError, DescriptorPool, }; #[derive(Clone, Copy)] struct DescriptorPoolOffsets { file: FileIndex, message: MessageIndex, enum_: EnumIndex, service: ServiceIndex, extension: ExtensionIndex, } #[derive(Copy, Clone, Debug)] enum ResolveNameFilter { Message, Extension, FieldType, } enum ResolveNameResult<'a, 'b> { Found { name: Cow<'b, str>, def: &'a Definition, }, InvalidType { name: Cow<'b, str>, def: &'a Definition, filter: ResolveNameFilter, }, NotImported { name: Cow<'b, str>, file: FileIndex, }, Shadowed { name: Cow<'b, str>, shadowed_name: Cow<'b, str>, }, NotFound, } impl DescriptorPoolOffsets { fn new(pool: &DescriptorPoolInner) -> Self { DescriptorPoolOffsets { file: to_index(pool.files.len()), message: to_index(pool.messages.len()), enum_: to_index(pool.enums.len()), service: to_index(pool.services.len()), extension: to_index(pool.extensions.len()), } } fn rollback(&self, pool: &mut DescriptorPoolInner) { pool.files.truncate(self.file as usize); pool.messages.truncate(self.message as usize); pool.enums.truncate(self.enum_ as usize); pool.extensions.truncate(self.extension as usize); pool.services.truncate(self.service as usize); pool.names.retain(|name, definition| match definition.kind { DefinitionKind::Package => pool.files.iter().any(|f| { f.prost.package().starts_with(name.as_ref()) && matches!( f.prost.package().as_bytes().get(name.len()), None | Some(&b'.') ) }), DefinitionKind::Message(message) | DefinitionKind::Field(message) | DefinitionKind::Oneof(message) => message < self.message, DefinitionKind::Service(service) | DefinitionKind::Method(service) => { service < self.service } DefinitionKind::Enum(enum_) | DefinitionKind::EnumValue(enum_) => enum_ < self.enum_, DefinitionKind::Extension(extension) => extension < self.extension, }); pool.file_names.retain(|_, &mut file| file < self.file); for message in &mut pool.messages { message.extensions.retain(|&message| message < self.message); } } } impl DescriptorPool { pub(crate) fn build_files(&mut self, files: I) -> Result<(), DescriptorError> where I: IntoIterator, { let offsets = DescriptorPoolOffsets::new(&self.inner); let deduped_files: Vec<_> = files .into_iter() .filter(|f| !self.inner.file_names.contains_key(f.name())) .collect(); let result = self.build_files_deduped(offsets, &deduped_files); if result.is_err() { debug_assert_eq!(Arc::strong_count(&self.inner), 1); offsets.rollback(Arc::get_mut(&mut self.inner).unwrap()); } result } fn build_files_deduped( &mut self, offsets: DescriptorPoolOffsets, deduped_files: &[FileDescriptorProto], ) -> Result<(), DescriptorError> { if deduped_files.is_empty() { return Ok(()); } let inner = Arc::make_mut(&mut self.inner); inner.collect_names(offsets, deduped_files)?; inner.resolve_names(offsets, deduped_files)?; self.resolve_options(offsets, deduped_files)?; debug_assert_eq!(Arc::strong_count(&self.inner), 1); let inner = Arc::get_mut(&mut self.inner).unwrap(); for file in &mut inner.files[offsets.file as usize..] { file.prost = file.raw.to_prost(); } Ok(()) } } impl ResolveNameFilter { fn is_match(&self, def: &DefinitionKind) -> bool { matches!( (self, def), (ResolveNameFilter::Message, DefinitionKind::Message(_)) | (ResolveNameFilter::Extension, DefinitionKind::Extension(_)) | ( ResolveNameFilter::FieldType, DefinitionKind::Message(_) | DefinitionKind::Enum(_), ) ) } } impl fmt::Display for ResolveNameFilter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ResolveNameFilter::Message => f.write_str("a message type"), ResolveNameFilter::Extension => f.write_str("an extension"), ResolveNameFilter::FieldType => f.write_str("a message or enum type"), } } } impl<'a, 'b> ResolveNameResult<'a, 'b> { fn new( dependencies: &HashSet, names: &'a HashMap, Definition>, name: impl Into>, filter: ResolveNameFilter, ) -> Self { let name = name.into(); if let Some(def) = names.get(name.as_ref()) { if !dependencies.contains(&def.file) { ResolveNameResult::NotImported { name, file: def.file, } } else if !filter.is_match(&def.kind) { ResolveNameResult::InvalidType { name, def, filter } } else { ResolveNameResult::Found { name, def } } } else { ResolveNameResult::NotFound } } fn into_owned(self) -> ResolveNameResult<'a, 'static> { match self { ResolveNameResult::Found { name, def } => ResolveNameResult::Found { name: Cow::Owned(name.into_owned()), def, }, ResolveNameResult::InvalidType { name, def, filter } => { ResolveNameResult::InvalidType { name: Cow::Owned(name.into_owned()), def, filter, } } ResolveNameResult::NotImported { name, file } => ResolveNameResult::NotImported { name: Cow::Owned(name.into_owned()), file, }, ResolveNameResult::Shadowed { name, shadowed_name, } => ResolveNameResult::Shadowed { name: Cow::Owned(name.into_owned()), shadowed_name: Cow::Owned(shadowed_name.into_owned()), }, ResolveNameResult::NotFound => ResolveNameResult::NotFound, } } fn is_found(&self) -> bool { matches!(self, ResolveNameResult::Found { .. }) } #[allow(clippy::result_large_err)] fn into_result( self, orig_name: impl Into, files: &[FileDescriptorInner], found_file: FileIndex, found_path1: &[i32], found_path2: &[i32], ) -> Result<(Cow<'b, str>, &'a Definition), DescriptorErrorKind> { match self { ResolveNameResult::Found { name, def } => Ok((name, def)), ResolveNameResult::InvalidType { name, def, filter } => { Err(DescriptorErrorKind::InvalidType { name: name.into_owned(), expected: filter.to_string(), found: Label::new( files, "found here", found_file, join_path(found_path1, found_path2), ), defined: Label::new(files, "defined here", def.file, def.path.clone()), }) } ResolveNameResult::NotImported { name, file } => { let root_name = files[found_file as usize].raw.name(); let dep_name = files[file as usize].raw.name(); Err(DescriptorErrorKind::NameNotFound { found: Label::new( files, "found here", found_file, join_path(found_path1, found_path2), ), help: Some(format!( "'{}' is defined in '{}', which is not imported by '{}'", name, dep_name, root_name )), name: name.into_owned(), }) } ResolveNameResult::NotFound => Err(DescriptorErrorKind::NameNotFound { name: orig_name.into(), found: Label::new( files, "found here", found_file, join_path(found_path1, found_path2), ), help: None, }), ResolveNameResult::Shadowed { name, shadowed_name } => Err(DescriptorErrorKind::NameShadowed { found: Label::new( files, "found here", found_file, join_path(found_path1, found_path2), ), help: Some(format!( "The innermost scope is searched first in name resolution. Consider using a leading '.' (i.e., '.{name}') to start from the outermost scope.", )), name: name.into_owned(), shadowed_name: shadowed_name.into_owned(), }), } } } fn to_json_name(name: &str) -> String { let mut result = String::with_capacity(name.len()); let mut uppercase_next = false; for ch in name.chars() { if ch == '_' { uppercase_next = true } else if uppercase_next { result.push(ch.to_ascii_uppercase()); uppercase_next = false; } else { result.push(ch); } } result } fn resolve_name<'a, 'b>( dependencies: &HashSet, names: &'a HashMap, Definition>, scope: &str, name: &'b str, filter: ResolveNameFilter, ) -> ResolveNameResult<'a, 'b> { match name.strip_prefix('.') { Some(full_name) => ResolveNameResult::new(dependencies, names, full_name, filter), None if scope.is_empty() => ResolveNameResult::new(dependencies, names, name, filter), None => resolve_relative_name(dependencies, names, scope, name, filter), } } fn resolve_relative_name<'a, 'b>( dependencies: &HashSet, names: &'a HashMap, Definition>, scope: &str, relative_name: &'b str, filter: ResolveNameFilter, ) -> ResolveNameResult<'a, 'b> { let mut err = ResolveNameResult::NotFound; let relative_first_part = relative_name.split('.').next().unwrap_or_default(); for candidate_parent in resolve_relative_candidate_parents(scope) { let candidate = match candidate_parent { "" => Cow::Borrowed(relative_first_part), _ => Cow::Owned(format!("{}.{}", candidate_parent, relative_first_part)), }; if relative_first_part.len() == relative_name.len() { // Looking up a simple name e.g. `Foo` let res = ResolveNameResult::new(dependencies, names, candidate, filter); if res.is_found() { return res.into_owned(); } else if matches!(err, ResolveNameResult::NotFound) { err = res; } } else { // Looking up a name including a namespace e.g. `foo.Foo`. First determine the scope using the first component of the name. match names.get(candidate.as_ref()) { Some(def) if def.kind.is_parent() => { let candidate_full = match candidate_parent { "" => Cow::Borrowed(relative_name), _ => Cow::Owned(format!("{}.{}", candidate_parent, relative_name)), }; let res = ResolveNameResult::new(dependencies, names, candidate_full.clone(), filter); if matches!(res, ResolveNameResult::NotFound) { return ResolveNameResult::Shadowed { name: Cow::Borrowed(relative_name), shadowed_name: candidate_full, }; } else { return res; } } _ => continue, } } } err.into_owned() } fn resolve_relative_candidate_parents(scope: &str) -> impl Iterator { iter::once(scope) .chain(scope.rmatch_indices('.').map(move |(i, _)| &scope[..i])) .chain(iter::once("")) } fn join_path(path1: &[i32], path2: &[i32]) -> Box<[i32]> { let mut path = Vec::with_capacity(path1.len() + path2.len()); path.extend_from_slice(path1); path.extend_from_slice(path2); path.into_boxed_slice() } prost-reflect-0.15.0/src/descriptor/build/names.rs000064400000000000000000000316721046102023000202260ustar 00000000000000use std::collections::{hash_map, BTreeMap, HashMap, HashSet}; use crate::{ descriptor::{ build::{ join_path, options::option_to_bool, visit::{visit, Visitor}, DescriptorPoolOffsets, }, error::{DescriptorError, DescriptorErrorKind, Label}, tag, to_index, types::{ DescriptorProto, EnumDescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto, FileDescriptorProto, MethodDescriptorProto, OneofDescriptorProto, ServiceDescriptorProto, }, Definition, DefinitionKind, DescriptorPoolInner, EnumDescriptorInner, EnumIndex, EnumValueDescriptorInner, EnumValueIndex, ExtensionIndex, FieldIndex, FileDescriptorInner, FileIndex, Identity, MessageDescriptorInner, MessageIndex, MethodIndex, OneofDescriptorInner, OneofIndex, ServiceIndex, }, Syntax, }; impl DescriptorPoolInner { pub(super) fn collect_names( &mut self, offsets: DescriptorPoolOffsets, files: &[FileDescriptorProto], ) -> Result<(), DescriptorError> { let mut visitor = NameVisitor { pool: self, errors: vec![], }; visit(offsets, files, &mut visitor); if visitor.errors.is_empty() { Ok(()) } else { Err(DescriptorError::new(visitor.errors)) } } } struct NameVisitor<'a> { pool: &'a mut DescriptorPoolInner, errors: Vec, } impl Visitor for NameVisitor<'_> { fn visit_file(&mut self, path: &[i32], index: FileIndex, file: &FileDescriptorProto) { debug_assert_eq!(to_index(self.pool.files.len()), index); let syntax = match file.syntax.as_deref() { None | Some("proto2") => Syntax::Proto2, Some("proto3") => Syntax::Proto3, Some(syntax) => { self.errors.push(DescriptorErrorKind::UnknownSyntax { syntax: syntax.to_owned(), found: Label::new( &self.pool.files, "found here", index, join_path(path, &[tag::file::SYNTAX]), ), }); return; } }; if self .pool .file_names .insert(file.name().into(), index) .is_some() { self.errors.push(DescriptorErrorKind::DuplicateFileName { name: file.name().to_owned(), }); } self.pool.files.push(FileDescriptorInner { syntax, raw: file.clone(), prost: Default::default(), // the prost descriptor is initialized from the internal descriptor once resolution is complete, to avoid needing to duplicate all modifications dependencies: Vec::with_capacity(file.dependency.len()), transitive_dependencies: HashSet::default(), }); if !file.package().is_empty() { for (i, _) in file.package().match_indices('.') { self.add_name( index, &file.package()[..i], path, &[tag::file::PACKAGE], DefinitionKind::Package, ); } self.add_name( index, file.package(), path, &[tag::file::PACKAGE], DefinitionKind::Package, ); } } fn visit_message( &mut self, path: &[i32], full_name: &str, file: FileIndex, parent: Option, index: MessageIndex, message: &DescriptorProto, ) { self.add_name( file, full_name, path, &[tag::message::NAME], DefinitionKind::Message(index), ); debug_assert_eq!(to_index(self.pool.messages.len()), index); self.pool.messages.push(MessageDescriptorInner { id: Identity::new(file, path, full_name, message.name()), fields: Vec::with_capacity(message.field.len()), field_numbers: BTreeMap::new(), field_names: HashMap::with_capacity(message.field.len()), field_json_names: HashMap::with_capacity(message.field.len()), oneofs: Vec::with_capacity(message.oneof_decl.len()), extensions: Vec::new(), parent, }); if self.pool.files[file as usize].syntax != Syntax::Proto2 { self.check_message_field_camel_case_names(file, path, message); } } fn visit_field( &mut self, path: &[i32], full_name: &str, file: FileIndex, message: MessageIndex, _: FieldIndex, _: &FieldDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::field::NAME], DefinitionKind::Field(message), ); } fn visit_oneof( &mut self, path: &[i32], full_name: &str, file: FileIndex, message: MessageIndex, index: OneofIndex, oneof: &OneofDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::oneof::NAME], DefinitionKind::Oneof(message), ); debug_assert_eq!( to_index(self.pool.messages[message as usize].oneofs.len()), index ); self.pool.messages[message as usize] .oneofs .push(OneofDescriptorInner { id: Identity::new(file, path, full_name, oneof.name()), fields: Vec::new(), }); } fn visit_service( &mut self, path: &[i32], full_name: &str, file: FileIndex, index: ServiceIndex, _: &ServiceDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::service::NAME], DefinitionKind::Service(index), ); } fn visit_method( &mut self, path: &[i32], full_name: &str, file: FileIndex, service: ServiceIndex, _: MethodIndex, _: &MethodDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::service::NAME], DefinitionKind::Method(service), ); } fn visit_enum( &mut self, path: &[i32], full_name: &str, file: FileIndex, parent: Option, index: EnumIndex, enum_: &EnumDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::enum_::NAME], DefinitionKind::Enum(index), ); if enum_.value.is_empty() { self.errors.push(DescriptorErrorKind::EmptyEnum { found: Label::new(&self.pool.files, "enum defined here", file, path.into()), }); } else if self.pool.files[file as usize].syntax != Syntax::Proto2 && enum_.value[0].number() != 0 { self.errors .push(DescriptorErrorKind::InvalidProto3EnumDefault { found: Label::new( &self.pool.files, "defined here", file, join_path(path, &[tag::enum_::VALUE, 0, tag::enum_value::NUMBER]), ), }); } let allow_alias = enum_.options.as_ref().is_some_and(|o| { o.value.allow_alias() || o.value.uninterpreted_option.iter().any(|u| { u.name.len() == 1 && u.name[0].name_part == "allow_alias" && !u.name[0].is_extension && option_to_bool(u).unwrap_or(false) }) }); debug_assert_eq!(to_index(self.pool.enums.len()), index); self.pool.enums.push(EnumDescriptorInner { id: Identity::new(file, path, full_name, enum_.name()), parent, values: Vec::with_capacity(enum_.value.len()), value_numbers: Vec::with_capacity(enum_.value.len()), value_names: HashMap::with_capacity(enum_.value.len()), allow_alias, }); } fn visit_enum_value( &mut self, path: &[i32], full_name: &str, file: FileIndex, enum_: EnumIndex, index: EnumValueIndex, value: &EnumValueDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::enum_value::NAME], DefinitionKind::EnumValue(enum_), ); debug_assert_eq!( to_index(self.pool.enums[enum_ as usize].values.len()), index ); self.pool.enums[enum_ as usize] .values .push(EnumValueDescriptorInner { id: Identity::new(file, path, full_name, value.name()), number: value.number(), }); } fn visit_extension( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: Option, index: ExtensionIndex, _: &FieldDescriptorProto, ) { self.add_name( file, full_name, path, &[tag::field::NAME], DefinitionKind::Extension(index), ); } } impl NameVisitor<'_> { fn add_name( &mut self, file: FileIndex, name: &str, path1: &[i32], path2: &[i32], kind: DefinitionKind, ) { let path = join_path(path1, path2); match self.pool.names.entry(name.into()) { hash_map::Entry::Vacant(entry) => { entry.insert(Definition { file, kind, path }); } hash_map::Entry::Occupied(_) => { let entry = &self.pool.names[name]; if matches!(kind, DefinitionKind::Package) && matches!(entry.kind, DefinitionKind::Package) { return; } self.errors.push(DescriptorErrorKind::DuplicateName { name: name.to_owned(), first: Label::new( &self.pool.files, "first defined here", entry.file, entry.path.clone(), ), second: Label::new(&self.pool.files, "defined again here", file, path), }) } } } fn check_message_field_camel_case_names( &mut self, file: FileIndex, path: &[i32], message: &DescriptorProto, ) { let mut names: HashMap = HashMap::new(); for (index, field) in message.field.iter().enumerate() { let name = field.name(); let index = index as i32; match names.entry(to_lower_without_underscores(name)) { hash_map::Entry::Occupied(entry) => { self.errors .push(DescriptorErrorKind::DuplicateFieldCamelCaseName { first_name: entry.get().0.to_owned(), first: Label::new( &self.pool.files, "first defined here", file, join_path( path, &[tag::message::FIELD, entry.get().1, tag::field::NAME], ), ), second_name: name.to_owned(), second: Label::new( &self.pool.files, "defined again here", file, join_path(path, &[tag::message::FIELD, index, tag::field::NAME]), ), }) } hash_map::Entry::Vacant(entry) => { entry.insert((name, index)); } } } } } fn to_lower_without_underscores(name: &str) -> String { name.chars() .filter_map(|ch| match ch { '_' => None, _ => Some(ch.to_ascii_lowercase()), }) .collect() } prost-reflect-0.15.0/src/descriptor/build/options.rs000064400000000000000000000703511046102023000206130ustar 00000000000000use std::sync::Arc; use prost::{bytes::Bytes, Message}; use crate::{ descriptor::{ build::{ join_path, resolve_name, visit::{visit, Visitor}, DescriptorPoolOffsets, ResolveNameFilter, }, error::{DescriptorErrorKind, Label}, tag, types::{ uninterpreted_option, DescriptorProto, EnumDescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto, FileDescriptorProto, MethodDescriptorProto, OneofDescriptorProto, Options, ServiceDescriptorProto, UninterpretedOption, }, Definition, DefinitionKind, EnumIndex, EnumValueIndex, ExtensionIndex, FieldIndex, FileIndex, MessageIndex, MethodIndex, OneofIndex, ServiceIndex, MAP_ENTRY_KEY_NUMBER, MAP_ENTRY_VALUE_NUMBER, }, dynamic::{fmt_string, FieldDescriptorLike}, Cardinality, DescriptorError, DescriptorPool, DynamicMessage, EnumDescriptor, ExtensionDescriptor, MapKey, MessageDescriptor, ReflectMessage, Value, }; impl DescriptorPool { pub(super) fn resolve_options( &mut self, offsets: DescriptorPoolOffsets, files: &[FileDescriptorProto], ) -> Result<(), DescriptorError> { debug_assert_eq!(Arc::strong_count(&self.inner), 1); let mut visitor = OptionsVisitor { pool: self, errors: Vec::new(), options: Vec::new(), locations: Vec::new(), }; visit(offsets, files, &mut visitor); if !visitor.errors.is_empty() { return Err(DescriptorError::new(visitor.errors)); } debug_assert_eq!(Arc::strong_count(&visitor.pool.inner), 1); let inner = Arc::get_mut(&mut visitor.pool.inner).unwrap(); for (file, path, encoded) in visitor.options { let file = &mut inner.files[file as usize].raw; set_file_option(file, &path, &encoded); } for (file, from, to) in visitor.locations { let file = &mut inner.files[file as usize].raw; if let Some(source_code_info) = &mut file.source_code_info { for location in &mut source_code_info.location { if location.path.starts_with(&from) { location.path.splice(..from.len(), to.iter().copied()); } } } } Ok(()) } } struct OptionsVisitor<'a> { pool: &'a mut DescriptorPool, errors: Vec, options: Vec<(FileIndex, Box<[i32]>, Vec)>, #[allow(clippy::type_complexity)] locations: Vec<(FileIndex, Box<[i32]>, Box<[i32]>)>, } impl Visitor for OptionsVisitor<'_> { fn visit_file(&mut self, path: &[i32], index: FileIndex, file: &FileDescriptorProto) { if let Some(options) = &file.options { let path = join_path(path, &[tag::file::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.FileOptions", options, &options.value.uninterpreted_option, file.package(), index, &path, ); self.options.push((index, path, encoded)); } } fn visit_message( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: Option, _: MessageIndex, message: &DescriptorProto, ) { if let Some(options) = &message.options { let path = join_path(path, &[tag::message::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.MessageOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } for (i, extension_range) in message.extension_range.iter().enumerate() { let path = join_path( path, &[ tag::message::EXTENSION_RANGE, i as i32, tag::message::extension_range::OPTIONS, ], ); if let Some(options) = &extension_range.options { let encoded = self.resolve_options( "google.protobuf.ExtensionRangeOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } } fn visit_field( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: MessageIndex, _: FieldIndex, field: &FieldDescriptorProto, ) { if let Some(options) = &field.options { let path = join_path(path, &[tag::field::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.FieldOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } fn visit_oneof( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: MessageIndex, _: OneofIndex, oneof: &OneofDescriptorProto, ) { if let Some(options) = &oneof.options { let path = join_path(path, &[tag::oneof::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.OneofOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } fn visit_service( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: ServiceIndex, service: &ServiceDescriptorProto, ) { if let Some(options) = &service.options { let path = join_path(path, &[tag::service::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.ServiceOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } fn visit_method( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: ServiceIndex, _: MethodIndex, method: &MethodDescriptorProto, ) { if let Some(options) = &method.options { let path = join_path(path, &[tag::method::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.MethodOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } fn visit_enum( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: Option, _: EnumIndex, enum_: &EnumDescriptorProto, ) { if let Some(options) = &enum_.options { let path = join_path(path, &[tag::enum_::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.EnumOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } fn visit_enum_value( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: EnumIndex, _: EnumValueIndex, value: &EnumValueDescriptorProto, ) { if let Some(options) = &value.options { let path = join_path(path, &[tag::enum_value::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.EnumValueOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } fn visit_extension( &mut self, path: &[i32], full_name: &str, file: FileIndex, _: Option, _: ExtensionIndex, extension: &FieldDescriptorProto, ) { if let Some(options) = &extension.options { let path = join_path(path, &[tag::field::OPTIONS]); let encoded = self.resolve_options( "google.protobuf.FieldOptions", options, &options.value.uninterpreted_option, full_name, file, &path, ); self.options.push((file, path, encoded)); } } } impl OptionsVisitor<'_> { fn resolve_options( &mut self, desc_name: &str, options: &Options, uninterpreted: &[UninterpretedOption], scope: &str, file: FileIndex, path: &[i32], ) -> Vec { let desc = self.pool.get_message_by_name(desc_name).unwrap_or_else(|| { DescriptorPool::global() .get_message_by_name(desc_name) .unwrap() }); let mut message = match DynamicMessage::decode(desc, options.encoded.as_slice()) { Ok(message) => message, Err(err) => { self.errors .push(DescriptorErrorKind::DecodeFileDescriptorSet { err }); return Vec::new(); } }; for (i, option) in uninterpreted.iter().enumerate() { if let Err(err) = self.set_option( &mut message, option, scope, file, join_path(path, &[tag::UNINTERPRETED_OPTION, i as i32]), ) { self.errors.push(err); } } message.clear_field_by_number(tag::UNINTERPRETED_OPTION as u32); message.encode_to_vec() } #[allow(clippy::result_large_err)] fn set_option( &mut self, mut message: &mut DynamicMessage, option: &UninterpretedOption, scope: &str, file: FileIndex, path: Box<[i32]>, ) -> Result<(), DescriptorErrorKind> { let mut resolved_path = Vec::with_capacity(path.len() - 2 + option.name.len()); resolved_path.extend_from_slice(&path[..path.len() - 2]); for (i, part) in option.name.iter().enumerate() { let is_last = i == option.name.len() - 1; let desc = message.descriptor(); if part.is_extension { let extension_desc = self.find_extension(scope, &part.name_part, file, &path, &desc)?; resolved_path.push(extension_desc.number() as i32); if is_last { if extension_desc.cardinality() != Cardinality::Repeated && message.has_extension(&extension_desc) { return Err(DescriptorErrorKind::DuplicateOption { name: fmt_option_name(&option.name), found: Label::new(&self.pool.inner.files, "found here", file, path), }); } else { self.set_field_value( message.get_extension_mut(&extension_desc), &mut resolved_path, &extension_desc, option, file, &path, )?; } } else if let Value::Message(submessage) = message.get_extension_mut(&extension_desc) { message = submessage; } else { return Err(DescriptorErrorKind::InvalidOptionType { name: fmt_option_name(&option.name[..i + 1]), ty: fmt_field_ty(&extension_desc), value: fmt_value(option), is_last, found: Label::new(&self.pool.inner.files, "found here", file, path), }); } } else { match desc.get_field_by_name(&part.name_part) { Some(field_desc) => { resolved_path.push(field_desc.number() as i32); if is_last { if field_desc.cardinality() != Cardinality::Repeated && message.has_field(&field_desc) { return Err(DescriptorErrorKind::DuplicateOption { name: fmt_option_name(&option.name), found: Label::new( &self.pool.inner.files, "found here", file, path, ), }); } else { self.set_field_value( message.get_field_mut(&field_desc), &mut resolved_path, &field_desc, option, file, &path, )?; } } else if let Value::Message(submessage) = message.get_field_mut(&field_desc) { message = submessage; } else { return Err(DescriptorErrorKind::InvalidOptionType { name: fmt_option_name(&option.name[..i + 1]), ty: fmt_field_ty(&field_desc), value: fmt_value(option), is_last, found: Label::new(&self.pool.inner.files, "found here", file, path), }); } } None => { return Err(DescriptorErrorKind::OptionNotFound { name: fmt_option_name(&option.name[..i + 1]), found: Label::new(&self.pool.inner.files, "found here", file, path), }) } } } } self.locations.push((file, path, resolved_path.into())); Ok(()) } #[allow(clippy::result_large_err)] fn set_field_value( &self, value: &mut Value, resolved_path: &mut Vec, desc: &impl FieldDescriptorLike, option: &UninterpretedOption, file: FileIndex, path: &[i32], ) -> Result<(), DescriptorErrorKind> { let err = |()| DescriptorErrorKind::InvalidOptionType { name: fmt_option_name(&option.name), ty: fmt_field_ty(desc), value: fmt_value(option), is_last: true, found: Label::new(&self.pool.inner.files, "found here", file, path.into()), }; let parse_err = |parse_err| match parse_err { #[cfg(feature = "text-format")] Some(parse_err) => DescriptorErrorKind::InvalidMessageOption { name: fmt_option_name(&option.name), ty: fmt_field_ty(desc), found: Label::new(&self.pool.inner.files, "found here", file, path.into()), err: parse_err, }, _ => err(()), }; match value { Value::Bool(value) => *value = option_to_bool(option).map_err(err)?, Value::I32(value) => *value = option_to_int(option).map_err(err)?, Value::I64(value) => *value = option_to_int(option).map_err(err)?, Value::U32(value) => *value = option_to_int(option).map_err(err)?, Value::U64(value) => *value = option_to_int(option).map_err(err)?, Value::F32(value) => *value = option_to_float(option).map_err(err)? as f32, Value::F64(value) => *value = option_to_float(option).map_err(err)?, Value::String(value) => *value = option_to_string(option).map_err(err)?, Value::Bytes(value) => *value = option_to_bytes(option).map_err(err)?, Value::EnumNumber(value) => { *value = option_to_enum(option, desc.kind().as_enum().unwrap()).map_err(err)? } Value::Message(value) => { *value = option_to_message(option, desc.kind().as_message().unwrap()) .map_err(parse_err)? } Value::List(value) => { resolved_path.push(value.len() as i32); let mut entry = Value::default_value(&desc.kind()); self.set_field_value(&mut entry, resolved_path, desc, option, file, path)?; value.push(entry); } Value::Map(value) => { let (entry_key, entry_value) = option_to_map_entry(option, desc.kind().as_message().unwrap()) .map_err(parse_err)?; value.insert(entry_key, entry_value); } } Ok(()) } #[allow(clippy::result_large_err)] fn find_extension( &self, scope: &str, name: &str, file: FileIndex, path: &[i32], extendee: &MessageDescriptor, ) -> Result { let (_, def) = resolve_name( &self.pool.inner.files[file as usize].transitive_dependencies, &self.pool.inner.names, scope, name, ResolveNameFilter::Extension, ) .into_result(name, &self.pool.inner.files, file, path, &[])?; let &Definition { kind: DefinitionKind::Extension(index), .. } = def else { unreachable!() }; let desc = ExtensionDescriptor { pool: self.pool.clone(), index, }; if desc.containing_message() == *extendee { Ok(desc) } else { Err(DescriptorErrorKind::InvalidOptionExtendee { name: desc.full_name().to_owned(), expected_extendee: extendee.full_name().to_owned(), actual_extendee: desc.containing_message().full_name().to_owned(), found: Label::new(&self.pool.inner.files, "found here", file, path.into()), }) } } } fn fmt_option_name(parts: &[uninterpreted_option::NamePart]) -> String { let mut result = String::new(); for part in parts { if !result.is_empty() { result.push('.'); } if part.is_extension { result.push('('); result.push_str(&part.name_part); result.push(')'); } else { result.push_str(&part.name_part); } } result } pub(super) fn option_to_bool(option: &UninterpretedOption) -> Result { match option.identifier_value.as_deref() { Some("true") => Ok(true), Some("false") => Ok(false), _ => Err(()), } } pub(super) fn option_to_int(option: &UninterpretedOption) -> Result where T: TryFrom + TryFrom, { if let Some(int) = option.positive_int_value { int.try_into().map_err(drop) } else if let Some(int) = option.negative_int_value { int.try_into().map_err(drop) } else { Err(()) } } pub(super) fn option_to_float(option: &UninterpretedOption) -> Result { if let Some(float) = option.double_value { Ok(float) } else if let Some(int) = option.positive_int_value { Ok(int as f64) } else if let Some(int) = option.negative_int_value { Ok(int as f64) } else { Err(()) } } pub(super) fn option_to_string(option: &UninterpretedOption) -> Result { if let Some(bytes) = &option.string_value { String::from_utf8(bytes.clone()).map_err(drop) } else { Err(()) } } pub(super) fn option_to_bytes(option: &UninterpretedOption) -> Result { if let Some(bytes) = &option.string_value { Ok(Bytes::copy_from_slice(bytes)) } else { Err(()) } } pub(super) fn option_to_enum( option: &UninterpretedOption, desc: &EnumDescriptor, ) -> Result { if let Some(ident) = &option.identifier_value { if let Some(value) = desc.get_value_by_name(ident) { Ok(value.number()) } else { Err(()) } } else { Err(()) } } #[cfg(feature = "text-format")] type ParseError = crate::text_format::ParseError; #[cfg(not(feature = "text-format"))] type ParseError = (); #[cfg(feature = "text-format")] pub(super) fn option_to_message( option: &UninterpretedOption, desc: &MessageDescriptor, ) -> Result> { if let Some(text_format) = &option.aggregate_value { DynamicMessage::parse_text_format(desc.clone(), text_format).map_err(Some) } else { Err(None) } } #[cfg(not(feature = "text-format"))] pub(super) fn option_to_message( option: &UninterpretedOption, desc: &MessageDescriptor, ) -> Result> { if option.aggregate_value.is_some() { Ok(DynamicMessage::new(desc.clone())) } else { Err(None) } } pub(super) fn option_to_map_entry( option: &UninterpretedOption, desc: &MessageDescriptor, ) -> Result<(MapKey, Value), Option> { debug_assert!(desc.is_map_entry()); let entry = option_to_message(option, desc)?; let key = entry .get_field_by_number(MAP_ENTRY_KEY_NUMBER) .ok_or(None)? .into_owned() .into_map_key() .ok_or(None)?; let value = entry .get_field_by_number(MAP_ENTRY_VALUE_NUMBER) .ok_or(None)? .into_owned(); Ok((key, value)) } fn fmt_field_ty(field: &impl FieldDescriptorLike) -> String { if field.is_map() { let entry = field.kind(); let entry = entry.as_message().unwrap(); format!( "map<{:?}, {:?}>", entry.map_entry_key_field().kind(), entry.map_entry_value_field().kind() ) } else if field.is_list() { format!("repeated {:?}", field.kind()) } else { format!("{:?}", field.kind()) } } fn fmt_value(option: &UninterpretedOption) -> String { if let Some(value) = &option.identifier_value { value.clone() } else if let Some(value) = &option.positive_int_value { value.to_string() } else if let Some(value) = &option.negative_int_value { value.to_string() } else if let Some(value) = &option.double_value { value.to_string() } else if let Some(value) = &option.string_value { let mut string = String::new(); fmt_string(&mut string, value).unwrap(); string } else if let Some(value) = &option.aggregate_value { value.clone() } else { String::new() } } fn set_file_option(file: &mut FileDescriptorProto, path: &[i32], encoded: &[u8]) { match path[0] { tag::file::OPTIONS => { debug_assert_eq!(path.len(), 1); file.options = Some(Options::decode(encoded).unwrap()); } tag::file::MESSAGE_TYPE => { let message = &mut file.message_type[path[1] as usize]; set_message_option(message, &path[2..], encoded); } tag::file::ENUM_TYPE => { let enum_ = &mut file.enum_type[path[1] as usize]; set_enum_option(enum_, &path[2..], encoded); } tag::file::SERVICE => { let service = &mut file.service[path[1] as usize]; match path[2] { tag::service::OPTIONS => service.options = Some(Options::decode(encoded).unwrap()), tag::service::METHOD => { debug_assert_eq!(path.len(), 5); debug_assert_eq!(path[4], tag::method::OPTIONS); let value = &mut service.method[path[3] as usize]; value.options = Some(Options::decode(encoded).unwrap()); } p => panic!("unknown path element {}", p), } } tag::file::EXTENSION => { debug_assert_eq!(path.len(), 3); debug_assert_eq!(path[2], tag::field::OPTIONS); let field = &mut file.extension[path[1] as usize]; field.options = Some(Options::decode(encoded).unwrap()); } p => panic!("unknown path element {}", p), } } fn set_message_option(message: &mut DescriptorProto, path: &[i32], encoded: &[u8]) { match path[0] { tag::message::OPTIONS => { debug_assert_eq!(path.len(), 1); message.options = Some(Options::decode(encoded).unwrap()); } tag::message::EXTENSION_RANGE => { debug_assert_eq!(path.len(), 3); debug_assert_eq!(path[2], tag::message::extension_range::OPTIONS); let extension_range = &mut message.extension_range[path[1] as usize]; extension_range.options = Some(Options::decode(encoded).unwrap()); } tag::message::FIELD => { debug_assert_eq!(path.len(), 3); debug_assert_eq!(path[2], tag::field::OPTIONS); let field = &mut message.field[path[1] as usize]; field.options = Some(Options::decode(encoded).unwrap()); } tag::message::ONEOF_DECL => { debug_assert_eq!(path.len(), 3); debug_assert_eq!(path[2], tag::oneof::OPTIONS); let field = &mut message.oneof_decl[path[1] as usize]; field.options = Some(Options::decode(encoded).unwrap()); } tag::message::NESTED_TYPE => { let nested_message = &mut message.nested_type[path[1] as usize]; set_message_option(nested_message, &path[2..], encoded); } tag::message::ENUM_TYPE => { let enum_ = &mut message.enum_type[path[1] as usize]; set_enum_option(enum_, &path[2..], encoded); } tag::message::EXTENSION => { debug_assert_eq!(path.len(), 3); debug_assert_eq!(path[2], tag::field::OPTIONS); let field = &mut message.extension[path[1] as usize]; field.options = Some(Options::decode(encoded).unwrap()); } p => panic!("unknown path element {}", p), } } fn set_enum_option(enum_: &mut EnumDescriptorProto, path: &[i32], encoded: &[u8]) { match path[0] { tag::enum_::OPTIONS => enum_.options = Some(Options::decode(encoded).unwrap()), tag::enum_::VALUE => { debug_assert_eq!(path.len(), 3); debug_assert_eq!(path[2], tag::enum_value::OPTIONS); let value = &mut enum_.value[path[1] as usize]; value.options = Some(Options::decode(encoded).unwrap()); } p => panic!("unknown path element {}", p), } } prost-reflect-0.15.0/src/descriptor/build/resolve.rs000064400000000000000000001074721046102023000206040ustar 00000000000000use std::collections::HashSet; use prost::bytes::Bytes; use crate::{ descriptor::{ build::{ join_path, resolve_name, to_json_name, visit::{visit, Visitor}, DescriptorPoolOffsets, ResolveNameFilter, }, error::{DescriptorError, DescriptorErrorKind, Label}, find_enum_proto, find_message_proto, tag, to_index, types::{ field_descriptor_proto, DescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto, FileDescriptorProto, MethodDescriptorProto, ServiceDescriptorProto, }, Definition, DefinitionKind, DescriptorPoolInner, EnumIndex, EnumValueIndex, ExtensionDescriptorInner, ExtensionIndex, FieldDescriptorInner, FieldIndex, FileIndex, Identity, KindIndex, MessageIndex, MethodDescriptorInner, MethodIndex, OneofIndex, ServiceDescriptorInner, ServiceIndex, RESERVED_MESSAGE_FIELD_NUMBERS, VALID_MESSAGE_FIELD_NUMBERS, }, Cardinality, Syntax, Value, }; impl DescriptorPoolInner { pub(super) fn resolve_names( &mut self, offsets: DescriptorPoolOffsets, files: &[FileDescriptorProto], ) -> Result<(), DescriptorError> { let mut visitor = ResolveVisitor { pool: self, errors: vec![], }; visit(offsets, files, &mut visitor); if visitor.errors.is_empty() { Ok(()) } else { Err(DescriptorError::new(visitor.errors)) } } } struct ResolveVisitor<'a> { pool: &'a mut DescriptorPoolInner, errors: Vec, } impl Visitor for ResolveVisitor<'_> { fn visit_file(&mut self, path: &[i32], index: FileIndex, file: &FileDescriptorProto) { let mut transitive_dependencies = HashSet::with_capacity(file.dependency.len() + 1); transitive_dependencies.insert(index); for (i, dependency) in file.dependency.iter().enumerate() { if let Some(&dependency_index) = self.pool.file_names.get(dependency.as_str()) { self.pool.files[index as usize] .dependencies .push(dependency_index); transitive_dependencies.insert(dependency_index); self.resolve_public_dependencies(&mut transitive_dependencies, dependency_index); } else { self.errors.push(DescriptorErrorKind::FileNotFound { name: dependency.clone(), found: Label::new( &self.pool.files, "found here", index, join_path(path, &[tag::file::DEPENDENCY, i as i32]), ), }); } } self.pool.files[index as usize].transitive_dependencies = transitive_dependencies; for &public_dependency in &file.public_dependency { if !matches!(usize::try_from(public_dependency), Ok(i) if i < file.dependency.len()) { self.errors.push(DescriptorErrorKind::InvalidImportIndex); } } for &weak_dependency in &file.weak_dependency { if !matches!(usize::try_from(weak_dependency), Ok(i) if i < file.dependency.len()) { self.errors.push(DescriptorErrorKind::InvalidImportIndex); } } } fn visit_field( &mut self, path: &[i32], full_name: &str, file: FileIndex, message: MessageIndex, index: FieldIndex, field: &FieldDescriptorProto, ) { debug_assert_eq!( to_index(self.pool.messages[message as usize].fields.len()), index ); let syntax = self.pool.files[file as usize].syntax; self.check_field_number(message, field, file, path); let cardinality = match field.label() { field_descriptor_proto::Label::Optional => Cardinality::Optional, field_descriptor_proto::Label::Required => Cardinality::Required, field_descriptor_proto::Label::Repeated => Cardinality::Repeated, }; let kind = self.resolve_field_type(field.r#type(), field.type_name(), full_name, file, path); let json_name: Box = self.resolve_field_json_name(field, file, path).into(); let is_packed = cardinality == Cardinality::Repeated && kind.is_some_and(|k| k.is_packable()) && (field .options .as_ref() .map_or(syntax == Syntax::Proto3, |o| o.value.packed())); let supports_presence = field.proto3_optional() || field.oneof_index.is_some() || (cardinality != Cardinality::Repeated && (kind.is_some_and(|k| k.is_message()) || syntax == Syntax::Proto2)); let default = kind.and_then(|kind| { self.parse_field_default_value(kind, field.default_value.as_deref(), file, path) }); let message = &mut self.pool.messages[message as usize]; let oneof = field.oneof_index.and_then(|oneof_index| { if oneof_index < 0 || oneof_index as usize >= message.oneofs.len() { self.errors.push(DescriptorErrorKind::InvalidOneofIndex); None } else { message.oneofs[oneof_index as usize].fields.push(index); Some(oneof_index as OneofIndex) } }); message.fields.push(FieldDescriptorInner { id: Identity::new(file, path, full_name, field.name()), number: field.number() as u32, kind: kind.unwrap_or(KindIndex::Double), oneof, is_packed, supports_presence, json_name: json_name.clone(), cardinality, default, }); if let Some(existing) = message.field_numbers.insert(field.number() as u32, index) { self.errors.push(DescriptorErrorKind::DuplicateFieldNumber { number: field.number() as u32, first: Label::new( &self.pool.files, "first defined here", file, join_path( &message.fields[existing as usize].id.path, &[tag::field::NUMBER], ), ), second: Label::new( &self.pool.files, "defined again here", file, join_path(path, &[tag::field::NUMBER]), ), }); } if let Some(existing) = message.field_names.insert(field.name().into(), index) { self.errors.push(DescriptorErrorKind::DuplicateName { name: full_name.to_owned(), first: Label::new( &self.pool.files, "first defined here", file, join_path( &message.fields[existing as usize].id.path, &[tag::field::NAME], ), ), second: Label::new( &self.pool.files, "defined again here", file, join_path(path, &[tag::field::NAME]), ), }); } if let Some(existing) = message.field_json_names.insert(json_name, index) { self.errors .push(DescriptorErrorKind::DuplicateFieldJsonName { name: field.json_name().to_owned(), first: Label::new( &self.pool.files, "first defined here", file, join_path( &message.fields[existing as usize].id.path, &[tag::field::NAME], ), ), second: Label::new( &self.pool.files, "defined again here", file, join_path(path, &[tag::field::NAME]), ), }); } } fn visit_service( &mut self, path: &[i32], full_name: &str, file: FileIndex, index: ServiceIndex, service: &ServiceDescriptorProto, ) { debug_assert_eq!(to_index(self.pool.services.len()), index); self.pool.services.push(ServiceDescriptorInner { id: Identity::new(file, path, full_name, service.name()), methods: Vec::with_capacity(service.method.len()), }); } fn visit_method( &mut self, path: &[i32], full_name: &str, file: FileIndex, service: ServiceIndex, index: MethodIndex, method: &MethodDescriptorProto, ) { debug_assert_eq!( to_index(self.pool.services[service as usize].methods.len()), index ); let input = self .find_message( full_name, method.input_type(), file, path, tag::method::INPUT_TYPE, ) .unwrap_or(MessageIndex::MAX); let output = self .find_message( full_name, method.output_type(), file, path, tag::method::OUTPUT_TYPE, ) .unwrap_or(MessageIndex::MAX); self.pool.services[service as usize] .methods .push(MethodDescriptorInner { id: Identity::new(file, path, full_name, method.name()), input, output, }); } fn visit_enum_value( &mut self, path: &[i32], full_name: &str, file: FileIndex, enum_index: EnumIndex, index: EnumValueIndex, value: &EnumValueDescriptorProto, ) { self.check_enum_number(enum_index, value, file, path); let enum_ = &mut self.pool.enums[enum_index as usize]; let value_numbers_index = match enum_ .value_numbers .binary_search_by(|(number, _)| number.cmp(&value.number())) { Ok(existing_index) => { if !enum_.allow_alias { let existing = enum_.value_numbers[existing_index].1; self.errors.push(DescriptorErrorKind::DuplicateEnumNumber { number: value.number(), first: Label::new( &self.pool.files, "first defined here", file, join_path( &enum_.values[existing as usize].id.path, &[tag::enum_value::NUMBER], ), ), second: Label::new( &self.pool.files, "defined again here", file, join_path(path, &[tag::enum_value::NUMBER]), ), }); } existing_index } Err(index) => index, }; enum_ .value_numbers .insert(value_numbers_index, (value.number(), index)); if let Some(existing) = enum_.value_names.insert(value.name().into(), index) { self.errors.push(DescriptorErrorKind::DuplicateName { name: full_name.to_owned(), first: Label::new( &self.pool.files, "first defined here", file, join_path( &enum_.values[existing as usize].id.path, &[tag::enum_value::NAME], ), ), second: Label::new( &self.pool.files, "defined again here", file, join_path(path, &[tag::enum_value::NAME]), ), }); } } fn visit_extension( &mut self, path: &[i32], full_name: &str, file: FileIndex, parent_message: Option, index: ExtensionIndex, extension: &FieldDescriptorProto, ) { debug_assert_eq!(to_index(self.pool.extensions.len()), index); let extendee = self.find_message( full_name, extension.extendee(), file, path, tag::field::EXTENDEE, ); if let Some(extendee) = extendee { self.pool.messages[extendee as usize].extensions.push(index); self.check_field_number(extendee, extension, file, path); } let syntax = self.pool.files[file as usize].syntax; let cardinality = match extension.label() { field_descriptor_proto::Label::Optional => Cardinality::Optional, field_descriptor_proto::Label::Required => Cardinality::Required, field_descriptor_proto::Label::Repeated => Cardinality::Repeated, }; let kind = self.resolve_field_type( extension.r#type(), extension.type_name(), full_name, file, path, ); self.resolve_field_json_name(extension, file, path); let is_packed = cardinality == Cardinality::Repeated && kind.is_some_and(|k| k.is_packable()) && (extension .options .as_ref() .map_or(syntax == Syntax::Proto3, |o| o.value.packed())); let default = kind.and_then(|kind| { self.parse_field_default_value(kind, extension.default_value.as_deref(), file, path) }); self.pool.extensions.push(ExtensionDescriptorInner { id: Identity::new(file, path, full_name, extension.name()), parent: parent_message, number: extension.number() as u32, json_name: format!("[{}]", full_name).into(), extendee: extendee.unwrap_or(MessageIndex::MAX), kind: kind.unwrap_or(KindIndex::Double), is_packed, cardinality, default, }); } } impl ResolveVisitor<'_> { fn resolve_public_dependencies(&self, dependencies: &mut HashSet, index: FileIndex) { let file = &self.pool.files[index as usize]; for (i, dependency) in file.raw.dependency.iter().enumerate() { if let Some(&dependency_index) = self.pool.file_names.get(dependency.as_str()) { if file.raw.public_dependency.contains(&(i as i32)) && !dependencies.insert(dependency_index) { self.resolve_public_dependencies(dependencies, dependency_index); } } } } fn check_field_number( &mut self, message: MessageIndex, field: &FieldDescriptorProto, file: FileIndex, path: &[i32], ) { if !VALID_MESSAGE_FIELD_NUMBERS.contains(&field.number()) || RESERVED_MESSAGE_FIELD_NUMBERS.contains(&field.number()) { self.errors.push(DescriptorErrorKind::InvalidFieldNumber { number: field.number(), found: Label::new( &self.pool.files, "defined here", file, join_path(path, &[tag::field::NUMBER]), ), }); } let message = &self.pool.messages[message as usize]; let message_proto = find_message_proto( &self.pool.files[message.id.file as usize].raw, &message.id.path, ); for (i, range) in message_proto.reserved_range.iter().enumerate() { if range.start() <= field.number() && field.number() < range.end() { self.errors .push(DescriptorErrorKind::FieldNumberInReservedRange { number: field.number(), range: range.start()..range.end(), defined: Label::new( &self.pool.files, "reserved range defined here", message.id.file, join_path(&message.id.path, &[tag::message::RESERVED_RANGE, i as i32]), ), found: Label::new( &self.pool.files, "defined here", file, join_path(path, &[tag::field::NUMBER]), ), }); } } let extension_range = message_proto .extension_range .iter() .enumerate() .find(|(_, range)| range.start() <= field.number() && field.number() < range.end()); match (&field.extendee, extension_range) { (None, None) | (Some(_), Some(_)) => (), (None, Some((i, range))) => { self.errors .push(DescriptorErrorKind::FieldNumberInExtensionRange { number: field.number(), range: range.start()..range.end(), defined: Label::new( &self.pool.files, "extension range defined here", message.id.file, join_path(&message.id.path, &[tag::message::EXTENSION_RANGE, i as i32]), ), found: Label::new( &self.pool.files, "defined here", file, join_path(path, &[tag::field::NUMBER]), ), }); } (Some(_), None) => { self.errors .push(DescriptorErrorKind::ExtensionNumberOutOfRange { number: field.number(), message: message.id.full_name().to_owned(), found: Label::new( &self.pool.files, "defined here", file, join_path(path, &[tag::field::NUMBER]), ), }); } } } fn check_enum_number( &mut self, enum_: EnumIndex, value: &EnumValueDescriptorProto, file: FileIndex, path: &[i32], ) { let enum_ = &self.pool.enums[enum_ as usize]; let enum_proto = find_enum_proto(&self.pool.files[enum_.id.file as usize].raw, &enum_.id.path); for (i, range) in enum_proto.reserved_range.iter().enumerate() { if range.start() <= value.number() && value.number() <= range.end() { self.errors .push(DescriptorErrorKind::EnumNumberInReservedRange { number: value.number(), range: range.start()..=range.end(), defined: Label::new( &self.pool.files, "reserved range defined here", enum_.id.file, join_path(&enum_.id.path, &[tag::enum_::RESERVED_RANGE, i as i32]), ), found: Label::new( &self.pool.files, "defined here", file, join_path(path, &[tag::field::NUMBER]), ), }); } } } fn resolve_field_json_name<'b>( &'b mut self, field: &'b FieldDescriptorProto, file: FileIndex, path: &[i32], ) -> &'b str { if let Some(json_name) = &field.json_name { json_name } else { let field = find_file_field_proto_mut(&mut self.pool.files[file as usize].raw, path); field.json_name.insert(to_json_name(field.name())) } } fn resolve_field_type( &mut self, ty: field_descriptor_proto::Type, ty_name: &str, scope: &str, file: FileIndex, path: &[i32], ) -> Option { if ty_name.is_empty() { match ty { field_descriptor_proto::Type::Double => Some(KindIndex::Double), field_descriptor_proto::Type::Float => Some(KindIndex::Float), field_descriptor_proto::Type::Int64 => Some(KindIndex::Int64), field_descriptor_proto::Type::Uint64 => Some(KindIndex::Uint64), field_descriptor_proto::Type::Int32 => Some(KindIndex::Int32), field_descriptor_proto::Type::Fixed64 => Some(KindIndex::Fixed64), field_descriptor_proto::Type::Fixed32 => Some(KindIndex::Fixed32), field_descriptor_proto::Type::Bool => Some(KindIndex::Bool), field_descriptor_proto::Type::String => Some(KindIndex::String), field_descriptor_proto::Type::Bytes => Some(KindIndex::Bytes), field_descriptor_proto::Type::Uint32 => Some(KindIndex::Uint32), field_descriptor_proto::Type::Sfixed32 => Some(KindIndex::Sfixed32), field_descriptor_proto::Type::Sfixed64 => Some(KindIndex::Sfixed64), field_descriptor_proto::Type::Sint32 => Some(KindIndex::Sint32), field_descriptor_proto::Type::Sint64 => Some(KindIndex::Sint64), field_descriptor_proto::Type::Group | field_descriptor_proto::Type::Message | field_descriptor_proto::Type::Enum => { self.add_missing_required_field_error( file, join_path(path, &[tag::field::TYPE_NAME]), ); None } } } else { let def = self.resolve_name( scope, ty_name, file, path, tag::field::TYPE_NAME, ResolveNameFilter::FieldType, )?; match def.kind { DefinitionKind::Message(message) => { if ty == field_descriptor_proto::Type::Group { Some(KindIndex::Group(message)) } else { Some(KindIndex::Message(message)) } } DefinitionKind::Enum(enum_) => Some(KindIndex::Enum(enum_)), _ => unreachable!(), } } } fn parse_field_default_value( &mut self, kind: KindIndex, default_value: Option<&str>, file: FileIndex, path: &[i32], ) -> Option { let default_value = default_value?; match kind { KindIndex::Double | KindIndex::Float | KindIndex::Int32 | KindIndex::Int64 | KindIndex::Uint32 | KindIndex::Uint64 | KindIndex::Sint32 | KindIndex::Sint64 | KindIndex::Fixed32 | KindIndex::Fixed64 | KindIndex::Sfixed32 | KindIndex::Sfixed64 | KindIndex::Bool | KindIndex::String | KindIndex::Bytes => match parse_simple_value(kind, default_value) { Ok(value) => Some(value), Err(_) => { self.errors.push(DescriptorErrorKind::InvalidFieldDefault { value: default_value.to_owned(), kind: format!("{:?}", kind), found: Label::new( &self.pool.files, "found here", file, join_path(path, &[tag::field::DEFAULT_VALUE]), ), }); None } }, KindIndex::Enum(enum_) => { let enum_ = &self.pool.enums[enum_ as usize]; if let Some(value) = enum_.values.iter().find(|v| v.id.name() == default_value) { Some(Value::EnumNumber(value.number)) } else { self.errors.push(DescriptorErrorKind::InvalidFieldDefault { value: default_value.to_owned(), kind: enum_.id.full_name().to_owned(), found: Label::new( &self.pool.files, "found here", file, join_path(path, &[tag::field::DEFAULT_VALUE]), ), }); None } } _ => { self.errors.push(DescriptorErrorKind::InvalidFieldDefault { value: default_value.to_owned(), kind: "message type".to_owned(), found: Label::new( &self.pool.files, "found here", file, join_path(path, &[tag::field::DEFAULT_VALUE]), ), }); None } } } fn find_message( &mut self, scope: &str, name: &str, file: FileIndex, path1: &[i32], path2: i32, ) -> Option { let def = self.resolve_name(scope, name, file, path1, path2, ResolveNameFilter::Message)?; match def.kind { DefinitionKind::Message(message) => Some(message), _ => unreachable!(), } } fn resolve_name( &mut self, scope: &str, name: &str, file: FileIndex, path: &[i32], tag: i32, filter: ResolveNameFilter, ) -> Option<&Definition> { let (type_name, def) = match resolve_name( &self.pool.files[file as usize].transitive_dependencies, &self.pool.names, scope, name, filter, ) .into_result(name, &self.pool.files, file, path, &[tag]) { Ok((type_name, def)) => (type_name, def), Err(err) => { self.errors.push(err); return None; } }; let ty = if matches!( def, Definition { kind: DefinitionKind::Message(_), .. } ) { field_descriptor_proto::Type::Message } else { field_descriptor_proto::Type::Enum }; set_type_name( &mut self.pool.files[file as usize].raw, path, tag, format!(".{}", type_name), ty, ); Some(def) } fn add_missing_required_field_error(&mut self, file: FileIndex, path: Box<[i32]>) { self.errors.push(DescriptorErrorKind::MissingRequiredField { label: Label::new(&self.pool.files, "found here", file, path), }); } } fn parse_simple_value( kind: KindIndex, value: &str, ) -> Result> { let value = match kind { KindIndex::Double => value.parse().map(Value::F64)?, KindIndex::Float => value.parse().map(Value::F32)?, KindIndex::Int32 | KindIndex::Sint32 | KindIndex::Sfixed32 => { value.parse().map(Value::I32)? } KindIndex::Int64 | KindIndex::Sint64 | KindIndex::Sfixed64 => { value.parse().map(Value::I64)? } KindIndex::Uint32 | KindIndex::Fixed32 => value.parse().map(Value::U32)?, KindIndex::Uint64 | KindIndex::Fixed64 => value.parse().map(Value::U64)?, KindIndex::Bool => value.parse().map(Value::Bool)?, KindIndex::String => Value::String(value.to_owned()), KindIndex::Bytes => unescape_c_escape_string(value).map(Value::Bytes)?, KindIndex::Enum(_) | KindIndex::Message(_) | KindIndex::Group(_) => unreachable!(), }; Ok(value) } /// From https://github.com/tokio-rs/prost/blob/c3b7037a7f2c56cef327b41ca32a8c4e9ce5a41c/prost-build/src/code_generator.rs#L887 /// Based on [`google::protobuf::UnescapeCEscapeString`][1] /// [1]: https://github.com/google/protobuf/blob/3.3.x/src/google/protobuf/stubs/strutil.cc#L312-L322 fn unescape_c_escape_string(s: &str) -> Result { let src = s.as_bytes(); let len = src.len(); let mut dst = Vec::new(); let mut p = 0; while p < len { if src[p] != b'\\' { dst.push(src[p]); p += 1; } else { p += 1; if p == len { return Err("missing escape character"); } match src[p] { b'a' => { dst.push(0x07); p += 1; } b'b' => { dst.push(0x08); p += 1; } b'f' => { dst.push(0x0C); p += 1; } b'n' => { dst.push(0x0A); p += 1; } b'r' => { dst.push(0x0D); p += 1; } b't' => { dst.push(0x09); p += 1; } b'v' => { dst.push(0x0B); p += 1; } b'\\' => { dst.push(0x5C); p += 1; } b'?' => { dst.push(0x3F); p += 1; } b'\'' => { dst.push(0x27); p += 1; } b'"' => { dst.push(0x22); p += 1; } b'0'..=b'7' => { let mut octal = 0; for _ in 0..3 { if p < len && src[p] >= b'0' && src[p] <= b'7' { octal = octal * 8 + (src[p] - b'0'); p += 1; } else { break; } } dst.push(octal); } b'x' | b'X' => { if p + 3 > len { return Err("hex escape must contain two characters"); } match u8::from_str_radix(&s[p + 1..p + 3], 16) { Ok(b) => dst.push(b), _ => return Err("invalid hex escape"), } p += 3; } _ => return Err("invalid escape character"), } } } Ok(dst.into()) } fn set_type_name( file: &mut FileDescriptorProto, path: &[i32], tag: i32, type_name: String, ty: field_descriptor_proto::Type, ) { match path[0] { tag::file::SERVICE => { debug_assert_eq!(path.len(), 4); let service = &mut file.service[path[1] as usize]; debug_assert_eq!(path[2], tag::service::METHOD); let method = &mut service.method[path[3] as usize]; match tag { tag::method::INPUT_TYPE => method.input_type = Some(type_name), tag::method::OUTPUT_TYPE => method.output_type = Some(type_name), p => panic!("unknown path element {}", p), } } tag::file::MESSAGE_TYPE | tag::file::EXTENSION => { let field = find_file_field_proto_mut(file, path); match tag { tag::field::TYPE_NAME => { field.type_name = Some(type_name); if field.r#type() != field_descriptor_proto::Type::Group { field.set_type(ty); } } tag::field::EXTENDEE => field.extendee = Some(type_name), p => panic!("unknown path element {}", p), } } p => panic!("unknown path element {}", p), } } fn find_file_field_proto_mut<'a>( file: &'a mut FileDescriptorProto, path: &[i32], ) -> &'a mut FieldDescriptorProto { match path[0] { tag::file::MESSAGE_TYPE => { let message = &mut file.message_type[path[1] as usize]; find_message_field_proto(message, &path[2..]) } tag::file::EXTENSION => { debug_assert_eq!(path.len(), 2); &mut file.extension[path[1] as usize] } p => panic!("unknown path element {}", p), } } fn find_message_field_proto<'a>( message: &'a mut DescriptorProto, path: &[i32], ) -> &'a mut FieldDescriptorProto { match path[0] { tag::message::FIELD => { debug_assert_eq!(path.len(), 2); &mut message.field[path[1] as usize] } tag::message::EXTENSION => { debug_assert_eq!(path.len(), 2); &mut message.extension[path[1] as usize] } tag::message::NESTED_TYPE => { let nested_message = &mut message.nested_type[path[1] as usize]; find_message_field_proto(nested_message, &path[2..]) } p => panic!("unknown path element {}", p), } } #[test] fn test_unescape_c_escape_string() { assert_eq!(Ok(Bytes::default()), unescape_c_escape_string("")); assert_eq!( Ok(Bytes::from_static(b"hello world")), unescape_c_escape_string("hello world"), ); assert_eq!( Ok(Bytes::from_static(b"\0")), unescape_c_escape_string(r"\0"), ); assert_eq!( Ok(Bytes::from_static(&[0o012, 0o156])), unescape_c_escape_string(r"\012\156"), ); assert_eq!( Ok(Bytes::from_static(&[0x01, 0x02])), unescape_c_escape_string(r"\x01\x02") ); assert_eq!( Ok(Bytes::from_static( b"\0\x01\x07\x08\x0C\n\r\t\x0B\\\'\"\xFE?" )), unescape_c_escape_string(r#"\0\001\a\b\f\n\r\t\v\\\'\"\xfe\?"#), ); assert_eq!( Err("hex escape must contain two characters"), unescape_c_escape_string(r"\x") ); assert_eq!( Err("hex escape must contain two characters"), unescape_c_escape_string(r"\x1") ); assert_eq!( Ok(Bytes::from_static(b"\x11")), unescape_c_escape_string(r"\x11"), ); assert_eq!( Ok(Bytes::from_static(b"\x111")), unescape_c_escape_string(r"\x111") ); assert_eq!( Err("invalid escape character"), unescape_c_escape_string(r"\w") ); assert_eq!(Err("invalid hex escape"), unescape_c_escape_string(r"\x__")); } prost-reflect-0.15.0/src/descriptor/build/visit.rs000064400000000000000000000246451046102023000202630ustar 00000000000000use crate::descriptor::{ build::DescriptorPoolOffsets, tag, to_index, types::{ DescriptorProto, EnumDescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto, FileDescriptorProto, MethodDescriptorProto, OneofDescriptorProto, ServiceDescriptorProto, }, EnumIndex, EnumValueIndex, ExtensionIndex, FieldIndex, FileIndex, MessageIndex, MethodIndex, OneofIndex, ServiceIndex, }; pub(super) trait Visitor { fn visit_file(&mut self, _path: &[i32], _index: FileIndex, _file: &FileDescriptorProto) {} fn visit_message( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _parent_message: Option, _index: MessageIndex, _message: &DescriptorProto, ) { } fn visit_field( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _message: MessageIndex, _index: FieldIndex, _field: &FieldDescriptorProto, ) { } fn visit_oneof( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _message: MessageIndex, _index: OneofIndex, _oneof: &OneofDescriptorProto, ) { } fn visit_service( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _index: ServiceIndex, _service: &ServiceDescriptorProto, ) { } fn visit_method( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _service: ServiceIndex, _index: MethodIndex, _method: &MethodDescriptorProto, ) { } fn visit_enum( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _parent_message: Option, _index: EnumIndex, _enum: &EnumDescriptorProto, ) { } fn visit_enum_value( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _enum_: EnumIndex, _index: EnumValueIndex, _value: &EnumValueDescriptorProto, ) { } fn visit_extension( &mut self, _path: &[i32], _full_name: &str, _file: FileIndex, _parent_message: Option, _index: ExtensionIndex, _extension: &FieldDescriptorProto, ) { } } pub(super) fn visit( offsets: DescriptorPoolOffsets, files: &[FileDescriptorProto], visitor: &mut dyn Visitor, ) { let mut context = Context { path: Vec::new(), scope: String::new(), offsets, }; for file in files { context.visit_file(file, visitor); } } struct Context { path: Vec, scope: String, offsets: DescriptorPoolOffsets, } impl Context { fn visit_file(&mut self, file: &FileDescriptorProto, visitor: &mut dyn Visitor) { if !file.package().is_empty() { self.push_scope(file.package()); } let index = post_inc(&mut self.offsets.file); visitor.visit_file(&self.path, index, file); self.push_path(tag::file::MESSAGE_TYPE); for (i, message) in file.message_type.iter().enumerate() { self.push_path(i as i32); self.visit_message(message, visitor, index, None); self.pop_path(); } self.pop_path(); self.push_path(tag::file::ENUM_TYPE); for (i, enum_) in file.enum_type.iter().enumerate() { self.push_path(i as i32); self.visit_enum(enum_, visitor, index, None); self.pop_path(); } self.pop_path(); self.push_path(tag::file::SERVICE); for (i, service) in file.service.iter().enumerate() { self.push_path(i as i32); self.visit_service(service, visitor, index); self.pop_path(); } self.pop_path(); self.push_path(tag::file::EXTENSION); for (i, extension) in file.extension.iter().enumerate() { self.push_path(i as i32); self.visit_extension(extension, visitor, index, None); self.pop_path(); } self.pop_path(); if !file.package().is_empty() { self.pop_scope(file.package()); } } fn visit_message( &mut self, message: &DescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, parent_message: Option, ) { self.push_scope(message.name()); let index = post_inc(&mut self.offsets.message); visitor.visit_message( &self.path, &self.scope, file, parent_message, index, message, ); self.push_path(tag::message::ONEOF_DECL); for (i, oneof) in message.oneof_decl.iter().enumerate() { self.push_path(i as i32); self.visit_oneof(oneof, visitor, file, index, to_index(i)); self.pop_path(); } self.pop_path(); self.push_path(tag::message::FIELD); for (i, field) in message.field.iter().enumerate() { self.push_path(i as i32); self.visit_field(field, visitor, file, index, to_index(i)); self.pop_path(); } self.pop_path(); self.push_path(tag::message::NESTED_TYPE); for (i, nested) in message.nested_type.iter().enumerate() { self.push_path(i as i32); self.visit_message(nested, visitor, file, Some(index)); self.pop_path(); } self.pop_path(); self.push_path(tag::message::ENUM_TYPE); for (i, enum_) in message.enum_type.iter().enumerate() { self.push_path(i as i32); self.visit_enum(enum_, visitor, file, Some(index)); self.pop_path(); } self.pop_path(); self.push_path(tag::message::EXTENSION); for (i, extension) in message.extension.iter().enumerate() { self.push_path(i as i32); self.visit_extension(extension, visitor, file, Some(index)); self.pop_path(); } self.pop_path(); self.pop_scope(message.name()); } fn visit_field( &mut self, field: &FieldDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, message: MessageIndex, index: FieldIndex, ) { self.push_scope(field.name()); visitor.visit_field(&self.path, &self.scope, file, message, index, field); self.pop_scope(field.name()); } fn visit_oneof( &mut self, oneof: &OneofDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, message: MessageIndex, index: OneofIndex, ) { self.push_scope(oneof.name()); visitor.visit_oneof(&self.path, &self.scope, file, message, index, oneof); self.pop_scope(oneof.name()); } fn visit_service( &mut self, service: &ServiceDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, ) { self.push_scope(service.name()); let index = post_inc(&mut self.offsets.service); visitor.visit_service(&self.path, &self.scope, file, index, service); self.push_path(tag::service::METHOD); for (i, method) in service.method.iter().enumerate() { self.push_path(i as i32); self.visit_method(method, visitor, file, index, to_index(i)); self.pop_path(); } self.pop_path(); self.pop_scope(service.name()); } fn visit_method( &mut self, method: &MethodDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, service: ServiceIndex, index: MethodIndex, ) { self.push_scope(method.name()); visitor.visit_method(&self.path, &self.scope, file, service, index, method); self.pop_scope(method.name()); } fn visit_enum( &mut self, enum_: &EnumDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, parent_message: Option, ) { self.push_scope(enum_.name()); let index = post_inc(&mut self.offsets.enum_); visitor.visit_enum(&self.path, &self.scope, file, parent_message, index, enum_); self.pop_scope(enum_.name()); self.push_path(tag::enum_::VALUE); for (i, method) in enum_.value.iter().enumerate() { self.push_path(i as i32); self.visit_enum_value(method, visitor, file, index, to_index(i)); self.pop_path(); } self.pop_path(); } fn visit_enum_value( &mut self, value: &EnumValueDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, enum_: EnumIndex, index: EnumValueIndex, ) { self.push_scope(value.name()); visitor.visit_enum_value(&self.path, &self.scope, file, enum_, index, value); self.pop_scope(value.name()); } fn visit_extension( &mut self, extension: &FieldDescriptorProto, visitor: &mut dyn Visitor, file: FileIndex, parent_message: Option, ) { self.push_scope(extension.name()); let index = post_inc(&mut self.offsets.extension); visitor.visit_extension( &self.path, &self.scope, file, parent_message, index, extension, ); self.pop_scope(extension.name()); } fn push_path(&mut self, path: i32) { self.path.push(path); } fn pop_path(&mut self) { self.path.pop().unwrap(); } fn push_scope(&mut self, scope: &str) { if !self.scope.is_empty() { self.scope.push('.'); } self.scope.push_str(scope); } fn pop_scope(&mut self, scope: &str) { debug_assert!(self.scope.ends_with(scope)); self.scope .truncate((self.scope.len() - scope.len()).saturating_sub(1)); } } fn post_inc(index: &mut u32) -> u32 { let value = *index; *index = value + 1; value } prost-reflect-0.15.0/src/descriptor/error.rs000064400000000000000000001000651046102023000171460ustar 00000000000000use std::{ fmt, ops::{Range, RangeInclusive}, }; use crate::descriptor::{FileDescriptorInner, FileIndex}; /// An error that may occur while creating a [`DescriptorPool`][crate::DescriptorPool]. pub struct DescriptorError { errors: Box<[DescriptorErrorKind]>, #[cfg(feature = "miette")] source: Option>, } #[derive(Debug)] pub(super) enum DescriptorErrorKind { MissingRequiredField { label: Label, }, UnknownSyntax { syntax: String, found: Label, }, DuplicateFileName { name: String, }, FileNotFound { name: String, found: Label, }, InvalidImportIndex, InvalidOneofIndex, DuplicateName { name: String, first: Label, second: Label, }, DuplicateFieldNumber { number: u32, #[cfg_attr(not(feature = "miette"), allow(dead_code))] first: Label, second: Label, }, DuplicateFieldJsonName { name: String, #[cfg_attr(not(feature = "miette"), allow(dead_code))] first: Label, second: Label, }, DuplicateFieldCamelCaseName { first_name: String, second_name: String, #[cfg_attr(not(feature = "miette"), allow(dead_code))] first: Label, second: Label, }, InvalidFieldNumber { number: i32, found: Label, }, FieldNumberInReservedRange { number: i32, range: Range, #[cfg_attr(not(feature = "miette"), allow(dead_code))] defined: Label, found: Label, }, FieldNumberInExtensionRange { number: i32, range: Range, #[cfg_attr(not(feature = "miette"), allow(dead_code))] defined: Label, found: Label, }, ExtensionNumberOutOfRange { number: i32, message: String, found: Label, }, NameNotFound { name: String, found: Label, #[cfg_attr(not(feature = "miette"), allow(dead_code))] help: Option, }, NameShadowed { name: String, shadowed_name: String, found: Label, #[cfg_attr(not(feature = "miette"), allow(dead_code))] help: Option, }, InvalidType { name: String, expected: String, found: Label, #[cfg_attr(not(feature = "miette"), allow(dead_code))] defined: Label, }, InvalidFieldDefault { value: String, kind: String, found: Label, }, EmptyEnum { found: Label, }, InvalidProto3EnumDefault { found: Label, }, DuplicateEnumNumber { number: i32, #[cfg_attr(not(feature = "miette"), allow(dead_code))] first: Label, second: Label, }, EnumNumberInReservedRange { number: i32, range: RangeInclusive, #[cfg_attr(not(feature = "miette"), allow(dead_code))] defined: Label, found: Label, }, OptionNotFound { name: String, found: Label, }, InvalidOptionType { name: String, ty: String, value: String, is_last: bool, found: Label, }, InvalidOptionExtendee { name: String, expected_extendee: String, actual_extendee: String, found: Label, }, #[cfg(feature = "text-format")] InvalidMessageOption { name: String, ty: String, found: Label, err: crate::text_format::ParseError, }, DuplicateOption { name: String, found: Label, }, DecodeFileDescriptorSet { err: prost::DecodeError, }, } #[derive(Debug)] pub(super) struct Label { file: String, path: Box<[i32]>, span: Option<[i32; 4]>, #[cfg(feature = "miette")] message: String, #[cfg(feature = "miette")] resolved: Option, } impl DescriptorError { pub(super) fn new(errors: Vec) -> DescriptorError { debug_assert!(!errors.is_empty()); DescriptorError { errors: errors.into(), #[cfg(feature = "miette")] source: None, } } /// The primary file in which this error occurred. pub fn file(&self) -> Option<&str> { self.first().label().map(|l| l.file.as_str()) } /// The 0-based line number at which this error occurred, if available. /// /// This field may be `None` if the error is not associated with a particular source location, or the /// [`source_code_info`](prost_types::FileDescriptorProto::source_code_info) field was not populated for the input file. pub fn line(&self) -> Option { self.first() .label() .and_then(|l| l.span) .map(|s| s[0] as usize) } /// The 0-based column number at which this error occurred, if available. /// /// This field may be `None` if the error is not associated with a particular source location, or the /// [`source_code_info`](prost_types::FileDescriptorProto::source_code_info) field was not populated for the input file. pub fn column(&self) -> Option { self.first() .label() .and_then(|l| l.span) .map(|s| s[1] as usize) } /// Gets the path where this error occurred in the [`FileDescriptorProto`][prost_types::FileDescriptorProto], if available. /// /// See [`path`][prost_types::source_code_info::Location::path] for more details on the structure of the path. pub fn path(&self) -> Option<&[i32]> { self.first().label().map(|l| l.path.as_ref()) } #[cfg(feature = "miette")] #[cfg_attr(docsrs, doc(cfg(feature = "miette")))] /// Provide source code information for this error. /// /// The source should correspond to the contents of [`file()`][DescriptorError::file]. pub fn with_source_code(mut self, source: &str) -> Self { if let Some(file) = self.file() { let file = file.to_owned(); self.source = Some(miette::NamedSource::new(&file, source.to_owned())); for error in self.errors.as_mut() { error.add_source_code(&file, source); } } self } fn first(&self) -> &DescriptorErrorKind { &self.errors[0] } } impl std::error::Error for DescriptorError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.first().source() } } impl fmt::Display for DescriptorError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.first().fmt(f) } } impl fmt::Debug for DescriptorError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(file) = self.file() { write!(f, "{}:", file)?; if let (Some(line), Some(column)) = (self.line(), self.column()) { write!(f, "{}:{}:", line + 1, column + 1)?; } write!(f, " ")?; } write!(f, "{}", self) } } #[cfg(feature = "miette")] #[cfg_attr(docsrs, doc(cfg(feature = "miette")))] impl miette::Diagnostic for DescriptorError { fn code<'a>(&'a self) -> Option> { self.first().code() } fn severity(&self) -> Option { self.first().severity() } fn help<'a>(&'a self) -> Option> { self.first().help() } fn url<'a>(&'a self) -> Option> { self.first().url() } fn source_code(&self) -> Option<&dyn miette::SourceCode> { match &self.source { Some(source) => Some(source), None => None, } } fn labels(&self) -> Option + '_>> { self.first().labels() } fn related<'a>(&'a self) -> Option + 'a>> { if self.errors.len() > 1 { Some(Box::new( self.errors .iter() .map(|e| e as &dyn miette::Diagnostic) .skip(1), )) } else { None } } fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> { self.first().diagnostic_source() } } impl DescriptorErrorKind { fn label(&self) -> Option<&Label> { match self { DescriptorErrorKind::MissingRequiredField { label } => Some(label), DescriptorErrorKind::UnknownSyntax { found, .. } => Some(found), DescriptorErrorKind::DuplicateFileName { .. } => None, DescriptorErrorKind::FileNotFound { found, .. } => Some(found), DescriptorErrorKind::InvalidImportIndex => None, DescriptorErrorKind::InvalidOneofIndex => None, DescriptorErrorKind::DuplicateName { second, .. } => Some(second), DescriptorErrorKind::DuplicateFieldNumber { second, .. } => Some(second), DescriptorErrorKind::DuplicateFieldJsonName { second, .. } => Some(second), DescriptorErrorKind::DuplicateFieldCamelCaseName { second, .. } => Some(second), DescriptorErrorKind::InvalidFieldNumber { found, .. } => Some(found), DescriptorErrorKind::FieldNumberInReservedRange { found, .. } => Some(found), DescriptorErrorKind::FieldNumberInExtensionRange { found, .. } => Some(found), DescriptorErrorKind::ExtensionNumberOutOfRange { found, .. } => Some(found), DescriptorErrorKind::NameNotFound { found, .. } => Some(found), DescriptorErrorKind::NameShadowed { found, .. } => Some(found), DescriptorErrorKind::InvalidType { found, .. } => Some(found), DescriptorErrorKind::InvalidFieldDefault { found, .. } => Some(found), DescriptorErrorKind::EmptyEnum { found } => Some(found), DescriptorErrorKind::InvalidProto3EnumDefault { found } => Some(found), DescriptorErrorKind::DuplicateEnumNumber { second, .. } => Some(second), DescriptorErrorKind::EnumNumberInReservedRange { found, .. } => Some(found), DescriptorErrorKind::OptionNotFound { found, .. } => Some(found), DescriptorErrorKind::InvalidOptionType { found, .. } => Some(found), DescriptorErrorKind::InvalidOptionExtendee { found, .. } => Some(found), #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { found, .. } => Some(found), DescriptorErrorKind::DuplicateOption { found, .. } => Some(found), DescriptorErrorKind::DecodeFileDescriptorSet { .. } => None, } } #[cfg(feature = "miette")] fn add_source_code(&mut self, file: &str, source: &str) { match self { DescriptorErrorKind::MissingRequiredField { label } => { label.resolve_span(file, source); } DescriptorErrorKind::UnknownSyntax { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::DuplicateFileName { .. } => {} DescriptorErrorKind::FileNotFound { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::InvalidImportIndex => {} DescriptorErrorKind::InvalidOneofIndex => {} DescriptorErrorKind::DuplicateName { first, second, .. } => { first.resolve_span(file, source); second.resolve_span(file, source); } DescriptorErrorKind::DuplicateFieldNumber { first, second, .. } => { first.resolve_span(file, source); second.resolve_span(file, source); } DescriptorErrorKind::DuplicateFieldJsonName { first, second, .. } => { first.resolve_span(file, source); second.resolve_span(file, source); } DescriptorErrorKind::DuplicateFieldCamelCaseName { first, second, .. } => { first.resolve_span(file, source); second.resolve_span(file, source); } DescriptorErrorKind::InvalidFieldNumber { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::FieldNumberInReservedRange { defined, found, .. } => { defined.resolve_span(file, source); found.resolve_span(file, source); } DescriptorErrorKind::FieldNumberInExtensionRange { defined, found, .. } => { defined.resolve_span(file, source); found.resolve_span(file, source); } DescriptorErrorKind::ExtensionNumberOutOfRange { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::NameNotFound { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::NameShadowed { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::InvalidType { found, defined, .. } => { found.resolve_span(file, source); defined.resolve_span(file, source); } DescriptorErrorKind::InvalidFieldDefault { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::EmptyEnum { found } => { found.resolve_span(file, source); } DescriptorErrorKind::InvalidProto3EnumDefault { found } => { found.resolve_span(file, source); } DescriptorErrorKind::DuplicateEnumNumber { first, second, .. } => { first.resolve_span(file, source); second.resolve_span(file, source); } DescriptorErrorKind::EnumNumberInReservedRange { defined, found, .. } => { found.resolve_span(file, source); defined.resolve_span(file, source); } DescriptorErrorKind::OptionNotFound { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::InvalidOptionType { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::InvalidOptionExtendee { found, .. } => { found.resolve_span(file, source); } #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::DuplicateOption { found, .. } => { found.resolve_span(file, source); } DescriptorErrorKind::DecodeFileDescriptorSet { .. } => {} } } } impl std::error::Error for DescriptorErrorKind { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { DescriptorErrorKind::DecodeFileDescriptorSet { err } => Some(err), #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { err, .. } => Some(err), _ => None, } } } impl fmt::Display for DescriptorErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { DescriptorErrorKind::MissingRequiredField { label } => { write!(f, "missing required field at {:?}", label.path) } DescriptorErrorKind::UnknownSyntax { syntax, .. } => { write!(f, "unknown syntax '{}'", syntax) } DescriptorErrorKind::DuplicateFileName { name, .. } => { write!( f, "a different file named '{}' has already been added", name ) } DescriptorErrorKind::FileNotFound { name, .. } => { write!(f, "imported file '{}' has not been added", name) } DescriptorErrorKind::InvalidImportIndex => { write!(f, "invalid import index") } DescriptorErrorKind::InvalidOneofIndex => { write!(f, "invalid oneof index") } DescriptorErrorKind::DuplicateName { name, first, second, } => { if first.file == second.file { write!(f, "name '{}' is defined twice", name) } else { write!( f, "name '{}' is already defined in file '{}'", name, first.file ) } } DescriptorErrorKind::DuplicateFieldNumber { number, .. } => { write!(f, "field number '{}' is already used", number) } DescriptorErrorKind::DuplicateFieldJsonName { name, .. } => { write!(f, "a field with JSON name '{}' is already defined", name) } DescriptorErrorKind::DuplicateFieldCamelCaseName { first_name, second_name, .. } => { write!( f, "camel-case name of field '{first_name}' conflicts with field '{second_name}'" ) } DescriptorErrorKind::InvalidFieldNumber { number, .. } => { write!(f, "invalid field number '{}'", number) } DescriptorErrorKind::FieldNumberInReservedRange { number, range, .. } => { write!( f, "field number '{}' conflicts with reserved range '{} to {}'", number, range.start, range.end - 1 ) } DescriptorErrorKind::FieldNumberInExtensionRange { number, range, .. } => { write!( f, "field number '{}' conflicts with extension range '{} to {}'", number, range.start, range.end - 1 ) } DescriptorErrorKind::ExtensionNumberOutOfRange { number, message, .. } => { write!( f, "message '{}' does not define '{}' as an extension number", message, number ) } DescriptorErrorKind::NameNotFound { name, .. } => { write!(f, "name '{}' is not defined", name) } DescriptorErrorKind::NameShadowed { name, shadowed_name, .. } => { write!( f, "'{name}' resolves to '{shadowed_name}', which is not defined", ) } DescriptorErrorKind::InvalidType { name, expected, .. } => { write!(f, "'{}' is not {}", name, expected) } DescriptorErrorKind::InvalidFieldDefault { value, kind, .. } => { write!(f, "invalid default value '{}' for type '{}'", value, kind) } DescriptorErrorKind::EmptyEnum { .. } => { write!(f, "enums must have at least one value") } DescriptorErrorKind::InvalidProto3EnumDefault { .. } => { write!(f, "the first value for proto3 enums must be 0") } DescriptorErrorKind::DuplicateEnumNumber { number, .. } => { write!(f, "enum number '{}' has already been used", number) } DescriptorErrorKind::EnumNumberInReservedRange { number, range, .. } => { write!( f, "enum number '{}' conflicts with reserved range '{} to {}'", number, range.start(), range.end() ) } DescriptorErrorKind::OptionNotFound { name, .. } => { write!(f, "option field '{}' is not defined", name) } DescriptorErrorKind::InvalidOptionType { name, ty, value, is_last, .. } => { if *is_last { write!( f, "expected a value of type '{}' for option '{}', but found '{}'", ty, name, value ) } else { write!( f, "cannot set field for option '{}' value of type '{}'", name, ty ) } } DescriptorErrorKind::InvalidOptionExtendee { name, expected_extendee, actual_extendee, .. } => { write!( f, "expected an extension to type '{}', but '{}' extends '{}'", expected_extendee, name, actual_extendee ) } #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { name, ty, .. } => { write!(f, "invalid value of type '{}' for option '{}'", ty, name) } DescriptorErrorKind::DuplicateOption { name, .. } => { write!(f, "option field '{}' has already been set", name) } DescriptorErrorKind::DecodeFileDescriptorSet { .. } => { write!(f, "failed to decode file descriptor set") } } } } #[cfg(feature = "miette")] #[cfg_attr(docsrs, doc(cfg(feature = "miette")))] impl miette::Diagnostic for DescriptorErrorKind { fn help<'a>(&'a self) -> Option> { use crate::descriptor::{RESERVED_MESSAGE_FIELD_NUMBERS, VALID_MESSAGE_FIELD_NUMBERS}; match self { DescriptorErrorKind::MissingRequiredField { .. } => None, DescriptorErrorKind::UnknownSyntax { .. } => { Some(Box::new("valid values are 'proto2' and 'proto3'")) } DescriptorErrorKind::DuplicateFileName { .. } => None, DescriptorErrorKind::FileNotFound { .. } => None, DescriptorErrorKind::InvalidImportIndex => None, DescriptorErrorKind::InvalidOneofIndex => None, DescriptorErrorKind::DuplicateName { .. } => None, DescriptorErrorKind::DuplicateFieldNumber { .. } => None, DescriptorErrorKind::InvalidFieldNumber { number, .. } => { if !VALID_MESSAGE_FIELD_NUMBERS.contains(number) { Some(Box::new(format!( "field numbers must be between {} and {}", VALID_MESSAGE_FIELD_NUMBERS.start, VALID_MESSAGE_FIELD_NUMBERS.end - 1 ))) } else if RESERVED_MESSAGE_FIELD_NUMBERS.contains(number) { Some(Box::new(format!( "field numbers {} to {} are reserved", RESERVED_MESSAGE_FIELD_NUMBERS.start, RESERVED_MESSAGE_FIELD_NUMBERS.end - 1 ))) } else { None } } DescriptorErrorKind::FieldNumberInReservedRange { .. } => None, DescriptorErrorKind::FieldNumberInExtensionRange { .. } => None, DescriptorErrorKind::DuplicateFieldJsonName { .. } => None, DescriptorErrorKind::DuplicateFieldCamelCaseName { .. } => None, DescriptorErrorKind::NameNotFound { help, .. } | DescriptorErrorKind::NameShadowed { help, .. } => help .as_ref() .map(|h| -> Box { Box::new(h.clone()) }), DescriptorErrorKind::InvalidType { .. } => None, DescriptorErrorKind::InvalidFieldDefault { .. } => None, DescriptorErrorKind::EmptyEnum { .. } => None, DescriptorErrorKind::InvalidProto3EnumDefault { .. } => None, DescriptorErrorKind::DuplicateEnumNumber { .. } => Some(Box::new( "set the 'allow_alias' option allow re-using enum numbers", )), DescriptorErrorKind::EnumNumberInReservedRange { .. } => None, DescriptorErrorKind::OptionNotFound { .. } => None, DescriptorErrorKind::InvalidOptionType { .. } => None, DescriptorErrorKind::InvalidOptionExtendee { .. } => None, #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { .. } => None, DescriptorErrorKind::DuplicateOption { .. } => None, DescriptorErrorKind::DecodeFileDescriptorSet { .. } => None, DescriptorErrorKind::ExtensionNumberOutOfRange { .. } => None, } } fn labels(&self) -> Option + '_>> { let mut spans = Vec::new(); match self { DescriptorErrorKind::MissingRequiredField { label } => spans.extend(label.to_span()), DescriptorErrorKind::UnknownSyntax { found: defined, .. } => { spans.extend(defined.to_span()); } DescriptorErrorKind::DuplicateFileName { .. } => {} DescriptorErrorKind::FileNotFound { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::InvalidImportIndex => {} DescriptorErrorKind::InvalidOneofIndex => {} DescriptorErrorKind::DuplicateName { first, second, .. } => { spans.extend(first.to_span()); spans.extend(second.to_span()); } DescriptorErrorKind::DuplicateFieldNumber { first, second, .. } => { spans.extend(first.to_span()); spans.extend(second.to_span()); } DescriptorErrorKind::DuplicateFieldJsonName { first, second, .. } => { spans.extend(first.to_span()); spans.extend(second.to_span()); } DescriptorErrorKind::DuplicateFieldCamelCaseName { first, second, .. } => { spans.extend(first.to_span()); spans.extend(second.to_span()); } DescriptorErrorKind::NameNotFound { found, .. } | DescriptorErrorKind::NameShadowed { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::InvalidFieldNumber { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::FieldNumberInReservedRange { defined, found, .. } => { spans.extend(defined.to_span()); spans.extend(found.to_span()); } DescriptorErrorKind::FieldNumberInExtensionRange { defined, found, .. } => { spans.extend(defined.to_span()); spans.extend(found.to_span()); } DescriptorErrorKind::ExtensionNumberOutOfRange { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::InvalidType { found, defined, .. } => { spans.extend(found.to_span()); spans.extend(defined.to_span()); } DescriptorErrorKind::InvalidFieldDefault { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::EmptyEnum { found } => { spans.extend(found.to_span()); } DescriptorErrorKind::InvalidProto3EnumDefault { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::DuplicateEnumNumber { first, second, .. } => { spans.extend(first.to_span()); spans.extend(second.to_span()); } DescriptorErrorKind::EnumNumberInReservedRange { defined, found, .. } => { spans.extend(found.to_span()); spans.extend(defined.to_span()); } DescriptorErrorKind::OptionNotFound { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::InvalidOptionType { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::InvalidOptionExtendee { found, .. } => { spans.extend(found.to_span()); } #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::DuplicateOption { found, .. } => { spans.extend(found.to_span()); } DescriptorErrorKind::DecodeFileDescriptorSet { .. } => {} } if spans.is_empty() { None } else { Some(Box::new(spans.into_iter())) } } fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> { match self { #[cfg(feature = "text-format")] DescriptorErrorKind::InvalidMessageOption { err, .. } => Some(err), _ => None, } } } impl Label { pub fn new( files: &[FileDescriptorInner], #[cfg_attr(not(feature = "miette"), allow(unused_variables))] message: impl ToString, file: FileIndex, path: Box<[i32]>, ) -> Self { let file = &files[file as usize].raw; let span = file .source_code_info .as_ref() .and_then(|s| s.location.iter().find(|l| *l.path == *path)) .and_then(|l| match *l.span { [start_line, start_col, end_col] => { Some([start_line, start_col, start_line, end_col]) } [start_line, start_col, end_line, end_col] => { Some([start_line, start_col, end_line, end_col]) } _ => None, }); Label { file: file.name().to_owned(), span, path, #[cfg(feature = "miette")] message: message.to_string(), #[cfg(feature = "miette")] resolved: None, } } #[cfg(feature = "miette")] pub fn resolve_span(&mut self, file: &str, source: &str) { if file == self.file { if let Some([start_line, start_col, end_line, end_col]) = self.span { let start = miette::SourceOffset::from_location( source, start_line.saturating_add(1) as _, start_col.saturating_add(1) as _, ) .offset(); let end = miette::SourceOffset::from_location( source, end_line.saturating_add(1) as _, end_col.saturating_add(1) as _, ) .offset(); self.resolved = Some(miette::SourceSpan::from(start..end)); } } } #[cfg(feature = "miette")] fn to_span(&self) -> Option { match self.resolved { Some(span) if !span.is_empty() => Some(miette::LabeledSpan::new_with_span( Some(self.message.clone()), span, )), _ => None, } } } prost-reflect-0.15.0/src/descriptor/global.rs000064400000000000000000000034421046102023000172560ustar 00000000000000use std::sync::{Mutex, MutexGuard, OnceLock}; use prost::bytes::Buf; use prost_types::FileDescriptorProto; use crate::{DescriptorError, DescriptorPool}; static INSTANCE: OnceLock> = OnceLock::new(); fn instance() -> MutexGuard<'static, DescriptorPool> { INSTANCE .get_or_init(|| Mutex::new(crate::reflect::make_wkt_descriptor_pool().unwrap())) .lock() .unwrap() } impl DescriptorPool { /// Gets a copy of the global descriptor pool. By default, this just contains the google well-known types. /// /// The global descriptor pool is typically used as a convenient place to store descriptors for `ReflectMessage` implementations. /// /// Note that modifications to the returned pool won't affect the global pool - use /// [`decode_global_file_descriptor_set`](DescriptorPool::decode_global_file_descriptor_set) or /// [`add_global_file_descriptor_proto`](DescriptorPool::add_global_file_descriptor_proto) to modify the global pool. pub fn global() -> DescriptorPool { instance().clone() } /// Decodes and adds a set of file descriptors to the global pool. /// /// See [`DescriptorPool::decode_file_descriptor_set`] for more details. pub fn decode_global_file_descriptor_set(bytes: B) -> Result<(), DescriptorError> where B: Buf, { instance().decode_file_descriptor_set(bytes)?; Ok(()) } /// Adds a single file descriptor to the global pool. /// /// See [`DescriptorPool::add_file_descriptor_proto`] for more details. pub fn add_global_file_descriptor_proto( file: FileDescriptorProto, ) -> Result<(), DescriptorError> { instance().add_file_descriptor_proto(file)?; Ok(()) } } prost-reflect-0.15.0/src/descriptor/mod.rs000064400000000000000000000306171046102023000166010ustar 00000000000000mod api; mod build; mod error; mod global; mod tag; #[cfg(test)] mod tests; pub(crate) mod types; pub use self::error::DescriptorError; use self::types::{DescriptorProto, EnumDescriptorProto}; use std::{ collections::{BTreeMap, HashMap, HashSet}, convert::TryInto, fmt, ops::Range, sync::Arc, }; use crate::{descriptor::types::FileDescriptorProto, Value}; pub(crate) const MAP_ENTRY_KEY_NUMBER: u32 = 1; pub(crate) const MAP_ENTRY_VALUE_NUMBER: u32 = 2; pub(crate) const RESERVED_MESSAGE_FIELD_NUMBERS: Range = 19_000..20_000; pub(crate) const VALID_MESSAGE_FIELD_NUMBERS: Range = 1..536_870_912; /// Cardinality determines whether a field is optional, required, or repeated. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Cardinality { /// The field appears zero or one times. Optional, /// The field appears exactly one time. This cardinality is invalid with Proto3. Required, /// The field appears zero or more times. Repeated, } /// The syntax of a proto file. #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum Syntax { /// The `proto2` syntax. Proto2, /// The `proto3` syntax. Proto3, } /// The type of a protobuf message field. #[derive(Clone, PartialEq, Eq)] pub enum Kind { /// The protobuf `double` type. Double, /// The protobuf `float` type. Float, /// The protobuf `int32` type. Int32, /// The protobuf `int64` type. Int64, /// The protobuf `uint32` type. Uint32, /// The protobuf `uint64` type. Uint64, /// The protobuf `sint32` type. Sint32, /// The protobuf `sint64` type. Sint64, /// The protobuf `fixed32` type. Fixed32, /// The protobuf `fixed64` type. Fixed64, /// The protobuf `sfixed32` type. Sfixed32, /// The protobuf `sfixed64` type. Sfixed64, /// The protobuf `bool` type. Bool, /// The protobuf `string` type. String, /// The protobuf `bytes` type. Bytes, /// A protobuf message type. Message(MessageDescriptor), /// A protobuf enum type. Enum(EnumDescriptor), } #[derive(Copy, Clone)] enum KindIndex { Double, Float, Int32, Int64, Uint32, Uint64, Sint32, Sint64, Fixed32, Fixed64, Sfixed32, Sfixed64, Bool, String, Bytes, Message(MessageIndex), Enum(EnumIndex), Group(MessageIndex), } type DescriptorIndex = u32; type FileIndex = DescriptorIndex; type ServiceIndex = DescriptorIndex; type MethodIndex = DescriptorIndex; type MessageIndex = DescriptorIndex; type FieldIndex = DescriptorIndex; type OneofIndex = DescriptorIndex; type ExtensionIndex = DescriptorIndex; type EnumIndex = DescriptorIndex; type EnumValueIndex = DescriptorIndex; /// A `DescriptorPool` is a collection of related descriptors. Typically it will be created from /// a [`FileDescriptorSet`][prost_types::FileDescriptorSet] output by the protobuf compiler /// (see [`DescriptorPool::from_file_descriptor_set`]) but it may also be built up by adding files individually. /// /// Methods like [`MessageDescriptor::extensions`] will be scoped to just the files contained within the parent /// `DescriptorPool`. /// /// This type uses reference counting internally so it is cheap to clone. Modifying an instance of a /// pool will not update any existing clones of the instance. #[derive(Clone, Default)] pub struct DescriptorPool { inner: Arc, } #[derive(Clone, Default)] struct DescriptorPoolInner { names: HashMap, Definition>, file_names: HashMap, FileIndex>, files: Vec, messages: Vec, enums: Vec, extensions: Vec, services: Vec, } #[derive(Clone)] struct Identity { file: FileIndex, path: Box<[i32]>, full_name: Box, name_index: usize, } #[derive(Clone, Debug)] struct Definition { file: FileIndex, path: Box<[i32]>, kind: DefinitionKind, } #[derive(Copy, Clone, Debug)] enum DefinitionKind { Package, Message(MessageIndex), Field(MessageIndex), Oneof(MessageIndex), Service(ServiceIndex), Method(ServiceIndex), Enum(EnumIndex), EnumValue(EnumIndex), Extension(ExtensionIndex), } /// A single source file containing protobuf messages and services. #[derive(Clone, PartialEq, Eq)] pub struct FileDescriptor { pool: DescriptorPool, index: FileIndex, } #[derive(Clone)] struct FileDescriptorInner { syntax: Syntax, raw: FileDescriptorProto, prost: prost_types::FileDescriptorProto, dependencies: Vec, transitive_dependencies: HashSet, } /// A protobuf message definition. #[derive(Clone, PartialEq, Eq)] pub struct MessageDescriptor { pool: DescriptorPool, index: MessageIndex, } #[derive(Clone)] struct MessageDescriptorInner { id: Identity, parent: Option, extensions: Vec, fields: Vec, field_numbers: BTreeMap, field_names: HashMap, FieldIndex>, field_json_names: HashMap, FieldIndex>, oneofs: Vec, } /// A oneof field in a protobuf message. #[derive(Clone, PartialEq, Eq)] pub struct OneofDescriptor { message: MessageDescriptor, index: OneofIndex, } #[derive(Clone)] struct OneofDescriptorInner { id: Identity, fields: Vec, } /// A protobuf message definition. #[derive(Clone, PartialEq, Eq)] pub struct FieldDescriptor { message: MessageDescriptor, index: FieldIndex, } #[derive(Clone)] struct FieldDescriptorInner { id: Identity, number: u32, json_name: Box, kind: KindIndex, oneof: Option, is_packed: bool, supports_presence: bool, cardinality: Cardinality, default: Option, } /// A protobuf extension field definition. #[derive(Clone, PartialEq, Eq)] pub struct ExtensionDescriptor { pool: DescriptorPool, index: ExtensionIndex, } #[derive(Clone)] pub struct ExtensionDescriptorInner { id: Identity, parent: Option, number: u32, json_name: Box, extendee: MessageIndex, kind: KindIndex, is_packed: bool, cardinality: Cardinality, default: Option, } /// A protobuf enum type. #[derive(Clone, PartialEq, Eq)] pub struct EnumDescriptor { pool: DescriptorPool, index: EnumIndex, } #[derive(Clone)] struct EnumDescriptorInner { id: Identity, parent: Option, values: Vec, value_numbers: Vec<(i32, EnumValueIndex)>, value_names: HashMap, EnumValueIndex>, allow_alias: bool, } /// A value in a protobuf enum type. #[derive(Clone, PartialEq, Eq)] pub struct EnumValueDescriptor { parent: EnumDescriptor, index: EnumValueIndex, } #[derive(Clone)] struct EnumValueDescriptorInner { id: Identity, number: i32, } /// A protobuf service definition. #[derive(Clone, PartialEq, Eq)] pub struct ServiceDescriptor { pool: DescriptorPool, index: ServiceIndex, } #[derive(Clone)] struct ServiceDescriptorInner { id: Identity, methods: Vec, } /// A method definition for a [`ServiceDescriptor`]. #[derive(Clone, PartialEq, Eq)] pub struct MethodDescriptor { service: ServiceDescriptor, index: MethodIndex, } #[derive(Clone)] struct MethodDescriptorInner { id: Identity, input: MessageIndex, output: MessageIndex, } impl Identity { fn new(file: FileIndex, path: &[i32], full_name: &str, name: &str) -> Identity { debug_assert!(full_name.ends_with(name)); let name_index = full_name.len() - name.len(); debug_assert!(name_index == 0 || full_name.as_bytes()[name_index - 1] == b'.'); Identity { file, path: path.into(), full_name: full_name.into(), name_index, } } fn full_name(&self) -> &str { &self.full_name } fn name(&self) -> &str { &self.full_name[self.name_index..] } } impl KindIndex { fn is_packable(&self) -> bool { match self { KindIndex::Double | KindIndex::Float | KindIndex::Int32 | KindIndex::Int64 | KindIndex::Uint32 | KindIndex::Uint64 | KindIndex::Sint32 | KindIndex::Sint64 | KindIndex::Fixed32 | KindIndex::Fixed64 | KindIndex::Sfixed32 | KindIndex::Sfixed64 | KindIndex::Bool | KindIndex::Enum(_) => true, KindIndex::String | KindIndex::Bytes | KindIndex::Message(_) | KindIndex::Group(_) => { false } } } fn is_message(&self) -> bool { matches!(self, KindIndex::Message(_) | KindIndex::Group(_)) } } impl fmt::Debug for KindIndex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { KindIndex::Double => write!(f, "double"), KindIndex::Float => write!(f, "float"), KindIndex::Int32 => write!(f, "int32"), KindIndex::Int64 => write!(f, "int64"), KindIndex::Uint32 => write!(f, "uint32"), KindIndex::Uint64 => write!(f, "uint64"), KindIndex::Sint32 => write!(f, "sint32"), KindIndex::Sint64 => write!(f, "sint64"), KindIndex::Fixed32 => write!(f, "fixed32"), KindIndex::Fixed64 => write!(f, "fixed64"), KindIndex::Sfixed32 => write!(f, "sfixed32"), KindIndex::Sfixed64 => write!(f, "sfixed64"), KindIndex::Bool => write!(f, "bool"), KindIndex::String => write!(f, "string"), KindIndex::Bytes => write!(f, "bytes"), KindIndex::Message(_) | KindIndex::Group(_) => write!(f, "message"), KindIndex::Enum(_) => write!(f, "enum"), } } } impl DefinitionKind { fn is_parent(&self) -> bool { match self { DefinitionKind::Package => true, DefinitionKind::Message(_) => true, DefinitionKind::Field(_) => false, DefinitionKind::Oneof(_) => false, DefinitionKind::Service(_) => true, DefinitionKind::Method(_) => false, DefinitionKind::Enum(_) => true, DefinitionKind::EnumValue(_) => false, DefinitionKind::Extension(_) => false, } } } impl DescriptorPoolInner { fn get_by_name(&self, name: &str) -> Option<&Definition> { let name = name.strip_prefix('.').unwrap_or(name); self.names.get(name) } } fn to_index(i: usize) -> DescriptorIndex { i.try_into().expect("index too large") } fn find_message_proto<'a>(file: &'a FileDescriptorProto, path: &[i32]) -> &'a DescriptorProto { debug_assert_ne!(path.len(), 0); debug_assert_eq!(path.len() % 2, 0); let mut message: Option<&'a types::DescriptorProto> = None; for part in path.chunks(2) { match part[0] { tag::file::MESSAGE_TYPE => message = Some(&file.message_type[part[1] as usize]), tag::message::NESTED_TYPE => { message = Some(&message.unwrap().nested_type[part[1] as usize]) } _ => panic!("invalid message path"), } } message.unwrap() } fn find_enum_proto<'a>(file: &'a FileDescriptorProto, path: &[i32]) -> &'a EnumDescriptorProto { debug_assert_ne!(path.len(), 0); debug_assert_eq!(path.len() % 2, 0); if path.len() == 2 { debug_assert_eq!(path[0], tag::file::ENUM_TYPE); &file.enum_type[path[1] as usize] } else { let message = find_message_proto(file, &path[..path.len() - 2]); debug_assert_eq!(path[path.len() - 2], tag::message::ENUM_TYPE); &message.enum_type[path[path.len() - 1] as usize] } } #[test] fn assert_descriptor_send_sync() { fn test_send_sync() {} test_send_sync::(); test_send_sync::(); test_send_sync::(); } prost-reflect-0.15.0/src/descriptor/tag.rs000064400000000000000000000124101046102023000165640ustar 00000000000000#![allow(dead_code)] pub(crate) const UNINTERPRETED_OPTION: i32 = 999; pub(crate) mod file_descriptor_set { pub(crate) const FILE: i32 = 1; } pub(crate) mod file { pub(crate) const PACKAGE: i32 = 2; pub(crate) const DEPENDENCY: i32 = 3; pub(crate) const PUBLIC_DEPENDENCY: i32 = 10; pub(crate) const WEAK_DEPENDENCY: i32 = 11; pub(crate) const MESSAGE_TYPE: i32 = 4; pub(crate) const ENUM_TYPE: i32 = 5; pub(crate) const SERVICE: i32 = 6; pub(crate) const EXTENSION: i32 = 7; pub(crate) const OPTIONS: i32 = 8; pub(crate) const SYNTAX: i32 = 12; pub(crate) mod options { pub(crate) const JAVA_PACKAGE: i32 = 1; pub(crate) const JAVA_OUTER_CLASSNAME: i32 = 8; pub(crate) const JAVA_MULTIPLE_FILES: i32 = 10; pub(crate) const JAVA_GENERATE_EQUALS_AND_HASH: i32 = 20; pub(crate) const JAVA_STRING_CHECK_UTF8: i32 = 27; pub(crate) const OPTIMIZE_FOR: i32 = 9; pub(crate) const GO_PACKAGE: i32 = 11; pub(crate) const CC_GENERIC_SERVICES: i32 = 16; pub(crate) const JAVA_GENERIC_SERVICES: i32 = 17; pub(crate) const PY_GENERIC_SERVICES: i32 = 18; pub(crate) const PHP_GENERIC_SERVICES: i32 = 42; pub(crate) const DEPRECATED: i32 = 23; pub(crate) const CC_ENABLE_ARENAS: i32 = 31; pub(crate) const OBJC_CLASS_PREFIX: i32 = 36; pub(crate) const CSHARP_NAMESPACE: i32 = 37; pub(crate) const SWIFT_PREFIX: i32 = 39; pub(crate) const PHP_CLASS_PREFIX: i32 = 40; pub(crate) const PHP_NAMESPACE: i32 = 41; pub(crate) const PHP_METADATA_NAMESPACE: i32 = 44; pub(crate) const RUBY_PACKAGE: i32 = 45; pub(crate) const FILE_UNINTERPRETED_OPTION: i32 = 999; } } pub(crate) mod message { pub(crate) const NAME: i32 = 1; pub(crate) const FIELD: i32 = 2; pub(crate) const EXTENSION: i32 = 6; pub(crate) const NESTED_TYPE: i32 = 3; pub(crate) const ENUM_TYPE: i32 = 4; pub(crate) const EXTENSION_RANGE: i32 = 5; pub(crate) const OPTIONS: i32 = 7; pub(crate) const ONEOF_DECL: i32 = 8; pub(crate) const RESERVED_RANGE: i32 = 9; pub(crate) const RESERVED_NAME: i32 = 10; pub(crate) mod extension_range { pub(crate) const START: i32 = 1; pub(crate) const END: i32 = 2; pub(crate) const OPTIONS: i32 = 3; } pub(crate) mod reserved_range { pub(crate) const START: i32 = 1; pub(crate) const END: i32 = 2; } pub(crate) mod options { pub(crate) const MESSAGE_SET_WIRE_FORMAT: i32 = 1; pub(crate) const NO_STANDARD_DESCRIPTOR_ACCESSOR: i32 = 2; pub(crate) const DEPRECATED: i32 = 3; pub(crate) const MAP_ENTRY: i32 = 7; pub(crate) const UNINTERPRETED_OPTION: i32 = 999; } } pub(crate) mod field { pub(crate) const NAME: i32 = 1; pub(crate) const EXTENDEE: i32 = 2; pub(crate) const NUMBER: i32 = 3; pub(crate) const LABEL: i32 = 4; pub(crate) const TYPE: i32 = 5; pub(crate) const TYPE_NAME: i32 = 6; pub(crate) const DEFAULT_VALUE: i32 = 7; pub(crate) const JSON_NAME: i32 = 10; pub(crate) const OPTIONS: i32 = 8; pub(crate) mod options { pub(crate) const CTYPE: i32 = 1; pub(crate) const PACKED: i32 = 2; pub(crate) const JSTYPE: i32 = 6; pub(crate) const LAZY: i32 = 5; pub(crate) const DEPRECATED: i32 = 3; pub(crate) const WEAK: i32 = 10; pub(crate) const UNINTERPRETED_OPTION: i32 = 999; } } pub(crate) mod oneof { pub(crate) const NAME: i32 = 1; pub(crate) const OPTIONS: i32 = 2; } pub(crate) mod enum_ { pub(crate) const NAME: i32 = 1; pub(crate) const VALUE: i32 = 2; pub(crate) const OPTIONS: i32 = 3; pub(crate) const RESERVED_RANGE: i32 = 4; pub(crate) const RESERVED_NAME: i32 = 5; pub(crate) mod reserved_range { pub(crate) const START: i32 = 1; pub(crate) const END: i32 = 2; } pub(crate) mod options { pub(crate) const ALLOW_ALIAS: i32 = 2; pub(crate) const DEPRECATED: i32 = 3; pub(crate) const UNINTERPRETED_OPTION: i32 = 999; } } pub(crate) mod enum_value { pub(crate) const NAME: i32 = 1; pub(crate) const NUMBER: i32 = 2; pub(crate) const OPTIONS: i32 = 3; pub(crate) mod options { pub(crate) const DEPRECATED: i32 = 1; pub(crate) const UNINTERPRETED_OPTION: i32 = 999; } } pub(crate) mod service { pub(crate) const NAME: i32 = 1; pub(crate) const METHOD: i32 = 2; pub(crate) const OPTIONS: i32 = 3; pub(crate) mod options { pub(crate) const DEPRECATED: i32 = 33; pub(crate) const UNINTERPRETED_OPTION: i32 = 999; } } pub(crate) mod method { pub(crate) const NAME: i32 = 1; pub(crate) const INPUT_TYPE: i32 = 2; pub(crate) const OUTPUT_TYPE: i32 = 3; pub(crate) const OPTIONS: i32 = 4; pub(crate) const CLIENT_STREAMING: i32 = 5; pub(crate) const SERVER_STREAMING: i32 = 6; pub(crate) mod options { pub(crate) const DEPRECATED: i32 = 33; pub(crate) const IDEMPOTENCY_LEVEL: i32 = 34; pub(crate) const UNINTERPRETED_OPTION: i32 = 999; } } prost-reflect-0.15.0/src/descriptor/types.rs000064400000000000000000000463041046102023000171660ustar 00000000000000use std::fmt; use prost::{ bytes::{Buf, BufMut}, encoding::{encode_key, skip_field, DecodeContext, WireType}, DecodeError, Message, }; pub(crate) use prost_types::{ enum_descriptor_proto, field_descriptor_proto, uninterpreted_option, EnumOptions, EnumValueOptions, ExtensionRangeOptions, FieldOptions, FileOptions, MessageOptions, MethodOptions, OneofOptions, ServiceOptions, SourceCodeInfo, UninterpretedOption, }; #[derive(Clone, PartialEq, Message)] pub(crate) struct FileDescriptorSet { #[prost(message, repeated, tag = "1")] pub file: Vec, } #[derive(Clone, PartialEq, Message)] pub(crate) struct FileDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(string, optional, tag = "2")] pub package: Option, #[prost(string, repeated, tag = "3")] pub dependency: Vec, #[prost(int32, repeated, packed = "false", tag = "10")] pub public_dependency: Vec, #[prost(int32, repeated, packed = "false", tag = "11")] pub weak_dependency: Vec, #[prost(message, repeated, tag = "4")] pub message_type: Vec, #[prost(message, repeated, tag = "5")] pub(crate) enum_type: Vec, #[prost(message, repeated, tag = "6")] pub service: Vec, #[prost(message, repeated, tag = "7")] pub extension: Vec, #[prost(message, optional, tag = "8")] pub options: Option>, #[prost(message, optional, tag = "9")] pub source_code_info: Option, #[prost(string, optional, tag = "12")] pub syntax: Option, } #[derive(Clone, PartialEq, Message)] pub(crate) struct DescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(message, repeated, tag = "2")] pub field: Vec, #[prost(message, repeated, tag = "6")] pub extension: Vec, #[prost(message, repeated, tag = "3")] pub nested_type: Vec, #[prost(message, repeated, tag = "4")] pub(crate) enum_type: Vec, #[prost(message, repeated, tag = "5")] pub extension_range: Vec, #[prost(message, repeated, tag = "8")] pub oneof_decl: Vec, #[prost(message, optional, tag = "7")] pub options: Option>, #[prost(message, repeated, tag = "9")] pub reserved_range: Vec, #[prost(string, repeated, tag = "10")] pub reserved_name: Vec, } pub(crate) mod descriptor_proto { pub(crate) use prost_types::descriptor_proto::ReservedRange; use super::*; #[derive(Clone, PartialEq, Message)] pub(crate) struct ExtensionRange { #[prost(int32, optional, tag = "1")] pub start: Option, #[prost(int32, optional, tag = "2")] pub end: Option, #[prost(message, optional, tag = "3")] pub options: Option>, } } #[derive(Clone, PartialEq, Message)] pub(crate) struct FieldDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(int32, optional, tag = "3")] pub number: Option, #[prost(enumeration = "field_descriptor_proto::Label", optional, tag = "4")] pub label: Option, #[prost(enumeration = "field_descriptor_proto::Type", optional, tag = "5")] pub r#type: Option, #[prost(string, optional, tag = "6")] pub type_name: Option, #[prost(string, optional, tag = "2")] pub extendee: Option, #[prost(string, optional, tag = "7")] pub default_value: Option, #[prost(int32, optional, tag = "9")] pub oneof_index: Option, #[prost(string, optional, tag = "10")] pub json_name: Option, #[prost(message, optional, tag = "8")] pub options: Option>, #[prost(bool, optional, tag = "17")] pub proto3_optional: Option, } #[derive(Clone, PartialEq, Message)] pub(crate) struct OneofDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(message, optional, tag = "2")] pub options: Option>, } #[derive(Clone, PartialEq, Message)] pub(crate) struct EnumDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(message, repeated, tag = "2")] pub value: Vec, #[prost(message, optional, tag = "3")] pub options: Option>, #[prost(message, repeated, tag = "4")] pub reserved_range: Vec, #[prost(string, repeated, tag = "5")] pub reserved_name: Vec, } #[derive(Clone, PartialEq, Message)] pub(crate) struct EnumValueDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(int32, optional, tag = "2")] pub number: Option, #[prost(message, optional, tag = "3")] pub options: Option>, } #[derive(Clone, PartialEq, Message)] pub(crate) struct ServiceDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(message, repeated, tag = "2")] pub method: Vec, #[prost(message, optional, tag = "3")] pub options: Option>, } #[derive(Clone, PartialEq, Message)] pub(crate) struct MethodDescriptorProto { #[prost(string, optional, tag = "1")] pub name: Option, #[prost(string, optional, tag = "2")] pub input_type: Option, #[prost(string, optional, tag = "3")] pub output_type: Option, #[prost(message, optional, tag = "4")] pub options: Option>, #[prost(bool, optional, tag = "5", default = "false")] pub client_streaming: Option, #[prost(bool, optional, tag = "6", default = "false")] pub server_streaming: Option, } #[derive(Clone, Default, PartialEq)] pub(crate) struct Options { pub(crate) encoded: Vec, pub(crate) value: T, } impl FileDescriptorProto { pub(crate) fn from_prost(file: prost_types::FileDescriptorProto) -> FileDescriptorProto { FileDescriptorProto { name: file.name, package: file.package, dependency: file.dependency, public_dependency: file.public_dependency, weak_dependency: file.weak_dependency, message_type: file .message_type .into_iter() .map(DescriptorProto::from_prost) .collect(), enum_type: file .enum_type .into_iter() .map(EnumDescriptorProto::from_prost) .collect(), service: file .service .into_iter() .map(ServiceDescriptorProto::from_prost) .collect(), extension: file .extension .into_iter() .map(FieldDescriptorProto::from_prost) .collect(), options: file.options.map(Options::from_prost), source_code_info: file.source_code_info, syntax: file.syntax, } } pub(crate) fn to_prost(&self) -> prost_types::FileDescriptorProto { prost_types::FileDescriptorProto { name: self.name.clone(), package: self.package.clone(), dependency: self.dependency.clone(), public_dependency: self.public_dependency.clone(), weak_dependency: self.weak_dependency.clone(), message_type: self .message_type .iter() .map(DescriptorProto::to_prost) .collect(), enum_type: self .enum_type .iter() .map(EnumDescriptorProto::to_prost) .collect(), service: self .service .iter() .map(ServiceDescriptorProto::to_prost) .collect(), extension: self .extension .iter() .map(FieldDescriptorProto::to_prost) .collect(), options: self.options.as_ref().map(Options::to_prost), source_code_info: self.source_code_info.clone(), syntax: self.syntax.clone(), } } } impl DescriptorProto { pub(crate) fn from_prost(file: prost_types::DescriptorProto) -> DescriptorProto { DescriptorProto { name: file.name, field: file .field .into_iter() .map(FieldDescriptorProto::from_prost) .collect(), extension: file .extension .into_iter() .map(FieldDescriptorProto::from_prost) .collect(), nested_type: file .nested_type .into_iter() .map(DescriptorProto::from_prost) .collect(), enum_type: file .enum_type .into_iter() .map(EnumDescriptorProto::from_prost) .collect(), extension_range: file .extension_range .into_iter() .map(descriptor_proto::ExtensionRange::from_prost) .collect(), oneof_decl: file .oneof_decl .into_iter() .map(OneofDescriptorProto::from_prost) .collect(), options: file.options.map(Options::from_prost), reserved_range: file.reserved_range, reserved_name: file.reserved_name, } } pub(crate) fn to_prost(&self) -> prost_types::DescriptorProto { prost_types::DescriptorProto { name: self.name.clone(), field: self .field .iter() .map(FieldDescriptorProto::to_prost) .collect(), extension: self .extension .iter() .map(FieldDescriptorProto::to_prost) .collect(), nested_type: self .nested_type .iter() .map(DescriptorProto::to_prost) .collect(), enum_type: self .enum_type .iter() .map(EnumDescriptorProto::to_prost) .collect(), extension_range: self .extension_range .iter() .map(descriptor_proto::ExtensionRange::to_prost) .collect(), oneof_decl: self .oneof_decl .iter() .map(OneofDescriptorProto::to_prost) .collect(), options: self.options.as_ref().map(Options::to_prost), reserved_range: self.reserved_range.clone(), reserved_name: self.reserved_name.clone(), } } } impl FieldDescriptorProto { pub(crate) fn from_prost(file: prost_types::FieldDescriptorProto) -> FieldDescriptorProto { FieldDescriptorProto { name: file.name, number: file.number, label: file.label, r#type: file.r#type, type_name: file.type_name, extendee: file.extendee, default_value: file.default_value, oneof_index: file.oneof_index, json_name: file.json_name, options: file.options.map(Options::from_prost), proto3_optional: file.proto3_optional, } } pub(crate) fn to_prost(&self) -> prost_types::FieldDescriptorProto { prost_types::FieldDescriptorProto { name: self.name.clone(), number: self.number, label: self.label, r#type: self.r#type, type_name: self.type_name.clone(), extendee: self.extendee.clone(), default_value: self.default_value.clone(), oneof_index: self.oneof_index, json_name: self.json_name.clone(), options: self.options.as_ref().map(Options::to_prost), proto3_optional: self.proto3_optional, } } } impl OneofDescriptorProto { pub(crate) fn from_prost(file: prost_types::OneofDescriptorProto) -> OneofDescriptorProto { OneofDescriptorProto { name: file.name, options: file.options.map(Options::from_prost), } } pub(crate) fn to_prost(&self) -> prost_types::OneofDescriptorProto { prost_types::OneofDescriptorProto { name: self.name.clone(), options: self.options.as_ref().map(Options::to_prost), } } } impl descriptor_proto::ExtensionRange { pub(crate) fn from_prost( file: prost_types::descriptor_proto::ExtensionRange, ) -> descriptor_proto::ExtensionRange { descriptor_proto::ExtensionRange { start: file.start, end: file.end, options: file.options.map(Options::from_prost), } } pub(crate) fn to_prost(&self) -> prost_types::descriptor_proto::ExtensionRange { prost_types::descriptor_proto::ExtensionRange { start: self.start, end: self.end, options: self.options.as_ref().map(Options::to_prost), } } } impl EnumDescriptorProto { pub(crate) fn from_prost(file: prost_types::EnumDescriptorProto) -> EnumDescriptorProto { EnumDescriptorProto { name: file.name, value: file .value .into_iter() .map(EnumValueDescriptorProto::from_prost) .collect(), options: file.options.map(Options::from_prost), reserved_range: file.reserved_range, reserved_name: file.reserved_name, } } pub(crate) fn to_prost(&self) -> prost_types::EnumDescriptorProto { prost_types::EnumDescriptorProto { name: self.name.clone(), value: self .value .iter() .map(EnumValueDescriptorProto::to_prost) .collect(), options: self.options.as_ref().map(Options::to_prost), reserved_range: self.reserved_range.clone(), reserved_name: self.reserved_name.clone(), } } } impl EnumValueDescriptorProto { pub(crate) fn from_prost( file: prost_types::EnumValueDescriptorProto, ) -> EnumValueDescriptorProto { EnumValueDescriptorProto { name: file.name, number: file.number, options: file.options.map(Options::from_prost), } } pub(crate) fn to_prost(&self) -> prost_types::EnumValueDescriptorProto { prost_types::EnumValueDescriptorProto { name: self.name.clone(), number: self.number, options: self.options.as_ref().map(Options::to_prost), } } } impl ServiceDescriptorProto { pub(crate) fn from_prost(file: prost_types::ServiceDescriptorProto) -> ServiceDescriptorProto { ServiceDescriptorProto { name: file.name, method: file .method .into_iter() .map(MethodDescriptorProto::from_prost) .collect(), options: file.options.map(Options::from_prost), } } pub(crate) fn to_prost(&self) -> prost_types::ServiceDescriptorProto { prost_types::ServiceDescriptorProto { name: self.name.clone(), method: self .method .iter() .map(MethodDescriptorProto::to_prost) .collect(), options: self.options.as_ref().map(Options::to_prost), } } } impl MethodDescriptorProto { pub(crate) fn from_prost(file: prost_types::MethodDescriptorProto) -> MethodDescriptorProto { MethodDescriptorProto { name: file.name, input_type: file.input_type, output_type: file.output_type, options: file.options.map(Options::from_prost), client_streaming: file.client_streaming, server_streaming: file.server_streaming, } } pub(crate) fn to_prost(&self) -> prost_types::MethodDescriptorProto { prost_types::MethodDescriptorProto { name: self.name.clone(), input_type: self.input_type.clone(), output_type: self.output_type.clone(), options: self.options.as_ref().map(Options::to_prost), client_streaming: self.client_streaming, server_streaming: self.server_streaming, } } } impl Options where T: Message + Clone, { pub(crate) fn from_prost(options: T) -> Self { Options { encoded: options.encode_to_vec(), value: options, } } fn to_prost(&self) -> T { self.value.clone() } } impl fmt::Debug for Options where T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.value.fmt(f) } } impl Message for Options where T: Message + Default, { fn encode_raw(&self, buf: &mut impl BufMut) where Self: Sized, { buf.put(self.encoded.as_slice()); } fn merge_field( &mut self, tag: u32, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext, ) -> Result<(), DecodeError> where Self: Sized, { struct CopyBufAdapter<'a, B> { dest: &'a mut Vec, src: &'a mut B, } impl Buf for CopyBufAdapter<'_, B> where B: Buf, { fn advance(&mut self, cnt: usize) { self.dest.put((&mut self.src).take(cnt)); } fn chunk(&self) -> &[u8] { self.src.chunk() } fn remaining(&self) -> usize { self.src.remaining() } } encode_key(tag, wire_type, &mut self.encoded); let start = self.encoded.len(); skip_field( wire_type, tag, &mut CopyBufAdapter { dest: &mut self.encoded, src: buf, }, ctx.clone(), )?; self.value .merge_field(tag, wire_type, &mut &self.encoded[start..], ctx)?; Ok(()) } fn encoded_len(&self) -> usize { self.encoded.len() } fn clear(&mut self) { self.encoded.clear(); self.value.clear(); } } prost-reflect-0.15.0/src/dynamic/fields.rs000064400000000000000000000361621046102023000165370ustar 00000000000000use std::{ borrow::Cow, collections::btree_map::{self, BTreeMap}, fmt, mem::replace, }; use crate::{ ExtensionDescriptor, FieldDescriptor, Kind, MessageDescriptor, OneofDescriptor, Value, }; use super::{ unknown::{UnknownField, UnknownFieldSet}, Either, }; pub(crate) trait FieldDescriptorLike: fmt::Debug { #[cfg(feature = "text-format")] fn text_name(&self) -> &str; fn number(&self) -> u32; fn default_value(&self) -> Value; fn is_default_value(&self, value: &Value) -> bool; fn is_valid(&self, value: &Value) -> bool; fn containing_oneof(&self) -> Option; fn supports_presence(&self) -> bool; fn kind(&self) -> Kind; fn is_group(&self) -> bool; fn is_list(&self) -> bool; fn is_map(&self) -> bool; fn is_packed(&self) -> bool; fn is_packable(&self) -> bool; fn has(&self, value: &Value) -> bool { self.supports_presence() || !self.is_default_value(value) } } /// A set of extension fields in a protobuf message. #[derive(Default, Debug, Clone, PartialEq)] pub(super) struct DynamicMessageFieldSet { fields: BTreeMap, } #[derive(Debug, Clone, PartialEq)] pub(super) enum ValueOrUnknown { /// Used to implement draining iterators. Taken, /// A protobuf value with known field type. Value(Value), /// One or more unknown fields. Unknown(UnknownFieldSet), } pub(super) enum ValueAndDescriptor<'a> { Field(Cow<'a, Value>, FieldDescriptor), Extension(Cow<'a, Value>, ExtensionDescriptor), Unknown(&'a UnknownFieldSet), } impl DynamicMessageFieldSet { fn get_value(&self, number: u32) -> Option<&Value> { match self.fields.get(&number) { Some(ValueOrUnknown::Value(value)) => Some(value), Some(ValueOrUnknown::Unknown(_) | ValueOrUnknown::Taken) | None => None, } } pub(super) fn has(&self, desc: &impl FieldDescriptorLike) -> bool { self.get_value(desc.number()) .map(|value| desc.has(value)) .unwrap_or(false) } pub(super) fn get(&self, desc: &impl FieldDescriptorLike) -> Cow<'_, Value> { match self.get_value(desc.number()) { Some(value) => Cow::Borrowed(value), None => Cow::Owned(desc.default_value()), } } pub(super) fn get_mut(&mut self, desc: &impl FieldDescriptorLike) -> &mut Value { self.clear_oneof_fields(desc); match self.fields.entry(desc.number()) { btree_map::Entry::Occupied(entry) => match entry.into_mut() { ValueOrUnknown::Value(value) => value, value => { *value = ValueOrUnknown::Value(desc.default_value()); value.unwrap_value_mut() } }, btree_map::Entry::Vacant(entry) => entry .insert(ValueOrUnknown::Value(desc.default_value())) .unwrap_value_mut(), } } pub(super) fn set(&mut self, desc: &impl FieldDescriptorLike, value: Value) { debug_assert!( desc.is_valid(&value), "invalid value {:?} for field {:?}", value, desc, ); self.clear_oneof_fields(desc); self.fields .insert(desc.number(), ValueOrUnknown::Value(value)); } fn clear_oneof_fields(&mut self, desc: &impl FieldDescriptorLike) { if let Some(oneof_desc) = desc.containing_oneof() { for oneof_field in oneof_desc.fields() { if oneof_field.number() != desc.number() { self.clear(&oneof_field); } } } } pub(crate) fn add_unknown(&mut self, number: u32, unknown: UnknownField) { match self.fields.entry(number) { btree_map::Entry::Occupied(mut entry) => match entry.get_mut() { ValueOrUnknown::Value(_) => { panic!("expected no field to be found with number {}", number) } value @ ValueOrUnknown::Taken => { *value = ValueOrUnknown::Unknown(UnknownFieldSet::from_iter([unknown])) } ValueOrUnknown::Unknown(unknowns) => unknowns.insert(unknown), }, btree_map::Entry::Vacant(entry) => { entry.insert(ValueOrUnknown::Unknown(UnknownFieldSet::from_iter([ unknown, ]))); } } } pub(super) fn clear(&mut self, desc: &impl FieldDescriptorLike) { self.fields.remove(&desc.number()); } pub(crate) fn take(&mut self, desc: &impl FieldDescriptorLike) -> Option { match self.fields.remove(&desc.number()) { Some(ValueOrUnknown::Value(value)) if desc.has(&value) => Some(value), _ => None, } } /// Iterates over the fields in the message. /// /// If `include_default` is `true`, fields with their default value will be included. /// If `index_order` is `true`, fields will be iterated in the order they were defined in the source code. Otherwise, they will be iterated in field number order. pub(crate) fn iter<'a>( &'a self, message: &'a MessageDescriptor, include_default: bool, index_order: bool, ) -> impl Iterator> + 'a { let field_descriptors = if index_order { Either::Left(message.fields_in_index_order()) } else { Either::Right(message.fields()) }; let fields = field_descriptors .filter(move |f| { if include_default { !f.supports_presence() || self.has(f) } else { self.has(f) } }) .map(|f| ValueAndDescriptor::Field(self.get(&f), f)); let extensions_unknowns = self.fields .iter() .filter_map(move |(&number, value)| match value { ValueOrUnknown::Value(value) => { if let Some(extension) = message.get_extension(number) { if extension.has(value) { Some(ValueAndDescriptor::Extension( Cow::Borrowed(value), extension, )) } else { None } } else { None } } ValueOrUnknown::Unknown(unknown) => Some(ValueAndDescriptor::Unknown(unknown)), ValueOrUnknown::Taken => None, }); fields.chain(extensions_unknowns) } pub(crate) fn iter_fields<'a>( &'a self, message: &'a MessageDescriptor, ) -> impl Iterator + 'a { self.fields.iter().filter_map(move |(&number, value)| { let value = match value { ValueOrUnknown::Value(value) => value, _ => return None, }; let field = match message.get_field(number) { Some(field) => field, _ => return None, }; if field.has(value) { Some((field, value)) } else { None } }) } pub(crate) fn iter_extensions<'a>( &'a self, message: &'a MessageDescriptor, ) -> impl Iterator + 'a { self.fields.iter().filter_map(move |(&number, value)| { let value = match value { ValueOrUnknown::Value(value) => value, _ => return None, }; let field = match message.get_extension(number) { Some(field) => field, _ => return None, }; if field.has(value) { Some((field, value)) } else { None } }) } pub(super) fn iter_unknown(&self) -> impl Iterator { self.fields.values().flat_map(move |value| match value { ValueOrUnknown::Taken | ValueOrUnknown::Value(_) => [].iter(), ValueOrUnknown::Unknown(unknowns) => unknowns.iter(), }) } pub(crate) fn iter_fields_mut<'a>( &'a mut self, message: &'a MessageDescriptor, ) -> impl Iterator + 'a { self.fields.iter_mut().filter_map(move |(&number, value)| { let value = match value { ValueOrUnknown::Value(value) => value, _ => return None, }; let field = match message.get_field(number) { Some(field) => field, _ => return None, }; if field.has(value) { Some((field, value)) } else { None } }) } pub(crate) fn iter_extensions_mut<'a>( &'a mut self, message: &'a MessageDescriptor, ) -> impl Iterator + 'a { self.fields.iter_mut().filter_map(move |(&number, value)| { let value = match value { ValueOrUnknown::Value(value) => value, _ => return None, }; let field = match message.get_extension(number) { Some(field) => field, _ => return None, }; if field.has(value) { Some((field, value)) } else { None } }) } pub(crate) fn take_fields<'a>( &'a mut self, message: &'a MessageDescriptor, ) -> impl Iterator + 'a { self.fields .iter_mut() .filter_map(move |(&number, value_or_unknown)| { let value = match value_or_unknown { ValueOrUnknown::Value(value) => value, _ => return None, }; let field = match message.get_field(number) { Some(field) => field, _ => return None, }; if field.has(value) { Some(( field, replace(value_or_unknown, ValueOrUnknown::Taken).unwrap_value(), )) } else { None } }) } pub(crate) fn take_extensions<'a>( &'a mut self, message: &'a MessageDescriptor, ) -> impl Iterator + 'a { self.fields .iter_mut() .filter_map(move |(&number, value_or_unknown)| { let value = match value_or_unknown { ValueOrUnknown::Value(value) => value, _ => return None, }; let field = match message.get_extension(number) { Some(field) => field, _ => return None, }; if field.has(value) { Some(( field, replace(value_or_unknown, ValueOrUnknown::Taken).unwrap_value(), )) } else { None } }) } pub(crate) fn take_unknown(&mut self) -> impl Iterator + '_ { self.fields .values_mut() .flat_map(move |value_or_unknown| match value_or_unknown { ValueOrUnknown::Unknown(_) => replace(value_or_unknown, ValueOrUnknown::Taken) .unwrap_unknown() .into_iter(), _ => vec![].into_iter(), }) } pub(super) fn clear_all(&mut self) { self.fields.clear(); } } impl ValueOrUnknown { fn unwrap_value_mut(&mut self) -> &mut Value { match self { ValueOrUnknown::Value(value) => value, ValueOrUnknown::Unknown(_) | ValueOrUnknown::Taken => unreachable!(), } } fn unwrap_value(self) -> Value { match self { ValueOrUnknown::Value(value) => value, ValueOrUnknown::Unknown(_) | ValueOrUnknown::Taken => unreachable!(), } } fn unwrap_unknown(self) -> UnknownFieldSet { match self { ValueOrUnknown::Unknown(unknowns) => unknowns, ValueOrUnknown::Value(_) | ValueOrUnknown::Taken => unreachable!(), } } } impl FieldDescriptorLike for FieldDescriptor { #[cfg(feature = "text-format")] fn text_name(&self) -> &str { self.name() } fn number(&self) -> u32 { self.number() } fn default_value(&self) -> Value { Value::default_value_for_field(self) } fn is_default_value(&self, value: &Value) -> bool { value.is_default_for_field(self) } fn is_valid(&self, value: &Value) -> bool { value.is_valid_for_field(self) } fn containing_oneof(&self) -> Option { self.containing_oneof() } fn supports_presence(&self) -> bool { self.supports_presence() } fn kind(&self) -> Kind { self.kind() } fn is_group(&self) -> bool { self.is_group() } fn is_list(&self) -> bool { self.is_list() } fn is_map(&self) -> bool { self.is_map() } fn is_packed(&self) -> bool { self.is_packed() } fn is_packable(&self) -> bool { self.is_packable() } } impl FieldDescriptorLike for ExtensionDescriptor { #[cfg(feature = "text-format")] fn text_name(&self) -> &str { self.json_name() } fn number(&self) -> u32 { self.number() } fn default_value(&self) -> Value { Value::default_value_for_extension(self) } fn is_default_value(&self, value: &Value) -> bool { value.is_default_for_extension(self) } fn is_valid(&self, value: &Value) -> bool { value.is_valid_for_extension(self) } fn containing_oneof(&self) -> Option { None } fn supports_presence(&self) -> bool { self.supports_presence() } fn kind(&self) -> Kind { self.kind() } fn is_group(&self) -> bool { self.is_group() } fn is_list(&self) -> bool { self.is_list() } fn is_map(&self) -> bool { self.is_map() } fn is_packed(&self) -> bool { self.is_packed() } fn is_packable(&self) -> bool { self.is_packable() } } prost-reflect-0.15.0/src/dynamic/message.rs000064400000000000000000000775001046102023000167160ustar 00000000000000use prost::{ bytes::{Buf, BufMut}, encoding::{DecodeContext, WireType}, DecodeError, Message, }; use crate::{ descriptor::{FieldDescriptor, Kind, MAP_ENTRY_KEY_NUMBER, MAP_ENTRY_VALUE_NUMBER}, DynamicMessage, MapKey, Value, }; use super::{ fields::{FieldDescriptorLike, ValueAndDescriptor}, unknown::UnknownField, }; impl Message for DynamicMessage { fn encode_raw(&self, buf: &mut impl BufMut) where Self: Sized, { for field in self.fields.iter(&self.desc, false, false) { match field { ValueAndDescriptor::Field(value, field_desc) => { value.encode_field(&field_desc, buf) } ValueAndDescriptor::Extension(value, extension_desc) => { value.encode_field(&extension_desc, buf) } ValueAndDescriptor::Unknown(unknowns) => unknowns.encode_raw(buf), } } } fn merge_field( &mut self, number: u32, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext, ) -> Result<(), DecodeError> where Self: Sized, { if let Some(field_desc) = self.desc.get_field(number) { self.get_field_mut(&field_desc) .merge_field(&field_desc, wire_type, buf, ctx) } else if let Some(extension_desc) = self.desc.get_extension(number) { self.get_extension_mut(&extension_desc).merge_field( &extension_desc, wire_type, buf, ctx, ) } else { let field = UnknownField::decode_value(number, wire_type, buf, ctx)?; self.fields.add_unknown(number, field); Ok(()) } } fn encoded_len(&self) -> usize { let mut len = 0; for field in self.fields.iter(&self.desc, false, false) { match field { ValueAndDescriptor::Field(value, field_desc) => { len += value.encoded_len(&field_desc); } ValueAndDescriptor::Extension(value, extension_desc) => { len += value.encoded_len(&extension_desc); } ValueAndDescriptor::Unknown(unknowns) => len += unknowns.encoded_len(), } } len } fn clear(&mut self) { self.fields.clear_all(); } } impl Value { pub(super) fn encode_field(&self, field_desc: &impl FieldDescriptorLike, buf: &mut B) where B: BufMut, { if !field_desc.supports_presence() && field_desc.is_default_value(self) { return; } let number = field_desc.number(); match (self, field_desc.kind()) { (Value::Bool(value), Kind::Bool) => prost::encoding::bool::encode(number, value, buf), (Value::I32(value), Kind::Int32) => prost::encoding::int32::encode(number, value, buf), (Value::I32(value), Kind::Sint32) => { prost::encoding::sint32::encode(number, value, buf) } (Value::I32(value), Kind::Sfixed32) => { prost::encoding::sfixed32::encode(number, value, buf) } (Value::I64(value), Kind::Int64) => prost::encoding::int64::encode(number, value, buf), (Value::I64(value), Kind::Sint64) => { prost::encoding::sint64::encode(number, value, buf) } (Value::I64(value), Kind::Sfixed64) => { prost::encoding::sfixed64::encode(number, value, buf) } (Value::U32(value), Kind::Uint32) => { prost::encoding::uint32::encode(number, value, buf) } (Value::U32(value), Kind::Fixed32) => { prost::encoding::fixed32::encode(number, value, buf) } (Value::U64(value), Kind::Uint64) => { prost::encoding::uint64::encode(number, value, buf) } (Value::U64(value), Kind::Fixed64) => { prost::encoding::fixed64::encode(number, value, buf) } (Value::F32(value), Kind::Float) => prost::encoding::float::encode(number, value, buf), (Value::F64(value), Kind::Double) => { prost::encoding::double::encode(number, value, buf) } (Value::String(value), Kind::String) => { prost::encoding::string::encode(number, value, buf) } (Value::Bytes(value), Kind::Bytes) => { prost::encoding::bytes::encode(number, value, buf) } (Value::EnumNumber(value), Kind::Enum(_)) => { prost::encoding::int32::encode(number, value, buf) } (Value::Message(message), Kind::Message(_)) => { if field_desc.is_group() { prost::encoding::group::encode(number, message, buf) } else { prost::encoding::message::encode(number, message, buf) } } (Value::List(values), _) if field_desc.is_list() => { if field_desc.is_packed() { match field_desc.kind() { Kind::Enum(_) => encode_packed_list( number, values .iter() .map(|v| v.as_enum_number().expect("expected enum number")), buf, |v, b| prost::encoding::encode_varint(v as u64, b), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Double => encode_packed_list( number, values.iter().map(|v| v.as_f64().expect("expected double")), buf, |v, b| b.put_f64_le(v), |_| 8, ), Kind::Float => encode_packed_list( number, values.iter().map(|v| v.as_f32().expect("expected float")), buf, |v, b| b.put_f32_le(v), |_| 4, ), Kind::Int32 => encode_packed_list( number, values.iter().map(|v| v.as_i32().expect("expected i32")), buf, |v, b| prost::encoding::encode_varint(v as u64, b), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Int64 => encode_packed_list( number, values.iter().map(|v| v.as_i64().expect("expected i64")), buf, |v, b| prost::encoding::encode_varint(v as u64, b), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Uint32 => encode_packed_list( number, values.iter().map(|v| v.as_u32().expect("expected u32")), buf, |v, b| prost::encoding::encode_varint(v as u64, b), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Uint64 => encode_packed_list( number, values.iter().map(|v| v.as_u64().expect("expected u64")), buf, |v, b| prost::encoding::encode_varint(v, b), prost::encoding::encoded_len_varint, ), Kind::Sint32 => encode_packed_list( number, values.iter().map(|v| v.as_i32().expect("expected i32")), buf, |v, b| prost::encoding::encode_varint(from_sint32(v) as u64, b), |v| prost::encoding::encoded_len_varint(from_sint32(v) as u64), ), Kind::Sint64 => encode_packed_list( number, values.iter().map(|v| v.as_i64().expect("expected i64")), buf, |v, b| prost::encoding::encode_varint(from_sint64(v), b), |v| prost::encoding::encoded_len_varint(from_sint64(v)), ), Kind::Fixed32 => encode_packed_list( number, values.iter().map(|v| v.as_u32().expect("expected u32")), buf, |v, b| b.put_u32_le(v), |_| 4, ), Kind::Fixed64 => encode_packed_list( number, values.iter().map(|v| v.as_u64().expect("expected u64")), buf, |v, b| b.put_u64_le(v), |_| 8, ), Kind::Sfixed32 => encode_packed_list( number, values.iter().map(|v| v.as_i32().expect("expected i32")), buf, |v, b| b.put_i32_le(v), |_| 4, ), Kind::Sfixed64 => encode_packed_list( number, values.iter().map(|v| v.as_i64().expect("expected i64")), buf, |v, b| b.put_i64_le(v), |_| 8, ), Kind::Bool => encode_packed_list( number, values.iter().map(|v| v.as_bool().expect("expected bool")), buf, |v, b| prost::encoding::encode_varint(v as u64, b), |v| prost::encoding::encoded_len_varint(v as u64), ), _ => panic!("invalid type for packed field in DynamicMessage"), } } else { for value in values { value.encode_field(field_desc, buf); } } } (Value::Map(values), Kind::Message(map_entry)) if field_desc.is_map() => { let key_desc = map_entry.get_field(MAP_ENTRY_KEY_NUMBER).unwrap(); let value_desc = map_entry.get_field(MAP_ENTRY_VALUE_NUMBER).unwrap(); for (key, value) in values { let len = key.encoded_len(&key_desc) + value.encoded_len(&value_desc); prost::encoding::encode_key(number, WireType::LengthDelimited, buf); prost::encoding::encode_varint(len as u64, buf); key.encode_field(&key_desc, buf); value.encode_field(&value_desc, buf); } } (value, ty) => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", value, ty ), } } pub(super) fn merge_field( &mut self, field_desc: &impl FieldDescriptorLike, wire_type: WireType, buf: &mut B, ctx: DecodeContext, ) -> Result<(), DecodeError> where B: Buf, { match (self, field_desc.kind()) { (Value::Bool(value), Kind::Bool) => { prost::encoding::bool::merge(wire_type, value, buf, ctx) } (Value::I32(value), Kind::Int32) => { prost::encoding::int32::merge(wire_type, value, buf, ctx) } (Value::I32(value), Kind::Sint32) => { prost::encoding::sint32::merge(wire_type, value, buf, ctx) } (Value::I32(value), Kind::Sfixed32) => { prost::encoding::sfixed32::merge(wire_type, value, buf, ctx) } (Value::I64(value), Kind::Int64) => { prost::encoding::int64::merge(wire_type, value, buf, ctx) } (Value::I64(value), Kind::Sint64) => { prost::encoding::sint64::merge(wire_type, value, buf, ctx) } (Value::I64(value), Kind::Sfixed64) => { prost::encoding::sfixed64::merge(wire_type, value, buf, ctx) } (Value::U32(value), Kind::Uint32) => { prost::encoding::uint32::merge(wire_type, value, buf, ctx) } (Value::U32(value), Kind::Fixed32) => { prost::encoding::fixed32::merge(wire_type, value, buf, ctx) } (Value::U64(value), Kind::Uint64) => { prost::encoding::uint64::merge(wire_type, value, buf, ctx) } (Value::U64(value), Kind::Fixed64) => { prost::encoding::fixed64::merge(wire_type, value, buf, ctx) } (Value::F32(value), Kind::Float) => { prost::encoding::float::merge(wire_type, value, buf, ctx) } (Value::F64(value), Kind::Double) => { prost::encoding::double::merge(wire_type, value, buf, ctx) } (Value::String(value), Kind::String) => { prost::encoding::string::merge(wire_type, value, buf, ctx) } (Value::Bytes(value), Kind::Bytes) => { prost::encoding::bytes::merge(wire_type, value, buf, ctx) } (Value::EnumNumber(value), Kind::Enum(_)) => { prost::encoding::int32::merge(wire_type, value, buf, ctx) } (Value::Message(message), Kind::Message(_)) => { if field_desc.is_group() { prost::encoding::group::merge(field_desc.number(), wire_type, message, buf, ctx) } else { prost::encoding::message::merge(wire_type, message, buf, ctx) } } (Value::List(values), field_kind) if field_desc.is_list() => { if wire_type == WireType::LengthDelimited && field_desc.is_packable() { prost::encoding::merge_loop(values, buf, ctx, |values, buf, ctx| { let mut value = Value::default_value(&field_kind); value.merge_field(field_desc, field_kind.wire_type(), buf, ctx)?; values.push(value); Ok(()) }) } else { let mut value = Value::default_value(&field_kind); value.merge_field(field_desc, wire_type, buf, ctx)?; values.push(value); Ok(()) } } (Value::Map(values), Kind::Message(map_entry)) if field_desc.is_map() => { let key_desc = map_entry.get_field(MAP_ENTRY_KEY_NUMBER).unwrap(); let value_desc = map_entry.get_field(MAP_ENTRY_VALUE_NUMBER).unwrap(); let mut key = MapKey::default_value(&key_desc.kind()); let mut value = Value::default_value_for_field(&value_desc); prost::encoding::merge_loop( &mut (&mut key, &mut value), buf, ctx, |(key, value), buf, ctx| { let (number, wire_type) = prost::encoding::decode_key(buf)?; match number { MAP_ENTRY_KEY_NUMBER => key.merge_field(&key_desc, wire_type, buf, ctx), MAP_ENTRY_VALUE_NUMBER => { value.merge_field(&value_desc, wire_type, buf, ctx) } _ => prost::encoding::skip_field(wire_type, number, buf, ctx), } }, )?; values.insert(key, value); Ok(()) } (value, ty) => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", value, ty ), } } pub(super) fn encoded_len(&self, field_desc: &impl FieldDescriptorLike) -> usize { if !field_desc.supports_presence() && field_desc.is_default_value(self) { return 0; } let number = field_desc.number(); match (self, field_desc.kind()) { (Value::Bool(value), Kind::Bool) => prost::encoding::bool::encoded_len(number, value), (Value::I32(value), Kind::Int32) => prost::encoding::int32::encoded_len(number, value), (Value::I32(value), Kind::Sint32) => { prost::encoding::sint32::encoded_len(number, value) } (Value::I32(value), Kind::Sfixed32) => { prost::encoding::sfixed32::encoded_len(number, value) } (Value::I64(value), Kind::Int64) => prost::encoding::int64::encoded_len(number, value), (Value::I64(value), Kind::Sint64) => { prost::encoding::sint64::encoded_len(number, value) } (Value::I64(value), Kind::Sfixed64) => { prost::encoding::sfixed64::encoded_len(number, value) } (Value::U32(value), Kind::Uint32) => { prost::encoding::uint32::encoded_len(number, value) } (Value::U32(value), Kind::Fixed32) => { prost::encoding::fixed32::encoded_len(number, value) } (Value::U64(value), Kind::Uint64) => { prost::encoding::uint64::encoded_len(number, value) } (Value::U64(value), Kind::Fixed64) => { prost::encoding::fixed64::encoded_len(number, value) } (Value::F32(value), Kind::Float) => prost::encoding::float::encoded_len(number, value), (Value::F64(value), Kind::Double) => { prost::encoding::double::encoded_len(number, value) } (Value::String(value), Kind::String) => { prost::encoding::string::encoded_len(number, value) } (Value::Bytes(value), Kind::Bytes) => { prost::encoding::bytes::encoded_len(number, value) } (Value::EnumNumber(value), Kind::Enum(_)) => { prost::encoding::int32::encoded_len(number, value) } (Value::Message(message), Kind::Message(_)) => { if field_desc.is_group() { prost::encoding::group::encoded_len(number, message) } else { prost::encoding::message::encoded_len(number, message) } } (Value::List(values), _) if field_desc.is_list() => { if field_desc.is_packed() { match field_desc.kind() { Kind::Enum(_) => packed_list_encoded_len( number, values .iter() .map(|v| v.as_enum_number().expect("expected enum number")), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Double => packed_list_encoded_len( number, values.iter().map(|v| v.as_f64().expect("expected double")), |_| 8, ), Kind::Float => packed_list_encoded_len( number, values.iter().map(|v| v.as_f32().expect("expected float")), |_| 4, ), Kind::Int32 => packed_list_encoded_len( number, values.iter().map(|v| v.as_i32().expect("expected i32")), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Int64 => packed_list_encoded_len( number, values.iter().map(|v| v.as_i64().expect("expected i64")), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Uint32 => packed_list_encoded_len( number, values.iter().map(|v| v.as_u32().expect("expected u32")), |v| prost::encoding::encoded_len_varint(v as u64), ), Kind::Uint64 => packed_list_encoded_len( number, values.iter().map(|v| v.as_u64().expect("expected u64")), prost::encoding::encoded_len_varint, ), Kind::Sint32 => packed_list_encoded_len( number, values.iter().map(|v| v.as_i32().expect("expected i32")), |v| prost::encoding::encoded_len_varint(from_sint32(v) as u64), ), Kind::Sint64 => packed_list_encoded_len( number, values.iter().map(|v| v.as_i64().expect("expected i64")), |v| prost::encoding::encoded_len_varint(from_sint64(v)), ), Kind::Fixed32 => packed_list_encoded_len( number, values.iter().map(|v| v.as_u32().expect("expected u32")), |_| 4, ), Kind::Fixed64 => packed_list_encoded_len( number, values.iter().map(|v| v.as_u64().expect("expected u64")), |_| 8, ), Kind::Sfixed32 => packed_list_encoded_len( number, values.iter().map(|v| v.as_i32().expect("expected i32")), |_| 4, ), Kind::Sfixed64 => packed_list_encoded_len( number, values.iter().map(|v| v.as_i64().expect("expected i64")), |_| 8, ), Kind::Bool => packed_list_encoded_len( number, values.iter().map(|v| v.as_bool().expect("expected bool")), |v| prost::encoding::encoded_len_varint(v as u64), ), _ => panic!("invalid type for packed field in DynamicMessage"), } } else { values .iter() .map(|value| value.encoded_len(field_desc)) .sum() } } (Value::Map(values), Kind::Message(map_entry)) if field_desc.is_map() => { let key_desc = map_entry.map_entry_key_field(); let value_desc = map_entry.map_entry_value_field(); let key_len = prost::encoding::key_len(number); values .iter() .map(|(key, value)| { let len = key.encoded_len(&key_desc) + value.encoded_len(&value_desc); key_len + prost::encoding::encoded_len_varint(len as u64) + len }) .sum::() } (value, ty) => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", value, ty ), } } } impl MapKey { fn encode_field(&self, field_desc: &FieldDescriptor, buf: &mut B) where B: BufMut, { if !field_desc.supports_presence() && self.is_default(&field_desc.kind()) { return; } let number = field_desc.number(); match (self, field_desc.kind()) { (MapKey::Bool(value), Kind::Bool) => prost::encoding::bool::encode(number, value, buf), (MapKey::I32(value), Kind::Int32) => prost::encoding::int32::encode(number, value, buf), (MapKey::I32(value), Kind::Sint32) => { prost::encoding::sint32::encode(number, value, buf) } (MapKey::I32(value), Kind::Sfixed32) => { prost::encoding::sfixed32::encode(number, value, buf) } (MapKey::I64(value), Kind::Int64) => prost::encoding::int64::encode(number, value, buf), (MapKey::I64(value), Kind::Sint64) => { prost::encoding::sint64::encode(number, value, buf) } (MapKey::I64(value), Kind::Sfixed64) => { prost::encoding::sfixed64::encode(number, value, buf) } (MapKey::U32(value), Kind::Uint32) => { prost::encoding::uint32::encode(number, value, buf) } (MapKey::U32(value), Kind::Fixed32) => { prost::encoding::fixed32::encode(number, value, buf) } (MapKey::U64(value), Kind::Uint64) => { prost::encoding::uint64::encode(number, value, buf) } (MapKey::U64(value), Kind::Fixed64) => { prost::encoding::fixed64::encode(number, value, buf) } (MapKey::String(value), Kind::String) => { prost::encoding::string::encode(number, value, buf) } (value, ty) => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", value, ty ), } } fn merge_field( &mut self, field_desc: &FieldDescriptor, wire_type: WireType, buf: &mut B, ctx: DecodeContext, ) -> Result<(), DecodeError> where B: Buf, { match (self, field_desc.kind()) { (MapKey::Bool(value), Kind::Bool) => { prost::encoding::bool::merge(wire_type, value, buf, ctx) } (MapKey::I32(value), Kind::Int32) => { prost::encoding::int32::merge(wire_type, value, buf, ctx) } (MapKey::I32(value), Kind::Sint32) => { prost::encoding::sint32::merge(wire_type, value, buf, ctx) } (MapKey::I32(value), Kind::Sfixed32) => { prost::encoding::sfixed32::merge(wire_type, value, buf, ctx) } (MapKey::I64(value), Kind::Int64) => { prost::encoding::int64::merge(wire_type, value, buf, ctx) } (MapKey::I64(value), Kind::Sint64) => { prost::encoding::sint64::merge(wire_type, value, buf, ctx) } (MapKey::I64(value), Kind::Sfixed64) => { prost::encoding::sfixed64::merge(wire_type, value, buf, ctx) } (MapKey::U32(value), Kind::Uint32) => { prost::encoding::uint32::merge(wire_type, value, buf, ctx) } (MapKey::U32(value), Kind::Fixed32) => { prost::encoding::fixed32::merge(wire_type, value, buf, ctx) } (MapKey::U64(value), Kind::Uint64) => { prost::encoding::uint64::merge(wire_type, value, buf, ctx) } (MapKey::U64(value), Kind::Fixed64) => { prost::encoding::fixed64::merge(wire_type, value, buf, ctx) } (MapKey::String(value), Kind::String) => { prost::encoding::string::merge(wire_type, value, buf, ctx) } (value, ty) => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", value, ty ), } } fn encoded_len(&self, field_desc: &FieldDescriptor) -> usize { if !field_desc.supports_presence() && self.is_default(&field_desc.kind()) { return 0; } let number = field_desc.number(); match (self, field_desc.kind()) { (MapKey::Bool(value), Kind::Bool) => prost::encoding::bool::encoded_len(number, value), (MapKey::I32(value), Kind::Int32) => prost::encoding::int32::encoded_len(number, value), (MapKey::I32(value), Kind::Sint32) => { prost::encoding::sint32::encoded_len(number, value) } (MapKey::I32(value), Kind::Sfixed32) => { prost::encoding::sfixed32::encoded_len(number, value) } (MapKey::I64(value), Kind::Int64) => prost::encoding::int64::encoded_len(number, value), (MapKey::I64(value), Kind::Sint64) => { prost::encoding::sint64::encoded_len(number, value) } (MapKey::I64(value), Kind::Sfixed64) => { prost::encoding::sfixed64::encoded_len(number, value) } (MapKey::U32(value), Kind::Uint32) => { prost::encoding::uint32::encoded_len(number, value) } (MapKey::U32(value), Kind::Fixed32) => { prost::encoding::fixed32::encoded_len(number, value) } (MapKey::U64(value), Kind::Uint64) => { prost::encoding::uint64::encoded_len(number, value) } (MapKey::U64(value), Kind::Fixed64) => { prost::encoding::fixed64::encoded_len(number, value) } (MapKey::String(value), Kind::String) => { prost::encoding::string::encoded_len(number, value) } (value, ty) => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", value, ty ), } } } fn encode_packed_list(number: u32, iter: I, buf: &mut B, encode: E, encoded_len: L) where I: IntoIterator + Clone, B: BufMut, E: Fn(T, &mut B), L: Fn(T) -> usize, { prost::encoding::encode_key(number, WireType::LengthDelimited, buf); let len: usize = iter.clone().into_iter().map(encoded_len).sum(); prost::encoding::encode_varint(len as u64, buf); for value in iter { encode(value, buf); } } fn packed_list_encoded_len(number: u32, iter: I, encoded_len: L) -> usize where I: IntoIterator, L: Fn(T) -> usize, { let len: usize = iter.into_iter().map(encoded_len).sum(); prost::encoding::key_len(number) + prost::encoding::encoded_len_varint(len as u64) + len } fn from_sint32(value: i32) -> u32 { ((value << 1) ^ (value >> 31)) as u32 } // fn to_sint32(value: u32) -> i32 { // ((value >> 1) as i32) ^ (-((value & 1) as i32)) // } fn from_sint64(value: i64) -> u64 { ((value << 1) ^ (value >> 63)) as u64 } // fn to_sint64(value: u64) -> i64 { // ((value >> 1) as i64) ^ (-((value & 1) as i64)) // } prost-reflect-0.15.0/src/dynamic/mod.rs000064400000000000000000001413371046102023000160510ustar 00000000000000/// Parsing and formatting for the protobuf [text format](https://developers.google.com/protocol-buffers/docs/text-format-spec). /// /// This module contains options for customizing the text format output. See the associated functions [`DynamicMessage::parse_text_format()`] and /// [`DynamicMessage::to_text_format()`]. #[cfg(feature = "text-format")] #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub mod text_format; mod fields; mod message; #[cfg(feature = "serde")] mod serde; #[cfg(not(feature = "text-format"))] mod text_format; mod unknown; use std::{borrow::Cow, collections::HashMap, error::Error, fmt}; #[cfg(feature = "serde")] pub use self::serde::{DeserializeOptions, SerializeOptions}; pub use self::unknown::UnknownField; pub(crate) use self::fields::FieldDescriptorLike; use prost::{ bytes::{Buf, Bytes}, DecodeError, Message, }; use self::fields::DynamicMessageFieldSet; use crate::{ descriptor::Kind, ExtensionDescriptor, FieldDescriptor, MessageDescriptor, ReflectMessage, }; /// [`DynamicMessage`] provides encoding, decoding and reflection of a protobuf message. /// /// It wraps a [`MessageDescriptor`] and the [`Value`] for each field of the message, and implements /// [`Message`][`prost::Message`]. #[derive(Debug, Clone, PartialEq)] pub struct DynamicMessage { desc: MessageDescriptor, fields: DynamicMessageFieldSet, } /// A dynamically-typed protobuf value. /// /// Note this type may map to multiple possible protobuf wire formats, so it must be /// serialized as part of a DynamicMessage. #[derive(Debug, Clone, PartialEq)] pub enum Value { /// A boolean value, encoded as the `bool` protobuf type. Bool(bool), /// A 32-bit signed integer, encoded as one of the `int32`, `sint32` or `sfixed32` protobuf types. I32(i32), /// A 64-bit signed integer, encoded as one of the `int64`, `sint64` or `sfixed64` protobuf types. I64(i64), /// A 32-bit unsigned integer, encoded as one of the `uint32` or `ufixed32` protobuf types. U32(u32), /// A 64-bit unsigned integer, encoded as one of the `uint64` or `ufixed64` protobuf types. U64(u64), /// A 32-bit floating point number, encoded as the `float` protobuf type. F32(f32), /// A 64-bit floating point number, encoded as the `double` protobuf type. F64(f64), /// A string, encoded as the `string` protobuf type. String(String), /// A byte string, encoded as the `bytes` protobuf type. Bytes(Bytes), /// An enumeration value, encoded as a protobuf enum. EnumNumber(i32), /// A protobuf message. Message(DynamicMessage), /// A list of values, encoded as a protobuf repeated field. List(Vec), /// A map of values, encoded as a protobuf map field. Map(HashMap), } /// A dynamically-typed key for a protobuf map. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum MapKey { /// A boolean value, encoded as the `bool` protobuf type. Bool(bool), /// A 32-bit signed integer, encoded as one of the `int32`, `sint32` or `sfixed32` protobuf types. I32(i32), /// A 64-bit signed integer, encoded as one of the `int64`, `sint64` or `sfixed64` protobuf types. I64(i64), /// A 32-bit unsigned integer, encoded as one of the `uint32` or `ufixed32` protobuf types. U32(u32), /// A 64-bit unsigned integer, encoded as one of the `uint64` or `ufixed64` protobuf types. U64(u64), /// A string, encoded as the `string` protobuf type. String(String), } /// Error type returned by [`DynamicMessage::try_set_field()`]. #[derive(Debug, Clone, PartialEq)] pub enum SetFieldError { /// The field was not found. NotFound, /// The value type was not compatible with the field type (see [`Value::is_valid_for_field`]). InvalidType { /// The descriptor for the field which could not be set. field: FieldDescriptor, /// The invalid value. value: Value, }, } impl DynamicMessage { /// Creates a new, empty instance of [`DynamicMessage`] for the message type specified by the [`MessageDescriptor`]. pub fn new(desc: MessageDescriptor) -> Self { DynamicMessage { fields: DynamicMessageFieldSet::default(), desc, } } /// Decodes an instance of the message type specified by the [`MessageDescriptor`] from the buffer and merges it into a /// new instance of [`DynamicMessage`]. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01".as_ref()).unwrap(); /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); /// ``` pub fn decode(desc: MessageDescriptor, buf: B) -> Result where B: Buf, { let mut message = DynamicMessage::new(desc); message.merge(buf)?; Ok(message) } /// Returns `true` if this message has the given field set. /// /// If the field type supports distinguishing whether a value has been set (see [`supports_presence`][FieldDescriptor::supports_presence]), /// such as for messages, then this method returns `true` only if a value has been set. For /// other types, such as integers, it returns `true` if the value is set to a non-default value. /// /// If this method returns `false`, then the field will not be included in the encoded bytes /// of this message. /// /// # Examples /// /// This example uses the following message definition: /// /// ```lang-protobuf /// message MyMessage { /// int32 foo = 1; /// /// oneof optional { /// int32 bar = 2; /// } /// } /// ``` /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let foo = message_descriptor.get_field_by_name("foo").unwrap(); /// let bar = message_descriptor.get_field_by_name("bar").unwrap(); /// /// assert!(!foo.supports_presence()); /// assert!(bar.supports_presence()); /// /// let mut dynamic_message = DynamicMessage::new(message_descriptor); /// assert!(!dynamic_message.has_field(&foo)); /// assert!(!dynamic_message.has_field(&bar)); /// /// dynamic_message.set_field(&foo, Value::I32(0)); /// dynamic_message.set_field(&bar, Value::I32(0)); /// assert!(!dynamic_message.has_field(&foo)); /// assert!(dynamic_message.has_field(&bar)); /// /// dynamic_message.set_field(&foo, Value::I32(5)); /// dynamic_message.set_field(&bar, Value::I32(6)); /// assert!(dynamic_message.has_field(&foo)); /// assert!(dynamic_message.has_field(&bar)); /// ``` pub fn has_field(&self, field_desc: &FieldDescriptor) -> bool { self.fields.has(field_desc) } /// Gets the value of the given field, or the default value if it is unset. pub fn get_field(&self, field_desc: &FieldDescriptor) -> Cow<'_, Value> { self.fields.get(field_desc) } /// Gets a mutable reference to the value ofthe given field. If the field is not set, /// it is inserted with its default value. pub fn get_field_mut(&mut self, field_desc: &FieldDescriptor) -> &mut Value { self.fields.get_mut(field_desc) } /// Sets the value of the given field. /// /// # Panics /// /// This method may panic if the value type is not compatible with the field type, as defined /// by [`Value::is_valid_for_field`]. Consider using [`try_set_field()`](DynamicMessage::try_set_field) /// for a non-panicking version. pub fn set_field(&mut self, field_desc: &FieldDescriptor, value: Value) { self.try_set_field(field_desc, value).unwrap() } /// Tries to set the value of the given field, returning an error if the value is an invalid type. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, SetFieldError}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let mut dynamic_message = DynamicMessage::new(message_descriptor.clone()); /// let foo = message_descriptor.get_field_by_name("foo").unwrap(); /// assert_eq!(dynamic_message.try_set_field(&foo, Value::I32(5)), Ok(())); /// assert_eq!(dynamic_message.try_set_field(&foo, Value::String("bar".to_owned())), Err(SetFieldError::InvalidType { /// field: foo, /// value: Value::String("bar".to_owned()), /// })); /// ``` pub fn try_set_field( &mut self, field_desc: &FieldDescriptor, value: Value, ) -> Result<(), SetFieldError> { if value.is_valid_for_field(field_desc) { self.fields.set(field_desc, value); Ok(()) } else { Err(SetFieldError::InvalidType { field: field_desc.clone(), value, }) } } /// Clears the given field. /// /// After calling this method, `has_field` will return false for the field, /// and it will not be included in the encoded bytes of this message. pub fn clear_field(&mut self, field_desc: &FieldDescriptor) { self.fields.clear(field_desc); } /// Returns `true` if this message has a field set with the given number. /// /// See [`has_field`][Self::has_field] for more details. pub fn has_field_by_number(&self, number: u32) -> bool { self.desc .get_field(number) .is_some_and(|field_desc| self.has_field(&field_desc)) } /// Gets the value of the field with the given number, or the default value if it is unset. /// /// If the message has no field with the given number, `None` is returned. /// /// See [`get_field`][Self::get_field] for more details. pub fn get_field_by_number(&self, number: u32) -> Option> { self.desc .get_field(number) .map(|field_desc| self.get_field(&field_desc)) } /// Gets a mutable reference to the value of the field with the given number. If the field /// is not set, it is inserted with its default value. /// /// If the message has no field with the given number, `None` is returned. /// /// See [`get_field_mut`][Self::get_field_mut] for more details. pub fn get_field_by_number_mut(&mut self, number: u32) -> Option<&mut Value> { self.desc .get_field(number) .map(move |field_desc| self.get_field_mut(&field_desc)) } /// Sets the value of the field with number `number`. /// /// If no field with the given number exists, this method does nothing. /// /// See [`set_field`][Self::set_field] for more details. pub fn set_field_by_number(&mut self, number: u32, value: Value) { if let Some(field_desc) = self.desc.get_field(number) { self.set_field(&field_desc, value) } } /// Tries to set the value of the field with number `number`, returning an error if the value is an invalid type or does not exist. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, SetFieldError}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let mut dynamic_message = DynamicMessage::new(message_descriptor.clone()); /// assert_eq!(dynamic_message.try_set_field_by_number(1, Value::I32(5)), Ok(())); /// assert_eq!(dynamic_message.try_set_field_by_number(1, Value::String("bar".to_owned())), Err(SetFieldError::InvalidType { /// field: message_descriptor.get_field(1).unwrap(), /// value: Value::String("bar".to_owned()), /// })); /// assert_eq!(dynamic_message.try_set_field_by_number(42, Value::I32(5)), Err(SetFieldError::NotFound)); /// ``` pub fn try_set_field_by_number( &mut self, number: u32, value: Value, ) -> Result<(), SetFieldError> { if let Some(field_desc) = self.desc.get_field(number) { self.try_set_field(&field_desc, value) } else { Err(SetFieldError::NotFound) } } /// Clears the field with the given number. /// /// If no field with the given number exists, this method does nothing. /// /// See [`clear_field`][Self::clear_field] for more details. pub fn clear_field_by_number(&mut self, number: u32) { if let Some(field_desc) = self.desc.get_field(number) { self.clear_field(&field_desc); } } /// Returns `true` if this message has a field set with the given name. /// /// See [`has_field`][Self::has_field] for more details. pub fn has_field_by_name(&self, name: &str) -> bool { self.desc .get_field_by_name(name) .is_some_and(|field_desc| self.has_field(&field_desc)) } /// Gets the value of the field with the given name, or the default value if it is unset. /// /// If the message has no field with the given name, `None` is returned. /// /// See [`get_field`][Self::get_field] for more details. pub fn get_field_by_name(&self, name: &str) -> Option> { self.desc .get_field_by_name(name) .map(|field_desc| self.get_field(&field_desc)) } /// Gets a mutable reference to the value of the field with the given name. If the field /// is not set, it is inserted with its default value. /// /// If the message has no field with the given name, `None` is returned. /// /// See [`get_field_mut`][Self::get_field_mut] for more details. pub fn get_field_by_name_mut(&mut self, name: &str) -> Option<&mut Value> { self.desc .get_field_by_name(name) .map(move |field_desc| self.get_field_mut(&field_desc)) } /// Sets the value of the field with name `name`. /// /// If no field with the given name exists, this method does nothing. /// /// See [`set_field`][Self::set_field] for more details. pub fn set_field_by_name(&mut self, name: &str, value: Value) { if let Some(field_desc) = self.desc.get_field_by_name(name) { self.set_field(&field_desc, value) } } /// Tries to set the value of the field with name `name`, returning an error if the value is an invalid type or does not exist. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, SetFieldError}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let mut dynamic_message = DynamicMessage::new(message_descriptor.clone()); /// assert_eq!(dynamic_message.try_set_field_by_name("foo", Value::I32(5)), Ok(())); /// assert_eq!(dynamic_message.try_set_field_by_name("foo", Value::String("bar".to_owned())), Err(SetFieldError::InvalidType { /// field: message_descriptor.get_field_by_name("foo").unwrap(), /// value: Value::String("bar".to_owned()), /// })); /// assert_eq!(dynamic_message.try_set_field_by_name("notfound", Value::I32(5)), Err(SetFieldError::NotFound)); /// ``` pub fn try_set_field_by_name(&mut self, name: &str, value: Value) -> Result<(), SetFieldError> { if let Some(field_desc) = self.desc.get_field_by_name(name) { self.try_set_field(&field_desc, value) } else { Err(SetFieldError::NotFound) } } /// Clears the field with the given name. /// /// If no field with the given name exists, this method does nothing. /// /// See [`clear_field`][Self::clear_field] for more details. pub fn clear_field_by_name(&mut self, name: &str) { if let Some(field_desc) = self.desc.get_field_by_name(name) { self.clear_field(&field_desc); } } /// Clears the value for the given field, and returns it. /// /// Returns the value if [`has_field`](Self::has_field) was `true`, or `None` otherwise. pub fn take_field(&mut self, field_desc: &FieldDescriptor) -> Option { self.fields.take(field_desc) } /// Clears the value for the field with the given name, and returns it. /// /// Returns the value if [`has_field_by_name`](Self::has_field_by_name) was `true`, or `None` otherwise. pub fn take_field_by_name(&mut self, name: &str) -> Option { if let Some(field_desc) = self.desc.get_field_by_name(name) { self.fields.take(&field_desc) } else { None } } /// Clears the value for the field with the given number, and returns it. /// /// Returns the value if [`has_field_by_number`](Self::has_field_by_number) was `true`, or `None` otherwise. pub fn take_field_by_number(&mut self, number: u32) -> Option { if let Some(field_desc) = self.desc.get_field(number) { self.fields.take(&field_desc) } else { None } } /// Returns `true` if this message has the given extension field set. /// /// See [`has_field`][Self::has_field] for more details. pub fn has_extension(&self, extension_desc: &ExtensionDescriptor) -> bool { self.fields.has(extension_desc) } /// Gets the value of the given extension field, or the default value if it is unset. /// /// See [`get_field`][Self::get_field] for more details. pub fn get_extension(&self, extension_desc: &ExtensionDescriptor) -> Cow<'_, Value> { self.fields.get(extension_desc) } /// Gets a mutable reference to the value of the given extension field. If the /// field is not set, it is inserted with its default value. /// /// See [`get_field_mut`][Self::get_field_mut] for more details. pub fn get_extension_mut(&mut self, extension_desc: &ExtensionDescriptor) -> &mut Value { self.fields.get_mut(extension_desc) } /// Sets the value of the given extension field. /// /// See [`set_field`][Self::set_field] for more details. pub fn set_extension(&mut self, extension_desc: &ExtensionDescriptor, value: Value) { self.fields.set(extension_desc, value) } /// Clears the given extension field. /// /// See [`clear_field`][Self::clear_field] for more details. pub fn clear_extension(&mut self, extension_desc: &ExtensionDescriptor) { self.fields.clear(extension_desc) } /// Clears the value for the given extension field, and returns it. /// /// Returns the value if [`has_extension`](Self::has_extension) was `true`, or `None` otherwise. pub fn take_extension(&mut self, extension_desc: &ExtensionDescriptor) -> Option { self.fields.take(extension_desc) } /// Gets an iterator over all fields of this message. /// /// The iterator will yield all fields for which [`has_field`](Self::has_field) returns `true`. pub fn fields(&self) -> impl Iterator { self.fields.iter_fields(&self.desc) } /// Gets an iterator returning mutable references to all fields of this message. /// /// The iterator will yield all fields for which [`has_field`](Self::has_field) returns `true`. pub fn fields_mut(&mut self) -> impl Iterator { self.fields.iter_fields_mut(&self.desc) } /// Clears all fields from the message and returns an iterator yielding the values. /// /// The iterator will yield all fields for which [`has_field`](Self::has_field) returns `true`. /// /// If the iterator is dropped before completing the iteration, it is unspecified how many fields are removed. pub fn take_fields(&mut self) -> impl Iterator + '_ { self.fields.take_fields(&self.desc) } /// Gets an iterator over all extension fields of this message. /// /// The iterator will yield all extension fields for which [`has_extension`](Self::has_extension) returns `true`. pub fn extensions(&self) -> impl Iterator { self.fields.iter_extensions(&self.desc) } /// Gets an iterator returning mutable references to all extension fields of this message. /// /// The iterator will yield all extension fields for which [`has_extension`](Self::has_extension) returns `true`. pub fn extensions_mut(&mut self) -> impl Iterator { self.fields.iter_extensions_mut(&self.desc) } /// Clears all extension fields from the message and returns an iterator yielding the values. /// /// The iterator will yield all extension fields for which [`has_extension`](Self::has_extension) returns `true`. /// /// If the iterator is dropped before completing the iteration, it is unspecified how many fields are removed. pub fn take_extensions(&mut self) -> impl Iterator + '_ { self.fields.take_extensions(&self.desc) } /// Gets an iterator over unknown fields for this message. /// /// A field is unknown if the message descriptor does not contain a field with the given number. This is often the /// result of a new field being added to the message definition. /// /// Unknown fields are preserved when decoding and re-encoding a message. pub fn unknown_fields(&self) -> impl Iterator { self.fields.iter_unknown() } /// Clears all unknown fields from the message and returns an iterator yielding the values. /// /// If the iterator is dropped before completing the iteration, it is unspecified how many fields are removed. pub fn take_unknown_fields(&mut self) -> impl Iterator + '_ { self.fields.take_unknown() } /// Merge a strongly-typed message into this one. /// /// The message should be compatible with the type specified by /// [`descriptor`][Self::descriptor], or the merge will likely fail with /// a [`DecodeError`]. pub fn transcode_from(&mut self, value: &T) -> Result<(), DecodeError> where T: Message, { let buf = value.encode_to_vec(); self.merge(buf.as_slice()) } /// Convert this dynamic message into a strongly typed value. /// /// The message should be compatible with the type specified by /// [`descriptor`][Self::descriptor], or the conversion will likely fail with /// a [`DecodeError`]. pub fn transcode_to(&self) -> Result where T: Message + Default, { let buf = self.encode_to_vec(); T::decode(buf.as_slice()) } } impl ReflectMessage for DynamicMessage { fn descriptor(&self) -> MessageDescriptor { self.desc.clone() } fn transcode_to_dynamic(&self) -> DynamicMessage where Self: Sized, { self.clone() } } impl Value { /// Returns the default value for the given protobuf field. /// /// This is equivalent to [`default_value`][Value::default_value] except for the following cases: /// /// * If the field is a map, an empty map is returned. /// * If the field is `repeated`, an empty list is returned. /// * If the field has a custom default value specified, that is returned (proto2 only). pub fn default_value_for_field(field_desc: &FieldDescriptor) -> Self { if field_desc.is_list() { Value::List(Vec::default()) } else if field_desc.is_map() { Value::Map(HashMap::default()) } else if let Some(default_value) = field_desc.default_value() { default_value.clone() } else { Self::default_value(&field_desc.kind()) } } /// Returns the default value for the given protobuf extension field. /// /// See [`default_value_for_field`][Value::default_value_for_field] for more details. pub fn default_value_for_extension(extension_desc: &ExtensionDescriptor) -> Self { if extension_desc.is_list() { Value::List(Vec::default()) } else if extension_desc.is_map() { Value::Map(HashMap::default()) } else if let Some(default_value) = extension_desc.default_value() { default_value.clone() } else { Self::default_value(&extension_desc.kind()) } } /// Returns the default value for the given protobuf type `kind`. /// /// Unlike [`default_value_for_field`](Value::default_value_for_field), this method does not /// look at field cardinality, so it will never return a list or map. pub fn default_value(kind: &Kind) -> Self { match kind { Kind::Message(desc) => Value::Message(DynamicMessage::new(desc.clone())), Kind::Enum(enum_ty) => Value::EnumNumber(enum_ty.default_value().number()), Kind::Double => Value::F64(0.0), Kind::Float => Value::F32(0.0), Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => Value::I32(0), Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => Value::I64(0), Kind::Uint32 | Kind::Fixed32 => Value::U32(0), Kind::Uint64 | Kind::Fixed64 => Value::U64(0), Kind::Bool => Value::Bool(false), Kind::String => Value::String(String::default()), Kind::Bytes => Value::Bytes(Bytes::default()), } } /// Returns `true` if this is the default value for the given protobuf field. pub fn is_default_for_field(&self, field_desc: &FieldDescriptor) -> bool { *self == Value::default_value_for_field(field_desc) } /// Returns `true` if this is the default value for the given protobuf extension field. pub fn is_default_for_extension(&self, extension_desc: &ExtensionDescriptor) -> bool { *self == Value::default_value_for_extension(extension_desc) } /// Returns `true` if this is the default value for the given protobuf type `kind`. pub fn is_default(&self, kind: &Kind) -> bool { *self == Value::default_value(kind) } /// Returns `true` if this value can be set for a given field. /// /// Note this only checks if the value can be successfully encoded. It doesn't /// check, for example, that enum values are in the defined range. pub fn is_valid_for_field(&self, field_desc: &FieldDescriptor) -> bool { match (self, field_desc.kind()) { (Value::List(list), kind) if field_desc.is_list() => { list.iter().all(|value| value.is_valid(&kind)) } (Value::Map(map), Kind::Message(message_desc)) if field_desc.is_map() => { let key_desc = message_desc.map_entry_key_field().kind(); let value_desc = message_desc.map_entry_value_field(); map.iter().all(|(key, value)| { key.is_valid(&key_desc) && value.is_valid_for_field(&value_desc) }) } (value, kind) => value.is_valid(&kind), } } /// Returns `true` if this value can be set for a given extension field. /// /// See [`is_valid_for_field`][Value::is_valid_for_field] for more details. pub fn is_valid_for_extension(&self, extension_desc: &ExtensionDescriptor) -> bool { match (self, extension_desc.kind()) { (Value::List(list), kind) if extension_desc.is_list() => { list.iter().all(|value| value.is_valid(&kind)) } (Value::Map(map), Kind::Message(message_desc)) if extension_desc.is_map() => { let key_desc = message_desc.map_entry_key_field().kind(); let value_desc = message_desc.map_entry_value_field(); map.iter().all(|(key, value)| { key.is_valid(&key_desc) && value.is_valid_for_field(&value_desc) }) } (value, kind) => value.is_valid(&kind), } } /// Returns `true` if this value can be encoded as the given [`Kind`]. /// /// Unlike [`is_valid_for_field`](Value::is_valid_for_field), this method does not /// look at field cardinality, so it will never return `true` for lists or maps. pub fn is_valid(&self, kind: &Kind) -> bool { matches!( (self, kind), (Value::Bool(_), Kind::Bool) | (Value::I32(_), Kind::Int32 | Kind::Sint32 | Kind::Sfixed32) | (Value::I64(_), Kind::Int64 | Kind::Sint64 | Kind::Sfixed64) | (Value::U32(_), Kind::Uint32 | Kind::Fixed32) | (Value::U64(_), Kind::Uint64 | Kind::Fixed64) | (Value::F32(_), Kind::Float) | (Value::F64(_), Kind::Double) | (Value::String(_), Kind::String) | (Value::Bytes(_), Kind::Bytes) | (Value::EnumNumber(_), Kind::Enum(_)) | (Value::Message(_), Kind::Message(_)) ) } /// Returns the value if it is a `Value::Bool`, or `None` if it is any other type. pub fn as_bool(&self) -> Option { match *self { Value::Bool(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::Bool`, or `None` if it is any other type. pub fn as_bool_mut(&mut self) -> Option<&mut bool> { match self { Value::Bool(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::U32`, or `None` if it is any other type. pub fn as_u32(&self) -> Option { match *self { Value::U32(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::U32`, or `None` if it is any other type. pub fn as_u32_mut(&mut self) -> Option<&mut u32> { match self { Value::U32(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::U64`, or `None` if it is any other type. pub fn as_u64(&self) -> Option { match *self { Value::U64(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::U64`, or `None` if it is any other type. pub fn as_u64_mut(&mut self) -> Option<&mut u64> { match self { Value::U64(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::I64`, or `None` if it is any other type. pub fn as_i64(&self) -> Option { match *self { Value::I64(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::I64`, or `None` if it is any other type. pub fn as_i64_mut(&mut self) -> Option<&mut i64> { match self { Value::I64(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::I32`, or `None` if it is any other type. pub fn as_i32(&self) -> Option { match *self { Value::I32(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::I32`, or `None` if it is any other type. pub fn as_i32_mut(&mut self) -> Option<&mut i32> { match self { Value::I32(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::F32`, or `None` if it is any other type. pub fn as_f32(&self) -> Option { match *self { Value::F32(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::F32`, or `None` if it is any other type. pub fn as_f32_mut(&mut self) -> Option<&mut f32> { match self { Value::F32(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::F64`, or `None` if it is any other type. pub fn as_f64(&self) -> Option { match *self { Value::F64(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::F64`, or `None` if it is any other type. pub fn as_f64_mut(&mut self) -> Option<&mut f64> { match self { Value::F64(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::EnumNumber`, or `None` if it is any other type. pub fn as_enum_number(&self) -> Option { match *self { Value::EnumNumber(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::EnumNumber`, or `None` if it is any other type. pub fn as_enum_number_mut(&mut self) -> Option<&mut i32> { match self { Value::EnumNumber(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::String`, or `None` if it is any other type. pub fn as_str(&self) -> Option<&str> { match self { Value::String(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::String`, or `None` if it is any other type. pub fn as_string_mut(&mut self) -> Option<&mut String> { match self { Value::String(value) => Some(value), _ => None, } } /// Returns the value if it is a `Value::Bytes`, or `None` if it is any other type. pub fn as_bytes(&self) -> Option<&Bytes> { match self { Value::Bytes(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::Bytes`, or `None` if it is any other type. pub fn as_bytes_mut(&mut self) -> Option<&mut Bytes> { match self { Value::Bytes(value) => Some(value), _ => None, } } /// Returns a a reference to the value if it is a `Value::Message`, or `None` if it is any other type. pub fn as_message(&self) -> Option<&DynamicMessage> { match self { Value::Message(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::Message`, or `None` if it is any other type. pub fn as_message_mut(&mut self) -> Option<&mut DynamicMessage> { match self { Value::Message(value) => Some(value), _ => None, } } /// Returns a a reference to the value if it is a `Value::List`, or `None` if it is any other type. pub fn as_list(&self) -> Option<&[Value]> { match self { Value::List(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::List`, or `None` if it is any other type. pub fn as_list_mut(&mut self) -> Option<&mut Vec> { match self { Value::List(value) => Some(value), _ => None, } } /// Returns a a reference to the value if it is a `Value::Map`, or `None` if it is any other type. pub fn as_map(&self) -> Option<&HashMap> { match self { Value::Map(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `Value::Map`, or `None` if it is any other type. pub fn as_map_mut(&mut self) -> Option<&mut HashMap> { match self { Value::Map(value) => Some(value), _ => None, } } /// Converts this value into a [`MapKey`], or `None` if it is not a valid map key type. /// /// # Examples /// /// ``` /// # use prost_reflect::{Value, MapKey, bytes::Bytes}; /// assert_eq!(Value::I32(5).into_map_key(), Some(MapKey::I32(5))); /// assert_eq!(Value::String("foo".to_owned()).into_map_key(), Some(MapKey::String("foo".to_owned()))); /// assert_eq!(Value::Bytes(Bytes::from_static(b"bytes")).into_map_key(), None); /// ``` pub fn into_map_key(self) -> Option { match self { Value::Bool(value) => Some(MapKey::Bool(value)), Value::I32(value) => Some(MapKey::I32(value)), Value::I64(value) => Some(MapKey::I64(value)), Value::U32(value) => Some(MapKey::U32(value)), Value::U64(value) => Some(MapKey::U64(value)), Value::String(value) => Some(MapKey::String(value)), _ => None, } } } impl MapKey { /// Returns the default value for the given protobuf type `kind`. /// /// # Panics /// /// Panics if `kind` is not a valid map key type (an integral type or string). pub fn default_value(kind: &Kind) -> Self { match *kind { Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => MapKey::I32(0), Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => MapKey::I64(0), Kind::Uint32 | Kind::Fixed32 => MapKey::U32(0), Kind::Uint64 | Kind::Fixed64 => MapKey::U64(0), Kind::Bool => MapKey::Bool(false), Kind::String => MapKey::String(String::default()), _ => panic!("invalid type for map key"), } } /// Returns `true` if this is the default value for the given protobuf type `kind`. /// /// # Panics /// /// Panics if `kind` is not a valid map key type (an integral type or string). pub fn is_default(&self, kind: &Kind) -> bool { *self == MapKey::default_value(kind) } /// Returns `true` if this map key can be encoded as the given [`Kind`]. pub fn is_valid(&self, kind: &Kind) -> bool { matches!( (self, kind), (MapKey::Bool(_), Kind::Bool) | (MapKey::I32(_), Kind::Int32 | Kind::Sint32 | Kind::Sfixed32) | (MapKey::I64(_), Kind::Int64 | Kind::Sint64 | Kind::Sfixed64) | (MapKey::U32(_), Kind::Uint32 | Kind::Fixed32) | (MapKey::U64(_), Kind::Uint64 | Kind::Fixed64) | (MapKey::String(_), Kind::String) ) } /// Returns the value if it is a `MapKey::Bool`, or `None` if it is any other type. pub fn as_bool(&self) -> Option { match *self { MapKey::Bool(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `MapKey::Bool`, or `None` if it is any other type. pub fn as_bool_mut(&mut self) -> Option<&mut bool> { match self { MapKey::Bool(value) => Some(value), _ => None, } } /// Returns the value if it is a `MapKey::U32`, or `None` if it is any other type. pub fn as_u32(&self) -> Option { match *self { MapKey::U32(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `MapKey::U32`, or `None` if it is any other type. pub fn as_u32_mut(&mut self) -> Option<&mut u32> { match self { MapKey::U32(value) => Some(value), _ => None, } } /// Returns the value if it is a `MapKey::U64`, or `None` if it is any other type. pub fn as_u64(&self) -> Option { match *self { MapKey::U64(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `MapKey::U64`, or `None` if it is any other type. pub fn as_u64_mut(&mut self) -> Option<&mut u64> { match self { MapKey::U64(value) => Some(value), _ => None, } } /// Returns the value if it is a `MapKey::I64`, or `None` if it is any other type. pub fn as_i64(&self) -> Option { match *self { MapKey::I64(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `MapKey::I64`, or `None` if it is any other type. pub fn as_i64_mut(&mut self) -> Option<&mut i64> { match self { MapKey::I64(value) => Some(value), _ => None, } } /// Returns the value if it is a `MapKey::I32`, or `None` if it is any other type. pub fn as_i32(&self) -> Option { match *self { MapKey::I32(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `MapKey::I32`, or `None` if it is any other type. pub fn as_i32_mut(&mut self) -> Option<&mut i32> { match self { MapKey::I32(value) => Some(value), _ => None, } } /// Returns the value if it is a `MapKey::String`, or `None` if it is any other type. pub fn as_str(&self) -> Option<&str> { match self { MapKey::String(value) => Some(value), _ => None, } } /// Returns a mutable reference to the value if it is a `MapKey::String`, or `None` if it is any other type. pub fn as_string_mut(&mut self) -> Option<&mut String> { match self { MapKey::String(value) => Some(value), _ => None, } } } impl From for Value { fn from(value: MapKey) -> Self { match value { MapKey::Bool(value) => Value::Bool(value), MapKey::I32(value) => Value::I32(value), MapKey::I64(value) => Value::I64(value), MapKey::U32(value) => Value::U32(value), MapKey::U64(value) => Value::U64(value), MapKey::String(value) => Value::String(value), } } } impl fmt::Display for SetFieldError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { SetFieldError::NotFound => write!(f, "field not found"), SetFieldError::InvalidType { field, value } => { write!(f, "expected a value of type '")?; if field.is_map() { let entry = field.kind(); let entry = entry.as_message().unwrap(); write!( f, "map<{:?}, {:?}>", entry.map_entry_key_field().kind(), entry.map_entry_value_field().kind() )?; } else if field.is_list() { write!(f, "repeated {:?}", field.kind())?; } else { write!(f, "{:?}", field.kind())?; } write!(f, "', but found '{}'", value) } } } } impl Error for SetFieldError {} pub(crate) fn fmt_string(f: &mut impl fmt::Write, bytes: &[u8]) -> fmt::Result { f.write_char('"')?; for &ch in bytes { match ch { b'\t' => f.write_str("\\t")?, b'\r' => f.write_str("\\r")?, b'\n' => f.write_str("\\n")?, b'\\' => f.write_str("\\\\")?, b'\'' => f.write_str("\\'")?, b'"' => f.write_str("\\\"")?, b'\x20'..=b'\x7e' => f.write_char(ch as char)?, _ => { write!(f, "\\{:03o}", ch)?; } } } f.write_char('"') } impl fmt::Display for DynamicMessage { /// Formats this message using the protobuf text format. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01\x1a\x02\x10\x42".as_ref()).unwrap(); /// assert_eq!(format!("{}", dynamic_message), "foo:150,nested{bar:66}"); /// // The alternate format specifier may be used to pretty-print the output /// assert_eq!(format!("{:#}", dynamic_message), "foo: 150\nnested {\n bar: 66\n}"); /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { text_format::Writer::new(text_format::FormatOptions::new().pretty(f.alternate()), f) .fmt_message(self) } } impl fmt::Display for Value { /// Formats this value using the protobuf text format. /// /// # Examples /// /// ``` /// # use std::{collections::HashMap, iter::FromIterator}; /// # use prost_reflect::{MapKey, Value}; /// assert_eq!(format!("{}", Value::String("hello".to_owned())), "\"hello\""); /// assert_eq!(format!("{}", Value::List(vec![Value::I32(1), Value::I32(2)])), "[1,2]"); /// assert_eq!(format!("{}", Value::Map(HashMap::from_iter([(MapKey::I32(1), Value::U32(2))]))), "[{key:1,value:2}]"); /// // The alternate format specifier may be used to indent the output /// assert_eq!(format!("{:#}", Value::Map(HashMap::from_iter([(MapKey::I32(1), Value::U32(2))]))), "[{\n key: 1\n value: 2\n}]"); /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { text_format::Writer::new(text_format::FormatOptions::new().pretty(f.alternate()), f) .fmt_value(self, None) } } #[test] fn type_sizes() { assert_eq!(std::mem::size_of::(), 40); assert_eq!(std::mem::size_of::(), 56); } pub(crate) enum Either { Left(L), Right(R), } impl> Iterator for Either { type Item = L::Item; fn next(&mut self) -> Option { match self { Either::Left(left) => left.next(), Either::Right(right) => right.next(), } } } fn get_type_url_message_name(type_url: &str) -> Result<&str, String> { let (_type_domain_name, message_name) = type_url .rsplit_once('/') .ok_or_else(|| format!("unsupported type url '{type_url}': missing at least one '/'",))?; Ok(message_name) } #[test] fn test_get_type_url_message_name() { assert_eq!( get_type_url_message_name("type.googleapis.com/my.messages.Message"), Ok("my.messages.Message") ); assert_eq!( get_type_url_message_name("type.googleprod.com/my.messages.Message"), Ok("my.messages.Message") ); assert_eq!( get_type_url_message_name("/my.messages.Message"), Ok("my.messages.Message") ); assert_eq!( get_type_url_message_name("any.url.com/my.messages.Message"), Ok("my.messages.Message") ); assert_eq!( get_type_url_message_name("http://even.multiple/slashes/my.messages.Message"), Ok("my.messages.Message") ); assert_eq!( get_type_url_message_name("/any.type.isAlsoValid"), Ok("any.type.isAlsoValid") ); assert_eq!( get_type_url_message_name("my.messages.Message"), Err("unsupported type url 'my.messages.Message': missing at least one '/'".to_owned()) ); } prost-reflect-0.15.0/src/dynamic/serde/case.rs000064400000000000000000000051611046102023000173010ustar 00000000000000/// Convert `src` from snake case to camel case, returning an error if roundtripping /// back to snake case would not be possible. pub(crate) fn snake_case_to_camel_case(dst: &mut String, src: &str) -> Result<(), ()> { let mut ucase_next = false; for ch in src.chars() { if ch.is_ascii_uppercase() { return Err(()); } if ucase_next { let upper_ch = ch.to_ascii_uppercase(); if upper_ch == ch { return Err(()); } dst.push(upper_ch); ucase_next = false; } else if ch == '_' { ucase_next = true; } else { dst.push(ch) } } Ok(()) } pub(crate) fn camel_case_to_snake_case(result: &mut String, part: &str) -> Result<(), ()> { for ch in part.chars() { if ch.is_ascii_uppercase() { result.push('_'); result.push(ch.to_ascii_lowercase()); } else if ch == '_' { return Err(()); } else { result.push(ch); } } Ok(()) } #[cfg(test)] mod tests { use proptest::prelude::*; use super::*; #[test] fn snake_to_camel() { let mut buf = String::new(); snake_case_to_camel_case(&mut buf, "foo").unwrap(); assert_eq!(&buf, "foo"); buf.clear(); snake_case_to_camel_case(&mut buf, "foo_bar").unwrap(); assert_eq!(&buf, "fooBar"); buf.clear(); } #[test] fn camel_to_snake() { let mut buf = String::new(); camel_case_to_snake_case(&mut buf, "foo").unwrap(); assert_eq!(&buf, "foo"); buf.clear(); camel_case_to_snake_case(&mut buf, "fooBar").unwrap(); assert_eq!(&buf, "foo_bar"); buf.clear(); } #[test] fn bad_roundtrips() { let mut buf = String::new(); assert!(snake_case_to_camel_case(&mut buf, "fooBar").is_err()); assert!(snake_case_to_camel_case(&mut buf, "foo_3_bar").is_err()); assert!(snake_case_to_camel_case(&mut buf, "foo__bar").is_err()); } proptest! { #[test] fn roundtrip_cases(snake_case in "[a-zA-Z0-9]+") { let mut camel_case = String::new(); if snake_case_to_camel_case(&mut camel_case, &snake_case).is_ok() { let mut roundtripped_snake_case = String::new(); camel_case_to_snake_case(&mut roundtripped_snake_case, &camel_case).unwrap(); prop_assert_eq!(snake_case, roundtripped_snake_case); } } } } prost-reflect-0.15.0/src/dynamic/serde/de/kind.rs000064400000000000000000000424451046102023000177110ustar 00000000000000use std::{borrow::Cow, collections::HashMap, convert::TryInto, fmt, str::FromStr}; use prost::bytes::Bytes; use serde::de::{DeserializeSeed, Deserializer, Error, IgnoredAny, MapAccess, SeqAccess, Visitor}; use crate::{ dynamic::{serde::DeserializeOptions, DynamicMessage, MapKey, Value}, EnumDescriptor, Kind, MessageDescriptor, ReflectMessage, }; use super::{ deserialize_enum, deserialize_message, FieldDescriptorSeed, OptionalFieldDescriptorSeed, }; pub struct KindSeed<'a>(pub &'a Kind, pub &'a DeserializeOptions); impl<'de> DeserializeSeed<'de> for KindSeed<'_> { type Value = Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { match self.0 { Kind::Double => deserializer.deserialize_any(DoubleVisitor).map(Value::F64), Kind::Float => deserializer.deserialize_any(FloatVisitor).map(Value::F32), Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => { deserializer.deserialize_any(Int32Visitor).map(Value::I32) } Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => { deserializer.deserialize_any(Int64Visitor).map(Value::I64) } Kind::Uint32 | Kind::Fixed32 => { deserializer.deserialize_any(Uint32Visitor).map(Value::U32) } Kind::Uint64 | Kind::Fixed64 => { deserializer.deserialize_any(Uint64Visitor).map(Value::U64) } Kind::Bool => deserializer.deserialize_any(BoolVisitor).map(Value::Bool), Kind::String => deserializer .deserialize_string(StringVisitor) .map(Value::String), Kind::Bytes => deserializer.deserialize_str(BytesVisitor).map(Value::Bytes), Kind::Message(desc) => { deserialize_message(desc, deserializer, self.1).map(Value::Message) } Kind::Enum(desc) => deserialize_enum(desc, deserializer).map(Value::EnumNumber), } } } pub struct ListVisitor<'a>(pub &'a Kind, pub &'a DeserializeOptions); pub struct MapVisitor<'a>(pub &'a Kind, pub &'a DeserializeOptions); pub struct DoubleVisitor; pub struct FloatVisitor; pub struct Int32Visitor; pub struct Uint32Visitor; pub struct Int64Visitor; pub struct Uint64Visitor; pub struct StringVisitor; pub struct BoolVisitor; pub struct BytesVisitor; pub struct MessageVisitor<'a>(pub &'a MessageDescriptor, pub &'a DeserializeOptions); pub struct MessageVisitorInner<'a>(pub &'a mut DynamicMessage, pub &'a DeserializeOptions); pub struct EnumVisitor<'a>(pub &'a EnumDescriptor); impl<'de> Visitor<'de> for ListVisitor<'_> { type Value = Vec; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a list") } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let mut result = Vec::with_capacity(seq.size_hint().unwrap_or(0)); while let Some(value) = seq.next_element_seed(KindSeed(self.0, self.1))? { result.push(value) } Ok(result) } } impl<'de> Visitor<'de> for MapVisitor<'_> { type Value = HashMap; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a map") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut result = HashMap::with_capacity(map.size_hint().unwrap_or(0)); let map_entry_message = self.0.as_message().unwrap(); let key_kind = map_entry_message.map_entry_key_field().kind(); let value_desc = map_entry_message.map_entry_value_field(); while let Some(key_str) = map.next_key::>()? { let key = match key_kind { Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => { MapKey::I32(i32::from_str(key_str.as_ref()).map_err(Error::custom)?) } Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => { MapKey::I64(i64::from_str(key_str.as_ref()).map_err(Error::custom)?) } Kind::Uint32 | Kind::Fixed32 => { MapKey::U32(u32::from_str(key_str.as_ref()).map_err(Error::custom)?) } Kind::Uint64 | Kind::Fixed64 => { MapKey::U64(u64::from_str(key_str.as_ref()).map_err(Error::custom)?) } Kind::Bool => { MapKey::Bool(bool::from_str(key_str.as_ref()).map_err(Error::custom)?) } Kind::String => MapKey::String(key_str.into_owned()), _ => unreachable!("invalid type for map key"), }; let value = map.next_value_seed(FieldDescriptorSeed(&value_desc, self.1))?; result.insert(key, value); } Ok(result) } } impl Visitor<'_> for DoubleVisitor { type Value = f64; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a 64-bit floating point value") } #[inline] fn visit_f64(self, v: f64) -> Result where E: Error, { Ok(v) } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { Ok(v as Self::Value) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { Ok(v as Self::Value) } fn visit_str(self, v: &str) -> Result where E: Error, { match f64::from_str(v) { Ok(value) => Ok(value), Err(_) if v == "Infinity" => Ok(f64::INFINITY), Err(_) if v == "-Infinity" => Ok(f64::NEG_INFINITY), Err(_) if v == "NaN" => Ok(f64::NAN), Err(err) => Err(Error::custom(err)), } } } impl Visitor<'_> for FloatVisitor { type Value = f32; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a 32-bit floating point value") } #[inline] fn visit_f32(self, v: f32) -> Result where E: Error, { Ok(v) } #[inline] fn visit_f64(self, v: f64) -> Result where E: Error, { if v < (f32::MIN as f64) || v > (f32::MAX as f64) { Err(Error::custom("float value out of range")) } else { Ok(v as f32) } } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { Ok(v as Self::Value) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { Ok(v as Self::Value) } fn visit_str(self, v: &str) -> Result where E: Error, { match f32::from_str(v) { Ok(value) => Ok(value), Err(_) if v == "Infinity" => Ok(f32::INFINITY), Err(_) if v == "-Infinity" => Ok(f32::NEG_INFINITY), Err(_) if v == "NaN" => Ok(f32::NAN), Err(err) => Err(Error::custom(err)), } } } impl Visitor<'_> for Int32Visitor { type Value = i32; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a 32-bit signed integer") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { v.parse().map_err(Error::custom) } #[inline] fn visit_i32(self, v: i32) -> Result where E: Error, { Ok(v) } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { v.try_into().map_err(Error::custom) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { v.try_into().map_err(Error::custom) } fn visit_f64(self, v: f64) -> Result where E: Error, { if v.fract() != 0.0 { return Err(Error::custom("expected integer value")); } if v < (i32::MIN as f64) || v > (i32::MAX as f64) { return Err(Error::custom("float value out of range")); } Ok(v as i32) } } impl Visitor<'_> for Uint32Visitor { type Value = u32; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a 32-bit unsigned integer or decimal string") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { v.parse().map_err(Error::custom) } #[inline] fn visit_u32(self, v: u32) -> Result where E: Error, { Ok(v) } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { v.try_into().map_err(Error::custom) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { v.try_into().map_err(Error::custom) } fn visit_f64(self, v: f64) -> Result where E: Error, { if v.fract() != 0.0 { return Err(Error::custom("expected integer value")); } if v < (u32::MIN as f64) || v > (u32::MAX as f64) { return Err(Error::custom("float value out of range")); } Ok(v as u32) } } impl Visitor<'_> for Int64Visitor { type Value = i64; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a 64-bit signed integer or decimal string") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { v.parse().map_err(Error::custom) } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { Ok(v) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { v.try_into().map_err(Error::custom) } fn visit_f64(self, v: f64) -> Result where E: Error, { if v.fract() != 0.0 { return Err(Error::custom("expected integer value")); } if v < (i64::MIN as f64) || v > (i64::MAX as f64) { return Err(Error::custom("float value out of range")); } Ok(v as i64) } } impl Visitor<'_> for Uint64Visitor { type Value = u64; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a 64-bit unsigned integer or decimal string") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { v.parse().map_err(Error::custom) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { Ok(v) } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { v.try_into().map_err(Error::custom) } fn visit_f64(self, v: f64) -> Result where E: Error, { if v.fract() != 0.0 { return Err(Error::custom("expected integer value")); } if v < (u64::MIN as f64) || v > (u64::MAX as f64) { return Err(Error::custom("float value out of range")); } Ok(v as u64) } } impl Visitor<'_> for StringVisitor { type Value = String; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a string") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { Ok(v.to_owned()) } #[inline] fn visit_string(self, v: String) -> Result where E: Error, { Ok(v) } } impl Visitor<'_> for BoolVisitor { type Value = bool; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a boolean") } #[inline] fn visit_bool(self, v: bool) -> Result where E: Error, { Ok(v) } } impl Visitor<'_> for BytesVisitor { type Value = Bytes; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a base64-encoded string") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { use base64::{ alphabet, engine::DecodePaddingMode, engine::{GeneralPurpose, GeneralPurposeConfig}, DecodeError, Engine, }; const CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() .with_decode_allow_trailing_bits(true) .with_decode_padding_mode(DecodePaddingMode::Indifferent); const STANDARD: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, CONFIG); const URL_SAFE: GeneralPurpose = GeneralPurpose::new(&alphabet::URL_SAFE, CONFIG); let mut buf = Vec::new(); match STANDARD.decode_vec(v, &mut buf) { Ok(()) => Ok(buf.into()), Err(DecodeError::InvalidByte(_, b'-')) | Err(DecodeError::InvalidByte(_, b'_')) => { buf.clear(); match URL_SAFE.decode_vec(v, &mut buf) { Ok(()) => Ok(buf.into()), Err(err) => Err(Error::custom(format!("invalid base64: {}", err))), } } Err(err) => Err(Error::custom(format!("invalid base64: {}", err))), } } } impl<'de> Visitor<'de> for MessageVisitor<'_> { type Value = DynamicMessage; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a map") } fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { let mut message = DynamicMessage::new(self.0.clone()); MessageVisitorInner(&mut message, self.1).visit_map(map)?; Ok(message) } } impl<'de> Visitor<'de> for MessageVisitorInner<'_> { type Value = (); fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a map") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let desc = self.0.descriptor(); while let Some(key) = map.next_key::>()? { if let Some(field) = desc .get_field_by_json_name(key.as_ref()) .or_else(|| desc.get_field_by_name(key.as_ref())) { if let Some(value) = map.next_value_seed(OptionalFieldDescriptorSeed(&field, self.1))? { if let Some(oneof_desc) = field.containing_oneof() { for oneof_field in oneof_desc.fields() { if self.0.has_field(&oneof_field) { return Err(Error::custom(format!( "multiple fields provided for oneof '{}'", oneof_desc.name() ))); } } } self.0.set_field(&field, value); } } else if let Some(extension_desc) = desc.get_extension_by_json_name(key.as_ref()) { if let Some(value) = map.next_value_seed(OptionalFieldDescriptorSeed(&extension_desc, self.1))? { self.0.set_extension(&extension_desc, value); } } else if self.1.deny_unknown_fields { return Err(Error::custom(format!("unrecognized field name '{}'", key))); } else { let _ = map.next_value::()?; } } Ok(()) } } impl Visitor<'_> for EnumVisitor<'_> { type Value = i32; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a string or integer") } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { match self.0.get_value_by_name(v) { Some(e) => Ok(e.number()), None => Err(Error::custom(format!("unrecognized enum value '{}'", v))), } } #[inline] fn visit_i32(self, v: i32) -> Result where E: Error, { Ok(v) } #[inline] fn visit_i64(self, v: i64) -> Result where E: Error, { self.visit_i32(v.try_into().map_err(Error::custom)?) } #[inline] fn visit_u64(self, v: u64) -> Result where E: Error, { self.visit_i32(v.try_into().map_err(Error::custom)?) } } prost-reflect-0.15.0/src/dynamic/serde/de/mod.rs000064400000000000000000000155371046102023000175450ustar 00000000000000mod kind; mod wkt; use std::fmt; use prost::Message; use serde::de::{DeserializeSeed, Deserializer, Error, Visitor}; use crate::{ dynamic::{fields::FieldDescriptorLike, serde::DeserializeOptions, DynamicMessage, Value}, EnumDescriptor, Kind, MessageDescriptor, }; pub(super) fn deserialize_message<'de, D>( desc: &MessageDescriptor, deserializer: D, options: &DeserializeOptions, ) -> Result where D: Deserializer<'de>, { match desc.full_name() { "google.protobuf.Any" => deserializer .deserialize_any(wkt::GoogleProtobufAnyVisitor(desc.parent_pool(), options)) .and_then(|timestamp| make_message(desc, timestamp)), "google.protobuf.Timestamp" => deserializer .deserialize_str(wkt::GoogleProtobufTimestampVisitor) .and_then(|timestamp| make_message(desc, timestamp)), "google.protobuf.Duration" => deserializer .deserialize_str(wkt::GoogleProtobufDurationVisitor) .and_then(|duration| make_message(desc, duration)), "google.protobuf.FloatValue" => deserializer .deserialize_any(kind::FloatVisitor) .and_then(|v| make_message(desc, v)), "google.protobuf.DoubleValue" => deserializer .deserialize_any(kind::DoubleVisitor) .and_then(|v| make_message(desc, v)), "google.protobuf.Int32Value" => deserializer .deserialize_any(kind::Int32Visitor) .and_then(|v| make_message(desc, v)), "google.protobuf.Int64Value" => deserializer .deserialize_any(kind::Int64Visitor) .and_then(|v| make_message(desc, v)), "google.protobuf.UInt32Value" => deserializer .deserialize_any(kind::Uint32Visitor) .and_then(|v| make_message(desc, v)), "google.protobuf.UInt64Value" => deserializer .deserialize_any(kind::Uint64Visitor) .and_then(|v| make_message(desc, v)), "google.protobuf.BoolValue" => deserializer .deserialize_any(kind::BoolVisitor) .and_then(|v| make_message(desc, v)), "google.protobuf.StringValue" => deserializer .deserialize_any(kind::StringVisitor) .and_then(|v| make_message(desc, v)), "google.protobuf.BytesValue" => deserializer .deserialize_any(kind::BytesVisitor) .and_then(|v| make_message(desc, v)), "google.protobuf.FieldMask" => deserializer .deserialize_str(wkt::GoogleProtobufFieldMaskVisitor) .and_then(|field_mask| make_message(desc, field_mask)), "google.protobuf.Struct" => deserializer .deserialize_map(wkt::GoogleProtobufStructVisitor) .and_then(|value| make_message(desc, value)), "google.protobuf.ListValue" => deserializer .deserialize_seq(wkt::GoogleProtobufListVisitor) .and_then(|list| make_message(desc, list)), "google.protobuf.Value" => deserializer .deserialize_any(wkt::GoogleProtobufValueVisitor) .and_then(|value| make_message(desc, value)), "google.protobuf.Empty" => deserializer .deserialize_map(wkt::GoogleProtobufEmptyVisitor) .and_then(|empty| make_message(desc, empty)), _ => deserializer.deserialize_map(kind::MessageVisitor(desc, options)), } } fn deserialize_enum<'de, D>(desc: &EnumDescriptor, deserializer: D) -> Result where D: Deserializer<'de>, { match desc.full_name() { "google.protobuf.NullValue" => deserializer.deserialize_any(wkt::GoogleProtobufNullVisitor), _ => deserializer.deserialize_any(kind::EnumVisitor(desc)), } } struct MessageSeed<'a>(&'a MessageDescriptor, &'a DeserializeOptions); impl<'de> DeserializeSeed<'de> for MessageSeed<'_> { type Value = DynamicMessage; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserialize_message(self.0, deserializer, self.1) } } struct FieldDescriptorSeed<'a, T>(&'a T, &'a DeserializeOptions); impl<'de, T> DeserializeSeed<'de> for FieldDescriptorSeed<'_, T> where T: FieldDescriptorLike, { type Value = Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { if self.0.is_list() { deserializer .deserialize_any(kind::ListVisitor(&self.0.kind(), self.1)) .map(Value::List) } else if self.0.is_map() { deserializer .deserialize_any(kind::MapVisitor(&self.0.kind(), self.1)) .map(Value::Map) } else { kind::KindSeed(&self.0.kind(), self.1).deserialize(deserializer) } } } struct OptionalFieldDescriptorSeed<'a, T>(&'a T, &'a DeserializeOptions); impl<'de, T> DeserializeSeed<'de> for OptionalFieldDescriptorSeed<'_, T> where T: FieldDescriptorLike, { type Value = Option; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_option(self) } } impl<'de, T> Visitor<'de> for OptionalFieldDescriptorSeed<'_, T> where T: FieldDescriptorLike, { type Value = Option; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "option") } #[inline] fn visit_unit(self) -> Result where E: Error, { self.visit_none() } #[inline] fn visit_none(self) -> Result where E: Error, { if let Kind::Message(message_desc) = self.0.kind() { match message_desc.full_name() { "google.protobuf.Value" => make_message( &message_desc, prost_types::Value { kind: Some(prost_types::value::Kind::NullValue(0)), }, ) .map(|v| Some(Value::Message(v))), _ => Ok(None), } } else { Ok(Some(self.0.default_value())) } } #[inline] fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { FieldDescriptorSeed(self.0, self.1) .deserialize(deserializer) .map(Some) } } fn make_message( desc: &MessageDescriptor, message: T, ) -> Result { let mut dynamic = DynamicMessage::new(desc.clone()); dynamic .transcode_from(&message) .map_err(|err| Error::custom(format!("error decoding: {}", err)))?; Ok(dynamic) } prost-reflect-0.15.0/src/dynamic/serde/de/wkt.rs000064400000000000000000000374001046102023000175640ustar 00000000000000use std::{ borrow::Cow, collections::{BTreeMap, HashMap}, fmt, marker::PhantomData, }; use prost::Message; use serde::de::{ DeserializeSeed, Deserializer, Error, IgnoredAny, IntoDeserializer, MapAccess, SeqAccess, Visitor, }; use crate::{ dynamic::{ get_type_url_message_name, serde::{ case::camel_case_to_snake_case, check_duration, check_timestamp, is_well_known_type, DeserializeOptions, }, DynamicMessage, }, DescriptorPool, }; use super::{deserialize_message, kind::MessageVisitorInner, MessageSeed}; pub struct GoogleProtobufAnyVisitor<'a>(pub &'a DescriptorPool, pub &'a DeserializeOptions); pub struct GoogleProtobufNullVisitor; pub struct GoogleProtobufTimestampVisitor; pub struct GoogleProtobufDurationVisitor; pub struct GoogleProtobufFieldMaskVisitor; pub struct GoogleProtobufListVisitor; pub struct GoogleProtobufStructVisitor; pub struct GoogleProtobufValueVisitor; pub struct GoogleProtobufEmptyVisitor; impl<'de> Visitor<'de> for GoogleProtobufAnyVisitor<'_> { type Value = prost_types::Any; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a map") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut buffered_entries = HashMap::new(); let type_url = find_field( &mut map, &mut buffered_entries, "@type", PhantomData::, )?; let message_name = get_type_url_message_name(&type_url).map_err(Error::custom)?; let message_desc = self .0 .get_message_by_name(message_name) .ok_or_else(|| Error::custom(format!("message '{}' not found", message_name)))?; let payload_message = if is_well_known_type(message_name) { let payload_message = match buffered_entries.remove("value") { Some(value) => { deserialize_message(&message_desc, value, self.1).map_err(Error::custom)? } None => find_field( &mut map, &mut buffered_entries, "value", MessageSeed(&message_desc, self.1), )?, }; if self.1.deny_unknown_fields { if let Some(key) = buffered_entries.keys().next() { return Err(Error::custom(format!("unrecognized field name '{}'", key))); } if let Some(key) = map.next_key::>()? { return Err(Error::custom(format!("unrecognized field name '{}'", key))); } } else { drop(buffered_entries); while map.next_entry::()?.is_some() {} } payload_message } else { let mut payload_message = DynamicMessage::new(message_desc); buffered_entries .into_deserializer() .deserialize_map(MessageVisitorInner(&mut payload_message, self.1)) .map_err(Error::custom)?; MessageVisitorInner(&mut payload_message, self.1).visit_map(map)?; payload_message }; let value = payload_message.encode_to_vec(); Ok(prost_types::Any { type_url, value }) } } impl Visitor<'_> for GoogleProtobufNullVisitor { type Value = i32; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "null") } fn visit_str(self, v: &str) -> Result where E: Error, { if v == "NULL_VALUE" { Ok(0) } else { Err(Error::custom("expected null")) } } #[inline] fn visit_unit(self) -> Result where E: Error, { Ok(0) } } impl Visitor<'_> for GoogleProtobufTimestampVisitor { type Value = prost_types::Timestamp; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a rfc3339 timestamp string") } fn visit_str(self, v: &str) -> Result where E: Error, { validate_strict_rfc3339(v).map_err(Error::custom)?; let timestamp: prost_types::Timestamp = v.parse().map_err(Error::custom)?; check_timestamp(×tamp).map_err(Error::custom)?; Ok(timestamp) } } impl Visitor<'_> for GoogleProtobufDurationVisitor { type Value = prost_types::Duration; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a duration string") } fn visit_str(self, v: &str) -> Result where E: Error, { let duration: prost_types::Duration = v.parse().map_err(Error::custom)?; check_duration(&duration).map_err(Error::custom)?; Ok(duration) } } impl Visitor<'_> for GoogleProtobufFieldMaskVisitor { type Value = prost_types::FieldMask; fn visit_str(self, v: &str) -> Result where E: Error, { let paths = v .split(',') .filter(|path| !path.is_empty()) .map(|path| { let mut result = String::new(); let mut parts = path.split('.'); if let Some(part) = parts.next() { camel_case_to_snake_case(&mut result, part)?; } for part in parts { result.push('.'); camel_case_to_snake_case(&mut result, part)?; } Ok(result) }) .collect::>() .map_err(|()| Error::custom("invalid field mask"))?; Ok(prost_types::FieldMask { paths }) } fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a field mask string") } } impl<'de> DeserializeSeed<'de> for GoogleProtobufValueVisitor { type Value = prost_types::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_any(self) } } impl<'de> Visitor<'de> for GoogleProtobufListVisitor { type Value = prost_types::ListValue; fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let mut values = Vec::with_capacity(seq.size_hint().unwrap_or(0)); while let Some(value) = seq.next_element_seed(GoogleProtobufValueVisitor)? { values.push(value); } Ok(prost_types::ListValue { values }) } fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a list") } } impl<'de> Visitor<'de> for GoogleProtobufStructVisitor { type Value = prost_types::Struct; fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut fields = BTreeMap::new(); while let Some(key) = map.next_key::()? { let value = map.next_value_seed(GoogleProtobufValueVisitor)?; fields.insert(key, value); } Ok(prost_types::Struct { fields }) } fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a map") } } impl<'de> Visitor<'de> for GoogleProtobufValueVisitor { type Value = prost_types::Value; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a value") } fn visit_bool(self, v: bool) -> Result where E: Error, { Ok(prost_types::Value { kind: Some(prost_types::value::Kind::BoolValue(v)), }) } fn visit_i64(self, v: i64) -> Result where E: Error, { self.visit_f64(v as f64) } fn visit_u64(self, v: u64) -> Result where E: Error, { self.visit_f64(v as f64) } fn visit_f64(self, v: f64) -> Result where E: Error, { Ok(prost_types::Value { kind: Some(prost_types::value::Kind::NumberValue(v)), }) } fn visit_str(self, v: &str) -> Result where E: Error, { self.visit_string(v.to_owned()) } fn visit_string(self, v: String) -> Result where E: Error, { Ok(prost_types::Value { kind: Some(prost_types::value::Kind::StringValue(v)), }) } #[inline] fn visit_unit(self) -> Result where E: Error, { Ok(prost_types::Value { kind: Some(prost_types::value::Kind::NullValue(0)), }) } fn visit_seq(self, seq: A) -> Result where A: SeqAccess<'de>, { GoogleProtobufListVisitor .visit_seq(seq) .map(|l| prost_types::Value { kind: Some(prost_types::value::Kind::ListValue(l)), }) } fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { GoogleProtobufStructVisitor .visit_map(map) .map(|s| prost_types::Value { kind: Some(prost_types::value::Kind::StructValue(s)), }) } } impl<'de> Visitor<'de> for GoogleProtobufEmptyVisitor { type Value = (); fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { if map.next_entry::()?.is_some() { return Err(Error::custom("unexpected value in map")); } Ok(()) } fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "an empty map") } } fn find_field<'de, A, D>( map: &mut A, buffered_entries: &mut HashMap, serde_value::Value>, expected: &str, value_seed: D, ) -> Result where A: MapAccess<'de>, D: DeserializeSeed<'de>, { loop { match map.next_key::>()? { Some(key) if key == expected => return map.next_value_seed(value_seed), Some(key) => { buffered_entries.insert(key, map.next_value()?); } None => return Err(Error::custom(format!("expected '{expected}' field"))), } } } /// Validates the string is a valid RFC3339 timestamp, requiring upper-case /// 'T' and 'Z' characters as recommended by the conformance tests. fn validate_strict_rfc3339(v: &str) -> Result<(), String> { use std::{ascii, iter::Peekable, str::Bytes}; fn pop_digit(bytes: &mut Peekable) -> bool { bytes.next_if(u8::is_ascii_digit).is_some() } fn pop_digits(bytes: &mut Peekable, n: usize) -> bool { (0..n).all(|_| pop_digit(bytes)) } fn pop_char(p: &mut Peekable, c: u8) -> bool { p.next_if_eq(&c).is_some() } fn fmt_next(p: &mut Peekable) -> String { match p.peek() { Some(&ch) => format!("'{}'", ascii::escape_default(ch)), None => "end of string".to_owned(), } } let mut v = v.bytes().peekable(); if !(pop_digits(&mut v, 4) && pop_char(&mut v, b'-') && pop_digits(&mut v, 2) && pop_char(&mut v, b'-') && pop_digits(&mut v, 2)) { return Err("invalid rfc3339 timestamp: invalid date".to_owned()); } if !pop_char(&mut v, b'T') { return Err(format!( "invalid rfc3339 timestamp: expected 'T' but found {}", fmt_next(&mut v) )); } if !(pop_digits(&mut v, 2) && pop_char(&mut v, b':') && pop_digits(&mut v, 2) && pop_char(&mut v, b':') && pop_digits(&mut v, 2)) { return Err("invalid rfc3339 timestamp: invalid time".to_owned()); } if pop_char(&mut v, b'.') { if !pop_digit(&mut v) { return Err("invalid rfc3339 timestamp: empty fractional seconds".to_owned()); } while pop_digit(&mut v) {} } if v.next_if(|&ch| ch == b'+' || ch == b'-').is_some() { if !(pop_digits(&mut v, 2) && pop_char(&mut v, b':') && pop_digits(&mut v, 2)) { return Err("invalid rfc3339 timestamp: invalid offset".to_owned()); } } else if !pop_char(&mut v, b'Z') { return Err(format!( "invalid rfc3339 timestamp: expected 'Z', '+' or '-' but found {}", fmt_next(&mut v) )); } if v.peek().is_some() { return Err(format!( "invalid rfc3339 timestamp: expected end of string but found {}", fmt_next(&mut v) )); } Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_validate_strict_rfc3339() { macro_rules! case { ($s:expr => Ok) => { assert_eq!(validate_strict_rfc3339($s), Ok(())) }; ($s:expr => Err($e:expr)) => { assert_eq!(validate_strict_rfc3339($s).unwrap_err().to_string(), $e) }; } case!("1972-06-30T23:59:60Z" => Ok); case!("2019-03-26T14:00:00.9Z" => Ok); case!("2019-03-26T14:00:00.4999Z" => Ok); case!("2019-03-26T14:00:00.4999+10:00" => Ok); case!("2019-03-26t14:00Z" => Err("invalid rfc3339 timestamp: expected 'T' but found 't'")); case!("2019-03-26T14:00z" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26T14:00:00,999Z" => Err("invalid rfc3339 timestamp: expected 'Z', '+' or '-' but found ','")); case!("2019-03-26T10:00-04" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26T14:00.9Z" => Err("invalid rfc3339 timestamp: invalid time")); case!("20190326T1400Z" => Err("invalid rfc3339 timestamp: invalid date")); case!("2019-02-30" => Err("invalid rfc3339 timestamp: expected 'T' but found end of string")); case!("2019-03-25T24:01Z" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26T14:00+24:00" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26Z" => Err("invalid rfc3339 timestamp: expected 'T' but found 'Z'")); case!("2019-03-26+01:00" => Err("invalid rfc3339 timestamp: expected 'T' but found '+'")); case!("2019-03-26-04:00" => Err("invalid rfc3339 timestamp: expected 'T' but found '-'")); case!("2019-03-26T10:00-0400" => Err("invalid rfc3339 timestamp: invalid time")); case!("+0002019-03-26T14:00Z" => Err("invalid rfc3339 timestamp: invalid date")); case!("+2019-03-26T14:00Z" => Err("invalid rfc3339 timestamp: invalid date")); case!("002019-03-26T14:00Z" => Err("invalid rfc3339 timestamp: invalid date")); case!("019-03-26T14:00Z" => Err("invalid rfc3339 timestamp: invalid date")); case!("2019-03-26T10:00Q" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26T10:00T" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26Q" => Err("invalid rfc3339 timestamp: expected 'T' but found 'Q'")); case!("2019-03-26T" => Err("invalid rfc3339 timestamp: invalid time")); case!("2019-03-26 14:00Z" => Err("invalid rfc3339 timestamp: expected 'T' but found ' '")); case!("2019-03-26T14:00:00." => Err("invalid rfc3339 timestamp: empty fractional seconds")); } } prost-reflect-0.15.0/src/dynamic/serde/mod.rs000064400000000000000000000263421046102023000171510ustar 00000000000000mod case; mod de; mod ser; use serde::{ de::{DeserializeSeed, Deserializer}, ser::{Serialize, Serializer}, }; use crate::{DynamicMessage, MessageDescriptor}; /// Options to control serialization of messages. /// /// Used by [`DynamicMessage::serialize_with_options()`]. #[derive(Debug, Clone)] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] pub struct SerializeOptions { stringify_64_bit_integers: bool, use_enum_numbers: bool, use_proto_field_name: bool, skip_default_fields: bool, } /// Options to control deserialization of messages. /// /// Used by [`DynamicMessage::deserialize_with_options()`]. #[derive(Debug, Clone)] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] pub struct DeserializeOptions { deny_unknown_fields: bool, } #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl Serialize for DynamicMessage { /// Serialize this message into `serializer` using the [canonical JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json). /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # use serde::Serialize; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01".as_ref()).unwrap(); /// let mut serializer = serde_json::Serializer::new(vec![]); /// dynamic_message.serialize(&mut serializer).unwrap(); /// assert_eq!(serializer.into_inner(), b"{\"foo\":150}"); /// ``` fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.serialize_with_options(serializer, &Default::default()) } } #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl<'de> DeserializeSeed<'de> for MessageDescriptor { type Value = DynamicMessage; /// Deserialize a [`DynamicMessage`] from `deserializer` using the [canonical JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json). /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// use serde::de::DeserializeSeed; /// /// let json = r#"{ "foo": 150 }"#; /// let mut deserializer = serde_json::de::Deserializer::from_str(json); /// let dynamic_message = message_descriptor.deserialize(&mut deserializer).unwrap(); /// deserializer.end().unwrap(); /// /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); /// ``` fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { DynamicMessage::deserialize(self, deserializer) } } impl DynamicMessage { /// Serialize this message into `serializer` using the encoding specified by `options`. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, SerializeOptions}; /// # use serde::Serialize; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::new(message_descriptor); /// let mut serializer = serde_json::Serializer::new(vec![]); /// let mut options = SerializeOptions::new().skip_default_fields(false); /// dynamic_message.serialize_with_options(&mut serializer, &options).unwrap(); /// assert_eq!(serializer.into_inner(), b"{\"foo\":0}"); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] pub fn serialize_with_options( &self, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { ser::serialize_message(self, serializer, options) } /// Deserialize an instance of the message type described by `desc` from `deserializer`. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let json = r#"{ "foo": 150 }"#; /// let mut deserializer = serde_json::de::Deserializer::from_str(json); /// let dynamic_message = DynamicMessage::deserialize(message_descriptor, &mut deserializer).unwrap(); /// deserializer.end().unwrap(); /// /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] pub fn deserialize<'de, D>(desc: MessageDescriptor, deserializer: D) -> Result where D: Deserializer<'de>, { Self::deserialize_with_options(desc, deserializer, &Default::default()) } /// Deserialize an instance of the message type described by `desc` from `deserializer`, using /// the encoding specified by `options`. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, DeserializeOptions}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let json = r#"{ "foo": 150, "unknown": true }"#; /// let mut deserializer = serde_json::de::Deserializer::from_str(json); /// let options = DeserializeOptions::new().deny_unknown_fields(false); /// let dynamic_message = DynamicMessage::deserialize_with_options(message_descriptor, &mut deserializer, &options).unwrap(); /// deserializer.end().unwrap(); /// /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] pub fn deserialize_with_options<'de, D>( desc: MessageDescriptor, deserializer: D, options: &DeserializeOptions, ) -> Result where D: Deserializer<'de>, { de::deserialize_message(&desc, deserializer, options) } } impl DeserializeOptions { /// Creates a new instance of [`DeserializeOptions`], with the default options chosen to conform to /// the standard JSON mapping. pub const fn new() -> Self { DeserializeOptions { deny_unknown_fields: true, } } /// Whether to error during deserialization when encountering unknown message fields. /// /// The default value is `true`. pub const fn deny_unknown_fields(mut self, yes: bool) -> Self { self.deny_unknown_fields = yes; self } } impl Default for DeserializeOptions { fn default() -> Self { Self::new() } } impl SerializeOptions { /// Creates a new instance of [`SerializeOptions`], with the default options chosen to conform to /// the standard JSON mapping. pub const fn new() -> Self { SerializeOptions { stringify_64_bit_integers: true, use_enum_numbers: false, use_proto_field_name: false, skip_default_fields: true, } } /// Whether to encode 64-bit integral types as strings. /// /// The spec requires encoding 64-bit integers as strings, to prevent loss of precision in JSON /// when the value cannot be represented exactly by a double. If this option is disabled, all /// numbers will be serialized as their corresponding serde types instead. /// /// The default value is `true`. pub const fn stringify_64_bit_integers(mut self, yes: bool) -> Self { self.stringify_64_bit_integers = yes; self } /// Whether to encode enum values as their numeric value. /// /// If `true`, enum values will be serialized as their integer values. Otherwise, they will be /// serialized as the string value specified in the proto file. /// /// The default value is `false`. pub const fn use_enum_numbers(mut self, yes: bool) -> Self { self.use_enum_numbers = yes; self } /// Whether to use the proto field name instead of the lowerCamelCase name in JSON field names. /// /// The default value is `false`. pub const fn use_proto_field_name(mut self, yes: bool) -> Self { self.use_proto_field_name = yes; self } /// Whether to skip fields which have their default value. /// /// If `true`, any fields for which [`has_field`][DynamicMessage::has_field] returns `false` will /// not be serialized. If `false`, they will be serialized with their default value. /// /// The default value is `true`. pub const fn skip_default_fields(mut self, yes: bool) -> Self { self.skip_default_fields = yes; self } } impl Default for SerializeOptions { fn default() -> Self { Self::new() } } const MAX_DURATION_SECONDS: u64 = 315_576_000_000; const MAX_DURATION_NANOS: u32 = 999_999_999; const MIN_TIMESTAMP_SECONDS: i64 = -62135596800; const MAX_TIMESTAMP_SECONDS: i64 = 253402300799; fn is_well_known_type(full_name: &str) -> bool { matches!( full_name, "google.protobuf.Any" | "google.protobuf.Timestamp" | "google.protobuf.Duration" | "google.protobuf.Struct" | "google.protobuf.FloatValue" | "google.protobuf.DoubleValue" | "google.protobuf.Int32Value" | "google.protobuf.Int64Value" | "google.protobuf.UInt32Value" | "google.protobuf.UInt64Value" | "google.protobuf.BoolValue" | "google.protobuf.StringValue" | "google.protobuf.BytesValue" | "google.protobuf.FieldMask" | "google.protobuf.ListValue" | "google.protobuf.Value" | "google.protobuf.Empty" ) } fn check_duration(duration: &prost_types::Duration) -> Result<(), &'static str> { if duration.seconds.unsigned_abs() > MAX_DURATION_SECONDS || duration.nanos.unsigned_abs() > MAX_DURATION_NANOS { Err("duration out of range") } else { Ok(()) } } fn check_timestamp(timestamp: &prost_types::Timestamp) -> Result<(), &'static str> { if timestamp.seconds < MIN_TIMESTAMP_SECONDS || MAX_TIMESTAMP_SECONDS < timestamp.seconds { Err("timestamp out of range") } else { Ok(()) } } prost-reflect-0.15.0/src/dynamic/serde/ser/mod.rs000064400000000000000000000176531046102023000177470ustar 00000000000000mod wkt; use base64::{display::Base64Display, prelude::BASE64_STANDARD}; use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer}; use crate::{ descriptor::Kind, dynamic::{fields::ValueAndDescriptor, serde::SerializeOptions, DynamicMessage, MapKey, Value}, ReflectMessage, }; struct SerializeWrapper<'a, T> { value: &'a T, options: &'a SerializeOptions, } pub(super) fn serialize_message( message: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { SerializeWrapper { value: message, options, } .serialize(serializer) } impl Serialize for SerializeWrapper<'_, DynamicMessage> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let message_desc = self.value.descriptor(); if let Some(serialize) = wkt::get_well_known_type_serializer(message_desc.full_name()) { serialize(self.value, serializer, self.options) } else { let mut map = serializer.serialize_map(None)?; serialize_dynamic_message_fields(&mut map, self.value, self.options)?; map.end() } } } fn serialize_dynamic_message_fields( map: &mut S, value: &DynamicMessage, options: &SerializeOptions, ) -> Result<(), S::Error> where S: SerializeMap, { let fields = value .fields .iter(&value.desc, !options.skip_default_fields, false); for field in fields { let (name, value, ref kind) = match field { ValueAndDescriptor::Field(value, ref field_desc) => { let name = if options.use_proto_field_name { field_desc.name() } else { field_desc.json_name() }; (name, value, field_desc.kind()) } ValueAndDescriptor::Extension(value, ref extension_desc) => { (extension_desc.json_name(), value, extension_desc.kind()) } ValueAndDescriptor::Unknown(_) => continue, }; map.serialize_entry( name, &SerializeWrapper { value: &ValueAndKind { value: value.as_ref(), kind, }, options, }, )?; } Ok(()) } struct ValueAndKind<'a> { value: &'a Value, kind: &'a Kind, } impl<'a> Serialize for SerializeWrapper<'a, ValueAndKind<'a>> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.value.value { Value::Bool(value) => serializer.serialize_bool(*value), Value::I32(value) => serializer.serialize_i32(*value), Value::I64(value) => { if self.options.stringify_64_bit_integers { serializer.collect_str(value) } else { serializer.serialize_i64(*value) } } Value::U32(value) => serializer.serialize_u32(*value), Value::U64(value) => { if self.options.stringify_64_bit_integers { serializer.collect_str(value) } else { serializer.serialize_u64(*value) } } Value::F32(value) => { if value.is_finite() { serializer.serialize_f32(*value) } else if *value == f32::INFINITY { serializer.serialize_str("Infinity") } else if *value == f32::NEG_INFINITY { serializer.serialize_str("-Infinity") } else { debug_assert!(value.is_nan()); serializer.serialize_str("NaN") } } Value::F64(value) => { if value.is_finite() { serializer.serialize_f64(*value) } else if *value == f64::INFINITY { serializer.serialize_str("Infinity") } else if *value == f64::NEG_INFINITY { serializer.serialize_str("-Infinity") } else { debug_assert!(value.is_nan()); serializer.serialize_str("NaN") } } Value::String(value) => serializer.serialize_str(value), Value::Bytes(value) => { serializer.collect_str(&Base64Display::new(value, &BASE64_STANDARD)) } Value::EnumNumber(number) => { let enum_ty = match self.value.kind { Kind::Enum(enum_ty) => enum_ty, _ => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", self.value.value, self.value.kind ), }; if enum_ty.full_name() == "google.protobuf.NullValue" { serializer.serialize_none() } else if self.options.use_enum_numbers { serializer.serialize_i32(*number) } else if let Some(enum_value) = enum_ty.get_value(*number) { serializer.serialize_str(enum_value.name()) } else { serializer.serialize_i32(*number) } } Value::Message(message) => message.serialize_with_options(serializer, self.options), Value::List(values) => { let mut list = serializer.serialize_seq(Some(values.len()))?; for value in values { list.serialize_element(&SerializeWrapper { value: &ValueAndKind { value, kind: self.value.kind, }, options: self.options, })?; } list.end() } Value::Map(values) => { let value_kind = match self.value.kind { Kind::Message(message) if message.is_map_entry() => { message.map_entry_value_field().kind() } _ => panic!( "mismatch between DynamicMessage value {:?} and type {:?}", self.value.value, self.value.kind ), }; let mut map = serializer.serialize_map(Some(values.len()))?; for (key, value) in values { map.serialize_entry( &SerializeWrapper { value: key, options: self.options, }, &SerializeWrapper { value: &ValueAndKind { value, kind: &value_kind, }, options: self.options, }, )?; } map.end() } } } } impl Serialize for SerializeWrapper<'_, MapKey> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.value { MapKey::Bool(value) => serializer.collect_str(value), MapKey::I32(value) => serializer.collect_str(value), MapKey::I64(value) => serializer.collect_str(value), MapKey::U32(value) => serializer.collect_str(value), MapKey::U64(value) => serializer.collect_str(value), MapKey::String(value) => serializer.serialize_str(value), } } } prost-reflect-0.15.0/src/dynamic/serde/ser/wkt.rs000064400000000000000000000254171046102023000177720ustar 00000000000000use base64::{display::Base64Display, prelude::BASE64_STANDARD}; use prost::{DecodeError, Message}; use serde::ser::{Error, Serialize, SerializeMap, SerializeSeq, Serializer}; use crate::{ dynamic::{ get_type_url_message_name, serde::{ case::snake_case_to_camel_case, check_duration, check_timestamp, is_well_known_type, SerializeOptions, }, DynamicMessage, }, ReflectMessage, }; use super::{serialize_dynamic_message_fields, SerializeWrapper}; #[allow(type_alias_bounds)] type WellKnownTypeSerializer = fn(&DynamicMessage, S, &SerializeOptions) -> Result; pub fn get_well_known_type_serializer(full_name: &str) -> Option> where S: Serializer, { match full_name { "google.protobuf.Any" => Some(serialize_any), "google.protobuf.Timestamp" => Some(serialize_timestamp), "google.protobuf.Duration" => Some(serialize_duration), "google.protobuf.Struct" => Some(serialize_struct), "google.protobuf.FloatValue" => Some(serialize_float), "google.protobuf.DoubleValue" => Some(serialize_double), "google.protobuf.Int32Value" => Some(serialize_int32), "google.protobuf.Int64Value" => Some(serialize_int64), "google.protobuf.UInt32Value" => Some(serialize_uint32), "google.protobuf.UInt64Value" => Some(serialize_uint64), "google.protobuf.BoolValue" => Some(serialize_bool), "google.protobuf.StringValue" => Some(serialize_string), "google.protobuf.BytesValue" => Some(serialize_bytes), "google.protobuf.FieldMask" => Some(serialize_field_mask), "google.protobuf.ListValue" => Some(serialize_list), "google.protobuf.Value" => Some(serialize_value), "google.protobuf.Empty" => Some(serialize_empty), _ => { debug_assert!(!is_well_known_type(full_name)); None } } } fn serialize_any( msg: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: prost_types::Any = msg.transcode_to().map_err(decode_to_ser_err)?; let message_name = get_type_url_message_name(&raw.type_url).map_err(Error::custom)?; let message_desc = msg .descriptor() .parent_pool() .get_message_by_name(message_name) .ok_or_else(|| Error::custom(format!("message '{}' not found", message_name)))?; let mut payload_message = DynamicMessage::new(message_desc); payload_message .merge(raw.value.as_ref()) .map_err(decode_to_ser_err)?; if is_well_known_type(message_name) { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("@type", &raw.type_url)?; map.serialize_entry( "value", &SerializeWrapper { value: &payload_message, options, }, )?; map.end() } else { let mut map = serializer.serialize_map(None)?; map.serialize_entry("@type", &raw.type_url)?; serialize_dynamic_message_fields(&mut map, &payload_message, options)?; map.end() } } fn serialize_timestamp( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let timestamp: prost_types::Timestamp = msg.transcode_to().map_err(decode_to_ser_err)?; check_timestamp(×tamp).map_err(Error::custom)?; serializer.collect_str(×tamp) } fn serialize_duration( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let duration: prost_types::Duration = msg.transcode_to().map_err(decode_to_ser_err)?; check_duration(&duration).map_err(Error::custom)?; serializer.collect_str(&duration) } fn serialize_float( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: f32 = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.serialize_f32(raw) } fn serialize_double( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: f64 = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.serialize_f64(raw) } fn serialize_int32( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: i32 = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.serialize_i32(raw) } fn serialize_int64( msg: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: i64 = msg.transcode_to().map_err(decode_to_ser_err)?; if options.stringify_64_bit_integers { serializer.collect_str(&raw) } else { serializer.serialize_i64(raw) } } fn serialize_uint32( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: u32 = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.serialize_u32(raw) } fn serialize_uint64( msg: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: u64 = msg.transcode_to().map_err(decode_to_ser_err)?; if options.stringify_64_bit_integers { serializer.collect_str(&raw) } else { serializer.serialize_u64(raw) } } fn serialize_bool( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: bool = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.serialize_bool(raw) } fn serialize_string( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: String = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.serialize_str(&raw) } fn serialize_bytes( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: Vec = msg.transcode_to().map_err(decode_to_ser_err)?; serializer.collect_str(&Base64Display::new(&raw, &BASE64_STANDARD)) } fn serialize_field_mask( msg: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: prost_types::FieldMask = msg.transcode_to().map_err(decode_to_ser_err)?; let mut result = String::new(); for path in raw.paths { if !result.is_empty() { result.push(','); } let mut first = true; for part in path.split('.') { if !first { result.push('.'); } snake_case_to_camel_case(&mut result, part) .map_err(|()| Error::custom("cannot roundtrip field name through camelcase"))?; first = false; } } serializer.serialize_str(&result) } fn serialize_empty( _: &DynamicMessage, serializer: S, _options: &SerializeOptions, ) -> Result where S: Serializer, { serializer.collect_map(std::iter::empty::<((), ())>()) } fn serialize_value( msg: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: prost_types::Value = msg.transcode_to().map_err(decode_to_ser_err)?; serialize_value_inner(&raw, serializer, options) } fn serialize_struct( msg: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: prost_types::Struct = msg.transcode_to().map_err(decode_to_ser_err)?; serialize_struct_inner(&raw, serializer, options) } fn serialize_list( msg: &DynamicMessage, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let raw: prost_types::ListValue = msg.transcode_to().map_err(decode_to_ser_err)?; serialize_list_inner(&raw, serializer, options) } impl Serialize for SerializeWrapper<'_, prost_types::Value> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serialize_value_inner(self.value, serializer, self.options) } } fn serialize_value_inner( raw: &prost_types::Value, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { match &raw.kind { None | Some(prost_types::value::Kind::NullValue(_)) => serializer.serialize_none(), Some(prost_types::value::Kind::BoolValue(value)) => serializer.serialize_bool(*value), Some(prost_types::value::Kind::NumberValue(number)) => { if number.is_finite() { serializer.serialize_f64(*number) } else { Err(Error::custom( "cannot serialize non-finite double in google.protobuf.Value", )) } } Some(prost_types::value::Kind::StringValue(value)) => serializer.serialize_str(value), Some(prost_types::value::Kind::ListValue(value)) => { serialize_list_inner(value, serializer, options) } Some(prost_types::value::Kind::StructValue(value)) => { serialize_struct_inner(value, serializer, options) } } } fn serialize_struct_inner( raw: &prost_types::Struct, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let mut map = serializer.serialize_map(Some(raw.fields.len()))?; for (key, value) in &raw.fields { map.serialize_entry(key, &SerializeWrapper { value, options })?; } map.end() } fn serialize_list_inner( raw: &prost_types::ListValue, serializer: S, options: &SerializeOptions, ) -> Result where S: Serializer, { let mut list = serializer.serialize_seq(Some(raw.values.len()))?; for value in &raw.values { list.serialize_element(&SerializeWrapper { value, options })?; } list.end() } fn decode_to_ser_err(err: DecodeError) -> E where E: Error, { Error::custom(format!("error decoding: {}", err)) } prost-reflect-0.15.0/src/dynamic/text_format/format.rs000064400000000000000000000352071046102023000211140ustar 00000000000000use std::fmt::{self, Write}; use prost::Message; use crate::{ dynamic::{ fields::ValueAndDescriptor, fmt_string, get_type_url_message_name, text_format::FormatOptions, unknown::{UnknownField, UnknownFieldSet, UnknownFieldValue}, }, DynamicMessage, Kind, MapKey, Value, }; pub(in crate::dynamic) struct Writer<'a, W> { options: FormatOptions, f: &'a mut W, indent_level: u32, } impl<'a, W> Writer<'a, W> where W: Write, { pub fn new(options: FormatOptions, f: &'a mut W) -> Self { Writer { options, f, indent_level: 0, } } pub fn fmt_message(&mut self, message: &DynamicMessage) -> fmt::Result { if self.options.expand_any { if let Some((type_url, body)) = as_any(message) { self.f.write_char('[')?; self.f.write_str(&type_url)?; self.f.write_str("]")?; self.fmt_field_value(&Value::Message(body), None)?; return Ok(()); } } let fields = message.fields.iter( &message.desc, !self.options.skip_default_fields, self.options.print_message_fields_in_index_order, ); if self.options.skip_unknown_fields { self.fmt_delimited( fields.filter(|f| !matches!(f, ValueAndDescriptor::Unknown(..))), Writer::fmt_message_field, ) } else { self.fmt_delimited(fields, Writer::fmt_message_field) } } pub fn fmt_value(&mut self, value: &Value, kind: Option<&Kind>) -> fmt::Result { match value { Value::Bool(value) => write!(self.f, "{}", value), Value::I32(value) => write!(self.f, "{}", value), Value::I64(value) => write!(self.f, "{}", value), Value::U32(value) => write!(self.f, "{}", value), Value::U64(value) => write!(self.f, "{}", value), Value::F32(value) => { if value.fract() == 0.0 { write!(self.f, "{:.1}", value) } else { write!(self.f, "{}", value) } } Value::F64(value) => { if value.fract() == 0.0 { write!(self.f, "{:.1}", value) } else { write!(self.f, "{}", value) } } Value::String(s) => self.fmt_string(s.as_bytes()), Value::Bytes(s) => self.fmt_string(s.as_ref()), Value::EnumNumber(value) => { if let Some(Kind::Enum(desc)) = kind { if let Some(value) = desc.get_value(*value) { return self.f.write_str(value.name()); } } write!(self.f, "{}", value) } Value::Message(message) => { let mut fields = message.fields.iter( &message.desc, !self.options.skip_default_fields, self.options.print_message_fields_in_index_order, ); if fields.all(|f| { self.options.skip_unknown_fields && matches!(f, ValueAndDescriptor::Unknown(..)) }) { self.f.write_str("{}") } else if self.options.pretty { self.f.write_char('{')?; self.indent_level += 2; self.fmt_newline()?; self.fmt_message(message)?; self.indent_level -= 2; self.fmt_newline()?; self.f.write_char('}') } else { self.f.write_char('{')?; self.fmt_message(message)?; self.f.write_char('}') } } Value::List(list) => { self.fmt_list(list.iter(), |this, value| this.fmt_value(value, kind)) } Value::Map(map) => { let value_kind = kind .and_then(|k| k.as_message()) .map(|m| m.map_entry_value_field().kind()); self.fmt_list(map.iter(), |this, (key, value)| { if this.options.pretty { this.f.write_str("{")?; this.indent_level += 2; this.fmt_newline()?; this.f.write_str("key: ")?; this.fmt_map_key(key)?; this.fmt_newline()?; this.f.write_str("value")?; this.fmt_field_value(value, value_kind.as_ref())?; this.indent_level -= 2; this.fmt_newline()?; this.f.write_char('}') } else { this.f.write_str("{key:")?; this.fmt_map_key(key)?; this.f.write_str(",value")?; this.fmt_field_value(value, value_kind.as_ref())?; this.f.write_char('}') } }) } } } fn fmt_map_key(&mut self, value: &MapKey) -> fmt::Result { match value { MapKey::Bool(value) => write!(self.f, "{}", value), MapKey::I32(value) => write!(self.f, "{}", value), MapKey::I64(value) => write!(self.f, "{}", value), MapKey::U32(value) => write!(self.f, "{}", value), MapKey::U64(value) => write!(self.f, "{}", value), MapKey::String(s) => self.fmt_string(s.as_bytes()), } } fn fmt_message_field(&mut self, field: ValueAndDescriptor) -> fmt::Result { match field { ValueAndDescriptor::Field(value, desc) => { if desc.is_group() { write!(self.f, "{}", desc.kind().as_message().unwrap().name())?; } else { write!(self.f, "{}", desc.name())?; } self.fmt_field_value(&value, Some(&desc.kind())) } ValueAndDescriptor::Extension(value, desc) => { write!(self.f, "[{}]", desc.full_name())?; self.fmt_field_value(&value, Some(&desc.kind())) } ValueAndDescriptor::Unknown(values) => { self.fmt_delimited(values.iter(), Writer::fmt_unknown_field) } } } fn fmt_field_value(&mut self, value: &Value, kind: Option<&Kind>) -> fmt::Result { if !matches!(value, Value::Message(_)) { self.f.write_char(':')?; } self.fmt_padding()?; self.fmt_value(value, kind) } pub fn fmt_unknown_field(&mut self, field: &UnknownField) -> fmt::Result { write!(self.f, "{}", field.number())?; match field.value() { UnknownFieldValue::Varint(int) => { self.f.write_char(':')?; self.fmt_padding()?; write!(self.f, "{}", int) } UnknownFieldValue::ThirtyTwoBit(bytes) => { self.f.write_char(':')?; self.fmt_padding()?; write!(self.f, "0x{:08x}", u32::from_le_bytes(*bytes)) } UnknownFieldValue::SixtyFourBit(bytes) => { self.f.write_char(':')?; self.fmt_padding()?; write!(self.f, "0x{:016x}", u64::from_le_bytes(*bytes)) } UnknownFieldValue::LengthDelimited(bytes) => { if !bytes.is_empty() { if let Ok(set) = UnknownFieldSet::decode(bytes.clone()) { self.fmt_padding()?; return self.fmt_unknown_field_set(&set); } } self.f.write_char(':')?; self.fmt_padding()?; self.fmt_string(bytes.as_ref()) } UnknownFieldValue::Group(set) => { self.fmt_padding()?; self.fmt_unknown_field_set(set) } } } fn fmt_unknown_field_set(&mut self, set: &UnknownFieldSet) -> fmt::Result { if set.is_empty() { self.f.write_str("{}") } else if self.options.pretty { self.f.write_char('{')?; self.indent_level += 2; self.fmt_newline()?; self.fmt_delimited(set.iter(), Writer::fmt_unknown_field)?; self.indent_level -= 2; self.fmt_newline()?; self.f.write_char('}') } else { self.f.write_char('{')?; self.fmt_delimited(set.iter(), Writer::fmt_unknown_field)?; self.f.write_char('}') } } fn fmt_string(&mut self, bytes: &[u8]) -> fmt::Result { fmt_string(&mut self.f, bytes) } fn fmt_delimited( &mut self, mut iter: impl Iterator, f: impl Fn(&mut Self, T) -> fmt::Result, ) -> fmt::Result { if let Some(first) = iter.next() { f(self, first)?; } for item in iter { if self.options.pretty { self.fmt_newline()?; } else { self.f.write_char(',')?; } f(self, item)?; } Ok(()) } fn fmt_list( &mut self, mut iter: impl Iterator, f: impl Fn(&mut Self, I) -> fmt::Result, ) -> fmt::Result { self.f.write_char('[')?; if let Some(first) = iter.next() { f(self, first)?; } for item in iter { self.f.write_char(',')?; self.fmt_padding()?; f(self, item)?; } self.f.write_char(']') } fn fmt_padding(&mut self) -> fmt::Result { if self.options.pretty { self.f.write_char(' ')?; } Ok(()) } fn fmt_newline(&mut self) -> fmt::Result { self.f.write_char('\n')?; for _ in 0..self.indent_level { self.f.write_char(' ')?; } Ok(()) } } fn as_any(message: &DynamicMessage) -> Option<(String, DynamicMessage)> { if message.desc.full_name() != "google.protobuf.Any" { return None; } let any = message.transcode_to::().ok()?; let message_name = get_type_url_message_name(&any.type_url).ok()?; let desc = message .desc .parent_pool() .get_message_by_name(message_name)?; let body = DynamicMessage::decode(desc, any.value.as_slice()).ok()?; Some((any.type_url, body)) } #[cfg(test)] #[cfg(feature = "text-format")] mod tests { use super::*; use crate::ReflectMessage; fn fmt_unknown(value: &UnknownFieldSet) -> String { let mut string = String::new(); Writer::new(FormatOptions::new().skip_unknown_fields(false), &mut string) .fmt_delimited(value.iter(), Writer::fmt_unknown_field) .unwrap(); string } fn fmt_unknown_pretty(value: &UnknownFieldSet) -> String { let mut string = String::new(); Writer::new( FormatOptions::new().skip_unknown_fields(false).pretty(true), &mut string, ) .fmt_delimited(value.iter(), Writer::fmt_unknown_field) .unwrap(); string } #[test] fn fmt_unknown_scalar() { let value = UnknownFieldSet::decode(b"\x09\x9a\x99\x99\x99\x99\x99\xf1\x3f\x15\xcd\xcc\x0c\x40\x18\x03\x20\x04\x28\x05\x30\x06\x38\x0e\x40\x10\x4d\x09\x00\x00\x00\x51\x0a\x00\x00\x00\x00\x00\x00\x00\x5d\x0b\x00\x00\x00\x61\x0c\x00\x00\x00\x00\x00\x00\x00\x68\x01\x72\x01\x35\x7a\x07\x69\xa6\xbe\x6d\xb6\xff\x58".as_ref()).unwrap(); assert_eq!( fmt_unknown(&value), r#"1:0x3ff199999999999a,2:0x400ccccd,3:3,4:4,5:5,6:6,7:14,8:16,9:0x00000009,10:0x000000000000000a,11:0x0000000b,12:0x000000000000000c,13:1,14:"5",15:"i\246\276m\266\377X""# ); assert_eq!( fmt_unknown_pretty(&value), r#"1: 0x3ff199999999999a 2: 0x400ccccd 3: 3 4: 4 5: 5 6: 6 7: 14 8: 16 9: 0x00000009 10: 0x000000000000000a 11: 0x0000000b 12: 0x000000000000000c 13: 1 14: "5" 15: "i\246\276m\266\377X""# ); } #[test] fn fmt_unknown_complex_type() { let value = UnknownFieldSet::decode(b"\x0a\x15\x0a\x01\x31\x12\x10\x09\x9a\x99\x99\x99\x99\x99\xf1\x3f\x15\xcd\xcc\x0c\x40\x18\x03\x12\x0d\x08\x03\x12\x09\x38\x0e\x40\x10\x4d\x09\x00\x00\x00\x1a\x16\x5d\x0b\x00\x00\x00\x61\x0c\x00\x00\x00\x00\x00\x00\x00\x68\x01\x72\x01\x35\x7a\x01\x36\x22\x0e\x00\x01\x02\x03\xfc\xff\xff\xff\xff\xff\xff\xff\xff\x01\x28\x01".as_ref()).unwrap(); assert_eq!( fmt_unknown(&value), r#"1{1:"1",2{1:0x3ff199999999999a,2:0x400ccccd,3:3}},2{1:3,2{7:14,8:16,9:0x00000009}},3{11:0x0000000b,12:0x000000000000000c,13:1,14:"5",15:"6"},4:"\000\001\002\003\374\377\377\377\377\377\377\377\377\001",5:1"# ); assert_eq!( fmt_unknown_pretty(&value), r#"1 { 1: "1" 2 { 1: 0x3ff199999999999a 2: 0x400ccccd 3: 3 } } 2 { 1: 3 2 { 7: 14 8: 16 9: 0x00000009 } } 3 { 11: 0x0000000b 12: 0x000000000000000c 13: 1 14: "5" 15: "6" } 4: "\000\001\002\003\374\377\377\377\377\377\377\377\377\001" 5: 1"# ); } #[test] fn fmt_unknown_group() { let value = UnknownFieldSet::decode(b"\x0b\x0a\x03\x62\x61\x72\x0c\x13\x0a\x03\x66\x6f\x6f\x10\xfb\xff\xff\xff\xff\xff\xff\xff\xff\x01\x14\x1b\x0a\x00\x1c\x1b\x0a\x05\x68\x65\x6c\x6c\x6f\x10\x0a\x1c".as_ref()).unwrap(); assert_eq!( fmt_unknown(&value), r#"1{1:"bar"},2{1:"foo",2:18446744073709551611},3{1:""},3{1:"hello",2:10}"# ); assert_eq!( fmt_unknown_pretty(&value), r#"1 { 1: "bar" } 2 { 1: "foo" 2: 18446744073709551611 } 3 { 1: "" } 3 { 1: "hello" 2: 10 }"# ); } #[test] fn fmt_include_default() { let timestamp: prost_types::Timestamp = Default::default(); let message = timestamp.transcode_to_dynamic(); let mut string = String::new(); Writer::new(FormatOptions::new().skip_default_fields(false), &mut string) .fmt_message(&message) .unwrap(); assert_eq!(string, "seconds:0,nanos:0"); } } prost-reflect-0.15.0/src/dynamic/text_format/mod.rs000064400000000000000000000230341046102023000203760ustar 00000000000000mod format; #[cfg(feature = "text-format")] mod parse; #[cfg(feature = "text-format")] pub use self::parse::ParseError; #[cfg(feature = "text-format")] use crate::{DynamicMessage, MessageDescriptor}; pub(super) use self::format::Writer; /// Options to control printing of the protobuf text format. /// /// Used by [`DynamicMessage::to_text_format_with_options()`]. #[derive(Debug, Clone)] #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub struct FormatOptions { pretty: bool, skip_unknown_fields: bool, expand_any: bool, skip_default_fields: bool, print_message_fields_in_index_order: bool, } #[cfg(feature = "text-format")] impl DynamicMessage { /// Parse a [`DynamicMessage`] from the given message encoded using the [text format](https://developers.google.com/protocol-buffers/docs/text-format-spec). /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::parse_text_format(message_descriptor, "foo: 150").unwrap(); /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub fn parse_text_format(desc: MessageDescriptor, input: &str) -> Result { let mut message = DynamicMessage::new(desc); message.merge_text_format(input)?; Ok(message) } /// Merges the given message encoded using the [text format](https://developers.google.com/protocol-buffers/docs/text-format-spec) into this message. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let mut dynamic_message = DynamicMessage::new(message_descriptor); /// dynamic_message.merge_text_format("foo: 150").unwrap(); /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150)); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub fn merge_text_format(&mut self, input: &str) -> Result<(), ParseError> { parse::Parser::new(input) .parse_message(self) .map_err(|kind| ParseError::new(kind, input)) } /// Formats this dynamic message using the protobuf text format, with default options. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, text_format::FormatOptions}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01\x1a\x02\x10\x42".as_ref()).unwrap(); /// assert_eq!(dynamic_message.to_text_format(), "foo:150,nested{bar:66}"); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub fn to_text_format(&self) -> String { self.to_text_format_with_options(&FormatOptions::new()) } /// Formats this dynamic message using the protobuf text format, with custom options. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, text_format::FormatOptions}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap(); /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01\x1a\x02\x10\x42".as_ref()).unwrap(); /// let options = FormatOptions::new().pretty(true); /// assert_eq!(dynamic_message.to_text_format_with_options(&options), "foo: 150\nnested {\n bar: 66\n}"); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub fn to_text_format_with_options(&self, options: &FormatOptions) -> String { let mut result = String::new(); format::Writer::new(options.clone(), &mut result) .fmt_message(self) .expect("writing to string cannot fail"); result } } impl FormatOptions { /// Creates new instance of [`FormatOptions`] with default options. pub fn new() -> Self { FormatOptions::default() } /// Whether to prettify the format output. /// /// If set to `true`, each field will be printed on a new line, and nested messages will be indented. /// /// The default value is `false`. pub fn pretty(mut self, yes: bool) -> Self { self.pretty = yes; self } /// Whether to include unknown fields in the output. /// /// If set to `false`, unknown fields will be printed. The protobuf format does not include type information, /// so the formatter will attempt to infer types. /// /// The default value is `true`. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, text_format::FormatOptions}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("google.protobuf.Empty").unwrap(); /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01\x1a\x02\x10\x42".as_ref()).unwrap(); /// assert_eq!(dynamic_message.to_text_format(), ""); /// let options = FormatOptions::new().skip_unknown_fields(false); /// assert_eq!(dynamic_message.to_text_format_with_options(&options), "1:150,3{2:66}"); /// ``` #[cfg(feature = "text-format")] pub fn skip_unknown_fields(mut self, yes: bool) -> Self { self.skip_unknown_fields = yes; self } /// Whether to skip fields which have their default value. /// /// If `true`, any fields for which [`has_field`][DynamicMessage::has_field] returns `false` will /// not be included. If `false`, they will be included with their default value. /// /// The default value is `true`. #[cfg(feature = "text-format")] pub fn skip_default_fields(mut self, yes: bool) -> Self { self.skip_default_fields = yes; self } /// Whether to print message fields in the order they were defined in source code. /// /// If set to `true`, message fields will be printed in the order they were defined in the source code. /// Otherwise, they will be printed in field number order. /// /// The default value is `false`. #[cfg(feature = "text-format")] pub fn print_message_fields_in_index_order(mut self, yes: bool) -> Self { self.print_message_fields_in_index_order = yes; self } /// Whether to use the expanded form of the `google.protobuf.Any` type. /// /// If set to `true`, `Any` fields will use an expanded form: /// /// ```textproto /// [type.googleapis.com/package.MyMessage] { /// foo: 150 /// } /// ``` /// /// If set to `false`, the normal text format representation will be used: /// /// ```textproto /// type_url: "type.googleapis.com/package.MyMessage" /// value: "\x08\x96\x01" /// ``` /// /// The default value is `true`. /// /// # Examples /// /// ``` /// # use prost::Message; /// # use prost_types::FileDescriptorSet; /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, text_format::FormatOptions, bytes::Bytes}; /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap(); /// let message_descriptor = pool.get_message_by_name("google.protobuf.Any").unwrap(); /// let mut dynamic_message = DynamicMessage::new(message_descriptor); /// dynamic_message.set_field_by_name("type_url", Value::String("type.googleapis.com/package.MyMessage".to_owned())); /// dynamic_message.set_field_by_name("value", Value::Bytes(Bytes::from_static(b"\x08\x96\x01\x1a\x02\x10\x42".as_ref()))); /// /// assert_eq!(dynamic_message.to_text_format(), "[type.googleapis.com/package.MyMessage]{foo:150,nested{bar:66}}"); /// let options = FormatOptions::new().expand_any(false); /// assert_eq!(dynamic_message.to_text_format_with_options(&options), r#"type_url:"type.googleapis.com/package.MyMessage",value:"\010\226\001\032\002\020B""#); /// ``` #[cfg(feature = "text-format")] pub fn expand_any(mut self, yes: bool) -> Self { self.expand_any = yes; self } } impl Default for FormatOptions { fn default() -> Self { FormatOptions { pretty: false, skip_unknown_fields: true, expand_any: true, skip_default_fields: true, print_message_fields_in_index_order: false, } } } prost-reflect-0.15.0/src/dynamic/text_format/parse/error.rs000064400000000000000000000163051046102023000220650ustar 00000000000000use logos::Span; use std::{ error::Error, fmt::{self, Display}, }; /// An error that may occur while parsing the protobuf text format. #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "text-format")))] pub struct ParseError { kind: Box, #[cfg(feature = "miette")] source: String, } impl ParseError { #[cfg(feature = "miette")] pub(crate) fn new(kind: ParseErrorKind, source: &str) -> Self { ParseError { kind: Box::new(kind), source: source.to_owned(), } } #[cfg(not(feature = "miette"))] pub(crate) fn new(kind: ParseErrorKind, _: &str) -> Self { ParseError { kind: Box::new(kind), } } } #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "miette", derive(miette::Diagnostic))] pub(crate) enum ParseErrorKind { InvalidToken { #[cfg_attr(feature = "miette", label("found here"))] span: Span, }, InvalidStringCharacters { #[cfg_attr(feature = "miette", label("invalid characters"))] span: Span, }, InvalidStringEscape { #[cfg_attr(feature = "miette", label("defined here"))] span: Span, }, InvalidUtf8String { #[cfg_attr(feature = "miette", label("defined here"))] span: Span, }, NoSpaceBetweenIntAndIdent { #[cfg_attr(feature = "miette", label("found here"))] span: Span, }, UnexpectedToken { expected: String, found: String, #[cfg_attr(feature = "miette", label("found here"))] span: Span, }, UnexpectedEof { expected: String, }, #[cfg_attr( feature = "miette", diagnostic(help("the value must be between {min} and {max} inclusive")) )] IntegerValueOutOfRange { expected: String, actual: String, min: String, max: String, #[cfg_attr(feature = "miette", label("defined here"))] span: Span, }, FieldNotFound { field_name: String, message_name: String, #[cfg_attr(feature = "miette", label("set here"))] span: Span, }, FieldAlreadySet { field_name: String, #[cfg_attr(feature = "miette", label("set here"))] span: Span, }, OneofAlreadySet { oneof_name: String, #[cfg_attr(feature = "miette", label("set here"))] span: Span, }, ExtensionNotFound { extension_name: String, message_name: String, #[cfg_attr(feature = "miette", label("set here"))] span: Span, }, MessageNotFound { message_name: String, #[cfg_attr(feature = "miette", label("used here"))] span: Span, }, EnumValueNotFound { value_name: String, enum_name: String, #[cfg_attr(feature = "miette", label("used here"))] span: Span, }, InvalidTypeForAny { #[cfg_attr(feature = "miette", label("used here"))] span: Span, }, InvalidMapKey, } impl Display for ParseErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParseErrorKind::InvalidToken { .. } => write!(f, "invalid token"), ParseErrorKind::InvalidStringCharacters { .. } => write!(f, "invalid string character"), ParseErrorKind::InvalidStringEscape { .. } => write!(f, "invalid string escape"), ParseErrorKind::InvalidUtf8String { .. } => write!(f, "string is not valid utf-8"), ParseErrorKind::NoSpaceBetweenIntAndIdent { .. } => write!( f, "whitespace is required between an integer literal and an identifier" ), ParseErrorKind::UnexpectedToken { expected, found, .. } => write!(f, "expected {}, but found '{}'", expected, found), ParseErrorKind::UnexpectedEof { expected, .. } => { write!(f, "expected {}, but reached end of input", expected) } ParseErrorKind::IntegerValueOutOfRange { expected, actual, .. } => write!( f, "expected value to be {}, but the value {} is out of range", expected, actual ), ParseErrorKind::FieldNotFound { field_name, message_name, .. } => write!( f, "field '{}' not found for message '{}'", field_name, message_name ), ParseErrorKind::FieldAlreadySet { field_name, .. } => { write!(f, "'{}' is already set", field_name,) } ParseErrorKind::OneofAlreadySet { oneof_name, .. } => { write!(f, "a value is already set for oneof '{}'", oneof_name) } ParseErrorKind::ExtensionNotFound { extension_name, message_name, .. } => { write!( f, "extension '{}' not found for message '{}'", extension_name, message_name ) } ParseErrorKind::MessageNotFound { message_name, .. } => { write!(f, "message type '{}' not found", message_name) } ParseErrorKind::EnumValueNotFound { value_name, enum_name, .. } => { write!( f, "value '{}' was not found for enum '{}'", value_name, enum_name ) } ParseErrorKind::InvalidTypeForAny { .. } => write!( f, "the field type must be 'google.protobuf.Any' to use Any expansion syntax" ), ParseErrorKind::InvalidMapKey => write!(f, "invalid value type for map key"), } } } impl Error for ParseErrorKind {} impl Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.kind.fmt(f) } } impl Error for ParseError {} #[cfg(feature = "miette")] #[cfg_attr(docsrs, doc(cfg(feature = "miette")))] impl miette::Diagnostic for ParseError { fn code<'a>(&'a self) -> Option> { self.kind.code() } fn severity(&self) -> Option { self.kind.severity() } fn help<'a>(&'a self) -> Option> { self.kind.help() } fn url<'a>(&'a self) -> Option> { self.kind.url() } fn source_code(&self) -> Option<&dyn miette::SourceCode> { Some(&self.source) } fn labels(&self) -> Option + '_>> { self.kind.labels() } fn related<'a>(&'a self) -> Option + 'a>> { self.kind.related() } fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> { self.kind.diagnostic_source() } } prost-reflect-0.15.0/src/dynamic/text_format/parse/lex.rs000064400000000000000000000417301046102023000215240ustar 00000000000000use std::{ascii, convert::TryInto, fmt}; use logos::{Lexer, Logos}; use super::error::ParseErrorKind; #[derive(Debug, Clone, Logos, PartialEq)] #[logos(extras = TokenExtras)] #[logos(skip r"[\t\v\f\r\n ]+")] #[logos(skip r"#[^\n]*\n?")] #[logos(subpattern exponent = r"[eE][+\-]?[0-9]+")] pub(crate) enum Token<'a> { #[regex("[A-Za-z_][A-Za-z0-9_]*")] Ident(&'a str), #[regex("0", |lex| int(lex, 10, 0))] #[regex("[1-9][0-9]*", |lex| int(lex, 10, 0))] #[regex("0[0-7]+", |lex| int(lex, 8, 1))] #[regex("0[xX][0-9A-Fa-f]+", |lex| int(lex, 16, 2))] IntLiteral(Int<'a>), #[regex("0[fF]", float)] #[regex("[1-9][0-9]*[fF]", float)] #[regex(r#"[0-9]+\.[0-9]*(?&exponent)?[fF]?"#, float)] #[regex(r#"[0-9]+(?&exponent)[fF]?"#, float)] #[regex(r#"\.[0-9]+(?&exponent)?[fF]?"#, float)] FloatLiteral(f64), #[regex(r#"'|""#, string)] StringLiteral(Vec), #[token(".")] Dot, #[token("-")] Minus, #[token("{")] LeftBrace, #[token("}")] RightBrace, #[token("[")] LeftBracket, #[token("]")] RightBracket, #[token("<")] LeftAngleBracket, #[token(">")] RightAngleBracket, #[token(",")] Comma, #[token(":")] Colon, #[token(";")] Semicolon, #[token("/")] ForwardSlash, } #[derive(Debug, Clone, PartialEq)] pub(crate) struct Int<'a> { pub value: &'a str, pub radix: u32, } #[derive(Default)] pub(crate) struct TokenExtras { pub error: Option, } impl fmt::Display for Token<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Token::Ident(value) => write!(f, "{}", value), Token::IntLiteral(value) => write!(f, "{}", value.value), Token::FloatLiteral(value) => { if value.fract() == 0.0 { write!(f, "{:.1}", value) } else { write!(f, "{}", value) } } Token::StringLiteral(bytes) => { write!(f, "\"")?; for &ch in bytes { write!(f, "{}", ascii::escape_default(ch))?; } write!(f, "\"")?; Ok(()) } Token::Dot => write!(f, "."), Token::Minus => write!(f, "-"), Token::LeftBrace => write!(f, "{{"), Token::RightBrace => write!(f, "}}"), Token::LeftBracket => write!(f, "["), Token::RightBracket => write!(f, "]"), Token::LeftAngleBracket => write!(f, "<"), Token::RightAngleBracket => write!(f, ">"), Token::Comma => write!(f, ","), Token::Colon => write!(f, ":"), Token::Semicolon => write!(f, ";"), Token::ForwardSlash => write!(f, "/"), } } } fn int<'a>(lex: &mut Lexer<'a, Token<'a>>, radix: u32, prefix_len: usize) -> Result, ()> { debug_assert!(lex.slice().len() > prefix_len); let span = lex.span().start + prefix_len..lex.span().end; if matches!(lex.remainder().chars().next(), Some(ch) if ch.is_ascii_alphabetic() || ch == '_') { let mut end = span.end + 1; while end < lex.source().len() && lex.source().as_bytes()[end].is_ascii_alphabetic() { end += 1; } lex.extras.error = Some(ParseErrorKind::NoSpaceBetweenIntAndIdent { span: span.start..end, }); return Err(()); } Ok(Int { value: &lex.source()[span], radix, }) } fn float<'a>(lex: &mut Lexer<'a, Token<'a>>) -> f64 { let start = lex.span().start; let last = lex.span().end - 1; let s = match lex.source().as_bytes()[last] { b'f' | b'F' => &lex.source()[start..last], _ => lex.slice(), }; s.parse().expect("failed to parse float") } fn string<'a>(lex: &mut Lexer<'a, Token<'a>>) -> Result, ()> { #[derive(Logos)] #[logos(subpattern hex = r"[0-9A-Fa-f]")] enum Component<'a> { #[regex(r#"[^\x00\n\\'"]+"#)] Unescaped(&'a str), #[regex(r#"['"]"#, terminator)] Terminator(u8), #[regex(r#"\\[xX](?&hex)(?&hex)?"#, hex_escape)] #[regex(r#"\\[0-7][0-7]?[0-7]?"#, oct_escape)] #[regex(r#"\\[abfnrtv?\\'"]"#, char_escape)] Byte(u8), #[regex(r#"\\u(?&hex)(?&hex)(?&hex)(?&hex)"#, unicode_escape)] #[regex( r#"\\U(?&hex)(?&hex)(?&hex)(?&hex)(?&hex)(?&hex)(?&hex)(?&hex)"#, unicode_escape )] Char(char), } fn terminator<'a>(lex: &mut Lexer<'a, Component<'a>>) -> u8 { debug_assert_eq!(lex.slice().len(), 1); lex.slice().bytes().next().unwrap() } fn hex_escape<'a>(lex: &mut Lexer<'a, Component<'a>>) -> u8 { u32::from_str_radix(&lex.slice()[2..], 16) .expect("expected valid hex escape") .try_into() .expect("two-digit hex escape should be valid byte") } fn oct_escape<'a>(lex: &mut Lexer<'a, Component<'a>>) -> Result { u32::from_str_radix(&lex.slice()[1..], 8) .expect("expected valid oct escape") .try_into() .map_err(drop) } fn char_escape<'a>(lex: &mut Lexer<'a, Component<'a>>) -> u8 { match lex.slice().as_bytes()[1] { b'a' => b'\x07', b'b' => b'\x08', b'f' => b'\x0c', b'n' => b'\n', b'r' => b'\r', b't' => b'\t', b'v' => b'\x0b', b'?' => b'?', b'\\' => b'\\', b'\'' => b'\'', b'"' => b'"', _ => panic!("failed to parse char escape"), } } fn unicode_escape<'a>(lex: &mut Lexer<'a, Component<'a>>) -> Option { let value = u32::from_str_radix(&lex.slice()[2..], 16).expect("expected valid hex escape"); char::from_u32(value) } let mut result = Vec::new(); let mut char_lexer = Component::lexer(lex.remainder()); let terminator = lex.slice().as_bytes()[0]; loop { match char_lexer.next() { Some(Ok(Component::Unescaped(s))) => result.extend_from_slice(s.as_bytes()), Some(Ok(Component::Terminator(t))) if t == terminator => { break; } Some(Ok(Component::Terminator(ch) | Component::Byte(ch))) => result.push(ch), Some(Ok(Component::Char(ch))) => { let mut buf = [0; 4]; result.extend_from_slice(ch.encode_utf8(&mut buf).as_bytes()); } Some(Err(())) => { let start = lex.span().end + char_lexer.span().start; let end = lex.span().end + char_lexer.span().end; if char_lexer.slice().starts_with('\\') { lex.extras.error = Some(ParseErrorKind::InvalidStringEscape { span: start..end }); } else { lex.extras.error = Some(ParseErrorKind::InvalidStringCharacters { span: start..end }); } return Err(()); } None => { lex.extras.error = Some(ParseErrorKind::UnexpectedEof { expected: "string terminator".to_owned(), }); return Err(()); } } } lex.bump(char_lexer.span().end); Ok(result) } #[cfg(test)] mod tests { use super::*; #[test] fn simple_tokens() { let source = r#"hell0 052 42 0x2A 5. 0.5 0.42e+2 2e-4 .2e+3 52e3 true false "hello \a\b\f\n\r\t\v\?\\\'\" \052 \x2a" #comment 'hello 😀' _foo"#; let mut lexer = Token::lexer(source); assert_eq!(lexer.next().unwrap(), Ok(Token::Ident("hell0"))); assert_eq!( lexer.next().unwrap(), Ok(Token::IntLiteral(Int { value: "52", radix: 8, })) ); assert_eq!( lexer.next().unwrap(), Ok(Token::IntLiteral(Int { value: "42", radix: 10, })) ); assert_eq!( lexer.next().unwrap(), Ok(Token::IntLiteral(Int { value: "2A", radix: 16, })) ); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(5.))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(0.5))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(0.42e+2))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(2e-4))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(0.2e+3))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(52e3))); assert_eq!(lexer.next().unwrap(), Ok(Token::Ident("true"))); assert_eq!(lexer.next().unwrap(), Ok(Token::Ident("false"))); assert_eq!( lexer.next().unwrap(), Ok(Token::StringLiteral( b"hello \x07\x08\x0c\n\r\t\x0b?\\'\" * *".as_ref().into() )) ); assert_eq!( lexer.next().unwrap(), Ok(Token::StringLiteral( b"hello \xF0\x9F\x98\x80".as_ref().into() )) ); assert_eq!(lexer.next().unwrap(), Ok(Token::Ident("_foo"))); assert_eq!(lexer.next(), None); assert_eq!(lexer.extras.error, None); } #[test] fn integer_overflow() { let source = "99999999999999999999999999999999999999"; let mut lexer = Token::lexer(source); assert_eq!( lexer.next(), Some(Ok(Token::IntLiteral(Int { value: "99999999999999999999999999999999999999", radix: 10, }))) ); assert_eq!(lexer.next(), None); assert_eq!(lexer.extras.error, None); } #[test] fn float_suffix() { let source = "10f 5.f 0.5f 0.42e+2f 2e-4f .2e+3f"; let mut lexer = Token::lexer(source); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(10.))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(5.))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(0.5))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(0.42e+2))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(2e-4))); assert_eq!(lexer.next().unwrap(), Ok(Token::FloatLiteral(0.2e+3))); assert_eq!(lexer.next(), None); assert_eq!(lexer.extras.error, None); } #[test] fn invalid_token() { let source = "@ foo"; let mut lexer = Token::lexer(source); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!(lexer.extras.error, None); } #[test] fn invalid_string_char() { let source = "\"\x00\" foo"; let mut lexer = Token::lexer(source); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!( lexer.extras.error, Some(ParseErrorKind::InvalidStringCharacters { span: 1..2 }) ); } #[test] fn unterminated_string() { let source = "\"hello \n foo"; let mut lexer = Token::lexer(source); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!( lexer.extras.error, Some(ParseErrorKind::InvalidStringCharacters { span: 7..8 }) ); } #[test] fn invalid_string_escape() { let source = r#""\m""#; let mut lexer = Token::lexer(source); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!( lexer.extras.error, Some(ParseErrorKind::InvalidStringEscape { span: 1..2 }) ); } #[test] fn string_escape_invalid_utf8() { let source = r#""\xFF""#; let mut lexer = Token::lexer(source); assert_eq!( lexer.next(), Some(Ok(Token::StringLiteral([0xff].as_ref().into()))) ); assert_eq!(lexer.next(), None); } #[test] fn string_unicode_escape() { let source = r"'\u0068\u0065\u006c\u006c\u006f\u0020\U0001f600'"; let mut lexer = Token::lexer(source); assert_eq!( lexer.next(), Some(Ok(Token::StringLiteral( b"hello \xF0\x9F\x98\x80".as_ref().into() ))) ); assert_eq!(lexer.next(), None); assert_eq!(lexer.extras.error, None); } #[test] fn string_invalid_unicode_escape() { let mut lexer = Token::lexer(r"'\Uffffffff'"); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!( lexer.extras.error, Some(ParseErrorKind::InvalidStringEscape { span: 1..11 }) ); } #[test] fn whitespace() { assert_eq!( Token::lexer("value: -2.0").collect::>(), vec![ Ok(Token::Ident("value")), Ok(Token::Colon), Ok(Token::Minus), Ok(Token::FloatLiteral(2.0)), ] ); assert_eq!( Token::lexer("value: - 2.0").collect::>(), vec![ Ok(Token::Ident("value")), Ok(Token::Colon), Ok(Token::Minus), Ok(Token::FloatLiteral(2.0)), ] ); assert_eq!( Token::lexer("value: -\n #comment\n 2.0").collect::>(), vec![ Ok(Token::Ident("value")), Ok(Token::Colon), Ok(Token::Minus), Ok(Token::FloatLiteral(2.0)), ] ); assert_eq!( Token::lexer("value: 2 . 0").collect::>(), vec![ Ok(Token::Ident("value")), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "2", radix: 10, })), Ok(Token::Dot), Ok(Token::IntLiteral(Int { value: "0", radix: 10, })), ] ); assert_eq!( Token::lexer("foo: 10 bar: 20").collect::>(), vec![ Ok(Token::Ident("foo")), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "10", radix: 10, })), Ok(Token::Ident("bar")), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "20", radix: 10, })), ] ); assert_eq!( Token::lexer("foo: 10,bar: 20").collect::>(), vec![ Ok(Token::Ident("foo")), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "10", radix: 10, })), Ok(Token::Comma), Ok(Token::Ident("bar")), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "20", radix: 10, })), ] ); assert_eq!( Token::lexer("foo: 10[com.foo.ext]: 20").collect::>(), vec![ Ok(Token::Ident("foo")), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "10", radix: 10, })), Ok(Token::LeftBracket), Ok(Token::Ident("com")), Ok(Token::Dot), Ok(Token::Ident("foo")), Ok(Token::Dot), Ok(Token::Ident("ext")), Ok(Token::RightBracket), Ok(Token::Colon), Ok(Token::IntLiteral(Int { value: "20", radix: 10, })), ] ); let mut lexer = Token::lexer("foo: 10bar: 20"); assert_eq!(lexer.next(), Some(Ok(Token::Ident("foo")))); assert_eq!(lexer.next(), Some(Ok(Token::Colon))); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!( lexer.extras.error, Some(ParseErrorKind::NoSpaceBetweenIntAndIdent { span: 5..10 }) ); let mut lexer = Token::lexer("bar: 20_foo"); assert_eq!(lexer.next(), Some(Ok(Token::Ident("bar")))); assert_eq!(lexer.next(), Some(Ok(Token::Colon))); assert_eq!(lexer.next(), Some(Err(()))); assert_eq!( lexer.extras.error, Some(ParseErrorKind::NoSpaceBetweenIntAndIdent { span: 5..11 }) ); } } prost-reflect-0.15.0/src/dynamic/text_format/parse/mod.rs000064400000000000000000000570031046102023000215130ustar 00000000000000mod error; mod lex; use std::{borrow::Cow, convert::TryFrom, iter::once}; use logos::{Lexer, Logos, Span}; use prost::Message; pub use self::error::ParseError; use self::{ error::ParseErrorKind, lex::{Int, Token}, }; use crate::{ descriptor::{MAP_ENTRY_KEY_NUMBER, MAP_ENTRY_VALUE_NUMBER}, dynamic::fields::FieldDescriptorLike, DynamicMessage, EnumDescriptor, FieldDescriptor, Kind, MapKey, MessageDescriptor, Value, }; pub(in crate::dynamic::text_format) struct Parser<'a> { lexer: Lexer<'a, Token<'a>>, peek: Option, Span), ParseErrorKind>>, } enum FieldName { Ident(String), Extension(String), Any(String, String), } impl<'a> Parser<'a> { pub fn new(input: &'a str) -> Self { Parser { lexer: Token::lexer(input), peek: None, } } pub fn parse_message(&mut self, message: &mut DynamicMessage) -> Result<(), ParseErrorKind> { while self.peek()?.is_some() { self.parse_field(message)?; } Ok(()) } fn parse_message_value( &mut self, message: &mut DynamicMessage, ) -> Result { let (terminator, start) = match self.peek()? { Some((Token::LeftBrace, _)) => (Token::RightBrace, self.bump()), Some((Token::LeftAngleBracket, _)) => (Token::RightAngleBracket, self.bump()), _ => self.unexpected_token("'{' or '<'")?, }; loop { match self.peek()? { Some((Token::Ident(_) | Token::LeftBracket, _)) => self.parse_field(message)?, Some((tok, _)) if tok == terminator => { let end = self.bump(); return Ok(join_span(start, end)); } _ => self.unexpected_token(format!("'{}' or a field name", terminator))?, } } } fn parse_field(&mut self, message: &mut DynamicMessage) -> Result<(), ParseErrorKind> { let (name, span) = self.parse_field_name()?; match self.peek()? { Some((Token::Colon, _)) => { self.bump(); } Some((Token::LeftBrace | Token::LeftAngleBracket, _)) => (), _ => self.unexpected_token("':' or a message value")?, }; match name { FieldName::Ident(field_name) => { let field = find_field(&message.desc, &field_name).ok_or_else(|| { ParseErrorKind::FieldNotFound { field_name, message_name: message.desc.full_name().to_owned(), span, } })?; self.parse_field_value(message, &field)?; } FieldName::Extension(extension_name) => { let extension = message .desc .get_extension_by_full_name(&extension_name) .ok_or_else(|| ParseErrorKind::ExtensionNotFound { extension_name, message_name: message.desc.full_name().to_owned(), span, })?; self.parse_field_value(message, &extension)?; } FieldName::Any(domain, message_name) => { let value_message = match message .desc .parent_pool() .get_message_by_name(&message_name) { Some(msg) => msg, None => return Err(ParseErrorKind::MessageNotFound { message_name, span }), }; let mut value = DynamicMessage::new(value_message); self.parse_message_value(&mut value)?; let type_url = format!("{}/{}", domain, message_name); let value = value.encode_to_vec(); if !(message.desc.full_name() == "google.protobuf.Any" && message .try_set_field_by_number(1, Value::String(type_url)) .is_ok() && message .try_set_field_by_number(2, Value::Bytes(value.into())) .is_ok()) { return Err(ParseErrorKind::InvalidTypeForAny { span }); } } } if matches!(self.peek()?, Some((Token::Comma | Token::Semicolon, _))) { self.bump(); } Ok(()) } fn parse_field_name(&mut self) -> Result<(FieldName, Span), ParseErrorKind> { match self.peek()? { Some((Token::Ident(ident), _)) => Ok((FieldName::Ident(ident.to_owned()), self.bump())), Some((Token::LeftBracket, _)) => { let start = self.bump(); let name_or_domain = self .parse_full_ident(&[Token::RightBracket, Token::ForwardSlash])? .into_owned(); match self.peek()? { Some((Token::RightBracket, _)) => { let end = self.bump(); Ok((FieldName::Extension(name_or_domain), join_span(start, end))) } Some((Token::ForwardSlash, _)) => { self.bump(); let type_name = self.parse_full_ident(&[Token::RightBracket])?; let end = self.expect(Token::RightBracket)?; Ok(( FieldName::Any(name_or_domain, type_name.into_owned()), join_span(start, end), )) } _ => self.unexpected_token("']' or '/'")?, } } _ => self.unexpected_token("a field name")?, } } fn parse_field_value( &mut self, message: &mut DynamicMessage, field: &impl FieldDescriptorLike, ) -> Result<(), ParseErrorKind> { if field.is_list() { let (value, _) = self.parse_repeated_value(&field.kind())?; let result = message.fields.get_mut(field).as_list_mut().unwrap(); if let Value::List(values) = value { result.extend(values); } else { result.push(value); } Ok(()) } else if field.is_map() { fn unpack(value: Value) -> Result<(MapKey, Value), ParseErrorKind> { match value { Value::Message(msg) => { let key = msg .get_field_by_number(MAP_ENTRY_KEY_NUMBER) .unwrap() .into_owned() .into_map_key() .ok_or(ParseErrorKind::InvalidMapKey)?; let value = msg .get_field_by_number(MAP_ENTRY_VALUE_NUMBER) .unwrap() .into_owned(); Ok((key, value)) } _ => panic!("map entry must be message"), } } let (value, _) = self.parse_repeated_value(&field.kind())?; let result = message.fields.get_mut(field).as_map_mut().unwrap(); if let Value::List(values) = value { for value in values { let (key, value) = unpack(value)?; result.insert(key, value); } } else { let (key, value) = unpack(value)?; result.insert(key, value); } Ok(()) } else { let kind = field.kind(); let (value, span) = self.parse_value(&kind)?; if message.fields.has(field) { return Err(ParseErrorKind::FieldAlreadySet { field_name: field.text_name().to_owned(), span, }); } else if let Some(oneof) = field.containing_oneof() { for oneof_field in oneof.fields() { if message.has_field(&oneof_field) { return Err(ParseErrorKind::OneofAlreadySet { oneof_name: oneof.name().to_owned(), span, }); } } } message.fields.set(field, value); Ok(()) } } fn parse_repeated_value(&mut self, kind: &Kind) -> Result<(Value, Span), ParseErrorKind> { match self.peek()? { Some((Token::LeftBracket, _)) => { let start = self.bump(); let mut result = Vec::new(); // Check for empty list first if let Some((Token::RightBracket, _)) = self.peek()? { let end = self.bump(); return Ok((Value::List(result), join_span(start, end))); } result.push(self.parse_value(kind)?.0); loop { match self.peek()? { Some((Token::Comma, _)) => { self.bump(); result.push(self.parse_value(kind)?.0); } Some((Token::RightBracket, _)) => { let end = self.bump(); return Ok((Value::List(result), join_span(start, end))); } _ => self.unexpected_token("',' or ']'")?, } } } _ => self.parse_value(kind), } } fn parse_value(&mut self, kind: &Kind) -> Result<(Value, Span), ParseErrorKind> { match kind { Kind::Float => { let (value, span) = self.parse_float()?; Ok((Value::F32(value as f32), span)) } Kind::Double => { let (value, span) = self.parse_float()?; Ok((Value::F64(value), span)) } Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => { let (value, span) = self.parse_i32()?; Ok((Value::I32(value), span)) } Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => { let (value, span) = self.parse_i64()?; Ok((Value::I64(value), span)) } Kind::Uint32 | Kind::Fixed32 => { let (value, span) = self.parse_u32()?; Ok((Value::U32(value), span)) } Kind::Uint64 | Kind::Fixed64 => { let (value, span) = self.parse_u64()?; Ok((Value::U64(value), span)) } Kind::Bool => { let (value, span) = self.parse_bool()?; Ok((Value::Bool(value), span)) } Kind::String => { let (value, span) = self.parse_bytes()?; match String::from_utf8(value) { Ok(value) => Ok((Value::String(value), span)), Err(_) => Err(ParseErrorKind::InvalidUtf8String { span }), } } Kind::Bytes => { let (value, span) = self.parse_bytes()?; Ok((Value::Bytes(value.into()), span)) } Kind::Message(desc) => { let mut message = DynamicMessage::new(desc.clone()); let span = self.parse_message_value(&mut message)?; Ok((Value::Message(message), span)) } Kind::Enum(desc) => { let (value, span) = self.parse_enum(desc)?; Ok((Value::EnumNumber(value), span)) } } } fn parse_float(&mut self) -> Result<(f64, Span), ParseErrorKind> { let (negative, start) = match self.peek()? { Some((Token::Minus, _)) => (true, self.bump()), Some((_, span)) => (false, span), None => self.unexpected_token("a number")?, }; let (value, end) = match self.peek()? { Some((Token::FloatLiteral(value), _)) => (value, self.bump()), Some((Token::IntLiteral(Int { value, radix: 10 }), _)) => { (value.parse().unwrap(), self.bump()) } Some((Token::Ident(value), _)) if value.eq_ignore_ascii_case("inf") || value.eq_ignore_ascii_case("infinity") => { (f64::INFINITY, self.bump()) } Some((Token::Ident(value), _)) if value.eq_ignore_ascii_case("nan") => { (f64::NAN, self.bump()) } _ => self.unexpected_token("a number")?, }; if negative { Ok((-value, join_span(start, end))) } else { Ok((value, join_span(start, end))) } } fn parse_i32(&mut self) -> Result<(i32, Span), ParseErrorKind> { let (negative, int, span) = self.parse_int()?; let converted_value = if negative { u32::from_str_radix(int.value, int.radix) .ok() .and_then(|value| { if value == (i32::MAX as u32 + 1) { Some(i32::MIN) } else { i32::try_from(value).map(|value| -value).ok() } }) } else { i32::from_str_radix(int.value, int.radix).ok() }; match converted_value { Some(value) => Ok((value, span)), None => Err(ParseErrorKind::IntegerValueOutOfRange { expected: "a signed 32-bit integer".to_owned(), actual: if negative { format!("-{}", int.value) } else { int.value.to_owned() }, min: i32::MIN.to_string(), max: i32::MAX.to_string(), span, }), } } fn parse_i64(&mut self) -> Result<(i64, Span), ParseErrorKind> { let (negative, int, span) = self.parse_int()?; let converted_value = if negative { u64::from_str_radix(int.value, int.radix) .ok() .and_then(|value| { if value == (i64::MAX as u64 + 1) { Some(i64::MIN) } else { i64::try_from(value).map(|value| -value).ok() } }) } else { i64::from_str_radix(int.value, int.radix).ok() }; match converted_value { Some(value) => Ok((value, span)), None => Err(ParseErrorKind::IntegerValueOutOfRange { expected: "a signed 64-bit integer".to_owned(), actual: if negative { format!("-{}", int.value) } else { int.value.to_owned() }, min: i64::MIN.to_string(), max: i64::MAX.to_string(), span, }), } } fn parse_u32(&mut self) -> Result<(u32, Span), ParseErrorKind> { let (negative, int, span) = self.parse_int()?; let converted_value = if negative { None } else { u32::from_str_radix(int.value, int.radix).ok() }; match converted_value { Some(value) => Ok((value, span)), None => Err(ParseErrorKind::IntegerValueOutOfRange { expected: "an unsigned 32-bit integer".to_owned(), actual: if negative { format!("-{}", int.value) } else { int.value.to_string() }, min: u32::MIN.to_string(), max: u32::MAX.to_string(), span, }), } } fn parse_u64(&mut self) -> Result<(u64, Span), ParseErrorKind> { let (negative, int, span) = self.parse_int()?; let converted_value = if negative { None } else { u64::from_str_radix(int.value, int.radix).ok() }; match converted_value { Some(value) => Ok((value, span)), None => Err(ParseErrorKind::IntegerValueOutOfRange { expected: "an unsigned 64-bit integer".to_owned(), actual: if negative { format!("-{}", int.value) } else { int.value.to_string() }, min: u64::MIN.to_string(), max: u64::MAX.to_string(), span, }), } } fn parse_int(&mut self) -> Result<(bool, Int<'a>, Span), ParseErrorKind> { let (negative, start) = match self.peek()? { Some((Token::Minus, _)) => (true, self.bump()), Some((_, span)) => (false, span), None => self.unexpected_token("an integer")?, }; let (value, end) = match self.peek()? { Some((Token::IntLiteral(value), _)) => (value, self.bump()), _ => self.unexpected_token("an integer")?, }; Ok((negative, value, join_span(start, end))) } fn parse_bool(&mut self) -> Result<(bool, Span), ParseErrorKind> { match self.peek()? { Some((Token::Ident("false"), _)) | Some((Token::Ident("False"), _)) | Some((Token::Ident("f"), _)) => Ok((false, self.bump())), Some((Token::Ident("true"), _)) | Some((Token::Ident("True"), _)) | Some((Token::Ident("t"), _)) => Ok((true, self.bump())), Some((Token::IntLiteral(v), _)) => { let value = match u8::from_str_radix(v.value, v.radix) { Ok(v) => v, Err(_e) => return self.unexpected_token("0 or 1"), }; if value == 1 { Ok((true, self.bump())) } else if value == 0 { Ok((false, self.bump())) } else { self.unexpected_token("0 or 1") } } _ => self.unexpected_token("'true' or 'false'"), } } fn parse_bytes(&mut self) -> Result<(Vec, Span), ParseErrorKind> { let (mut result, mut span) = match self.peek()? { Some((Token::StringLiteral(value), _)) => (value, self.bump()), _ => self.unexpected_token("a string")?, }; while let Some((Token::StringLiteral(value), _)) = self.peek()? { result.extend_from_slice(&value); span = join_span(span, self.bump()); } Ok((result, span)) } fn parse_enum(&mut self, desc: &EnumDescriptor) -> Result<(i32, Span), ParseErrorKind> { match self.peek()? { Some((Token::Ident(name), _)) => { let span = self.bump(); if let Some(value) = desc.get_value_by_name(name) { Ok((value.number(), span)) } else { Err(ParseErrorKind::EnumValueNotFound { value_name: name.to_owned(), enum_name: desc.full_name().to_owned(), span, }) } } Some((Token::Minus | Token::IntLiteral(_), _)) => self.parse_i32(), _ => self.unexpected_token("an enum value")?, } } fn parse_full_ident(&mut self, terminators: &[Token]) -> Result, ParseErrorKind> { let mut result = match self.peek()? { Some((Token::Ident(ident), _)) => Cow::Borrowed(ident), _ => self.unexpected_token("an identifier")?, }; self.bump(); loop { match self.peek()? { Some((Token::Dot, _)) => { self.bump(); } Some((tok, _)) if terminators.contains(&tok) => return Ok(result), _ => self.unexpected_token(fmt_expected( once(Token::Dot).chain(terminators.iter().cloned()), ))?, } match self.peek()? { Some((Token::Ident(ident), _)) => { let result = result.to_mut(); result.push('.'); result.push_str(ident); self.bump(); } _ => self.unexpected_token("an identifier")?, }; } } fn expect(&mut self, expected: Token) -> Result { if let Some((tok, _)) = self.peek()? { if tok == expected { return Ok(self.bump()); } }; self.unexpected_token(expected)? } fn bump(&mut self) -> Span { let (_, span) = self .peek .take() .expect("called bump without peek returning Some()") .expect("called bump on invalid token"); span } fn peek(&mut self) -> Result, Span)>, ParseErrorKind> { if self.peek.is_none() { self.peek = self.next(); } self.peek.clone().transpose() } fn next(&mut self) -> Option, Span), ParseErrorKind>> { debug_assert!(self.peek.is_none()); match self.lexer.next() { Some(Err(())) => Some(Err(self.lexer.extras.error.take().unwrap_or_else(|| { ParseErrorKind::InvalidToken { span: self.lexer.span(), } }))), Some(Ok(tok)) => Some(Ok((tok, self.lexer.span()))), None => None, } } fn unexpected_token(&mut self, expected: impl ToString) -> Result { match self.peek()? { Some((found, span)) => Err(ParseErrorKind::UnexpectedToken { expected: expected.to_string(), found: found.to_string(), span, }), None => Err(ParseErrorKind::UnexpectedEof { expected: expected.to_string(), }), } } } fn find_field(desc: &MessageDescriptor, name: &str) -> Option { if let Some(field) = desc.get_field_by_name(name) { if !field.is_group() { return Some(field); } } if let Some(field) = desc.get_field_by_name(&name.to_ascii_lowercase()) { if field.is_group() && name == field.kind().as_message().unwrap().name() { return Some(field); } } None } fn fmt_expected<'a>(ts: impl Iterator>) -> String { use std::fmt::Write; let ts: Vec<_> = ts.collect(); let mut s = String::with_capacity(32); write!(s, "'{}'", ts[0]).unwrap(); if ts.len() > 1 { for t in &ts[1..][..ts.len() - 2] { s.push_str(", "); write!(s, "'{}'", t).unwrap(); } s.push_str(" or "); write!(s, "'{}'", ts[ts.len() - 1]).unwrap(); } s } fn join_span(start: Span, end: Span) -> Span { start.start..end.end } prost-reflect-0.15.0/src/dynamic/unknown.rs000064400000000000000000000341761046102023000167730ustar 00000000000000use std::{fmt, slice, vec}; use prost::{ bytes::{Buf, BufMut, Bytes}, encoding::{self, DecodeContext, WireType}, DecodeError, Message, }; use crate::dynamic::text_format; /// An unknown field found when deserializing a protobuf message. /// /// A field is unknown if the message descriptor does not contain a field with the given number. This is often the /// result of a new field being added to the message definition. /// /// The [`Message`](prost::Message) implementation of [`DynamicMessage`](crate::DynamicMessage) will preserve any unknown /// fields. #[derive(Debug, Clone, PartialEq)] pub struct UnknownField { number: u32, value: UnknownFieldValue, } /// The vaalue of an unknown field in a protobuf message. #[derive(Debug, Clone, PartialEq)] pub(crate) enum UnknownFieldValue { /// An unknown field with the `Varint` wire type. Varint(u64), /// An unknown field with the `SixtyFourBit` wire type. SixtyFourBit([u8; 8]), /// An unknown field with the `LengthDelimited` wire type. LengthDelimited(Bytes), /// An unknown field with the group wire type. Group(UnknownFieldSet), /// An unknown field with the `ThirtyTwoBit` wire type. ThirtyTwoBit([u8; 4]), } #[derive(Debug, Default, Clone, PartialEq)] pub(crate) struct UnknownFieldSet { fields: Vec, } impl UnknownField { /// The number of this field as found during decoding. pub fn number(&self) -> u32 { self.number } /// The wire type of this field as found during decoding. pub fn wire_type(&self) -> WireType { match &self.value { UnknownFieldValue::Varint(_) => WireType::Varint, UnknownFieldValue::SixtyFourBit(_) => WireType::SixtyFourBit, UnknownFieldValue::LengthDelimited(_) => WireType::LengthDelimited, UnknownFieldValue::Group(_) => WireType::StartGroup, UnknownFieldValue::ThirtyTwoBit(_) => WireType::ThirtyTwoBit, } } pub(crate) fn value(&self) -> &UnknownFieldValue { &self.value } /// Encodes this field into its byte representation. pub fn encode(&self, buf: &mut B) where B: BufMut, { match &self.value { UnknownFieldValue::Varint(value) => { encoding::encode_key(self.number, WireType::Varint, buf); encoding::encode_varint(*value, buf); } UnknownFieldValue::SixtyFourBit(value) => { encoding::encode_key(self.number, WireType::SixtyFourBit, buf); buf.put_slice(value); } UnknownFieldValue::LengthDelimited(value) => { encoding::bytes::encode(self.number, value, buf); } UnknownFieldValue::Group(value) => { encoding::group::encode(self.number, value, buf); } UnknownFieldValue::ThirtyTwoBit(value) => { encoding::encode_key(self.number, WireType::ThirtyTwoBit, buf); buf.put_slice(value); } } } /// Decodes an unknown field from the given buffer. /// /// This method will read the field number and wire type from the buffer. Normally, it is useful to know /// the field number before deciding whether to treat a field as unknown. See [`decode_value`](UnknownField::decode_value) /// if you have already read the number. /// /// # Examples /// /// ``` /// # use prost_reflect::{DescriptorPool, UnknownField}; /// # use prost::encoding::{DecodeContext, WireType}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("google.protobuf.Empty").unwrap(); /// let unknown_field = UnknownField::decode(&mut b"\x1a\x02\x10\x42".as_ref(), DecodeContext::default()).unwrap(); /// assert_eq!(unknown_field.number(), 3); /// assert_eq!(unknown_field.wire_type(), WireType::LengthDelimited); /// ``` pub fn decode(buf: &mut B, ctx: DecodeContext) -> Result where B: Buf, { let (number, wire_type) = encoding::decode_key(buf)?; Self::decode_value(number, wire_type, buf, ctx) } /// Given a field number and wire type, decodes the value of an unknown field. /// /// This method assumes the field number and wire type have already been read from the buffer. /// See also [`decode`](UnknownField::decode). /// /// # Examples /// /// ``` /// # use prost_reflect::{DescriptorPool, UnknownField}; /// # use prost::encoding::{DecodeContext, WireType}; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("google.protobuf.Empty").unwrap(); /// let unknown_field = UnknownField::decode_value(3, WireType::LengthDelimited, &mut b"\x02\x10\x42".as_ref(), DecodeContext::default()).unwrap(); /// assert_eq!(unknown_field.number(), 3); /// assert_eq!(unknown_field.wire_type(), WireType::LengthDelimited); /// /// let mut buf = Vec::new(); /// unknown_field.encode(&mut buf); /// assert_eq!(buf, b"\x1a\x02\x10\x42"); /// ``` pub fn decode_value( number: u32, wire_type: WireType, buf: &mut B, ctx: DecodeContext, ) -> Result where B: Buf, { let value = match wire_type { WireType::Varint => { let value = encoding::decode_varint(buf)?; UnknownFieldValue::Varint(value) } WireType::SixtyFourBit => { let mut value = [0; 8]; if buf.remaining() < value.len() { return Err(DecodeError::new("buffer underflow")); } buf.copy_to_slice(&mut value); UnknownFieldValue::SixtyFourBit(value) } WireType::LengthDelimited => { let mut value = Bytes::default(); encoding::bytes::merge(wire_type, &mut value, buf, ctx)?; UnknownFieldValue::LengthDelimited(value) } WireType::StartGroup => { let mut value = UnknownFieldSet::default(); encoding::group::merge(number, wire_type, &mut value, buf, ctx)?; UnknownFieldValue::Group(value) } WireType::EndGroup => return Err(DecodeError::new("unexpected end group tag")), WireType::ThirtyTwoBit => { let mut value = [0; 4]; if buf.remaining() < value.len() { return Err(DecodeError::new("buffer underflow")); } buf.copy_to_slice(&mut value); UnknownFieldValue::ThirtyTwoBit(value) } }; Ok(UnknownField { number, value }) } /// Gets the length of this field when encoded to its byte representation. pub fn encoded_len(&self) -> usize { match &self.value { UnknownFieldValue::Varint(value) => { encoding::key_len(self.number) + encoding::encoded_len_varint(*value) } UnknownFieldValue::SixtyFourBit(value) => encoding::key_len(self.number) + value.len(), UnknownFieldValue::LengthDelimited(value) => { encoding::bytes::encoded_len(self.number, value) } UnknownFieldValue::Group(value) => encoding::group::encoded_len(self.number, value), UnknownFieldValue::ThirtyTwoBit(value) => encoding::key_len(self.number) + value.len(), } } } impl fmt::Display for UnknownField { /// Formats this unknown field using the protobuf text format. /// /// The protobuf format does not include type information, so the formatter will attempt to infer types. /// /// # Examples /// /// ``` /// # use prost_reflect::{DescriptorPool, UnknownField}; /// # use prost::encoding::DecodeContext; /// # let pool = DescriptorPool::decode(include_bytes!("../file_descriptor_set.bin").as_ref()).unwrap(); /// # let message_descriptor = pool.get_message_by_name("google.protobuf.Empty").unwrap(); /// let unknown_field = UnknownField::decode(&mut b"\x1a\x02\x10\x42".as_ref(), DecodeContext::default()).unwrap(); /// assert_eq!(format!("{}", unknown_field), "3{2:66}"); /// // The alternate format specifier may be used to indent the output /// assert_eq!(format!("{:#}", unknown_field), "3 {\n 2: 66\n}"); /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { text_format::Writer::new(text_format::FormatOptions::new().pretty(f.alternate()), f) .fmt_unknown_field(self) } } impl UnknownFieldSet { pub(crate) fn is_empty(&self) -> bool { self.fields.is_empty() } pub(crate) fn iter(&self) -> slice::Iter<'_, UnknownField> { self.fields.iter() } pub(crate) fn into_iter(self) -> vec::IntoIter { self.fields.into_iter() } pub(crate) fn insert(&mut self, unknown: UnknownField) { self.fields.push(unknown); } } impl Message for UnknownFieldSet { fn encode_raw(&self, buf: &mut impl BufMut) where Self: Sized, { for field in &self.fields { field.encode(buf) } } fn merge_field( &mut self, number: u32, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext, ) -> Result<(), DecodeError> where Self: Sized, { let field = UnknownField::decode_value(number, wire_type, buf, ctx)?; self.fields.push(field); Ok(()) } fn encoded_len(&self) -> usize { let mut len = 0; for field in &self.fields { len += field.encoded_len(); } len } fn clear(&mut self) { self.fields.clear(); } } impl FromIterator for UnknownFieldSet { fn from_iter(iter: T) -> Self where T: IntoIterator, { UnknownFieldSet { fields: Vec::from_iter(iter), } } } #[cfg(test)] mod tests { use prost::{ bytes::Bytes, encoding::{DecodeContext, WireType}, }; use super::{UnknownField, UnknownFieldSet, UnknownFieldValue}; fn assert_roundtrip(expected: &[u8], value: &UnknownField) { assert_eq!(expected.len(), value.encoded_len()); let mut actual = Vec::with_capacity(expected.len()); value.encode(&mut actual); assert_eq!(expected, actual.as_slice()); } #[test] fn sixty_four_bit() { let bytes = b"\x09\x9a\x99\x99\x99\x99\x99\xf1\x3ftail"; let mut buf = bytes.as_ref(); let value = UnknownField::decode(&mut buf, DecodeContext::default()).unwrap(); assert_eq!(value.number(), 1); assert_eq!(value.wire_type(), WireType::SixtyFourBit); assert_eq!( value.value(), &UnknownFieldValue::SixtyFourBit(*b"\x9a\x99\x99\x99\x99\x99\xf1\x3f") ); assert_eq!(buf, b"tail"); assert_roundtrip(bytes.strip_suffix(buf).unwrap(), &value); } #[test] fn thirty_two_bit() { let bytes = b"\x15\xcd\xcc\x0c\x40tail"; let mut buf = bytes.as_ref(); let value = UnknownField::decode(&mut buf, DecodeContext::default()).unwrap(); assert_eq!(value.number(), 2); assert_eq!(value.wire_type(), WireType::ThirtyTwoBit); assert_eq!( value.value(), &UnknownFieldValue::ThirtyTwoBit(*b"\xcd\xcc\x0c\x40") ); assert_eq!(buf, b"tail"); assert_roundtrip(bytes.strip_suffix(buf).unwrap(), &value); } #[test] fn varint() { let bytes = b"\x18\x03tail"; let mut buf = bytes.as_ref(); let value = UnknownField::decode(&mut buf, DecodeContext::default()).unwrap(); assert_eq!(value.number(), 3); assert_eq!(value.wire_type(), WireType::Varint); assert_eq!(value.value(), &UnknownFieldValue::Varint(3)); assert_eq!(buf, b"tail"); assert_roundtrip(bytes.strip_suffix(buf).unwrap(), &value); } #[test] fn length_delimited() { let bytes = b"\x7a\x07\x69\xa6\xbe\x6d\xb6\xff\x58tail"; let mut buf = bytes.as_ref(); let value = UnknownField::decode(&mut buf, DecodeContext::default()).unwrap(); assert_eq!(value.number(), 15); assert_eq!(value.wire_type(), WireType::LengthDelimited); assert_eq!( value.value(), &UnknownFieldValue::LengthDelimited(Bytes::from_static( b"\x69\xa6\xbe\x6d\xb6\xff\x58" )) ); assert_eq!(buf, b"tail"); assert_roundtrip(bytes.strip_suffix(buf).unwrap(), &value); } #[test] fn group() { let bytes = b"\x1b\x0a\x05\x68\x65\x6c\x6c\x6f\x10\x0a\x10\x0b\x1ctail"; let mut buf = bytes.as_ref(); let value = UnknownField::decode(&mut buf, DecodeContext::default()).unwrap(); assert_eq!(value.number(), 3); assert_eq!(value.wire_type(), WireType::StartGroup); assert_eq!( value.value(), &UnknownFieldValue::Group(UnknownFieldSet::from_iter([ UnknownField { number: 1, value: UnknownFieldValue::LengthDelimited(Bytes::from_static(b"hello")) }, UnknownField { number: 2, value: UnknownFieldValue::Varint(10) }, UnknownField { number: 2, value: UnknownFieldValue::Varint(11) }, ])) ); assert_eq!(buf, b"tail"); assert_roundtrip(bytes.strip_suffix(buf).unwrap(), &value); } } prost-reflect-0.15.0/src/lib.rs000064400000000000000000000025501046102023000144050ustar 00000000000000#![doc = include_str!("../doc/intro.md")] #![doc = "# Example - decoding"] #![doc = include_str!("../doc/decoding.md")] #![cfg_attr(feature = "serde", doc = "# Example - JSON mapping")] #![cfg_attr(feature = "serde", doc = include_str!("../doc/json.md"))] #![cfg_attr(feature = "derive", doc = "# Implementing [`ReflectMessage`]")] #![cfg_attr(feature = "derive", doc = include_str!("../doc/reflect.md"))] #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(missing_debug_implementations, missing_docs)] #![deny(unsafe_code)] #![doc(html_root_url = "https://docs.rs/prost-reflect/0.15.0/")] mod descriptor; mod dynamic; mod reflect; pub use {prost, prost::bytes, prost_types}; pub use self::descriptor::{ Cardinality, DescriptorError, DescriptorPool, EnumDescriptor, EnumValueDescriptor, ExtensionDescriptor, FieldDescriptor, FileDescriptor, Kind, MessageDescriptor, MethodDescriptor, OneofDescriptor, ServiceDescriptor, Syntax, }; pub use self::dynamic::{DynamicMessage, MapKey, SetFieldError, UnknownField, Value}; pub use self::reflect::ReflectMessage; #[cfg(feature = "serde")] pub use self::dynamic::{DeserializeOptions, SerializeOptions}; #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use prost_reflect_derive::ReflectMessage; #[cfg(feature = "text-format")] pub use self::dynamic::text_format; prost-reflect-0.15.0/src/reflect/mod.rs000064400000000000000000000021771046102023000160470ustar 00000000000000mod wkt; pub(crate) use wkt::make_wkt_descriptor_pool; use prost::Message; use crate::{DynamicMessage, MessageDescriptor}; /// Trait for message types that support reflection. pub trait ReflectMessage: Message { /// Gets a [`MessageDescriptor`] describing the type of this message. fn descriptor(&self) -> MessageDescriptor; /// Converts this message into an instance of [`DynamicMessage`] by going /// through the byte representation. fn transcode_to_dynamic(&self) -> DynamicMessage where Self: Sized, { let mut message = DynamicMessage::new(self.descriptor()); // This can only fail if `self.descriptor` returns a descriptor incompatible with the // actual serialized bytes. message .transcode_from(self) .expect("error converting to dynamic message"); message } } impl ReflectMessage for Box where M: ReflectMessage, { fn descriptor(&self) -> MessageDescriptor { (**self).descriptor() } } #[test] fn assert_object_safe() { fn _foo(_: Box) {} } prost-reflect-0.15.0/src/reflect/wkt.rs000064400000000000000000007265401046102023000161040ustar 00000000000000use crate::descriptor::types::descriptor_proto::ExtensionRange; use crate::descriptor::types::descriptor_proto::ReservedRange; use crate::descriptor::types::field_descriptor_proto::Label::*; use crate::descriptor::types::field_descriptor_proto::Type::*; use crate::descriptor::types::DescriptorProto; use crate::descriptor::types::EnumDescriptorProto; use crate::descriptor::types::EnumValueDescriptorProto; use crate::descriptor::types::FieldDescriptorProto; use crate::descriptor::types::FieldOptions; use crate::descriptor::types::FileDescriptorProto; use crate::descriptor::types::FileDescriptorSet; use crate::descriptor::types::FileOptions; use crate::descriptor::types::MessageOptions; use crate::descriptor::types::OneofDescriptorProto; use crate::descriptor::types::Options; use crate::prost_types::file_options::OptimizeMode::Speed; use crate::DescriptorError; use crate::{DescriptorPool, MessageDescriptor, ReflectMessage}; #[allow(deprecated)] fn make_descriptor() -> FileDescriptorSet { FileDescriptorSet { file: vec![ FileDescriptorProto { name: Some("google/protobuf/any.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![DescriptorProto { name: Some("Any".into()), field: vec![ FieldDescriptorProto { name: Some("type_url".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("typeUrl".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("value".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Bytes.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("AnyProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/anypb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: None, objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/source_context.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![DescriptorProto { name: Some("SourceContext".into()), field: vec![FieldDescriptorProto { name: Some("file_name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("fileName".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("SourceContextProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some( "google.golang.org/protobuf/types/known/sourcecontextpb".into(), ), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: None, objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/type.proto".into()), package: Some("google.protobuf".into()), dependency: vec![ "google/protobuf/any.proto".into(), "google/protobuf/source_context.proto".into(), ], public_dependency: vec![], weak_dependency: vec![], message_type: vec![ DescriptorProto { name: Some("Type".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("fields".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Field".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("fields".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("oneofs".into()), number: Some(3), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("oneofs".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(4), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Option".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("source_context".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.SourceContext".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("sourceContext".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("syntax".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.Syntax".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("syntax".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Field".into()), field: vec![ FieldDescriptorProto { name: Some("kind".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.Field.Kind".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("kind".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("cardinality".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.Field.Cardinality".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("cardinality".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("number".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("number".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("name".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("type_url".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("typeUrl".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("oneof_index".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("oneofIndex".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("packed".into()), number: Some(8), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("packed".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(9), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Option".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("json_name".into()), number: Some(10), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("jsonName".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("default_value".into()), number: Some(11), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("defaultValue".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![ EnumDescriptorProto { name: Some("Kind".into()), value: vec![ EnumValueDescriptorProto { name: Some("TYPE_UNKNOWN".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_DOUBLE".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_FLOAT".into()), number: Some(2), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_INT64".into()), number: Some(3), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_UINT64".into()), number: Some(4), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_INT32".into()), number: Some(5), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_FIXED64".into()), number: Some(6), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_FIXED32".into()), number: Some(7), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_BOOL".into()), number: Some(8), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_STRING".into()), number: Some(9), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_GROUP".into()), number: Some(10), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_MESSAGE".into()), number: Some(11), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_BYTES".into()), number: Some(12), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_UINT32".into()), number: Some(13), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_ENUM".into()), number: Some(14), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SFIXED32".into()), number: Some(15), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SFIXED64".into()), number: Some(16), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SINT32".into()), number: Some(17), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SINT64".into()), number: Some(18), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }, EnumDescriptorProto { name: Some("Cardinality".into()), value: vec![ EnumValueDescriptorProto { name: Some("CARDINALITY_UNKNOWN".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("CARDINALITY_OPTIONAL".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("CARDINALITY_REQUIRED".into()), number: Some(2), options: None, }, EnumValueDescriptorProto { name: Some("CARDINALITY_REPEATED".into()), number: Some(3), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }, ], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Enum".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("enumvalue".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.EnumValue".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("enumvalue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Option".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("source_context".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.SourceContext".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("sourceContext".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("syntax".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.Syntax".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("syntax".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("EnumValue".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("number".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("number".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Option".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Option".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("value".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Any".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![EnumDescriptorProto { name: Some("Syntax".into()), value: vec![ EnumValueDescriptorProto { name: Some("SYNTAX_PROTO2".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("SYNTAX_PROTO3".into()), number: Some(1), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("TypeProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/typepb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/api.proto".into()), package: Some("google.protobuf".into()), dependency: vec![ "google/protobuf/source_context.proto".into(), "google/protobuf/type.proto".into(), ], public_dependency: vec![], weak_dependency: vec![], message_type: vec![ DescriptorProto { name: Some("Api".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("methods".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Method".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("methods".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Option".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("version".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("version".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("source_context".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.SourceContext".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("sourceContext".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("mixins".into()), number: Some(6), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Mixin".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("mixins".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("syntax".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.Syntax".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("syntax".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Method".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("request_type_url".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("requestTypeUrl".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("request_streaming".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("requestStreaming".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("response_type_url".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("responseTypeUrl".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("response_streaming".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("responseStreaming".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(6), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Option".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("syntax".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.Syntax".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("syntax".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Mixin".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("root".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("root".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("ApiProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/apipb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: None, objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/descriptor.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![ DescriptorProto { name: Some("FileDescriptorSet".into()), field: vec![FieldDescriptorProto { name: Some("file".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FileDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("file".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("FileDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("package".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("package".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("dependency".into()), number: Some(3), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("dependency".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("public_dependency".into()), number: Some(10), label: Some(Repeated.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("publicDependency".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("weak_dependency".into()), number: Some(11), label: Some(Repeated.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("weakDependency".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("message_type".into()), number: Some(4), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.DescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("messageType".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("enum_type".into()), number: Some(5), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.EnumDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("enumType".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("service".into()), number: Some(6), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.ServiceDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("service".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("extension".into()), number: Some(7), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FieldDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("extension".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(8), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FileOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("source_code_info".into()), number: Some(9), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.SourceCodeInfo".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("sourceCodeInfo".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("syntax".into()), number: Some(12), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("syntax".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("edition".into()), number: Some(13), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("edition".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("DescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("field".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FieldDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("field".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("extension".into()), number: Some(6), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FieldDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("extension".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("nested_type".into()), number: Some(3), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.DescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("nestedType".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("enum_type".into()), number: Some(4), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.EnumDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("enumType".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("extension_range".into()), number: Some(5), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some( ".google.protobuf.DescriptorProto.ExtensionRange".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("extensionRange".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("oneof_decl".into()), number: Some(8), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.OneofDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("oneofDecl".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.MessageOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("reserved_range".into()), number: Some(9), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some( ".google.protobuf.DescriptorProto.ReservedRange".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("reservedRange".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("reserved_name".into()), number: Some(10), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("reservedName".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![ DescriptorProto { name: Some("ExtensionRange".into()), field: vec![ FieldDescriptorProto { name: Some("start".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("start".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("end".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("end".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some( ".google.protobuf.ExtensionRangeOptions".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("ReservedRange".into()), field: vec![ FieldDescriptorProto { name: Some("start".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("start".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("end".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("end".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("ExtensionRangeOptions".into()), field: vec![FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("FieldDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("number".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("number".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("label".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some( ".google.protobuf.FieldDescriptorProto.Label".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("label".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("type".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some( ".google.protobuf.FieldDescriptorProto.Type".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("type".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("type_name".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("typeName".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("extendee".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("extendee".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("default_value".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("defaultValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("oneof_index".into()), number: Some(9), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("oneofIndex".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("json_name".into()), number: Some(10), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("jsonName".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(8), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FieldOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("proto3_optional".into()), number: Some(17), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("proto3Optional".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![ EnumDescriptorProto { name: Some("Type".into()), value: vec![ EnumValueDescriptorProto { name: Some("TYPE_DOUBLE".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_FLOAT".into()), number: Some(2), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_INT64".into()), number: Some(3), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_UINT64".into()), number: Some(4), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_INT32".into()), number: Some(5), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_FIXED64".into()), number: Some(6), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_FIXED32".into()), number: Some(7), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_BOOL".into()), number: Some(8), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_STRING".into()), number: Some(9), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_GROUP".into()), number: Some(10), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_MESSAGE".into()), number: Some(11), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_BYTES".into()), number: Some(12), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_UINT32".into()), number: Some(13), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_ENUM".into()), number: Some(14), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SFIXED32".into()), number: Some(15), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SFIXED64".into()), number: Some(16), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SINT32".into()), number: Some(17), options: None, }, EnumValueDescriptorProto { name: Some("TYPE_SINT64".into()), number: Some(18), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }, EnumDescriptorProto { name: Some("Label".into()), value: vec![ EnumValueDescriptorProto { name: Some("LABEL_OPTIONAL".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("LABEL_REQUIRED".into()), number: Some(2), options: None, }, EnumValueDescriptorProto { name: Some("LABEL_REPEATED".into()), number: Some(3), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }, ], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("OneofDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.OneofOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("EnumDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("value".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.EnumValueDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.EnumOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("reserved_range".into()), number: Some(4), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some( ".google.protobuf.EnumDescriptorProto.EnumReservedRange".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("reservedRange".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("reserved_name".into()), number: Some(5), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("reservedName".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![DescriptorProto { name: Some("EnumReservedRange".into()), field: vec![ FieldDescriptorProto { name: Some("start".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("start".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("end".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("end".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("EnumValueDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("number".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("number".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.EnumValueOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("ServiceDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("method".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.MethodDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("method".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.ServiceOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("MethodDescriptorProto".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("input_type".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("inputType".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("output_type".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("outputType".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("options".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.MethodOptions".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("options".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("client_streaming".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("clientStreaming".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("server_streaming".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("serverStreaming".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("FileOptions".into()), field: vec![ FieldDescriptorProto { name: Some("java_package".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("javaPackage".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("java_outer_classname".into()), number: Some(8), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("javaOuterClassname".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("java_multiple_files".into()), number: Some(10), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("javaMultipleFiles".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("java_generate_equals_and_hash".into()), number: Some(20), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("javaGenerateEqualsAndHash".into()), options: Some(Options::from_prost(FieldOptions { ctype: None, packed: None, jstype: None, lazy: None, deprecated: Some(true), weak: None, uninterpreted_option: vec![], })), proto3_optional: None, }, FieldDescriptorProto { name: Some("java_string_check_utf8".into()), number: Some(27), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("javaStringCheckUtf8".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("optimize_for".into()), number: Some(9), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.FileOptions.OptimizeMode".into()), extendee: None, default_value: Some("SPEED".into()), oneof_index: None, json_name: Some("optimizeFor".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("go_package".into()), number: Some(11), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("goPackage".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("cc_generic_services".into()), number: Some(16), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("ccGenericServices".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("java_generic_services".into()), number: Some(17), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("javaGenericServices".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("py_generic_services".into()), number: Some(18), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("pyGenericServices".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("php_generic_services".into()), number: Some(42), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("phpGenericServices".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("deprecated".into()), number: Some(23), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("cc_enable_arenas".into()), number: Some(31), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("true".into()), oneof_index: None, json_name: Some("ccEnableArenas".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("objc_class_prefix".into()), number: Some(36), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("objcClassPrefix".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("csharp_namespace".into()), number: Some(37), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("csharpNamespace".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("swift_prefix".into()), number: Some(39), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("swiftPrefix".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("php_class_prefix".into()), number: Some(40), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("phpClassPrefix".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("php_namespace".into()), number: Some(41), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("phpNamespace".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("php_metadata_namespace".into()), number: Some(44), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("phpMetadataNamespace".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("ruby_package".into()), number: Some(45), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("rubyPackage".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![EnumDescriptorProto { name: Some("OptimizeMode".into()), value: vec![ EnumValueDescriptorProto { name: Some("SPEED".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("CODE_SIZE".into()), number: Some(2), options: None, }, EnumValueDescriptorProto { name: Some("LITE_RUNTIME".into()), number: Some(3), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![ReservedRange { start: Some(38), end: Some(39), }], reserved_name: vec![], }, DescriptorProto { name: Some("MessageOptions".into()), field: vec![ FieldDescriptorProto { name: Some("message_set_wire_format".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("messageSetWireFormat".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("no_standard_descriptor_accessor".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("noStandardDescriptorAccessor".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("deprecated".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("map_entry".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("mapEntry".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![ ReservedRange { start: Some(4), end: Some(5), }, ReservedRange { start: Some(5), end: Some(6), }, ReservedRange { start: Some(6), end: Some(7), }, ReservedRange { start: Some(8), end: Some(9), }, ReservedRange { start: Some(9), end: Some(10), }, ], reserved_name: vec![], }, DescriptorProto { name: Some("FieldOptions".into()), field: vec![ FieldDescriptorProto { name: Some("ctype".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.FieldOptions.CType".into()), extendee: None, default_value: Some("STRING".into()), oneof_index: None, json_name: Some("ctype".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("packed".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("packed".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("jstype".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.FieldOptions.JSType".into()), extendee: None, default_value: Some("JS_NORMAL".into()), oneof_index: None, json_name: Some("jstype".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("lazy".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("lazy".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("unverified_lazy".into()), number: Some(15), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("unverifiedLazy".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("deprecated".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("weak".into()), number: Some(10), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("weak".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![ EnumDescriptorProto { name: Some("CType".into()), value: vec![ EnumValueDescriptorProto { name: Some("STRING".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("CORD".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("STRING_PIECE".into()), number: Some(2), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }, EnumDescriptorProto { name: Some("JSType".into()), value: vec![ EnumValueDescriptorProto { name: Some("JS_NORMAL".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("JS_STRING".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("JS_NUMBER".into()), number: Some(2), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }, ], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![ReservedRange { start: Some(4), end: Some(5), }], reserved_name: vec![], }, DescriptorProto { name: Some("OneofOptions".into()), field: vec![FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("EnumOptions".into()), field: vec![ FieldDescriptorProto { name: Some("allow_alias".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("allowAlias".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("deprecated".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![ReservedRange { start: Some(5), end: Some(6), }], reserved_name: vec![], }, DescriptorProto { name: Some("EnumValueOptions".into()), field: vec![ FieldDescriptorProto { name: Some("deprecated".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("ServiceOptions".into()), field: vec![ FieldDescriptorProto { name: Some("deprecated".into()), number: Some(33), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("MethodOptions".into()), field: vec![ FieldDescriptorProto { name: Some("deprecated".into()), number: Some(33), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: Some("false".into()), oneof_index: None, json_name: Some("deprecated".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("idempotency_level".into()), number: Some(34), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some( ".google.protobuf.MethodOptions.IdempotencyLevel".into(), ), extendee: None, default_value: Some("IDEMPOTENCY_UNKNOWN".into()), oneof_index: None, json_name: Some("idempotencyLevel".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("uninterpreted_option".into()), number: Some(999), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.UninterpretedOption".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("uninterpretedOption".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![EnumDescriptorProto { name: Some("IdempotencyLevel".into()), value: vec![ EnumValueDescriptorProto { name: Some("IDEMPOTENCY_UNKNOWN".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("NO_SIDE_EFFECTS".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("IDEMPOTENT".into()), number: Some(2), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }], extension_range: vec![ExtensionRange { start: Some(1000), end: Some(536870912), options: None, }], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("UninterpretedOption".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some( ".google.protobuf.UninterpretedOption.NamePart".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("identifier_value".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("identifierValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("positive_int_value".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(Uint64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("positiveIntValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("negative_int_value".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Int64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("negativeIntValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("double_value".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(Double.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("doubleValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("string_value".into()), number: Some(7), label: Some(Optional.into()), r#type: Some(Bytes.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("stringValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("aggregate_value".into()), number: Some(8), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("aggregateValue".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![DescriptorProto { name: Some("NamePart".into()), field: vec![ FieldDescriptorProto { name: Some("name_part".into()), number: Some(1), label: Some(Required.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("namePart".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("is_extension".into()), number: Some(2), label: Some(Required.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("isExtension".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("SourceCodeInfo".into()), field: vec![FieldDescriptorProto { name: Some("location".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.SourceCodeInfo.Location".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("location".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![DescriptorProto { name: Some("Location".into()), field: vec![ FieldDescriptorProto { name: Some("path".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("path".into()), options: Some(Options::from_prost(FieldOptions { ctype: None, packed: Some(true), jstype: None, lazy: None, deprecated: None, weak: None, uninterpreted_option: vec![], })), proto3_optional: None, }, FieldDescriptorProto { name: Some("span".into()), number: Some(2), label: Some(Repeated.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("span".into()), options: Some(Options::from_prost(FieldOptions { ctype: None, packed: Some(true), jstype: None, lazy: None, deprecated: None, weak: None, uninterpreted_option: vec![], })), proto3_optional: None, }, FieldDescriptorProto { name: Some("leading_comments".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("leadingComments".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("trailing_comments".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("trailingComments".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("leading_detached_comments".into()), number: Some(6), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("leadingDetachedComments".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("GeneratedCodeInfo".into()), field: vec![FieldDescriptorProto { name: Some("annotation".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.GeneratedCodeInfo.Annotation".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("annotation".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![DescriptorProto { name: Some("Annotation".into()), field: vec![ FieldDescriptorProto { name: Some("path".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("path".into()), options: Some(Options::from_prost(FieldOptions { ctype: None, packed: Some(true), jstype: None, lazy: None, deprecated: None, weak: None, uninterpreted_option: vec![], })), proto3_optional: None, }, FieldDescriptorProto { name: Some("source_file".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("sourceFile".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("begin".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("begin".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("end".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("end".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("semantic".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some( ".google.protobuf.GeneratedCodeInfo.Annotation.Semantic" .into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("semantic".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![EnumDescriptorProto { name: Some("Semantic".into()), value: vec![ EnumValueDescriptorProto { name: Some("NONE".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("SET".into()), number: Some(1), options: None, }, EnumValueDescriptorProto { name: Some("ALIAS".into()), number: Some(2), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("DescriptorProtos".into()), java_multiple_files: None, java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: Some(Speed.into()), go_package: Some("google.golang.org/protobuf/types/descriptorpb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.Reflection".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: None, }, FileDescriptorProto { name: Some("google/protobuf/duration.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![DescriptorProto { name: Some("Duration".into()), field: vec![ FieldDescriptorProto { name: Some("seconds".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("seconds".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("nanos".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("nanos".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("DurationProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/durationpb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/empty.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![DescriptorProto { name: Some("Empty".into()), field: vec![], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("EmptyProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/emptypb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/field_mask.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![DescriptorProto { name: Some("FieldMask".into()), field: vec![FieldDescriptorProto { name: Some("paths".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("paths".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("FieldMaskProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/fieldmaskpb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/struct.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![ DescriptorProto { name: Some("Struct".into()), field: vec![FieldDescriptorProto { name: Some("fields".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Struct.FieldsEntry".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("fields".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![DescriptorProto { name: Some("FieldsEntry".into()), field: vec![ FieldDescriptorProto { name: Some("key".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("key".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("value".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Value".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: Some(Options::from_prost(MessageOptions { message_set_wire_format: None, no_standard_descriptor_accessor: None, deprecated: None, map_entry: Some(true), uninterpreted_option: vec![], })), reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Value".into()), field: vec![ FieldDescriptorProto { name: Some("null_value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Enum.into()), type_name: Some(".google.protobuf.NullValue".into()), extendee: None, default_value: None, oneof_index: Some(0), json_name: Some("nullValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("number_value".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Double.into()), type_name: None, extendee: None, default_value: None, oneof_index: Some(0), json_name: Some("numberValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("string_value".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: Some(0), json_name: Some("stringValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("bool_value".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: Some(0), json_name: Some("boolValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("struct_value".into()), number: Some(5), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Struct".into()), extendee: None, default_value: None, oneof_index: Some(0), json_name: Some("structValue".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("list_value".into()), number: Some(6), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.ListValue".into()), extendee: None, default_value: None, oneof_index: Some(0), json_name: Some("listValue".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![OneofDescriptorProto { name: Some("kind".into()), options: None, }], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("ListValue".into()), field: vec![FieldDescriptorProto { name: Some("values".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.Value".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("values".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![EnumDescriptorProto { name: Some("NullValue".into()), value: vec![EnumValueDescriptorProto { name: Some("NULL_VALUE".into()), number: Some(0), options: None, }], options: None, reserved_range: vec![], reserved_name: vec![], }], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("StructProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/structpb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/timestamp.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![DescriptorProto { name: Some("Timestamp".into()), field: vec![ FieldDescriptorProto { name: Some("seconds".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("seconds".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("nanos".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("nanos".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("TimestampProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/timestamppb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/wrappers.proto".into()), package: Some("google.protobuf".into()), dependency: vec![], public_dependency: vec![], weak_dependency: vec![], message_type: vec![ DescriptorProto { name: Some("DoubleValue".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Double.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("FloatValue".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Float.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Int64Value".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("UInt64Value".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Uint64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("Int32Value".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("UInt32Value".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Uint32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("BoolValue".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Bool.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("StringValue".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("BytesValue".into()), field: vec![FieldDescriptorProto { name: Some("value".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Bytes.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("value".into()), options: None, proto3_optional: None, }], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf".into()), java_outer_classname: Some("WrappersProto".into()), java_multiple_files: Some(true), java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/known/wrapperspb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: Some(true), objc_class_prefix: Some("GPB".into()), csharp_namespace: Some("Google.Protobuf.WellKnownTypes".into()), swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: Some("proto3".into()), }, FileDescriptorProto { name: Some("google/protobuf/compiler/plugin.proto".into()), package: Some("google.protobuf.compiler".into()), dependency: vec!["google/protobuf/descriptor.proto".into()], public_dependency: vec![], weak_dependency: vec![], message_type: vec![ DescriptorProto { name: Some("Version".into()), field: vec![ FieldDescriptorProto { name: Some("major".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("major".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("minor".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("minor".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("patch".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Int32.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("patch".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("suffix".into()), number: Some(4), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("suffix".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("CodeGeneratorRequest".into()), field: vec![ FieldDescriptorProto { name: Some("file_to_generate".into()), number: Some(1), label: Some(Repeated.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("fileToGenerate".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("parameter".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("parameter".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("proto_file".into()), number: Some(15), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.FileDescriptorProto".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("protoFile".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("compiler_version".into()), number: Some(3), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.compiler.Version".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("compilerVersion".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, DescriptorProto { name: Some("CodeGeneratorResponse".into()), field: vec![ FieldDescriptorProto { name: Some("error".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("error".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("supported_features".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(Uint64.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("supportedFeatures".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("file".into()), number: Some(15), label: Some(Repeated.into()), r#type: Some(Message.into()), type_name: Some( ".google.protobuf.compiler.CodeGeneratorResponse.File".into(), ), extendee: None, default_value: None, oneof_index: None, json_name: Some("file".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![DescriptorProto { name: Some("File".into()), field: vec![ FieldDescriptorProto { name: Some("name".into()), number: Some(1), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("name".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("insertion_point".into()), number: Some(2), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("insertionPoint".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("content".into()), number: Some(15), label: Some(Optional.into()), r#type: Some(String.into()), type_name: None, extendee: None, default_value: None, oneof_index: None, json_name: Some("content".into()), options: None, proto3_optional: None, }, FieldDescriptorProto { name: Some("generated_code_info".into()), number: Some(16), label: Some(Optional.into()), r#type: Some(Message.into()), type_name: Some(".google.protobuf.GeneratedCodeInfo".into()), extendee: None, default_value: None, oneof_index: None, json_name: Some("generatedCodeInfo".into()), options: None, proto3_optional: None, }, ], extension: vec![], nested_type: vec![], enum_type: vec![], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }], enum_type: vec![EnumDescriptorProto { name: Some("Feature".into()), value: vec![ EnumValueDescriptorProto { name: Some("FEATURE_NONE".into()), number: Some(0), options: None, }, EnumValueDescriptorProto { name: Some("FEATURE_PROTO3_OPTIONAL".into()), number: Some(1), options: None, }, ], options: None, reserved_range: vec![], reserved_name: vec![], }], extension_range: vec![], oneof_decl: vec![], options: None, reserved_range: vec![], reserved_name: vec![], }, ], enum_type: vec![], service: vec![], extension: vec![], options: Some(Options::from_prost(FileOptions { java_package: Some("com.google.protobuf.compiler".into()), java_outer_classname: Some("PluginProtos".into()), java_multiple_files: None, java_generate_equals_and_hash: None, java_string_check_utf8: None, optimize_for: None, go_package: Some("google.golang.org/protobuf/types/pluginpb".into()), cc_generic_services: None, java_generic_services: None, py_generic_services: None, php_generic_services: None, deprecated: None, cc_enable_arenas: None, objc_class_prefix: None, csharp_namespace: None, swift_prefix: None, php_class_prefix: None, php_namespace: None, php_metadata_namespace: None, ruby_package: None, uninterpreted_option: vec![], })), source_code_info: None, syntax: None, }, ], } } pub fn make_wkt_descriptor_pool() -> Result { let file_descriptor_set = make_descriptor(); let mut pool = DescriptorPool::new(); pool.build_files(file_descriptor_set.file.into_iter())?; Ok(pool) } macro_rules! impl_reflect_message { ($($ty:ty => $name:literal;)*) => { $( impl ReflectMessage for $ty { #[doc = concat!("Returns a descriptor for the `", $name, "` message type.")] fn descriptor(&self) -> MessageDescriptor { match DescriptorPool::global().get_message_by_name($name) { Some(desc) => desc, None => panic!("descriptor for well-known type `{}` not found", $name), } } } )* #[test] fn test_reflect_message_impls() { $( assert_eq!(<$ty>::default().descriptor().full_name(), $name); )* } }; } impl_reflect_message! { () => "google.protobuf.Empty"; bool => "google.protobuf.BoolValue"; f32 => "google.protobuf.FloatValue"; f64 => "google.protobuf.DoubleValue"; i32 => "google.protobuf.Int32Value"; i64 => "google.protobuf.Int64Value"; std::string::String => "google.protobuf.StringValue"; u32 => "google.protobuf.UInt32Value"; u64 => "google.protobuf.UInt64Value"; Vec => "google.protobuf.BytesValue"; prost_types::Any => "google.protobuf.Any"; prost_types::Api => "google.protobuf.Api"; prost_types::compiler::CodeGeneratorRequest => "google.protobuf.compiler.CodeGeneratorRequest"; prost_types::compiler::CodeGeneratorResponse => "google.protobuf.compiler.CodeGeneratorResponse"; prost_types::compiler::code_generator_response::File => "google.protobuf.compiler.CodeGeneratorResponse.File"; prost_types::compiler::Version => "google.protobuf.compiler.Version"; prost_types::DescriptorProto => "google.protobuf.DescriptorProto"; prost_types::descriptor_proto::ExtensionRange => "google.protobuf.DescriptorProto.ExtensionRange"; prost_types::descriptor_proto::ReservedRange => "google.protobuf.DescriptorProto.ReservedRange"; prost_types::Duration => "google.protobuf.Duration"; prost_types::Enum => "google.protobuf.Enum"; prost_types::EnumDescriptorProto => "google.protobuf.EnumDescriptorProto"; prost_types::enum_descriptor_proto::EnumReservedRange => "google.protobuf.EnumDescriptorProto.EnumReservedRange"; prost_types::EnumOptions => "google.protobuf.EnumOptions"; prost_types::EnumValue => "google.protobuf.EnumValue"; prost_types::EnumValueDescriptorProto => "google.protobuf.EnumValueDescriptorProto"; prost_types::EnumValueOptions => "google.protobuf.EnumValueOptions"; prost_types::ExtensionRangeOptions => "google.protobuf.ExtensionRangeOptions"; prost_types::Field => "google.protobuf.Field"; prost_types::FieldDescriptorProto => "google.protobuf.FieldDescriptorProto"; prost_types::FieldMask => "google.protobuf.FieldMask"; prost_types::FieldOptions => "google.protobuf.FieldOptions"; prost_types::FileDescriptorProto => "google.protobuf.FileDescriptorProto"; prost_types::FileDescriptorSet => "google.protobuf.FileDescriptorSet"; prost_types::FileOptions => "google.protobuf.FileOptions"; prost_types::GeneratedCodeInfo => "google.protobuf.GeneratedCodeInfo"; prost_types::generated_code_info::Annotation => "google.protobuf.GeneratedCodeInfo.Annotation"; prost_types::ListValue => "google.protobuf.ListValue"; prost_types::MessageOptions => "google.protobuf.MessageOptions"; prost_types::Method => "google.protobuf.Method"; prost_types::MethodDescriptorProto => "google.protobuf.MethodDescriptorProto"; prost_types::MethodOptions => "google.protobuf.MethodOptions"; prost_types::Mixin => "google.protobuf.Mixin"; prost_types::OneofDescriptorProto => "google.protobuf.OneofDescriptorProto"; prost_types::OneofOptions => "google.protobuf.OneofOptions"; prost_types::Option => "google.protobuf.Option"; prost_types::ServiceDescriptorProto => "google.protobuf.ServiceDescriptorProto"; prost_types::ServiceOptions => "google.protobuf.ServiceOptions"; prost_types::SourceCodeInfo => "google.protobuf.SourceCodeInfo"; prost_types::source_code_info::Location => "google.protobuf.SourceCodeInfo.Location"; prost_types::SourceContext => "google.protobuf.SourceContext"; prost_types::Struct => "google.protobuf.Struct"; prost_types::Timestamp => "google.protobuf.Timestamp"; prost_types::Type => "google.protobuf.Type"; prost_types::UninterpretedOption => "google.protobuf.UninterpretedOption"; prost_types::uninterpreted_option::NamePart => "google.protobuf.UninterpretedOption.NamePart"; prost_types::Value => "google.protobuf.Value"; prost::bytes::Bytes => "google.protobuf.BytesValue"; }