<commit_before>use crate::{
    analysis::{
        functions::{Info as FuncInfo, Visibility},
        imports::Imports,
    },
    config::GObject,
    library::{Type as LibType, TypeId},
    version::Version,
};
use std::{collections::BTreeMap, str::FromStr};

#[derive(Clone, Copy, Eq, Debug, Ord, PartialEq, PartialOrd)]
pub enum Type {
    Compare,
    Copy,
    Equal,
    Free,
    Ref,
    Display,
    Unref,
    Hash,
}

impl FromStr for Type {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::Type::*;
        match s {
            "compare" => Ok(Compare),
            "copy" => Ok(Copy),
            "equal" => Ok(Equal),
            "free" | "destroy" => Ok(Free),
            "is_equal" => Ok(Equal),
            "ref" | "ref_" => Ok(Ref),
            "unref" => Ok(Unref),
            "hash" => Ok(Hash),
            _ => Err(format!("Unknown type '{}'", s)),
        }
    }
}

#[derive(Debug, Clone)]
pub struct TraitInfo {
    pub glib_name: String,
    pub version: Option<Version>,
    pub first_parameter_mut: bool,
}

type TraitInfos = BTreeMap<Type, TraitInfo>;

#[derive(Clone, Copy, Eq, Debug, Ord, PartialEq, PartialOrd)]
pub enum FunctionType {
    StaticStringify,
}

#[derive(Debug, Clone)]
pub struct FunctionInfo {
    pub type_: FunctionType,
    pub version: Option<Version>,
}

type FunctionInfos = BTreeMap<String, FunctionInfo>;

#[derive(Debug, Default)]
pub struct Infos {
    traits: TraitInfos,
    functions: FunctionInfos,
}

impl Infos {
    pub fn traits(&self) -> &TraitInfos {
        &self.traits
    }

    pub fn traits_mut(&mut self) -> &mut TraitInfos {
        &mut self.traits
    }

    pub fn has_trait(&self, type_: Type) -> bool {
        self.traits.contains_key(&type_)
    }

    pub fn functions(&self) -> &FunctionInfos {
        &self.functions
    }
}

/// Returns true on functions that take an instance as single argument and
/// return a string as result.
fn is_stringify(func: &mut FuncInfo, parent_type: &LibType, obj: &GObject) -> bool {
    if func.parameters.c_parameters.len() != 1 {
        return false;
    }
    if !func.parameters.c_parameters[0].instance_parameter {
        return false;
    }

    if let Some(ret) = func.ret.parameter.as_mut() {
        if ret.typ != TypeId::tid_utf8() {
            return false;
        }

        if func.name == "to_string" {
            // Rename to to_str to make sure it doesn't clash with ToString::to_string
            func.name = "to_str".to_owned();

            // As to not change old code behaviour, assume non-nullability outside
            // enums and flags only, and exclusively for to_string. Function inside
            // enums and flags have been appropriately marked in Gir.
            if !obj.trust_return_value_nullability
                && !matches!(parent_type, LibType::Enumeration(_) | LibType::Bitfield(_))
            {
                *ret.nullable = false;
            }
        }

        // Cannot generate Display implementation for Option<>
        !*ret.nullable
    } else {
        false
    }
}

fn update_func(func: &mut FuncInfo, type_: Type) -> bool {
    if func.visibility != Visibility::Comment {
        func.visibility = visibility(type_);
    }
    true
}

pub fn extract(functions: &mut Vec<FuncInfo>, parent_type: &LibType, obj: &GObject) -> Infos {
    let mut specials = Infos::default();
    let mut has_copy = false;
    let mut has_free = false;
    let mut destroy = None;

    for (pos, func) in functions.iter_mut().enumerate() {
        if is_stringify(func, parent_type, obj) {
            let return_transfer_none = func
                .ret
                .parameter
                .as_ref()
                .map_or(false, |ret| ret.transfer == crate::library::Transfer::None);

            // Assume only enumerations and bitfields can return static strings
            let returns_static_ref = return_transfer_none
                && matches!(parent_type, LibType::Enumeration(_) | LibType::Bitfield(_))
                // We cannot mandate returned lifetime if this is not generated.
                // (And this prevents an unused std::ffi::CStr from being emitted below)
                && func.status.need_generate();

            if returns_static_ref {
                // Override the function with a &'static (non allocating) -returning string
                // if the transfer type is none and it matches the above heuristics.
                specials.functions.insert(
                    func.glib_name.clone(),
                    FunctionInfo {
                        type_: FunctionType::StaticStringify,
                        version: func.version,
                    },
                );
            }

            // Some stringifying functions can serve as Display implementation
            if matches!(
                func.name.as_str(),
                "to_string" | "to_str" | "name" | "get_name"
            ) {
                // FUTURE: Decide which function gets precedence if multiple Display prospects exist.
                specials.traits.insert(
                    Type::Display,
                    TraitInfo {
                        glib_name: func.glib_name.clone(),
                        version: func.version,
                        first_parameter_mut: false,
                    },
                );
            }
        } else if let Ok(type_) = func.name.parse() {
            if func.name == "destroy" {
                destroy = Some((func.glib_name.clone(), pos));
                continue;
            }
            if !update_func(func, type_) {
                continue;
            }
            if func.name == "copy" {
                has_copy = true;
            } else if func.name == "free" {
                has_free = true;
            }

            let first_parameter_mut = func
                .parameters
                .c_parameters
                .first()
                .map_or(false, |p| p.ref_mode == super::ref_mode::RefMode::ByRefMut);

            specials.traits.insert(
                type_,
                TraitInfo {
                    glib_name: func.glib_name.clone(),
                    version: func.version,
                    first_parameter_mut,
                },
            );
        }
    }

    if has_copy && !has_free {
        if let Some((glib_name, pos)) = destroy {
            let ty_ = Type::from_str("destroy").unwrap();
            let func = &mut functions[pos];
            update_func(func, ty_);
            specials.traits.insert(
                ty_,
                TraitInfo {
                    glib_name,
                    version: func.version,
                    first_parameter_mut: true,
                },
            );
        }
    }

    specials
}

fn visibility(t: Type) -> Visibility {
    use self::Type::*;
    match t {
        Copy | Free | Ref | Unref => Visibility::Hidden,
        Hash | Compare | Equal => Visibility::Private,
        Display => Visibility::Public,
    }
}

// Some special functions (e.g. `copy` on refcounted types) should be exposed
pub fn unhide(functions: &mut Vec<FuncInfo>, specials: &Infos, type_: Type) {
    if let Some(func) = specials.traits().get(&type_) {
        let func = functions
            .iter_mut()
            .find(|f| f.glib_name == func.glib_name && f.visibility != Visibility::Comment);
        if let Some(func) = func {
            func.visibility = Visibility::Public;
        }
    }
}

pub fn analyze_imports(specials: &Infos, imports: &mut Imports) {
    for (type_, info) in specials.traits() {
        use self::Type::*;
        match *type_ {
            Compare => imports.add_with_version("std::cmp", info.version),
            Display => imports.add_with_version("std::fmt", info.version),
            Hash => imports.add_with_version("std::hash", info.version),
            _ => {}
        }
    }
    for info in specials.functions().values() {
        match info.type_ {
            FunctionType::StaticStringify => {
                imports.add_with_version("std::ffi::CStr", info.version)
            }
        }
    }
}
<commit_msg>analysis/special_functions: Import glib::translate for mut_override<commit_after>use crate::{
    analysis::{
        functions::{Info as FuncInfo, Visibility},
        imports::Imports,
    },
    config::GObject,
    library::{Type as LibType, TypeId},
    version::Version,
};
use std::{collections::BTreeMap, str::FromStr};

#[derive(Clone, Copy, Eq, Debug, Ord, PartialEq, PartialOrd)]
pub enum Type {
    Compare,
    Copy,
    Equal,
    Free,
    Ref,
    Display,
    Unref,
    Hash,
}

impl FromStr for Type {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::Type::*;
        match s {
            "compare" => Ok(Compare),
            "copy" => Ok(Copy),
            "equal" => Ok(Equal),
            "free" | "destroy" => Ok(Free),
            "is_equal" => Ok(Equal),
            "ref" | "ref_" => Ok(Ref),
            "unref" => Ok(Unref),
            "hash" => Ok(Hash),
            _ => Err(format!("Unknown type '{}'", s)),
        }
    }
}

#[derive(Debug, Clone)]
pub struct TraitInfo {
    pub glib_name: String,
    pub version: Option<Version>,
    pub first_parameter_mut: bool,
}

type TraitInfos = BTreeMap<Type, TraitInfo>;

