diff --git a/rust/bench/bench.rs b/rust/bench/bench.rs index 04459df9..43b2a4c8 100644 --- a/rust/bench/bench.rs +++ b/rust/bench/bench.rs @@ -1,5 +1,5 @@ use canbench_rs::{bench, bench_fn, bench_scope, BenchResult}; -use candid::{CandidType, Decode, Deserialize, Encode, Int, Nat}; +use candid::{CandidType, Decode, DecoderConfig, Deserialize, Encode, Int, Nat}; use std::collections::BTreeMap; #[allow(clippy::all)] @@ -13,6 +13,8 @@ const SKIP: usize = 10_000; fn blob() -> BenchResult { use serde_bytes::ByteBuf; let vec: Vec = vec![0x61; N]; + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); bench_fn(|| { let bytes = { let _p = bench_scope("1. Encoding"); @@ -20,7 +22,7 @@ fn blob() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, ByteBuf).unwrap(); + Decode!([config]; &bytes, ByteBuf).unwrap(); } }) } @@ -29,6 +31,8 @@ fn blob() -> BenchResult { fn text() -> BenchResult { let vec: Vec = vec![0x61; N]; let text = String::from_utf8(vec).unwrap(); + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); bench_fn(|| { let bytes = { let _p = bench_scope("1. Encoding"); @@ -36,7 +40,7 @@ fn text() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, String).unwrap(); + Decode!([config]; &bytes, String).unwrap(); } }) } @@ -44,6 +48,8 @@ fn text() -> BenchResult { #[bench(raw)] fn vec_int16() -> BenchResult { let vec: Vec = vec![-1; N]; + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); bench_fn(|| { let bytes = { let _p = bench_scope("1. Encoding"); @@ -51,13 +57,15 @@ fn vec_int16() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, Vec).unwrap(); + Decode!([config]; &bytes, Vec).unwrap(); } }) } #[bench(raw)] fn btreemap() -> BenchResult { + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); let n = 1048576; let map: BTreeMap = (0u32..n as u32) .map(|i| (i.to_string(), Nat::from(i))) @@ -69,13 +77,15 @@ fn btreemap() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, BTreeMap).unwrap(); + Decode!([config]; &bytes, BTreeMap).unwrap(); } }) } #[bench(raw)] fn option_list() -> BenchResult { + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); let n = 2048; #[derive(CandidType, Deserialize)] struct List { @@ -95,13 +105,15 @@ fn option_list() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, Option>).unwrap(); + Decode!([config]; &bytes, Option>).unwrap(); } }) } #[bench(raw)] fn variant_list() -> BenchResult { + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); let n = 2048; #[derive(CandidType, Deserialize)] enum VariantList { @@ -118,7 +130,7 @@ fn variant_list() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, VariantList).unwrap(); + Decode!([config]; &bytes, VariantList).unwrap(); } }) } @@ -126,6 +138,8 @@ fn variant_list() -> BenchResult { #[bench(raw)] fn nns() -> BenchResult { use candid_parser::utils::CandidSource; + let mut config = DecoderConfig::new(); + config.set_decoding_quota(COST).set_skipping_quota(SKIP); let nns_did = CandidSource::Text(include_str!("./nns.did")); let motion_proposal = r#" ( @@ -209,18 +223,20 @@ fn nns() -> BenchResult { }; { let _p = bench_scope("2. Decoding"); - Decode!([COST; SKIP]; &bytes, nns::ManageNeuron).unwrap(); + Decode!([config]; &bytes, nns::ManageNeuron).unwrap(); } }) } #[bench(raw)] fn extra_args() -> BenchResult { + let mut config = DecoderConfig::new(); + config.set_skipping_quota(SKIP); let vec_null = hex::decode("4449444c036c01d6fca702016d026c00010080ade204").unwrap(); let vec_opt_record = hex::decode("4449444c176c02017f027f6c02010002006c02000101016c02000201026c02000301036c02000401046c02000501056c02000601066c02000701076c02000801086c02000901096c02000a010a6c02000b010b6c02000c010c6c02000d020d6c02000e010e6c02000f010f6c02001001106c02001101116c02001201126c02001301136e146d150116050101010101").unwrap(); bench_fn(|| { - assert!(Decode!([COST; SKIP]; &vec_null).is_err()); - assert!(Decode!([COST; SKIP]; &vec_opt_record).is_err()); + assert!(Decode!([config]; &vec_null).is_err()); + assert!(Decode!([config]; &vec_opt_record).is_err()); }) } diff --git a/rust/candid/src/de.rs b/rust/candid/src/de.rs index f10e5a4e..b8cb533f 100644 --- a/rust/candid/src/de.rs +++ b/rust/candid/src/de.rs @@ -29,13 +29,12 @@ impl<'de> IDLDeserialize<'de> { /// Create a new deserializer with IDL binary message. pub fn new(bytes: &'de [u8]) -> Result { let config = DecoderConfig::new(); - Self::new_with_config(bytes, config) + Self::new_with_config(bytes, &config) } /// Create a new deserializer with IDL binary message. The config is used to adjust some parameters in the deserializer. - pub fn new_with_config(bytes: &'de [u8], config: DecoderConfig) -> Result { - let full_error_message = config.full_error_message; + pub fn new_with_config(bytes: &'de [u8], config: &DecoderConfig) -> Result { let mut de = Deserializer::from_bytes(bytes, config).with_context(|| { - if full_error_message || bytes.len() <= 500 { + if config.full_error_message || bytes.len() <= 500 { format!("Cannot parse header {}", &hex::encode(bytes)) } else { "Cannot parse header".to_string() @@ -247,7 +246,7 @@ struct Deserializer<'de> { } impl<'de> Deserializer<'de> { - fn from_bytes(bytes: &'de [u8], config: DecoderConfig) -> Result { + fn from_bytes(bytes: &'de [u8], config: &DecoderConfig) -> Result { let mut reader = Cursor::new(bytes); let header = Header::read(&mut reader)?; let (env, types) = header.to_types()?; @@ -260,7 +259,7 @@ impl<'de> Deserializer<'de> { gamma: Gamma::default(), field_name: None, is_untyped: false, - config, + config: config.clone(), #[cfg(not(target_arch = "wasm32"))] recursion_depth: 0, }) diff --git a/rust/candid/src/types/value.rs b/rust/candid/src/types/value.rs index ce227799..d770dc26 100644 --- a/rust/candid/src/types/value.rs +++ b/rust/candid/src/types/value.rs @@ -122,7 +122,7 @@ impl IDLArgs { bytes: &[u8], env: &TypeEnv, types: &[Type], - config: DecoderConfig, + config: &DecoderConfig, ) -> Result { let mut de = crate::de::IDLDeserialize::new_with_config(bytes, config)?; let mut args = Vec::new(); @@ -143,7 +143,7 @@ impl IDLArgs { de.done()?; Ok(IDLArgs { args }) } - pub fn from_bytes_with_config(bytes: &[u8], config: DecoderConfig) -> Result { + pub fn from_bytes_with_config(bytes: &[u8], config: &DecoderConfig) -> Result { let mut de = crate::de::IDLDeserialize::new_with_config(bytes, config)?; let mut args = Vec::new(); while !de.is_done() { diff --git a/rust/candid/src/utils.rs b/rust/candid/src/utils.rs index 5bdb060a..129124c6 100644 --- a/rust/candid/src/utils.rs +++ b/rust/candid/src/utils.rs @@ -61,10 +61,8 @@ macro_rules! Decode { .and_then(|mut de| Decode!(@GetValue [] de $($ty,)*) .and_then(|res| de.done().and(Ok(res)))) }}; - ( [ $cost:expr; $skip:expr ] ; $hex:expr $(,$ty:ty)* ) => {{ - let mut config = $crate::de::DecoderConfig::new(); - config.set_decoding_quota($cost).set_skipping_quota($skip); - $crate::de::IDLDeserialize::new_with_config($hex, config) + ( [ $config:expr ] ; $hex:expr $(,$ty:ty)* ) => {{ + $crate::de::IDLDeserialize::new_with_config($hex, &$config) .and_then(|mut de| Decode!(@GetValue [] de $($ty,)*) .and_then(|res| de.done().and(Ok(res)))) }}; @@ -102,7 +100,7 @@ where de.done()?; Ok(res) } -pub fn decode_args_with_config<'a, Tuple>(bytes: &'a [u8], config: DecoderConfig) -> Result +pub fn decode_args_with_config<'a, Tuple>(bytes: &'a [u8], config: &DecoderConfig) -> Result where Tuple: ArgumentDecoder<'a>, { @@ -132,7 +130,7 @@ where let (res,) = decode_args(bytes)?; Ok(res) } -pub fn decode_one_with_config<'a, T>(bytes: &'a [u8], config: DecoderConfig) -> Result +pub fn decode_one_with_config<'a, T>(bytes: &'a [u8], config: &DecoderConfig) -> Result where T: Deserialize<'a> + CandidType, { diff --git a/rust/candid/tests/serde.rs b/rust/candid/tests/serde.rs index 77907b2a..56e4d0b0 100644 --- a/rust/candid/tests/serde.rs +++ b/rust/candid/tests/serde.rs @@ -779,12 +779,12 @@ fn test_decode<'de, T>(bytes: &'de [u8], expected: &T) where T: PartialEq + serde::de::Deserialize<'de> + std::fmt::Debug + CandidType, { - let cost = 20_000_000; - let skip = 100_000; let mut config = DecoderConfig::new(); - config.set_decoding_quota(cost).set_skipping_quota(skip); - let decoded_one = decode_one_with_config::(bytes, config).unwrap(); - let decoded_macro = Decode!([cost; skip]; bytes, T).unwrap(); + config + .set_decoding_quota(20_000_000) + .set_skipping_quota(10_000); + let decoded_one = decode_one_with_config::(bytes, &config).unwrap(); + let decoded_macro = Decode!([config]; bytes, T).unwrap(); assert_eq!(decoded_one, *expected); assert_eq!(decoded_macro, *expected); } diff --git a/rust/candid_parser/src/test.rs b/rust/candid_parser/src/test.rs index 8bca2bb7..563b756a 100644 --- a/rust/candid_parser/src/test.rs +++ b/rust/candid_parser/src/test.rs @@ -58,7 +58,7 @@ impl Input { let mut config = DecoderConfig::new(); config.set_decoding_quota(DECODING_COST); Ok(IDLArgs::from_bytes_with_types_with_config( - bytes, env, types, config, + bytes, env, types, &config, )?) } } @@ -117,7 +117,7 @@ impl HostTest { let mut config = DecoderConfig::new(); config.set_decoding_quota(DECODING_COST); let args = - IDLArgs::from_bytes_with_types_with_config(&bytes, env, &types, config) + IDLArgs::from_bytes_with_types_with_config(&bytes, env, &types, &config) .unwrap(); asserts.push(Decode(bytes.clone(), types.clone(), true, args)); // round tripping