decaf377_fmd/
precision.rs

1use core::fmt;
2
3use crate::Error;
4
5/// The maximum detection precision, chosen so that the message bits fit in 3 bytes.
6pub(crate) const MAX_PRECISION: u8 = 24;
7
8/// Represents the precision governing the false positive rate of detection.
9///
10/// This is usually measured in bits, where a precision of `n` bits yields false
11/// positives with a rate of `2^-n`.
12///
13/// This type implements `TryFrom` for `u8`, `u32`, `u64`, and `i32`, which has the behavior of considering
14/// the value as a number of bits, and converting if this number isn't too large.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct Precision(u8);
17
18impl Precision {
19    pub const MAX: Precision = Precision(MAX_PRECISION);
20
21    pub fn new(precision_bits: u8) -> Result<Self, Error> {
22        if precision_bits > MAX_PRECISION {
23            return Err(Error::PrecisionTooLarge(precision_bits.into()));
24        }
25        Ok(Self(precision_bits))
26    }
27
28    pub fn bits(&self) -> u8 {
29        self.0
30    }
31}
32
33impl Default for Precision {
34    fn default() -> Self {
35        Self(0)
36    }
37}
38
39impl fmt::Display for Precision {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        write!(f, "{}", self.0)
42    }
43}
44
45impl TryFrom<u8> for Precision {
46    type Error = Error;
47
48    fn try_from(value: u8) -> Result<Self, Self::Error> {
49        Self::new(value)
50    }
51}
52
53impl TryFrom<u32> for Precision {
54    type Error = Error;
55
56    fn try_from(value: u32) -> Result<Self, Self::Error> {
57        u8::try_from(value)
58            .map_err(|_| Error::PrecisionTooLarge(value.into()))?
59            .try_into()
60    }
61}
62
63impl TryFrom<u64> for Precision {
64    type Error = Error;
65
66    fn try_from(value: u64) -> Result<Self, Self::Error> {
67        u8::try_from(value)
68            .map_err(|_| Error::PrecisionTooLarge(value))?
69            .try_into()
70    }
71}
72
73impl TryFrom<i32> for Precision {
74    type Error = Error;
75
76    fn try_from(value: i32) -> Result<Self, Self::Error> {
77        u8::try_from(value)
78            .map_err(|_| Error::PrecisionTooLarge(value as u64))?
79            .try_into()
80    }
81}