fluvio_index/
target.rs

1use std::fmt;
2use serde::{Serialize, Deserialize};
3use crate::Error;
4use std::borrow::Cow;
5
6const PACKAGE_TARGET: &str = env!("PACKAGE_TARGET");
7
8/// Detects the target triple of the current build and returns
9/// the name of a compatible build target on packages.fluvio.io.
10///
11/// Returns `Some(Target)` if there is a compatible target, or
12/// `None` if this target is unsupported or has no compatible target.
13pub fn package_target() -> Result<Target, Error> {
14    let target = PACKAGE_TARGET.parse()?;
15    Ok(target)
16}
17
18/// An object representing a specific build target for an artifact
19/// being managed by fluvio-index.
20///
21/// This type is generally constructed using `FromStr` via the
22/// `parse` method.
23///
24/// # Example
25///
26/// ```
27/// # use fluvio_index::Target;
28/// let target: Target = "x86_64-unknown-linux-musl".parse().unwrap();
29/// ```
30#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize)]
31#[serde(transparent)]
32pub struct Target(Cow<'static, str>);
33
34#[allow(non_upper_case_globals)]
35impl Target {
36    // These constants are from back when `Target` was an enum.
37    // Their variants are now constants, so constructors should not have broken
38    pub const X86_64AppleDarwin: Target = Target(Cow::Borrowed("x86_64-apple-darwin"));
39    pub const X86_64UnknownLinuxMusl: Target = Target(Cow::Borrowed("x86_64-unknown-linux-musl"));
40    pub const ALL_TARGETS: &'static [Target] =
41        &[Target::X86_64AppleDarwin, Target::X86_64UnknownLinuxMusl];
42
43    pub fn as_str(&self) -> &str {
44        self.0.as_ref()
45    }
46}
47
48impl std::str::FromStr for Target {
49    type Err = Error;
50
51    /// When parsing from a string, here is the chance to make any
52    /// edits or to collapse multiple target names into one. An
53    /// example of this is how we transform the target name
54    /// `x86_64-unknown-linux-gnu` into `x86_64-unknown-linux-musl`.
55    ///
56    /// Additionally, if there are any "target strings" that we
57    /// know for a fact that we cannot support, we can identify
58    /// those strings here and manually reject them in order to
59    /// prevent downstream tooling from incorrectly allowing those
60    /// targets.
61    ///
62    /// All other target names should pass through unchanged.
63    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
64        let platform = match s {
65            "x86_64-apple-darwin" => Self::X86_64AppleDarwin,
66            "x86_64-unknown-linux-musl" => Self::X86_64UnknownLinuxMusl,
67            "x86_64-unknown-linux-gnu" => Self::X86_64UnknownLinuxMusl,
68            other => Self(Cow::Owned(other.to_owned())),
69        };
70        Ok(platform)
71    }
72}
73
74impl fmt::Display for Target {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        write!(f, "{}", self.as_str())
77    }
78}
79
80impl<'de> Deserialize<'de> for Target {
81    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82    where
83        D: serde::Deserializer<'de>,
84    {
85        let string = String::deserialize(deserializer)?;
86        let me: Self = std::str::FromStr::from_str(&string).map_err(|e: Error| {
87            serde::de::Error::invalid_value(
88                serde::de::Unexpected::Other(&e.to_string()),
89                &"valid Target",
90            )
91        })?;
92        Ok(me)
93    }
94}