Skip to main content

RefusalDigest

Struct RefusalDigest 

Source
pub struct RefusalDigest<const N: usize = 0> { /* private fields */ }
Available on target_has_atomic=32 only.
Expand description

How many times each failure code was returned, for one route.

One counter per code form-net returns, one per inspector code named in with_codes, and one for every other inspector refusal. record is a match and one relaxed atomic add: no allocation, no lock, safe to call from every thread at once. Keep one digest per route (a static works) and record every error the route returns, whichever call returned it; a detection layer reads the counts and compares them over time.

Counters are 64 bits where the target has 64-bit atomics and 32 bits elsewhere; they wrap, so compare readings with wrapping_sub.

§Examples

use form_net::RefusalDigest;

static LOGIN: RefusalDigest<1> = RefusalDigest::with_codes(["customs.unexpected_field"]);

for body in [&b"email=a%zz"[..], b"a=1", b"b=%"] {
    if let Err(e) = form_net::parse_urlencoded(body) {
        LOGIN.record(&e);
    }
}
assert_eq!(LOGIN.count("encoding.invalid_percent"), 2);
assert_eq!(LOGIN.total(), 2);

Implementations§

Source§

impl RefusalDigest<0>

Source

pub const fn new() -> RefusalDigest<0>

A digest of form-net’s own codes; every inspector refusal counts as unnamed.

Source§

impl<const N: usize> RefusalDigest<N>

Source

pub const fn with_codes(codes: [&'static str; N]) -> RefusalDigest<N>

A digest that also counts these inspector codes one by one (the codes the route’s inspectors can return, such as customs-sec’s).

Source

pub fn record(&self, error: &FormError)

Counts error under its code.

Cost: one match and one relaxed atomic add for form-net’s codes; an inspector refusal compares its code with the named codes first.

Source

pub fn count(&self, code: &str) -> u64

How many times code was recorded (form-net’s codes and the named inspector codes; a code named twice, or named and also form-net’s, sums its counters).

Source

pub fn unnamed(&self) -> u64

How many inspector refusals had a code that was not named.

Source

pub fn total(&self) -> u64

Everything recorded.

Source

pub fn iter(&self) -> impl Iterator<Item = (&'static str, u64)> + '_

Every code with a count above zero, form-net’s first in a fixed order, then the named codes; unnamed is apart.

Trait Implementations§

Source§

impl<const N: usize> Debug for RefusalDigest<N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RefusalDigest<0>

Source§

fn default() -> Self

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

Auto Trait Implementations§

§

impl<const N: usize = 0> !Freeze for RefusalDigest<N>

§

impl<const N: usize> Forget for RefusalDigest<N>

§

impl<const N: usize> RefUnwindSafe for RefusalDigest<N>
where [&'static str; N]: RefUnwindSafe, [Atomic<u64>; N]: RefUnwindSafe,

§

impl<const N: usize> Send for RefusalDigest<N>
where [&'static str; N]: Send, [Atomic<u64>; N]: Send,

§

impl<const N: usize> Sync for RefusalDigest<N>
where [&'static str; N]: Sync, [Atomic<u64>; N]: Sync,

§

impl<const N: usize> Unpin for RefusalDigest<N>
where [&'static str; N]: Unpin, [Atomic<u64>; N]: Unpin,

§

impl<const N: usize> UnsafeUnpin for RefusalDigest<N>
where [&'static str; N]: UnsafeUnpin, [Atomic<u64>; N]: UnsafeUnpin,

§

impl<const N: usize> UnwindSafe for RefusalDigest<N>
where [&'static str; N]: UnwindSafe, [Atomic<u64>; N]: UnwindSafe,

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

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.