<commit_before>use std::path::{Path, PathBuf};
use std::borrow::Cow;
use std::env;
use std::io;
use std::process::Command;
use std::fmt::{self, Display};
use std::sync::Arc;

use errors::*;
use notifications::*;
use rustup_dist::{temp, dist};
use rustup_utils::utils;
use toolchain::{Toolchain, UpdateStatus};
use telemetry_analysis::*;
use settings::{TelemetryMode, SettingsFile, DEFAULT_METADATA_VERSION};

#[derive(Debug)]
pub enum OverrideReason {
    Environment,
    OverrideDB(PathBuf),
}

impl Display for OverrideReason {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            OverrideReason::Environment => write!(f, "environment override by RUSTUP_TOOLCHAIN"),
            OverrideReason::OverrideDB(ref path) => {
                write!(f, "directory override for '{}'", path.display())
            }
        }
    }
}

pub struct Cfg {
    pub multirust_dir: PathBuf,
    pub settings_file: SettingsFile,
    pub toolchains_dir: PathBuf,
    pub update_hash_dir: PathBuf,
    pub temp_cfg: temp::Cfg,
    pub gpg_key: Cow<'static, str>,
    pub env_override: Option<String>,
    pub dist_root_url: String,
    pub dist_root_server: String,
    pub notify_handler: Arc<Fn(Notification)>,
}

impl Cfg {
    pub fn from_env(notify_handler: Arc<Fn(Notification)>) -> Result<Self> {
        // Set up the multirust home directory
        let multirust_dir = try!(utils::multirust_home());

        try!(utils::ensure_dir_exists("home", &multirust_dir,
                                      &|n| notify_handler(n.into())));

        let settings_file = SettingsFile::new(multirust_dir.join("settings.toml"));
        // Convert from old settings format if necessary
        try!(settings_file.maybe_upgrade_from_legacy(&multirust_dir));

        let toolchains_dir = multirust_dir.join("toolchains");
        let update_hash_dir = multirust_dir.join("update-hashes");

        // GPG key
        let gpg_key = if let Some(path) = env::var_os("RUSTUP_GPG_KEY")
                                              .and_then(utils::if_not_empty) {
            Cow::Owned(try!(utils::read_file("public key", Path::new(&path))))
        } else {
            Cow::Borrowed(include_str!("rust-key.gpg.ascii"))
        };

        // Environment override
        let env_override = env::var("RUSTUP_TOOLCHAIN")
                               .ok()
                               .and_then(utils::if_not_empty);

        let dist_root_server = match env::var("RUSTUP_DIST_SERVER") {
            Ok(ref s) if !s.is_empty() => {
                s.clone()
            }
            _ => {
                // For backward compatibility
                env::var("RUSTUP_DIST_ROOT")
                    .ok()
                    .and_then(utils::if_not_empty)
                    .map_or(Cow::Borrowed(dist::DEFAULT_DIST_ROOT), Cow::Owned)
                    .as_ref()
                    .trim_right_matches("/dist")
                    .to_owned()
            }
        };

        let notify_clone = notify_handler.clone();
        let temp_cfg = temp::Cfg::new(multirust_dir.join("tmp"),
                                      dist_root_server.as_str(),
                                      Box::new(move |n| {
                                          (notify_clone)(n.into())
                                      }));
        let dist_root = dist_root_server.clone() + "/dist";

        Ok(Cfg {
            multirust_dir: multirust_dir,
            settings_file: settings_file,
            toolchains_dir: toolchains_dir,
            update_hash_dir: update_hash_dir,
            temp_cfg: temp_cfg,
            gpg_key: gpg_key,
            notify_handler: notify_handler,
            env_override: env_override,
            dist_root_url: dist_root,
            dist_root_server: dist_root_server,
        })
    }

    pub fn set_default(&self, toolchain: &str) -> Result<()> {
        try!(self.settings_file.with_mut(|s| {
            s.default_toolchain = Some(toolchain.to_owned());
            Ok(())
        }));
        (self.notify_handler)(Notification::SetDefaultToolchain(toolchain));
        Ok(())
    }

    pub fn get_toolchain(&self, name: &str, create_parent: bool) -> Result<Toolchain> {
        if create_parent {
            try!(utils::ensure_dir_exists("toolchains",
                                          &self.toolchains_dir,
                                          &|n| (self.notify_handler)(n.into())));
        }

        Toolchain::from(self, name)
    }

    pub fn verify_toolchain(&self, name: &str) -> Result<Toolchain> {
        let toolchain = try!(self.get_toolchain(name, false));
        try!(toolchain.verify());
        Ok(toolchain)
    }

    pub fn get_hash_file(&self, toolchain: &str, create_parent: bool) -> Result<PathBuf> {
        if create_parent {
            try!(utils::ensure_dir_exists("update-hash",
                                          &self.update_hash_dir,
                                          &|n| (self.notify_handler)(n.into())));
        }

        Ok(self.update_hash_dir.join(toolchain))
    }

    pub fn which_binary(&self, path: &Path, binary: &str) -> Result<Option<PathBuf>> {

        if let Some((toolchain, _)) = try!(self.find_override_toolchain_or_default(path)) {
            Ok(Some(toolchain.binary_file(binary)))
        } else {
            Ok(None)
        }
    }

    pub fn upgrade_data(&self) -> Result<()> {

        let current_version = try!(self.settings_file.with(|s| Ok(s.version.clone())));

        if current_version == DEFAULT_METADATA_VERSION {
            (self.notify_handler)
                (Notification::MetadataUpgradeNotNeeded(&current_version));
            return Ok(());
        }

        (self.notify_handler)
            (Notification::UpgradingMetadata(&current_version, DEFAULT_METADATA_VERSION));

        match &*current_version {
            "2" => {
                // The toolchain installation format changed. Just delete them all.
                (self.notify_handler)(Notification::UpgradeRemovesToolchains);

                let dirs = try!(utils::read_dir("toolchains", &self.toolchains_dir));
                for dir in dirs {
                    let dir = try!(dir.chain_err(|| ErrorKind::UpgradeIoError));
                    try!(utils::remove_dir("toolchain", &dir.path(),
                                           &|n| (self.notify_handler)(n.into())));
                }

                // Also delete the update hashes
                let files = try!(utils::read_dir("update hashes", &self.update_hash_dir));
                for file in files {
                    let file = try!(file.chain_err(|| ErrorKind::UpgradeIoError));
                    try!(utils::remove_file("update hash", &file.path()));
                }

                self.settings_file.with_mut(|s| {
                    s.version = DEFAULT_METADATA_VERSION.to_owned();
                    Ok(())
                })
            }
            _ => Err(ErrorKind::UnknownMetadataVersion(current_version).into()),
        }
    }

    pub fn delete_data(&self) -> Result<()> {
        if utils::path_exists(&self.multirust_dir) {
            Ok(try!(utils::remove_dir("home", &self.multirust_dir,
                                      &|n| (self.notify_handler)(n.into()))))
        } else {
            Ok(())
        }
    }

    pub fn find_default(&self) -> Result<Option<Toolchain>> {
        let opt_name = try!(self.settings_file.with(|s| Ok(s.default_toolchain.clone())));

        if let Some(name) = opt_name {
            let toolchain = try!(self.verify_toolchain(&name)
                                 .chain_err(|| ErrorKind::ToolchainNotInstalled(name.to_string())));

            Ok(Some(toolchain))
        } else {
            Ok(None)
        }
    }

