ffsend_api/api/version.rs
1use std::fmt;
2
3use version_compare::{CompOp, VersionCompare};
4
5/// Firefox Send API version selector.
6#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7pub enum Version {
8 /// Firefox Send v2.
9 #[cfg(feature = "send2")]
10 V2,
11
12 /// Firefox Send v3.
13 #[cfg(feature = "send3")]
14 V3,
15}
16
17impl Version {
18 /// Attempt to parse the API version from a version number string.
19 ///
20 /// If the given version number string could not be matched to a known
21 /// (or not compiled due to a missing compiler feature) API version an
22 /// `Err` is returning holding the version string.
23 pub fn parse<'a>(ver: &'a str) -> Result<Self, &'a str> {
24 // Trim, and strip any prefixed v
25 let mut stripped = ver.trim();
26 if stripped.starts_with('v') {
27 stripped = &stripped[1..];
28 }
29
30 // Error on empty string
31 if stripped.is_empty() {
32 return Err(ver);
33 }
34
35 // Is this using version 2
36 #[cfg(feature = "send2")]
37 {
38 // Test the lower and upper version bounds
39 let lower =
40 VersionCompare::compare_to(stripped, "2.0", &CompOp::Ge).map_err(|_| ver)?;
41 let upper =
42 VersionCompare::compare_to(stripped, "3.0", &CompOp::Lt).map_err(|_| ver)?;
43 if lower && upper {
44 return Ok(Version::V2);
45 }
46 }
47
48 // Is this using version 3
49 #[cfg(feature = "send3")]
50 {
51 // Test the lower and upper version bounds
52 let lower =
53 VersionCompare::compare_to(stripped, "3.0", &CompOp::Ge).map_err(|_| ver)?;
54 let upper =
55 VersionCompare::compare_to(stripped, "4.0", &CompOp::Lt).map_err(|_| ver)?;
56 if lower && upper {
57 return Ok(Version::V3);
58 }
59 }
60
61 Err(ver)
62 }
63}
64
65impl fmt::Display for Version {
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 match self {
68 #[cfg(feature = "send2")]
69 Version::V2 => write!(f, "2"),
70
71 #[cfg(feature = "send3")]
72 Version::V3 => write!(f, "3"),
73 }
74 }
75}
76
77/// A desired version to use for communicating with a Send server.
78///
79/// Various options are available, to use an exact version, or to look it up at runtime.
80#[derive(Debug, Copy, Clone, PartialEq, Eq)]
81pub enum DesiredVersion {
82 /// Use just the given API version when communicating with a Send server.
83 Use(Version),
84
85 /// Assume the given API version when communicating with a Send version, but attempt to look up
86 /// the correct version if communication fails.
87 Assume(Version),
88
89 /// Attempt to look up the server API version at runtime.
90 Lookup,
91}
92
93impl DesiredVersion {
94 /// Get the selected API version, if set.
95 ///
96 /// This returns `None` if it is the `Lookup` variant.
97 pub fn version(self) -> Option<Version> {
98 match self {
99 DesiredVersion::Use(v) => Some(v),
100 DesiredVersion::Assume(v) => Some(v),
101 DesiredVersion::Lookup => None,
102 }
103 }
104}