1use core::convert::TryFrom;
2use core::fmt;
3
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5pub struct BerClassFromIntError(pub(crate) ());
6
7#[derive(Debug, Copy, Clone, Eq, PartialEq)]
9#[repr(u8)]
10pub enum Class {
11 Universal = 0b00,
13 Application = 0b01,
15 ContextSpecific = 0b10,
17 Private = 0b11,
19}
20
21impl Class {
22 pub const UNIVERSAL: u8 = 0b00;
24 pub const APPLICATION: u8 = 0b01;
26 pub const CONTEXT_SPECIFIC: u8 = 0b10;
28 pub const PRIVATE: u8 = 0b11;
30
31 pub const fn assert_eq(&self, class: Class) -> Result<(), crate::error::Error> {
32 if *self as u8 == class as u8 {
33 Ok(())
34 } else {
35 Err(crate::error::Error::UnexpectedClass {
36 expected: Some(class),
37 actual: *self,
38 })
39 }
40 }
41}
42
43impl fmt::Display for Class {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 let s = match self {
46 Class::Universal => "UNIVERSAL",
47 Class::Application => "APPLICATION",
48 Class::ContextSpecific => "CONTEXT-SPECIFIC",
49 Class::Private => "PRIVATE",
50 };
51 write!(f, "{}", s)
52 }
53}
54
55impl TryFrom<u8> for Class {
56 type Error = BerClassFromIntError;
57
58 #[inline]
59 fn try_from(value: u8) -> Result<Self, Self::Error> {
60 match value {
61 0b00 => Ok(Class::Universal),
62 0b01 => Ok(Class::Application),
63 0b10 => Ok(Class::ContextSpecific),
64 0b11 => Ok(Class::Private),
65 _ => Err(BerClassFromIntError(())),
66 }
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn methods_class() {
76 let c = Class::Universal;
77 assert!(c.assert_eq(Class::Universal).is_ok());
78 assert!(c.assert_eq(Class::Private).is_err());
79
80 assert_eq!(Class::Universal.to_string().as_str(), "UNIVERSAL");
81 assert_eq!(Class::Application.to_string().as_str(), "APPLICATION");
82 assert_eq!(
83 Class::ContextSpecific.to_string().as_str(),
84 "CONTEXT-SPECIFIC"
85 );
86 assert_eq!(Class::Private.to_string().as_str(), "PRIVATE");
87
88 assert!(Class::try_from(0b00).is_ok());
89 assert!(Class::try_from(0b01).is_ok());
90 assert!(Class::try_from(0b10).is_ok());
91 assert!(Class::try_from(0b11).is_ok());
92 assert!(Class::try_from(4).is_err());
93 }
94}