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}