#[derive(Clone, Copy, Eq, Debug, Ord, PartialEq, PartialOrd)]
pub enum FunctionType {
    StaticStringify,
}

#[derive(Debug, Clone)]
pub struct FunctionInfo {
    pub type_: FunctionType,
    pub version: Option<Version>,
}

type FunctionInfos = BTreeMap<String, FunctionInfo>;

#[derive(Debug, Default)]
pub struct Infos {
    traits: TraitInfos,
    functions: FunctionInfos,
}

impl Infos {
    pub fn traits(&self) -> &TraitInfos {
        &self.traits
    }

    pub fn traits_mut(&mut self) -> &mut TraitInfos {
        &mut self.traits
    }

    pub fn has_trait(&self, type_: Type) -> bool {
        self.traits.contains_key(&type_)
    }

    pub fn functions(&self) -> &FunctionInfos {
        &self.functions
    }
}

/// Returns true on functions that take an instance as single argument and
/// return a string as result.
fn is_stringify(func: &mut FuncInfo, parent_type: &LibType, obj: &GObject) -> bool {
    if func.parameters.c_parameters.len() != 1 {
        return false;
    }
    if !func.parameters.c_parameters[0].instance_parameter {
        return false;
    }

    if let Some(ret) = func.ret.parameter.as_mut() {
        if ret.typ != TypeId::tid_utf8() {
            return false;
        }

        if func.name == "to_string" {
            // Rename to to_str to make sure it doesn't clash with ToString::to_string
            func.name = "to_str".to_owned();

            // As to not change old code behaviour, assume non-nullability outside
            // enums and flags only, and exclusively for to_string. Function inside
            // enums and flags have been appropriately marked in Gir.
            if !obj.trust_return_value_nullability
                && !matches!(parent_type, LibType::Enumeration(_) | LibType::Bitfield(_))
            {
                *ret.nullable = false;
            }
        }

        // Cannot generate Display implementation for Option<>
        !*ret.nullable
    } else {
        false
    }
}

fn update_func(func: &mut FuncInfo, type_: Type) -> bool {
    if func.visibility != Visibility::Comment {
        func.visibility = visibility(type_);
    }
    true
}

pub fn extract(functions: &mut Vec<FuncInfo>, parent_type: &LibType, obj: &GObject) -> Infos {
    let mut specials = Infos::default();
    let mut has_copy = false;
    let mut has_free = false;
    let mut destroy = None;

    for (pos, func) in functions.iter_mut().enumerate() {
        if is_stringify(func, parent_type, obj) {
            let return_transfer_none = func
                .ret
                .parameter
                .as_ref()
                .map_or(false, |ret| ret.transfer == crate::library::Transfer::None);

            // Assume only enumerations and bitfields can return static strings
            let returns_static_ref = return_transfer_none
                && matches!(parent_type, LibType::Enumeration(_) | LibType::Bitfield(_))
                // We cannot mandate returned lifetime if this is not generated.
                // (And this prevents an unused std::ffi::CStr from being emitted below)
                && func.status.need_generate();

            if returns_static_ref {
                // Override the function with a &'static (non allocating) -returning string
                // if the transfer type is none and it matches the above heuristics.
                specials.functions.insert(
                    func.glib_name.clone(),
                    FunctionInfo {
                        type_: FunctionType::StaticStringify,
                        version: func.version,
                    },
                );
            }

            // Some stringifying functions can serve as Display implementation
            if matches!(
                func.name.as_str(),
                "to_string" | "to_str" | "name" | "get_name"
            ) {
                // FUTURE: Decide which function gets precedence if multiple Display prospects exist.
                specials.traits.insert(
                    Type::Display,
                    TraitInfo {
                        glib_name: func.glib_name.clone(),
                        version: func.version,
                        first_parameter_mut: false,
                    },
                );
            }
        } else if let Ok(type_) = func.name.parse() {
            if func.name == "destroy" {
                destroy = Some((func.glib_name.clone(), pos));
                continue;
            }
            if !update_func(func, type_) {
                continue;
            }
            if func.name == "copy" {
                has_copy = true;
            } else if func.name == "free" {
                has_free = true;
            }

            let first_parameter_mut = func
                .parameters
                .c_parameters
                .first()
                .map_or(false, |p| p.ref_mode == super::ref_mode::RefMode::ByRefMut);

            specials.traits.insert(
                type_,
                TraitInfo {
                    glib_name: func.glib_name.clone(),
                    version: func.version,
                    first_parameter_mut,
                },
            );
        }
    }

    if has_copy && !has_free {
        if let Some((glib_name, pos)) = destroy {
            let ty_ = Type::from_str("destroy").unwrap();
            let func = &mut functions[pos];
            update_func(func, ty_);
            specials.traits.insert(
                ty_,
                TraitInfo {
                    glib_name,
                    version: func.version,
                    first_parameter_mut: true,
                },
            );
        }
    }

    specials
}

fn visibility(t: Type) -> Visibility {
    use self::Type::*;
    match t {
        Copy | Free | Ref | Unref => Visibility::Hidden,
        Hash | Compare | Equal => Visibility::Private,
        Display => Visibility::Public,
    }
}

// Some special functions (e.g. `copy` on refcounted types) should be exposed
pub fn unhide(functions: &mut Vec<FuncInfo>, specials: &Infos, type_: Type) {
    if let Some(func) = specials.traits().get(&type_) {
        let func = functions
            .iter_mut()
            .find(|f| f.glib_name == func.glib_name && f.visibility != Visibility::Comment);
        if let Some(func) = func {
            func.visibility = Visibility::Public;
        }
    }
}

