1 use serde::de; 2 use std::fmt; 3 4 #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] 5 pub struct Tag(u8); 6 7 impl Tag { 8 pub const BOOLEAN: Self = Tag(0x01); 9 pub const INTEGER: Self = Tag(0x02); 10 pub const BIT_STRING: Self = Tag(0x03); 11 pub const OCTET_STRING: Self = Tag(0x04); 12 pub const NULL: Self = Tag(0x05); 13 pub const OID: Self = Tag(0x06); 14 pub const REAL: Self = Tag(0x09); 15 pub const UTF8_STRING: Self = Tag(0x0C); 16 pub const RELATIVE_OID: Self = Tag(0xD); 17 pub const NUMERIC_STRING: Self = Tag(0x12); 18 pub const PRINTABLE_STRING: Self = Tag(0x13); 19 pub const TELETEX_STRING: Self = Tag(0x14); 20 pub const VIDEOTEX_STRING: Self = Tag(0x15); 21 pub const IA5_STRING: Self = Tag(0x16); 22 pub const UTC_TIME: Self = Tag(0x17); 23 pub const GENERALIZED_TIME: Self = Tag(0x18); 24 pub const SEQUENCE: Self = Tag(0x30); 25 pub const SET: Self = Tag(0x31); 26 pub const APP_0: Self = Tag::application(0); 27 pub const APP_1: Self = Tag::application(1); 28 pub const APP_2: Self = Tag::application(2); 29 pub const APP_3: Self = Tag::application(3); 30 pub const APP_4: Self = Tag::application(4); 31 pub const APP_5: Self = Tag::application(5); 32 pub const APP_6: Self = Tag::application(6); 33 pub const APP_7: Self = Tag::application(7); 34 pub const APP_8: Self = Tag::application(8); 35 pub const APP_9: Self = Tag::application(9); 36 pub const APP_10: Self = Tag::application(10); 37 pub const APP_11: Self = Tag::application(11); 38 pub const APP_12: Self = Tag::application(12); 39 pub const APP_13: Self = Tag::application(13); 40 pub const APP_14: Self = Tag::application(14); 41 pub const APP_15: Self = Tag::application(15); 42 pub const CTX_0: Self = Tag::context_specific(0); 43 pub const CTX_1: Self = Tag::context_specific(1); 44 pub const CTX_2: Self = Tag::context_specific(2); 45 pub const CTX_3: Self = Tag::context_specific(3); 46 pub const CTX_4: Self = Tag::context_specific(4); 47 pub const CTX_5: Self = Tag::context_specific(5); 48 pub const CTX_6: Self = Tag::context_specific(6); 49 pub const CTX_7: Self = Tag::context_specific(7); 50 pub const CTX_8: Self = Tag::context_specific(8); 51 pub const CTX_9: Self = Tag::context_specific(9); 52 pub const CTX_10: Self = Tag::context_specific(10); 53 pub const CTX_11: Self = Tag::context_specific(11); 54 pub const CTX_12: Self = Tag::context_specific(12); 55 pub const CTX_13: Self = Tag::context_specific(13); 56 pub const CTX_14: Self = Tag::context_specific(14); 57 pub const CTX_15: Self = Tag::context_specific(15); 58 59 #[inline] application(number: u8) -> Self60 pub const fn application(number: u8) -> Self { 61 Tag(0xA0 | number) 62 } 63 64 #[inline] context_specific(number: u8) -> Self65 pub const fn context_specific(number: u8) -> Self { 66 Tag(0x80 | number) 67 } 68 69 #[inline] number(self) -> u870 pub const fn number(self) -> u8 { 71 self.0 72 } 73 74 #[inline] is_application(self) -> bool75 pub fn is_application(self) -> bool { 76 self.0 >= Self::APP_0.0 && self.0 <= Self::APP_15.0 77 } 78 79 #[inline] is_context_specific(self) -> bool80 pub fn is_context_specific(self) -> bool { 81 self.0 >= Self::CTX_0.0 && self.0 <= Self::CTX_15.0 82 } 83 } 84 85 impl From<u8> for Tag { from(tag: u8) -> Self86 fn from(tag: u8) -> Self { 87 Self(tag) 88 } 89 } 90 91 impl fmt::Display for Tag { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 93 match *self { 94 Tag::BOOLEAN => write!(f, "BOOLEAN"), 95 Tag::INTEGER => write!(f, "INTEGER"), 96 Tag::BIT_STRING => write!(f, "BIT STRING"), 97 Tag::OCTET_STRING => write!(f, "OCTET STRING"), 98 Tag::NULL => write!(f, "NULL"), 99 Tag::OID => write!(f, "OBJECT IDENTIFIER"), 100 Tag::REAL => write!(f, "REAL"), 101 Tag::UTF8_STRING => write!(f, "UTF8String"), 102 Tag::RELATIVE_OID => write!(f, "RELATIVE-OID"), 103 Tag::NUMERIC_STRING => write!(f, "NumericString"), 104 Tag::PRINTABLE_STRING => write!(f, "PrintableString"), 105 Tag::TELETEX_STRING => write!(f, "TeletexString"), 106 Tag::VIDEOTEX_STRING => write!(f, "VideotexString"), 107 Tag::IA5_STRING => write!(f, "IA5String"), 108 Tag::UTC_TIME => write!(f, "UTCTime"), 109 Tag::GENERALIZED_TIME => write!(f, "GeneralizedTime"), 110 Tag::SEQUENCE => write!(f, "SEQUENCE"), 111 Tag::SET => write!(f, "SET"), 112 Tag::APP_0 => write!(f, "ApplicationTag0"), 113 Tag::APP_1 => write!(f, "ApplicationTag1"), 114 Tag::APP_2 => write!(f, "ApplicationTag2"), 115 Tag::APP_3 => write!(f, "ApplicationTag3"), 116 Tag::APP_4 => write!(f, "ApplicationTag4"), 117 Tag::APP_5 => write!(f, "ApplicationTag5"), 118 Tag::APP_6 => write!(f, "ApplicationTag6"), 119 Tag::APP_7 => write!(f, "ApplicationTag7"), 120 Tag::APP_8 => write!(f, "ApplicationTag8"), 121 Tag::APP_9 => write!(f, "ApplicationTag9"), 122 Tag::APP_10 => write!(f, "ApplicationTag10"), 123 Tag::APP_11 => write!(f, "ApplicationTag11"), 124 Tag::APP_12 => write!(f, "ApplicationTag12"), 125 Tag::APP_13 => write!(f, "ApplicationTag13"), 126 Tag::APP_14 => write!(f, "ApplicationTag14"), 127 Tag::APP_15 => write!(f, "ApplicationTag15"), 128 Tag::CTX_0 => write!(f, "ContextTag0"), 129 Tag::CTX_1 => write!(f, "ContextTag1"), 130 Tag::CTX_2 => write!(f, "ContextTag2"), 131 Tag::CTX_3 => write!(f, "ContextTag3"), 132 Tag::CTX_4 => write!(f, "ContextTag4"), 133 Tag::CTX_5 => write!(f, "ContextTag5"), 134 Tag::CTX_6 => write!(f, "ContextTag6"), 135 Tag::CTX_7 => write!(f, "ContextTag7"), 136 Tag::CTX_8 => write!(f, "ContextTag8"), 137 Tag::CTX_9 => write!(f, "ContextTag9"), 138 Tag::CTX_10 => write!(f, "ContextTag10"), 139 Tag::CTX_11 => write!(f, "ContextTag11"), 140 Tag::CTX_12 => write!(f, "ContextTag12"), 141 Tag::CTX_13 => write!(f, "ContextTag13"), 142 Tag::CTX_14 => write!(f, "ContextTag14"), 143 Tag::CTX_15 => write!(f, "ContextTag15"), 144 unknown => write!(f, "UNKNOWN({})", unknown.0), 145 } 146 } 147 } 148 149 impl fmt::Debug for Tag { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 151 write!(f, "Tag({}[{}])", self, self.0) 152 } 153 } 154 155 /// Used to peek next tag by using `Deserializer::deserialize_identifier`. 156 /// 157 /// Can be used to implement ASN.1 Choice. 158 /// 159 /// # Examples 160 /// ``` 161 /// use serde::de; 162 /// use picky_asn1::{ 163 /// wrapper::{IntegerAsn1, Utf8StringAsn1}, 164 /// tag::{Tag, TagPeeker}, 165 /// }; 166 /// use std::fmt; 167 /// 168 /// pub enum MyChoice { 169 /// Integer(u32), 170 /// Utf8String(String), 171 /// } 172 /// 173 /// impl<'de> de::Deserialize<'de> for MyChoice { 174 /// fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error> 175 /// where 176 /// D: de::Deserializer<'de>, 177 /// { 178 /// struct Visitor; 179 /// 180 /// impl<'de> de::Visitor<'de> for Visitor { 181 /// type Value = MyChoice; 182 /// 183 /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 184 /// formatter.write_str("a valid MyChoice") 185 /// } 186 /// 187 /// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> 188 /// where 189 /// A: de::SeqAccess<'de>, 190 /// { 191 /// match seq.next_element::<TagPeeker>()?.unwrap().next_tag { 192 /// Tag::INTEGER => { 193 /// let value = seq.next_element::<u32>()?.unwrap(); 194 /// Ok(MyChoice::Integer(value)) 195 /// } 196 /// Tag::UTF8_STRING => { 197 /// let value = seq.next_element::<String>()?.unwrap(); 198 /// Ok(MyChoice::Utf8String(value)) 199 /// } 200 /// _ => Err(de::Error::invalid_value( 201 /// de::Unexpected::Other( 202 /// "[MyChoice] unsupported or unknown choice value", 203 /// ), 204 /// &"a supported choice value", 205 /// )) 206 /// } 207 /// } 208 /// } 209 /// 210 /// deserializer.deserialize_enum("MyChoice", &["Integer", "Utf8String"], Visitor) 211 /// } 212 /// } 213 /// 214 /// let buffer = b"\x0C\x06\xE8\x8B\x97\xE5\xAD\x97"; 215 /// let my_choice: MyChoice = picky_asn1_der::from_bytes(buffer).unwrap(); 216 /// match my_choice { 217 /// MyChoice::Integer(_) => panic!("wrong variant"), 218 /// MyChoice::Utf8String(string) => assert_eq!(string, "苗字"), 219 /// } 220 /// ``` 221 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 222 pub struct TagPeeker { 223 pub next_tag: Tag, 224 } 225 226 impl<'de> de::Deserialize<'de> for TagPeeker { deserialize<D>(deserializer: D) -> Result<TagPeeker, D::Error> where D: de::Deserializer<'de>,227 fn deserialize<D>(deserializer: D) -> Result<TagPeeker, D::Error> 228 where 229 D: de::Deserializer<'de>, 230 { 231 struct Visitor; 232 233 impl<'de> de::Visitor<'de> for Visitor { 234 type Value = TagPeeker; 235 236 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 237 formatter.write_str("a valid ASN.1 tag") 238 } 239 240 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> 241 where 242 E: de::Error, 243 { 244 Ok(TagPeeker { next_tag: v.into() }) 245 } 246 } 247 248 deserializer.deserialize_identifier(Visitor) 249 } 250 } 251