#![allow(dead_code, unused_variables)]
pub extern crate semver;
use std::env;
use std::error::Error;
use std::fmt::{self, Display};
use std::ops::Range;
use std::path::{Path, PathBuf};
use std::str::FromStr;
#[macro_export]
macro_rules! warning {
($($args:tt)*) => {
$crate::warning(format!($($args)*))
};
}
macro_rules! env_var {
($name:expr) => {
::std::env::var($name)
.expect(concat!($name, " environment variable is not set"))
};
}
macro_rules! env_var_os {
($name:expr) => {
::std::env::var_os($name)
.expect(concat!($name, " environment variable is not set"))
};
}
macro_rules! parse_env_var {
(try: $name:expr, $ty_desc:expr) => {
{
::std::env::var($name)
.ok()
.map(|v| v.parse()
.expect(&format!(concat!($name, " {:?} is not a valid ", $ty_desc), v))
)
}
};
($name:expr, $ty_desc:expr) => {
{
let v = env_var!($name);
v.parse()
.expect(&format!(concat!($name, " {:?} is not a valid ", $ty_desc), v))
}
};
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct InvalidInput(String);
impl InvalidInput {
pub fn input(&self) -> &str {
&self.0
}
}
impl Display for InvalidInput {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "invalid input: {:?}", self.0)
}
}
impl Error for InvalidInput {
fn description(&self) -> &str {
"invalid input"
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Atomic {
Integer { bits: u8 },
Pointer,
}
impl Display for Atomic {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Atomic::Integer { bits } => bits.fmt(fmt),
Atomic::Pointer => "ptr".fmt(fmt),
}
}
}
impl FromStr for Atomic {
type Err = InvalidInput;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "ptr" {
Ok(Atomic::Pointer)
} else if let Ok(bits) = s.parse() {
Ok(Atomic::Integer { bits: bits })
} else {
Err(InvalidInput(s.into()))
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Endianness {
Big,
Little,
}
impl Display for Endianness {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Endianness::Big => "big".fmt(fmt),
Endianness::Little => "little".fmt(fmt),
}
}
}
impl FromStr for Endianness {
type Err = InvalidInput;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"big" => Ok(Endianness::Big),
"little" => Ok(Endianness::Little),
_ => Err(InvalidInput(s.into()))
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum LibKind {
Static,
DyLib,
Framework,
}
impl Display for LibKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
LibKind::Static => "static".fmt(fmt),
LibKind::DyLib => "dylib".fmt(fmt),
LibKind::Framework => "framework".fmt(fmt),
}
}
}
impl FromStr for LibKind {
type Err = InvalidInput;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"static" => Ok(LibKind::Static),
"dylib" => Ok(LibKind::DyLib),
"framework" => Ok(LibKind::Framework),
_ => Err(InvalidInput(s.into()))
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Profile {
Debug,
Release,
}
impl Display for Profile {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Profile::Debug => "debug".fmt(fmt),
Profile::Release => "release".fmt(fmt),
}
}
}
impl FromStr for Profile {
type Err = InvalidInput;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"debug" => Ok(Profile::Debug),
"release" => Ok(Profile::Release),
_ => Err(InvalidInput(s.into()))
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SearchKind {
Dependency,
Crate,
Native,
Framework,
All,
}
impl Display for SearchKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
SearchKind::Dependency => "dependency".fmt(fmt),
SearchKind::Crate => "crate".fmt(fmt),
SearchKind::Native => "native".fmt(fmt),
SearchKind::Framework => "framework".fmt(fmt),
SearchKind::All => "all".fmt(fmt),
}
}
}
impl FromStr for SearchKind {
type Err = InvalidInput;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"dependency" => Ok(SearchKind::Dependency),
"crate" => Ok(SearchKind::Crate),
"native" => Ok(SearchKind::Native),
"framework" => Ok(SearchKind::Framework),
"all" => Ok(SearchKind::All),
_ => Err(InvalidInput(s.into()))
}
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Triple {
triple: String,
arch: Range<usize>,
env: Option<Range<usize>>,
family: Range<usize>,
os: Range<usize>,
}
impl Triple {
pub fn new(triple: String) -> Triple {
let arch;
let env;
let family;
let os;
{
let mut parts = triple.splitn(4, '-')
.map(|s| {
let off = subslice_offset(&triple, s);
off..(off + s.len())
});
arch = parts.next().expect(&format!("could not find architecture in triple {:?}", triple));
family = parts.next().expect(&format!("could not find family in triple {:?}", triple));
os = parts.next().expect(&format!("could not find os in triple {:?}", triple));
env = parts.next();
}
Triple {
triple: triple,
arch: arch,
env: env,
family: family,
os: os,
}
}
pub fn as_str(&self) -> &str {
&self.triple
}
pub fn arch(&self) -> &str {
&self.triple[self.arch.clone()]
}
pub fn env(&self) -> Option<&str> {
self.env.as_ref()
.map(|s| &self.triple[s.clone()])
}
pub fn family(&self) -> &str {
&self.triple[self.family.clone()]
}
pub fn os(&self) -> &str {
&self.triple[self.os.clone()]
}
}
impl Display for Triple {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.triple.fmt(fmt)
}
}
impl FromStr for Triple {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Triple::new(s.into()))
}
}
pub mod bin {
use std::env;
use std::path::PathBuf;
pub fn cargo() -> PathBuf {
env::var_os("CARGO")
.unwrap_or_else(|| "cargo".into())
.into()
}
pub fn rustc() -> PathBuf {
env_var_os!("RUSTC").into()
}
pub fn rustdoc() -> PathBuf {
env_var_os!("RUSTDOC").into()
}
}
pub mod cargo {
pub mod features {
use std::ascii::AsciiExt;
use std::env;
pub struct Iter {
iter: env::Vars,
}
impl Iterator for Iter {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
while let Some((key, _)) = self.iter.next() {
if key.starts_with("CARGO_FEATURE_") {
return Some(canon_feature_name(&key["CARGO_FEATURE_".len()..]));
}
}
None
}
}
pub fn all() -> Iter {
Iter {
iter: env::vars(),
}
}
pub fn enabled(name: &str) -> bool {
let key = format!("CARGO_FEATURE_{}", env_feature_name(name));
env::var(&key).is_ok()
}
fn canon_feature_name(name: &str) -> String {
name.chars()
.map(|c| match c {
'A'...'Z' => c.to_ascii_lowercase(),
'_' => '-',
c => c
})
.collect()
}
fn env_feature_name(name: &str) -> String {
name.chars()
.map(|c| match c {
'a'...'z' => c.to_ascii_uppercase(),
'-' => '_',
c => c
})
.collect()
}
}
pub mod manifest {
use std::env;
use std::path::PathBuf;
pub fn dir() -> PathBuf {
env_var!("CARGO_MANIFEST_DIR").into()
}
pub fn links() -> Option<String> {
env::var("CARGO_MANIFEST_LINKS").ok()
}
}
pub mod pkg {
use semver::Version;
pub fn authors() -> Vec<String> {
env_var!("CARGO_PKG_AUTHORS")
.split(':')
.map(Into::into)
.collect()
}
pub fn description() -> Option<String> {
let v = env_var!("CARGO_PKG_DESCRIPTION");
if v == "" {
None
} else {
Some(v)
}
}
pub fn homepage() -> Option<String> {
let v = env_var!("CARGO_PKG_HOMEPAGE");
if v == "" {
None
} else {
Some(v)
}
}
pub fn name() -> String {
env_var!("CARGO_PKG_NAME")
}
pub fn version() -> Version {
parse_env_var!("CARGO_PKG_VERSION", "version")
}
}
}
pub mod metadata {
use std::env;
pub fn emit_raw(key: &str, value: &str) {
println!("cargo:{}={}", key, value);
}
pub fn get_raw(dep: &str, key: &str) -> Option<String> {
let name = format!("DEP_{}_{}", dep.to_uppercase(), key.to_uppercase());
env::var(&name).ok()
}
}
pub mod rustc {
use std::path::Path;
use ::{LibKind, SearchKind};
pub fn link_lib<P: AsRef<Path>>(link_kind: Option<LibKind>, name: P) {
println!("cargo:rustc-link-lib={}{}",
link_kind.map(|v| format!("{}=", v))
.unwrap_or_else(|| "".into()),
name.as_ref().display());
}
pub fn link_search<P: AsRef<Path>>(link_kind: Option<SearchKind>, path: P) {
println!("cargo:rustc-link-search={}{}",
link_kind.map(|v| format!("{}=", v))
.unwrap_or_else(|| "".into()),
path.as_ref().display());
}
pub fn flags(flags: &str) {
println!("cargo:rustc-flags={}", flags);
}
pub fn cfg(cfg: &str) {
println!("cargo:rustc-cfg={}", cfg);
}
}
pub mod target {
use super::*;
pub fn endian() -> Option<Endianness> {
parse_env_var!(try: "CARGO_CFG_TARGET_ENDIAN", "endianness")
}
#[cfg(feature = "nightly")]
pub fn features() -> Option<Vec<String>> {
env::var("CARGO_CFG_TARGET_FEATURE")
.ok()
.map(|v| v.split(',').map(Into::into).collect())
}
#[cfg(feature = "nightly")]
pub fn has_atomic() -> Option<Vec<Atomic>> {
env::var("CARGO_CFG_TARGET_HAS_ATOMIC")
.ok()
.map(|v| {
v.split(',')
.map(|s| s.parse()
.expect(&format!("CARGO_CFG_TARGET_HAS_ATOMIC \
contained invalid atomic type {:?}", s)))
.collect()
})
}
pub fn pointer_width() -> Option<u8> {
parse_env_var!(try: "CARGO_CFG_TARGET_POINTER_WIDTH", "integer")
}
pub fn triple() -> Triple {
parse_env_var!("TARGET", "triple")
}
}
pub fn debug() -> bool {
parse_env_var!("DEBUG", "bool")
}
pub fn host() -> Triple {
parse_env_var!("HOST", "triple")
}
pub fn num_jobs() -> u32 {
parse_env_var!("NUM_JOBS", "integer")
}
pub fn opt_level() -> u32 {
parse_env_var!("OPT_LEVEL", "integer")
}
pub fn out_dir() -> PathBuf {
env_var_os!("OUT_DIR").into()
}
pub fn profile() -> Profile {
let s = env_var!("PROFILE");
match &*s {
"debug" => Profile::Debug,
"release" => Profile::Release,
_ => panic!("PROFILE {:?} is not a valid profile", s),
}
}
pub fn rerun_if_changed<P: AsRef<Path>>(path: P) {
println!("cargo:rerun-if-changed={}", path.as_ref().display());
}
pub fn warning<S: AsRef<str>>(msg: S) {
println!("cargo:warning={}", msg.as_ref());
}
pub fn unix() -> bool {
env::var("CARGO_CFG_UNIX").is_ok()
}
pub fn windows() -> bool {
env::var("CARGO_CFG_WINDOWS").is_ok()
}
fn subslice_offset(base: &str, inner: &str) -> usize {
let base_beg = base.as_ptr() as usize;
let inner = inner.as_ptr() as usize;
if inner < base_beg || inner > base_beg.wrapping_add(base.len()) {
panic!("cannot compute subslice offset of disjoint strings")
} else {
inner.wrapping_sub(base_beg)
}
}