pub fn analyze_imports(specials: &Infos, imports: &mut Imports) {
    for (type_, info) in specials.traits() {
        use self::Type::*;
        match *type_ {
            Copy if info.first_parameter_mut => {
                imports.add_with_version("glib::translate::*", info.version)
            }
            Compare => imports.add_with_version("std::cmp", info.version),
            Display => imports.add_with_version("std::fmt", info.version),
            Hash => imports.add_with_version("std::hash", info.version),
            _ => {}
        }
    }
    for info in specials.functions().values() {
        match info.type_ {
            FunctionType::StaticStringify => {
                imports.add_with_version("std::ffi::CStr", info.version)
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    env, fs,
    path::{Path, PathBuf},
};

use flapigen::{JavaConfig, JavaReachabilityFence, LanguageConfig};

fn main() {
    env_logger::init();

    let out_dir = env::var("OUT_DIR").unwrap();
    let jni_c_headers_rs = Path::new(&out_dir).join("jni_c_header.rs");
    gen_jni_bindings(&jni_c_headers_rs);
    let have_java_9 = fs::read_to_string(&jni_c_headers_rs)
        .unwrap()
        .contains("JNI_VERSION_9");

    let java_cfg = JavaConfig::new(
        Path::new("java").join("com").join("example").join("rust"),
        "com.example.rust".into(),
    )
    .use_reachability_fence(if have_java_9 {
        JavaReachabilityFence::Std
    } else {
        JavaReachabilityFence::GenerateFence(8)
    });

    let in_src = Path::new("src").join("java_glue.rs.in");
    let test_opt_rsc = Path::new("src").join("test_optional.rs.in");
    let out_src = Path::new(&out_dir).join("java_glue.rs");
    let swig_gen = flapigen::Generator::new(LanguageConfig::JavaConfig(java_cfg))
        .rustfmt_bindings(true)
        .remove_not_generated_files_from_output_directory(true)
        .merge_type_map("chrono_support", include_str!("src/chrono-include.rs"))
        .register_class_attribute_callback("PartialEq", |code, class_name| {
            let needle = format!("class {} {{", class_name);
            let class_pos = code
                .windows(needle.len())
                .position(|window| window == needle.as_bytes())
                .expect("Can not find begin of class");
            let insert_pos = class_pos + needle.len();
            code.splice(
                insert_pos..insert_pos,
                format!(
                    r#"
    public boolean equals(Object obj) {{
        boolean equal = false;
        if (obj instanceof {class})
          equal = (({class})obj).rustEq(this);
        return equal;
    }}
    public int hashCode() {{
        return (int)mNativeObj;
    }}
"#,
                    class = class_name
                )
                .as_bytes()
                .iter()
                .copied(),
            );
        });
    swig_gen.expand_many("flapigen_test_jni", &[&in_src, &test_opt_rsc], &out_src);

    println!("cargo:rerun-if-changed={}", in_src.display());
    println!("cargo:rerun-if-changed={}", test_opt_rsc.display());
    println!("cargo:rerun-if-changed=src/chrono-include.rs");
}

fn gen_jni_bindings(jni_c_headers_rs: &Path) {
    let java_home = env::var("JAVA_HOME").expect("JAVA_HOME env variable not settted");

    let java_include_dir = Path::new(&java_home).join("include");

    let target = env::var("TARGET").expect("target env var not setted");
    let java_sys_include_dir = java_include_dir.join(if target.contains("windows") {
        "win32"
    } else if target.contains("darwin") {
        "darwin"
    } else {
        "linux"
    });

    let include_dirs = [java_include_dir, java_sys_include_dir];
    println!("jni include dirs {:?}", include_dirs);

    let jni_h_path =
        search_file_in_directory(&include_dirs[..], "jni.h").expect("Can not find jni.h");
    println!("cargo:rerun-if-changed={}", jni_h_path.display());

    gen_binding(&include_dirs[..], &jni_h_path, jni_c_headers_rs).expect("gen_binding failed");
}

fn search_file_in_directory<P: AsRef<Path>>(dirs: &[P], file: &str) -> Result<PathBuf, ()> {
    for dir in dirs {
        let dir = dir.as_ref().to_path_buf();
        let file_path = dir.join(file);
        if file_path.exists() && file_path.is_file() {
            return Ok(file_path);
        }
    }
    Err(())
}

fn gen_binding<P: AsRef<Path>>(
    include_dirs: &[P],
    c_file_path: &Path,
    output_rust: &Path,
) -> Result<(), String> {
    let mut bindings: bindgen::Builder = bindgen::builder().header(c_file_path.to_str().unwrap());
    bindings = include_dirs.iter().fold(bindings, |acc, x| {
        acc.clang_arg("-I".to_string() + x.as_ref().to_str().unwrap())
    });

    let generated_bindings = bindings
        .generate()
        .map_err(|_| "Failed to generate bindings".to_string())?;
    generated_bindings
        .write_to_file(output_rust)
        .map_err(|err| err.to_string())?;

    Ok(())
}
<commit_msg>infra/ci: trying to fix stuck in windows ci<commit_after>use std::{
    env, fs,
    path::{Path, PathBuf},
};

use flapigen::{JavaConfig, JavaReachabilityFence, LanguageConfig};

fn main() {
    env_logger::init();

    let out_dir = env::var("OUT_DIR").unwrap();
    let jni_c_headers_rs = Path::new(&out_dir).join("jni_c_header.rs");
    gen_jni_bindings(&jni_c_headers_rs);
    let have_java_9 = fs::read_to_string(&jni_c_headers_rs)
        .unwrap()
        .contains("JNI_VERSION_9");

    let java_cfg = JavaConfig::new(
        Path::new("java").join("com").join("example").join("rust"),
        "com.example.rust".into(),
    )
    .use_reachability_fence(if have_java_9 {
        JavaReachabilityFence::Std
    } else {
        JavaReachabilityFence::GenerateFence(8)
    });

    let in_src = Path::new("src").join("java_glue.rs.in");
    let test_opt_rsc = Path::new("src").join("test_optional.rs.in");
    let out_src = Path::new(&out_dir).join("java_glue.rs");
    let swig_gen = flapigen::Generator::new(LanguageConfig::JavaConfig(java_cfg))
        .rustfmt_bindings(true)
        .remove_not_generated_files_from_output_directory(true)
        .merge_type_map("chrono_support", include_str!("src/chrono-include.rs"))
        .register_class_attribute_callback("PartialEq", |code, class_name| {
            let needle = format!("class {} {{", class_name);
            let class_pos = code
                .windows(needle.len())
                .position(|window| window == needle.as_bytes())
                .expect("Can not find begin of class");
            let insert_pos = class_pos + needle.len();
            code.splice(
                insert_pos..insert_pos,
                format!(
                    r#"
    public boolean equals(Object obj) {{
        boolean equal = false;
        if (obj instanceof {class})
          equal = (({class})obj).rustEq(this);
        return equal;
    }}
    public int hashCode() {{
        return (int)mNativeObj;
    }}
"#,
                    class = class_name
                )
                .as_bytes()
                .iter()
                .copied(),
            );
        });
    swig_gen.expand_many("flapigen_test_jni", &[&in_src, &test_opt_rsc], &out_src);

    println!("cargo:rerun-if-changed={}", in_src.display());
    println!("cargo:rerun-if-changed={}", test_opt_rsc.display());
    println!("cargo:rerun-if-changed=src/chrono-include.rs");
}

fn gen_jni_bindings(jni_c_headers_rs: &Path) {
    let java_home = env::var("JAVA_HOME").expect("JAVA_HOME env variable not settted");

    let java_include_dir = Path::new(&java_home).join("include");

    let target = env::var("TARGET").expect("target env var not setted");
    let java_sys_include_dir = java_include_dir.join(if target.contains("windows") {
        "win32"
    } else if target.contains("darwin") {
        "darwin"
    } else {
        "linux"
    });

    let include_dirs = [java_include_dir, java_sys_include_dir];
    println!("jni include dirs {:?}", include_dirs);

    let jni_h_path =
        search_file_in_directory(&include_dirs[..], "jni.h").expect("Can not find jni.h");
    println!("cargo:rerun-if-changed={}", jni_h_path.display());

    gen_binding(&include_dirs[..], &jni_h_path, jni_c_headers_rs).expect("gen_binding failed");
}

fn search_file_in_directory<P: AsRef<Path>>(dirs: &[P], file: &str) -> Result<PathBuf, ()> {
    for dir in dirs {
        let dir = dir.as_ref().to_path_buf();
        let file_path = dir.join(file);
        if file_path.exists() && file_path.is_file() {
            return Ok(file_path);
        }
    }
    Err(())
}

fn gen_binding<P: AsRef<Path>>(
    include_dirs: &[P],
    c_file_path: &Path,
    output_rust: &Path,
) -> Result<(), String> {
    let mut bindings: bindgen::Builder = bindgen::builder()
        .layout_tests(false)
        .header(c_file_path.to_str().unwrap());
    bindings = include_dirs.iter().fold(bindings, |acc, x| {
        acc.clang_arg("-I".to_string() + x.as_ref().to_str().unwrap())
    });

    let generated_bindings = bindings
        .generate()
        .map_err(|_| "Failed to generate bindings".to_string())?;
    generated_bindings
        .write_to_file(output_rust)
        .map_err(|err| err.to_string())?;

    Ok(())
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_int, c_uint};

#[repr(C)]
#[deriving(Copy)]
pub struct RawEvent {
    pub etype: u8,
    pub emod: u8,
    pub key: u16,
    pub ch: u32,
    pub w: i32,
    pub h: i32,
}

extern "C" {
    pub fn tb_init() -> c_int;
    pub fn tb_shutdown();

    pub fn tb_width() -> c_uint;
    pub fn tb_height() -> c_uint;

    pub fn tb_clear();
    pub fn tb_present();

    pub fn tb_set_cursor(cx: c_int, cy: c_int);
    pub fn tb_change_cell(x: c_uint, y: c_uint, ch: u32, fg: u16, bg: u16);

    //pub fn tb_select_input_mode(mode: c_int) -> c_int;
    //pub fn tb_set_clear_attributes(fg: u16, bg: u16);

    pub fn tb_peek_event(ev: *const ::RawEvent, timeout: c_uint) -> c_int;
    pub fn tb_poll_event(ev: *const ::RawEvent) -> c_int;
}
<commit_msg>uncomment methods<commit_after>extern crate libc;

use libc::{c_int, c_uint};

#[repr(C)]
#[deriving(Copy)]
pub struct RawEvent {
    pub etype: u8,
    pub emod: u8,
    pub key: u16,
    pub ch: u32,
    pub w: i32,
    pub h: i32,
}

extern "C" {
    pub fn tb_init() -> c_int;
    pub fn tb_shutdown();

    pub fn tb_width() -> c_uint;
    pub fn tb_height() -> c_uint;

    pub fn tb_clear();
    pub fn tb_present();

    pub fn tb_set_cursor(cx: c_int, cy: c_int);
    pub fn tb_change_cell(x: c_uint, y: c_uint, ch: u32, fg: u16, bg: u16);

    pub fn tb_select_input_mode(mode: c_int) -> c_int;
    pub fn tb_set_clear_attributes(fg: u16, bg: u16);

    pub fn tb_peek_event(ev: *const ::RawEvent, timeout: c_uint) -> c_int;
    pub fn tb_poll_event(ev: *const ::RawEvent) -> c_int;
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
 ```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#[crate_id = "fourcc#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://static.rust-lang.org/doc/master")];

#[deny(deprecated_owned_vector)];
#[feature(macro_registrar, managed_boxes)];

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
    MRExpr(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>Convert most code to new inner attribute syntax.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
 ```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#![crate_id = "fourcc#0.10-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![deny(deprecated_owned_vector)]
#![feature(macro_registrar, managed_boxes)]

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
    MRExpr(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>


<commit_before>use super::{ ParseState, LiteralExpression, LITERAL_EXPRESSION, DotExpression,
DOT_EXPRESSION, Text, ParseResult, Node, Expression, CHAR_CLASS_EXPRESSION,
CharClassExpression };

fn ToParseState<'a>( text: &'a str ) -> ParseState<'a> {
  text.chars().enumerate()
}

#[test]
fn LiteralExpression_Match() {
  let expr = LiteralExpression { text: "foo" };
  match expr.apply( &ToParseState( "foobar" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: LITERAL_EXPRESSION,
                         start: 0,
                         end: 3,
                         contents: Text( ~"foo" ) } );
      assert_eq!( parse_state.next(), Some( ( 3, 'b' ) ) );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn LiteralExpression_NoMatch() {
  let expr = LiteralExpression { text: "zoo" };
  assert!( expr.apply( &ToParseState( "foobar" ) ).is_none() )
  assert!( expr.apply( &ToParseState( "" ) ).is_none() )
}

#[test]
fn DotExpression_Match_InputOneChar() {
  match DotExpression.apply( &ToParseState( "x" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: DOT_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( ~"x" ) } );
      assert_eq!( parse_state.next(), None );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn DotExpression_Match_InputOneWideChar() {
  match DotExpression.apply( &ToParseState( "葉" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: DOT_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( ~"葉" ) } );
      assert_eq!( parse_state.next(), None );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn DotExpression_Match_InputSeveralChars() {
  match DotExpression.apply( &ToParseState( "xb" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: DOT_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( ~"x" ) } );
      assert_eq!( parse_state.next(), Some( ( 1, 'b' ) ) );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn DotExpression_NoMatch() {
  assert!( DotExpression.apply( &ToParseState( "" ) ).is_none() )
}

fn charClassMatch( char_class: CharClassExpression, input: &str ) {
  match char_class.apply( &ToParseState( input ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: CHAR_CLASS_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( input.to_owned() ) } );
      assert_eq!( parse_state.next(), None );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn CharClassExpression_Match() {
  charClassMatch( CharClassExpression::new( "a" ), "a" );
  charClassMatch( CharClassExpression::new( "abcdef" ), "e" );
  charClassMatch( CharClassExpression::new( "a-z" ), "a" );
  charClassMatch( CharClassExpression::new( "a-z" ), "c" );
  charClassMatch( CharClassExpression::new( "a-z" ), "z" );
  charClassMatch( CharClassExpression::new( "0-9" ), "2" );
  charClassMatch( CharClassExpression::new( "α-ω" ), "η" );
  charClassMatch( CharClassExpression::new( "-" ), "-" );
  charClassMatch( CharClassExpression::new( "a-" ), "-" );
  charClassMatch( CharClassExpression::new( "-a" ), "-" );
  charClassMatch( CharClassExpression::new( "a-zA-Z-" ), "-" );
  charClassMatch( CharClassExpression::new( "aa-zA-Z-a" ), "-" );
  charClassMatch( CharClassExpression::new( "a-zA-Z-" ), "z" );
  charClassMatch( CharClassExpression::new( "aa-zA-Z-0" ), "0" );
  charClassMatch( CharClassExpression::new( "a-cdefgh-k" ), "e" );
}

<commit_msg>NoMatch tests for CharClassExpression<commit_after>use super::{ ParseState, LiteralExpression, LITERAL_EXPRESSION, DotExpression,
DOT_EXPRESSION, Text, ParseResult, Node, Expression, CHAR_CLASS_EXPRESSION,
CharClassExpression };

fn ToParseState<'a>( text: &'a str ) -> ParseState<'a> {
  text.chars().enumerate()
}

#[test]
fn LiteralExpression_Match() {
  let expr = LiteralExpression { text: "foo" };
  match expr.apply( &ToParseState( "foobar" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: LITERAL_EXPRESSION,
                         start: 0,
                         end: 3,
                         contents: Text( ~"foo" ) } );
      assert_eq!( parse_state.next(), Some( ( 3, 'b' ) ) );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn LiteralExpression_NoMatch() {
  let expr = LiteralExpression { text: "zoo" };
  assert!( expr.apply( &ToParseState( "foobar" ) ).is_none() )
  assert!( expr.apply( &ToParseState( "" ) ).is_none() )
}

#[test]
fn DotExpression_Match_InputOneChar() {
  match DotExpression.apply( &ToParseState( "x" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: DOT_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( ~"x" ) } );
      assert_eq!( parse_state.next(), None );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn DotExpression_Match_InputOneWideChar() {
  match DotExpression.apply( &ToParseState( "葉" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: DOT_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( ~"葉" ) } );
      assert_eq!( parse_state.next(), None );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn DotExpression_Match_InputSeveralChars() {
  match DotExpression.apply( &ToParseState( "xb" ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: DOT_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( ~"x" ) } );
      assert_eq!( parse_state.next(), Some( ( 1, 'b' ) ) );
    }
    _ => fail!( "No match!" )
  };
}

#[test]
fn DotExpression_NoMatch() {
  assert!( DotExpression.apply( &ToParseState( "" ) ).is_none() )
}

fn charClassMatch( char_class: CharClassExpression, input: &str ) -> bool {
  match char_class.apply( &ToParseState( input ) ) {
    Some( ParseResult{ node: Some( ref node ),
                       parse_state: mut parse_state } ) => {
      assert_eq!( *node,
                  Node { name: CHAR_CLASS_EXPRESSION,
                         start: 0,
                         end: 1,
                         contents: Text( input.to_owned() ) } );
      assert_eq!( parse_state.next(), None );
      true
    }
    _ => false
  }
}

#[test]
fn CharClassExpression_Match() {
  assert!( charClassMatch( CharClassExpression::new( "a" ), "a" ) );
  assert!( charClassMatch( CharClassExpression::new( "abcdef" ), "e" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-z" ), "a" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-z" ), "c" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-z" ), "z" ) );
  assert!( charClassMatch( CharClassExpression::new( "0-9" ), "2" ) );
  assert!( charClassMatch( CharClassExpression::new( "α-ω" ), "η" ) );
  assert!( charClassMatch( CharClassExpression::new( "-" ), "-" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-" ), "-" ) );
  assert!( charClassMatch( CharClassExpression::new( "-a" ), "-" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-zA-Z-" ), "-" ) );
  assert!( charClassMatch( CharClassExpression::new( "aa-zA-Z-a" ), "-" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-zA-Z-" ), "z" ) );
  assert!( charClassMatch( CharClassExpression::new( "aa-zA-Z-0" ), "0" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-cdefgh-k" ), "e" ) );
  assert!( charClassMatch( CharClassExpression::new( "---" ), "-" ) );
  assert!( charClassMatch( CharClassExpression::new( "a-a" ), "a" ) );
}

#[test]
fn CharClassExpression_NoMatch() {
  assert!( !charClassMatch( CharClassExpression::new( "a" ), "b" ) );
  assert!( !charClassMatch( CharClassExpression::new( "-" ), "a" ) );
  assert!( !charClassMatch( CharClassExpression::new( "z-a" ), "a" ) );
  assert!( !charClassMatch( CharClassExpression::new( "z-a" ), "b" ) );
  assert!( !charClassMatch( CharClassExpression::new( "a-z" ), "0" ) );
  assert!( !charClassMatch( CharClassExpression::new( "a-z" ), "A" ) );
}
<|endoftext|>


<commit_before>mod ball_ball_toi;
mod compound_penetration;
mod epa2;
mod ray_cast;
mod time_of_impact2;
mod ball_cuboid_contact;<commit_msg>Run cargo fmt.<commit_after>mod ball_ball_toi;
mod ball_cuboid_contact;
mod compound_penetration;
mod epa2;
mod ray_cast;
mod time_of_impact2;
<|endoftext|>


<commit_before>use clap::{App, Arg, AppSettings, SubCommand, ArgMatches};
use common;
use rustup::{Cfg, Toolchain, command};
use rustup::telemetry::TelemetryMode;
use errors::*;
use rustup_dist::manifest::Component;
use rustup_dist::dist::TargetTriple;
use rustup_utils::utils;
use self_update;
use std::path::Path;

pub fn main() -> Result<()> {
    try!(::self_update::cleanup_self_updater());

    let ref matches = cli().get_matches();
    let verbose = matches.is_present("verbose");
    let ref cfg = try!(common::set_globals(verbose));

    if try!(maybe_upgrade_data(cfg, matches)) {
        return Ok(())
    }

    try!(cfg.check_metadata_version());

    match matches.subcommand() {
        ("default", Some(m)) => try!(default_(cfg, m)),
        ("update", Some(m)) => try!(update(cfg, m)),
        ("run", Some(m)) => try!(run(cfg, m)),
        ("which", Some(m)) => try!(which(cfg, m)),
        ("show", Some(_)) => try!(show(cfg)),
        ("target", Some(c)) => {
            match c.subcommand() {
                ("list", Some(m)) => try!(target_list(cfg, m)),
                ("add", Some(m)) => try!(target_add(cfg, m)),
                ("remove", Some(m)) => try!(target_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("toolchain", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_toolchains(cfg)),
                ("link", Some(m)) => try!(toolchain_link(cfg, m)),
                ("remove", Some(m)) => try!(toolchain_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("override", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_overrides(cfg)),
                ("add", Some(m)) => try!(override_add(cfg, m)),
                ("remove", Some(_)) => try!(override_remove(cfg)),
                (_ ,_) => unreachable!(),
            }
        }
        ("doc", Some(m)) => try!(doc(cfg, m)),
        ("self", Some(c)) => {
            match c.subcommand() {
                ("update", Some(_)) => try!(self_update::update()),
                ("uninstall", Some(m)) => try!(self_uninstall(m)),
                (_ ,_) => unreachable!(),
            }
        }
        ("telemetry", Some(c)) => {
            match c.subcommand() {
                ("enable", Some(_)) => try!(set_telemetry(&cfg, TelemetryMode::On)),
                ("disable", Some(_)) => try!(set_telemetry(&cfg, TelemetryMode::Off)),
                ("analyze", Some(_)) => try!(analyze_telemetry(&cfg)),
                (_, _) => unreachable!(),
            }
        }
        (_, _) => unreachable!(),
    }

    Ok(())
}

pub fn cli() -> App<'static, 'static> {
    App::new("rustup")
        .version(common::version())
        .about("The Rust toolchain installer")
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::DeriveDisplayOrder)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("verbose")
            .help("Enable verbose output")
            .short("v")
            .long("verbose"))
        .subcommand(SubCommand::with_name("default")
            .about("Set the default toolchain")
            .arg(Arg::with_name("toolchain")
                .required(true)))
        .subcommand(SubCommand::with_name("update")
            .about("Update all toolchains, install or update a given toolchain")
            .arg(Arg::with_name("toolchain")
                .required(false))
            .arg(Arg::with_name("no-self-update")
                .help("Don't perform self update when running the `rustup` command")
                .long("no-self-update")
                .takes_value(false)
                .hidden(true)))
        .subcommand(SubCommand::with_name("run")
            .about("Run a command with an environment configured for a given toolchain")
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("toolchain")
                .required(true))
            .arg(Arg::with_name("command")
                .required(true).multiple(true)))
        .subcommand(SubCommand::with_name("which")
            .about("Display which binary will be run for a given command")
            .arg(Arg::with_name("command")
                .required(true)))
        .subcommand(SubCommand::with_name("show")
            .about("Show the active toolchain"))
        .subcommand(SubCommand::with_name("target")
            .about("Modify a toolchain's supported targets")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed and available targets")
                .arg(Arg::with_name("toolchain")
                    .long("toolchain")
                    .takes_value(true)))
            .subcommand(SubCommand::with_name("add")
                .about("Add a target to a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true))
                .arg(Arg::with_name("toolchain")
                    .long("toolchain")
                    .takes_value(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove a target  from a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true))
                .arg(Arg::with_name("toolchain")
                    .long("toolchain")
                    .takes_value(true))))
        .subcommand(SubCommand::with_name("toolchain")
            .about("Modify or query the installed toolchains")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed toolchains"))
            .subcommand(SubCommand::with_name("link")
                .about("Create a custom toolchain by symlinking to a directory")
                .arg(Arg::with_name("toolchain")
                    .required(true))
                .arg(Arg::with_name("path")
                    .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Uninstall a toolchain")
                .arg(Arg::with_name("toolchain")
                     .required(true))))
        .subcommand(SubCommand::with_name("override")
            .about("Modify directory toolchain overrides")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List directory toolchain overrides"))
            .subcommand(SubCommand::with_name("add")
                .about("Set the override toolchain for a directory")
                .arg(Arg::with_name("toolchain")
                     .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove the override toolchain for a directory")))
        .subcommand(SubCommand::with_name("self")
            .about("Modify the rustup installation")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("update")
                .about("Download and install updates to rustup"))
            .subcommand(SubCommand::with_name("uninstall")
                .about("Uninstall rustup.")
                .arg(Arg::with_name("no-prompt")
                     .short("y")))
            .subcommand(SubCommand::with_name("upgrade-data")
                .about("Upgrade the internal data format.")))
        .subcommand(SubCommand::with_name("telemetry")
            .about("rustup telemetry commands")
            .subcommand(SubCommand::with_name("enable")
                            .about("Enable rustup telemetry"))
            .subcommand(SubCommand::with_name("disable")
                            .about("Disable rustup telemetry"))
            .subcommand(SubCommand::with_name("analyze")
                            .about("Analyze stored telemetry")))
}

fn maybe_upgrade_data(cfg: &Cfg, m: &ArgMatches) -> Result<bool> {
    match m.subcommand() {
        ("self", Some(c)) => {
            match c.subcommand() {
                ("upgrade-data", Some(_)) => {
                    try!(cfg.upgrade_data());
                    Ok(true)
                }
                _ => Ok(false),
            }
        }
        _ => Ok(false)
    }
}

fn default_(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(ErrorKind::ToolchainNotInstalled(toolchain.name().to_string()).into());
    } else {
        None
    };

    try!(toolchain.make_default());

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn update(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    if let Some(name) = m.value_of("toolchain") {
        let toolchain = try!(cfg.get_toolchain(name, false));

        let status = if !toolchain.is_custom() {
            Some(try!(toolchain.install_from_dist()))
        } else if !toolchain.exists() {
            return Err(ErrorKind::ToolchainNotInstalled(toolchain.name().to_string()).into());
        } else {
            None
        };

        if let Some(status) = status {
            println!("");
            try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
        }
    } else {
        try!(common::update_all_channels(cfg, !m.is_present("no-self-update")));
    }

    Ok(())
}

fn run(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let args = m.values_of("command").unwrap();
    let args: Vec<_> = args.collect();
    let cmd = try!(cfg.create_command_for_toolchain(toolchain, args[0]));

    Ok(try!(command::run_command_for_dir(cmd, &args, &cfg)))
}

fn which(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let binary = m.value_of("command").expect("");

    let binary_path = try!(cfg.which_binary(&try!(utils::current_dir()), binary))
                          .expect("binary not found");

    try!(utils::assert_is_file(&binary_path));

    println!("{}", binary_path.display());

    Ok(())
}

fn show(cfg: &Cfg) -> Result<()> {
    let ref cwd = try!(utils::current_dir());
    let override_ = try!(cfg.find_override(cwd));
    if let Some((toolchain, reason)) = override_ {
        println!("{} ({})", toolchain.name(), reason);
        return Ok(());
    }

    let toolchain = try!(cfg.find_default());
    if let Some(toolchain) = toolchain {
        println!("{} (default toolchain)", toolchain.name());
        return Ok(());
    }

    println!("no active toolchain");

    Ok(())
}

fn target_list(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = try!(explicit_or_dir_toolchain(cfg, m));

    common::list_targets(&toolchain)
}

fn target_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = try!(explicit_or_dir_toolchain(cfg, m));
    let target = m.value_of("target").expect("");
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: TargetTriple::from_str(target),
    };

    Ok(try!(toolchain.add_component(new_component)))
}

fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = try!(explicit_or_dir_toolchain(cfg, m));
    let target = m.value_of("target").expect("");
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: TargetTriple::from_str(target),
    };

    Ok(try!(toolchain.remove_component(new_component)))
}

fn explicit_or_dir_toolchain<'a>(cfg: &'a Cfg, m: &ArgMatches) -> Result<Toolchain<'a>> {
    let toolchain = m.value_of("toolchain");
    if let Some(toolchain) = toolchain {
        let toolchain = try!(cfg.get_toolchain(toolchain, false));
        return Ok(toolchain);
    }

    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));

    Ok(toolchain)
}

fn toolchain_link(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref path = m.value_of("path").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, true));

    Ok(try!(toolchain.install_from_dir(Path::new(path), true)))
}

fn toolchain_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    Ok(try!(toolchain.remove()))
}

fn override_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(ErrorKind::ToolchainNotInstalled(toolchain.name().to_string()).into());
    } else {
        None
    };

    try!(toolchain.make_override(&try!(utils::current_dir())));

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn override_remove(cfg: &Cfg) -> Result<()> {
    let ref path = try!(utils::current_dir());

    let ref override_db = cfg.override_db;
    let notify_handler = cfg.notify_handler.as_ref();

    if try!(override_db.find(path, notify_handler)).is_none() {
        info!("no override toolchain for '{}'", path.display());
        return Ok(());
    }

    try!(override_db.remove(path, &cfg.temp_cfg, notify_handler));
    info!("override toolchain for '{}' removed", path.display());
    Ok(())
}

fn doc(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let doc_url = if m.is_present("book") {
        "book/index.html"
    } else if m.is_present("std") {
        "std/index.html"
    } else {
        "index.html"
    };

    Ok(try!(cfg.open_docs_for_dir(&try!(utils::current_dir()), doc_url)))
}

fn self_uninstall(m: &ArgMatches) -> Result<()> {
    let no_prompt = m.is_present("no-prompt");

    self_update::uninstall(no_prompt)
}

fn set_telemetry(cfg: &Cfg, t: TelemetryMode) -> Result<()> {
    match t {
        TelemetryMode::On => Ok(try!(cfg.set_telemetry(true))),
        TelemetryMode::Off => Ok(try!(cfg.set_telemetry(false))),
    }
}

fn analyze_telemetry(cfg: &Cfg) -> Result<()> {
    let analysis = try!(cfg.analyze_telemetry());
    common::show_telemetry(analysis)
}
<commit_msg>Fixes panic on bare
ustup telemetry command<commit_after>use clap::{App, Arg, AppSettings, SubCommand, ArgMatches};
use common;
use rustup::{Cfg, Toolchain, command};
use rustup::telemetry::TelemetryMode;
use errors::*;
use rustup_dist::manifest::Component;
use rustup_dist::dist::TargetTriple;
use rustup_utils::utils;
use self_update;
use std::path::Path;

pub fn main() -> Result<()> {
    try!(::self_update::cleanup_self_updater());

    let ref matches = cli().get_matches();
    let verbose = matches.is_present("verbose");
    let ref cfg = try!(common::set_globals(verbose));

    if try!(maybe_upgrade_data(cfg, matches)) {
        return Ok(())
    }

    try!(cfg.check_metadata_version());

    match matches.subcommand() {
        ("default", Some(m)) => try!(default_(cfg, m)),
        ("update", Some(m)) => try!(update(cfg, m)),
        ("run", Some(m)) => try!(run(cfg, m)),
        ("which", Some(m)) => try!(which(cfg, m)),
        ("show", Some(_)) => try!(show(cfg)),
        ("target", Some(c)) => {
            match c.subcommand() {
                ("list", Some(m)) => try!(target_list(cfg, m)),
                ("add", Some(m)) => try!(target_add(cfg, m)),
                ("remove", Some(m)) => try!(target_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("toolchain", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_toolchains(cfg)),
                ("link", Some(m)) => try!(toolchain_link(cfg, m)),
                ("remove", Some(m)) => try!(toolchain_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("override", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_overrides(cfg)),
                ("add", Some(m)) => try!(override_add(cfg, m)),
                ("remove", Some(_)) => try!(override_remove(cfg)),
                (_ ,_) => unreachable!(),
            }
        }
        ("doc", Some(m)) => try!(doc(cfg, m)),
        ("self", Some(c)) => {
            match c.subcommand() {
                ("update", Some(_)) => try!(self_update::update()),
                ("uninstall", Some(m)) => try!(self_uninstall(m)),
                (_ ,_) => unreachable!(),
            }
        }
        ("telemetry", Some(c)) => {
            match c.subcommand() {
                ("enable", Some(_)) => try!(set_telemetry(&cfg, TelemetryMode::On)),
                ("disable", Some(_)) => try!(set_telemetry(&cfg, TelemetryMode::Off)),
                ("analyze", Some(_)) => try!(analyze_telemetry(&cfg)),
                (_, _) => unreachable!(),
            }
        }
        (_, _) => unreachable!(),
    }

    Ok(())
}

pub fn cli() -> App<'static, 'static> {
    App::new("rustup")
        .version(common::version())
        .about("The Rust toolchain installer")
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::DeriveDisplayOrder)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("verbose")
            .help("Enable verbose output")
            .short("v")
            .long("verbose"))
        .subcommand(SubCommand::with_name("default")
            .about("Set the default toolchain")
            .arg(Arg::with_name("toolchain")
                .required(true)))
        .subcommand(SubCommand::with_name("update")
            .about("Update all toolchains, install or update a given toolchain")
            .arg(Arg::with_name("toolchain")
                .required(false))
            .arg(Arg::with_name("no-self-update")
                .help("Don't perform self update when running the `rustup` command")
                .long("no-self-update")
                .takes_value(false)
                .hidden(true)))
        .subcommand(SubCommand::with_name("run")
            .about("Run a command with an environment configured for a given toolchain")
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("toolchain")
                .required(true))
            .arg(Arg::with_name("command")
                .required(true).multiple(true)))
        .subcommand(SubCommand::with_name("which")
            .about("Display which binary will be run for a given command")
            .arg(Arg::with_name("command")
                .required(true)))
        .subcommand(SubCommand::with_name("show")
            .about("Show the active toolchain"))
        .subcommand(SubCommand::with_name("target")
            .about("Modify a toolchain's supported targets")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed and available targets")
                .arg(Arg::with_name("toolchain")
                    .long("toolchain")
                    .takes_value(true)))
            .subcommand(SubCommand::with_name("add")
                .about("Add a target to a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true))
                .arg(Arg::with_name("toolchain")
                    .long("toolchain")
                    .takes_value(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove a target  from a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true))
                .arg(Arg::with_name("toolchain")
                    .long("toolchain")
                    .takes_value(true))))
        .subcommand(SubCommand::with_name("toolchain")
            .about("Modify or query the installed toolchains")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed toolchains"))
            .subcommand(SubCommand::with_name("link")
                .about("Create a custom toolchain by symlinking to a directory")
                .arg(Arg::with_name("toolchain")
                    .required(true))
                .arg(Arg::with_name("path")
                    .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Uninstall a toolchain")
                .arg(Arg::with_name("toolchain")
                     .required(true))))
        .subcommand(SubCommand::with_name("override")
            .about("Modify directory toolchain overrides")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List directory toolchain overrides"))
            .subcommand(SubCommand::with_name("add")
                .about("Set the override toolchain for a directory")
                .arg(Arg::with_name("toolchain")
                     .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove the override toolchain for a directory")))
        .subcommand(SubCommand::with_name("self")
            .about("Modify the rustup installation")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("update")
                .about("Download and install updates to rustup"))
            .subcommand(SubCommand::with_name("uninstall")
                .about("Uninstall rustup.")
                .arg(Arg::with_name("no-prompt")
                     .short("y")))
            .subcommand(SubCommand::with_name("upgrade-data")
                .about("Upgrade the internal data format.")))
        .subcommand(SubCommand::with_name("telemetry")
            .about("rustup telemetry commands")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("enable")
                            .about("Enable rustup telemetry"))
            .subcommand(SubCommand::with_name("disable")
                            .about("Disable rustup telemetry"))
            .subcommand(SubCommand::with_name("analyze")
                            .about("Analyze stored telemetry")))
}

fn maybe_upgrade_data(cfg: &Cfg, m: &ArgMatches) -> Result<bool> {
    match m.subcommand() {
        ("self", Some(c)) => {
            match c.subcommand() {
                ("upgrade-data", Some(_)) => {
                    try!(cfg.upgrade_data());
                    Ok(true)
                }
                _ => Ok(false),
            }
        }
        _ => Ok(false)
    }
}

fn default_(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(ErrorKind::ToolchainNotInstalled(toolchain.name().to_string()).into());
    } else {
        None
    };

    try!(toolchain.make_default());

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn update(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    if let Some(name) = m.value_of("toolchain") {
        let toolchain = try!(cfg.get_toolchain(name, false));

        let status = if !toolchain.is_custom() {
            Some(try!(toolchain.install_from_dist()))
        } else if !toolchain.exists() {
            return Err(ErrorKind::ToolchainNotInstalled(toolchain.name().to_string()).into());
        } else {
            None
        };

        if let Some(status) = status {
            println!("");
            try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
        }
    } else {
        try!(common::update_all_channels(cfg, !m.is_present("no-self-update")));
    }

    Ok(())
}

fn run(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let args = m.values_of("command").unwrap();
    let args: Vec<_> = args.collect();
    let cmd = try!(cfg.create_command_for_toolchain(toolchain, args[0]));

    Ok(try!(command::run_command_for_dir(cmd, &args, &cfg)))
}

fn which(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let binary = m.value_of("command").expect("");

    let binary_path = try!(cfg.which_binary(&try!(utils::current_dir()), binary))
                          .expect("binary not found");

    try!(utils::assert_is_file(&binary_path));

    println!("{}", binary_path.display());

    Ok(())
}

fn show(cfg: &Cfg) -> Result<()> {
    let ref cwd = try!(utils::current_dir());
    let override_ = try!(cfg.find_override(cwd));
    if let Some((toolchain, reason)) = override_ {
        println!("{} ({})", toolchain.name(), reason);
        return Ok(());
    }

    let toolchain = try!(cfg.find_default());
    if let Some(toolchain) = toolchain {
        println!("{} (default toolchain)", toolchain.name());
        return Ok(());
    }

    println!("no active toolchain");

    Ok(())
}

fn target_list(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = try!(explicit_or_dir_toolchain(cfg, m));

    common::list_targets(&toolchain)
}

fn target_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = try!(explicit_or_dir_toolchain(cfg, m));
    let target = m.value_of("target").expect("");
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: TargetTriple::from_str(target),
    };

    Ok(try!(toolchain.add_component(new_component)))
}

fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = try!(explicit_or_dir_toolchain(cfg, m));
    let target = m.value_of("target").expect("");
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: TargetTriple::from_str(target),
    };

    Ok(try!(toolchain.remove_component(new_component)))
}

fn explicit_or_dir_toolchain<'a>(cfg: &'a Cfg, m: &ArgMatches) -> Result<Toolchain<'a>> {
    let toolchain = m.value_of("toolchain");
    if let Some(toolchain) = toolchain {
        let toolchain = try!(cfg.get_toolchain(toolchain, false));
        return Ok(toolchain);
    }

    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));

    Ok(toolchain)
}