    pub fn find_override(&self, path: &Path) -> Result<Option<(Toolchain, OverrideReason)>> {
        if let Some(ref name) = self.env_override {
            let toolchain = try!(self.verify_toolchain(name).chain_err(|| ErrorKind::ToolchainNotInstalled(name.to_string())));

            return Ok(Some((toolchain, OverrideReason::Environment)));
        }

        let result = try!(self.settings_file.with(|s| {
            Ok(s.find_override(path, self.notify_handler.as_ref()))
        }));
        if let Some((name, reason_path)) = result {
            let toolchain = try!(self.verify_toolchain(&name).chain_err(|| ErrorKind::ToolchainNotInstalled(name.to_string())));
            return Ok(Some((toolchain, OverrideReason::OverrideDB(reason_path))));
        }

        Ok(None)
    }

    pub fn find_override_toolchain_or_default
        (&self,
         path: &Path)
         -> Result<Option<(Toolchain, Option<OverrideReason>)>> {
        Ok(if let Some((toolchain, reason)) = try!(self.find_override(path)) {
            Some((toolchain, Some(reason)))
        } else {
            try!(self.find_default()).map(|toolchain| (toolchain, None))
        })
    }

    pub fn list_toolchains(&self) -> Result<Vec<String>> {
        if utils::is_directory(&self.toolchains_dir) {
            let mut toolchains: Vec<_> = try!(utils::read_dir("toolchains", &self.toolchains_dir))
                                         .filter_map(io::Result::ok)
                                         .filter(|e| e.file_type().map(|f| f.is_dir()).unwrap_or(false))
                                         .filter_map(|e| e.file_name().into_string().ok())
                                         .collect();

            utils::toolchain_sort(&mut toolchains);

            Ok(toolchains)
        } else {
            Ok(Vec::new())
        }
    }

    pub fn update_all_channels(&self) -> Result<Vec<(String, Result<UpdateStatus>)>> {
        let toolchains = try!(self.list_toolchains());

        // Convert the toolchain strings to Toolchain values
        let toolchains = toolchains.into_iter();
        let toolchains = toolchains.map(|n| (n.clone(), self.get_toolchain(&n, true)));

        // Filter out toolchains that don't track a release channel
        let toolchains = toolchains.filter(|&(_, ref t)| {
            t.as_ref().map(|t| t.is_tracking()).unwrap_or(false)
        });

        // Update toolchains and collect the results
        let toolchains = toolchains.map(|(n, t)| {
            let t = t.and_then(|t| {
                let t = t.install_from_dist();
                if let Err(ref e) = t {
                    (self.notify_handler)(Notification::NonFatalError(e));
                }
                t
            });

            (n, t)
        });

        Ok(toolchains.collect())
    }

    pub fn check_metadata_version(&self) -> Result<()> {
        try!(utils::assert_is_directory(&self.multirust_dir));

        self.settings_file.with(|s| {
            (self.notify_handler)(Notification::ReadMetadataVersion(&s.version));
            if s.version == DEFAULT_METADATA_VERSION {
                Ok(())
            } else {
                Err(ErrorKind::NeedMetadataUpgrade.into())
            }
        })
    }

    pub fn toolchain_for_dir(&self, path: &Path) -> Result<(Toolchain, Option<OverrideReason>)> {
        self.find_override_toolchain_or_default(path)
            .and_then(|r| r.ok_or("no default toolchain configured".into()))
    }

    pub fn create_command_for_dir(&self, path: &Path, binary: &str) -> Result<Command> {
        let (ref toolchain, _) = try!(self.toolchain_for_dir(path));

        if let Some(cmd) = try!(self.maybe_do_cargo_fallback(toolchain, binary)) {
            Ok(cmd)
        } else {
            toolchain.create_command(binary)
        }
    }

    pub fn create_command_for_toolchain(&self, toolchain: &str, binary: &str) -> Result<Command> {
        let ref toolchain = try!(self.get_toolchain(toolchain, false));

        if let Some(cmd) = try!(self.maybe_do_cargo_fallback(toolchain, binary)) {
            Ok(cmd)
        } else {
            toolchain.create_command(binary)
        }
    }

    // Custom toolchains don't have cargo, so here we detect that situation and
    // try to find a different cargo.
    fn maybe_do_cargo_fallback(&self, toolchain: &Toolchain, binary: &str) -> Result<Option<Command>> {
        if !toolchain.is_custom() {
            return Ok(None);
        }

        if binary != "cargo" && binary != "cargo.exe" {
            return Ok(None);
        }

        let cargo_path = toolchain.path().join("bin/cargo");
        let cargo_exe_path = toolchain.path().join("bin/cargo.exe");

        if cargo_path.exists() || cargo_exe_path.exists() {
            return Ok(None);
        }

        for fallback in &["nightly", "beta", "stable"] {
            let fallback = try!(self.get_toolchain(fallback, false));
            if fallback.exists() {
                let cmd = try!(fallback.create_fallback_command("cargo", toolchain));
                return Ok(Some(cmd));
            }
        }

        Ok(None)
    }

    pub fn doc_path_for_dir(&self, path: &Path, relative: &str) -> Result<PathBuf> {
        let (toolchain, _) = try!(self.toolchain_for_dir(path));
        toolchain.doc_path(relative)
    }

    pub fn open_docs_for_dir(&self, path: &Path, relative: &str) -> Result<()> {
        let (toolchain, _) = try!(self.toolchain_for_dir(path));
        toolchain.open_docs(relative)
    }

    pub fn set_default_host_triple(&self, host_triple: &str) -> Result<()> {
        self.settings_file.with_mut(|s| {
            s.default_host_triple = Some(host_triple.to_owned());
            Ok(())
        })
    }

    pub fn get_default_host_triple(&self) -> Result<dist::TargetTriple> {
        Ok(try!(self.settings_file.with(|s| {
            Ok(s.default_host_triple.as_ref().map(|s| dist::TargetTriple::from_str(&s)))
        })).unwrap_or_else(dist::TargetTriple::from_build))
    }

    pub fn resolve_toolchain(&self, name: &str) -> Result<String> {
        if let Ok(desc) = dist::PartialToolchainDesc::from_str(name) {
            let host = try!(self.get_default_host_triple());
            Ok(desc.resolve(&host).to_string())
        } else {
            Ok(name.to_owned())
        }
    }

    pub fn set_telemetry(&self, telemetry_enabled: bool) -> Result<()> {
        if telemetry_enabled { self.enable_telemetry() } else { self.disable_telemetry() }
    }

    fn enable_telemetry(&self) -> Result<()> {
        try!(self.settings_file.with_mut(|s| {
            s.telemetry = TelemetryMode::On;
            Ok(())
        }));

        let _ = utils::ensure_dir_exists("telemetry", &self.multirust_dir.join("telemetry"),
                                         &|_| ());

        (self.notify_handler)(Notification::SetTelemetry("on"));

        Ok(())
    }

    fn disable_telemetry(&self) -> Result<()> {
        try!(self.settings_file.with_mut(|s| {
            s.telemetry = TelemetryMode::Off;
            Ok(())
        }));

        (self.notify_handler)(Notification::SetTelemetry("off"));

        Ok(())
    }

    pub fn telemetry_enabled(&self) -> Result<bool> {
        Ok(match try!(self.settings_file.with(|s| Ok(s.telemetry))) {
            TelemetryMode::On => true,
            TelemetryMode::Off => false,
        })
    }

    pub fn analyze_telemetry(&self) -> Result<TelemetryAnalysis> {
        let mut t = TelemetryAnalysis::new(self.multirust_dir.join("telemetry"));

        let events = try!(t.import_telemery());
        try!(t.analyze_telemetry_events(&events));

        Ok(t)
    }
}
<commit_msg>Widen the range of entries seen as toolchains<commit_after>use std::path::{Path, PathBuf};
use std::borrow::Cow;
use std::env;
use std::io;
use std::process::Command;
use std::fmt::{self, Display};
use std::sync::Arc;

