pub struct RefusalDigest<const N: usize = 0> { /* private fields */ }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>
impl RefusalDigest<0>
Sourcepub const fn new() -> RefusalDigest<0>
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>
impl<const N: usize> RefusalDigest<N>
Sourcepub const fn with_codes(codes: [&'static str; N]) -> RefusalDigest<N>
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).
Sourcepub fn record(&self, error: &FormError)
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.