fn toolchain_link(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref path = m.value_of("path").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, true));

    Ok(try!(toolchain.install_from_dir(Path::new(path), true)))
}

fn toolchain_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    Ok(try!(toolchain.remove()))
}

fn override_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(ErrorKind::ToolchainNotInstalled(toolchain.name().to_string()).into());
    } else {
        None
    };

    try!(toolchain.make_override(&try!(utils::current_dir())));

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn override_remove(cfg: &Cfg) -> Result<()> {
    let ref path = try!(utils::current_dir());

    let ref override_db = cfg.override_db;
    let notify_handler = cfg.notify_handler.as_ref();

    if try!(override_db.find(path, notify_handler)).is_none() {
        info!("no override toolchain for '{}'", path.display());
        return Ok(());
    }

    try!(override_db.remove(path, &cfg.temp_cfg, notify_handler));
    info!("override toolchain for '{}' removed", path.display());
    Ok(())
}

fn doc(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let doc_url = if m.is_present("book") {
        "book/index.html"
    } else if m.is_present("std") {
        "std/index.html"
    } else {
        "index.html"
    };

    Ok(try!(cfg.open_docs_for_dir(&try!(utils::current_dir()), doc_url)))
}

fn self_uninstall(m: &ArgMatches) -> Result<()> {
    let no_prompt = m.is_present("no-prompt");

    self_update::uninstall(no_prompt)
}

