1use core::{error, fmt, ops, str};
14
15use alloc::string::{String, ToString};
16
17#[derive(Debug)]
19pub struct VcardVersionParseError(
20 String,
22);
23
24impl fmt::Display for VcardVersionParseError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 write!(f, "Cannot parse vCard version `{}`", self.0)
27 }
28}
29
30impl error::Error for VcardVersionParseError {}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35pub enum VcardVersion {
36 V2_1,
38 V3_0,
40 V4_0,
42}
43
44impl str::FromStr for VcardVersion {
45 type Err = VcardVersionParseError;
46
47 fn from_str(version: &str) -> Result<Self, Self::Err> {
49 match version {
50 "2.1" => Ok(Self::V2_1),
51 "3.0" => Ok(Self::V3_0),
52 "4.0" => Ok(Self::V4_0),
53 _ => Err(VcardVersionParseError(version.to_string())),
54 }
55 }
56}
57
58impl ops::Deref for VcardVersion {
59 type Target = str;
60
61 fn deref(&self) -> &Self::Target {
62 match self {
63 Self::V2_1 => "2.1",
64 Self::V3_0 => "3.0",
65 Self::V4_0 => "4.0",
66 }
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use alloc::string::ToString;
73
74 use crate::version::VcardVersion;
75
76 #[test]
77 fn maps_known_wire_strings_both_ways() {
78 assert_eq!("2.1".parse().ok(), Some(VcardVersion::V2_1));
79 assert_eq!(VcardVersion::V3_0.to_string(), "3.0");
80 assert_eq!(&*VcardVersion::V4_0, "4.0");
81 }
82
83 #[test]
84 fn rejects_unknown_versions() {
85 let error = "5.0".parse::<VcardVersion>().unwrap_err();
86 assert!(error.to_string().contains("5.0"));
87 }
88}