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