fn set_telemetry(cfg: &Cfg, t: TelemetryMode) -> Result<()> {
    match t {
        TelemetryMode::On => Ok(try!(cfg.set_telemetry(true))),
        TelemetryMode::Off => Ok(try!(cfg.set_telemetry(false))),
    }
}

fn analyze_telemetry(cfg: &Cfg) -> Result<()> {
    let analysis = try!(cfg.analyze_telemetry());
    common::show_telemetry(analysis)
}
<|endoftext|>


<commit_before>#![crate_name = "prob0096"]
#![crate_type = "rlib"]

use std::{char, fmt, iter};
use std::io::{BufferedReader, File};

pub static EXPECTED_ANSWER: &'static str = "24702";

static BOARD_WIDTH: uint = 9;
static BOARD_HEIGHT: uint = 9;
static GROUP_WIDTH: uint = 3;
static GROUP_HEIGHT: uint = 3;
static MAX_NUMBER: uint = 9;
type BITS = u16;
static MASK_ALL: BITS = 0x1ff;

struct SuDoku {
    name: String,
    map: [[BITS, .. BOARD_WIDTH], .. BOARD_HEIGHT]
}

// #7622 (rust): #[deriving(Eq, Eq, Clone)] cannnot be used
impl Eq for SuDoku {}

