From 45196c722c769aa8dce523458e698ad5dd6445db Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 20 Feb 2022 16:24:11 +0100 Subject: [PATCH] benchmark and improve method parsing --- Cargo.lock | 413 ++++++++++++++++++++- amqp_transport/Cargo.toml | 7 + amqp_transport/benches/parser.rs | 39 ++ amqp_transport/src/lib.rs | 3 +- amqp_transport/src/methods/generated.rs | 181 +++------ amqp_transport/src/methods/mod.rs | 68 ++++ amqp_transport/src/methods/parse_helper.rs | 11 +- amqp_transport/src/methods/tests.rs | 71 +--- xtask/src/codegen/parser.rs | 6 +- xtask/src/codegen/random.rs | 4 +- 10 files changed, 593 insertions(+), 210 deletions(-) create mode 100644 amqp_transport/benches/parser.rs diff --git a/Cargo.lock b/Cargo.lock index a90b3c0..8b6f3b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,7 @@ version = "0.1.0" dependencies = [ "amqp_core", "anyhow", + "criterion", "nom", "once_cell", "rand", @@ -85,6 +86,23 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "axum" version = "0.4.5" @@ -136,18 +154,158 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + +[[package]] +name = "criterion" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "either" version = "1.6.1" @@ -220,6 +378,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "heck" version = "0.4.0" @@ -243,7 +407,7 @@ checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.1", ] [[package]] @@ -289,7 +453,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 1.0.1", "pin-project-lite", "socket2", "tokio", @@ -307,6 +471,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + [[package]] name = "itoa" version = "1.0.1" @@ -319,6 +489,15 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9447923c57a8a2d5c1b0875cdf96a6324275df728b498f2ede0e5cbde088a15" +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -367,6 +546,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -421,6 +609,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -437,6 +634,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "parking_lot" version = "0.12.0" @@ -498,6 +701,34 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "plotters" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -562,6 +793,31 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rayon" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.10" @@ -582,24 +838,54 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7" + [[package]] name = "serde" version = "1.0.136" @@ -609,6 +895,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.136" @@ -626,7 +922,7 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -638,7 +934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -718,6 +1014,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.30" @@ -747,6 +1052,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tokio" version = "1.17.0" @@ -918,6 +1233,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -942,6 +1263,17 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -958,6 +1290,70 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -974,6 +1370,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/amqp_transport/Cargo.toml b/amqp_transport/Cargo.toml index 383d1cf..cb0199c 100644 --- a/amqp_transport/Cargo.toml +++ b/amqp_transport/Cargo.toml @@ -18,3 +18,10 @@ tracing = "0.1.30" uuid = "0.8.2" [features] + +[dev-dependencies] +criterion = "0.3.5" + +[[bench]] +name = "parser" +harness = false diff --git a/amqp_transport/benches/parser.rs b/amqp_transport/benches/parser.rs new file mode 100644 index 0000000..189e1ce --- /dev/null +++ b/amqp_transport/benches/parser.rs @@ -0,0 +1,39 @@ +use amqp_transport::methods; +use amqp_transport::methods::{Method, RandomMethod}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use rand::SeedableRng; + +fn random_method_from_seed(seed: u128) -> Method { + let mut rng = rand::rngs::StdRng::from_seed( + [seed.to_be_bytes(), seed.to_be_bytes()] + .concat() + .try_into() + .unwrap(), + ); + Method::random(&mut rng) +} + +fn serialize_method(method: Method) -> Vec { + let mut writer = Vec::new(); + methods::write::write_method(method, &mut writer).unwrap(); + writer +} + +fn parse_method(c: &mut Criterion) { + let methods = (0..10000) + .map(random_method_from_seed) + .map(serialize_method) + .collect::>(); + + c.bench_function("parse random methods", |b| { + b.iter(|| { + for data in &methods { + let result = methods::parse_method(black_box(data)).unwrap(); + black_box(result); + } + }) + }); +} + +criterion_group!(benches, parse_method); +criterion_main!(benches); diff --git a/amqp_transport/src/lib.rs b/amqp_transport/src/lib.rs index 2ebffd4..990217d 100644 --- a/amqp_transport/src/lib.rs +++ b/amqp_transport/src/lib.rs @@ -3,11 +3,12 @@ mod connection; mod error; mod frame; -mod methods; +pub mod methods; mod sasl; #[cfg(test)] mod tests; + use crate::connection::Connection; use amqp_core::GlobalData; use anyhow::Result; diff --git a/amqp_transport/src/methods/generated.rs b/amqp_transport/src/methods/generated.rs index ea8c3c3..547792d 100644 --- a/amqp_transport/src/methods/generated.rs +++ b/amqp_transport/src/methods/generated.rs @@ -887,8 +887,7 @@ pub mod parse { table(input) } fn connection(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = tag(10_u16.to_be_bytes())(input) - .map_err(fail_err("invalid tag for class connection"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; alt(( connection_start, connection_start_ok, @@ -904,8 +903,7 @@ pub mod parse { .map_err(fail_err("class connection")) } fn connection_start(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(10_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; let (input, version_major) = domain_octet(input).map_err(fail_err("field version-major in method start"))?; let (input, version_minor) = @@ -934,8 +932,7 @@ pub mod parse { )) } fn connection_start_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(11_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(11_u16.to_be_bytes())(input)?; let (input, client_properties) = domain_peer_properties(input) .map_err(fail_err("field client-properties in method start-ok"))?; let (input, mechanism) = @@ -964,15 +961,13 @@ pub mod parse { )) } fn connection_secure(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; let (input, challenge) = domain_longstr(input).map_err(fail_err("field challenge in method secure"))?; Ok((input, Method::ConnectionSecure { challenge })) } fn connection_secure_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(21_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(21_u16.to_be_bytes())(input)?; let (input, response) = domain_longstr(input).map_err(fail_err("field response in method secure-ok"))?; if response.is_empty() { @@ -981,8 +976,7 @@ pub mod parse { Ok((input, Method::ConnectionSecureOk { response })) } fn connection_tune(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(30_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(30_u16.to_be_bytes())(input)?; let (input, channel_max) = domain_short(input).map_err(fail_err("field channel-max in method tune"))?; let (input, frame_max) = @@ -999,8 +993,7 @@ pub mod parse { )) } fn connection_tune_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(31_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(31_u16.to_be_bytes())(input)?; let (input, channel_max) = domain_short(input).map_err(fail_err("field channel-max in method tune-ok"))?; if channel_max == 0 { @@ -1020,8 +1013,7 @@ pub mod parse { )) } fn connection_open(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(40_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(40_u16.to_be_bytes())(input)?; let (input, virtual_host) = domain_path(input).map_err(fail_err("field virtual-host in method open"))?; let (input, reserved_1) = @@ -1038,15 +1030,13 @@ pub mod parse { )) } fn connection_open_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(41_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(41_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_shortstr(input).map_err(fail_err("field reserved-1 in method open-ok"))?; Ok((input, Method::ConnectionOpenOk { reserved_1 })) } fn connection_close(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(50_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(50_u16.to_be_bytes())(input)?; let (input, reply_code) = domain_reply_code(input).map_err(fail_err("field reply-code in method close"))?; let (input, reply_text) = @@ -1066,13 +1056,11 @@ pub mod parse { )) } fn connection_close_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(51_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(51_u16.to_be_bytes())(input)?; Ok((input, Method::ConnectionCloseOk {})) } fn channel(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("invalid tag for class channel"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; alt(( channel_open, channel_open_ok, @@ -1084,36 +1072,31 @@ pub mod parse { .map_err(fail_err("class channel")) } fn channel_open(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(10_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_shortstr(input).map_err(fail_err("field reserved-1 in method open"))?; Ok((input, Method::ChannelOpen { reserved_1 })) } fn channel_open_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(11_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(11_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_longstr(input).map_err(fail_err("field reserved-1 in method open-ok"))?; Ok((input, Method::ChannelOpenOk { reserved_1 })) } fn channel_flow(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; let (input, bits) = bit(input, 1).map_err(fail_err("field active in method flow"))?; let active = bits[0]; Ok((input, Method::ChannelFlow { active })) } fn channel_flow_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(21_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(21_u16.to_be_bytes())(input)?; let (input, bits) = bit(input, 1).map_err(fail_err("field active in method flow-ok"))?; let active = bits[0]; Ok((input, Method::ChannelFlowOk { active })) } fn channel_close(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(40_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(40_u16.to_be_bytes())(input)?; let (input, reply_code) = domain_reply_code(input).map_err(fail_err("field reply-code in method close"))?; let (input, reply_text) = @@ -1133,13 +1116,11 @@ pub mod parse { )) } fn channel_close_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(41_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(41_u16.to_be_bytes())(input)?; Ok((input, Method::ChannelCloseOk {})) } fn exchange(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(40_u16.to_be_bytes())(input).map_err(fail_err("invalid tag for class exchange"))?; + let (input, _) = tag(40_u16.to_be_bytes())(input)?; alt(( exchange_declare, exchange_declare_ok, @@ -1149,8 +1130,7 @@ pub mod parse { .map_err(fail_err("class exchange")) } fn exchange_declare(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(10_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method declare"))?; let (input, exchange) = @@ -1184,13 +1164,11 @@ pub mod parse { )) } fn exchange_declare_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(11_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(11_u16.to_be_bytes())(input)?; Ok((input, Method::ExchangeDeclareOk {})) } fn exchange_delete(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method delete"))?; let (input, exchange) = @@ -1212,13 +1190,11 @@ pub mod parse { )) } fn exchange_delete_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(21_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(21_u16.to_be_bytes())(input)?; Ok((input, Method::ExchangeDeleteOk {})) } fn queue(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(50_u16.to_be_bytes())(input).map_err(fail_err("invalid tag for class queue"))?; + let (input, _) = tag(50_u16.to_be_bytes())(input)?; alt(( queue_declare, queue_declare_ok, @@ -1234,8 +1210,7 @@ pub mod parse { .map_err(fail_err("class queue")) } fn queue_declare(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(10_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method declare"))?; let (input, queue) = @@ -1263,8 +1238,7 @@ pub mod parse { )) } fn queue_declare_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(11_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(11_u16.to_be_bytes())(input)?; let (input, queue) = domain_queue_name(input).map_err(fail_err("field queue in method declare-ok"))?; if queue.is_empty() { @@ -1284,8 +1258,7 @@ pub mod parse { )) } fn queue_bind(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method bind"))?; let (input, queue) = @@ -1311,13 +1284,11 @@ pub mod parse { )) } fn queue_bind_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(21_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(21_u16.to_be_bytes())(input)?; Ok((input, Method::QueueBindOk {})) } fn queue_unbind(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(50_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(50_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method unbind"))?; let (input, queue) = @@ -1340,13 +1311,11 @@ pub mod parse { )) } fn queue_unbind_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(51_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(51_u16.to_be_bytes())(input)?; Ok((input, Method::QueueUnbindOk {})) } fn queue_purge(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(30_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(30_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method purge"))?; let (input, queue) = @@ -1363,15 +1332,13 @@ pub mod parse { )) } fn queue_purge_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(31_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(31_u16.to_be_bytes())(input)?; let (input, message_count) = domain_message_count(input) .map_err(fail_err("field message-count in method purge-ok"))?; Ok((input, Method::QueuePurgeOk { message_count })) } fn queue_delete(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(40_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(40_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method delete"))?; let (input, queue) = @@ -1392,15 +1359,13 @@ pub mod parse { )) } fn queue_delete_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(41_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(41_u16.to_be_bytes())(input)?; let (input, message_count) = domain_message_count(input) .map_err(fail_err("field message-count in method delete-ok"))?; Ok((input, Method::QueueDeleteOk { message_count })) } fn basic(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(60_u16.to_be_bytes())(input).map_err(fail_err("invalid tag for class basic"))?; + let (input, _) = tag(60_u16.to_be_bytes())(input)?; alt(( basic_qos, basic_qos_ok, @@ -1423,8 +1388,7 @@ pub mod parse { .map_err(fail_err("class basic")) } fn basic_qos(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(10_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; let (input, prefetch_size) = domain_long(input).map_err(fail_err("field prefetch-size in method qos"))?; let (input, prefetch_count) = @@ -1441,13 +1405,11 @@ pub mod parse { )) } fn basic_qos_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(11_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(11_u16.to_be_bytes())(input)?; Ok((input, Method::BasicQosOk {})) } fn basic_consume(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method consume"))?; let (input, queue) = @@ -1476,15 +1438,13 @@ pub mod parse { )) } fn basic_consume_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(21_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(21_u16.to_be_bytes())(input)?; let (input, consumer_tag) = domain_consumer_tag(input) .map_err(fail_err("field consumer-tag in method consume-ok"))?; Ok((input, Method::BasicConsumeOk { consumer_tag })) } fn basic_cancel(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(30_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(30_u16.to_be_bytes())(input)?; let (input, consumer_tag) = domain_consumer_tag(input).map_err(fail_err("field consumer-tag in method cancel"))?; let (input, bits) = bit(input, 1).map_err(fail_err("field no-wait in method cancel"))?; @@ -1498,15 +1458,13 @@ pub mod parse { )) } fn basic_cancel_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(31_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(31_u16.to_be_bytes())(input)?; let (input, consumer_tag) = domain_consumer_tag(input) .map_err(fail_err("field consumer-tag in method cancel-ok"))?; Ok((input, Method::BasicCancelOk { consumer_tag })) } fn basic_publish(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(40_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(40_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method publish"))?; let (input, exchange) = @@ -1528,8 +1486,7 @@ pub mod parse { )) } fn basic_return(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(50_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(50_u16.to_be_bytes())(input)?; let (input, reply_code) = domain_reply_code(input).map_err(fail_err("field reply-code in method return"))?; let (input, reply_text) = @@ -1549,8 +1506,7 @@ pub mod parse { )) } fn basic_deliver(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(60_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(60_u16.to_be_bytes())(input)?; let (input, consumer_tag) = domain_consumer_tag(input).map_err(fail_err("field consumer-tag in method deliver"))?; let (input, delivery_tag) = @@ -1574,8 +1530,7 @@ pub mod parse { )) } fn basic_get(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(70_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(70_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_short(input).map_err(fail_err("field reserved-1 in method get"))?; let (input, queue) = @@ -1592,8 +1547,7 @@ pub mod parse { )) } fn basic_get_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(71_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(71_u16.to_be_bytes())(input)?; let (input, delivery_tag) = domain_delivery_tag(input).map_err(fail_err("field delivery-tag in method get-ok"))?; let (input, bits) = @@ -1617,15 +1571,13 @@ pub mod parse { )) } fn basic_get_empty(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(72_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(72_u16.to_be_bytes())(input)?; let (input, reserved_1) = domain_shortstr(input).map_err(fail_err("field reserved-1 in method get-empty"))?; Ok((input, Method::BasicGetEmpty { reserved_1 })) } fn basic_ack(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(80_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(80_u16.to_be_bytes())(input)?; let (input, delivery_tag) = domain_delivery_tag(input).map_err(fail_err("field delivery-tag in method ack"))?; let (input, bits) = bit(input, 1).map_err(fail_err("field multiple in method ack"))?; @@ -1639,8 +1591,7 @@ pub mod parse { )) } fn basic_reject(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(90_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(90_u16.to_be_bytes())(input)?; let (input, delivery_tag) = domain_delivery_tag(input).map_err(fail_err("field delivery-tag in method reject"))?; let (input, bits) = bit(input, 1).map_err(fail_err("field requeue in method reject"))?; @@ -1654,28 +1605,24 @@ pub mod parse { )) } fn basic_recover_async(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(100_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(100_u16.to_be_bytes())(input)?; let (input, bits) = bit(input, 1).map_err(fail_err("field requeue in method recover-async"))?; let requeue = bits[0]; Ok((input, Method::BasicRecoverAsync { requeue })) } fn basic_recover(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(110_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(110_u16.to_be_bytes())(input)?; let (input, bits) = bit(input, 1).map_err(fail_err("field requeue in method recover"))?; let requeue = bits[0]; Ok((input, Method::BasicRecover { requeue })) } fn basic_recover_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(111_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(111_u16.to_be_bytes())(input)?; Ok((input, Method::BasicRecoverOk {})) } fn tx(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(90_u16.to_be_bytes())(input).map_err(fail_err("invalid tag for class tx"))?; + let (input, _) = tag(90_u16.to_be_bytes())(input)?; alt(( tx_select, tx_select_ok, @@ -1687,33 +1634,27 @@ pub mod parse { .map_err(fail_err("class tx")) } fn tx_select(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(10_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(10_u16.to_be_bytes())(input)?; Ok((input, Method::TxSelect {})) } fn tx_select_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(11_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(11_u16.to_be_bytes())(input)?; Ok((input, Method::TxSelectOk {})) } fn tx_commit(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(20_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(20_u16.to_be_bytes())(input)?; Ok((input, Method::TxCommit {})) } fn tx_commit_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(21_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(21_u16.to_be_bytes())(input)?; Ok((input, Method::TxCommitOk {})) } fn tx_rollback(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(30_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(30_u16.to_be_bytes())(input)?; Ok((input, Method::TxRollback {})) } fn tx_rollback_ok(input: &[u8]) -> IResult<'_, Method> { - let (input, _) = - tag(31_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?; + let (input, _) = tag(31_u16.to_be_bytes())(input)?; Ok((input, Method::TxRollbackOk {})) } } @@ -2134,10 +2075,10 @@ pub mod write { Ok(()) } } -#[cfg(test)] + mod random { use super::*; - use crate::methods::tests::RandomMethod; + use crate::methods::RandomMethod; use rand::Rng; impl RandomMethod for Method { diff --git a/amqp_transport/src/methods/mod.rs b/amqp_transport/src/methods/mod.rs index 186c364..1296ffc 100644 --- a/amqp_transport/src/methods/mod.rs +++ b/amqp_transport/src/methods/mod.rs @@ -1,4 +1,5 @@ use crate::error::{ConException, TransError}; +use rand::Rng; use std::collections::HashMap; mod generated; @@ -56,3 +57,70 @@ pub fn parse_method(payload: &[u8]) -> Result { Err(nom::Err::Failure(err) | nom::Err::Error(err)) => Err(err), } } + +/// Allows the creation of a random instance of that type +pub trait RandomMethod { + fn random(rng: &mut R) -> Self; +} + +impl RandomMethod for String { + fn random(rng: &mut R) -> Self { + let n = rng.gen_range(0_u16..9999); + format!("string{n}") + } +} + +impl> RandomMethod for Vec { + fn random(rng: &mut R) -> Self { + let len = rng.gen_range(1_usize..10); + let mut vec = Vec::with_capacity(len); + (0..len).for_each(|_| vec.push(RandomMethod::random(rng))); + vec + } +} + +macro_rules! rand_random_method { + ($($ty:ty),+) => { + $( + impl RandomMethod for $ty { + fn random(rng: &mut R) -> Self { + rng.gen() + } + })+ + }; +} + +rand_random_method!(bool, u8, i8, u16, i16, u32, i32, u64, i64, f32, f64); + +impl RandomMethod for HashMap { + fn random(rng: &mut R) -> Self { + let len = rng.gen_range(0..3); + HashMap::from_iter((0..len).map(|_| (String::random(rng), FieldValue::random(rng)))) + } +} + +impl RandomMethod for FieldValue { + fn random(rng: &mut R) -> Self { + let index = rng.gen_range(0_u32..17); + match index { + 0 => FieldValue::Boolean(RandomMethod::random(rng)), + 1 => FieldValue::ShortShortInt(RandomMethod::random(rng)), + 2 => FieldValue::ShortShortUInt(RandomMethod::random(rng)), + 3 => FieldValue::ShortInt(RandomMethod::random(rng)), + 4 => FieldValue::ShortUInt(RandomMethod::random(rng)), + 5 => FieldValue::LongInt(RandomMethod::random(rng)), + 6 => FieldValue::LongUInt(RandomMethod::random(rng)), + 7 => FieldValue::LongLongInt(RandomMethod::random(rng)), + 8 => FieldValue::LongLongUInt(RandomMethod::random(rng)), + 9 => FieldValue::Float(RandomMethod::random(rng)), + 10 => FieldValue::Double(RandomMethod::random(rng)), + 11 => FieldValue::ShortString(RandomMethod::random(rng)), + 12 => FieldValue::LongString(RandomMethod::random(rng)), + 13 => FieldValue::FieldArray(RandomMethod::random(rng)), + 14 => FieldValue::Timestamp(RandomMethod::random(rng)), + 15 => FieldValue::FieldTable(RandomMethod::random(rng)), + 16 => FieldValue::Void, + _ => unreachable!(), + } + } +} diff --git a/amqp_transport/src/methods/parse_helper.rs b/amqp_transport/src/methods/parse_helper.rs index 99c57e2..7cbe7f6 100644 --- a/amqp_transport/src/methods/parse_helper.rs +++ b/amqp_transport/src/methods/parse_helper.rs @@ -12,9 +12,6 @@ use nom::number::Endianness::Big; use nom::Err; use std::collections::HashMap; -// todo: remove the debug machinery or change it in a way that actually does what it should lmao -// I'm probably misusing nom hard - impl nom::error::ParseError for TransError { fn from_error_kind(_input: T, _kind: ErrorKind) -> Self { ConException::SyntaxError(vec![]).into_trans() @@ -27,12 +24,6 @@ impl nom::error::ParseError for TransError { pub fn fail_err>(msg: S) -> impl FnOnce(Err) -> Err { move |err| { - let error_level = if matches!(err, nom::Err::Failure(_)) { - Err::Failure - } else { - Err::Error - }; - let msg = msg.into(); let stack = match err { Err::Error(e) | Err::Failure(e) => match e { @@ -46,7 +37,7 @@ pub fn fail_err>(msg: S) -> impl FnOnce(Err) -> Err< }, _ => vec![msg], }; - error_level(ConException::SyntaxError(stack).into_trans()) + Err::Failure(ConException::SyntaxError(stack).into_trans()) } } pub fn err_other>(msg: S) -> impl FnOnce(E) -> Err { diff --git a/amqp_transport/src/methods/tests.rs b/amqp_transport/src/methods/tests.rs index bb21cad..571ba3c 100644 --- a/amqp_transport/src/methods/tests.rs +++ b/amqp_transport/src/methods/tests.rs @@ -1,77 +1,10 @@ // create random methods to test the ser/de code together. if they diverge, we have a bug // this is not perfect, if they both have the same bug it won't be found, but tha's an ok tradeoff -use crate::methods::{FieldValue, Method}; -use rand::{Rng, SeedableRng}; +use crate::methods::{FieldValue, Method, RandomMethod}; +use rand::SeedableRng; use std::collections::HashMap; -/// Allows the creation of a random instance of that type -pub(crate) trait RandomMethod { - fn random(rng: &mut R) -> Self; -} - -impl RandomMethod for String { - fn random(rng: &mut R) -> Self { - let n = rng.gen_range(0_u16..9999); - format!("string{n}") - } -} - -impl> RandomMethod for Vec { - fn random(rng: &mut R) -> Self { - let len = rng.gen_range(1_usize..10); - let mut vec = Vec::with_capacity(len); - (0..len).for_each(|_| vec.push(RandomMethod::random(rng))); - vec - } -} - -macro_rules! rand_random_method { - ($($ty:ty),+) => { - $( - impl RandomMethod for $ty { - fn random(rng: &mut R) -> Self { - rng.gen() - } - })+ - }; -} - -rand_random_method!(bool, u8, i8, u16, i16, u32, i32, u64, i64, f32, f64); - -impl RandomMethod for HashMap { - fn random(rng: &mut R) -> Self { - let len = rng.gen_range(0..3); - HashMap::from_iter((0..len).map(|_| (String::random(rng), FieldValue::random(rng)))) - } -} - -impl RandomMethod for FieldValue { - fn random(rng: &mut R) -> Self { - let index = rng.gen_range(0_u32..17); - match index { - 0 => FieldValue::Boolean(RandomMethod::random(rng)), - 1 => FieldValue::ShortShortInt(RandomMethod::random(rng)), - 2 => FieldValue::ShortShortUInt(RandomMethod::random(rng)), - 3 => FieldValue::ShortInt(RandomMethod::random(rng)), - 4 => FieldValue::ShortUInt(RandomMethod::random(rng)), - 5 => FieldValue::LongInt(RandomMethod::random(rng)), - 6 => FieldValue::LongUInt(RandomMethod::random(rng)), - 7 => FieldValue::LongLongInt(RandomMethod::random(rng)), - 8 => FieldValue::LongLongUInt(RandomMethod::random(rng)), - 9 => FieldValue::Float(RandomMethod::random(rng)), - 10 => FieldValue::Double(RandomMethod::random(rng)), - 11 => FieldValue::ShortString(RandomMethod::random(rng)), - 12 => FieldValue::LongString(RandomMethod::random(rng)), - 13 => FieldValue::FieldArray(RandomMethod::random(rng)), - 14 => FieldValue::Timestamp(RandomMethod::random(rng)), - 15 => FieldValue::FieldTable(RandomMethod::random(rng)), - 16 => FieldValue::Void, - _ => unreachable!(), - } - } -} - #[test] fn pack_few_bits() { let bits = [true, false, true]; diff --git a/xtask/src/codegen/parser.rs b/xtask/src/codegen/parser.rs index eda0306..5ced7fd 100644 --- a/xtask/src/codegen/parser.rs +++ b/xtask/src/codegen/parser.rs @@ -56,7 +56,7 @@ pub type IResult<'a, T> = nom::IResult<&'a [u8], T, TransError>; .join(", "); let class_name_raw = &class.name; println!( - r#" let (input, _) = tag({class_index}_u16.to_be_bytes())(input).map_err(fail_err("invalid tag for class {class_name_raw}"))?; + r#" let (input, _) = tag({class_index}_u16.to_be_bytes())(input)?; alt(({all_methods}))(input).map_err(fail_err("class {class_name_raw}"))"# ); }); @@ -96,9 +96,7 @@ fn method_parser(amqp: &Amqp, class: &Class, method: &Method) { let function_name = method_function_name(&class_name)(method); function(&function_name, "Method", || { let method_index = method.index; - println!( - r#" let (input, _) = tag({method_index}_u16.to_be_bytes())(input).map_err(fail_err("parsing method index"))?;"# - ); + println!(r#" let (input, _) = tag({method_index}_u16.to_be_bytes())(input)?;"#); let mut iter = method.fields.iter().peekable(); while let Some(field) = iter.next() { let field_name_raw = &field.name; diff --git a/xtask/src/codegen/random.rs b/xtask/src/codegen/random.rs index d952e1a..9db17b6 100644 --- a/xtask/src/codegen/random.rs +++ b/xtask/src/codegen/random.rs @@ -3,10 +3,10 @@ use heck::ToUpperCamelCase; pub(super) fn codegen_random(amqp: &Amqp) { println!( - "#[cfg(test)] + " mod random {{ use rand::Rng; -use crate::methods::tests::RandomMethod; +use crate::methods::RandomMethod; use super::*; " );