use core::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Fault {
LengthInTwoOctets,
SmallFragment,
SmallNumberAsLarge,
LongNumber,
Padding,
LongArc,
}
impl Fault {
pub const fn clause(self) -> &'static str {
match self {
Self::LengthInTwoOctets => "11.9.3.6",
Self::SmallFragment => "11.9.3.8.1",
Self::SmallNumberAsLarge => "11.6.1",
Self::LongNumber => "11.3.6, 11.4.6",
Self::Padding => "11.1.4",
Self::LongArc => "8.19.2",
}
}
pub const fn standard(self) -> &'static str {
match self {
Self::LongArc => "X.690",
_ => "X.691",
}
}
}
impl fmt::Display for Fault {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let what = match self {
Self::LengthInTwoOctets => "a length of 127 or less is in two octets",
Self::SmallFragment => "a fragment before another is not the largest",
Self::SmallNumberAsLarge => "a number of 63 or less is in the form of a larger one",
Self::LongNumber => "a whole number is in more octets than it needs",
Self::Padding => "padding bits are not zero",
Self::LongArc => {
"an arc of an object identifier starts with an octet that holds nothing"
}
};
write!(formatter, "{what} ({} §{})", self.standard(), self.clause())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Noted {
pub fault: Fault,
pub bit: usize,
}
impl fmt::Display for Noted {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "at bit {}, {}", self.bit, self.fault)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Faults {
first: [Noted; Self::KEPT],
count: usize,
}
impl Faults {
const KEPT: usize = 4;
pub(crate) const fn new() -> Self {
let unused = Noted {
fault: Fault::LengthInTwoOctets,
bit: 0,
};
Self {
first: [unused; Self::KEPT],
count: 0,
}
}
pub(crate) fn push(&mut self, fault: Fault, bit: usize) {
if let Some(place) = self.first.get_mut(self.count) {
*place = Noted { fault, bit };
}
self.count = self.count.saturating_add(1);
}
pub const fn count(&self) -> usize {
self.count
}
pub fn as_slice(&self) -> &[Noted] {
&self.first[..self.count.min(Self::KEPT)]
}
}
impl Default for Faults {
fn default() -> Self {
Self::new()
}
}
impl core::ops::Deref for Faults {
type Target = [Noted];
fn deref(&self) -> &[Noted] {
self.as_slice()
}
}
impl fmt::Debug for Faults {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_slice().fmt(formatter)
}
}