use errors::*;
use notifications::*;
use rustup_dist::{temp, dist};
use rustup_utils::utils;
use toolchain::{Toolchain, UpdateStatus};
use telemetry_analysis::*;
use settings::{TelemetryMode, SettingsFile, DEFAULT_METADATA_VERSION};

#[derive(Debug)]
pub enum OverrideReason {
    Environment,
    OverrideDB(PathBuf),
}

impl Display for OverrideReason {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            OverrideReason::Environment => write!(f, "environment override by RUSTUP_TOOLCHAIN"),
            OverrideReason::OverrideDB(ref path) => {
                write!(f, "directory override for '{}'", path.display())
            }
        }
    }
}

pub struct Cfg {
    pub multirust_dir: PathBuf,
    pub settings_file: SettingsFile,
    pub toolchains_dir: PathBuf,
    pub update_hash_dir: PathBuf,
    pub temp_cfg: temp::Cfg,
    pub gpg_key: Cow<'static, str>,
    pub env_override: Option<String>,
    pub dist_root_url: String,
    pub dist_root_server: String,
    pub notify_handler: Arc<Fn(Notification)>,
}

impl Cfg {
    pub fn from_env(notify_handler: Arc<Fn(Notification)>) -> Result<Self> {
        // Set up the multirust home directory
        let multirust_dir = try!(utils::multirust_home());

        try!(utils::ensure_dir_exists("home", &multirust_dir,
                                      &|n| notify_handler(n.into())));

        let settings_file = SettingsFile::new(multirust_dir.join("settings.toml"));
        // Convert from old settings format if necessary
        try!(settings_file.maybe_upgrade_from_legacy(&multirust_dir));

        let toolchains_dir = multirust_dir.join("toolchains");
        let update_hash_dir = multirust_dir.join("update-hashes");

        // GPG key
        let gpg_key = if let Some(path) = env::var_os("RUSTUP_GPG_KEY")
                                              .and_then(utils::if_not_empty) {
            Cow::Owned(try!(utils::read_file("public key", Path::new(&path))))
        } else {
            Cow::Borrowed(include_str!("rust-key.gpg.ascii"))
        };

        // Environment override
        let env_override = env::var("RUSTUP_TOOLCHAIN")
                               .ok()
                               .and_then(utils::if_not_empty);

        let dist_root_server = match env::var("RUSTUP_DIST_SERVER") {
            Ok(ref s) if !s.is_empty() => {
                s.clone()
            }
            _ => {
                // For backward compatibility
                env::var("RUSTUP_DIST_ROOT")
                    .ok()
                    .and_then(utils::if_not_empty)
                    .map_or(Cow::Borrowed(dist::DEFAULT_DIST_ROOT), Cow::Owned)
                    .as_ref()
                    .trim_right_matches("/dist")
                    .to_owned()
            }
        };

        let notify_clone = notify_handler.clone();
        let temp_cfg = temp::Cfg::new(multirust_dir.join("tmp"),
                                      dist_root_server.as_str(),
                                      Box::new(move |n| {
                                          (notify_clone)(n.into())
                                      }));
        let dist_root = dist_root_server.clone() + "/dist";

        Ok(Cfg {
            multirust_dir: multirust_dir,
            settings_file: settings_file,
            toolchains_dir: toolchains_dir,
            update_hash_dir: update_hash_dir,
            temp_cfg: temp_cfg,
            gpg_key: gpg_key,
            notify_handler: notify_handler,
            env_override: env_override,
            dist_root_url: dist_root,
            dist_root_server: dist_root_server,
        })
    }

    pub fn set_default(&self, toolchain: &str) -> Result<()> {
        try!(self.settings_file.with_mut(|s| {
            s.default_toolchain = Some(toolchain.to_owned());
            Ok(())
        }));
        (self.notify_handler)(Notification::SetDefaultToolchain(toolchain));
        Ok(())
    }

    pub fn get_toolchain(&self, name: &str, create_parent: bool) -> Result<Toolchain> {
        if create_parent {
            try!(utils::ensure_dir_exists("toolchains",
                                          &self.toolchains_dir,
                                          &|n| (self.notify_handler)(n.into())));
        }

        Toolchain::from(self, name)
    }

    pub fn verify_toolchain(&self, name: &str) -> Result<Toolchain> {
        let toolchain = try!(self.get_toolchain(name, false));
        try!(toolchain.verify());
        Ok(toolchain)
    }

    pub fn get_hash_file(&self, toolchain: &str, create_parent: bool) -> Result<PathBuf> {
        if create_parent {
            try!(utils::ensure_dir_exists("update-hash",
                                          &self.update_hash_dir,
                                          &|n| (self.notify_handler)(n.into())));
        }

        Ok(self.update_hash_dir.join(toolchain))
    }

    pub fn which_binary(&self, path: &Path, binary: &str) -> Result<Option<PathBuf>> {

        if let Some((toolchain, _)) = try!(self.find_override_toolchain_or_default(path)) {
            Ok(Some(toolchain.binary_file(binary)))
        } else {
            Ok(None)
        }
    }

    pub fn upgrade_data(&self) -> Result<()> {

        let current_version = try!(self.settings_file.with(|s| Ok(s.version.clone())));

        if current_version == DEFAULT_METADATA_VERSION {
            (self.notify_handler)
                (Notification::MetadataUpgradeNotNeeded(&current_version));
            return Ok(());
        }

        (self.notify_handler)
            (Notification::UpgradingMetadata(&current_version, DEFAULT_METADATA_VERSION));

        match &*current_version {
            "2" => {
                // The toolchain installation format changed. Just delete them all.
                (self.notify_handler)(Notification::UpgradeRemovesToolchains);

                let dirs = try!(utils::read_dir("toolchains", &self.toolchains_dir));
                for dir in dirs {
                    let dir = try!(dir.chain_err(|| ErrorKind::UpgradeIoError));
                    try!(utils::remove_dir("toolchain", &dir.path(),
                                           &|n| (self.notify_handler)(n.into())));
                }

                // Also delete the update hashes
                let files = try!(utils::read_dir("update hashes", &self.update_hash_dir));
                for file in files {
                    let file = try!(file.chain_err(|| ErrorKind::UpgradeIoError));
                    try!(utils::remove_file("update hash", &file.path()));
                }

                self.settings_file.with_mut(|s| {
                    s.version = DEFAULT_METADATA_VERSION.to_owned();
                    Ok(())
                })
            }
            _ => Err(ErrorKind::UnknownMetadataVersion(current_version).into()),
        }
    }

    pub fn delete_data(&self) -> Result<()> {
        if utils::path_exists(&self.multirust_dir) {
            Ok(try!(utils::remove_dir("home", &self.multirust_dir,
                                      &|n| (self.notify_handler)(n.into()))))
        } else {
            Ok(())
        }
    }

    pub fn find_default(&self) -> Result<Option<Toolchain>> {
        let opt_name = try!(self.settings_file.with(|s| Ok(s.default_toolchain.clone())));

        if let Some(name) = opt_name {
            let toolchain = try!(self.verify_toolchain(&name)
                                 .chain_err(|| ErrorKind::ToolchainNotInstalled(name.to_string())));

            Ok(Some(toolchain))
        } else {
            Ok(None)
        }
    }

