<commit_before>use ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods};
use ir::context::BindgenContext;
use ir::derive::CanTriviallyDeriveDebug;
use ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName};
use ir::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, TypeKind};
use quote;

pub fn gen_debug_impl(
    ctx: &BindgenContext,
    fields: &[Field],
    item: &Item,
    kind: CompKind,
) -> quote::Tokens {
    let struct_name = item.canonical_name(ctx);
    let mut format_string = format!("{} {{{{ ", struct_name);
    let mut tokens = vec![];

    if item.is_opaque(ctx, &()) {
        format_string.push_str("opaque");
    } else {
        match kind {
            CompKind::Union => {
                format_string.push_str("union");
            }
            CompKind::Struct => {
                let processed_fields = fields.iter().filter_map(|f| match f {
                    &Field::DataMember(ref fd) => fd.impl_debug(ctx, ()),
                    &Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
                });

                for (i, (fstring, toks)) in processed_fields.enumerate() {
                    if i > 0 {
                        format_string.push_str(", ");
                    }
                    tokens.extend(toks);
                    format_string.push_str(&fstring);
                }
            }
        }
    }

    format_string.push_str(" }}");
    tokens.insert(0, quote! { #format_string });

    let prefix = ctx.trait_prefix();

    quote! {
        fn fmt(&self, f: &mut ::#prefix::fmt::Formatter) -> ::#prefix ::fmt::Result {
            write!(f, #( #tokens ),*)
        }
    }
}

/// A trait for the things which we can codegen tokens that contribute towards a
/// generated `impl Debug`.
pub trait ImplDebug<'a> {
    /// Any extra parameter required by this a particular `ImplDebug` implementation.
    type Extra;

    /// Generate a format string snippet to be included in the larger `impl Debug`
    /// format string, and the code to get the format string's interpolation values.
    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        extra: Self::Extra,
    ) -> Option<(String, Vec<quote::Tokens>)>;
}

impl<'a> ImplDebug<'a> for FieldData {
    type Extra = ();

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        _: Self::Extra,
    ) -> Option<(String, Vec<quote::Tokens>)> {
        if let Some(name) = self.name() {
            ctx.resolve_item(self.ty()).impl_debug(ctx, name)
        } else {
            None
        }
    }
}

impl<'a> ImplDebug<'a> for BitfieldUnit {
    type Extra = ();

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        _: Self::Extra,
    ) -> Option<(String, Vec<quote::Tokens>)> {
        let mut format_string = String::new();
        let mut tokens = vec![];
        for (i, bitfield) in self.bitfields().iter().enumerate() {
            if i > 0 {
                format_string.push_str(", ");
            }

            if let Some(bitfield_name) = bitfield.name() {
                format_string.push_str(&format!("{} : {{:?}}", bitfield_name));
                let getter_name = bitfield.getter_name();
                let name_ident = ctx.rust_ident_raw(getter_name);
                tokens.push(quote! {
                    self.#name_ident ()
                });
            }
        }

        Some((format_string, tokens))
    }
}

