Struct candid::de::DecoderConfig

source ·
pub struct DecoderConfig {
    pub decoding_quota: Option<usize>,
    pub skipping_quota: Option<usize>,
    /* private fields */
}
Expand description

Config the deserialization quota, used to prevent spending too much time in decoding malicious payload.

Fields§

§decoding_quota: Option<usize>§skipping_quota: Option<usize>

Implementations§

source§

impl DecoderConfig

source

pub fn new() -> Self

Creates a config with no quota. This allows developers to handle large Candid data internally, e.g., persisting states to stable memory. When using Candid in canister endpoints, we recommend setting the quota to prevent malicious payload.

source

pub fn set_decoding_quota(&mut self, n: usize) -> &mut Self

Limit the total amount of work the deserailizer can perform. Deserialization errors out when the limit is reached. If your canister endpoint has variable-length data types and expects that the valid data will be small, you can set this limit to prevent spending too much time decoding invalid data.

The cost of decoding a message = 4 * the byte length of the header (the byte before the value part) + the cost of decoding each value.

The cost of decoding a value is roughly defined as follows (it’s not precise because the cost also depends on how Rust data types are defined),

C : <val> -> <primtype> -> nat
C(n : nat)      = |leb128(n)|
C(i : int)      = |sleb128(i)|
C(n : nat<N>)   = N / 8
C(i : int<N>)   = N / 8
C(z : float<N>) = N / 8
C(b : bool)     = 1
C(t : text)     = 1 + |t|
C(_ : null)     = 1
C(_ : reserved) = 1
C(_ : empty)    = undefined

C : <val> -> <constype> -> nat
C(null : opt <datatype>)  = 2
C(?v   : opt <datatype>)  = 2 + C(v : <datatype>)
C(v^N  : vec <datatype>)  = 2 + 3 * N + sum_i C(v[i] : <datatype>)
C(kv*  : record {<fieldtype>*})  = 2 + sum_i C(kv : <fieldtype>*[i])
C(kv   : variant {<fieldtype>*}) = 2 + C(kv : <fieldtype>*[i])

C : (<nat>, <val>) -> <fieldtype> -> nat
C((k,v) : k:<datatype>) = 7 + |k| + C(v : <datatype>)  // record field
C((k,v) : k:<datatype>) = 5 + |k| + C(v : <datatype>)  // variant field

C : <val> -> <reftype> -> nat
C(id(v*)        : service <actortype>) = 2 + C(id(v*) : principal) + |type table|
C((id(v*),name) : func <functype>)     = 2 + C(id(v*) : principal) + C(name : text) + |type table|
C(id(v*)        : principal)           = max(30, |v*|)

When a value `v : t` on the wire is skipped, due to being extra arguments, extra fields and mismatched option types,
we apply a 50x penalty on `C(v : t)` in the decoding cost.
source

pub fn set_skipping_quota(&mut self, n: usize) -> &mut Self

Limit the amount of work for skipping unneeded data on the wire. This includes extra arguments, extra fields and mismatched option values. Decoding values to IDLValue is also counted towards this limit. For the cost model, please refer to the docs in set_decoding_quota. Note that unlike the decoding_quota, we will not apply the 50x penalty for skipped values in this counter. When using Candid in canister endpoints, it’s strongly encouraged to set this quota to a small value, e.g., 10_000.

source

pub fn set_full_error_message(&mut self, n: bool) -> &mut Self

When set to false, error message only displays the concrete type when the type is small. The error message also doesn’t include the decoding states. When set to true, error message always shows the full type and decoding states.

source

pub fn compute_cost(&self, original: &Self) -> Self

Given the original config, compute the decoding cost

Trait Implementations§

source§

impl Clone for DecoderConfig

source§

fn clone(&self) -> DecoderConfig

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for DecoderConfig

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.