    pub fn find_override(&self, path: &Path) -> Result<Option<(Toolchain, OverrideReason)>> {
        if let Some(ref name) = self.env_override {
            let toolchain = try!(self.verify_toolchain(name).chain_err(|| ErrorKind::ToolchainNotInstalled(name.to_string())));

            return Ok(Some((toolchain, OverrideReason::Environment)));
        }

        let result = try!(self.settings_file.with(|s| {
            Ok(s.find_override(path, self.notify_handler.as_ref()))
        }));
        if let Some((name, reason_path)) = result {
            let toolchain = try!(self.verify_toolchain(&name).chain_err(|| ErrorKind::ToolchainNotInstalled(name.to_string())));
            return Ok(Some((toolchain, OverrideReason::OverrideDB(reason_path))));
        }

        Ok(None)
    }

    pub fn find_override_toolchain_or_default
        (&self,
         path: &Path)
         -> Result<Option<(Toolchain, Option<OverrideReason>)>> {
        Ok(if let Some((toolchain, reason)) = try!(self.find_override(path)) {
            Some((toolchain, Some(reason)))
        } else {
            try!(self.find_default()).map(|toolchain| (toolchain, None))
        })
    }

    pub fn list_toolchains(&self) -> Result<Vec<String>> {
        if utils::is_directory(&self.toolchains_dir) {
            let mut toolchains: Vec<_> = try!(utils::read_dir("toolchains", &self.toolchains_dir))
                                         .filter_map(io::Result::ok)
                                         .filter(|e| e.file_type().map(|f| !f.is_file()).unwrap_or(false))
                                         .filter_map(|e| e.file_name().into_string().ok())
                                         .collect();

            utils::toolchain_sort(&mut toolchains);

            Ok(toolchains)
        } else {
            Ok(Vec::new())
        }
    }

    pub fn update_all_channels(&self) -> Result<Vec<(String, Result<UpdateStatus>)>> {
        let toolchains = try!(self.list_toolchains());

        // Convert the toolchain strings to Toolchain values
        let toolchains = toolchains.into_iter();
        let toolchains = toolchains.map(|n| (n.clone(), self.get_toolchain(&n, true)));

        // Filter out toolchains that don't track a release channel
        let toolchains = toolchains.filter(|&(_, ref t)| {
            t.as_ref().map(|t| t.is_tracking()).unwrap_or(false)
        });

        // Update toolchains and collect the results
        let toolchains = toolchains.map(|(n, t)| {
            let t = t.and_then(|t| {
                let t = t.install_from_dist();
                if let Err(ref e) = t {
                    (self.notify_handler)(Notification::NonFatalError(e));
                }
                t
            });

            (n, t)
        });

        Ok(toolchains.collect())
    }

    pub fn check_metadata_version(&self) -> Result<()> {
        try!(utils::assert_is_directory(&self.multirust_dir));

        self.settings_file.with(|s| {
            (self.notify_handler)(Notification::ReadMetadataVersion(&s.version));
            if s.version == DEFAULT_METADATA_VERSION {
                Ok(())
            } else {
                Err(ErrorKind::NeedMetadataUpgrade.into())
            }
        })
    }

    pub fn toolchain_for_dir(&self, path: &Path) -> Result<(Toolchain, Option<OverrideReason>)> {
        self.find_override_toolchain_or_default(path)
            .and_then(|r| r.ok_or("no default toolchain configured".into()))
    }

    pub fn create_command_for_dir(&self, path: &Path, binary: &str) -> Result<Command> {
        let (ref toolchain, _) = try!(self.toolchain_for_dir(path));

        if let Some(cmd) = try!(self.maybe_do_cargo_fallback(toolchain, binary)) {
            Ok(cmd)
        } else {
            toolchain.create_command(binary)
        }
    }

    pub fn create_command_for_toolchain(&self, toolchain: &str, binary: &str) -> Result<Command> {
        let ref toolchain = try!(self.get_toolchain(toolchain, false));

        if let Some(cmd) = try!(self.maybe_do_cargo_fallback(toolchain, binary)) {
            Ok(cmd)
        } else {
            toolchain.create_command(binary)
        }
    }

    // Custom toolchains don't have cargo, so here we detect that situation and
    // try to find a different cargo.
    fn maybe_do_cargo_fallback(&self, toolchain: &Toolchain, binary: &str) -> Result<Option<Command>> {
        if !toolchain.is_custom() {
            return Ok(None);
        }

        if binary != "cargo" && binary != "cargo.exe" {
            return Ok(None);
        }

        let cargo_path = toolchain.path().join("bin/cargo");
        let cargo_exe_path = toolchain.path().join("bin/cargo.exe");

        if cargo_path.exists() || cargo_exe_path.exists() {
            return Ok(None);
        }

        for fallback in &["nightly", "beta", "stable"] {
            let fallback = try!(self.get_toolchain(fallback, false));
            if fallback.exists() {
                let cmd = try!(fallback.create_fallback_command("cargo", toolchain));
                return Ok(Some(cmd));
            }
        }

        Ok(None)
    }

    pub fn doc_path_for_dir(&self, path: &Path, relative: &str) -> Result<PathBuf> {
        let (toolchain, _) = try!(self.toolchain_for_dir(path));
        toolchain.doc_path(relative)
    }

    pub fn open_docs_for_dir(&self, path: &Path, relative: &str) -> Result<()> {
        let (toolchain, _) = try!(self.toolchain_for_dir(path));
        toolchain.open_docs(relative)
    }

    pub fn set_default_host_triple(&self, host_triple: &str) -> Result<()> {
        self.settings_file.with_mut(|s| {
            s.default_host_triple = Some(host_triple.to_owned());
            Ok(())
        })
    }

    pub fn get_default_host_triple(&self) -> Result<dist::TargetTriple> {
        Ok(try!(self.settings_file.with(|s| {
            Ok(s.default_host_triple.as_ref().map(|s| dist::TargetTriple::from_str(&s)))
        })).unwrap_or_else(dist::TargetTriple::from_build))
    }

    pub fn resolve_toolchain(&self, name: &str) -> Result<String> {
        if let Ok(desc) = dist::PartialToolchainDesc::from_str(name) {
            let host = try!(self.get_default_host_triple());
            Ok(desc.resolve(&host).to_string())
        } else {
            Ok(name.to_owned())
        }
    }

    pub fn set_telemetry(&self, telemetry_enabled: bool) -> Result<()> {
        if telemetry_enabled { self.enable_telemetry() } else { self.disable_telemetry() }
    }

    fn enable_telemetry(&self) -> Result<()> {
        try!(self.settings_file.with_mut(|s| {
            s.telemetry = TelemetryMode::On;
            Ok(())
        }));

        let _ = utils::ensure_dir_exists("telemetry", &self.multirust_dir.join("telemetry"),
                                         &|_| ());

        (self.notify_handler)(Notification::SetTelemetry("on"));

        Ok(())
    }

    fn disable_telemetry(&self) -> Result<()> {
        try!(self.settings_file.with_mut(|s| {
            s.telemetry = TelemetryMode::Off;
            Ok(())
        }));

        (self.notify_handler)(Notification::SetTelemetry("off"));

        Ok(())
    }

    pub fn telemetry_enabled(&self) -> Result<bool> {
        Ok(match try!(self.settings_file.with(|s| Ok(s.telemetry))) {
            TelemetryMode::On => true,
            TelemetryMode::Off => false,
        })
    }

    pub fn analyze_telemetry(&self) -> Result<TelemetryAnalysis> {
        let mut t = TelemetryAnalysis::new(self.multirust_dir.join("telemetry"));

        let events = try!(t.import_telemery());
        try!(t.analyze_telemetry_events(&events));

        Ok(t)
    }
}
<|endoftext|>


<commit_before><commit_msg>Load game is working<commit_after><|endoftext|>


<commit_before><commit_msg>added thread example<commit_after>use std::thread;

