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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
//! Types for expressing properties of different target platforms and platform-based conditions

/// CPU architecture, as reported by `target_arch`.
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum Arch {
  X86,
  X86_64,
  Mips,
  PowerPC,
  PowerPC64,
  Arm,
  AArch64,
}

/// Operating system, as reported by `target_os`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum OS {
  Windows,
  MacOS,
  IOS,
  Linux,
  Android,
  FreeBSD,
  DragonFly,
  Bitrig,
  OpenBSD,
  NetBSD,
}

/// Operating system family, as reported by `target_family`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum Family {
  Windows,
  Unix,
}

/// Further disambiguates the target platform with information about the ABI/libc,
/// as reported by `target_env`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum Env {
  Gnu,
  Msvc,
  Musl,
  None,
}

/// Pointer width in bits,
/// as reported by `target_pointer_width`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum PointerWidth {
  P64,
  P32,
}

/// CPU endianness, as reported by `target_endian`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum Endian {
  Little,
  Big,
}

/// Combined information about a target, as reported by configuration
/// values of the Rust compiler.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub struct Target {
  /// CPU architecture
  pub arch: Arch,
  /// Operating system
  pub os: OS,
  /// Operating system family
  pub family: Family,
  /// Further disambiguates the target platform with information about the ABI/libc,
  pub env: Env,
  /// Pointer width in bits,
  pub pointer_width: PointerWidth,
  /// Endianness of the target CPU
  pub endian: Endian,
}

/// Condition on properties of the target. Simple conditions
/// are considered true if the property of the current platform
/// is the same as the associated value of the enum. For
/// example, `Condition::OS(OS::Windows)` will be true on Windows
/// and false otherwise. `And`, `Or` and `Not` variants provide
/// logical operations on nested conditions. `True` and `False`
/// variants provide conditions which are always true and false,
/// respectively.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Serialize, Deserialize)]
pub enum Condition {
  Arch(Arch),
  OS(OS),
  Family(Family),
  Env(Env),
  PointerWidth(PointerWidth),
  // Vendor(Vendor),
  Endian(Endian),
  And(Vec<Condition>),
  Or(Vec<Condition>),
  Not(Box<Condition>),
  True,
  False,
}

#[cfg(target_arch = "x86")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::X86
}
#[cfg(target_arch = "x86_64")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::X86_64
}
#[cfg(target_arch = "mips")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::Mips
}
#[cfg(target_arch = "powerpc")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::PowerPC
}
#[cfg(target_arch = "powerpc64")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::PowerPC64
}
#[cfg(target_arch = "arm")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::Arm
}
#[cfg(target_arch = "aarch64")]
/// Returns current CPU architecture
pub fn current_arch() -> Arch {
  Arch::AArch64
}


#[cfg(target_os = "windows")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::Windows
}
#[cfg(target_os = "macos")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::MacOS
}
#[cfg(target_os = "ios")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::IOS
}
#[cfg(target_os = "linux")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::Linux
}
#[cfg(target_os = "android")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::Android
}
#[cfg(target_os = "freebsd")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::FreeBSD
}
#[cfg(target_os = "dragonfly")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::DragonFly
}
#[cfg(target_os = "bitrig")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::Bitrig
}
#[cfg(target_os = "openbsd")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::OpenBSD
}
#[cfg(target_os = "netbsd")]
/// Returns current operating system
pub fn current_os() -> OS {
  OS::NetBSD
}


#[cfg(target_family = "unix")]
/// Returns current operating system family
pub fn current_family() -> Family {
  Family::Unix
}
#[cfg(target_family = "windows")]
/// Returns current operating system family
pub fn current_family() -> Family {
  Family::Windows
}

#[cfg(target_env = "gnu")]
/// Returns current platform disambiguation
pub fn current_env() -> Env {
  Env::Gnu
}
#[cfg(target_env = "msvc")]
/// Returns current platform disambiguation
pub fn current_env() -> Env {
  Env::Msvc
}
#[cfg(target_env = "musl")]
/// Returns current platform disambiguation
pub fn current_env() -> Env {
  Env::Musl
}
#[cfg(target_env = "")]
/// Returns current platform disambiguation
pub fn current_env() -> Env {
  Env::None
}

#[cfg(target_pointer_width = "32")]
/// Returns current pointer width
pub fn current_pointer_width() -> PointerWidth {
  PointerWidth::P32
}
#[cfg(target_pointer_width = "64")]
/// Returns current pointer width
pub fn current_pointer_width() -> PointerWidth {
  PointerWidth::P64
}

#[cfg(target_endian = "little")]
/// Returns current CPU endianness
pub fn current_endian() -> Endian {
  Endian::Little
}
#[cfg(target_endian = "big")]
/// Returns current CPU endianness
pub fn current_endian() -> Endian {
  Endian::Big
}

/// Returns properties of the current target
pub fn current_target() -> Target {
  Target {
    arch: current_arch(),
    os: current_os(),
    family: current_family(),
    env: current_env(),
    pointer_width: current_pointer_width(),
    endian: current_endian(),
  }
}


impl Condition {
  /// Evaluate the condition for `target`. Returns true if
  /// `target` matches the condition.
  pub fn eval(&self, target: &Target) -> bool {
    use target::Condition::*;
    match *self {
      Arch(ref arch) => &target.arch == arch,
      OS(ref os) => &target.os == os,
      Family(ref family) => &target.family == family,
      Env(ref env) => &target.env == env,
      PointerWidth(ref pointer_width) => &target.pointer_width == pointer_width,
      Endian(ref endian) => &target.endian == endian,
      And(ref conditions) => conditions.iter().all(|c| c.eval(target)),
      Or(ref conditions) => conditions.iter().any(|c| c.eval(target)),
      Not(ref condition) => !condition.eval(target),
      True => true,
      False => false,
    }
  }
  /// Construct a condition opposite to `self`.
  pub fn negate(&self) -> Condition {
    Condition::Not(Box::new(self.clone()))
  }
}