impl PartialEq for SuDoku {
    #[inline]
    fn eq(&self, other: &SuDoku) -> bool {
        self.name == other.name && range(0, BOARD_HEIGHT).all(|y| self.map[y] == other.map[y])
    }
}

impl fmt::Show for SuDoku {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "{}", self.name));

        for row in self.map.iter() {
            for cell in row.iter() {
                if cell.count_ones() == 1 {
                    try!(write!(f, "_"));
                } else {
                    try!(write!(f, "{}", 1u << (cell.trailing_zeros() as uint)));
                }
            }
            try!(writeln!(f, ""));
        }

        Ok(())
    }
}

impl Clone for SuDoku {
    #[inline]
    fn clone(&self) -> SuDoku {
        SuDoku { name: self.name.clone(), map: self.map }
    }
}

impl SuDoku {
    #[inline]
    fn get_num(&self, x: uint, y: uint) -> BITS {
        match self.map[y][x].count_ones() {
            0 => -1,
            1 => self.map[y][x].trailing_zeros() + 1,
            _ => 0
        }
    }
}

fn read_sudoku<T: Reader>(r: &mut BufferedReader<T>) -> Option<SuDoku> {
    r.read_line().ok()
        .and_then(|name| {
            let mut sudoku = SuDoku {
                name: name,
                map: [[MASK_ALL, .. BOARD_WIDTH], .. BOARD_HEIGHT]
            };
            for y in range(0, BOARD_HEIGHT) {
                match r.read_line().ok() {
                    None => return None,
                    Some(line) => {
                        for x in range(0, BOARD_WIDTH) {
                            let n = char::to_digit(line.as_slice().char_at(x), 10).unwrap();
                            if n != 0 { sudoku.map[y][x] = 1 << (n - 1); }
                        }
                    }
                }
            }
            Some(sudoku)
        })
}