fn main() {
  let mut thread_vec: Vec<_> = Vec::new();
  let nums = [1, 2];
  let noms = ["gerald", "chriss", "martin", "mike"];

  let mut odds = nums.iter().map(|&x| x * 2 - 1);

  for num in odds {
    let child = thread::spawn(move || {
      println!("{} says hello from a thread!", noms[num]);
    });
    thread_vec.push(child);
  }

  for handle in thread_vec {
        // .unwrap() will propagate a panic from the child thread to the whole program
        // .unwrap() just panics on None/Err(e)
        // And returns the value from Some(x)/Ok(x)

        handle.join().unwrap();
    }
}<|endoftext|>


<commit_before><commit_msg>Fix IdDeserializer::deserialize_ignored_any<commit_after>extern crate ron;
#[macro_use]
extern crate serde;

#[derive(Serialize, Deserialize)]
pub struct ImVec2 {
    pub x: f32,
    pub y: f32,
}

#[derive(Serialize, Deserialize)]
pub struct ImColorsSave {
    pub text: f32,
}

#[derive(Serialize, Deserialize)]
pub struct ImGuiStyleSave {
    pub alpha: f32,
    pub window_padding: ImVec2,
    pub window_min_size: ImVec2,
    pub window_rounding: f32,
    pub window_title_align: ImVec2,
    pub child_window_rounding: f32,
    pub frame_padding: ImVec2,
    pub frame_rounding: f32,
    pub item_spacing: ImVec2,
    pub item_inner_spacing: ImVec2,
    pub touch_extra_padding: ImVec2,
    pub indent_spacing: f32,
    pub columns_min_spacing: f32,
    pub scrollbar_size: f32,
    pub scrollbar_rounding: f32,
    pub grab_min_size: f32,
    pub grab_rounding: f32,
    pub button_text_align: ImVec2,
    pub display_window_padding: ImVec2,
    pub display_safe_area_padding: ImVec2,
    pub anti_aliased_lines: bool,
    pub anti_aliased_shapes: bool,
    pub curve_tessellation_tol: f32,
    pub colors: ImColorsSave,
}

const CONFIG: &str = "(
    alpha: 1.0,
    window_padding: (x: 8, y: 8),
    window_min_size: (x: 32, y: 32),
    window_rounding: 9.0,
    window_title_align: (x: 0.0, y: 0.5),
    child_window_rounding: 0.0,
    frame_padding: (x: 4, y: 3),
    frame_rounding: 0.0,
    item_spacing: (x: 8, y: 4),
    item_inner_spacing: (x: 4, y: 4),
    touch_extra_padding: (x: 0, y: 0),
    indent_spacing: 21.0,
    columns_min_spacing: 6.0,
    scrollbar_size: 16,
    scrollbar_rounding: 9,
    grab_min_size: 10,
    grab_rounding: 0,
    button_text_align: (x: 0.5, y: 0.5),
    display_window_padding: (x: 22, y: 22),
    display_safe_area_padding: (x: 4, y: 4),
    anti_aliased_lines: true,
    anti_aliased_shapes: true,
    curve_tessellation_tol: 1.25,
    colors: (text: 4),

    ignored_field: \"Totally ignored, not causing a panic. Hopefully.\",
)";

#[test]
fn deserialize_big_struct() {
    ron::de::from_str::<ImGuiStyleSave>(CONFIG).unwrap();
}
<|endoftext|>


<commit_before><commit_msg>Dummy main application.<commit_after>#![feature(globs)]
extern crate scirust;
#[cfg(not(test))]
fn main(){
    use scirust::matrix::*;
    use scirust::linalg::*;
    let a = matrix_cw_f64(2,2, [1., 4., 2., 8.]);
    println!("{}", a);
    let b = vector_f64([3.0, 6.0]);
    let result = GaussElimination::new(&a, &b).solve();
    match result {
        Ok(x) => println!("{}", x),
        Err(e) => println!("{}", e),
    }
    let m = matrix_cw_c64(2,2, []);
    println!("{}", m);
}
<|endoftext|>


<commit_before><commit_msg>Fixed a possible divide-by-zero bug in Vector2::nor<commit_after><|endoftext|>


<commit_before><commit_msg>Add get and get_mut methods to SignatureMap.<commit_after><|endoftext|>


<commit_before>extern crate libc;

use std::io;
use std::io::fs;
use std::io::File;
use std::path::Path;
use std::collections::HashMap;

use document::Document;

pub struct Runner;

impl Runner {
    pub fn run(path_string: &str) {
        let base_path      = Path::new(path_string);
        let documents_path = base_path.join("_posts");
        let layout_path    = base_path.join("_layouts");
        let index_path     = base_path.join("index.tpl");
        let build_path     = base_path.join("build");

        println!("Generating site in {}\n", path_string);

        let index     = Runner::parse_document(&index_path);
        let posts     = Runner::parse_documents(&documents_path);
        let post_path = Runner::create_dirs(&build_path);

        Runner::create_files(&build_path, &post_path, &layout_path, index, posts);
    }

    fn parse_documents(path: &Path) -> Vec<Document> {

        let paths = fs::readdir(path);
        let mut documents = vec!();

        if paths.is_ok() {
            for path in paths.unwrap().iter() {
                if path.extension_str().unwrap() != "tpl" {
                    continue;
                }

                documents.push(Runner::parse_document(path));
            }
        } else {
            // TODO panic!
            fail!("Path {} doesn't exist\n", path.display());
        }

        return documents;
    }

    fn parse_document(path: &Path) -> Document {
        let attributes = Runner::extract_attributes(path);
        let content    = Runner::extract_content(path);

        Document::new(
            attributes,
            content,
            path.filestem_str().unwrap().to_string() + ".html",
        )
    }

    fn parse_file(path: &Path) -> String {
        match File::open(path) {
            // TODO handle IOResult
            Ok(mut x) => x.read_to_string().unwrap(),
            // TODO panic!
            Err(e) => fail!("File {} doesn't exist\n", path.display())
        }
    }

    fn create_dirs(build_path: &Path) -> Path {
        let postpath = build_path.join("posts");

        fs::mkdir(build_path, io::USER_RWX);
        fs::mkdir(&postpath, io::USER_RWX);

        // TODO: copy non cobalt relevant folders into /build folder (assets, stylesheets, etc...)

        println!("Directory {} created\n", build_path.display());

        return postpath;
    }

    fn create_files(index_path: &Path, document_path: &Path, layout_path: &Path, index: Document, documents: Vec<Document>) {
        index.create_file(index_path, layout_path);

        for document in documents.iter() {
            document.create_file(document_path, layout_path);
        }
    }

    fn extract_attributes(path: &Path) -> HashMap<String, String> {
        let mut attributes = HashMap::new();
        attributes.insert("name".to_string(), path.filestem_str().unwrap().to_string());

        let content = Runner::parse_file(path);

        if content.as_slice().contains("---") {
            let mut content_splits = content.as_slice().split_str("---");

            let attribute_string = content_splits.nth(0u).unwrap();

            for attribute_line in attribute_string.split_str("\n") {
                if !attribute_line.contains_char(':') {
                    continue;
                }

                let mut attribute_split = attribute_line.split(':');

                // TODO: Refactor, find a better way for doing this
                // .nth() method is consuming the iterator and therefore the 0th index on the second method
                // is in real index 1
                let key   = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();
                let value = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();

                attributes.insert(key, value);
            }
        }

        return attributes;
    }

    fn extract_content(path: &Path) -> String {
        let content = Runner::parse_file(path);

        if content.as_slice().contains("---") {
            let mut content_splits = content.as_slice().split_str("---");

            return content_splits.nth(1u).unwrap().to_string();
        }

        return content;
    }
}
<commit_msg>Shorten parse_documents<commit_after>extern crate libc;

