Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyan-dfinity committed Feb 22, 2024
1 parent 1fe4a3e commit 719fe86
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 31 deletions.
36 changes: 26 additions & 10 deletions rust/bench/bench.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -13,14 +13,16 @@ const SKIP: usize = 10_000;
fn blob() -> BenchResult {
use serde_bytes::ByteBuf;
let vec: Vec<u8> = 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");
Encode!(&ByteBuf::from(vec)).unwrap()
};
{
let _p = bench_scope("2. Decoding");
Decode!([COST; SKIP]; &bytes, ByteBuf).unwrap();
Decode!([config]; &bytes, ByteBuf).unwrap();
}
})
}
Expand All @@ -29,35 +31,41 @@ fn blob() -> BenchResult {
fn text() -> BenchResult {
let vec: Vec<u8> = 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");
Encode!(&text).unwrap()
};
{
let _p = bench_scope("2. Decoding");
Decode!([COST; SKIP]; &bytes, String).unwrap();
Decode!([config]; &bytes, String).unwrap();
}
})
}

#[bench(raw)]
fn vec_int16() -> BenchResult {
let vec: Vec<i16> = 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");
Encode!(&vec).unwrap()
};
{
let _p = bench_scope("2. Decoding");
Decode!([COST; SKIP]; &bytes, Vec<i16>).unwrap();
Decode!([config]; &bytes, Vec<i16>).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<String, Nat> = (0u32..n as u32)
.map(|i| (i.to_string(), Nat::from(i)))
Expand All @@ -69,13 +77,15 @@ fn btreemap() -> BenchResult {
};
{
let _p = bench_scope("2. Decoding");
Decode!([COST; SKIP]; &bytes, BTreeMap<String, Nat>).unwrap();
Decode!([config]; &bytes, BTreeMap<String, Nat>).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 {
Expand All @@ -95,13 +105,15 @@ fn option_list() -> BenchResult {
};
{
let _p = bench_scope("2. Decoding");
Decode!([COST; SKIP]; &bytes, Option<Box<List>>).unwrap();
Decode!([config]; &bytes, Option<Box<List>>).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 {
Expand All @@ -118,14 +130,16 @@ fn variant_list() -> BenchResult {
};
{
let _p = bench_scope("2. Decoding");
Decode!([COST; SKIP]; &bytes, VariantList).unwrap();
Decode!([config]; &bytes, VariantList).unwrap();
}
})
}

#[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#"
(
Expand Down Expand Up @@ -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());
})
}

Expand Down
11 changes: 5 additions & 6 deletions rust/candid/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ impl<'de> IDLDeserialize<'de> {
/// Create a new deserializer with IDL binary message.
pub fn new(bytes: &'de [u8]) -> Result<Self> {
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<Self> {
let full_error_message = config.full_error_message;
pub fn new_with_config(bytes: &'de [u8], config: &DecoderConfig) -> Result<Self> {
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()
Expand Down Expand Up @@ -247,7 +246,7 @@ struct Deserializer<'de> {
}

impl<'de> Deserializer<'de> {
fn from_bytes(bytes: &'de [u8], config: DecoderConfig) -> Result<Self> {
fn from_bytes(bytes: &'de [u8], config: &DecoderConfig) -> Result<Self> {
let mut reader = Cursor::new(bytes);
let header = Header::read(&mut reader)?;
let (env, types) = header.to_types()?;
Expand All @@ -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,
})
Expand Down
4 changes: 2 additions & 2 deletions rust/candid/src/types/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl IDLArgs {
bytes: &[u8],
env: &TypeEnv,
types: &[Type],
config: DecoderConfig,
config: &DecoderConfig,
) -> Result<Self> {
let mut de = crate::de::IDLDeserialize::new_with_config(bytes, config)?;
let mut args = Vec::new();
Expand All @@ -143,7 +143,7 @@ impl IDLArgs {
de.done()?;
Ok(IDLArgs { args })
}
pub fn from_bytes_with_config(bytes: &[u8], config: DecoderConfig) -> Result<Self> {
pub fn from_bytes_with_config(bytes: &[u8], config: &DecoderConfig) -> Result<Self> {
let mut de = crate::de::IDLDeserialize::new_with_config(bytes, config)?;
let mut args = Vec::new();
while !de.is_done() {
Expand Down
10 changes: 4 additions & 6 deletions rust/candid/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
}};
Expand Down Expand Up @@ -102,7 +100,7 @@ where
de.done()?;
Ok(res)
}
pub fn decode_args_with_config<'a, Tuple>(bytes: &'a [u8], config: DecoderConfig) -> Result<Tuple>
pub fn decode_args_with_config<'a, Tuple>(bytes: &'a [u8], config: &DecoderConfig) -> Result<Tuple>
where
Tuple: ArgumentDecoder<'a>,
{
Expand Down Expand Up @@ -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<T>
pub fn decode_one_with_config<'a, T>(bytes: &'a [u8], config: &DecoderConfig) -> Result<T>
where
T: Deserialize<'a> + CandidType,
{
Expand Down
10 changes: 5 additions & 5 deletions rust/candid/tests/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<T>(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::<T>(bytes, &config).unwrap();
let decoded_macro = Decode!([config]; bytes, T).unwrap();
assert_eq!(decoded_one, *expected);
assert_eq!(decoded_macro, *expected);
}
Expand Down
4 changes: 2 additions & 2 deletions rust/candid_parser/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)?)
}
}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 719fe86

Please sign in to comment.