impl<'a> ImplDebug<'a> for Item {
    type Extra = &'a str;

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        name: &str,
    ) -> Option<(String, Vec<quote::Tokens>)> {
        let name_ident = ctx.rust_ident(name);

        // We don't know if blacklisted items `impl Debug` or not, so we can't
        // add them to the format string we're building up.
        if !ctx.whitelisted_items().contains(&self.id()) {
            return None;
        }

        let ty = match self.as_type() {
            Some(ty) => ty,
            None => {
                return None;
            }
        };

        fn debug_print(
            name: &str,
            name_ident: quote::Tokens,
        ) -> Option<(String, Vec<quote::Tokens>)> {
            Some((
                format!("{}: {{:?}}", name),
                vec![quote! {
                    self.#name_ident
                }],
            ))
        }

        match *ty.kind() {
            // Handle the simple cases.
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::BlockPointer |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::Comp(..) |
            TypeKind::ObjCSel => debug_print(name, quote! { #name_ident }),

            TypeKind::TemplateInstantiation(ref inst) => {
                if inst.is_opaque(ctx, self) {
                    Some((format!("{}: opaque", name), vec![]))
                } else {
                    debug_print(name, quote! { #name_ident })
                }
            }

            // The generic is not required to implement Debug, so we can not debug print that type
            TypeKind::TypeParam => {
                Some((format!("{}: Non-debuggable generic", name), vec![]))
            }

            TypeKind::Array(_, len) => {
                // Generics are not required to implement Debug
                if self.has_type_param_in_array(ctx) {
                    Some(
                        (format!("{}: Array with length {}", name, len), vec![]),
                    )
                } else if len < RUST_DERIVE_IN_ARRAY_LIMIT {
                    // The simple case
                    debug_print(name, quote! { #name_ident })
                } else {
                    // Let's implement our own print function
                    Some((
                        format!("{}: [{{}}]", name),
                        vec![quote! {
                            self.#name_ident
                                .iter()
                                .enumerate()
                                .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
                                .collect::<String>()
                        }],
                    ))
                }
            }
            TypeKind::Vector(_, len) => {
                let self_ids = 0..len;
                Some((
                    format!("{}({{}})", name),
                    vec![quote! {
                        #(format!("{:?}", self.#self_ids)),*
                    }]
                ))
            }

            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) => {
                // We follow the aliases
                ctx.resolve_item(t).impl_debug(ctx, name)
            }

            TypeKind::Pointer(inner) => {
                let inner_type = ctx.resolve_type(inner).canonical_type(ctx);
                match *inner_type.kind() {
                    TypeKind::Function(ref sig)
                        if !sig.can_trivially_derive_debug() => {
                            Some((format!("{}: FunctionPointer", name), vec![]))
                    }
                    _ => debug_print(name, quote! { #name_ident }),
                }
            }

            TypeKind::Opaque => None,
        }
    }
}
<commit_msg>Debug implementation: Don't use format! or String when core is enabled<commit_after>use ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods};
use ir::context::BindgenContext;
use ir::derive::CanTriviallyDeriveDebug;
use ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName};
use ir::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, TypeKind};
use quote;

pub fn gen_debug_impl(
    ctx: &BindgenContext,
    fields: &[Field],
    item: &Item,
    kind: CompKind,
) -> quote::Tokens {
    let struct_name = item.canonical_name(ctx);
    let mut format_string = format!("{} {{{{ ", struct_name);
    let mut tokens = vec![];

    if item.is_opaque(ctx, &()) {
        format_string.push_str("opaque");
    } else {
        match kind {
            CompKind::Union => {
                format_string.push_str("union");
            }
            CompKind::Struct => {
                let processed_fields = fields.iter().filter_map(|f| match f {
                    &Field::DataMember(ref fd) => fd.impl_debug(ctx, ()),
                    &Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
                });

                for (i, (fstring, toks)) in processed_fields.enumerate() {
                    if i > 0 {
                        format_string.push_str(", ");
                    }
                    tokens.extend(toks);
                    format_string.push_str(&fstring);
                }
            }
        }
    }

    format_string.push_str(" }}");
    tokens.insert(0, quote! { #format_string });

    let prefix = ctx.trait_prefix();

    quote! {
        fn fmt(&self, f: &mut ::#prefix::fmt::Formatter) -> ::#prefix ::fmt::Result {
            write!(f, #( #tokens ),*)
        }
    }
}

/// A trait for the things which we can codegen tokens that contribute towards a
/// generated `impl Debug`.
pub trait ImplDebug<'a> {
    /// Any extra parameter required by this a particular `ImplDebug` implementation.
    type Extra;

    /// Generate a format string snippet to be included in the larger `impl Debug`
    /// format string, and the code to get the format string's interpolation values.
    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        extra: Self::Extra,
    ) -> Option<(String, Vec<quote::Tokens>)>;
}

impl<'a> ImplDebug<'a> for FieldData {
    type Extra = ();

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        _: Self::Extra,
    ) -> Option<(String, Vec<quote::Tokens>)> {
        if let Some(name) = self.name() {
            ctx.resolve_item(self.ty()).impl_debug(ctx, name)
        } else {
            None
        }
    }
}

impl<'a> ImplDebug<'a> for BitfieldUnit {
    type Extra = ();

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        _: Self::Extra,
    ) -> Option<(String, Vec<quote::Tokens>)> {
        let mut format_string = String::new();
        let mut tokens = vec![];
        for (i, bitfield) in self.bitfields().iter().enumerate() {
            if i > 0 {
                format_string.push_str(", ");
            }

            if let Some(bitfield_name) = bitfield.name() {
                format_string.push_str(&format!("{} : {{:?}}", bitfield_name));
                let getter_name = bitfield.getter_name();
                let name_ident = ctx.rust_ident_raw(getter_name);
                tokens.push(quote! {
                    self.#name_ident ()
                });
            }
        }

        Some((format_string, tokens))
    }
}

impl<'a> ImplDebug<'a> for Item {
    type Extra = &'a str;

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        name: &str,
    ) -> Option<(String, Vec<quote::Tokens>)> {
        let name_ident = ctx.rust_ident(name);

        // We don't know if blacklisted items `impl Debug` or not, so we can't
        // add them to the format string we're building up.
        if !ctx.whitelisted_items().contains(&self.id()) {
            return None;
        }

        let ty = match self.as_type() {
            Some(ty) => ty,
            None => {
                return None;
            }
        };

        fn debug_print(
            name: &str,
            name_ident: quote::Tokens,
        ) -> Option<(String, Vec<quote::Tokens>)> {
            Some((
                format!("{}: {{:?}}", name),
                vec![quote! {
                    self.#name_ident
                }],
            ))
        }

        match *ty.kind() {
            // Handle the simple cases.
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::BlockPointer |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::Comp(..) |
            TypeKind::ObjCSel => debug_print(name, quote! { #name_ident }),

            TypeKind::TemplateInstantiation(ref inst) => {
                if inst.is_opaque(ctx, self) {
                    Some((format!("{}: opaque", name), vec![]))
                } else {
                    debug_print(name, quote! { #name_ident })
                }
            }

            // The generic is not required to implement Debug, so we can not debug print that type
            TypeKind::TypeParam => {
                Some((format!("{}: Non-debuggable generic", name), vec![]))
            }

            TypeKind::Array(_, len) => {
                // Generics are not required to implement Debug
                if self.has_type_param_in_array(ctx) {
                    Some(
                        (format!("{}: Array with length {}", name, len), vec![]),
                    )
                } else if len < RUST_DERIVE_IN_ARRAY_LIMIT {
                    // The simple case
                    debug_print(name, quote! { #name_ident })
                } else {
                    if ctx.options().use_core {
                        // There is no String in core; reducing field visibility to avoid breaking
                        // no_std setups.
                        Some((
                            format!("{}: [...]", name), vec![]
                        ))
                    } else {
                        // Let's implement our own print function
                        Some((
                            format!("{}: [{{}}]", name),
                            vec![quote! {
                                self.#name_ident
                                    .iter()
                                    .enumerate()
                                    .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
                                    .collect::<String>()
                            }],
                        ))
                    }
                }
            }
            TypeKind::Vector(_, len) => {
                if ctx.options().use_core {
                    // There is no format! in core; reducing field visibility to avoid breaking
                    // no_std setups.
                    Some((
                        format!("{}(...)", name), vec![]
                    ))
                } else {
                    let self_ids = 0..len;
                    Some((
                        format!("{}({{}})", name),
                        vec![quote! {
                            #(format!("{:?}", self.#self_ids)),*
                        }]
                    ))
                }
            }

            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) => {
                // We follow the aliases
                ctx.resolve_item(t).impl_debug(ctx, name)
            }

            TypeKind::Pointer(inner) => {
                let inner_type = ctx.resolve_type(inner).canonical_type(ctx);
                match *inner_type.kind() {
                    TypeKind::Function(ref sig)
                        if !sig.can_trivially_derive_debug() => {
                            Some((format!("{}: FunctionPointer", name), vec![]))
                    }
                    _ => debug_print(name, quote! { #name_ident }),
                }
            }

            TypeKind::Opaque => None,
        }
    }
}
<|endoftext|>


<commit_before>//! Crate documentation builder
//!
//! This module is extremely similar to cargo install operation, except it's building
//! documentation of a crate and not installing anything.

use std::path::{Path, PathBuf};
use std::env;

use cargo::core::{SourceId, Dependency, Registry, Source, Package, Workspace};
use cargo::util::{CargoResult, Config, human, Filesystem};
use cargo::sources::SourceConfigMap;
use cargo::ops;

/// Builds documentation of a crate and version.
///
/// Crate will be built into current working directory/crate-version.
///
/// It will build latest version, if no version is given.
// idea is to make cargo to download
// and build a crate and its documentation
// instead of doing it manually like in the previous version of cratesfyi
pub fn build_doc(name: &str, vers: Option<&str>, target: Option<&str>) -> CargoResult<Package> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    // update crates.io-index registry
    try!(source.update());

    let dep = try!(Dependency::parse(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    let current_dir = try!(env::current_dir());
    let target_dir = PathBuf::from(current_dir)
        .join(format!("{}-{}", pkg.manifest().name(), pkg.manifest().version()));

    let opts = ops::CompileOptions {
        config: &config,
        jobs: None,
        target: target,
        features: &[],
        no_default_features: false,
        spec: &[],
        exec_engine: None,
        mode: ops::CompileMode::Doc { deps: false },
        release: false,
        filter: ops::CompileFilter::new(true, &[], &[], &[], &[]),
        target_rustc_args: None,
        target_rustdoc_args: None,
    };

    let ws = try!(Workspace::one(pkg, &config, Some(Filesystem::new(target_dir))));

    try!(ops::compile_ws(&ws, Some(source), &opts));

    Ok(try!(ws.current()).clone())
}

/// Downloads a crate and returns Cargo Package.
pub fn get_package(name: &str, vers: Option<&str>) -> CargoResult<Package> {
    debug!("Getting package with cargo");
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    let dep = try!(Dependency::parse(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    Ok(pkg)
}

/// Updates central crates-io.index repository
pub fn update_sources() -> CargoResult<()> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    source.update()
}

/// Gets source path of a downloaded package.
pub fn source_path(pkg: &Package) -> Option<&Path> {
    // parent of the manifest file is where source codes are stored
    pkg.manifest_path().parent()
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::*;

    #[test]
    #[ignore]
    fn test_build_doc() {
        // FIXME: Need to remove directory after we are finished
        let doc = build_doc("rand", None, None);
        assert!(doc.is_ok());

        let doc = build_doc("SOMECRATEWICHWILLBENVEREXISTS", None, None);
        assert!(doc.is_err());
    }

    #[test]
    #[ignore]
    fn test_get_package() {
        let pkg = get_package("rand", None);
        assert!(pkg.is_ok());

        let pkg = pkg.unwrap();

        let manifest = pkg.manifest();
        assert_eq!(manifest.name(), "rand");
    }

    #[test]
    #[ignore]
    fn test_source_path() {
        let pkg = get_package("rand", None).unwrap();
        let source_path = source_path(&pkg).unwrap();
        assert!(source_path.is_dir());

        let cargo_toml_path = Path::new(source_path).join("Cargo.toml");
        assert!(cargo_toml_path.exists());
        assert!(cargo_toml_path.is_file());

        let src_path = Path::new(source_path).join("src");
        assert!(src_path.exists());
        assert!(src_path.is_dir());
    }
}
<commit_msg>Remove test directory after test<commit_after>//! Crate documentation builder
//!
//! This module is extremely similar to cargo install operation, except it's building
//! documentation of a crate and not installing anything.

use std::path::{Path, PathBuf};
use std::env;

use cargo::core::{SourceId, Dependency, Registry, Source, Package, Workspace};
use cargo::util::{CargoResult, Config, human, Filesystem};
use cargo::sources::SourceConfigMap;
use cargo::ops;

/// Builds documentation of a crate and version.
///
/// Crate will be built into current working directory/crate-version.
///
/// It will build latest version, if no version is given.
// idea is to make cargo to download
// and build a crate and its documentation
// instead of doing it manually like in the previous version of cratesfyi
pub fn build_doc(name: &str, vers: Option<&str>, target: Option<&str>) -> CargoResult<Package> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    // update crates.io-index registry
    try!(source.update());

    let dep = try!(Dependency::parse(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    let current_dir = try!(env::current_dir());
    let target_dir = PathBuf::from(current_dir)
        .join(format!("{}-{}", pkg.manifest().name(), pkg.manifest().version()));

    let opts = ops::CompileOptions {
        config: &config,
        jobs: None,
        target: target,
        features: &[],
        no_default_features: false,
        spec: &[],
        exec_engine: None,
        mode: ops::CompileMode::Doc { deps: false },
        release: false,
        filter: ops::CompileFilter::new(true, &[], &[], &[], &[]),
        target_rustc_args: None,
        target_rustdoc_args: None,
    };

    let ws = try!(Workspace::one(pkg, &config, Some(Filesystem::new(target_dir))));

    try!(ops::compile_ws(&ws, Some(source), &opts));

    Ok(try!(ws.current()).clone())
}

/// Downloads a crate and returns Cargo Package.
pub fn get_package(name: &str, vers: Option<&str>) -> CargoResult<Package> {
    debug!("Getting package with cargo");
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    let dep = try!(Dependency::parse(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    Ok(pkg)
}

/// Updates central crates-io.index repository
pub fn update_sources() -> CargoResult<()> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    source.update()
}

/// Gets source path of a downloaded package.
pub fn source_path(pkg: &Package) -> Option<&Path> {
    // parent of the manifest file is where source codes are stored
    pkg.manifest_path().parent()
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use std::fs::remove_dir_all;
    use super::*;

    #[test]
    #[ignore]
    fn test_build_doc() {
        let doc = build_doc("rand", None, None);
        assert!(doc.is_ok());

        let doc = doc.unwrap();
        remove_dir_all(format!("{}-{}", doc.manifest().name(), doc.manifest().version())).unwrap();

        let doc = build_doc("SOMECRATEWICHWILLBENVEREXISTS", None, None);
        assert!(doc.is_err());
    }

    #[test]
    #[ignore]
    fn test_get_package() {
        let pkg = get_package("rand", None);
        assert!(pkg.is_ok());

        let pkg = pkg.unwrap();

        let manifest = pkg.manifest();
        assert_eq!(manifest.name(), "rand");
    }

    #[test]
    #[ignore]
    fn test_source_path() {
        let pkg = get_package("rand", None).unwrap();
        let source_path = source_path(&pkg).unwrap();
        assert!(source_path.is_dir());

        let cargo_toml_path = Path::new(source_path).join("Cargo.toml");
        assert!(cargo_toml_path.exists());
        assert!(cargo_toml_path.is_file());

        let src_path = Path::new(source_path).join("src");
        assert!(src_path.exists());
        assert!(src_path.is_dir());
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A task that takes a URL and streams back the binary data.

use file_loader;
use http_loader;
use data_loader;

use std::comm::{channel, Receiver, Sender};
use std::task;
use http::headers::content_type::MediaType;
use url::Url;

#[cfg(test)]
use std::from_str::FromStr;

pub enum ControlMsg {
    /// Request the data associated with a particular URL
    Load(Url, Sender<LoadResponse>),
    Exit
}

/// Metadata about a loaded resource, such as is obtained from HTTP headers.
pub struct Metadata {
    /// Final URL after redirects.
    pub final_url: Url,

    /// MIME type / subtype.
    pub content_type: Option<(~str, ~str)>,

    /// Character set.
    pub charset: Option<~str>,
}

impl Metadata {
    /// Metadata with defaults for everything optional.
    pub fn default(url: Url) -> Metadata {
        Metadata {
            final_url:    url,
            content_type: None,
            charset:      None,
        }
    }

    /// Extract the parts of a MediaType that we care about.
    pub fn set_content_type(&mut self, content_type: &Option<MediaType>) {
        match *content_type {
            None => (),
            Some(MediaType { type_:      ref type_,
                             subtype:    ref subtype,
                             parameters: ref parameters }) => {
                self.content_type = Some((type_.clone(), subtype.clone()));
                for &(ref k, ref v) in parameters.iter() {
                    if "charset" == k.as_slice() {
                        self.charset = Some(v.clone());
                    }
                }
            }
        }
    }
}

/// Message sent in response to `Load`.  Contains metadata, and a port
/// for receiving the data.
///
/// Even if loading fails immediately, we send one of these and the
/// progress_port will provide the error.
pub struct LoadResponse {
    /// Metadata, such as from HTTP headers.
    pub metadata: Metadata,
    /// Port for reading data.
    pub progress_port: Receiver<ProgressMsg>,
}

/// Messages sent in response to a `Load` message
#[deriving(Eq,Show)]
pub enum ProgressMsg {
    /// Binary data - there may be multiple of these
    Payload(Vec<u8>),
    /// Indicates loading is complete, either successfully or not
    Done(Result<(), ()>)
}

/// For use by loaders in responding to a Load message.
pub fn start_sending(start_chan: Sender<LoadResponse>,
                     metadata:   Metadata) -> Sender<ProgressMsg> {
    let (progress_chan, progress_port) = channel();
    start_chan.send(LoadResponse {
        metadata:      metadata,
        progress_port: progress_port,
    });
    progress_chan
}

/// Convenience function for synchronously loading a whole resource.
pub fn load_whole_resource(resource_task: &ResourceTask, url: Url)
        -> Result<(Metadata, Vec<u8>), ()> {
    let (start_chan, start_port) = channel();
    resource_task.send(Load(url, start_chan));
    let response = start_port.recv();

    let mut buf = vec!();
    loop {
        match response.progress_port.recv() {
            Payload(data) => buf.push_all(data.as_slice()),
            Done(Ok(()))  => return Ok((response.metadata, buf)),
            Done(Err(e))  => return Err(e)
        }
    }
}

/// Handle to a resource task
pub type ResourceTask = Sender<ControlMsg>;

pub type LoaderTask = proc(url: Url, Sender<LoadResponse>);

/**
Creates a task to load a specific resource

The ResourceManager delegates loading to a different type of loader task for
each URL scheme
*/
type LoaderTaskFactory = extern "Rust" fn() -> LoaderTask;

/// Create a ResourceTask with the default loaders
pub fn ResourceTask() -> ResourceTask {
    let loaders = ~[
        ("file".to_owned(), file_loader::factory),
        ("http".to_owned(), http_loader::factory),
        ("data".to_owned(), data_loader::factory),
    ];
    create_resource_task_with_loaders(loaders)
}

fn create_resource_task_with_loaders(loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask {
    let (setup_chan, setup_port) = channel();
    let builder = task::task().named("ResourceManager");
    builder.spawn(proc() {
        let (chan, port) = channel();
        setup_chan.send(chan);
        ResourceManager(port, loaders).start();
    });
    setup_port.recv()
}

struct ResourceManager {
    from_client: Receiver<ControlMsg>,
    /// Per-scheme resource loaders
    loaders: ~[(~str, LoaderTaskFactory)],
}

fn ResourceManager(from_client: Receiver<ControlMsg>,
                   loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceManager {
    ResourceManager {
        from_client : from_client,
        loaders : loaders,
    }
}

impl ResourceManager {
    fn start(&self) {
        loop {
            match self.from_client.recv() {
              Load(url, start_chan) => {
                self.load(url.clone(), start_chan)
              }
              Exit => {
                break
              }
            }
        }
    }

    fn load(&self, url: Url, start_chan: Sender<LoadResponse>) {
        match self.get_loader_factory(&url) {
            Some(loader_factory) => {
                debug!("resource_task: loading url: {:s}", url.to_str());
                loader_factory(url, start_chan);
            }
            None => {
                debug!("resource_task: no loader for scheme {:s}", url.scheme);
                start_sending(start_chan, Metadata::default(url)).send(Done(Err(())));
            }
        }
    }

    fn get_loader_factory(&self, url: &Url) -> Option<LoaderTask> {
        for scheme_loader in self.loaders.iter() {
            match *scheme_loader {
                (ref scheme, ref loader_factory) => {
	            if (*scheme) == url.scheme {
                        return Some((*loader_factory)());
                    }
	        }
            }
        }
        return None;
    }
}

#[test]
fn test_exit() {
    let resource_task = ResourceTask();
    resource_task.send(Exit);
}

#[test]
fn test_bad_scheme() {
    let resource_task = ResourceTask();
    let (start_chan, start) = channel();
    resource_task.send(Load(FromStr::from_str("bogus://whatever").unwrap(), start_chan));
    let response = start.recv();
    match response.progress_port.recv() {
      Done(result) => { assert!(result.is_err()) }
      _ => fail!("bleh")
    }
    resource_task.send(Exit);
}

#[cfg(test)]
static snicklefritz_payload: [u8, ..3] = [1, 2, 3];

#[cfg(test)]
fn snicklefritz_loader_factory() -> LoaderTask {
    let f: LoaderTask = proc(url: Url, start_chan: Sender<LoadResponse>) {
        let progress_chan = start_sending(start_chan, Metadata::default(url));
        progress_chan.send(Payload(Vec::from_slice(snicklefritz_payload)));
        progress_chan.send(Done(Ok(())));
    };
    f
}

#[test]
fn should_delegate_to_scheme_loader() {
    let loader_factories = ~[("snicklefritz".to_owned(), snicklefritz_loader_factory)];
    let resource_task = create_resource_task_with_loaders(loader_factories);
    let (start_chan, start) = channel();
    resource_task.send(Load(FromStr::from_str("snicklefritz://heya").unwrap(), start_chan));

    let response = start.recv();
    let progress = response.progress_port;

    assert!(progress.recv() == Payload(Vec::from_slice(snicklefritz_payload)));
    assert!(progress.recv() == Done(Ok(())));
    resource_task.send(Exit);
}
<commit_msg>Use Vec for ResourceTask.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A task that takes a URL and streams back the binary data.

use file_loader;
use http_loader;
use data_loader;

use std::comm::{channel, Receiver, Sender};
use std::task;
use http::headers::content_type::MediaType;
use url::Url;

#[cfg(test)]
use std::from_str::FromStr;

pub enum ControlMsg {
    /// Request the data associated with a particular URL
    Load(Url, Sender<LoadResponse>),
    Exit
}

/// Metadata about a loaded resource, such as is obtained from HTTP headers.
pub struct Metadata {
    /// Final URL after redirects.
    pub final_url: Url,

    /// MIME type / subtype.
    pub content_type: Option<(~str, ~str)>,

    /// Character set.
    pub charset: Option<~str>,
}

impl Metadata {
    /// Metadata with defaults for everything optional.
    pub fn default(url: Url) -> Metadata {
        Metadata {
            final_url:    url,
            content_type: None,
            charset:      None,
        }
    }

    /// Extract the parts of a MediaType that we care about.
    pub fn set_content_type(&mut self, content_type: &Option<MediaType>) {
        match *content_type {
            None => (),
            Some(MediaType { type_:      ref type_,
                             subtype:    ref subtype,
                             parameters: ref parameters }) => {
                self.content_type = Some((type_.clone(), subtype.clone()));
                for &(ref k, ref v) in parameters.iter() {
                    if "charset" == k.as_slice() {
                        self.charset = Some(v.clone());
                    }
                }
            }
        }
    }
}

/// Message sent in response to `Load`.  Contains metadata, and a port
/// for receiving the data.
///
/// Even if loading fails immediately, we send one of these and the
/// progress_port will provide the error.
pub struct LoadResponse {
    /// Metadata, such as from HTTP headers.
    pub metadata: Metadata,
    /// Port for reading data.
    pub progress_port: Receiver<ProgressMsg>,
}

/// Messages sent in response to a `Load` message
#[deriving(Eq,Show)]
pub enum ProgressMsg {
    /// Binary data - there may be multiple of these
    Payload(Vec<u8>),
    /// Indicates loading is complete, either successfully or not
    Done(Result<(), ()>)
}

/// For use by loaders in responding to a Load message.
pub fn start_sending(start_chan: Sender<LoadResponse>,
                     metadata:   Metadata) -> Sender<ProgressMsg> {
    let (progress_chan, progress_port) = channel();
    start_chan.send(LoadResponse {
        metadata:      metadata,
        progress_port: progress_port,
    });
    progress_chan
}

/// Convenience function for synchronously loading a whole resource.
pub fn load_whole_resource(resource_task: &ResourceTask, url: Url)
        -> Result<(Metadata, Vec<u8>), ()> {
    let (start_chan, start_port) = channel();
    resource_task.send(Load(url, start_chan));
    let response = start_port.recv();

    let mut buf = vec!();
    loop {
        match response.progress_port.recv() {
            Payload(data) => buf.push_all(data.as_slice()),
            Done(Ok(()))  => return Ok((response.metadata, buf)),
            Done(Err(e))  => return Err(e)
        }
    }
}

/// Handle to a resource task
pub type ResourceTask = Sender<ControlMsg>;

pub type LoaderTask = proc(url: Url, Sender<LoadResponse>);

/**
Creates a task to load a specific resource

The ResourceManager delegates loading to a different type of loader task for
each URL scheme
*/
type LoaderTaskFactory = extern "Rust" fn() -> LoaderTask;

/// Create a ResourceTask with the default loaders
pub fn ResourceTask() -> ResourceTask {
    let loaders = vec!(
        ("file".to_owned(), file_loader::factory),
        ("http".to_owned(), http_loader::factory),
        ("data".to_owned(), data_loader::factory),
    );
    create_resource_task_with_loaders(loaders)
}

fn create_resource_task_with_loaders(loaders: Vec<(~str, LoaderTaskFactory)>) -> ResourceTask {
    let (setup_chan, setup_port) = channel();
    let builder = task::task().named("ResourceManager");
    builder.spawn(proc() {
        let (chan, port) = channel();
        setup_chan.send(chan);
        ResourceManager(port, loaders).start();
    });
    setup_port.recv()
}

struct ResourceManager {
    from_client: Receiver<ControlMsg>,
    /// Per-scheme resource loaders
    loaders: Vec<(~str, LoaderTaskFactory)>,
}

fn ResourceManager(from_client: Receiver<ControlMsg>,
                   loaders: Vec<(~str, LoaderTaskFactory)>) -> ResourceManager {
    ResourceManager {
        from_client : from_client,
        loaders : loaders,
    }
}

impl ResourceManager {
    fn start(&self) {
        loop {
            match self.from_client.recv() {
              Load(url, start_chan) => {
                self.load(url.clone(), start_chan)
              }
              Exit => {
                break
              }
            }
        }
    }

    fn load(&self, url: Url, start_chan: Sender<LoadResponse>) {
        match self.get_loader_factory(&url) {
            Some(loader_factory) => {
                debug!("resource_task: loading url: {:s}", url.to_str());
                loader_factory(url, start_chan);
            }
            None => {
                debug!("resource_task: no loader for scheme {:s}", url.scheme);
                start_sending(start_chan, Metadata::default(url)).send(Done(Err(())));
            }
        }
    }

    fn get_loader_factory(&self, url: &Url) -> Option<LoaderTask> {
        for scheme_loader in self.loaders.iter() {
            match *scheme_loader {
                (ref scheme, ref loader_factory) => {
	            if (*scheme) == url.scheme {
                        return Some((*loader_factory)());
                    }
	        }
            }
        }
        return None;
    }
}

#[test]
fn test_exit() {
    let resource_task = ResourceTask();
    resource_task.send(Exit);
}

#[test]
fn test_bad_scheme() {
    let resource_task = ResourceTask();
    let (start_chan, start) = channel();
    resource_task.send(Load(FromStr::from_str("bogus://whatever").unwrap(), start_chan));
    let response = start.recv();
    match response.progress_port.recv() {
      Done(result) => { assert!(result.is_err()) }
      _ => fail!("bleh")
    }
    resource_task.send(Exit);
}

#[cfg(test)]
static snicklefritz_payload: [u8, ..3] = [1, 2, 3];

#[cfg(test)]
fn snicklefritz_loader_factory() -> LoaderTask {
    let f: LoaderTask = proc(url: Url, start_chan: Sender<LoadResponse>) {
        let progress_chan = start_sending(start_chan, Metadata::default(url));
        progress_chan.send(Payload(Vec::from_slice(snicklefritz_payload)));
        progress_chan.send(Done(Ok(())));
    };
    f
}

#[test]
fn should_delegate_to_scheme_loader() {
    let loader_factories = vec!(("snicklefritz".to_owned(), snicklefritz_loader_factory));
    let resource_task = create_resource_task_with_loaders(loader_factories);
    let (start_chan, start) = channel();
    resource_task.send(Load(FromStr::from_str("snicklefritz://heya").unwrap(), start_chan));

    let response = start.recv();
    let progress = response.progress_port;

    assert!(progress.recv() == Payload(Vec::from_slice(snicklefritz_payload)));
    assert!(progress.recv() == Done(Ok(())));
    resource_task.send(Exit);
}
<|endoftext|>


<commit_before>extern crate getopts;
use std::io::Write;

pub struct HelpText<'a> {
    pub name : &'a str,
    pub version : &'a str,
    pub syntax : &'a str,
    pub summary : &'a str,
    pub long_help : &'a str
}

pub struct CoreOptions<'a> {
    options : getopts::Options,
    help_text : HelpText<'a>
}

impl<'a> CoreOptions<'a> {
    pub fn new(help_text: HelpText<'a>) -> Self {
        let mut ret = CoreOptions {
            options : getopts::Options::new(),
            help_text : help_text
        };
        ret.options
            .optflag("", "help", "print usage information")
            .optflag("", "version", "print name and version number");
        ret
    }
    pub fn optopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions<'a> {
        self.options.optopt(short_name, long_name, desc, hint);
        self
    }
    pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut CoreOptions<'a> {
        self.options.optflag(short_name, long_name, desc);
        self
    }
    pub fn usage(&self, summary : &str) -> String {
        self.options.usage(summary)
    }
    pub fn parse(&mut self, args : Vec<String>) -> getopts::Matches {
        let matches = match self.options.parse(&args[1..]) {
            Ok(m) => { Some(m) },
            Err(f) => {
                crash!(1, "{}", f);
            }
        }.unwrap();
        if matches.opt_present("help") {
            print!("
 {0} {1}

 {0} {2}

 {3}

 Reference
{4}
",
self.help_text.name, self.help_text.version, self.help_text.syntax, self.options.usage(self.help_text.summary), self.help_text.long_help);
            exit!(0);
        } else if matches.opt_present("version") {
            print!("{} {}", self.help_text.name, self.help_text.version);
            exit!(0);
        }
        matches
    }
}

#[macro_export]
macro_rules! new_coreopts {
    ($syntax: expr, $summary: expr, $long_help: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help
        })
    );
}<commit_msg>uucore: coreopts alignment, spacing, and optional usage<commit_after>extern crate getopts;
use std::io::Write;

pub struct HelpText<'a> {
    pub name : &'a str,
    pub version : &'a str,
    pub syntax : &'a str,
    pub summary : &'a str,
    pub long_help : &'a str,
    pub display_usage : bool
}

pub struct CoreOptions<'a> {
    options : getopts::Options,
    help_text : HelpText<'a>
}

impl<'a> CoreOptions<'a> {
    pub fn new(help_text: HelpText<'a>) -> Self {
        let mut ret = CoreOptions {
            options : getopts::Options::new(),
            help_text : help_text
        };
        ret.options
            .optflag("", "help", "print usage information")
            .optflag("", "version", "print name and version number");
        ret
    }
    pub fn optopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions<'a> {
        self.options.optopt(short_name, long_name, desc, hint);
        self
    }
    pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut CoreOptions<'a> {
        self.options.optflag(short_name, long_name, desc);
        self
    }
    pub fn usage(&self, summary : &str) -> String {
        self.options.usage(summary)
    }
    pub fn parse(&mut self, args : Vec<String>) -> getopts::Matches {
        let matches = match self.options.parse(&args[1..]) {
            Ok(m) => { Some(m) },
            Err(f) => {
                crash!(1, "{}", f);
            }
        }.unwrap();
        if matches.opt_present("help") {
            let usage_str = if self.help_text.display_usage {
                    format!("\n {}\n\n Reference\n",
                        self.options.usage(self.help_text.summary)
                    ).replace("Options:", " Options:")
                } else { String::new() };
            print!("
 {0} {1}

 {0} {2}
{3}{4}
", self.help_text.name, self.help_text.version, self.help_text.syntax, usage_str, self.help_text.long_help);
            exit!(0);
        } else if matches.opt_present("version") {
            println!("{} {}", self.help_text.name, self.help_text.version);
            exit!(0);
        }
        matches
    }
}

#[macro_export]
macro_rules! new_coreopts {
    ($syntax: expr, $summary: expr, $long_help: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help,
            display_usage: true
        })
    );
    ($syntax: expr, $summary: expr, $long_help: expr, $display_usage: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help,
            display_usage: $display_usage
        })
    );
}<|endoftext|>


<commit_before>// we have lots of arguments, cleaning this up would be a large project
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]

extern crate cargo;
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate failure;
extern crate git2_curl;
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::collections::BTreeSet;

use cargo::core::shell::Shell;
use cargo::util::{self, lev_distance, CargoResult, CliResult, Config};
use cargo::util::{CliError, ProcessError};

mod cli;
mod command_prelude;
mod commands;

fn main() {
    env_logger::init();
    cargo::core::maybe_allow_nightly_features();

    let mut config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = match cargo::ops::fix_maybe_exec_rustc() {
        Ok(true) => Ok(()),
        Ok(false) => {
            init_git_transports(&config);
            let _token = cargo::util::job::setup();
            cli::main(&mut config)
        }
        Err(e) => Err(CliError::from(e)),
    };

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let mut result = Ok(None);
    match config.get_string(&alias_name) {
        Ok(value) => {
            if let Some(record) = value {
                let alias_commands = record
                    .val
                    .split_whitespace()
                    .map(|s| s.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
        Err(_) => {
            let value = config.get_list(&alias_name)?;
            if let Some(record) = value {
                let alias_commands: Vec<String> =
                    record.val.iter().map(|s| s.0.to_string()).collect();
                result = Ok(Some(alias_commands));
            }
        }
    }
    result
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<(String, Option<String>)> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert((
                    filename[prefix.len()..end].to_string(),
                    Some(path.display().to_string()),
                ));
            }
        }
    }

    for cmd in commands::builtin() {
        commands.insert((cmd.get_name().to_string(), None));
    }

    commands
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    cmds.into_iter()
        .map(|(c, _)| (lev_distance(&c, cmd), c))
        .filter(|&(d, _)| d < 4)
        .min_by_key(|a| a.0)
        .map(|slot| slot.1)
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            let err = match find_closest(config, cmd) {
                Some(closest) => format_err!(
                    "no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
                    cmd,
                    closest
                ),
                None => format_err!("no such subcommand: `{}`", cmd),
            };
            return Err(CliError::new(err, 101));
        }
    };

    let cargo_exe = config.cargo_exe()?;
    let err = match util::process(&command)
        .env(cargo::CARGO_ENV, cargo_exe)
        .args(args)
        .exec_replace()
    {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let Some(perr) = err.downcast_ref::<ProcessError>() {
        if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
            return Err(CliError::code(code));
        }
    }
    Err(CliError::new(err, 101))
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path)
        .map(|metadata| metadata.is_file())
        .unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if any HTTP options are specified,
    // such as proxies or custom certificate authorities. The custom
    // transport, however, is not as well battle-tested.

    match cargo::ops::needs_custom_http_transport(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<commit_msg>Exempt a call from the redundant_closure linter<commit_after>// we have lots of arguments, cleaning this up would be a large project
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]

extern crate cargo;
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate failure;
extern crate git2_curl;
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::collections::BTreeSet;

use cargo::core::shell::Shell;
use cargo::util::{self, lev_distance, CargoResult, CliResult, Config};
use cargo::util::{CliError, ProcessError};

mod cli;
mod command_prelude;
mod commands;

fn main() {
    env_logger::init();
    cargo::core::maybe_allow_nightly_features();

    let mut config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = match cargo::ops::fix_maybe_exec_rustc() {
        Ok(true) => Ok(()),
        Ok(false) => {
            init_git_transports(&config);
            let _token = cargo::util::job::setup();
            cli::main(&mut config)
        }
        Err(e) => Err(CliError::from(e)),
    };

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let mut result = Ok(None);
    match config.get_string(&alias_name) {
        Ok(value) => {
            if let Some(record) = value {
                let alias_commands = record
                    .val
                    .split_whitespace()
                    .map(|s| s.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
        Err(_) => {
            let value = config.get_list(&alias_name)?;
            if let Some(record) = value {
                let alias_commands: Vec<String> =
                    record.val.iter().map(|s| s.0.to_string()).collect();
                result = Ok(Some(alias_commands));
            }
        }
    }
    result
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<(String, Option<String>)> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert((
                    filename[prefix.len()..end].to_string(),
                    Some(path.display().to_string()),
                ));
            }
        }
    }

    for cmd in commands::builtin() {
        commands.insert((cmd.get_name().to_string(), None));
    }

    commands
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    cmds.into_iter()
        .map(|(c, _)| (lev_distance(&c, cmd), c))
        .filter(|&(d, _)| d < 4)
        .min_by_key(|a| a.0)
        .map(|slot| slot.1)
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    #[cfg_attr(feature = "cargo-clippy", allow(redundant_closure))] // false positive
    let path = search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            let err = match find_closest(config, cmd) {
                Some(closest) => format_err!(
                    "no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
                    cmd,
                    closest
                ),
                None => format_err!("no such subcommand: `{}`", cmd),
            };
            return Err(CliError::new(err, 101));
        }
    };

    let cargo_exe = config.cargo_exe()?;
    let err = match util::process(&command)
        .env(cargo::CARGO_ENV, cargo_exe)
        .args(args)
        .exec_replace()
    {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let Some(perr) = err.downcast_ref::<ProcessError>() {
        if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
            return Err(CliError::code(code));
        }
    }
    Err(CliError::new(err, 101))
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path)
        .map(|metadata| metadata.is_file())
        .unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if any HTTP options are specified,
    // such as proxies or custom certificate authorities. The custom
    // transport, however, is not as well battle-tested.

    match cargo::ops::needs_custom_http_transport(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use ansi::{NamedColor, Color};
use grid;
use index::Column;

bitflags! {
    #[derive(Serialize, Deserialize)]
    pub flags Flags: u32 {
        const INVERSE   = 0b00000001,
        const BOLD      = 0b00000010,
        const ITALIC    = 0b00000100,
        const UNDERLINE = 0b00001000,
        const WRAPLINE  = 0b00010000,
    }
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct Cell {
    pub c: char,
    pub fg: Color,
    pub bg: Color,
    pub flags: Flags,
}

impl Default for Cell {
    fn default() -> Cell {
        Cell::new(
            ' ',
            Color::Named(NamedColor::Foreground),
            Color::Named(NamedColor::Background)
        )
    }

}

/// Get the length of occupied cells in a line
pub trait LineLength {
    /// Calculate the occupied line length
    fn line_length(&self) -> Column;
}

impl LineLength for grid::Row<Cell> {
    fn line_length(&self) -> Column {
        let mut length = Column(0);

        if self[Column(self.len() - 1)].flags.contains(WRAPLINE) {
            return Column(self.len());
        }

        for (index, cell) in self[..].iter().rev().enumerate() {
            if cell.c != ' ' {
                length = Column(self.len() - index);
                break;
            }
        }

        length
    }
}

impl Cell {
    pub fn bold(&self) -> bool {
        self.flags.contains(BOLD)
    }

    pub fn new(c: char, fg: Color, bg: Color) -> Cell {
        Cell {
            c: c.into(),
            bg: bg,
            fg: fg,
            flags: Flags::empty(),
        }
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.c == ' ' &&
            self.bg == Color::Named(NamedColor::Background) &&
            !self.flags.contains(INVERSE)
    }

    #[inline]
    pub fn reset(&mut self, template: &Cell) {
        // memcpy template to self
        *self = *template;
    }
}

#[cfg(test)]
mod tests {
    use super::{Cell, LineLength};

    use grid::Row;
    use index::Column;

    #[test]
    fn line_length_works() {
        let template = Cell::default();
        let mut row = Row::new(Column(10), &template);
        row[Column(5)].c = 'a';

        assert_eq!(row.line_length(), Column(6));
    }

    #[test]
    fn line_length_works_with_wrapline() {
        let template = Cell::default();
        let mut row = Row::new(Column(10), &template);
        row[Column(9)].flags.insert(super::WRAPLINE);

        assert_eq!(row.line_length(), Column(10));
    }
}

#[cfg(all(test, feature = "bench"))]
mod benches {
    extern crate test;
    use super::Cell;

    #[bench]
    fn cell_reset(b: &mut test::Bencher) {
        b.iter(|| {
            let mut cell = Cell::default();

            for _ in 0..100 {
                cell.reset(test::black_box(&Cell::default()));
            }

            test::black_box(cell);
        });
    }
}
<commit_msg>Render underline on empty cells<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use ansi::{NamedColor, Color};
use grid;
use index::Column;

bitflags! {
    #[derive(Serialize, Deserialize)]
    pub flags Flags: u32 {
        const INVERSE   = 0b00000001,
        const BOLD      = 0b00000010,
        const ITALIC    = 0b00000100,
        const UNDERLINE = 0b00001000,
        const WRAPLINE  = 0b00010000,
    }
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct Cell {
    pub c: char,
    pub fg: Color,
    pub bg: Color,
    pub flags: Flags,
}

impl Default for Cell {
    fn default() -> Cell {
        Cell::new(
            ' ',
            Color::Named(NamedColor::Foreground),
            Color::Named(NamedColor::Background)
        )
    }

}

/// Get the length of occupied cells in a line
pub trait LineLength {
    /// Calculate the occupied line length
    fn line_length(&self) -> Column;
}

impl LineLength for grid::Row<Cell> {
    fn line_length(&self) -> Column {
        let mut length = Column(0);

        if self[Column(self.len() - 1)].flags.contains(WRAPLINE) {
            return Column(self.len());
        }

        for (index, cell) in self[..].iter().rev().enumerate() {
            if cell.c != ' ' {
                length = Column(self.len() - index);
                break;
            }
        }

        length
    }
}

impl Cell {
    pub fn bold(&self) -> bool {
        self.flags.contains(BOLD)
    }

    pub fn new(c: char, fg: Color, bg: Color) -> Cell {
        Cell {
            c: c.into(),
            bg: bg,
            fg: fg,
            flags: Flags::empty(),
        }
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.c == ' ' &&
            self.bg == Color::Named(NamedColor::Background) &&
            !self.flags.intersects(INVERSE | UNDERLINE)
    }

    #[inline]
    pub fn reset(&mut self, template: &Cell) {
        // memcpy template to self
        *self = *template;
    }
}

#[cfg(test)]
mod tests {
    use super::{Cell, LineLength};

    use grid::Row;
    use index::Column;

    #[test]
    fn line_length_works() {
        let template = Cell::default();
        let mut row = Row::new(Column(10), &template);
        row[Column(5)].c = 'a';

        assert_eq!(row.line_length(), Column(6));
    }

    #[test]
    fn line_length_works_with_wrapline() {
        let template = Cell::default();
        let mut row = Row::new(Column(10), &template);
        row[Column(9)].flags.insert(super::WRAPLINE);

        assert_eq!(row.line_length(), Column(10));
    }
}

#[cfg(all(test, feature = "bench"))]
mod benches {
    extern crate test;
    use super::Cell;

    #[bench]
    fn cell_reset(b: &mut test::Bencher) {
        b.iter(|| {
            let mut cell = Cell::default();

            for _ in 0..100 {
                cell.reset(test::black_box(&Cell::default()));
            }

            test::black_box(cell);
        });
    }
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_core;

use tokio_core::reactor::Interval;
use tokio_core::reactor::Handle;
use futures::stream::{Stream};

use std::time::{Instant, Duration};
use futures::Future;
use futures::IntoFuture;
use futures::Then;
use futures::Map;
use std::result::Result;
use std::io;
use futures::Async;
use futures::future::Ok;
use futures::Poll;
use std::thread;
use std::cell::Cell;
use std::boxed::Box;
//use std::boxed::FnBox;

use tokio_core::reactor::{Core, Timeout};

#[derive(Debug)]
struct Error {
    code: i32
}

impl Error {
    fn new(c: i32) -> Error {
        Error { code: c }
    }
}

//struct MyFuture<S: Clone> {
//    v: S
//}
//
//impl<S: Clone> Future for MyFuture<S>
//{
//    type Item = S;
//    type Error = Error;
//
//    fn poll(&mut self) -> Poll<S, Error> {
//        //self.get().poll()
//        Ok(Async::Ready(self.v.clone()))
//    }
//}

//impl<S: Clone> IntoFuture for MyFuture<S> {
//    type Future = MyFuture<S>;
//    type Item = S;
//    type Error = Error;
//
//    fn into_future(self) -> MyFuture<S> {
//        self
//    }
//}

//impl<F, R> Future for Lazy<F, R>
//where F: FnOnce() -> R,
//R: IntoFuture,

enum Cmd<S: Clone> {
    Start(S),
    //    Run(Box<FnBox(Handle) -> MyFuture<S>>),
    //Run(Box<FnOnce(Handle) -> MyFuture<S>>),
    Run(fn(handle: Handle) -> Box<Future<Item = S, Error = ()>>),
    After(Duration, S)
}

// A struct that holds some state and a handle on
// which to run its worker function.
#[derive(Debug)]
struct Actor<S: Clone> {
    //dur: Duration,
    state: S,
    //fu: fn(S) -> Cmd<S>,
}

impl<S: 'static + Clone> Actor<S> {
    fn new(handle: Handle, start_state: S, guts: fn(S) -> Cmd<S>) -> Actor<S> {
        //        let d = Duration::from_millis(5000);
        //        let a: Actor<S> = Actor { dur: d, state: start.clone(), fu: f };
        let a: Actor<S> = Actor { state: start_state.clone() };
        let cmd = Cmd::Start(start_state.clone());
        Actor::run_guts(handle, cmd, guts);
        a
    }

    fn run_guts(handle: Handle, cmd: Cmd<S>, guts: fn(S) -> Cmd<S>) {
        let futu = match cmd {
            Cmd::Start(state) => {
                let timeout = Timeout::new(Duration::from_millis(5000), &handle).unwrap();
                let handle_copy = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut = timeout.then(move |r| {
                    println!("******************************** START **********");
                    let next_cmd = guts_copy(state_copy);
                    Actor::run_guts(handle_copy, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::After(d, state) => {
                let timeout = Timeout::new(d, &handle).unwrap();
                let handle_copy = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut = timeout.then(move |r| {
                    println!("******************************** AFTER **********");
                    let next_cmd = guts_copy(state_copy);
                    Actor::run_guts(handle_copy, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::Run(work_future) => {
                let handle_copy = handle.clone();
                let handle_copy2 = handle.clone();
                //                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut0: Box<Future<Item = S, Error = ()>> = work_future(handle_copy);
                let fut = fut0.then(move |x: Result<S, ()>| {
                    let new_state = x.unwrap();
                    println!("******************************** RUN **********");
                    let next_cmd = guts_copy(new_state);
                    Actor::run_guts(handle_copy2, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            }
        };
    }

    // Will later on be used to access state from other threads in a reactive way.
    //    fn getAsync(&self) -> MyFuture {
    //        MyFuture { v: self.state }
    //    }
}

#[derive(Copy, Clone)]
enum State {
    Start(i32),
    Foo(i32),
    End
}

fn main() {
    // A thread on which background workers will be run.
    let worker_thread = thread::spawn(move || {
        let mut core = Core::new().unwrap();

        //        let z = testSimulateRemoteGetValue(&(core.handle()), |()| { State::End }).then(|_| {
        //            println!("XXXXXXXXXXXXX");
        //            futures::future::ok::<(), ()>(())
        //        });
        //        core.handle().spawn(z);

        fn doFoo(handle: Handle) -> Box<Future<Item = State, Error = ()>> {
            println!("Starting dofoo >>>> =======================================");
            let f = testSimulateRemoteGetValue(&handle, |()| { State::End });
            //Box::new(f.map(|x| { State::End }).map_err(|e| { () }))
            Box::new(f.map(|x| {
                println!("completed dofoo <<<< =======================================");
                State::End
            }).map_err(|e| { () }))
        }

        fn update(state: State) -> Cmd<State> {
            match state {
                State::Start(s) => {
                    println!("start - foo in 1 sec");
                    Cmd::After(Duration::new(1, 0), State::Foo(20))
                },
                State::Foo(s) => {
                    println!("foo - run doFoo now");
                    Cmd::Run(doFoo)
                },
                State::End => {
                    println!("end - end, run end egain in 1 sec");
                    Cmd::After(Duration::new(1, 0), State::End)
                },
            }
        }

        // Create a background worker
        let a: Actor<State> = Actor::new(core.handle(), State::Start(10), update);

        // An interval stream to drive the background worker futures.
        let interval_stream = Interval::new(Duration::new(1, 0), &(core.handle())).unwrap();
        let stream_future = interval_stream.for_each(|_| {
            println!("Worker driver says hello");
            Ok(())
        });

        core.run(stream_future).unwrap();
    });

    // Request handler threads to be started here (e.g. HTTP server)
    // These threads will eventually use the state the workers work on.

    worker_thread.join().unwrap();
}

fn testSimulateRemoteGetValue<R, F>(handle: &Handle, f: F) -> Map<Timeout, F>
    where R: Clone, F: FnOnce(()) -> R,
{
    let timeout = Timeout::new(Duration::from_millis(5000), handle).unwrap();
    let fut: Map<Timeout, F> = timeout.map(f);
    fut
}<commit_msg>Add Run2 command that takes state as input, too<commit_after>extern crate futures;
extern crate tokio_core;

use tokio_core::reactor::Interval;
use tokio_core::reactor::Handle;
use futures::stream::{Stream};

use std::time::{Instant, Duration};
use futures::Future;
use futures::IntoFuture;
use futures::Then;
use futures::Map;
use std::result::Result;
use std::io;
use futures::Async;
use futures::future::Ok;
use futures::Poll;
use std::thread;
use std::cell::Cell;
use std::boxed::Box;

use tokio_core::reactor::{Core, Timeout};

#[derive(Debug)]
struct Error {
    code: i32
}

impl Error {
    fn new(c: i32) -> Error {
        Error { code: c }
    }
}

// The instructions that the 'Actor' understands
// Commands return a new state to drive the next action
enum Cmd<S: Clone> {
    // Start with a certain state
    Start(S),
    // Run a function that returns a future of the state to proceed with
    Run(fn(handle: Handle) -> Box<Future<Item = S, Error = ()>>),
    Run2(S, fn(handle: Handle, S) -> Box<Future<Item = S, Error = ()>>),
    // Switch to a new state after duration
    After(Duration, S)
}

// A struct that holds some state and a handle on
// which to run its worker function.
#[derive(Debug)]
struct Actor<S: Clone> {
    //dur: Duration,
    state: S,
    //fu: fn(S) -> Cmd<S>,
}

// An actor takes an internal state machine (guts) which is a function
// from state to command-resulting-in-state
impl<S: 'static + Clone> Actor<S> {
    fn new(handle: Handle, start_state: S, guts: fn(S) -> Cmd<S>) -> Actor<S> {
        //        let d = Duration::from_millis(5000);
        //        let a: Actor<S> = Actor { dur: d, state: start.clone(), fu: f };
        let a: Actor<S> = Actor { state: start_state.clone() };
        let cmd = Cmd::Start(start_state.clone());
        Actor::run_guts(handle, cmd, guts);
        a
    }

    // execute the provided internals (guts)
    fn run_guts(handle: Handle, cmd: Cmd<S>, guts: fn(S) -> Cmd<S>) {
        let futu = match cmd {
            Cmd::Start(state) => {
                let timeout = Timeout::new(Duration::from_millis(5000), &handle).unwrap();
                let handle_copy = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut = timeout.then(move |r| {
                    println!("******************************** START **********");
                    let next_cmd = guts_copy(state_copy);
                    Actor::run_guts(handle_copy, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::After(d, state) => {
                let timeout = Timeout::new(d, &handle).unwrap();
                let handle_copy = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut = timeout.then(move |r| {
                    println!("******************************** AFTER **********");
                    let next_cmd = guts_copy(state_copy);
                    Actor::run_guts(handle_copy, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::Run(work_future) => {
                let handle_copy = handle.clone();
                let handle_copy2 = handle.clone();
                //                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut0: Box<Future<Item = S, Error = ()>> = work_future(handle_copy);
                let fut = fut0.then(move |x: Result<S, ()>| {
                    let new_state = x.unwrap();
                    println!("******************************** RUN **********");
                    let next_cmd = guts_copy(new_state);
                    Actor::run_guts(handle_copy2, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::Run2(state, work_future) => {
                let handle_copy = handle.clone();
                let handle_copy2 = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut0: Box<Future<Item = S, Error = ()>> = work_future(handle_copy, state_copy);
                let fut = fut0.then(move |x: Result<S, ()>| {
                    let new_state = x.unwrap();
                    println!("******************************** RUN **********");
                    let next_cmd = guts_copy(new_state);
                    Actor::run_guts(handle_copy2, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            }
        };
    }

    // Will later on be used to access state from other threads in a reactive way.
    //    fn getAsync(&self) -> MyFuture {
    //        MyFuture { v: self.state }
    //    }
}

#[derive(Copy, Clone, Debug)]
enum State {
    Start(i32),
    Foo(i32),
    Foo2(i32),
    End
}

fn main() {
    // A thread on which background workers will be run.
    let worker_thread = thread::spawn(move || {
        let mut core = Core::new().unwrap();

        fn doFoo(handle: Handle) -> Box<Future<Item = State, Error = ()>> {
            println!("Starting dofoo >>>> =======================================");
            let f = testSimulateRemoteGetValue(&handle, |()| { State::End });
            //Box::new(f.map(|x| { State::End }).map_err(|e| { () }))
            Box::new(f.map(|x| {
                println!("completed dofoo <<<< =======================================");
                State::Foo2(22)
            }).map_err(|e| { () }))
        }

        fn doFoo2(handle: Handle, state: State) -> Box<Future<Item = State, Error = ()>> {
            println!("Starting dofoo >>>> =======================================");
            let f = testSimulateRemoteGetValue(&handle, |()| { State::End });
            //Box::new(f.map(|x| { State::End }).map_err(|e| { () }))
            Box::new(f.map(move |x| {
                println!("completed dofoo <<<< ======================================= {:?} ", state);
                State::End
            }).map_err(|e| { () }))
        }

        fn update(state: State) -> Cmd<State> {
            match state {
                State::Start(s) => {
                    println!("start - foo in 1 sec");
                    Cmd::After(Duration::new(1, 0), State::Foo(20))
                },
                State::Foo(s) => {
                    println!("foo - run doFoo now");
                    Cmd::Run(doFoo)
                },
                State::Foo2(s) => {
                    println!("foo - run doFoo now");
                    Cmd::Run2(State::Foo2(s.clone()), doFoo2)
                },
                State::End => {
                    println!("end - end, run end egain in 1 sec");
                    Cmd::After(Duration::new(1, 0), State::End)
                },
            }
        }

        // Create a background worker
        let a: Actor<State> = Actor::new(core.handle(), State::Start(10), update);

        // An interval stream to drive the background worker futures.
        let interval_stream = Interval::new(Duration::new(60, 0), &(core.handle())).unwrap();
        let stream_future = interval_stream.for_each(|_| {
            println!("Worker driver says hello");
            Ok(())
        });

        core.run(stream_future).unwrap();
    });

    // Request handler threads to be started here (e.g. HTTP server)
    // These threads will eventually use the state the workers work on.

    worker_thread.join().unwrap();
}

fn testSimulateRemoteGetValue<R, F>(handle: &Handle, f: F) -> Map<Timeout, F>
    where R: Clone, F: FnOnce(()) -> R,
{
    let timeout = Timeout::new(Duration::from_millis(5000), handle).unwrap();
    let fut: Map<Timeout, F> = timeout.map(f);
    fut
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use bindgen::ir::Type;

pub fn mangle_path(name: &str, generic_values: &[Type]) -> String {
    internal_mangle_path(name, generic_values, true)
}

fn internal_mangle_path(name: &str, generic_values: &[Type], last_in_parent: bool) -> String {
    assert!(!name.contains("_"));

    if generic_values.is_empty() {
        return String::from(name);
    }

    let mut out = String::from(name);

    out.push_str("_"); // <
    for (i, ty) in generic_values.iter().enumerate() {
        if i != 0 {
            out.push_str("__"); // ,
        }

        let is_last = i == generic_values.len() - 1;
        match ty {
            &Type::Path(ref path) => {
                out.push_str(&internal_mangle_path(&path.name,
                                                   &path.generics,
                                                   last_in_parent && is_last));
            }
            &Type::Primitive(ref primitive) => {
                out.push_str(primitive.to_repr_rust());
            }
            &Type::ConstPtr(..) |
            &Type::Ptr(..) |
            &Type::Array(..)|
            &Type::FuncPtr(..) => {
                unimplemented!()
            }
        }

        // Skip writing the trailing '>' mangling when possible
        if is_last && !last_in_parent {
            out.push_str("___"); // >
        }
    }

    out
}

#[test]
fn mangle_test() {
    use bindgen::ir::{GenericPath, PrimitiveType};

    fn float() -> Type {
        Type::Primitive(PrimitiveType::Float)
    }

    fn path(path: &str) -> Type {
        Type::Path(GenericPath::new(path.to_owned(), Vec::new()))
    }

    fn generic_path(path: &str, generics: &[Type]) -> Type {
        Type::Path(GenericPath::new(path.to_owned(), generics.to_owned()))
    }

    /* Foo<f32> => Foo_f32 */
    assert_eq!(mangle_path("Foo", &vec![float()]),
               "Foo_f32");

    /* Foo<Bar<f32>> => Foo_Bar_f32 */
    assert_eq!(mangle_path("Foo", &vec![generic_path("Bar", &[float()])]),
               "Foo_Bar_f32");

    /* Foo<Bar> => Foo_Bar */
    assert_eq!(mangle_path("Foo", &[path("Bar")]),
               "Foo_Bar");

    /* Foo<Bar<T>> => Foo_Bar_T */
    assert_eq!(mangle_path("Foo", &[generic_path("Bar", &[path("T")])]),
               "Foo_Bar_T");

    // /* Foo<Bar<T>, E> => Foo_Bar_T_____E */
    assert_eq!(mangle_path("Foo", &[generic_path("Bar", &[path("T")]),
                                    path("E")]),
               "Foo_Bar_T_____E");

    // /* Foo<Bar<T>, Bar<E>> => Foo_Bar_T_____Bar_E */
    assert_eq!(mangle_path("Foo", &[generic_path("Bar", &[path("T")]),
                                    generic_path("Bar", &[path("E")])]),
               "Foo_Bar_T_____Bar_E");
}
<commit_msg>Improve error message for generic types with underscores.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use bindgen::ir::Type;

pub fn mangle_path(name: &str, generic_values: &[Type]) -> String {
    internal_mangle_path(name, generic_values, true)
}

fn internal_mangle_path(name: &str, generic_values: &[Type], last_in_parent: bool) -> String {
    assert!(!name.contains("_"), format!("name '{}' contains an underscore", name));

    if generic_values.is_empty() {
        return String::from(name);
    }

    let mut out = String::from(name);

    out.push_str("_"); // <
    for (i, ty) in generic_values.iter().enumerate() {
        if i != 0 {
            out.push_str("__"); // ,
        }

        let is_last = i == generic_values.len() - 1;
        match ty {
            &Type::Path(ref path) => {
                out.push_str(&internal_mangle_path(&path.name,
                                                   &path.generics,
                                                   last_in_parent && is_last));
            }
            &Type::Primitive(ref primitive) => {
                out.push_str(primitive.to_repr_rust());
            }
            &Type::ConstPtr(..) |
            &Type::Ptr(..) |
            &Type::Array(..)|
            &Type::FuncPtr(..) => {
                unimplemented!()
            }
        }

        // Skip writing the trailing '>' mangling when possible
        if is_last && !last_in_parent {
            out.push_str("___"); // >
        }
    }

    out
}

#[test]
fn generics() {
    use bindgen::ir::{GenericPath, PrimitiveType};

    fn float() -> Type {
        Type::Primitive(PrimitiveType::Float)
    }

    fn path(path: &str) -> Type {
        Type::Path(GenericPath::new(path.to_owned(), Vec::new()))
    }

    fn generic_path(path: &str, generics: &[Type]) -> Type {
        Type::Path(GenericPath::new(path.to_owned(), generics.to_owned()))
    }

    // Foo<f32> => Foo_f32
    assert_eq!(mangle_path("Foo", &vec![float()]),
               "Foo_f32");

    // Foo<Bar<f32>> => Foo_Bar_f32
    assert_eq!(mangle_path("Foo", &vec![generic_path("Bar", &[float()])]),
               "Foo_Bar_f32");

    // Foo<Bar> => Foo_Bar
    assert_eq!(mangle_path("Foo", &[path("Bar")]),
               "Foo_Bar");

    // Foo<Bar<T>> => Foo_Bar_T
    assert_eq!(mangle_path("Foo", &[generic_path("Bar", &[path("T")])]),
               "Foo_Bar_T");

    // Foo<Bar<T>, E> => Foo_Bar_T_____E
    assert_eq!(mangle_path("Foo", &[generic_path("Bar", &[path("T")]),
                                    path("E")]),
               "Foo_Bar_T_____E");

    // Foo<Bar<T>, Bar<E>> => Foo_Bar_T_____Bar_E
    assert_eq!(mangle_path("Foo", &[generic_path("Bar", &[path("T")]),
                                    generic_path("Bar", &[path("E")])]),
               "Foo_Bar_T_____Bar_E");
}

#[test]
#[should_panic(expected = "name 'foo_bar' contains an underscore")]
fn invalid() {
    use bindgen::ir::PrimitiveType;

    // foo_bar<u32> => foo_bar_f32
    let t = Type::Primitive(PrimitiveType::UInt32);
    assert_eq!(mangle_path("foo_bar", &vec![t]),
               "foo_bar_u32");
}
<|endoftext|>