fn solve_sudoku(mut puzzle: SuDoku) -> Vec<SuDoku> {
    let group_it = range(0, GROUP_WIDTH * GROUP_HEIGHT)
        .map(|i| (i % GROUP_WIDTH, i / GROUP_WIDTH))
        .collect::<Vec<(uint, uint)>>();

    loop {
        let bkup = puzzle.clone();

        for y in range(0, BOARD_HEIGHT) {
            for x in range(0, BOARD_WIDTH) {
                if puzzle.map[y][x].count_ones() != 1 { continue }

                let (x0, y0) = (x / GROUP_WIDTH * GROUP_WIDTH,
                                y / GROUP_HEIGHT * GROUP_HEIGHT);
                let row = range(0, BOARD_WIDTH).map(|x| (x, y));
                let col = range(0, BOARD_HEIGHT).map(|y| (x, y));
                let grp = group_it.iter().map(|&(dx, dy)| (x0 + dx, y0 + dy));

                let mut it = row.chain(col).chain(grp)
                    .filter(|&pos: &(uint, uint)| pos != (x, y));
                let mask = !puzzle.map[y][x] & MASK_ALL;
                for (x, y) in it { puzzle.map[y][x] &= mask; }
            }
        }

        for n in range(0, MAX_NUMBER) {
            let bit = 1 << n;

            for y in range(0, BOARD_HEIGHT) {
                let next = {
                    let mut it = range(0, BOARD_WIDTH)
                        .filter(|&x| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_none() || it.next().is_some() { continue }
                    next
                };
                puzzle.map[y][next.unwrap()] = bit;
            }

            for x in range(0, BOARD_WIDTH) {
                let next = {
                    let mut it = range(0, BOARD_HEIGHT)
                        .filter(|&y| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_none() || it.next().is_some() { continue }
                    next
                };
                puzzle.map[next.unwrap()][x] = bit;
            }

            for y0 in iter::range_step(0, BOARD_HEIGHT, GROUP_WIDTH) {
                for x0 in iter::range_step(0, BOARD_WIDTH, GROUP_HEIGHT) {
                    let next = {
                        let mut it = group_it
                            .iter()
                            .map(|&(dx, dy)| (x0 + dx, y0 + dy))
                            .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                        let next = it.next();
                        if next.is_none() || it.next().is_some() { continue }
                        next
                    };
                    let (x, y) = next.unwrap();
                    puzzle.map[y][x] = bit;
                }
            }
        }

        if puzzle == bkup { break }
    }

    let it = range(0, BOARD_HEIGHT * BOARD_WIDTH)
        .map(|i| (i % BOARD_WIDTH, i / BOARD_WIDTH))
        .map(|(x, y)| (x, y, puzzle.map[y][x].count_ones()))
        .collect::<Vec<(uint, uint, u16)>>();

    if it.iter().any(|&(_x, _y, cnt)| cnt == 0) { return vec![]; }
    if it.iter().all(|&(_x, _y, cnt)| cnt == 1) { return vec![puzzle]; }

    let (x, y, _cnt) = *it.iter()
        .filter(|& &(_x, _y, cnt)| cnt > 1)
        .min_by(|& &(_x, _y, cnt)| cnt)
        .unwrap();

    let mut answers = Vec::new();
    for n in range(0, MAX_NUMBER) {
        let bit = 1 << n;
        if puzzle.map[y][x] & bit == 0 { continue }

        let mut p2 = puzzle.clone();
        p2.map[y][x] = bit;
        answers.push_all(solve_sudoku(p2).as_slice());
    }

    answers.move_iter().collect()
}

pub fn solve() -> String {
    let mut br = BufferedReader::new(
        File::open(&Path::new("files/p096_sudoku.txt")).ok().expect("file not found."));

    let mut puzzles = Vec::new();
    loop {
        match read_sudoku(&mut br) {
            Some(sudoku) => puzzles.push(sudoku),
            None => break
        }
    }
    let mut answers = puzzles
        .move_iter()
        .map(solve_sudoku)
        .map(|mut ans| { assert_eq!(ans.len(), 1); ans.remove(0).unwrap() });
    let mut sum = 0;
    for ans in answers {
        sum += 100 * ans.get_num(0, 0) + 10 * ans.get_num(1, 0) + ans.get_num(2, 0);
    }
    sum.to_string()
}
<commit_msg>fix for compile<commit_after>#![crate_name = "prob0096"]
#![crate_type = "rlib"]

use std::{char, fmt, iter};
use std::io::{BufferedReader, File};

pub static EXPECTED_ANSWER: &'static str = "24702";

static BOARD_WIDTH: uint = 9;
static BOARD_HEIGHT: uint = 9;
static GROUP_WIDTH: uint = 3;
static GROUP_HEIGHT: uint = 3;
static MAX_NUMBER: uint = 9;
type BITS = u16;
static MASK_ALL: BITS = 0x1ff;

struct SuDoku {
    name: String,
    map: [[BITS, .. BOARD_WIDTH], .. BOARD_HEIGHT]
}

// #7622 (rust): #[deriving(Eq, Eq, Clone)] cannnot be used
impl Eq for SuDoku {}

impl PartialEq for SuDoku {
    #[inline]
    fn eq(&self, other: &SuDoku) -> bool {
        self.name == other.name && range(0, BOARD_HEIGHT).all(|y| self.map[y] == other.map[y])
    }
}

impl fmt::Show for SuDoku {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "{}", self.name));

        for row in self.map.iter() {
            for cell in row.iter() {
                if cell.count_ones() == 1 {
                    try!(write!(f, "_"));
                } else {
                    try!(write!(f, "{}", 1u << cell.trailing_zeros()));
                }
            }
            try!(writeln!(f, ""));
        }

        Ok(())
    }
}