use std::io;
use std::io::fs;
use std::io::File;
use std::path::Path;
use std::collections::HashMap;

use document::Document;

pub struct Runner;

impl Runner {
    pub fn run(path_string: &str) {
        let base_path      = Path::new(path_string);
        let documents_path = base_path.join("_posts");
        let layout_path    = base_path.join("_layouts");
        let index_path     = base_path.join("index.tpl");
        let build_path     = base_path.join("build");

        println!("Generating site in {}\n", path_string);

        let index     = Runner::parse_document(&index_path);
        let posts     = Runner::parse_documents(&documents_path);
        let post_path = Runner::create_dirs(&build_path);

        Runner::create_files(&build_path, &post_path, &layout_path, index, posts);
    }

    fn parse_documents(path: &Path) -> Vec<Document> {
        match fs::readdir(path) {
            Ok(paths) => paths.iter().filter_map( |path|
                    if path.extension_str().unwrap() == "tpl" {
                        Some(Runner::parse_document(path))
                    }else{
                        None
                    }
                ).collect(),
            // TODO panic!
            Err(e) => fail!("Path {} doesn't exist\n", path.display())
        }
    }

    fn parse_document(path: &Path) -> Document {
        let attributes = Runner::extract_attributes(path);
        let content    = Runner::extract_content(path);

        Document::new(
            attributes,
            content,
            path.filestem_str().unwrap().to_string() + ".html",
        )
    }

    fn parse_file(path: &Path) -> String {
        match File::open(path) {
            // TODO handle IOResult
            Ok(mut x) => x.read_to_string().unwrap(),
            // TODO panic!
            Err(e) => fail!("File {} doesn't exist\n", path.display())
        }
    }

    fn create_dirs(build_path: &Path) -> Path {
        let postpath = build_path.join("posts");

        fs::mkdir(build_path, io::USER_RWX);
        fs::mkdir(&postpath, io::USER_RWX);

        // TODO: copy non cobalt relevant folders into /build folder (assets, stylesheets, etc...)

        println!("Directory {} created\n", build_path.display());

        return postpath;
    }

    fn create_files(index_path: &Path, document_path: &Path, layout_path: &Path, index: Document, documents: Vec<Document>) {
        index.create_file(index_path, layout_path);

        for document in documents.iter() {
            document.create_file(document_path, layout_path);
        }
    }

    fn extract_attributes(path: &Path) -> HashMap<String, String> {
        let mut attributes = HashMap::new();
        attributes.insert("name".to_string(), path.filestem_str().unwrap().to_string());

        let content = Runner::parse_file(path);

        if content.as_slice().contains("---") {
            let mut content_splits = content.as_slice().split_str("---");

            let attribute_string = content_splits.nth(0u).unwrap();

            for attribute_line in attribute_string.split_str("\n") {
                if !attribute_line.contains_char(':') {
                    continue;
                }

                let mut attribute_split = attribute_line.split(':');

                // TODO: Refactor, find a better way for doing this
                // .nth() method is consuming the iterator and therefore the 0th index on the second method
                // is in real index 1
                let key   = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();
                let value = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();

                attributes.insert(key, value);
            }
        }

        return attributes;
    }

    fn extract_content(path: &Path) -> String {
        let content = Runner::parse_file(path);

        if content.as_slice().contains("---") {
            let mut content_splits = content.as_slice().split_str("---");

            return content_splits.nth(1u).unwrap().to_string();
        }

        return content;
    }
}
<|endoftext|>


