1 use serde::{de, ser, Deserialize, Serialize}; 2 use std::fmt; 3 4 #[derive(Debug, PartialEq, Clone, Copy)] 5 #[repr(u8)] 6 pub enum Version { 7 V1 = 0x00, 8 V2 = 0x01, 9 V3 = 0x02, 10 } 11 12 impl Default for Version { default() -> Self13 fn default() -> Self { 14 Self::V1 15 } 16 } 17 18 impl Version { from_u8(v: u8) -> Option<Self>19 pub fn from_u8(v: u8) -> Option<Self> { 20 match v { 21 0x00 => Some(Self::V1), 22 0x01 => Some(Self::V2), 23 0x02 => Some(Self::V3), 24 _ => None, 25 } 26 } 27 } 28 29 impl Serialize for Version { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,30 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 31 where 32 S: ser::Serializer, 33 { 34 serializer.serialize_u8(*self as u8) 35 } 36 } 37 38 impl<'de> Deserialize<'de> for Version { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>,39 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 40 where 41 D: de::Deserializer<'de>, 42 { 43 struct Visitor; 44 45 impl<'de> de::Visitor<'de> for Visitor { 46 type Value = Version; 47 48 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 49 write!(formatter, "a valid version number") 50 } 51 52 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> 53 where 54 E: de::Error, 55 { 56 let version = Version::from_u8(v).ok_or_else(|| { 57 E::invalid_value( 58 de::Unexpected::Other("invalid version number"), 59 &"a valid integer representing a supported version number (0, 1 or 2)", 60 ) 61 })?; 62 63 if version != Version::V3 { 64 return Err(E::invalid_value( 65 de::Unexpected::Other("unsupported certificate version"), 66 &"only V3 certificate are supported", 67 )); 68 } 69 70 Ok(version) 71 } 72 } 73 74 deserializer.deserialize_u8(Visitor) 75 } 76 } 77 78 #[cfg(test)] 79 mod tests { 80 use super::*; 81 use picky_asn1::wrapper::{ApplicationTag9, Implicit}; 82 use picky_asn1_der::Asn1DerError; 83 84 #[derive(Serialize, Deserialize, Debug, PartialEq)] 85 struct OptionalVersionTestStruct { 86 #[serde(skip_serializing_if = "version_is_default")] 87 version: Implicit<ApplicationTag9<Version>>, 88 other_non_optional_integer: u8, 89 } 90 version_is_default(version: &Implicit<ApplicationTag9<Version>>) -> bool91 fn version_is_default(version: &Implicit<ApplicationTag9<Version>>) -> bool { 92 (version.0).0 == Version::V1 93 } 94 95 #[test] optional_version()96 fn optional_version() { 97 let buffer_with_version: [u8; 10] = [0x30, 0x08, 0xA9, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x6E]; 98 99 let non_default = OptionalVersionTestStruct { 100 version: ApplicationTag9(Version::V3).into(), 101 other_non_optional_integer: 0x6E, 102 }; 103 104 check_serde!(non_default: OptionalVersionTestStruct in buffer_with_version); 105 106 let buffer_without_version: [u8; 5] = [0x30, 0x03, 0x02, 0x01, 0x6E]; 107 108 let default = OptionalVersionTestStruct { 109 version: ApplicationTag9(Version::default()).into(), 110 other_non_optional_integer: 0x6E, 111 }; 112 113 check_serde!(default: OptionalVersionTestStruct in buffer_without_version); 114 } 115 116 #[test] unsupported_version()117 fn unsupported_version() { 118 let buffer: [u8; 3] = [0x02, 0x01, 0x0F]; 119 120 let version: picky_asn1_der::Result<Version> = picky_asn1_der::from_bytes(&buffer); 121 match version { 122 Err(Asn1DerError::Message(msg)) => assert_eq!( 123 msg, 124 "invalid value: invalid version number, expected a valid integer \ 125 representing a supported version number (0, 1 or 2)" 126 ), 127 Err(err) => panic!("invalid error: {}", err), 128 Ok(_) => panic!("parsing should have failed but did not"), 129 } 130 } 131 } 132