impl Clone for SuDoku {
    #[inline]
    fn clone(&self) -> SuDoku {
        SuDoku { name: self.name.clone(), map: self.map }
    }
}

impl SuDoku {
    #[inline]
    fn get_num(&self, x: uint, y: uint) -> BITS {
        match self.map[y][x].count_ones() {
            0 => -1,
            1 => (self.map[y][x].trailing_zeros() + 1) as BITS,
            _ => 0
        }
    }
}

fn read_sudoku<T: Reader>(r: &mut BufferedReader<T>) -> Option<SuDoku> {
    r.read_line().ok()
        .and_then(|name| {
            let mut sudoku = SuDoku {
                name: name,
                map: [[MASK_ALL, .. BOARD_WIDTH], .. BOARD_HEIGHT]
            };
            for y in range(0, BOARD_HEIGHT) {
                match r.read_line().ok() {
                    None => return None,
                    Some(line) => {
                        for x in range(0, BOARD_WIDTH) {
                            let n = char::to_digit(line.as_slice().char_at(x), 10).unwrap();
                            if n != 0 { sudoku.map[y][x] = 1 << (n - 1); }
                        }
                    }
                }
            }
            Some(sudoku)
        })
}

fn solve_sudoku(mut puzzle: SuDoku) -> Vec<SuDoku> {
    let group_it = range(0, GROUP_WIDTH * GROUP_HEIGHT)
        .map(|i| (i % GROUP_WIDTH, i / GROUP_WIDTH))
        .collect::<Vec<(uint, uint)>>();

    loop {
        let bkup = puzzle.clone();

        for y in range(0, BOARD_HEIGHT) {
            for x in range(0, BOARD_WIDTH) {
                if puzzle.map[y][x].count_ones() != 1 { continue }

                let (x0, y0) = (x / GROUP_WIDTH * GROUP_WIDTH,
                                y / GROUP_HEIGHT * GROUP_HEIGHT);
                let row = range(0, BOARD_WIDTH).map(|x| (x, y));
                let col = range(0, BOARD_HEIGHT).map(|y| (x, y));
                let grp = group_it.iter().map(|&(dx, dy)| (x0 + dx, y0 + dy));

                let mut it = row.chain(col).chain(grp)
                    .filter(|&pos: &(uint, uint)| pos != (x, y));
                let mask = !puzzle.map[y][x] & MASK_ALL;
                for (x, y) in it { puzzle.map[y][x] &= mask; }
            }
        }

        for n in range(0, MAX_NUMBER) {
            let bit = 1 << n;

            for y in range(0, BOARD_HEIGHT) {
                let next = {
                    let mut it = range(0, BOARD_WIDTH)
                        .filter(|&x| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_none() || it.next().is_some() { continue }
                    next
                };
                puzzle.map[y][next.unwrap()] = bit;
            }

            for x in range(0, BOARD_WIDTH) {
                let next = {
                    let mut it = range(0, BOARD_HEIGHT)
                        .filter(|&y| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_none() || it.next().is_some() { continue }
                    next
                };
                puzzle.map[next.unwrap()][x] = bit;
            }

            for y0 in iter::range_step(0, BOARD_HEIGHT, GROUP_WIDTH) {
                for x0 in iter::range_step(0, BOARD_WIDTH, GROUP_HEIGHT) {
                    let next = {
                        let mut it = group_it
                            .iter()
                            .map(|&(dx, dy)| (x0 + dx, y0 + dy))
                            .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                        let next = it.next();
                        if next.is_none() || it.next().is_some() { continue }
                        next
                    };
                    let (x, y) = next.unwrap();
                    puzzle.map[y][x] = bit;
                }
            }
        }

        if puzzle == bkup { break }
    }

    let it = range(0, BOARD_HEIGHT * BOARD_WIDTH)
        .map(|i| (i % BOARD_WIDTH, i / BOARD_WIDTH))
        .map(|(x, y)| (x, y, puzzle.map[y][x].count_ones() as BITS))
        .collect::<Vec<(uint, uint, BITS)>>();

    if it.iter().any(|&(_x, _y, cnt)| cnt == 0) { return vec![]; }
    if it.iter().all(|&(_x, _y, cnt)| cnt == 1) { return vec![puzzle]; }

    let (x, y, _cnt) = *it.iter()
        .filter(|& &(_x, _y, cnt)| cnt > 1)
        .min_by(|& &(_x, _y, cnt)| cnt)
        .unwrap();

    let mut answers = Vec::new();
    for n in range(0, MAX_NUMBER) {
        let bit = 1 << n;
        if puzzle.map[y][x] & bit == 0 { continue }

        let mut p2 = puzzle.clone();
        p2.map[y][x] = bit;
        answers.push_all(solve_sudoku(p2).as_slice());
    }

    answers.move_iter().collect()
}

pub fn solve() -> String {
    let mut br = BufferedReader::new(
        File::open(&Path::new("files/p096_sudoku.txt")).ok().expect("file not found."));

    let mut puzzles = Vec::new();
    loop {
        match read_sudoku(&mut br) {
            Some(sudoku) => puzzles.push(sudoku),
            None => break
        }
    }
    let mut answers = puzzles
        .move_iter()
        .map(solve_sudoku)
        .map(|mut ans| { assert_eq!(ans.len(), 1); ans.remove(0).unwrap() });
    let mut sum = 0;
    for ans in answers {
        sum += 100 * ans.get_num(0, 0) + 10 * ans.get_num(1, 0) + ans.get_num(2, 0);
    }
    sum.to_string()
}
<|endoftext|>