<commit_before><commit_msg>Simple mutability example<commit_after>fn main() {
  let a_vector = @[1,2,3];
  let mut another_vector = @[];
  another_vector = another_vector + a_vector;

  println(fmt!("The first number is %d.", another_vector[0]));
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 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.

//! An implementation of SipHash 2-4.

use prelude::v1::*;

use ptr;
use super::Hasher;

/// An implementation of SipHash 2-4.
///
/// See: http://131002.net/siphash/
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
///
/// Although the SipHash algorithm is considered to be generally strong,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SipHasher {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64, // hash state
    v2: u64,
    v1: u64,
    v3: u64,
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    })
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        let mut state = SipHasher {
            k0: key0,
            k1: key1,
            length: 0,
            v0: 0,
            v1: 0,
            v2: 0,
            v3: 0,
            tail: 0,
            ntail: 0,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.v0 = self.k0 ^ 0x736f6d6570736575;
        self.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.v2 = self.k0 ^ 0x6c7967656e657261;
        self.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.v3 ^= m;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.v3 ^= mi;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut v0 = self.v0;
        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        v3 ^= b;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        v0 ^= b;

        v2 ^= 0xff;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);

        v0 ^ v1 ^ v2 ^ v3
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SipHasher {
    #[inline]
    fn clone(&self) -> SipHasher {
        SipHasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            v0: self.v0,
            v1: self.v1,
            v2: self.v2,
            v3: self.v3,
            tail: self.tail,
            ntail: self.ntail,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Default for SipHasher {
    fn default() -> SipHasher {
        SipHasher::new()
    }
}
<commit_msg>Auto merge of #32564 - frewsxcv:patch-27, r=alexcrichton<commit_after>// Copyright 2012-2015 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.

//! An implementation of SipHash 2-4.

use prelude::v1::*;

use ptr;
use super::Hasher;

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
///
/// Although the SipHash algorithm is considered to be generally strong,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SipHasher {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64, // hash state
    v2: u64,
    v1: u64,
    v3: u64,
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    })
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        let mut state = SipHasher {
            k0: key0,
            k1: key1,
            length: 0,
            v0: 0,
            v1: 0,
            v2: 0,
            v3: 0,
            tail: 0,
            ntail: 0,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.v0 = self.k0 ^ 0x736f6d6570736575;
        self.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.v2 = self.k0 ^ 0x6c7967656e657261;
        self.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.v3 ^= m;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.v3 ^= mi;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut v0 = self.v0;
        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        v3 ^= b;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        v0 ^= b;

        v2 ^= 0xff;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);

        v0 ^ v1 ^ v2 ^ v3
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SipHasher {
    #[inline]
    fn clone(&self) -> SipHasher {
        SipHasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            v0: self.v0,
            v1: self.v1,
            v2: self.v2,
            v3: self.v3,
            tail: self.tail,
            ntail: self.ntail,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Default for SipHasher {
    fn default() -> SipHasher {
        SipHasher::new()
    }
}
<|endoftext|>


<commit_before><commit_msg>update `closure_exchange_malloc`<commit_after><|endoftext|>


<commit_before><commit_msg>Add ID reporting in imag-gps<commit_after><|endoftext|>


<commit_before><commit_msg>Better use of associated types.<commit_after><|endoftext|>


<commit_before><commit_msg>Simplify assignment<commit_after><|endoftext|>


<commit_before><commit_msg>Removed use Async::*, replaced with full path<commit_after><|endoftext|>


<commit_before><commit_msg>Remove deprecated feature `phase` in tests<commit_after><|endoftext|>


<commit_before>// Copyright 2012 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.

// this checks that a pred with a non-bool return
// type is rejected, even if the pred is never used

// pretty-expanded FIXME #23616

fn bad(_a: isize) -> isize { return 37; } //~ ERROR Non-boolean return type

pub fn main() { }
<commit_msg>Rollup merge of #35648 - ahmedcharles:pred, r=alexcrichton<commit_after><|endoftext|>


<commit_before><commit_msg>Extremely simple build step for now<commit_after>fn main() {
    println!("cargo:rustc-flags=-l forestdb");
}
<|endoftext|>


<commit_before><commit_msg>test: Add missing tests for the tutorial<commit_after>extern crate env_logger;
extern crate embed_lang;

use embed_lang::vm::api::Function;
use embed_lang::vm::vm::{RootedThread, Value};
use embed_lang::import::Import;
use embed_lang::Compiler;

fn new_vm() -> RootedThread {
    let vm = ::embed_lang::new_vm();
    let import = vm.get_macros().get("import");
    import.as_ref()
          .and_then(|import| import.downcast_ref::<Import>())
          .expect("Import macro")
          .add_path("..");
    vm
}

#[test]
fn access_field_through_alias() {
    let _ = ::env_logger::init();
    let vm = new_vm();
    Compiler::new()
        .run_expr::<Value>(&vm, "example", " import \"std/prelude.hs\" ")
        .unwrap();
    let mut add: Function<fn (i32, i32) -> i32> = vm.get_global("std.prelude.num_Int.(+)")
        .unwrap();
    let result = add.call(1, 2);
    assert_eq!(result, Ok(3));
}
#[test]
fn call_rust_from_embed_lang() {
    let _ = ::env_logger::init();
    fn factorial(x: i32) -> i32 {
        if x <= 1 { 1 } else { x * factorial(x - 1) }
    }
    let vm = new_vm();
    vm.define_global("factorial", factorial as fn (_) -> _)
        .unwrap();
    let result = Compiler::new()
        .run_expr::<i32>(&vm, "example", "factorial 5")
        .unwrap();
    assert_eq!(result, 120);
}

#[test]
fn use_string_module() {
    let _ = ::env_logger::init();
    let vm = new_vm();
    let result = Compiler::new()
        .run_expr::<String>(&vm, "example", " let string = import \"std/string.hs\" in string.trim \"  Hello world  \t\" ")
        .unwrap();
    assert_eq!(result, "Hello world");
}
<|endoftext|>


<commit_before><commit_msg>Collapse spawn errors where we do the spawn.<commit_after><|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.

// aux-build:issue-13560-1.rs
// aux-build:issue-13560-2.rs
// aux-build:issue-13560-3.rs
// ignore-stage1

// Regression test for issue #13560, the test itself is all in the dependent
// libraries. The fail which previously failed to compile is the one numbered 3.

extern crate "issue-13560-2" as t2;
extern crate "issue-13560-3" as t3;

fn main() {}
<commit_msg>auto merge of #19502 : alexcrichton/rust/issue-19501, r=sfackler<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.

// aux-build:issue-13560-1.rs
// aux-build:issue-13560-2.rs
// aux-build:issue-13560-3.rs
// ignore-pretty FIXME #19501
// ignore-stage1

// Regression test for issue #13560, the test itself is all in the dependent
// libraries. The fail which previously failed to compile is the one numbered 3.

extern crate "issue-13560-2" as t2;
extern crate "issue-13560-3" as t3;

fn main() {}
<|endoftext|>


<commit_before>// Derive the `fmt::Debug` implementation for `Structure`. `Structure`
// is a structure which contains a single `i32`.
#[derive(Debug)]
struct Structure(i32);

// Put a `Structure` inside of the structure `Deep`. Make it printable
// also.
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // Printing with `{:?}` is similar to with `{}`.
    println!("{:?} months in a year.", 12);
    println!("{1:?} {0:?} is the {actor:?} name.",
             "Slater",
             "Christian",
             actor="actor's");

    // `Structure` is printable!
    println!("Now {:?} will print!", Structure(3));

    // The problem with `derive` is there is no control over how
    // the results look. What if I was this to just show a `7`?
    println!("Now {:?} will print!", Deep(Structure(7)));
}
<commit_msg>Fix the sentence in the comment - was to want<commit_after>// Derive the `fmt::Debug` implementation for `Structure`. `Structure`
// is a structure which contains a single `i32`.
#[derive(Debug)]
struct Structure(i32);

// Put a `Structure` inside of the structure `Deep`. Make it printable
// also.
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // Printing with `{:?}` is similar to with `{}`.
    println!("{:?} months in a year.", 12);
    println!("{1:?} {0:?} is the {actor:?} name.",
             "Slater",
             "Christian",
             actor="actor's");

    // `Structure` is printable!
    println!("Now {:?} will print!", Structure(3));

    // The problem with `derive` is there is no control over how
    // the results look. What if I want this to just show a `7`?
    println!("Now {:?} will print!", Deep(Structure(7)));
}
<|endoftext|>


<commit_before><commit_msg>Create screenshot-asynchronous example.<commit_after>#![feature(box_syntax)]

#[macro_use]
extern crate glium;
extern crate image;

use std::path::Path;
use std::thread;

use glium::glutin;
use glium::index::PrimitiveType;

mod screenshot {
    use std::collections::VecDeque;
    use std::vec::Vec;
    use std::borrow::Cow;

    use glium;
    use glium::Surface;

    // Container that holds image data as vector of (u8, u8, u8, u8).
    // This is used to take data from PixelBuffer and move it to another thread
    // with minimum conversions done on main thread.
    pub struct RGBAImageData {
        pub data: Vec<(u8, u8, u8, u8)>,
        pub width: u32,
        pub height: u32,
    }

    impl glium::texture::Texture2dDataSink<(u8, u8, u8, u8)> for RGBAImageData {
        fn from_raw(data: Cow<[(u8, u8, u8, u8)]>, width: u32, height: u32) -> Self {
            RGBAImageData {
                data: data.into_owned(),
                width: width,
                height: height,
            }
        }
    }

    struct AsyncScreenshotTask {
        pub target_frame: u64,
        pub pixel_buffer: glium::texture::pixel_buffer::PixelBuffer<(u8, u8, u8, u8)>,
    }

    impl AsyncScreenshotTask {
        fn new(facade: &glium::backend::Facade, target_frame: u64) -> Self {
            // Get information about current framebuffer
            let dimensions = facade.get_context().get_framebuffer_dimensions();
            let rect = glium::Rect {
                left: 0,
                bottom: 0,
                width: dimensions.0,
                height: dimensions.1,
            };
            let blit_target = glium::BlitTarget {
                left: 0,
                bottom: 0,
                width: dimensions.0 as i32,
                height: dimensions.1 as i32,
            };

            // Create temporary texture and blit the front buffer to it
            let texture = glium::texture::Texture2d::empty(facade, dimensions.0, dimensions.1)
                .unwrap();
            let framebuffer = glium::framebuffer::SimpleFrameBuffer::new(facade, &texture).unwrap();
            framebuffer.blit_from_frame(&rect,
                                        &blit_target,
                                        glium::uniforms::MagnifySamplerFilter::Nearest);

            // Read the texture into new pixel buffer
            let pixel_buffer = texture.read_to_pixel_buffer();

            AsyncScreenshotTask {
                target_frame: target_frame,
                pixel_buffer: pixel_buffer,
            }
        }

        fn read_image_data(self) -> RGBAImageData {
            self.pixel_buffer.read_as_texture_2d().unwrap()
        }
    }

    pub struct ScreenshotIterator<'a>(&'a mut AsyncScreenshotTaker);

    impl<'a> Iterator for ScreenshotIterator<'a> {
        type Item = RGBAImageData;

        fn next(&mut self) -> Option<RGBAImageData> {
            if self.0.screenshot_tasks.front().map(|task| task.target_frame) == Some(self.0.frame) {
                let task = self.0.screenshot_tasks.pop_front().unwrap();
                Some(task.read_image_data())
            } else {
                None
            }
        }
    }

    pub struct AsyncScreenshotTaker {
        screenshot_delay: u64,
        frame: u64,
        screenshot_tasks: VecDeque<AsyncScreenshotTask>,
    }

    impl AsyncScreenshotTaker {
        pub fn new(screenshot_delay: u64) -> Self {
            AsyncScreenshotTaker {
                screenshot_delay: screenshot_delay,
                frame: 0,
                screenshot_tasks: VecDeque::new(),
            }
        }

        pub fn next_frame(&mut self) {
            self.frame += 1;
        }

        pub fn pickup_screenshots(&mut self) -> ScreenshotIterator {
            ScreenshotIterator(self)
        }

        pub fn take_screenshot(&mut self, facade: &glium::backend::Facade) {
            self.screenshot_tasks
                .push_back(AsyncScreenshotTask::new(facade, self.frame + self.screenshot_delay));
        }
    }
}

