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
132
133
//! Rust target environments

use crate::error::Error;
use core::{fmt, str::FromStr};

#[cfg(feature = "serde")]
use serde::{de, de::Error as DeError, ser, Deserialize, Serialize};

/// `target_env`: target environment that disambiguates the target platform by ABI / libc.
///
/// This value is closely related to the fourth element of the platform target triple,
/// though it is not identical. For example, embedded ABIs such as `gnueabihf` will simply
/// define `target_env` as `"gnu"` (i.e. `target::Env::GNU`)
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum Env {
    /// ``: None
    None,

    /// `gnu`: The GNU C Library (glibc)
    Gnu,

    /// `msvc`: Microsoft Visual C(++)
    Msvc,

    /// `musl`: Clean, efficient, standards-conformant libc implementation.
    Musl,

    /// `newlib`
    Newlib,

    /// `nto70`
    Nto70,

    /// `nto71`
    Nto71,

    /// `ohos`
    OhOS,

    /// `p1`
    P1,

    /// `p2`
    P2,

    /// `psx`
    Psx,

    /// `relibc`
    Relibc,

    /// `sgx`: Intel Software Guard Extensions (SGX) Enclave
    Sgx,

    /// `uclibc`: C library for developing embedded Linux systems
    UClibc,
}

impl Env {
    /// String representing this `Env` which matches `#[cfg(target_env)]`
    pub fn as_str(self) -> &'static str {
        match self {
            Env::None => "",
            Env::Gnu => "gnu",
            Env::Msvc => "msvc",
            Env::Musl => "musl",
            Env::Newlib => "newlib",
            Env::Nto70 => "nto70",
            Env::Nto71 => "nto71",
            Env::OhOS => "ohos",
            Env::P1 => "p1",
            Env::P2 => "p2",
            Env::Psx => "psx",
            Env::Relibc => "relibc",
            Env::Sgx => "sgx",
            Env::UClibc => "uclibc",
        }
    }
}

impl FromStr for Env {
    type Err = Error;

    /// Create a new `Env` from the given string
    fn from_str(name: &str) -> Result<Self, Self::Err> {
        let result = match name {
            "" => Env::None,
            "gnu" => Env::Gnu,
            "msvc" => Env::Msvc,
            "musl" => Env::Musl,
            "newlib" => Env::Newlib,
            "nto70" => Env::Nto70,
            "nto71" => Env::Nto71,
            "ohos" => Env::OhOS,
            "p1" => Env::P1,
            "p2" => Env::P2,
            "psx" => Env::Psx,
            "relibc" => Env::Relibc,
            "sgx" => Env::Sgx,
            "uclibc" => Env::UClibc,
            _ => return Err(Error),
        };

        Ok(result)
    }
}

impl fmt::Display for Env {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

#[cfg(feature = "serde")]
impl Serialize for Env {
    fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str(self.as_str())
    }
}

#[cfg(all(feature = "serde", feature = "std"))]
impl<'de> Deserialize<'de> for Env {
    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        let string = std::string::String::deserialize(deserializer)?;
        string.parse().map_err(|_| {
            D::Error::custom(std::format!(
                "Unrecognized value '{}' for target_env",
                string
            ))
        })
    }
}