<commit_before>use std::error;
use std::path::{Path, PathBuf};
use std::fmt::{self, Display};
use std::io;
use temp;
use walkdir;
use toml;
use multirust_utils;
use multirust_utils::notify::{self, NotificationLevel, Notifyable};
use manifest::Component;
use dist::TargetTriple;

#[derive(Debug)]
pub enum Notification<'a> {
    Utils(multirust_utils::Notification<'a>),
    Temp(temp::Notification<'a>),

    Extracting(&'a Path, &'a Path),
    ComponentAlreadyInstalled(&'a Component),
    CantReadUpdateHash(&'a Path),
    NoUpdateHash(&'a Path),
    ChecksumValid(&'a str),
    SignatureValid(&'a str),
    RollingBack,
    ExtensionNotInstalled(&'a Component),
    NonFatalError(&'a Error),
    MissingInstalledComponent(&'a str),
    DownloadingComponent(&'a str, &'a TargetTriple, &'a TargetTriple),
    InstallingComponent(&'a str, &'a TargetTriple, &'a TargetTriple),
    DownloadingManifest(&'a str),
    DownloadingLegacyManifest,
}

#[derive(Debug)]
pub enum Error {
    Utils(multirust_utils::Error),
    Temp(temp::Error),

    InvalidFileExtension,
    InvalidInstaller,
    InvalidTargetTriple(String),
    InvalidToolchainName(String),
    InvalidCustomToolchainName(String),
    NotInstalledHere,
    UnsupportedHost(String),
    ChecksumFailed {
        url: String,
        expected: String,
        calculated: String,
    },
    ComponentConflict {
        name: String,
        path: PathBuf,
    },
    ComponentMissingFile {
        name: String,
        path: PathBuf,
    },
    ComponentMissingDir {
        name: String,
        path: PathBuf,
    },
    CorruptComponent(String),
    ExtractingPackage(io::Error),
    ExtensionNotFound(Component),
    InvalidChangeSet,
    NoGPG,
    BadInstallerVersion(String),
    BadInstalledMetadataVersion(String),
    ComponentDirPermissionsFailed(walkdir::Error),
    ComponentFilePermissionsFailed(io::Error),
    ComponentDownloadFailed(Component, multirust_utils::Error),
    ObsoleteDistManifest,
    Parsing(Vec<toml::ParserError>),
    MissingKey(String),
    ExpectedType(&'static str, String),
    PackageNotFound(String),
    TargetNotFound(TargetTriple),
    MissingRoot,
    UnsupportedVersion(String),
    MissingPackageForComponent(Component),
    RequestedComponentsUnavailable(Vec<Component>),
    NoManifestFound(String, Box<Error>),
}

pub type Result<T> = ::std::result::Result<T, Error>;
pub type NotifyHandler<'a> = notify::NotifyHandler<'a, for<'b> Notifyable<Notification<'b>>>;
pub type SharedNotifyHandler =
    notify::SharedNotifyHandler<for<'b> Notifyable<Notification<'b>>>;

extend_error!(Error: temp::Error, e => Error::Temp(e));
extend_error!(Error: multirust_utils::Error, e => Error::Utils(e));

extend_notification!(Notification: multirust_utils::Notification, n => Notification::Utils(n));
extend_notification!(Notification: temp::Notification, n => Notification::Temp(n));

impl<'a> Notification<'a> {
    pub fn level(&self) -> NotificationLevel {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.level(),
            Utils(ref n) => n.level(),
            ChecksumValid(_) | NoUpdateHash(_) |
            DownloadingLegacyManifest  => NotificationLevel::Verbose,
            Extracting(_, _) | SignatureValid(_)  |
            DownloadingComponent(_, _, _) |
            InstallingComponent(_, _, _) |
            ComponentAlreadyInstalled(_)  |
            RollingBack | DownloadingManifest(_) => NotificationLevel::Info,
            CantReadUpdateHash(_) | ExtensionNotInstalled(_) |
            MissingInstalledComponent(_) => NotificationLevel::Warn,
            NonFatalError(_) => NotificationLevel::Error,
        }
    }
}

impl<'a> Display for Notification<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.fmt(f),
            Utils(ref n) => n.fmt(f),
            Extracting(_, _) => write!(f, "extracting..."),
            ComponentAlreadyInstalled(ref c) => {
                write!(f, "component '{}' for target '{}' is up to date",
                       c.pkg, c.target)
            }
            CantReadUpdateHash(path) => {
                write!(f,
                       "can't read update hash file: '{}', can't skip update...",
                       path.display())
            }
            NoUpdateHash(path) => write!(f, "no update hash at: '{}'", path.display()),
            ChecksumValid(_) => write!(f, "checksum passed"),
            SignatureValid(_) => write!(f, "signature valid"),
            RollingBack => write!(f, "rolling back changes"),
            ExtensionNotInstalled(c) => {
                write!(f, "extension '{}-{}' was not installed", c.pkg, c.target)
            }
            NonFatalError(e) => write!(f, "{}", e),
            MissingInstalledComponent(c) => write!(f, "during uninstall component {} was not found", c),
            DownloadingComponent(c, h, t) => {
                if h == t {
                    write!(f, "downloading component '{}'", c)
                } else {
                    write!(f, "downloading component '{}' for '{}'", c, t)
                }
            }
            InstallingComponent(c, h, t) => {
                if h == t {
                    write!(f, "installing component '{}'", c)
                } else {
                    write!(f, "installing component '{}' for '{}'", c, t)
                }
            }
            DownloadingManifest(t) => write!(f, "syncing channel updates for '{}'", t),
            DownloadingLegacyManifest => write!(f, "manifest not found. trying legacy manifest"),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            Utils(ref e) => error::Error::description(e),
            Temp(ref e) => error::Error::description(e),
            InvalidFileExtension => "invalid file extension",
            InvalidInstaller => "invalid installer",
            InvalidTargetTriple(_) => "invalid target triple",
            InvalidToolchainName(_) => "invalid toolchain name",
            InvalidCustomToolchainName(_) => "invalid custom toolchain name",
            NotInstalledHere => "not installed here",
            UnsupportedHost(_) => "binary package not provided for host",
            ChecksumFailed {..} => "checksum failed",
            ComponentConflict {..} => "conflicting component",
            ComponentMissingFile {..} => "missing file in component",
            ComponentMissingDir {..} => "missing directory in component",
            CorruptComponent(_) => "corrupt component manifest",
            ExtractingPackage(_) => "failed to extract package",
            ExtensionNotFound(_) => "could not find extension",
            InvalidChangeSet => "invalid change-set",
            NoGPG => "could not find 'gpg' on PATH",
            BadInstallerVersion(_) => "unsupported installer version",
            BadInstalledMetadataVersion(_) => "unsupported metadata version in existing installation",
            ComponentDirPermissionsFailed(_) => "I/O error walking directory during install",
            ComponentFilePermissionsFailed(_) => "error setting file permissions during install",
            ComponentDownloadFailed(_, _) => "component download failed",
            ObsoleteDistManifest => "the server unexpectedly provided an obsolete version of the distribution manifest",
            Parsing(_) => "error parsing manifest",
            MissingKey(_) => "missing key",
            ExpectedType(_, _) => "expected type",
            PackageNotFound(_) => "package not found",
            TargetNotFound(_) => "target not found",
            MissingRoot => "manifest has no root package",
            UnsupportedVersion(_) => "unsupported manifest version",
            MissingPackageForComponent(_) => "missing package for component",
            RequestedComponentsUnavailable(_) => "some requested components are unavailable to download",
            NoManifestFound(_, _) => "no release found",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        use self::Error::*;
        match *self {
            Utils(ref e) => Some(e),
            Temp(ref e) => Some(e),
            ComponentFilePermissionsFailed(ref e) => Some(e),
            ComponentDirPermissionsFailed(ref e) => Some(e),
            ExtractingPackage(ref e) => Some(e),
            ComponentDownloadFailed(_, ref e) => Some(e),
            NoManifestFound(_, ref e) => Some(e),
            InvalidFileExtension |
            InvalidInstaller |
            InvalidTargetTriple(_) |
            InvalidToolchainName(_) |
            InvalidCustomToolchainName(_) |
            NotInstalledHere |
            UnsupportedHost(_) |
            ChecksumFailed {..} |
            ComponentConflict {..} |
            ComponentMissingFile {..} |
            ComponentMissingDir {..} |
            CorruptComponent(_) |
            ExtensionNotFound(_) |
            InvalidChangeSet |
            NoGPG |
            BadInstallerVersion(_) |
            BadInstalledMetadataVersion(_) |
            ObsoleteDistManifest |
            Parsing(_) |
            MissingKey(_) |
            ExpectedType(_, _) |
            PackageNotFound(_) |
            TargetNotFound(_) |
            MissingRoot |
            UnsupportedVersion(_) |
            MissingPackageForComponent(_) |
            RequestedComponentsUnavailable(_) => None
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        use self::Error::*;
        match *self {
            Temp(ref n) => n.fmt(f),
            Utils(ref n) => n.fmt(f),

            InvalidFileExtension => write!(f, "invalid file extension"),
            InvalidInstaller => write!(f, "invalid installer"),
            InvalidTargetTriple(ref s) => write!(f, "invalid target triple: '{}'", s),
            InvalidToolchainName(ref s) => write!(f, "invalid toolchain name: '{}'", s),
            InvalidCustomToolchainName(ref s) => write!(f, "invalid custom toolchain name: '{}'", s),
            NotInstalledHere => write!(f, "not installed here"),
            UnsupportedHost(ref spec) => {
                write!(f, "a binary package was not provided for: '{}'", spec)
            }
            ChecksumFailed { url: _, ref expected, ref calculated } => {
                write!(f,
                       "checksum failed, expected: '{}', calculated: '{}'",
                       expected,
                       calculated)
            }
            ComponentConflict { ref name, ref path } => {
                write!(f,
                       "failed to install component: '{}', detected conflict: '{:?}'",
                       name,
                       path)
            }
            ComponentMissingFile { ref name, ref path } => {
                write!(f,
                       "failure removing component '{}', file does not exist: '{:?}'",
                       name,
                       path)
            }
            ComponentMissingDir { ref name, ref path } => {
                write!(f,
                       "failure removing component '{}', directory does not exist: '{:?}'",
                       name,
                       path)
            }
            CorruptComponent(ref name) => write!(f, "component manifest for '{}' is corrupt", name),
            ExtractingPackage(ref error) => write!(f, "failed to extract package: {}", error),
            ExtensionNotFound(ref c) => {
                write!(f, "could not find extension: '{}-{}'", c.pkg, c.target)
            }
            InvalidChangeSet => write!(f, "invalid change-set"),
            NoGPG => {
                write!(f,
                       "could not find 'gpg': ensure it is on PATH or disable GPG verification")
            }
            BadInstallerVersion(ref v) => write!(f, "unsupported installer version: {}", v),
            BadInstalledMetadataVersion(ref v) => {
                write!(f,
                       "unsupported metadata version in existing installation: {}",
                       v)
            }
            ComponentDirPermissionsFailed(ref e) => {
                write!(f, "I/O error walking directory during install: {}", e)
            }
            ComponentFilePermissionsFailed(ref e) => {
                write!(f, "error setting file permissions during install: {}", e)
            }
            ComponentDownloadFailed(ref component, ref e) => {
                write!(f, "component download failed for {}-{}: {}", component.pkg, component.target, e)
            }
            ObsoleteDistManifest => {
                write!(f, "the server unexpectedly provided an obsolete version of the distribution manifest")
            },
            Parsing(ref n) => {
                for e in n {
                    try!(e.fmt(f));
                    try!(writeln!(f, ""));
                }
                Ok(())
            }
            MissingKey(ref n) => write!(f, "missing key: '{}'", n),
            ExpectedType(ref t, ref n) => write!(f, "expected type: '{}' for '{}'", t, n),
            PackageNotFound(ref n) => write!(f, "package not found: '{}'", n),
            TargetNotFound(ref n) => write!(f, "target not found: '{}'", n),
            MissingRoot => write!(f, "manifest has no root package"),
            UnsupportedVersion(ref v) => write!(f, "manifest version '{}' is not supported", v),
            MissingPackageForComponent(ref c) => write!(f,"manifest missing package for component {}", c.name()),
            RequestedComponentsUnavailable(ref cs) => {
                assert!(!cs.is_empty());
                if cs.len() == 1 {
                    write!(f, "component '{}' for '{}' is unavailable for download",
                           cs[0].pkg, cs[0].target)
                } else {
                    use itertools::Itertools;
                    let same_target = cs.iter().all(|c| c.target == cs[0].target);
                    if same_target {
                        let mut cs_strs = cs.iter().map(|c| format!("'{}'", c.pkg));
                        let cs_str = cs_strs.join(", ");
                        write!(f, "some components unavailable for download: {}",
                               cs_str)
                    } else {
                        let mut cs_strs = cs.iter().map(|c| format!("'{}' for '{}'", c.pkg, c.target));
                        let cs_str = cs_strs.join(", ");
                        write!(f, "some components unavailable for download: {}",
                               cs_str)
                    }
                }
            }
            NoManifestFound(ref ch, ref e) => {
                use multirust_utils::raw::DownloadError;
                use hyper::status::StatusCode::NotFound;
                match **e {
                    Error::Utils(multirust_utils::Error::DownloadingFile {
                        error: DownloadError::Status(NotFound),
                        ..
                    }) => {
                        write!(f, "no release found for '{}'", ch)
                    }
                    _ => {
                        // FIXME: Need handle other common cases nicely,
                        // like dns lookup, network unavailable.
                        write!(f, "failed to download manifest for '{}': {}", ch, e)
                    }
                }
            }
        }
    }
}
<commit_msg>Clarify that bad manifest is not user's fault<commit_after>use std::error;
use std::path::{Path, PathBuf};
use std::fmt::{self, Display};
use std::io;
use temp;
use walkdir;
use toml;
use multirust_utils;
use multirust_utils::notify::{self, NotificationLevel, Notifyable};
use manifest::Component;
use dist::TargetTriple;

#[derive(Debug)]
pub enum Notification<'a> {
    Utils(multirust_utils::Notification<'a>),
    Temp(temp::Notification<'a>),

    Extracting(&'a Path, &'a Path),
    ComponentAlreadyInstalled(&'a Component),
    CantReadUpdateHash(&'a Path),
    NoUpdateHash(&'a Path),
    ChecksumValid(&'a str),
    SignatureValid(&'a str),
    RollingBack,
    ExtensionNotInstalled(&'a Component),
    NonFatalError(&'a Error),
    MissingInstalledComponent(&'a str),
    DownloadingComponent(&'a str, &'a TargetTriple, &'a TargetTriple),
    InstallingComponent(&'a str, &'a TargetTriple, &'a TargetTriple),
    DownloadingManifest(&'a str),
    DownloadingLegacyManifest,
}

#[derive(Debug)]
pub enum Error {
    Utils(multirust_utils::Error),
    Temp(temp::Error),

    InvalidFileExtension,
    InvalidInstaller,
    InvalidTargetTriple(String),
    InvalidToolchainName(String),
    InvalidCustomToolchainName(String),
    NotInstalledHere,
    UnsupportedHost(String),
    ChecksumFailed {
        url: String,
        expected: String,
        calculated: String,
    },
    ComponentConflict {
        name: String,
        path: PathBuf,
    },
    ComponentMissingFile {
        name: String,
        path: PathBuf,
    },
    ComponentMissingDir {
        name: String,
        path: PathBuf,
    },
    CorruptComponent(String),
    ExtractingPackage(io::Error),
    ExtensionNotFound(Component),
    InvalidChangeSet,
    NoGPG,
    BadInstallerVersion(String),
    BadInstalledMetadataVersion(String),
    ComponentDirPermissionsFailed(walkdir::Error),
    ComponentFilePermissionsFailed(io::Error),
    ComponentDownloadFailed(Component, multirust_utils::Error),
    ObsoleteDistManifest,
    Parsing(Vec<toml::ParserError>),
    MissingKey(String),
    ExpectedType(&'static str, String),
    PackageNotFound(String),
    TargetNotFound(TargetTriple),
    MissingRoot,
    UnsupportedVersion(String),
    MissingPackageForComponent(Component),
    RequestedComponentsUnavailable(Vec<Component>),
    NoManifestFound(String, Box<Error>),
}

pub type Result<T> = ::std::result::Result<T, Error>;
pub type NotifyHandler<'a> = notify::NotifyHandler<'a, for<'b> Notifyable<Notification<'b>>>;
pub type SharedNotifyHandler =
    notify::SharedNotifyHandler<for<'b> Notifyable<Notification<'b>>>;

extend_error!(Error: temp::Error, e => Error::Temp(e));
extend_error!(Error: multirust_utils::Error, e => Error::Utils(e));

extend_notification!(Notification: multirust_utils::Notification, n => Notification::Utils(n));
extend_notification!(Notification: temp::Notification, n => Notification::Temp(n));

impl<'a> Notification<'a> {
    pub fn level(&self) -> NotificationLevel {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.level(),
            Utils(ref n) => n.level(),
            ChecksumValid(_) | NoUpdateHash(_) |
            DownloadingLegacyManifest  => NotificationLevel::Verbose,
            Extracting(_, _) | SignatureValid(_)  |
            DownloadingComponent(_, _, _) |
            InstallingComponent(_, _, _) |
            ComponentAlreadyInstalled(_)  |
            RollingBack | DownloadingManifest(_) => NotificationLevel::Info,
            CantReadUpdateHash(_) | ExtensionNotInstalled(_) |
            MissingInstalledComponent(_) => NotificationLevel::Warn,
            NonFatalError(_) => NotificationLevel::Error,
        }
    }
}

impl<'a> Display for Notification<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.fmt(f),
            Utils(ref n) => n.fmt(f),
            Extracting(_, _) => write!(f, "extracting..."),
            ComponentAlreadyInstalled(ref c) => {
                write!(f, "component '{}' for target '{}' is up to date",
                       c.pkg, c.target)
            }
            CantReadUpdateHash(path) => {
                write!(f,
                       "can't read update hash file: '{}', can't skip update...",
                       path.display())
            }
            NoUpdateHash(path) => write!(f, "no update hash at: '{}'", path.display()),
            ChecksumValid(_) => write!(f, "checksum passed"),
            SignatureValid(_) => write!(f, "signature valid"),
            RollingBack => write!(f, "rolling back changes"),
            ExtensionNotInstalled(c) => {
                write!(f, "extension '{}-{}' was not installed", c.pkg, c.target)
            }
            NonFatalError(e) => write!(f, "{}", e),
            MissingInstalledComponent(c) => write!(f, "during uninstall component {} was not found", c),
            DownloadingComponent(c, h, t) => {
                if h == t {
                    write!(f, "downloading component '{}'", c)
                } else {
                    write!(f, "downloading component '{}' for '{}'", c, t)
                }
            }
            InstallingComponent(c, h, t) => {
                if h == t {
                    write!(f, "installing component '{}'", c)
                } else {
                    write!(f, "installing component '{}' for '{}'", c, t)
                }
            }
            DownloadingManifest(t) => write!(f, "syncing channel updates for '{}'", t),
            DownloadingLegacyManifest => write!(f, "manifest not found. trying legacy manifest"),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            Utils(ref e) => error::Error::description(e),
            Temp(ref e) => error::Error::description(e),
            InvalidFileExtension => "invalid file extension",
            InvalidInstaller => "invalid installer",
            InvalidTargetTriple(_) => "invalid target triple",
            InvalidToolchainName(_) => "invalid toolchain name",
            InvalidCustomToolchainName(_) => "invalid custom toolchain name",
            NotInstalledHere => "not installed here",
            UnsupportedHost(_) => "binary package not provided for host",
            ChecksumFailed {..} => "checksum failed",
            ComponentConflict {..} => "conflicting component",
            ComponentMissingFile {..} => "missing file in component",
            ComponentMissingDir {..} => "missing directory in component",
            CorruptComponent(_) => "corrupt component manifest",
            ExtractingPackage(_) => "failed to extract package",
            ExtensionNotFound(_) => "could not find extension",
            InvalidChangeSet => "invalid change-set",
            NoGPG => "could not find 'gpg' on PATH",
            BadInstallerVersion(_) => "unsupported installer version",
            BadInstalledMetadataVersion(_) => "unsupported metadata version in existing installation",
            ComponentDirPermissionsFailed(_) => "I/O error walking directory during install",
            ComponentFilePermissionsFailed(_) => "error setting file permissions during install",
            ComponentDownloadFailed(_, _) => "component download failed",
            ObsoleteDistManifest => "the server unexpectedly provided an obsolete version of the distribution manifest",
            Parsing(_) => "error parsing manifest",
            MissingKey(_) => "missing key",
            ExpectedType(_, _) => "expected type",
            PackageNotFound(_) => "package not found",
            TargetNotFound(_) => "target not found",
            MissingRoot => "manifest has no root package",
            UnsupportedVersion(_) => "unsupported manifest version",
            MissingPackageForComponent(_) => "missing package for component",
            RequestedComponentsUnavailable(_) => "some requested components are unavailable to download",
            NoManifestFound(_, _) => "no release found",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        use self::Error::*;
        match *self {
            Utils(ref e) => Some(e),
            Temp(ref e) => Some(e),
            ComponentFilePermissionsFailed(ref e) => Some(e),
            ComponentDirPermissionsFailed(ref e) => Some(e),
            ExtractingPackage(ref e) => Some(e),
            ComponentDownloadFailed(_, ref e) => Some(e),
            NoManifestFound(_, ref e) => Some(e),
            InvalidFileExtension |
            InvalidInstaller |
            InvalidTargetTriple(_) |
            InvalidToolchainName(_) |
            InvalidCustomToolchainName(_) |
            NotInstalledHere |
            UnsupportedHost(_) |
            ChecksumFailed {..} |
            ComponentConflict {..} |
            ComponentMissingFile {..} |
            ComponentMissingDir {..} |
            CorruptComponent(_) |
            ExtensionNotFound(_) |
            InvalidChangeSet |
            NoGPG |
            BadInstallerVersion(_) |
            BadInstalledMetadataVersion(_) |
            ObsoleteDistManifest |
            Parsing(_) |
            MissingKey(_) |
            ExpectedType(_, _) |
            PackageNotFound(_) |
            TargetNotFound(_) |
            MissingRoot |
            UnsupportedVersion(_) |
            MissingPackageForComponent(_) |
            RequestedComponentsUnavailable(_) => None
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        use self::Error::*;
        match *self {
            Temp(ref n) => n.fmt(f),
            Utils(ref n) => n.fmt(f),

            InvalidFileExtension => write!(f, "invalid file extension"),
            InvalidInstaller => write!(f, "invalid installer"),
            InvalidTargetTriple(ref s) => write!(f, "invalid target triple: '{}'", s),
            InvalidToolchainName(ref s) => write!(f, "invalid toolchain name: '{}'", s),
            InvalidCustomToolchainName(ref s) => write!(f, "invalid custom toolchain name: '{}'", s),
            NotInstalledHere => write!(f, "not installed here"),
            UnsupportedHost(ref spec) => {
                write!(f, "a binary package was not provided for: '{}'", spec)
            }
            ChecksumFailed { url: _, ref expected, ref calculated } => {
                write!(f,
                       "checksum failed, expected: '{}', calculated: '{}'",
                       expected,
                       calculated)
            }
            ComponentConflict { ref name, ref path } => {
                write!(f,
                       "failed to install component: '{}', detected conflict: '{:?}'",
                       name,
                       path)
            }
            ComponentMissingFile { ref name, ref path } => {
                write!(f,
                       "failure removing component '{}', file does not exist: '{:?}'",
                       name,
                       path)
            }
            ComponentMissingDir { ref name, ref path } => {
                write!(f,
                       "failure removing component '{}', directory does not exist: '{:?}'",
                       name,
                       path)
            }
            CorruptComponent(ref name) => write!(f, "component manifest for '{}' is corrupt", name),
            ExtractingPackage(ref error) => write!(f, "failed to extract package: {}", error),
            ExtensionNotFound(ref c) => {
                write!(f, "could not find extension: '{}-{}'", c.pkg, c.target)
            }
            InvalidChangeSet => write!(f, "invalid change-set"),
            NoGPG => {
                write!(f,
                       "could not find 'gpg': ensure it is on PATH or disable GPG verification")
            }
            BadInstallerVersion(ref v) => write!(f, "unsupported installer version: {}", v),
            BadInstalledMetadataVersion(ref v) => {
                write!(f,
                       "unsupported metadata version in existing installation: {}",
                       v)
            }
            ComponentDirPermissionsFailed(ref e) => {
                write!(f, "I/O error walking directory during install: {}", e)
            }
            ComponentFilePermissionsFailed(ref e) => {
                write!(f, "error setting file permissions during install: {}", e)
            }
            ComponentDownloadFailed(ref component, ref e) => {
                write!(f, "component download failed for {}-{}: {}", component.pkg, component.target, e)
            }
            ObsoleteDistManifest => {
                write!(f, "the server unexpectedly provided an obsolete version of the distribution manifest")
            },
            Parsing(ref n) => {
                for e in n {
                    try!(e.fmt(f));
                    try!(writeln!(f, ""));
                }
                Ok(())
            }
            MissingKey(ref n) => write!(f, "missing key: '{}'", n),
            ExpectedType(ref t, ref n) => write!(f, "expected type: '{}' for '{}'", t, n),
            PackageNotFound(ref n) => write!(f, "package not found: '{}'", n),
            TargetNotFound(ref n) => write!(f, "target not found: '{}'", n),
            MissingRoot => write!(f, "manifest has no root package"),
            UnsupportedVersion(ref v) => write!(f, "manifest version '{}' is not supported", v),
            MissingPackageForComponent(ref c) => {
                write!(f,"server sent a broken manifest: missing package for component {}", c.name()),
            }
            RequestedComponentsUnavailable(ref cs) => {
                assert!(!cs.is_empty());
                if cs.len() == 1 {
                    write!(f, "component '{}' for '{}' is unavailable for download",
                           cs[0].pkg, cs[0].target)
                } else {
                    use itertools::Itertools;
                    let same_target = cs.iter().all(|c| c.target == cs[0].target);
                    if same_target {
                        let mut cs_strs = cs.iter().map(|c| format!("'{}'", c.pkg));
                        let cs_str = cs_strs.join(", ");
                        write!(f, "some components unavailable for download: {}",
                               cs_str)
                    } else {
                        let mut cs_strs = cs.iter().map(|c| format!("'{}' for '{}'", c.pkg, c.target));
                        let cs_str = cs_strs.join(", ");
                        write!(f, "some components unavailable for download: {}",
                               cs_str)
                    }
                }
            }
            NoManifestFound(ref ch, ref e) => {
                use multirust_utils::raw::DownloadError;
                use hyper::status::StatusCode::NotFound;
                match **e {
                    Error::Utils(multirust_utils::Error::DownloadingFile {
                        error: DownloadError::Status(NotFound),
                        ..
                    }) => {
                        write!(f, "no release found for '{}'", ch)
                    }
                    _ => {
                        // FIXME: Need handle other common cases nicely,
                        // like dns lookup, network unavailable.
                        write!(f, "failed to download manifest for '{}': {}", ch, e)
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add reverse, to_lowercase, to_uppercase<commit_after><|endoftext|>


<commit_before><commit_msg>Add test for #35423<commit_after>// Copyright 2016 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.

fn main () {
    let x = 4;
    match x {
        ref r if *r < 0 => println!("got negative num {} < 0", r),
        e @ 1 ... 100 => println!("got number within range [1,100] {}", e),
        _ => println!("no"),
    }
}
<|endoftext|>


<commit_before>// Regression test for issue #762
// xfail-stage0

fn f() { }
fn main() { ret ::f(); }<commit_msg>Disable expr-scope test, since it break windows<commit_after>// Regression test for issue #762
// xfail-stage0

// Breaks with fast-check, disabling to get tinderbox green again
// xfail-stage1
// xfail-stage2

fn f() { }
fn main() { ret ::f(); }<|endoftext|>


<commit_before><commit_msg>Add cube example.<commit_after>extern crate rier;
#[macro_use] extern crate glium;
extern crate cgmath;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 3],
    color: [f32; 3],
}

implement_vertex! {Vertex, position, color}

struct Graphics;

impl rier::Graphics for Graphics {
    type Vertex = Vertex;

    fn vertex() -> &'static str {
r#"
#version 330 core
uniform mat4 matrix;
in vec3 position;
in vec3 color;
out vec3 vColor;

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

    fn fragment() -> &'static str {
r#"
#version 330 core
in vec3 position;
in vec3 vColor;
out vec4 f_color;

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

fn cube_model(gfx: &rier::Gfx) -> rier::Mesh<Vertex> {
    let indices = [
    0, 1, 2,
    3, 0, 4,
    5, 0, 6,
    3, 6, 0,
    0, 2, 4,
    5, 1, 0,
    2, 1, 5,
    7, 6, 3,
    6, 7, 5,
    7, 3, 4,
    7, 4, 2,
    7, 2, 5];
    let vertices = [
        Vertex { position: [-1.0,-1.0,-1.0], color: [0.6, 0.2, 0.3] },
        Vertex { position: [-1.0,-1.0, 1.0], color: [0.1, 0.8, 0.4] },
        Vertex { position: [-1.0, 1.0, 1.0], color: [0.3, 0.5, 0.5] },
        Vertex { position: [ 1.0, 1.0,-1.0], color: [1.0, 0.6, 1.0] },
        Vertex { position: [-1.0, 1.0,-1.0], color: [1.0, 1.0, 1.0] },
        Vertex { position: [ 1.0,-1.0, 1.0], color: [0.7, 0.9, 0.6] },
        Vertex { position: [ 1.0,-1.0,-1.0], color: [0.0, 0.0, 0.0] },
        Vertex { position: [ 1.0, 1.0, 1.0], color: [0.9, 0.2, 0.5] },
    ];
    rier::Mesh::with_indices(gfx, &vertices, &indices).unwrap()
}

fn main()
{
    let gfx = rier::Context::create("Cube", (800, 600)).gfx();
    let renderer = rier::render::Renderer::<Graphics>::new(gfx.clone()).unwrap();
    let mut camera = rier::Camera3D::new(gfx.clone());
    camera.eye = cgmath::Point3::new(4.0, 3.0, 3.0);
    let mesh = cube_model(&gfx);
    'main: loop {
        camera.update();
        for event in gfx.display.poll_events() {
            match event {
                rier::WindowEvent::Closed => break 'main,
                _ => (),
            }
        }
        gfx.frame(|| {
            renderer.draw(&mesh, &uniform! { matrix: &camera }).unwrap();
        }).unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>Study rust-1 hello world<commit_after>fn main() {
    println!("Hello, world");
}
<|endoftext|>


<commit_before><commit_msg>Get started with importing the ip scheme to userspace<commit_after>use redox::Box;
use redox::fs::file::File;
use redox::io::{Read, Write, Seek, SeekFrom};
use redox::mem;
use redox::net::*;
use redox::ptr;
use redox::rand;
use redox::slice;
use redox::str;
use redox::{String, ToString};
use redox::to_num::*;
use redox::Vec;

/// IP resource
pub struct Resource {
    link: Box<Resource>,
    data: Vec<u8>,
    peer_addr: IPv4Addr,
    proto: u8,
    id: u16,
}

impl Resource {
    pub fn dup(&self) -> Option<Box<Self>> {
        match self.link.dup() {
            Some(link) => Some(box IPResource {
                link: link,
                data: self.data.clone(),
                peer_addr: self.peer_addr,
                proto: self.proto,
                id: self.id,
            }),
            None => None
        }
    }

    pub fn path(&self, buf: &mut [u8]) -> Option<usize> {
        let path = format!("ip://{}{}/{}", self.peer_addr.to_string(), String::from_num_radix(self.proto as usize, 16));

        let mut i = 0;
        for b in path.bytes() {
            if i < buf.len() {
                buf[i] = b;
                i += 1;
            } else {
                break;
            }
        }

        Some(i)
    }

    pub fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        /*
           if self.data.len() > 0 {
            let mut bytes: Vec<u8> = Vec::new();
            mem::swap(&mut self.data, &mut bytes);
            vec.push_all(&bytes);
            return Some(bytes.len());
        }

        loop {
            let mut bytes: Vec<u8> = Vec::new();
            match self.link.read_to_end(&mut bytes) {
                Some(_) => {
                    if let Some(packet) = IPv4::from_bytes(bytes) {
                        if packet.header.proto == self.proto && packet.header.dst.equals(IP_ADDR) &&
                           packet.header.src.equals(self.peer_addr) {
                            vec.push_all(&packet.data);
                            return Some(packet.data.len());
                        }
                    }
                }
                None => return None,
            }
        }
        */
        None
    }

    pub fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let ip_data = Vec::from(buf);

        self.id += 1;
        let mut ip = IPv4 {
            header: IPv4Header {
                ver_hlen: 0x40 | (mem::size_of::<IPv4Header>()/4 & 0xF) as u8, // No Options
                services: 0,
                len: n16::new((mem::size_of::<IPv4Header>() + ip_data.len()) as u16), // No Options
                id: n16::new(self.id),
                flags_fragment: n16::new(0),
                ttl: 128,
                proto: self.proto,
                checksum: Checksum { data: 0 },
                src: IP_ADDR,
                dst: self.peer_addr,
            },
            options: Vec::new(),
            data: ip_data,
        };

        unsafe {
            let header_ptr: *const IPv4Header = &ip.header;
            ip.header.checksum.data =
                Checksum::compile(Checksum::sum(header_ptr as usize, mem::size_of::<IPv4Header>()) +
                                  Checksum::sum(ip.options.as_ptr() as usize, ip.options.len()));
        }

        match self.link.write(ip.to_bytes().as_slice()) {
            Some(_) => return Some(buf.len()),
            None => return None,
        }
    }

    pub fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        None
    }

    pub fn sync(&mut self) -> bool {
        self.link.sync()
    }
}

/// A ARP entry (MAC + IP)
pub struct ARPEntry {
    ip: IPv4Addr,
    mac: MACAddr,
}

/// IP scheme
pub struct Scheme {
    pub arp: Vec<ARPEntry>,
}

impl Scheme {
    pub fn new() -> Box<Self> {
        box Scheme
    }

    pub fn open(&mut self, url: &str) -> Option<Box<Resource>> {
        if url.path().len() > 0 {
            let proto = url.path().to_num_radix(16) as u8;

            if url.host().len() > 0 {
                let peer_addr = IPv4Addr::from_string(&url.host());
                let mut peer_mac = BROADCAST_MAC_ADDR;

                for entry in self.arp.iter() {
                    if entry.ip.equals(peer_addr) {
                        peer_mac = entry.mac;
                        break;
                    }
                }

                if peer_mac.equals(BROADCAST_MAC_ADDR) {
                    if let Some(mut link) = URL::from_string(&("ethernet://".to_string() + peer_mac.to_string() + "/806")).open() {
                        let arp = ARP {
                            header: ARPHeader {
                                htype: n16::new(1),
                                ptype: n16::new(0x800),
                                hlen: 6,
                                plen: 4,
                                oper: n16::new(1),
                                src_mac: unsafe { MAC_ADDR },
                                src_ip: IP_ADDR,
                                dst_mac: peer_mac,
                                dst_ip: peer_addr,
                            },
                            data: Vec::new(),
                        };

                        match link.write(arp.to_bytes().as_slice()) {
                            Some(_) => loop {
                                let mut bytes: Vec<u8> = Vec::new();
                                match link.read_to_end(&mut bytes) {
                                    Some(_) =>
                                        if let Some(packet) = ARP::from_bytes(bytes) {
                                        if packet.header.oper.get() == 2 &&
                                           packet.header.src_ip.equals(peer_addr) {
                                            peer_mac = packet.header.src_mac;
                                            self.arp.push(ARPEntry {
                                                ip: peer_addr,
                                                mac: peer_mac,
                                            });
                                            break;
                                        }
                                    },
                                    None => (),
                                }
                            },
                            None => debug::d("IP: ARP Write Failed!\n"),
                        }
                    }
                }

                if let Some(link) = URL::from_string(&("ethernet://".to_string() + peer_mac.to_string() + "/800")).open() {
                    return Some(box IPResource {
                        link: link,
                        data: Vec::new(),
                        peer_addr: peer_addr,
                        proto: proto,
                        id: (rand() % 65536) as u16,
                    });
                }
            } else {
                while let Some(mut link) = URL::from_str("ethernet:///800").open() {
                    let mut bytes: Vec<u8> = Vec::new();
                    match link.read_to_end(&mut bytes) {
                        Some(_) => {
                            if let Some(packet) = IPv4::from_bytes(bytes) {
                                if packet.header.proto == proto &&
                                   packet.header.dst.equals(IP_ADDR) {
                                    return Some(box IPResource {
                                        link: link,
                                        data: packet.data,
                                        peer_addr: packet.header.src,
                                        proto: proto,
                                        id: (rand() % 65536) as u16,
                                    });
                                }
                            }
                        }
                        None => break,
                    }
                }
            }
        } else {
            /*
            debug::d("IP: No protocol provided\n");
            */
        }

        None
    }
}
<|endoftext|>


<commit_before><commit_msg>iterating over vector using different methods<commit_after><|endoftext|>


<commit_before><commit_msg>borrowed reference is not mutable<commit_after><|endoftext|>


<commit_before><commit_msg>Some changes to collision resolution<commit_after><|endoftext|>


<commit_before><commit_msg>Update key::verification::start tests<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented global Unicode emoji stats<commit_after><|endoftext|>


<commit_before><commit_msg>Refactor use Hash.<commit_after><|endoftext|>


<commit_before><commit_msg>isaac cipher<commit_after>// http://rosettacode.org/wiki/The_ISAAC_Cipher
#![feature(macro_rules)]
use std::iter::range_step;

static MSG :&'static str = "a Top Secret secret";
static KEY: &'static str = "this is my secret key";

#[cfg(not(test))]
fn main () {
    let mut isaac = Isaac::new();
    isaac.seed(KEY, true);
    let encr = isaac.vernam(MSG);

    println!("msg: {}", MSG);
    println!("key: {}", KEY);
    print!("XOR: ");
    for a in encr.iter() {
        print!("{:02X}", *a);
    }

    let mut isaac = Isaac::new();
    isaac.seed(KEY, true);
    let decr = isaac.vernam((String::from_utf8(encr).unwrap()).as_slice());

    print!("\nXOR dcr:");
    for a in decr.iter() {
        print!("{}", a.to_ascii());
    }
}

macro_rules! mix_v(
   ($a:expr) => (
   {
       $a[0] ^= $a[1] << 11; $a[3] += $a[0]; $a[1] += $a[2]; $a[1] ^= $a[2] >> 2;
       $a[4] += $a[1]; $a[2] += $a[3]; $a[2] ^= $a[3] << 8; $a[5] += $a[2];
       $a[3] += $a[4]; $a[3] ^= $a[4] >> 16; $a[6] += $a[3]; $a[4] += $a[5];
       $a[4] ^= $a[5] << 10; $a[7] += $a[4]; $a[5] += $a[6]; $a[5] ^= $a[6] >> 4;
       $a[0] += $a[5]; $a[6] += $a[7]; $a[6] ^= $a[7] << 8; $a[1] += $a[6];
       $a[7] += $a[0]; $a[7] ^= $a[0] >> 9; $a[2] += $a[7]; $a[0] += $a[1];
   } );
)

struct Isaac {
    mm: [u32,.. 256],
    aa: u32,
    bb: u32,
    cc: u32,
    rand_rsl: [u32,..256],
    rand_cnt: u32
}

impl Isaac {
    fn new() -> Isaac {
        Isaac {
            mm: [0u32, ..256],
            aa: 0,
            bb: 0,
            cc: 0,
            rand_rsl: [0u32, ..256],
            rand_cnt: 0
        }
    }

    fn isaac(&mut self) {
        self.cc += 1;
        self.bb += self.cc;

        for i in range(0u, 256) {
            let x = self.mm[i];
            match i%4 {
                0 => self.aa ^= (self.aa as uint << 13) as u32,
                1 => self.aa ^= (self.aa as uint >>  6) as u32,
                2 => self.aa ^= (self.aa as uint <<  2) as u32,
                3 => self.aa ^= (self.aa as uint >> 16) as u32,
                _ => unreachable!()
            }

            self.aa = self.mm[((i + 128) % 256) as uint] + self.aa;
            let y = self.mm[((x >> 2) % 256) as uint] + self.aa + self.bb;
            self.bb = self.mm[((y >> 10) % 256) as uint] + x;
            self.rand_rsl[i] = self.bb;
        }

        self.rand_cnt = 0;
    }

    fn rand_init(&mut self, flag: bool)
    {
        let mut a_v = [0x9e3779b9u32, ..8];

        for i in range(0u, 4) {
            // scramble it
            mix_v!(a_v);
        }

        for i in range_step(0, 256, 8) {
        // fill in mm[] with messy stuff
            if flag {
                // use all the information in the seed
                for j in range(0u, 8) { a_v[j] += self.rand_rsl[i+j]; }
            }
            mix_v!(a_v);
            for j in range(0u, 8) { self.mm[i+j] = a_v[j]; }
        }

        if flag {
            // do a second pass to make all of the seed affect all of mm
            for i in range_step(0, 256, 8) {
                for j in range(0u, 8) { a_v[j] += self.mm[i+j]; }
                mix_v!(a_v);
                for j in range(0u, 8) { self.mm[i+j] = a_v[j]; }
            }
        }

        self.isaac();       // fill in the first set of results
        self.rand_cnt = 0;  // prepare to use the first set of results
    }

    // Get a random 32-bit value
    fn i_random(&mut self) -> u32 {
        let r = self.rand_rsl[self.rand_cnt as uint];
        self.rand_cnt += 1;
        if self.rand_cnt >255 {
            self.isaac();
            self.rand_cnt = 0;
        }
        r
    }

    // Seed ISAAC with a string
    fn seed(&mut self, seed: &str, flag: bool) {
        for i in range (0u, 256) { self.mm[i] = 0; }
        for i in range (0u, 256) { self.rand_rsl[i] = 0; }

        for i in range(0u, seed.len()) {
            self.rand_rsl[i] = seed.as_bytes()[i] as u32;
        }
        // initialize ISAAC with seed
        self.rand_init(flag);
    }

    // Get a random character in printable ASCII range
    fn i_rand_ascii(&mut self) -> u8 {
        (self.i_random() % 95 + 32) as u8
    }

    /// XOR message
    fn vernam(&mut self, msg :&str) -> Vec<u8> {
        msg.bytes().map(|b| (self.i_rand_ascii() ^ b))
            .collect::<Vec<u8>>()
    }
}

#[cfg(test)]
mod test {
    use super::{Isaac, MSG, KEY};
    static encripted: [u8,..19] = [0x1C, 0x06, 0x36, 0x19, 0x0B, 0x12,
        0x60, 0x23, 0x3B, 0x35, 0x12, 0x5F, 0x1E, 0x1D, 0x0E, 0x2F,
        0x4C, 0x54, 0x22];

    #[test]
    fn encrypt() {
        let mut isaac = Isaac::new();
        isaac.seed(KEY, true);
        let encr = isaac.vernam(MSG);

        for (a, b) in encr.iter().zip(encripted.iter()) {
            assert_eq!(a, b);
        }
    }

    #[test]
    fn decrypt() {
        let expected = MSG;

        let mut isaac = Isaac::new();
        isaac.seed(KEY, true);
        let encr_msg = String::from_utf8(encripted.to_vec()).unwrap();
        let decr = isaac.vernam(encr_msg.as_slice());

        for (&a, b) in decr.iter().zip(expected.bytes()) {
            assert_eq!(a, b);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Include number of timers in stats<commit_after><|endoftext|>


<commit_before><commit_msg>Remove unused line.<commit_after><|endoftext|>


<commit_before><commit_msg>timer<commit_after>use std::time::Duration;

// Timer
pub struct Timer {
    time : Duration,
    time_left : Duration,
    pub ready : bool,
}

impl Timer {
    pub fn from_millis(milliseconds : u64) -> Self {
        let duration = Duration::from_millis(milliseconds);
        Self {
            time : duration,
            time_left : duration,
            ready : false,
        }
    }

    pub fn reset(&mut self) {
        self.time_left = self.time;
    }

    pub fn update(&mut self, delta : Duration) {
        if self.ready {
            return;
        }
        self.time_left = self.time_left - delta;
        if self.time_left < Duration::from_secs(0) {
            self.ready = true;
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add problem #83<commit_after>use core::to_bytes::{ IterBytes, Cb };
use core::hashmap::{ HashSet };

use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 83,
    answer: "425185",
    solver: solve
};

#[deriving(Eq)]
struct Point { x: uint, y: uint }

impl IterBytes for Point {
    fn iter_bytes(&self, lsb0: bool, f: Cb) {
        for self.x.iter_bytes(lsb0) |bytes| {
            if !f(bytes) { return; }
        }
        for self.y.iter_bytes(lsb0) |bytes| {
            if !f(bytes) { return; }
        }
    }
}

fn solve() -> ~str {
    let result = io::file_reader(&Path("files/matrix.txt")).map(|file| {
        let mut mat = ~[];
        for file.each_line |line| {
            let mut row = ~[];
            for line.each_split_char(',') |n| {
                row.push(uint::from_str(n).get());
            }
            mat.push(row);
            assert_eq!(mat[0].len(), mat.last().len());
        }
        let w = mat[0].len();
        let h = mat.len();
        ((w, h), mat)
    }).map(|&((w, h), mat)| {
        let start = Point { x: 0,     y: 0 };
        let goal  = Point { x: w - 1, y: h - 1 };

        let mut closed = HashSet::new();
        let mut open   = HashSet::new();
        let mut dist = vec::from_fn(h, |_y| vec::from_elem(w, uint::max_value));
        let mut parent = vec::from_fn(h, |_y| vec::from_elem(w, Point { x: w, y: h }));

        dist[start.y][start.x] = mat[start.y][start.x];
        open.insert(start);

        loop {
            if open.is_empty() { fail!(); }

            let mut min_dist = uint::max_value;
            let mut min_pt   = Point { x: w, y: h};
            for open.each |&pt| {
                let d = dist[pt.y][pt.x] + (h - pt.y - 1) + (w - pt.x - 1);
                if d < min_dist {
                    min_dist = d;
                    min_pt = pt;
                }
            }

            if min_pt == goal { break; }
            open.remove(&min_pt);
            closed.insert(min_pt);

            let mut ms = ~[];
            if min_pt.x > 0 { ms.push(Point { x: min_pt.x - 1, .. min_pt }) }
            if min_pt.y > 0 { ms.push(Point { y: min_pt.y - 1, .. min_pt }) }
            if min_pt.x < w - 1 { ms.push(Point { x: min_pt.x + 1, .. min_pt }) }
            if min_pt.y < h - 1 { ms.push(Point { y: min_pt.y + 1, .. min_pt }) }

            for ms.each |&pt| {
                let new_dist = dist[min_pt.y][min_pt.x] + mat[pt.y][pt.x];
                if open.contains(&pt) {
                    if new_dist < dist[pt.y][pt.x] {
                        dist[pt.y][pt.x]   = new_dist;
                        parent[pt.y][pt.x] = min_pt;
                    }
                    loop;
                }
                if closed.contains(&pt) {
                    if new_dist < dist[pt.y][pt.x] {
                        closed.remove(&pt);
                        dist[pt.y][pt.x] = uint::min(dist[pt.y][pt.x], new_dist);
                        parent[pt.y][pt.x] = min_pt;
                        open.insert(pt);
                    }
                    loop;
                }
                dist[pt.y][pt.x] = uint::min(dist[pt.y][pt.x], new_dist);
                parent[pt.y][pt.x] = min_pt;
                open.insert(pt);
            }
        }

        dist[h - 1][w - 1]
    });

    match result {
        Err(msg) => fail!(msg),
        Ok(value) => return value.to_str()
    }
}
<|endoftext|>


<commit_before><commit_msg>fixed empty line lyr crash<commit_after>extern crate sdl2;
use sdl2::pixels::Color;
use std::cmp::{max,min};

/// will always return a flat color regardless or alpha
pub fn mix_colors(color1:Color,color2:Color,mix_ratio:f32) -> Color {
	let (r1,g1,b1) = color1.rgb();
	let (r2,g2,b2) = color2.rgb();
	let (r1,g1,b1) = (r1 as i16, g1 as i16, b1 as i16);
	let (r2,g2,b2) = (r2 as i16, g2 as i16, b2 as i16);
	let (r,g,b) : (i16,i16,i16) =
		(((r2 - r1) as f32 * mix_ratio ) as i16 + r1 ,
		((g2 - g1) as f32 * mix_ratio ) as i16 + g1 ,
		((b2 - b1) as f32 * mix_ratio ) as i16 + b1);

	let (r,g,b) = (max(min(r,0xFF),0) as u8,max(min(g,0xFF),0) as u8, max(min(b,0xFF),0) as u8);
	Color::RGB(r,g,b)
}

pub fn fade_color(color1:Color,fade_ratio:f32) -> Color {
	let (r,g,b,a) : (u8,u8,u8,u8) = match color1 {
		Color::RGB(r,g,b) => (r,g,b,255),
		Color::RGBA(r,g,b,a) => (r,g,b,a)
	};
	Color::RGBA(r,g,b,(a as f32 * fade_ratio) as u8 )
}
<|endoftext|>


<commit_before><commit_msg>Added a tests directory<commit_after>#[test]
fn it_works() {
    assert!(1 > 0);
}
<|endoftext|>


<commit_before><commit_msg>[Rust] pretty print for vec<commit_after>fn main() {
    println!("{:?}", vec![1, 2, 3, 4, 5]);
    println!("{:#?}", vec![1, 2, 3, 4, 5]);
}
<|endoftext|>


<commit_before><commit_msg>Commit with finished joiner.rs file<commit_after><|endoftext|>


<commit_before><commit_msg>Add a point counting example<commit_after>//! Count the number of points in the file twice, once with sync-to-pps and once without.

extern crate scanifc;

use scanifc::point3d::Stream;

fn main() {
    let ref path = std::env::args().skip(1).next().expect(
        "Must have one argument (the filename)",
    );
    let with = Stream::from_path(path)
        .sync_to_pps(true)
        .open()
        .unwrap()
        .into_points()
        .unwrap()
        .len();
    println!("With sync_to_pps: {}", with);
    let without = Stream::from_path(path)
        .sync_to_pps(false)
        .open()
        .unwrap()
        .into_points()
        .unwrap()
        .len();
    println!("Without sync_to_pps: {}", without);
}
<|endoftext|>


<commit_before><commit_msg>Hello world!<commit_after>// Hello Rust world!

fn main() {
    println!("Hello world!");
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Delete char
    pub fn delete(&mut self) {
        let y = self.y();
        let x = self.x();
        if self.text[y].len() == 0 {
            self.text.remove(y);
        } else {
            self.text[y].remove(x);
        }
    }
}
<commit_msg>Fix out-of-bound bug<commit_after>use super::*;

impl Editor {
    /// Delete char
    pub fn delete(&mut self) {
        let y = self.y();
        let x = self.x();
        if self.text[y].len() == 0 {
            if self.text.len() != 1 {
                self.text.remove(y);
            }
        } else if x < self.text[y].len() {
            self.text[y].remove(x);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>fix windows build<commit_after><|endoftext|>


<commit_before>extern crate clap;

use cli::CliConfig;

use std::path::Path;
use config::reader::from_file;
use config::types::Config as Cfg;

use std::fmt::Debug;
use std::fmt::Formatter;
use std::fmt::Error;

pub struct Configuration {
    pub rtp         : String,
    pub store_sub   : String,
    pub verbose     : bool,
    pub debugging   : bool,
}

impl Configuration {

    pub fn new(config: &CliConfig) -> Configuration {
        use std::env::home_dir;

        let rtp = rtp_path(config).or(default_path());

        let mut verbose     = false;
        let mut debugging   = false;
        let mut store_sub   = String::from("/store");

        if let Some(cfg) = fetch_config(rtp.clone()) {
            if let Some(v) = cfg.lookup_boolean("verbose") {
                verbose = v;
            }
            if let Some(d) = cfg.lookup_boolean("debug") {
                debugging = d;
            }
            if let Some(s) = cfg.lookup_str("store") {
                store_sub = String::from(s);
            }
        }

        Configuration {
            verbose: verbose,
            debugging: debugging,
            store_sub: store_sub,
            rtp: rtp.unwrap_or(String::from("/tmp/")),
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.verbose
    }

    pub fn is_debugging(&self) -> bool {
        self.debugging
    }

    pub fn store_path_str(&self) -> String {
        format!("{}{}", self.rtp, self.store_sub)
    }

    pub fn get_rtp(&self) -> String {
        self.rtp.clone()
    }

}

fn rtp_path(config: &CliConfig) -> Option<String> {
    config.cli_matches.value_of("rtp")
                      .and_then(|s| Some(String::from(s)))
}

fn fetch_config(rtp: Option<String>) -> Option<Cfg> {
    rtp.and_then(|r| from_file(Path::new(&(r.clone() + "/config"))).ok())
}

fn default_path() -> Option<String> {
    use std::env::home_dir;

    home_dir().and_then(|mut buf| {
        buf.push("/.imag");
        buf.to_str().map(|s| String::from(s))
    })

}

impl Debug for Configuration {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Configuration (verbose: {}, debugging: {}, rtp: {}, store path: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp(),
            self.store_path_str()
            )
    }

}

<commit_msg>Add debug output for Configuration::new()<commit_after>extern crate clap;

use cli::CliConfig;

use std::path::Path;
use config::reader::from_file;
use config::types::Config as Cfg;

use std::fmt::Debug;
use std::fmt::Formatter;
use std::fmt::Error;

pub struct Configuration {
    pub rtp         : String,
    pub store_sub   : String,
    pub verbose     : bool,
    pub debugging   : bool,
}

impl Configuration {

    pub fn new(config: &CliConfig) -> Configuration {
        use std::env::home_dir;

        let rtp = rtp_path(config).or(default_path());

        let mut verbose     = false;
        let mut debugging   = false;
        let mut store_sub   = String::from("/store");

        if let Some(cfg) = fetch_config(rtp.clone()) {
            if let Some(v) = cfg.lookup_boolean("verbose") {
                verbose = v;
            }
            if let Some(d) = cfg.lookup_boolean("debug") {
                debugging = d;
            }
            if let Some(s) = cfg.lookup_str("store") {
                store_sub = String::from(s);
            }
        }

        let runtimepath = rtp.unwrap_or(String::from("/tmp/"));

        debug!("Building configuration");
        debug!("  - verbose    : {}", verbose);
        debug!("  - debugging  : {}", debugging);
        debug!("  - store sub  : {}", store_sub);
        debug!("  - runtimepath: {}", runtimepath);

        Configuration {
            verbose: verbose,
            debugging: debugging,
            store_sub: store_sub,
            rtp: runtimepath,
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.verbose
    }

    pub fn is_debugging(&self) -> bool {
        self.debugging
    }

    pub fn store_path_str(&self) -> String {
        format!("{}{}", self.rtp, self.store_sub)
    }

    pub fn get_rtp(&self) -> String {
        self.rtp.clone()
    }

}

fn rtp_path(config: &CliConfig) -> Option<String> {
    config.cli_matches.value_of("rtp")
                      .and_then(|s| Some(String::from(s)))
}

fn fetch_config(rtp: Option<String>) -> Option<Cfg> {
    rtp.and_then(|r| from_file(Path::new(&(r.clone() + "/config"))).ok())
}

fn default_path() -> Option<String> {
    use std::env::home_dir;

    home_dir().and_then(|mut buf| {
        buf.push("/.imag");
        buf.to_str().map(|s| String::from(s))
    })

}

impl Debug for Configuration {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Configuration (verbose: {}, debugging: {}, rtp: {}, store path: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp(),
            self.store_path_str()
            )
    }

}

<|endoftext|>


<commit_before>//! Tests for custom json target specifications.

use cargo_test_support::is_nightly;
use cargo_test_support::{basic_manifest, project};

#[cargo_test]
fn custom_target_minimal() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn foo() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
    p.cargo("build --lib --target src/../custom-target.json -v")
        .run();

    // Ensure that the correct style of flag is passed to --target with doc tests.
    p.cargo("test --doc --target src/../custom-target.json -v -Zdoctest-xcompile")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..]")
        .run();
}

#[cargo_test]
fn custom_target_dependency() {
    if !is_nightly() {
        // Requires features no_core, lang_items, optin_builtin_traits
        return;
    }
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]

                name = "foo"
                version = "0.0.1"
                authors = ["author@example.com"]

                [dependencies]
                bar = { path = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![feature(optin_builtin_traits)]
                #![no_core]

                extern crate bar;

                pub fn foo() -> u32 {
                    bar::bar()
                }

                #[lang = "freeze"]
                unsafe auto trait Freeze {}
            "#,
        )
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file(
            "bar/src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn bar() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
}

#[cargo_test]
fn custom_bin_target() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/main.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]
                #![no_main]

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-bin-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld",
                    "linker": "rust-lld",
                    "executables": true
                }
            "#,
        )
        .build();

    p.cargo("build --target custom-bin-target.json -v").run();
}
<commit_msg>Fix custom_target_dependency test.<commit_after>//! Tests for custom json target specifications.

use cargo_test_support::is_nightly;
use cargo_test_support::{basic_manifest, project};

#[cargo_test]
fn custom_target_minimal() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn foo() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
    p.cargo("build --lib --target src/../custom-target.json -v")
        .run();

    // Ensure that the correct style of flag is passed to --target with doc tests.
    p.cargo("test --doc --target src/../custom-target.json -v -Zdoctest-xcompile")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..]")
        .run();
}

#[cargo_test]
fn custom_target_dependency() {
    if !is_nightly() {
        // Requires features no_core, lang_items, auto_traits
        return;
    }
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]

                name = "foo"
                version = "0.0.1"
                authors = ["author@example.com"]

                [dependencies]
                bar = { path = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![feature(auto_traits)]
                #![no_core]

                extern crate bar;

                pub fn foo() -> u32 {
                    bar::bar()
                }

                #[lang = "freeze"]
                unsafe auto trait Freeze {}
            "#,
        )
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file(
            "bar/src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn bar() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
}

#[cargo_test]
fn custom_bin_target() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/main.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]
                #![no_main]

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-bin-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld",
                    "linker": "rust-lld",
                    "executables": true
                }
            "#,
        )
        .build();

    p.cargo("build --target custom-bin-target.json -v").run();
}
<|endoftext|>


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

use std::collections::HashSet;
use std::collections::hash_map::RandomState;
use std::iter::FromIterator;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;

use devicemapper::consts::SECTOR_SIZE;
use devicemapper::DM;
use devicemapper::{DataBlocks, Sectors};
use devicemapper::LinearDev;
use devicemapper::{ThinPoolDev, ThinPoolStatus, ThinPoolWorkingStatus};
use time::now;
use uuid::Uuid;
use serde_json;

use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;
use engine::Filesystem;
use engine::Pool;
use engine::RenameAction;
use engine::engine::Redundancy;
use engine::strat_engine::device::wipe_sectors;
use consts::IEC::Mi;

use super::super::engine::{FilesystemUuid, HasName, HasUuid};
use super::super::structures::Table;

use super::serde_structs::{Isomorphism, PoolSave};
use super::blockdevmgr::BlockDevMgr;
use super::dmdevice::{FlexRole, ThinPoolRole, format_flex_name, format_thinpool_name};
use super::filesystem::{StratFilesystem, FilesystemStatus};
use super::metadata::MIN_MDA_SECTORS;

const DATA_BLOCK_SIZE: Sectors = Sectors(2048);
const META_LOWATER: u64 = 512;
const DATA_LOWATER: DataBlocks = DataBlocks(512);

const INITIAL_META_SIZE: Sectors = Sectors(16 * Mi / SECTOR_SIZE as u64);
const INITIAL_DATA_SIZE: Sectors = Sectors(512 * Mi / SECTOR_SIZE as u64);

#[derive(Debug)]
pub struct StratPool {
    name: String,
    pool_uuid: Uuid,
    pub block_devs: BlockDevMgr,
    pub filesystems: Table<StratFilesystem>,
    redundancy: Redundancy,
    thin_pool: ThinPoolDev,
}

impl StratPool {
    /// Initialize a Stratis Pool.
    /// 1. Initialize the block devices specified by paths.
    /// 2. Set up thinpool device to back filesystems.
    pub fn initialize(name: &str,
                      dm: &DM,
                      paths: &[&Path],
                      redundancy: Redundancy,
                      force: bool)
                      -> EngineResult<StratPool> {
        let pool_uuid = Uuid::new_v4();

        let mut block_mgr =
            try!(BlockDevMgr::initialize(&pool_uuid, paths, MIN_MDA_SECTORS, force));

        if block_mgr.avail_space() < StratPool::min_initial_size() {
            let avail_size = block_mgr.avail_space().bytes();
            try!(block_mgr.destroy_all());
            return Err(EngineError::Engine(ErrorEnum::Invalid,
                                           format!("Space on pool must be at least {} bytes, \
                                                   available space is only {} bytes",
                                                   StratPool::min_initial_size().bytes(),
                                                   avail_size)));

        }

        let meta_regions = block_mgr
            .alloc_space(INITIAL_META_SIZE)
            .expect("blockmgr must not fail, already checked for space");
        let device_name = format_flex_name(&pool_uuid, FlexRole::ThinMeta);
        let meta_dev = try!(LinearDev::new(&device_name, dm, meta_regions));

        // When constructing a thin-pool, Stratis reserves the first N
        // sectors on a block device by creating a linear device with a
        // starting offset. DM writes the super block in the first block.
        // DM requires this first block to be zeros when the meta data for
        // the thin-pool is initially created. If we don't zero the
        // superblock DM issue error messages because it triggers code paths
        // that are trying to re-adopt the device with the attributes that
        // have been passed.
        try!(wipe_sectors(&try!(meta_dev.devnode()), Sectors(0), INITIAL_META_SIZE));

        let data_regions = block_mgr
            .alloc_space(INITIAL_DATA_SIZE)
            .expect("blockmgr must not fail, already checked for space");
        let device_name = format_flex_name(&pool_uuid, FlexRole::ThinData);
        let data_dev = try!(LinearDev::new(&device_name, dm, data_regions));
        let length = try!(data_dev.size()).sectors();

        let device_name = format_thinpool_name(&pool_uuid, ThinPoolRole::Pool);
        // TODO Fix hard coded data blocksize and low water mark.
        let thinpool_dev = try!(ThinPoolDev::new(&device_name,
                                                 dm,
                                                 length,
                                                 DATA_BLOCK_SIZE,
                                                 DataBlocks(256000),
                                                 meta_dev,
                                                 data_dev));

        let mut pool = StratPool {
            name: name.to_owned(),
            pool_uuid: pool_uuid,
            block_devs: block_mgr,
            filesystems: Table::new(),
            redundancy: redundancy,
            thin_pool: thinpool_dev,
        };

        try!(pool.write_metadata());

        Ok(pool)
    }

    /// Minimum initial size for a pool.
    pub fn min_initial_size() -> Sectors {
        INITIAL_META_SIZE + INITIAL_DATA_SIZE
    }

    // TODO: Check current time against global last updated, and use
    // alternate time value if earlier, as described in SWDD
    pub fn write_metadata(&mut self) -> EngineResult<()> {
        let data = try!(serde_json::to_string(&self.to_save()));
        self.block_devs
            .save_state(&now().to_timespec(), data.as_bytes())
    }

    pub fn check(&mut self) -> () {
        let dm = DM::new().expect("Could not get DM handle");

        let result = match self.thin_pool.status(&dm) {
            Ok(r) => r,
            Err(_) => {
                error!("Could not get thinpool status");
                // TODO: Take pool offline?
                return;
            }
        };

        match result {
            ThinPoolStatus::Good(wstatus, usage) => {
                match wstatus {
                    ThinPoolWorkingStatus::Good => {}
                    ThinPoolWorkingStatus::ReadOnly => {
                        // TODO: why is pool r/o and how do we get it
                        // rw again?
                    }
                    ThinPoolWorkingStatus::OutOfSpace => {
                        // TODO: Add more space if possible, or
                        // prevent further usage
                        // Should never happen -- we should be extending first!
                    }
                    ThinPoolWorkingStatus::NeedsCheck => {
                        // TODO: Take pool offline?
                        // TODO: run thin_check
                    }
                }

                if usage.used_meta > usage.total_meta - META_LOWATER {
                    // TODO: Extend meta device
                }

                if usage.used_data > usage.total_data - DATA_LOWATER {
                    // TODO: Extend data device
                }
            }
            ThinPoolStatus::Fail => {
                // TODO: Take pool offline?
                // TODO: Run thin_check
            }
        }

        for fs in &mut self.filesystems {
            match fs.check(&dm) {
                Ok(f_status) => {
                    if let FilesystemStatus::Failed = f_status {
                        // TODO: recover fs? (how?)
                    }
                }
                Err(_e) => error!("fs.check() failed"),
            }
        }
    }

    /// Teardown a pool.
    /// Take down the device mapper devices belonging to the pool.
    /// This method and destroy() must keep their DM teardown operations
    /// in sync.
    pub fn teardown(self) -> EngineResult<()> {
        // TODO: any necessary clean up of filesystems
        if !self.filesystems.is_empty() {
            return Err(EngineError::Engine(ErrorEnum::Busy,
                                           format!("May be unsynced files on device.")));
        }
        let dm = try!(DM::new());
        try!(self.thin_pool.teardown(&dm));
        Ok(())
    }
}

impl Pool for StratPool {
    fn create_filesystems<'a, 'b>(&'a mut self,
                                  specs: &[&'b str])
                                  -> EngineResult<Vec<(&'b str, FilesystemUuid)>> {
        let names: HashSet<_, RandomState> = HashSet::from_iter(specs);
        for name in names.iter() {
            if self.filesystems.contains_name(name) {
                return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.to_string()));
            }
        }

        // TODO: Roll back on filesystem initialization failure.
        let dm = try!(DM::new());
        let pool_uuid = &self.pool_uuid;
        let mut result = Vec::new();
        for name in names.iter() {
            let uuid = Uuid::new_v4();
            let new_filesystem =
                try!(StratFilesystem::initialize(pool_uuid, uuid, name, &dm, &mut self.thin_pool));
            self.filesystems.insert(new_filesystem);
            result.push((**name, uuid));
        }

        Ok(result)
    }

    fn add_blockdevs(&mut self, paths: &[&Path], force: bool) -> EngineResult<Vec<PathBuf>> {
        let bdev_paths = try!(self.block_devs.add(&self.pool_uuid, paths, force));
        try!(self.write_metadata());
        Ok(bdev_paths)
    }

    fn destroy(self) -> EngineResult<()> {
        // Ensure that DM teardown operations in this method are in sync
        // with operations in teardown().
        let dm = try!(DM::new());
        try!(self.thin_pool.teardown(&dm));
        try!(self.block_devs.destroy_all());

        Ok(())
    }

    fn destroy_filesystems<'a, 'b>(&'a mut self,
                                   fs_uuids: &[&'b FilesystemUuid])
                                   -> EngineResult<Vec<&'b FilesystemUuid>> {
        destroy_filesystems!{self; fs_uuids}
    }

    fn rename_filesystem(&mut self,
                         uuid: &FilesystemUuid,
                         new_name: &str)
                         -> EngineResult<RenameAction> {
        rename_filesystem!{self; uuid; new_name}
    }

    fn rename(&mut self, name: &str) {
        self.name = name.to_owned();
    }

    fn get_filesystem(&mut self, uuid: &FilesystemUuid) -> Option<&mut Filesystem> {
        get_filesystem!(self; uuid)
    }
}

impl HasUuid for StratPool {
    fn uuid(&self) -> &FilesystemUuid {
        &self.pool_uuid
    }
}

impl HasName for StratPool {
    fn name(&self) -> &str {
        &self.name
    }
}

impl Isomorphism<PoolSave> for StratPool {
    fn to_save(&self) -> PoolSave {
        PoolSave { name: self.name.clone() }
    }
}
<commit_msg>Eliminate pool_uuid name<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::collections::HashSet;
use std::collections::hash_map::RandomState;
use std::iter::FromIterator;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;

use devicemapper::consts::SECTOR_SIZE;
use devicemapper::DM;
use devicemapper::{DataBlocks, Sectors};
use devicemapper::LinearDev;
use devicemapper::{ThinPoolDev, ThinPoolStatus, ThinPoolWorkingStatus};
use time::now;
use uuid::Uuid;
use serde_json;

use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;
use engine::Filesystem;
use engine::Pool;
use engine::RenameAction;
use engine::engine::Redundancy;
use engine::strat_engine::device::wipe_sectors;
use consts::IEC::Mi;

use super::super::engine::{FilesystemUuid, HasName, HasUuid};
use super::super::structures::Table;

use super::serde_structs::{Isomorphism, PoolSave};
use super::blockdevmgr::BlockDevMgr;
use super::dmdevice::{FlexRole, ThinPoolRole, format_flex_name, format_thinpool_name};
use super::filesystem::{StratFilesystem, FilesystemStatus};
use super::metadata::MIN_MDA_SECTORS;

const DATA_BLOCK_SIZE: Sectors = Sectors(2048);
const META_LOWATER: u64 = 512;
const DATA_LOWATER: DataBlocks = DataBlocks(512);

const INITIAL_META_SIZE: Sectors = Sectors(16 * Mi / SECTOR_SIZE as u64);
const INITIAL_DATA_SIZE: Sectors = Sectors(512 * Mi / SECTOR_SIZE as u64);

#[derive(Debug)]
pub struct StratPool {
    name: String,
    pool_uuid: Uuid,
    pub block_devs: BlockDevMgr,
    pub filesystems: Table<StratFilesystem>,
    redundancy: Redundancy,
    thin_pool: ThinPoolDev,
}

impl StratPool {
    /// Initialize a Stratis Pool.
    /// 1. Initialize the block devices specified by paths.
    /// 2. Set up thinpool device to back filesystems.
    pub fn initialize(name: &str,
                      dm: &DM,
                      paths: &[&Path],
                      redundancy: Redundancy,
                      force: bool)
                      -> EngineResult<StratPool> {
        let pool_uuid = Uuid::new_v4();

        let mut block_mgr =
            try!(BlockDevMgr::initialize(&pool_uuid, paths, MIN_MDA_SECTORS, force));

        if block_mgr.avail_space() < StratPool::min_initial_size() {
            let avail_size = block_mgr.avail_space().bytes();
            try!(block_mgr.destroy_all());
            return Err(EngineError::Engine(ErrorEnum::Invalid,
                                           format!("Space on pool must be at least {} bytes, \
                                                   available space is only {} bytes",
                                                   StratPool::min_initial_size().bytes(),
                                                   avail_size)));

        }

        let meta_regions = block_mgr
            .alloc_space(INITIAL_META_SIZE)
            .expect("blockmgr must not fail, already checked for space");
        let device_name = format_flex_name(&pool_uuid, FlexRole::ThinMeta);
        let meta_dev = try!(LinearDev::new(&device_name, dm, meta_regions));

        // When constructing a thin-pool, Stratis reserves the first N
        // sectors on a block device by creating a linear device with a
        // starting offset. DM writes the super block in the first block.
        // DM requires this first block to be zeros when the meta data for
        // the thin-pool is initially created. If we don't zero the
        // superblock DM issue error messages because it triggers code paths
        // that are trying to re-adopt the device with the attributes that
        // have been passed.
        try!(wipe_sectors(&try!(meta_dev.devnode()), Sectors(0), INITIAL_META_SIZE));

        let data_regions = block_mgr
            .alloc_space(INITIAL_DATA_SIZE)
            .expect("blockmgr must not fail, already checked for space");
        let device_name = format_flex_name(&pool_uuid, FlexRole::ThinData);
        let data_dev = try!(LinearDev::new(&device_name, dm, data_regions));
        let length = try!(data_dev.size()).sectors();

        let device_name = format_thinpool_name(&pool_uuid, ThinPoolRole::Pool);
        // TODO Fix hard coded data blocksize and low water mark.
        let thinpool_dev = try!(ThinPoolDev::new(&device_name,
                                                 dm,
                                                 length,
                                                 DATA_BLOCK_SIZE,
                                                 DataBlocks(256000),
                                                 meta_dev,
                                                 data_dev));

        let mut pool = StratPool {
            name: name.to_owned(),
            pool_uuid: pool_uuid,
            block_devs: block_mgr,
            filesystems: Table::new(),
            redundancy: redundancy,
            thin_pool: thinpool_dev,
        };

        try!(pool.write_metadata());

        Ok(pool)
    }

    /// Minimum initial size for a pool.
    pub fn min_initial_size() -> Sectors {
        INITIAL_META_SIZE + INITIAL_DATA_SIZE
    }

    // TODO: Check current time against global last updated, and use
    // alternate time value if earlier, as described in SWDD
    pub fn write_metadata(&mut self) -> EngineResult<()> {
        let data = try!(serde_json::to_string(&self.to_save()));
        self.block_devs
            .save_state(&now().to_timespec(), data.as_bytes())
    }

    pub fn check(&mut self) -> () {
        let dm = DM::new().expect("Could not get DM handle");

        let result = match self.thin_pool.status(&dm) {
            Ok(r) => r,
            Err(_) => {
                error!("Could not get thinpool status");
                // TODO: Take pool offline?
                return;
            }
        };

        match result {
            ThinPoolStatus::Good(wstatus, usage) => {
                match wstatus {
                    ThinPoolWorkingStatus::Good => {}
                    ThinPoolWorkingStatus::ReadOnly => {
                        // TODO: why is pool r/o and how do we get it
                        // rw again?
                    }
                    ThinPoolWorkingStatus::OutOfSpace => {
                        // TODO: Add more space if possible, or
                        // prevent further usage
                        // Should never happen -- we should be extending first!
                    }
                    ThinPoolWorkingStatus::NeedsCheck => {
                        // TODO: Take pool offline?
                        // TODO: run thin_check
                    }
                }

                if usage.used_meta > usage.total_meta - META_LOWATER {
                    // TODO: Extend meta device
                }

                if usage.used_data > usage.total_data - DATA_LOWATER {
                    // TODO: Extend data device
                }
            }
            ThinPoolStatus::Fail => {
                // TODO: Take pool offline?
                // TODO: Run thin_check
            }
        }

        for fs in &mut self.filesystems {
            match fs.check(&dm) {
                Ok(f_status) => {
                    if let FilesystemStatus::Failed = f_status {
                        // TODO: recover fs? (how?)
                    }
                }
                Err(_e) => error!("fs.check() failed"),
            }
        }
    }

    /// Teardown a pool.
    /// Take down the device mapper devices belonging to the pool.
    /// This method and destroy() must keep their DM teardown operations
    /// in sync.
    pub fn teardown(self) -> EngineResult<()> {
        // TODO: any necessary clean up of filesystems
        if !self.filesystems.is_empty() {
            return Err(EngineError::Engine(ErrorEnum::Busy,
                                           format!("May be unsynced files on device.")));
        }
        let dm = try!(DM::new());
        try!(self.thin_pool.teardown(&dm));
        Ok(())
    }
}

impl Pool for StratPool {
    fn create_filesystems<'a, 'b>(&'a mut self,
                                  specs: &[&'b str])
                                  -> EngineResult<Vec<(&'b str, FilesystemUuid)>> {
        let names: HashSet<_, RandomState> = HashSet::from_iter(specs);
        for name in names.iter() {
            if self.filesystems.contains_name(name) {
                return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.to_string()));
            }
        }

        // TODO: Roll back on filesystem initialization failure.
        let dm = try!(DM::new());
        let mut result = Vec::new();
        for name in names.iter() {
            let uuid = Uuid::new_v4();
            let new_filesystem = try!(StratFilesystem::initialize(&self.pool_uuid,
                                                                  uuid,
                                                                  name,
                                                                  &dm,
                                                                  &mut self.thin_pool));
            self.filesystems.insert(new_filesystem);
            result.push((**name, uuid));
        }

        Ok(result)
    }

    fn add_blockdevs(&mut self, paths: &[&Path], force: bool) -> EngineResult<Vec<PathBuf>> {
        let bdev_paths = try!(self.block_devs.add(&self.pool_uuid, paths, force));
        try!(self.write_metadata());
        Ok(bdev_paths)
    }

    fn destroy(self) -> EngineResult<()> {
        // Ensure that DM teardown operations in this method are in sync
        // with operations in teardown().
        let dm = try!(DM::new());
        try!(self.thin_pool.teardown(&dm));
        try!(self.block_devs.destroy_all());

        Ok(())
    }

    fn destroy_filesystems<'a, 'b>(&'a mut self,
                                   fs_uuids: &[&'b FilesystemUuid])
                                   -> EngineResult<Vec<&'b FilesystemUuid>> {
        destroy_filesystems!{self; fs_uuids}
    }

    fn rename_filesystem(&mut self,
                         uuid: &FilesystemUuid,
                         new_name: &str)
                         -> EngineResult<RenameAction> {
        rename_filesystem!{self; uuid; new_name}
    }

    fn rename(&mut self, name: &str) {
        self.name = name.to_owned();
    }

    fn get_filesystem(&mut self, uuid: &FilesystemUuid) -> Option<&mut Filesystem> {
        get_filesystem!(self; uuid)
    }
}

impl HasUuid for StratPool {
    fn uuid(&self) -> &FilesystemUuid {
        &self.pool_uuid
    }
}

impl HasName for StratPool {
    fn name(&self) -> &str {
        &self.name
    }
}

impl Isomorphism<PoolSave> for StratPool {
    fn to_save(&self) -> PoolSave {
        PoolSave { name: self.name.clone() }
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove page_size argument for layer creation<commit_after><|endoftext|>


<commit_before><commit_msg>imports added<commit_after><|endoftext|>