fn main() {
    use glium::{DisplayBuild, Surface};

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_title("Press S to take screenshot")
        .build_glium()
        .unwrap();

    // building the vertex buffer, which contains all the vertices that we will draw
    let vertex_buffer = {
        #[derive(Copy, Clone)]
        struct Vertex {
            position: [f32; 2],
            color: [f32; 3],
        }

        implement_vertex!(Vertex, position, color);

        glium::VertexBuffer::new(&display,
                                 &[Vertex {
                                       position: [-0.5, -0.5],
                                       color: [0.0, 1.0, 0.0],
                                   },
                                   Vertex {
                                       position: [0.0, 0.5],
                                       color: [0.0, 0.0, 1.0],
                                   },
                                   Vertex {
                                       position: [0.5, -0.5],
                                       color: [1.0, 0.0, 0.0],
                                   }])
            .unwrap()
    };

    // building the index buffer
    let index_buffer =
        glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &[0u16, 1, 2]).unwrap();

    // compiling shaders and linking them together
    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 matrix;

                in vec2 position;
                in vec3 color;

                out vec3 vColor;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0) * matrix;
                    vColor = color;
                }
            ",

            fragment: "
                #version 140
                in vec3 vColor;
                out vec4 f_color;

                void main() {
                    f_color = vec4(vColor, 1.0);
                }
            "
        },

        110 => {
            vertex: "
                #version 110

                uniform mat4 matrix;

                attribute vec2 position;
                attribute vec3 color;

                varying vec3 vColor;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0) * matrix;
                    vColor = color;
                }
            ",

            fragment: "
                #version 110
                varying vec3 vColor;

                void main() {
                    gl_FragColor = vec4(vColor, 1.0);
                }
            ",
        },
    )
        .unwrap();

    // drawing once

    // building the uniforms
    let uniforms = uniform! {
        matrix: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.0, 0.0, 0.0, 1.0f32]
        ]
    };

    // The parameter sets the amount of frames between requesting the image
    // transfer and picking it up. If the value is too small, the main thread
    // will block waiting for the image to finish transfering. Tune it based on
    // your requirements.
    let mut screenshot_taker = screenshot::AsyncScreenshotTaker::new(5);

    loop {
        // Tell Screenshot Taker to count next frame
        screenshot_taker.next_frame();

        // drawing a frame
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.draw(&vertex_buffer,
                  &index_buffer,
                  &program,
                  &uniforms,
                  &Default::default())
            .unwrap();

        // React to events
        for event in display.poll_events() {
            use glium::glutin::Event::*;
            use glium::glutin::ElementState::*;
            use glium::glutin::VirtualKeyCode::*;

            match event {
                Closed => return,

                // Take screenshot and queue it's delivery
                KeyboardInput(Pressed, _, Some(S)) => screenshot_taker.take_screenshot(&display),

                _ => {}
            }
        }

        // Pick up screenshots that are ready this frame
        for image_data in screenshot_taker.pickup_screenshots() {
            // Process and write the image in separate thread to not block the rendering thread.
            thread::spawn(move || {
                // Convert (u8, u8, u8, u8) given by glium's PixelBuffer to flat u8 required by
                // image's ImageBuffer.
                let pixels = {
                    let mut v = Vec::with_capacity(image_data.data.len() * 4);
                    for (a, b, c, d) in image_data.data {
                        v.push(a);
                        v.push(b);
                        v.push(c);
                        v.push(d);
                    }
                    v
                };

                // Create ImageBuffer
                let image_buffer =
                    image::ImageBuffer::from_raw(image_data.width, image_data.height, pixels)
                        .unwrap();

                // Save the screenshot to file
                let image = image::DynamicImage::ImageRgba8(image_buffer).flipv();
                let mut output = std::fs::File::create(&Path::new("glium-example-screenshot.png"))
                    .unwrap();
                image.save(&mut output, image::ImageFormat::PNG).unwrap();
            });
        }

        target.finish().unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>start implementing command line utility that prints TC<commit_after>extern crate tcc;
extern crate time;

fn main() {
    let ts = time::get_time();
    let t = ts.sec as f64 + 1.0e-9*(ts.nsec as f64);
    println!("{}",t);
}
<|endoftext|>


<commit_before><commit_msg>add table<commit_after><|endoftext|>


<commit_before><commit_msg>Remove small old code<commit_after><|endoftext|>


<commit_before>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use utility::to_u32;

pub fn frame_parser(input: &[u8], channels: u8) -> IResult<&[u8], Frame> {
  chain!(input,
    frame_header: header ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  )
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

named!(header <&[u8], Header>,
  chain!(
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)             = tuple0;
      let (channel_assignment, bits_per_sample) = tuple1;

      let block_size = match block_byte {
        0b0000          => 0,
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => 0,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        0b1111 => 0,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  )
);

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Add actual bits_per_sample numbers<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use utility::to_u32;

pub fn frame_parser(input: &[u8], channels: u8) -> IResult<&[u8], Frame> {
  chain!(input,
    frame_header: header ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  )
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

named!(header <&[u8], Header>,
  chain!(
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)       = tuple0;
      let (channel_assignment, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0000          => 0,
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => 0,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        0b1111 => 0,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => 0,
        0b0001 => 8,
        0b0010 => 12,
        0b0011 => 0,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        0b0111 => 0,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  )
);

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/**
 * Force-increment the reference count on a shared box. If used
 * carelessly, this can leak the box.
 */
#[inline]
pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::{bump_box_refcount, transmute};
    use raw;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_bump_managed_refcount() {
        unsafe {
            let managed = @~"box box box";      // refcount 1
            bump_box_refcount(managed);     // refcount 2
            let ptr: *int = transmute(managed); // refcount 2
            let _box1: @~str = ::cast::transmute_copy(&ptr);
            let _box2: @~str = ::cast::transmute_copy(&ptr);
            assert!(*_box1 == ~"box box box");
            assert!(*_box2 == ~"box box box");
            // Will destroy _box1 and _box2. Without the bump, this would
            // use-after-free. With too many bumps, it would leak.
        }
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(~[76u8], transmute(~"L"));
        }
    }
}
<commit_msg>fix copyright message based on `make check`<commit_after>// Copyright 2012-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.

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/**
 * Force-increment the reference count on a shared box. If used
 * carelessly, this can leak the box.
 */
#[inline]
pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::{bump_box_refcount, transmute};
    use raw;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_bump_managed_refcount() {
        unsafe {
            let managed = @~"box box box";      // refcount 1
            bump_box_refcount(managed);     // refcount 2
            let ptr: *int = transmute(managed); // refcount 2
            let _box1: @~str = ::cast::transmute_copy(&ptr);
            let _box2: @~str = ::cast::transmute_copy(&ptr);
            assert!(*_box1 == ~"box box box");
            assert!(*_box2 == ~"box box box");
            // Will destroy _box1 and _box2. Without the bump, this would
            // use-after-free. With too many bumps, it would leak.
        }
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(~[76u8], transmute(~"L"));
        }
    }
}
<|endoftext|>