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

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

use rustc::hir::def_id::CrateNum;
use rustc::middle::cstore::LibSource;

pub struct RPathConfig<'a> {
    pub used_crates: Vec<(CrateNum, LibSource)>,
    pub out_filename: PathBuf,
    pub is_like_osx: bool,
    pub has_rpath: bool,
    pub linker_is_gnu: bool,
    pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
}

pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
    // No rpath on windows
    if !config.has_rpath {
        return Vec::new();
    }

    let mut flags = Vec::new();

    debug!("preparing the RPATH!");

    let libs = config.used_crates.clone();
    let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
    let rpaths = get_rpaths(config, &libs[..]);
    flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));

    // Use DT_RUNPATH instead of DT_RPATH if available
    if config.linker_is_gnu {
        flags.push("-Wl,--enable-new-dtags".to_string());
    }

    flags
}

fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
    let mut ret = Vec::new();
    for rpath in rpaths {
        ret.push(format!("-Wl,-rpath,{}", &(*rpath)));
    }
    return ret;
}

fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec<String> {
    debug!("output: {:?}", config.out_filename.display());
    debug!("libs:");
    for libpath in libs {
        debug!("    {:?}", libpath.display());
    }

    // Use relative paths to the libraries. Binaries can be moved
    // as long as they maintain the relative relationship to the
    // crates they depend on.
    let rel_rpaths = get_rpaths_relative_to_output(config, libs);

    // And a final backup rpath to the global library location.
    let fallback_rpaths = vec![get_install_prefix_rpath(config)];

    fn log_rpaths(desc: &str, rpaths: &[String]) {
        debug!("{} rpaths:", desc);
        for rpath in rpaths {
            debug!("    {}", *rpath);
        }
    }

    log_rpaths("relative", &rel_rpaths[..]);
    log_rpaths("fallback", &fallback_rpaths[..]);

    let mut rpaths = rel_rpaths;
    rpaths.extend_from_slice(&fallback_rpaths[..]);

    // Remove duplicates
    let rpaths = minimize_rpaths(&rpaths[..]);
    return rpaths;
}

fn get_rpaths_relative_to_output(config: &mut RPathConfig,
                                 libs: &[PathBuf]) -> Vec<String> {
    libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
}

fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String {
    // Mac doesn't appear to support $ORIGIN
    let prefix = if config.is_like_osx {
        "@loader_path"
    } else {
        "$ORIGIN"
    };

    let cwd = env::current_dir().unwrap();
    let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or(cwd.join(lib));
    lib.pop();
    let mut output = cwd.join(&config.out_filename);
    output.pop();
    let output = fs::canonicalize(&output).unwrap_or(output);
    let relative = path_relative_from(&lib, &output)
        .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
    // FIXME (#9639): This needs to handle non-utf8 paths
    format!("{}/{}", prefix,
            relative.to_str().expect("non-utf8 component in path"))
}

// This routine is adapted from the *old* Path's `path_relative_from`
// function, which works differently from the new `relative_from` function.
// In particular, this handles the case on unix where both paths are
// absolute but with only the root as the common directory.
fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
    use std::path::Component;

    if path.is_absolute() != base.is_absolute() {
        if path.is_absolute() {
            Some(PathBuf::from(path))
        } else {
            None
        }
    } else {
        let mut ita = path.components();
        let mut itb = base.components();
        let mut comps: Vec<Component> = vec![];
        loop {
            match (ita.next(), itb.next()) {
                (None, None) => break,
                (Some(a), None) => {
                    comps.push(a);
                    comps.extend(ita.by_ref());
                    break;
                }
                (None, _) => comps.push(Component::ParentDir),
                (Some(a), Some(b)) if comps.is_empty() && a == b => (),
                (Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
                (Some(_), Some(b)) if b == Component::ParentDir => return None,
                (Some(a), Some(_)) => {
                    comps.push(Component::ParentDir);
                    for _ in itb {
                        comps.push(Component::ParentDir);
                    }
                    comps.push(a);
                    comps.extend(ita.by_ref());
                    break;
                }
            }
        }
        Some(comps.iter().map(|c| c.as_os_str()).collect())
    }
}

fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
    let path = (config.get_install_prefix_lib_path)();
    let path = env::current_dir().unwrap().join(&path);
    // FIXME (#9639): This needs to handle non-utf8 paths
    path.to_str().expect("non-utf8 component in rpath").to_string()
}

fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
    let mut set = HashSet::new();
    let mut minimized = Vec::new();
    for rpath in rpaths {
        if set.insert(&rpath[..]) {
            minimized.push(rpath.clone());
        }
    }
    minimized
}

#[cfg(all(unix, test))]
mod tests {
    use super::{RPathConfig};
    use super::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
    use std::path::{Path, PathBuf};

    #[test]
    fn test_rpaths_to_flags() {
        let flags = rpaths_to_flags(&[
            "path1".to_string(),
            "path2".to_string()
        ]);
        assert_eq!(flags,
                   ["-Wl,-rpath,path1",
                    "-Wl,-rpath,path2"]);
    }

    #[test]
    fn test_minimize1() {
        let res = minimize_rpaths(&[
            "rpath1".to_string(),
            "rpath2".to_string(),
            "rpath1".to_string()
        ]);
        assert!(res == [
            "rpath1",
            "rpath2",
        ]);
    }

    #[test]
    fn test_minimize2() {
        let res = minimize_rpaths(&[
            "1a".to_string(),
            "2".to_string(),
            "2".to_string(),
            "1a".to_string(),
            "4a".to_string(),
            "1a".to_string(),
            "2".to_string(),
            "3".to_string(),
            "4a".to_string(),
            "3".to_string()
        ]);
        assert!(res == [
            "1a",
            "2",
            "4a",
            "3",
        ]);
    }

    #[test]
    fn test_rpath_relative() {
        if cfg!(target_os = "macos") {
            let config = &mut RPathConfig {
                used_crates: Vec::new(),
                has_rpath: true,
                is_like_osx: true,
                linker_is_gnu: false,
                out_filename: PathBuf::from("bin/rustc"),
                get_install_prefix_lib_path: &mut || panic!(),
            };
            let res = get_rpath_relative_to_output(config,
                                                   Path::new("lib/libstd.so"));
            assert_eq!(res, "@loader_path/../lib");
        } else {
            let config = &mut RPathConfig {
                used_crates: Vec::new(),
                out_filename: PathBuf::from("bin/rustc"),
                get_install_prefix_lib_path: &mut || panic!(),
                has_rpath: true,
                is_like_osx: false,
                linker_is_gnu: true,
            };
            let res = get_rpath_relative_to_output(config,
                                                   Path::new("lib/libstd.so"));
            assert_eq!(res, "$ORIGIN/../lib");
        }
    }
}
<commit_msg>Auto merge of #38798 - jsgf:fix-rpath, r=nikomatsakis<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

use rustc::hir::def_id::CrateNum;
use rustc::middle::cstore::LibSource;

pub struct RPathConfig<'a> {
    pub used_crates: Vec<(CrateNum, LibSource)>,
    pub out_filename: PathBuf,
    pub is_like_osx: bool,
    pub has_rpath: bool,
    pub linker_is_gnu: bool,
    pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
}

pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
    // No rpath on windows
    if !config.has_rpath {
        return Vec::new();
    }

    let mut flags = Vec::new();

    debug!("preparing the RPATH!");

    let libs = config.used_crates.clone();
    let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
    let rpaths = get_rpaths(config, &libs[..]);
    flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));

    // Use DT_RUNPATH instead of DT_RPATH if available
    if config.linker_is_gnu {
        flags.push("-Wl,--enable-new-dtags".to_string());
    }

    flags
}

fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
    let mut ret = Vec::new();
    for rpath in rpaths {
        if rpath.contains(',') {
            ret.push("-Wl,-rpath".into());
            ret.push("-Xlinker".into());
            ret.push(rpath.clone());
        } else {
            ret.push(format!("-Wl,-rpath,{}", &(*rpath)));
        }
    }
    return ret;
}

fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec<String> {
    debug!("output: {:?}", config.out_filename.display());
    debug!("libs:");
    for libpath in libs {
        debug!("    {:?}", libpath.display());
    }

    // Use relative paths to the libraries. Binaries can be moved
    // as long as they maintain the relative relationship to the
    // crates they depend on.
    let rel_rpaths = get_rpaths_relative_to_output(config, libs);

    // And a final backup rpath to the global library location.
    let fallback_rpaths = vec![get_install_prefix_rpath(config)];

    fn log_rpaths(desc: &str, rpaths: &[String]) {
        debug!("{} rpaths:", desc);
        for rpath in rpaths {
            debug!("    {}", *rpath);
        }
    }

    log_rpaths("relative", &rel_rpaths[..]);
    log_rpaths("fallback", &fallback_rpaths[..]);

    let mut rpaths = rel_rpaths;
    rpaths.extend_from_slice(&fallback_rpaths[..]);

    // Remove duplicates
    let rpaths = minimize_rpaths(&rpaths[..]);
    return rpaths;
}

fn get_rpaths_relative_to_output(config: &mut RPathConfig,
                                 libs: &[PathBuf]) -> Vec<String> {
    libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
}

fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String {
    // Mac doesn't appear to support $ORIGIN
    let prefix = if config.is_like_osx {
        "@loader_path"
    } else {
        "$ORIGIN"
    };

    let cwd = env::current_dir().unwrap();
    let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or(cwd.join(lib));
    lib.pop();
    let mut output = cwd.join(&config.out_filename);
    output.pop();
    let output = fs::canonicalize(&output).unwrap_or(output);
    let relative = path_relative_from(&lib, &output)
        .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
    // FIXME (#9639): This needs to handle non-utf8 paths
    format!("{}/{}", prefix,
            relative.to_str().expect("non-utf8 component in path"))
}

// This routine is adapted from the *old* Path's `path_relative_from`
// function, which works differently from the new `relative_from` function.
// In particular, this handles the case on unix where both paths are
// absolute but with only the root as the common directory.
fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
    use std::path::Component;

    if path.is_absolute() != base.is_absolute() {
        if path.is_absolute() {
            Some(PathBuf::from(path))
        } else {
            None
        }
    } else {
        let mut ita = path.components();
        let mut itb = base.components();
        let mut comps: Vec<Component> = vec![];
        loop {
            match (ita.next(), itb.next()) {
                (None, None) => break,
                (Some(a), None) => {
                    comps.push(a);
                    comps.extend(ita.by_ref());
                    break;
                }
                (None, _) => comps.push(Component::ParentDir),
                (Some(a), Some(b)) if comps.is_empty() && a == b => (),
                (Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
                (Some(_), Some(b)) if b == Component::ParentDir => return None,
                (Some(a), Some(_)) => {
                    comps.push(Component::ParentDir);
                    for _ in itb {
                        comps.push(Component::ParentDir);
                    }
                    comps.push(a);
                    comps.extend(ita.by_ref());
                    break;
                }
            }
        }
        Some(comps.iter().map(|c| c.as_os_str()).collect())
    }
}

fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
    let path = (config.get_install_prefix_lib_path)();
    let path = env::current_dir().unwrap().join(&path);
    // FIXME (#9639): This needs to handle non-utf8 paths
    path.to_str().expect("non-utf8 component in rpath").to_string()
}

fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
    let mut set = HashSet::new();
    let mut minimized = Vec::new();
    for rpath in rpaths {
        if set.insert(&rpath[..]) {
            minimized.push(rpath.clone());
        }
    }
    minimized
}

#[cfg(all(unix, test))]
mod tests {
    use super::{RPathConfig};
    use super::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
    use std::path::{Path, PathBuf};

    #[test]
    fn test_rpaths_to_flags() {
        let flags = rpaths_to_flags(&[
            "path1".to_string(),
            "path2".to_string()
        ]);
        assert_eq!(flags,
                   ["-Wl,-rpath,path1",
                    "-Wl,-rpath,path2"]);
    }

    #[test]
    fn test_minimize1() {
        let res = minimize_rpaths(&[
            "rpath1".to_string(),
            "rpath2".to_string(),
            "rpath1".to_string()
        ]);
        assert!(res == [
            "rpath1",
            "rpath2",
        ]);
    }

    #[test]
    fn test_minimize2() {
        let res = minimize_rpaths(&[
            "1a".to_string(),
            "2".to_string(),
            "2".to_string(),
            "1a".to_string(),
            "4a".to_string(),
            "1a".to_string(),
            "2".to_string(),
            "3".to_string(),
            "4a".to_string(),
            "3".to_string()
        ]);
        assert!(res == [
            "1a",
            "2",
            "4a",
            "3",
        ]);
    }

    #[test]
    fn test_rpath_relative() {
        if cfg!(target_os = "macos") {
            let config = &mut RPathConfig {
                used_crates: Vec::new(),
                has_rpath: true,
                is_like_osx: true,
                linker_is_gnu: false,
                out_filename: PathBuf::from("bin/rustc"),
                get_install_prefix_lib_path: &mut || panic!(),
            };
            let res = get_rpath_relative_to_output(config,
                                                   Path::new("lib/libstd.so"));
            assert_eq!(res, "@loader_path/../lib");
        } else {
            let config = &mut RPathConfig {
                used_crates: Vec::new(),
                out_filename: PathBuf::from("bin/rustc"),
                get_install_prefix_lib_path: &mut || panic!(),
                has_rpath: true,
                is_like_osx: false,
                linker_is_gnu: true,
            };
            let res = get_rpath_relative_to_output(config,
                                                   Path::new("lib/libstd.so"));
            assert_eq!(res, "$ORIGIN/../lib");
        }
    }

    #[test]
    fn test_xlinker() {
        let args = rpaths_to_flags(&[
            "a/normal/path".to_string(),
            "a,comma,path".to_string()
        ]);

        assert_eq!(args, vec![
            "-Wl,-rpath,a/normal/path".to_string(),
            "-Wl,-rpath".to_string(),
            "-Xlinker".to_string(),
            "a,comma,path".to_string()
        ]);
    }
}
<|endoftext|>


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

#![feature(unsafe_destructor)]

struct Leak<'a> {
    dropped: &'a mut bool
}

#[unsafe_destructor]
impl<'a> Drop for Leak<'a> {
    fn drop(&mut self) {
        *self.dropped = true;
    }
}

fn main() {
    let mut dropped = false;
    {
        let leak = Leak { dropped: &mut dropped };
        for ((), leaked) in Some(((),leak)).move_iter() {}
    }

    assert!(dropped);
}
<|endoftext|>


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

#![allow(dead_code)]

// this code used to cause an ICE

trait X<T> {}

struct S<T> {f: Box<X<T>>, g: Box<X<T>>}

struct F;
impl X<int> for F {}

fn main() {
  S {f: box F, g: box F};
}
<|endoftext|>


<commit_before><commit_msg>Optimize implementation: Less matches<commit_after><|endoftext|>


<commit_before><commit_msg>Initial commit with context initialization and drop<commit_after>struct TssContext { handle: u32 }
struct TssTpm { handle: u32 }

type TssHContext = u32;
type TssResult = u32;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_Create(&mut handle);
            if result == TSS_SUCCESS {
                Ok(TssContext { handle: handle })
            } else {
                Err(result)
            }
        }
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_Close(self.handle);
        }
    }
}

fn main() {
    let blah = TssContext::new();
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
}
<|endoftext|>


<commit_before><commit_msg>rustfmt<commit_after><|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::fs::create_dir;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;

use devicemapper::DM;
use uuid::Uuid;

use super::super::engine::{Engine, HasName, HasUuid, Pool};
use super::super::errors::{EngineError, EngineResult, ErrorEnum};
use super::super::structures::Table;
use super::super::types::{PoolUuid, Redundancy, RenameAction};

use super::pool::StratPool;
use super::setup::{find_all, get_blockdevmgr, get_metadata};

pub const DEV_PATH: &'static str = "/dev/stratis";

#[derive(Debug, PartialEq, Eq)]
pub enum DevOwnership {
    Ours(Uuid),
    Unowned,
    Theirs,
}

#[derive(Debug)]
pub struct StratEngine {
    pools: Table<StratPool>,
}

impl StratEngine {
    pub fn initialize() -> EngineResult<StratEngine> {
        if let Err(err) = create_dir(DEV_PATH) {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        let pools = try!(find_all());

        // FIXME: This is quite clearly incomplete pool reconstruction.
        for (pool_uuid, devices) in pools.iter() {
            let pool_save = try!(try!(get_metadata(pool_uuid, devices))
                                     .ok_or(EngineError::Engine(ErrorEnum::NotFound,
                                                                format!("no metadata for pool {}",
                                                                        pool_uuid))));
            let _ = get_blockdevmgr(&pool_save, devices);
        }
        if !pools.is_empty() {
            let err_msg = "Stratis was already run once, can not yet reconstruct state";
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, err_msg.into()));
        }

        Ok(StratEngine { pools: Table::new() })
    }

    /// Teardown Stratis, preparatory to a shutdown.
    pub fn teardown(self) -> EngineResult<()> {
        for pool in self.pools.empty() {
            try!(pool.teardown());
        }
        Ok(())
    }
}

impl Engine for StratEngine {
    fn configure_simulator(&mut self, _denominator: u32) -> EngineResult<()> {
        Ok(()) // we're not the simulator and not configurable, so just say ok
    }

    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<(PoolUuid, Vec<PathBuf>)> {

        let redundancy = calculate_redundancy!(redundancy);

        if self.pools.contains_name(name) {
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.into()));
        }

        let dm = try!(DM::new());
        let pool = try!(StratPool::initialize(name, &dm, blockdev_paths, redundancy, force));
        let bdev_devnodes = pool.block_devs.devnodes();

        let uuid = pool.uuid().clone();
        self.pools.insert(pool);
        Ok((uuid, bdev_devnodes))
    }

    fn destroy_pool(&mut self, uuid: &PoolUuid) -> EngineResult<bool> {
        destroy_pool!{self; uuid}
    }

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

    fn get_pool(&mut self, uuid: &PoolUuid) -> Option<&mut Pool> {
        get_pool!(self; uuid)
    }

    fn check(&mut self) -> () {
        check_engine!(self);
    }
}
<commit_msg>Add a method to get a pool as an immutable StratPool<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::fs::create_dir;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;

use devicemapper::DM;
use uuid::Uuid;

use super::super::engine::{Engine, HasName, HasUuid, Pool};
use super::super::errors::{EngineError, EngineResult, ErrorEnum};
use super::super::structures::Table;
use super::super::types::{PoolUuid, Redundancy, RenameAction};

use super::pool::StratPool;
use super::setup::{find_all, get_blockdevmgr, get_metadata};

pub const DEV_PATH: &'static str = "/dev/stratis";

#[derive(Debug, PartialEq, Eq)]
pub enum DevOwnership {
    Ours(Uuid),
    Unowned,
    Theirs,
}

#[derive(Debug)]
pub struct StratEngine {
    pools: Table<StratPool>,
}

impl StratEngine {
    pub fn initialize() -> EngineResult<StratEngine> {
        if let Err(err) = create_dir(DEV_PATH) {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        let pools = try!(find_all());

        // FIXME: This is quite clearly incomplete pool reconstruction.
        for (pool_uuid, devices) in pools.iter() {
            let pool_save = try!(try!(get_metadata(pool_uuid, devices))
                                     .ok_or(EngineError::Engine(ErrorEnum::NotFound,
                                                                format!("no metadata for pool {}",
                                                                        pool_uuid))));
            let _ = get_blockdevmgr(&pool_save, devices);
        }
        if !pools.is_empty() {
            let err_msg = "Stratis was already run once, can not yet reconstruct state";
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, err_msg.into()));
        }

        Ok(StratEngine { pools: Table::new() })
    }

    /// Teardown Stratis, preparatory to a shutdown.
    pub fn teardown(self) -> EngineResult<()> {
        for pool in self.pools.empty() {
            try!(pool.teardown());
        }
        Ok(())
    }

    /// Get pool as StratPool
    pub fn get_strat_pool(&self, uuid: &PoolUuid) -> Option<&StratPool> {
        self.pools.get_by_uuid(uuid)
    }
}

impl Engine for StratEngine {
    fn configure_simulator(&mut self, _denominator: u32) -> EngineResult<()> {
        Ok(()) // we're not the simulator and not configurable, so just say ok
    }

    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<(PoolUuid, Vec<PathBuf>)> {

        let redundancy = calculate_redundancy!(redundancy);

        if self.pools.contains_name(name) {
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.into()));
        }

        let dm = try!(DM::new());
        let pool = try!(StratPool::initialize(name, &dm, blockdev_paths, redundancy, force));
        let bdev_devnodes = pool.block_devs.devnodes();

        let uuid = pool.uuid().clone();
        self.pools.insert(pool);
        Ok((uuid, bdev_devnodes))
    }

    fn destroy_pool(&mut self, uuid: &PoolUuid) -> EngineResult<bool> {
        destroy_pool!{self; uuid}
    }

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

    fn get_pool(&mut self, uuid: &PoolUuid) -> Option<&mut Pool> {
        get_pool!(self; uuid)
    }

    fn check(&mut self) -> () {
        check_engine!(self);
    }
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #26670 - frewsxcv:regression-test-13902, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
const JSVAL_TYPE_INT32: u8 = 0x01;
const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
#[repr(u32)]
enum ValueTag {
    JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
    JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
}

fn main() {
    let _ = ValueTag::JSVAL_TAG_INT32;
}
<|endoftext|>


<commit_before><commit_msg>rustup<commit_after><|endoftext|>


<commit_before><commit_msg>added usable_cores test<commit_after><|endoftext|>


<commit_before><commit_msg>Extract events tests from mod.rs<commit_after>    use std::io;
    use std::thread;
    use std::net::SocketAddr;
    use std::collections::VecDeque;

    use time::{get_time, Duration};
    use env_logger;

    use super::{Events, Reactor, Event, InternalEvent, Channel};
    use super::{Network, NetworkConfiguration, EventHandler};

    use ::messages::{MessageWriter, RawMessage};
    use ::crypto::gen_keypair;

    pub type TestEvent = InternalEvent<(), u32>;

    pub struct TestHandler {
        events: VecDeque<TestEvent>,
        messages: VecDeque<RawMessage>,
    }

    pub trait TestPoller {
        fn event(&mut self) -> Option<TestEvent>;
        fn message(&mut self) -> Option<RawMessage>;
    }

    impl TestHandler {
        pub fn new() -> TestHandler {
            TestHandler {
                events: VecDeque::new(),
                messages: VecDeque::new(),
            }
        }
    }

    impl TestPoller for TestHandler {
        fn event(&mut self) -> Option<TestEvent> {
            self.events.pop_front()
        }
        fn message(&mut self) -> Option<RawMessage> {
            self.messages.pop_front()
        }
    }

    impl EventHandler for TestHandler {
        type Timeout = ();
        type ApplicationEvent = ();

        fn handle_event(&mut self, event: Event) {
            info!("handle event: {:?}", event);
            match event {
                Event::Incoming(raw) => self.messages.push_back(raw),
                _ => {
                    self.events.push_back(InternalEvent::Node(event));
                }
            }
        }
        fn handle_timeout(&mut self, _: Self::Timeout) {}
        fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
            self.events.push_back(InternalEvent::Application(event));
        }
    }

    pub struct TestEvents(pub Events<TestHandler>);

    impl TestEvents {
        pub fn with_addr(addr: SocketAddr) -> TestEvents {
            let network = Network::with_config(addr,
                                               NetworkConfiguration {
                                                   max_incoming_connections: 128,
                                                   max_outgoing_connections: 128,
                                                   tcp_nodelay: true,
                                                   tcp_keep_alive: Some(1),
                                                   tcp_reconnect_timeout: 1000,
                                                   tcp_reconnect_timeout_max: 600000,
                                               });
            let handler = TestHandler::new();

            TestEvents(Events::new(network, handler).unwrap())
        }

        pub fn wait_for_bind(&mut self, addr: &SocketAddr) -> Option<()> {
            self.0.bind().unwrap();
            self.wait_for_connect(addr)
        }

        pub fn wait_for_connect(&mut self, addr: &SocketAddr) -> Option<()> {
            self.0.channel().connect(addr);

            let start = get_time();
            loop {
                self.process_events().unwrap();

                if start + Duration::milliseconds(10000) < get_time() {
                    return None;
                }
                while let Some(e) = self.0.inner.handler.event() {
                    match e {
                        InternalEvent::Node(Event::Connected(_)) => return Some(()),
                        _ => {}
                    }
                }
            }
        }

        pub fn wait_for_message(&mut self, duration: Duration) -> Option<RawMessage> {
            let start = get_time();
            loop {
                self.process_events().unwrap();

                if start + duration < get_time() {
                    return None;
                }

                while let Some(e) = self.0.inner.handler.event() {
                    match e {
                        InternalEvent::Node(Event::Error(e)) => {
                            error!("An error during wait occured {:?}", e);
                        }
                        _ => {}
                    }
                }

                if let Some(msg) = self.0.inner.handler.message() {
                    return Some(msg);
                }
            }
        }

        pub fn wait_for_messages(&mut self,
                                 mut count: usize,
                                 duration: Duration)
                                 -> Result<Vec<RawMessage>, String> {
            let mut v = Vec::new();
            let start = get_time();
            loop {
                self.process_events().unwrap();

                if start + duration < get_time() {
                    return Err(format!("Timeout exceeded, {} messages is not received", count));
                }

                if let Some(msg) = self.0.inner.handler.message() {
                    v.push(msg);
                    count -= 1;
                    if count == 0 {
                        return Ok(v);
                    }
                }
            }
        }

        pub fn wait_for_disconnect(&mut self, max_duration: Duration) -> Option<()> {
            let start = get_time();
            loop {
                self.process_events().unwrap();

                if start + max_duration < get_time() {
                    return None;
                }
                while let Some(e) = self.0.inner.handler.event() {
                    match e {
                        InternalEvent::Node(Event::Disconnected(_)) => return Some(()),
                        _ => {}
                    }
                }
            }
        }

        pub fn send_to(&mut self, addr: &SocketAddr, msg: RawMessage) {
            self.0.channel().send_to(addr, msg);
            self.process_events().unwrap();
        }

        pub fn process_events(&mut self) -> io::Result<()> {
            self.0.run_once(Some(100))
        }
    }

    pub fn gen_message(id: u16, len: usize) -> RawMessage {
        let writer = MessageWriter::new(id, len);
        RawMessage::new(writer.sign(&gen_keypair().1))
    }

    #[test]
    fn big_message() {
        let _ = env_logger::init();
        let addrs: [SocketAddr; 2] = ["127.0.0.1:7200".parse().unwrap(),
                                      "127.0.0.1:7201".parse().unwrap()];

        let m1 = gen_message(15, 100000);
        let m2 = gen_message(16, 400);

        let mut e1 = TestEvents::with_addr(addrs[0]);
        let mut e2 = TestEvents::with_addr(addrs[1]);
        e1.0.bind().unwrap();
        e2.0.bind().unwrap();

        let t1;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            t1 = thread::spawn(move || {
                let mut e = e1;
                e.wait_for_connect(&addrs[1]);

                e.send_to(&addrs[1], m1.clone());
                e.send_to(&addrs[1], m2.clone());
                e.send_to(&addrs[1], m1.clone());

                let msgs = e.wait_for_messages(3, Duration::milliseconds(10000)).unwrap();
                assert_eq!(msgs[0], m2);
                assert_eq!(msgs[1], m1);
                assert_eq!(msgs[2], m2);
            });
        }

        let t2;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            t2 = thread::spawn(move || {
                let mut e = e2;
                e.wait_for_connect(&addrs[0]);

                e.send_to(&addrs[0], m2.clone());
                e.send_to(&addrs[0], m1.clone());
                e.send_to(&addrs[0], m2.clone());
                let msgs = e.wait_for_messages(3, Duration::milliseconds(10000)).unwrap();
                assert_eq!(msgs[0], m1);
                assert_eq!(msgs[1], m2);
                assert_eq!(msgs[2], m1);
                e.wait_for_disconnect(Duration::milliseconds(10000)).unwrap();
            });
        }

        t2.join().unwrap();
        t1.join().unwrap();
    }

    #[test]
    fn reconnect() {
        let _ = env_logger::init();
        let addrs: [SocketAddr; 2] = ["127.0.0.1:9100".parse().unwrap(),
                                      "127.0.0.1:9101".parse().unwrap()];

        let m1 = gen_message(15, 250);
        let m2 = gen_message(16, 400);
        let m3 = gen_message(17, 600);

        let mut e1 = TestEvents::with_addr(addrs[0]);
        let mut e2 = TestEvents::with_addr(addrs[1]);
        e1.0.bind().unwrap();
        e2.0.bind().unwrap();

        let t1;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            let m3 = m3.clone();
            t1 = thread::spawn(move || {
                {
                    let mut e = e1;
                    e.wait_for_connect(&addrs[1]).unwrap();

                    debug!("t1: connection opened");
                    debug!("t1: send m1 to t2");
                    e.send_to(&addrs[1], m1);
                    debug!("t1: wait for m2");
                    assert_eq!(e.wait_for_message(Duration::milliseconds(5000)), Some(m2));
                    debug!("t1: received m2 from t2");
                }
                debug!("t1: connection closed");
                {
                    let mut e = TestEvents::with_addr(addrs[0]);
                    e.wait_for_bind(&addrs[1]).unwrap();

                    debug!("t1: connection reopened");
                    debug!("t1: send m3 to t2");
                    e.send_to(&addrs[1], m3.clone());
                    debug!("t1: wait for m3");
                    assert_eq!(e.wait_for_message(Duration::milliseconds(5000)), Some(m3));
                    debug!("t1: received m3 from t2");
                    e.process_events().unwrap();
                }
                debug!("t1: finished");
            });
        }

        let t2;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            let m3 = m3.clone();
            t2 = thread::spawn(move || {
                {
                    let mut e = e2;
                    e.wait_for_connect(&addrs[0]).unwrap();

                    debug!("t2: connection opened");
                    debug!("t2: send m2 to t1");
                    e.send_to(&addrs[0], m2);
                    debug!("t2: wait for m1");
                    assert_eq!(e.wait_for_message(Duration::milliseconds(5000)), Some(m1));
                    debug!("t2: received m1 from t1");
                    debug!("t2: wait for m3");
                    assert_eq!(e.wait_for_message(Duration::milliseconds(5000)),
                               Some(m3.clone()));
                    debug!("t2: received m3 from t1");
                }
                debug!("t2: connection closed");
                {
                    debug!("t2: connection reopened");
                    let mut e = TestEvents::with_addr(addrs[1]);
                    e.wait_for_bind(&addrs[0]).unwrap();

                    debug!("t2: send m3 to t1");
                    e.send_to(&addrs[0], m3.clone());
                    e.wait_for_disconnect(Duration::milliseconds(5000)).unwrap();
                }
                debug!("t2: finished");
            });
        }

        t2.join().unwrap();
        t1.join().unwrap();
    }

#[cfg(feature = "long_benchmarks")]
mod benches {

    use std::thread;
    use std::net::SocketAddr;

    use time::Duration;

    use ::events::{Network, NetworkConfiguration, Events, Reactor};
    use super::{gen_message, TestEvents, TestHandler};

    use test::Bencher;

    struct BenchConfig {
        times: usize,
        len: usize,
        tcp_nodelay: bool,
    }

    impl TestEvents {
        fn with_cfg(cfg: &BenchConfig, addr: SocketAddr) -> TestEvents {
            let network = Network::with_config(addr,
                                               NetworkConfiguration {
                                                   max_incoming_connections: 128,
                                                   max_outgoing_connections: 128,
                                                   tcp_nodelay: cfg.tcp_nodelay,
                                                   tcp_keep_alive: None,
                                                   tcp_reconnect_timeout: 1000,
                                                   tcp_reconnect_timeout_max: 600000,
                                               });
            let handler = TestHandler::new();

            TestEvents(Events::new(network, handler).unwrap())
        }
    }

    fn bench_network(b: &mut Bencher, addrs: [SocketAddr; 2], cfg: BenchConfig) {
        b.iter(|| {
            let mut e1 = TestEvents::with_cfg(&cfg, addrs[0]);
            let mut e2 = TestEvents::with_cfg(&cfg, addrs[1]);
            e1.0.bind().unwrap();
            e2.0.bind().unwrap();

            let timeout = Duration::seconds(30);
            let len = cfg.len;
            let times = cfg.times;
            let t1 = thread::spawn(move || {
                e1.wait_for_connect(&addrs[1]).unwrap();
                for _ in 0..times {
                    let msg = gen_message(0, len);
                    e1.send_to(&addrs[1], msg);
                    e1.wait_for_messages(1, timeout).unwrap();
                }
                e1.wait_for_disconnect(Duration::milliseconds(1000)).unwrap();
            });
            let t2 = thread::spawn(move || {
                e2.wait_for_connect(&addrs[0]).unwrap();
                for _ in 0..times {
                    let msg = gen_message(1, len);
                    e2.send_to(&addrs[0], msg);
                    e2.wait_for_messages(1, timeout).unwrap();
                }
            });
            t1.join().unwrap();
            t2.join().unwrap();
        })
    }

    #[bench]
    fn bench_msg_short_100(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100,
            times: 100,
        };
        let addrs = ["127.0.0.1:6990".parse().unwrap(), "127.0.0.1:6991".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_short_1000(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100,
            times: 1000,
        };
        let addrs = ["127.0.0.1:9792".parse().unwrap(), "127.0.0.1:9793".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_short_10000(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100,
            times: 10000,
        };
        let addrs = ["127.0.0.1:9982".parse().unwrap(), "127.0.0.1:9983".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_short_100_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 100,
        };
        let addrs = ["127.0.0.1:4990".parse().unwrap(), "127.0.0.1:4991".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_short_10000_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 10000,
        };
        let addrs = ["127.0.0.1:5990".parse().unwrap(), "127.0.0.1:5991".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_long_10(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100000,
            times: 10,
        };
        let addrs = ["127.0.0.1:9984".parse().unwrap(), "127.0.0.1:9985".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_long_100(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100000,
            times: 100,
        };
        let addrs = ["127.0.0.1:9946".parse().unwrap(), "127.0.0.1:9947".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }

    #[bench]
    fn bench_msg_long_100_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100000,
            times: 100,
        };
        let addrs = ["127.0.0.1:9198".parse().unwrap(), "127.0.0.1:9199".parse().unwrap()];
        bench_network(b, addrs, cfg);
    }
}<|endoftext|>


<commit_before><commit_msg>Add regression test for issue 73899<commit_after>// run-pass
#![feature(const_evaluatable_checked)]
#![feature(const_generics)]
#![allow(incomplete_features)]

trait Foo {}

impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}

trait FooImpl<const IS_ZERO: bool> {}

impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}

impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}

fn foo<T: Foo>(_v: T) {}

fn main() {
    foo([]);
    foo([()]);
}
<|endoftext|>


<commit_before><commit_msg>Fix the shader unit test that was failing to build<commit_after><|endoftext|>


<commit_before><commit_msg>Change reading mechanism of read_client_packet<commit_after><|endoftext|>


<commit_before><commit_msg>Manually map out bitmaps tags<commit_after><|endoftext|>


<commit_before><commit_msg>Start of testing for HTTP request line()<commit_after><|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use toml::Value;
use toml_query::read::TomlValueReadExt;
use toml_query::insert::TomlValueInsertExt;
use chrono::NaiveDateTime;
use chrono::Local;
use chrono::NaiveDate;

use error::HabitError as HE;
use error::HabitErrorKind as HEK;
use error::*;
use iter::HabitInstanceStoreIdIterator;
use util::date_to_string;
use util::IsHabitCheck;
use util::get_string_header_from_entry;

use libimagentrylink::internal::InternalLinker;
use libimagstore::store::Store;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Entry;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreIdIterator;

/// A HabitTemplate is a "template" of a habit. A user may define a habit "Eat vegetable".
/// If the user ate a vegetable, she should create a HabitInstance from the Habit with the
/// appropriate date (and optionally a comment) set.
pub trait HabitTemplate : Sized {

    /// Create an instance from this habit template
    ///
    /// By default creates an instance with the name of the template, the current time and the
    /// current date and copies the comment from the template to the instance.
    ///
    /// It uses `Store::retrieve()` underneath. So if there is already an instance for the day
    /// passed, this will simply return the instance.
    fn create_instance_with_date<'a>(&self, store: &'a Store, date: &NaiveDate)
        -> Result<FileLockEntry<'a>>;

    /// Shortcut for calling `Self::create_instance_with_date()` with an instance of
    /// `::chrono::Local::today().naive_local()`.
    fn create_instance_today<'a>(&self, store: &'a Store) -> Result<FileLockEntry<'a>>;

    /// Get instances for this template
    fn linked_instances(&self) -> Result<HabitInstanceStoreIdIterator>;

    /// Get the date of the next date when the habit should be done
    fn next_instance_date_after(&self, base: &NaiveDateTime) -> Result<Option<NaiveDate>>;

    /// Get the date of the next date when the habit should be done
    fn next_instance_date(&self) -> Result<Option<NaiveDate>>;

    /// Check whether the instance is a habit by checking its headers for the habit data
    fn is_habit_template(&self) -> Result<bool>;

    fn habit_name(&self) -> Result<String>;
    fn habit_basedate(&self) -> Result<String>;
    fn habit_recur_spec(&self) -> Result<String>;
    fn habit_comment(&self) -> Result<String>;
    fn habit_until_date(&self) -> Result<Option<String>>;

    /// Create a StoreId for a habit name and a date the habit should be instantiated for
    fn instance_id_for(habit_name: &String, habit_date: &NaiveDate) -> Result<StoreId>;
}

impl HabitTemplate for Entry {

    fn create_instance_with_date<'a>(&self, store: &'a Store, date: &NaiveDate) -> Result<FileLockEntry<'a>> {
        let name    = self.habit_name()?;
        let comment = self.habit_comment()?;
        let date    = date_to_string(date);
        let id      = instance_id_for_name_and_datestr(&name, &date)?;

        store.retrieve(id)
            .map_err(From::from)
            .and_then(|mut entry| {
                {
                    let hdr = entry.get_header_mut();
                    hdr.insert("habit.instance.name",    Value::String(name))?;
                    hdr.insert("habit.instance.date",    Value::String(date))?;
                    hdr.insert("habit.instance.comment", Value::String(comment))?;
                }
                Ok(entry)
            })
    }

    fn create_instance_today<'a>(&self, store: &'a Store) -> Result<FileLockEntry<'a>> {
        self.create_instance_with_date(store, &Local::today().naive_local())
    }

    fn linked_instances(&self) -> Result<HabitInstanceStoreIdIterator> {
        let iter = self
            .get_internal_links()?
            .map(|link| link.get_store_id().clone())
            .filter(IsHabitCheck::is_habit_instance);

        let sidi = StoreIdIterator::new(Box::new(iter));
        Ok(HabitInstanceStoreIdIterator::new(sidi))
    }

    fn next_instance_date_after(&self, base: &NaiveDateTime) -> Result<Option<NaiveDate>> {
        use kairos::timetype::TimeType;
        use kairos::parser::parse;
        use kairos::parser::Parsed;
        use kairos::iter::extensions::Every;

        let date_from_s = |r: String| -> Result<TimeType> {
            match parse(&r)? {
                Parsed::TimeType(tt) => Ok(tt),
                Parsed::Iterator(_) => {
                    Err(format!("'{}' yields an iterator. Cannot use.", r).into())
                },
            }
        };

        debug!("Base is {:?}", base);

        let basedate  = date_from_s(self.habit_basedate()?)?;
        debug!("Basedate is {:?}", basedate);

        let increment = date_from_s(self.habit_recur_spec()?)?;
        debug!("Increment is {:?}", increment);

        let until = self.habit_until_date()?.map(|s| -> Result<_> {
            try!(date_from_s(s))
                .calculate()?
                .get_moment()
                .map(Clone::clone)
                .ok_or_else(|| {
                    let kind : HEK = "until-date seems to have non-date value".to_owned().into();
                    HE::from_kind(kind)
                })
        });

        debug!("Until-Date is {:?}", basedate);

        for element in basedate.every(increment)? {
            debug!("Calculating: {:?}", element);
            let element = element?.calculate()?;
            debug!(" = {:?}", element);
            if let Some(ndt) = element.get_moment() {
                if ndt >= base {
                    debug!("-> {:?} >= {:?}", ndt, base);
                    if let Some(u) = until {
                        if ndt > &(u?) {
                            return Ok(None);
                        } else {
                            return Ok(Some(ndt.date()));
                        }
                    } else {
                        return Ok(Some(ndt.date()));
                    }
                }
            } else {
                return Err("Iterator seems to return bogus values.".to_owned().into());
            }
        }

        unreachable!() // until we have habit-end-date support
    }

    /// Get the date of the next date when the habit should be done
    fn next_instance_date(&self) -> Result<Option<NaiveDate>> {
        use kairos::timetype::TimeType;

        let today = TimeType::today();
        let today = today.get_moment().unwrap(); // we know this is safe.
        debug!("Today is {:?}", today);

        self.next_instance_date_after(&today.date().and_hms(0, 0, 0))
    }

    /// Check whether the instance is a habit by checking its headers for the habit data
    fn is_habit_template(&self) -> Result<bool> {
        [
            "habit.template.name",
            "habit.template.basedate",
            "habit.template.comment",
        ].iter().fold(Ok(true), |acc, path| acc.and_then(|_| {
            self.get_header()
                .read(path)
                .map(|o| is_match!(o, Some(&Value::String(_))))
                .map_err(From::from)
        }))
    }

    fn habit_name(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.name")
    }

    fn habit_basedate(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.basedate")
    }

    fn habit_recur_spec(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.recurspec")
    }

    fn habit_comment(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.comment")
    }

    fn habit_until_date(&self) -> Result<Option<String>> {
        match self.get_header().read("habit.template.until")? {
            Some(&Value::String(ref s)) => Ok(Some(s.clone())),
            Some(_) => Err(HEK::HeaderTypeError("habit.template.until", "String").into()),
            None    => Ok(None),
        }
    }

    fn instance_id_for(habit_name: &String, habit_date: &NaiveDate) -> Result<StoreId> {
        instance_id_for_name_and_datestr(habit_name, &date_to_string(habit_date))
    }

}

fn instance_id_for_name_and_datestr(habit_name: &String, habit_date: &String) -> Result<StoreId> {
    use module_path::ModuleEntryPath;

    ModuleEntryPath::new(format!("instance/{}-{}", habit_name, habit_date))
        .into_storeid()
        .map_err(HE::from)
}

pub mod builder {
    use toml::Value;
    use toml_query::insert::TomlValueInsertExt;
    use chrono::NaiveDate;

    use libimagstore::store::Store;
    use libimagstore::storeid::StoreId;
    use libimagstore::storeid::IntoStoreId;
    use libimagstore::store::FileLockEntry;

    use error::HabitError as HE;
    use error::HabitErrorKind as HEK;
    use error::*;
    use util::date_to_string;

    pub struct HabitBuilder {
        name: Option<String>,
        comment: Option<String>,
        basedate: Option<NaiveDate>,
        recurspec: Option<String>,
        untildate: Option<NaiveDate>,
    }

    impl HabitBuilder {

        pub fn with_name(mut self, name: String) -> Self {
            self.name = Some(name);
            self
        }

        pub fn with_comment(mut self, comment: String) -> Self {
            self.comment = Some(comment);
            self
        }

        pub fn with_basedate(mut self, date: NaiveDate) -> Self {
            self.basedate = Some(date);
            self
        }

        pub fn with_recurspec(mut self, spec: String) -> Self {
            self.recurspec = Some(spec);
            self
        }

        pub fn with_until(mut self, date: NaiveDate) -> Self {
            self.untildate = Some(date);
            self
        }

        pub fn build<'a>(self, store: &'a Store) -> Result<FileLockEntry<'a>> {
            #[inline]
            fn mkerr(s: &'static str) -> HE {
                HE::from_kind(HEK::HabitBuilderMissing(s))
            }

            let name      = try!(self.name.ok_or_else(|| mkerr("name")));
            debug!("Success: Name present");

            let dateobj   = try!(self.basedate.ok_or_else(|| mkerr("date")));
            debug!("Success: Date present");

            let recur     = try!(self.recurspec.ok_or_else(|| mkerr("recurspec")));
            debug!("Success: Recurr spec present");

            if let Some(until) = self.untildate {
                debug!("Success: Until-Date present");
                if dateobj > until {
                    let e = HE::from_kind(HEK::HabitBuilderLogicError("until-date before start date"));
                    return Err(e);
                }
            }

            if let Err(e) = ::kairos::parser::parse(&recur) {
                return Err(e).map_err(From::from);
            }
            let date      = date_to_string(&dateobj);
            debug!("Success: Date valid");

            let comment   = self.comment.unwrap_or_else(|| String::new());
            let sid       = try!(build_habit_template_sid(&name));

            debug!("Creating entry in store for: {:?}", sid);
            let mut entry = try!(store.create(sid));

            try!(entry.get_header_mut().insert("habit.template.name", Value::String(name)));
            try!(entry.get_header_mut().insert("habit.template.basedate", Value::String(date)));
            try!(entry.get_header_mut().insert("habit.template.recurspec", Value::String(recur)));
            try!(entry.get_header_mut().insert("habit.template.comment", Value::String(comment)));
            if let Some(until) = self.untildate {
                let until = date_to_string(&until);
                try!(entry.get_header_mut().insert("habit.template.until", Value::String(until)));
            }

            debug!("Success: Created entry in store and set headers");
            Ok(entry)
        }

    }

    impl Default for HabitBuilder {
        fn default() -> Self {
            HabitBuilder {
                name: None,
                comment: None,
                basedate: None,
                recurspec: None,
                untildate: None,
            }
        }
    }

    /// Buld a StoreId for a Habit from a date object and a name of a habit
    fn build_habit_template_sid(name: &String) -> Result<StoreId> {
        use module_path::ModuleEntryPath;
        ModuleEntryPath::new(format!("template/{}", name)).into_storeid().map_err(From::from)
    }

}

<commit_msg>Replace matching with function chaining<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use toml::Value;
use toml_query::read::TomlValueReadExt;
use toml_query::insert::TomlValueInsertExt;
use chrono::NaiveDateTime;
use chrono::Local;
use chrono::NaiveDate;

use error::HabitError as HE;
use error::HabitErrorKind as HEK;
use error::*;
use iter::HabitInstanceStoreIdIterator;
use util::date_to_string;
use util::IsHabitCheck;
use util::get_string_header_from_entry;

use libimagentrylink::internal::InternalLinker;
use libimagstore::store::Store;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Entry;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreIdIterator;

/// A HabitTemplate is a "template" of a habit. A user may define a habit "Eat vegetable".
/// If the user ate a vegetable, she should create a HabitInstance from the Habit with the
/// appropriate date (and optionally a comment) set.
pub trait HabitTemplate : Sized {

    /// Create an instance from this habit template
    ///
    /// By default creates an instance with the name of the template, the current time and the
    /// current date and copies the comment from the template to the instance.
    ///
    /// It uses `Store::retrieve()` underneath. So if there is already an instance for the day
    /// passed, this will simply return the instance.
    fn create_instance_with_date<'a>(&self, store: &'a Store, date: &NaiveDate)
        -> Result<FileLockEntry<'a>>;

    /// Shortcut for calling `Self::create_instance_with_date()` with an instance of
    /// `::chrono::Local::today().naive_local()`.
    fn create_instance_today<'a>(&self, store: &'a Store) -> Result<FileLockEntry<'a>>;

    /// Get instances for this template
    fn linked_instances(&self) -> Result<HabitInstanceStoreIdIterator>;

    /// Get the date of the next date when the habit should be done
    fn next_instance_date_after(&self, base: &NaiveDateTime) -> Result<Option<NaiveDate>>;

    /// Get the date of the next date when the habit should be done
    fn next_instance_date(&self) -> Result<Option<NaiveDate>>;

    /// Check whether the instance is a habit by checking its headers for the habit data
    fn is_habit_template(&self) -> Result<bool>;

    fn habit_name(&self) -> Result<String>;
    fn habit_basedate(&self) -> Result<String>;
    fn habit_recur_spec(&self) -> Result<String>;
    fn habit_comment(&self) -> Result<String>;
    fn habit_until_date(&self) -> Result<Option<String>>;

    /// Create a StoreId for a habit name and a date the habit should be instantiated for
    fn instance_id_for(habit_name: &String, habit_date: &NaiveDate) -> Result<StoreId>;
}

impl HabitTemplate for Entry {

    fn create_instance_with_date<'a>(&self, store: &'a Store, date: &NaiveDate) -> Result<FileLockEntry<'a>> {
        let name    = self.habit_name()?;
        let comment = self.habit_comment()?;
        let date    = date_to_string(date);
        let id      = instance_id_for_name_and_datestr(&name, &date)?;

        store.retrieve(id)
            .map_err(From::from)
            .and_then(|mut entry| {
                {
                    let hdr = entry.get_header_mut();
                    hdr.insert("habit.instance.name",    Value::String(name))?;
                    hdr.insert("habit.instance.date",    Value::String(date))?;
                    hdr.insert("habit.instance.comment", Value::String(comment))?;
                }
                Ok(entry)
            })
    }

    fn create_instance_today<'a>(&self, store: &'a Store) -> Result<FileLockEntry<'a>> {
        self.create_instance_with_date(store, &Local::today().naive_local())
    }

    fn linked_instances(&self) -> Result<HabitInstanceStoreIdIterator> {
        let iter = self
            .get_internal_links()?
            .map(|link| link.get_store_id().clone())
            .filter(IsHabitCheck::is_habit_instance);

        let sidi = StoreIdIterator::new(Box::new(iter));
        Ok(HabitInstanceStoreIdIterator::new(sidi))
    }

    fn next_instance_date_after(&self, base: &NaiveDateTime) -> Result<Option<NaiveDate>> {
        use kairos::timetype::TimeType;
        use kairos::parser::parse;
        use kairos::parser::Parsed;
        use kairos::iter::extensions::Every;

        let date_from_s = |r: String| -> Result<TimeType> {
            match parse(&r)? {
                Parsed::TimeType(tt) => Ok(tt),
                Parsed::Iterator(_) => {
                    Err(format!("'{}' yields an iterator. Cannot use.", r).into())
                },
            }
        };

        debug!("Base is {:?}", base);

        let basedate  = date_from_s(self.habit_basedate()?)?;
        debug!("Basedate is {:?}", basedate);

        let increment = date_from_s(self.habit_recur_spec()?)?;
        debug!("Increment is {:?}", increment);

        let until = self.habit_until_date()?.map(|s| -> Result<_> {
            try!(date_from_s(s))
                .calculate()?
                .get_moment()
                .map(Clone::clone)
                .ok_or_else(|| {
                    let kind : HEK = "until-date seems to have non-date value".to_owned().into();
                    HE::from_kind(kind)
                })
        });

        debug!("Until-Date is {:?}", basedate);

        for element in basedate.every(increment)? {
            debug!("Calculating: {:?}", element);
            let element = element?.calculate()?;
            debug!(" = {:?}", element);
            if let Some(ndt) = element.get_moment() {
                if ndt >= base {
                    debug!("-> {:?} >= {:?}", ndt, base);
                    if let Some(u) = until {
                        if ndt > &(u?) {
                            return Ok(None);
                        } else {
                            return Ok(Some(ndt.date()));
                        }
                    } else {
                        return Ok(Some(ndt.date()));
                    }
                }
            } else {
                return Err("Iterator seems to return bogus values.".to_owned().into());
            }
        }

        unreachable!() // until we have habit-end-date support
    }

    /// Get the date of the next date when the habit should be done
    fn next_instance_date(&self) -> Result<Option<NaiveDate>> {
        use kairos::timetype::TimeType;

        let today = TimeType::today();
        let today = today.get_moment().unwrap(); // we know this is safe.
        debug!("Today is {:?}", today);

        self.next_instance_date_after(&today.date().and_hms(0, 0, 0))
    }

    /// Check whether the instance is a habit by checking its headers for the habit data
    fn is_habit_template(&self) -> Result<bool> {
        [
            "habit.template.name",
            "habit.template.basedate",
            "habit.template.comment",
        ].iter().fold(Ok(true), |acc, path| acc.and_then(|_| {
            self.get_header()
                .read(path)
                .map(|o| is_match!(o, Some(&Value::String(_))))
                .map_err(From::from)
        }))
    }

    fn habit_name(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.name")
    }

    fn habit_basedate(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.basedate")
    }

    fn habit_recur_spec(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.recurspec")
    }

    fn habit_comment(&self) -> Result<String> {
        get_string_header_from_entry(self, "habit.template.comment")
    }

    fn habit_until_date(&self) -> Result<Option<String>> {
        self.get_header()
            .read("habit.template.until")?
            .map(|v| v.as_str().map(String::from))
            .ok_or(HEK::HeaderTypeError("habit.template.until", "String").into())
    }

    fn instance_id_for(habit_name: &String, habit_date: &NaiveDate) -> Result<StoreId> {
        instance_id_for_name_and_datestr(habit_name, &date_to_string(habit_date))
    }

}

fn instance_id_for_name_and_datestr(habit_name: &String, habit_date: &String) -> Result<StoreId> {
    use module_path::ModuleEntryPath;

    ModuleEntryPath::new(format!("instance/{}-{}", habit_name, habit_date))
        .into_storeid()
        .map_err(HE::from)
}

pub mod builder {
    use toml::Value;
    use toml_query::insert::TomlValueInsertExt;
    use chrono::NaiveDate;

    use libimagstore::store::Store;
    use libimagstore::storeid::StoreId;
    use libimagstore::storeid::IntoStoreId;
    use libimagstore::store::FileLockEntry;

    use error::HabitError as HE;
    use error::HabitErrorKind as HEK;
    use error::*;
    use util::date_to_string;

    pub struct HabitBuilder {
        name: Option<String>,
        comment: Option<String>,
        basedate: Option<NaiveDate>,
        recurspec: Option<String>,
        untildate: Option<NaiveDate>,
    }

    impl HabitBuilder {

        pub fn with_name(mut self, name: String) -> Self {
            self.name = Some(name);
            self
        }

        pub fn with_comment(mut self, comment: String) -> Self {
            self.comment = Some(comment);
            self
        }

        pub fn with_basedate(mut self, date: NaiveDate) -> Self {
            self.basedate = Some(date);
            self
        }

        pub fn with_recurspec(mut self, spec: String) -> Self {
            self.recurspec = Some(spec);
            self
        }

        pub fn with_until(mut self, date: NaiveDate) -> Self {
            self.untildate = Some(date);
            self
        }

        pub fn build<'a>(self, store: &'a Store) -> Result<FileLockEntry<'a>> {
            #[inline]
            fn mkerr(s: &'static str) -> HE {
                HE::from_kind(HEK::HabitBuilderMissing(s))
            }

            let name      = try!(self.name.ok_or_else(|| mkerr("name")));
            debug!("Success: Name present");

            let dateobj   = try!(self.basedate.ok_or_else(|| mkerr("date")));
            debug!("Success: Date present");

            let recur     = try!(self.recurspec.ok_or_else(|| mkerr("recurspec")));
            debug!("Success: Recurr spec present");

            if let Some(until) = self.untildate {
                debug!("Success: Until-Date present");
                if dateobj > until {
                    let e = HE::from_kind(HEK::HabitBuilderLogicError("until-date before start date"));
                    return Err(e);
                }
            }

            if let Err(e) = ::kairos::parser::parse(&recur) {
                return Err(e).map_err(From::from);
            }
            let date      = date_to_string(&dateobj);
            debug!("Success: Date valid");

            let comment   = self.comment.unwrap_or_else(|| String::new());
            let sid       = try!(build_habit_template_sid(&name));

            debug!("Creating entry in store for: {:?}", sid);
            let mut entry = try!(store.create(sid));

            try!(entry.get_header_mut().insert("habit.template.name", Value::String(name)));
            try!(entry.get_header_mut().insert("habit.template.basedate", Value::String(date)));
            try!(entry.get_header_mut().insert("habit.template.recurspec", Value::String(recur)));
            try!(entry.get_header_mut().insert("habit.template.comment", Value::String(comment)));
            if let Some(until) = self.untildate {
                let until = date_to_string(&until);
                try!(entry.get_header_mut().insert("habit.template.until", Value::String(until)));
            }

            debug!("Success: Created entry in store and set headers");
            Ok(entry)
        }

    }

    impl Default for HabitBuilder {
        fn default() -> Self {
            HabitBuilder {
                name: None,
                comment: None,
                basedate: None,
                recurspec: None,
                untildate: None,
            }
        }
    }

    /// Buld a StoreId for a Habit from a date object and a name of a habit
    fn build_habit_template_sid(name: &String) -> Result<StoreId> {
        use module_path::ModuleEntryPath;
        ModuleEntryPath::new(format!("template/{}", name)).into_storeid().map_err(From::from)
    }

}

<|endoftext|>


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


<commit_before><commit_msg>Add crawler bin<commit_after>extern crate pink_spider;
extern crate feed_rs;
extern crate hyper;
extern crate hyper_native_tls;
extern crate chrono;
extern crate serde_json;

use pink_spider::model::{Model, Feed};

pub fn main() {
    println!("Start crawling...");

    let mut page  = 0;
    let per_page  = 10;
    let mut feeds = Feed::find(0, 0);
    let total = feeds.total;
    println!("{} feeds", total);
    while feeds.page * feeds.per_page < total {
        feeds = Feed::find(page, per_page);
        for mut feed in feeds.items {
            println!("Crawl {} ", feed.url);
            if let Ok(entries) = feed.crawl() {
                println!("Found {} entries", entries.len());
                println!("Found {} tracks",
                         entries.iter().fold(0, |sum, e| sum + e.tracks.len()));
                println!("Found {} albums",
                         entries.iter().fold(0, |sum, e| sum + e.albums.len()));
                println!("Found {} playlists",
                         entries.iter().fold(0, |sum, e| sum + e.playlists.len()));
            }
        }
        page += 1;
    }
    println!("Complete crawling...");
}
<|endoftext|>


<commit_before><commit_msg>Convert testfile command line argument to a positional argument<commit_after><|endoftext|>


<commit_before><commit_msg>Add gltypes module<commit_after>use libc::*;

/* Base GL types */
pub type GLenum         = c_uint;
pub type GLboolean      = c_uchar;
pub type GLbitfield     = c_uint;
pub type GLbyte         = c_schar;
pub type GLshort        = c_short;
pub type GLint          = c_int;
pub type GLsizei        = c_int;
pub type GLubyte        = c_uchar;
pub type GLushort       = c_ushort;
pub type GLuint         = c_uint;
pub type GLhalf         = c_ushort;
pub type GLfloat        = c_float;
pub type GLclampf       = c_float;
pub type GLdouble       = c_double;
pub type GLclampd       = c_double;
pub type GLvoid         = c_void;

/* GL type for program/shader text */
pub type GLchar = c_char;

/* GL types for handling large vertex buffer objects */
pub type GLintptr = ptrdiff_t;
pub type GLsizeiptr = ptrdiff_t;

/* GL types for handling large vertex buffer objects */
pub type GLintptrARB = ptrdiff_t;
pub type GLsizeiptrARB = ptrdiff_t;

/* GL types for program/shader text and shader object handles */
pub type GLcharARB = c_char;
pub type GLhandleARB = c_uint;

/* GL type for "half" precision (s10e5) float data in host memory */
pub type GLhalfARB = c_ushort;
pub type GLhalfNV = c_ushort;

pub type GLint64EXT = i64;
pub type GLuint64EXT = u64;
pub type GLint64 = i64;
pub type GLuint64 = u64;

pub struct __GLsync {}
pub type GLsync = *__GLsync;

/* These incomplete types let us declare types compatible with OpenCL's cl_context and cl_event */
pub struct _cl_context {}
pub struct _cl_event {}

pub type GLDEBUGPROCARB = extern "C" fn(source: GLenum, gltype: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: *GLchar, userParam: *GLvoid);
pub type GLDEBUGPROCAMD = extern "C" fn(id: GLuint, category: GLenum, severity: GLenum, length: GLsizei, message: *GLchar, userParam: *GLvoid);
pub type GLDEBUGPROC = extern "C" fn(source: GLenum, gltype: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: *GLchar, userParam: *GLvoid);

pub type GLvdpauSurfaceNV = GLintptr;<|endoftext|>


<commit_before><commit_msg>Use ruma-identifiers types in receipt module.<commit_after><|endoftext|>


<commit_before><commit_msg>item gen starting<commit_after><|endoftext|>


<commit_before><commit_msg>chore: cloned from iter()<commit_after><|endoftext|>


<commit_before><commit_msg>chore: use partition instead of filter<commit_after><|endoftext|>


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

use ast::Ident;
use errors::Handler;
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
use parse::token::{self, MatchNt, SubstNt, Token, NtIdent, NtTT};
use syntax_pos::{Span, DUMMY_SP};
use tokenstream::{self, TokenTree, Delimited, SequenceRepetition};
use util::small_vector::SmallVector;

use std::rc::Rc;
use std::ops::Add;
use std::collections::HashMap;

// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
enum Frame {
    Delimited {
        forest: Rc<Delimited>,
        idx: usize,
        span: Span,
    },
    MatchNt {
        name: Ident,
        kind: Ident,
        idx: usize,
        span: Span,
    },
    Sequence {
        forest: Rc<SequenceRepetition>,
        idx: usize,
        sep: Option<Token>,
    },
}

impl Iterator for Frame {
    type Item = TokenTree;

    fn next(&mut self) -> Option<TokenTree> {
        match *self {
            Frame::Delimited { ref forest, ref mut idx, span } => {
                *idx += 1;
                if *idx == forest.delim.len() {
                    Some(forest.open_tt(span))
                } else if let Some(tree) = forest.tts.get(*idx - forest.delim.len() - 1) {
                    Some(tree.clone())
                } else if *idx == forest.tts.len() + 2 * forest.delim.len() {
                    Some(forest.close_tt(span))
                } else {
                    None
                }
            }
            Frame::Sequence { ref forest, ref mut idx, .. } => {
                *idx += 1;
                forest.tts.get(*idx - 1).cloned()
            }
            Frame::MatchNt { ref mut idx, name, kind, span } => {
                *idx += 1;
                match *idx {
                    1 => Some(TokenTree::Token(span, token::SubstNt(name))),
                    2 => Some(TokenTree::Token(span, token::Colon)),
                    3 => Some(TokenTree::Token(span, token::Ident(kind))),
                    _ => None,
                }
            }
        }
    }
}

struct TtReader<'a> {
    sp_diag: &'a Handler,
    /// the unzipped tree:
    stack: SmallVector<Frame>,
    /* for MBE-style macro transcription */
    interpolations: HashMap<Ident, Rc<NamedMatch>>,

    repeat_idx: Vec<usize>,
    repeat_len: Vec<usize>,
}

/// This can do Macro-By-Example transcription. On the other hand, if
/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
/// (and should) be None.
pub fn transcribe(sp_diag: &Handler,
                  interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
                  src: Vec<tokenstream::TokenTree>)
                  -> Vec<TokenTree> {
    let mut r = TtReader {
        sp_diag: sp_diag,
        stack: SmallVector::one(Frame::Delimited {
            forest: Rc::new(tokenstream::Delimited { delim: token::NoDelim, tts: src }),
            idx: 0,
            span: DUMMY_SP,
        }),
        interpolations: match interp { /* just a convenience */
            None => HashMap::new(),
            Some(x) => x,
        },
        repeat_idx: Vec::new(),
        repeat_len: Vec::new(),
    };

    let mut tts = Vec::new();
    let mut prev_span = DUMMY_SP;
    while let Some(tt) = tt_next_token(&mut r, prev_span) {
        prev_span = tt.span();
        tts.push(tt);
    }
    tts
}

fn lookup_cur_matched_by_matched(r: &TtReader, start: Rc<NamedMatch>) -> Rc<NamedMatch> {
    r.repeat_idx.iter().fold(start, |ad, idx| {
        match *ad {
            MatchedNonterminal(_) => {
                // end of the line; duplicate henceforth
                ad.clone()
            }
            MatchedSeq(ref ads, _) => ads[*idx].clone()
        }
    })
}

fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> {
    let matched_opt = r.interpolations.get(&name).cloned();
    matched_opt.map(|s| lookup_cur_matched_by_matched(r, s))
}

#[derive(Clone)]
enum LockstepIterSize {
    LisUnconstrained,
    LisConstraint(usize, Ident),
    LisContradiction(String),
}

impl Add for LockstepIterSize {
    type Output = LockstepIterSize;

    fn add(self, other: LockstepIterSize) -> LockstepIterSize {
        match self {
            LisUnconstrained => other,
            LisContradiction(_) => self,
            LisConstraint(l_len, ref l_id) => match other {
                LisUnconstrained => self.clone(),
                LisContradiction(_) => other,
                LisConstraint(r_len, _) if l_len == r_len => self.clone(),
                LisConstraint(r_len, r_id) => {
                    LisContradiction(format!("inconsistent lockstep iteration: \
                                              '{}' has {} items, but '{}' has {}",
                                              l_id, l_len, r_id, r_len))
                }
            },
        }
    }
}

fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
    match *t {
        TokenTree::Delimited(_, ref delimed) => {
            delimed.tts.iter().fold(LisUnconstrained, |size, tt| {
                size + lockstep_iter_size(tt, r)
            })
        },
        TokenTree::Sequence(_, ref seq) => {
            seq.tts.iter().fold(LisUnconstrained, |size, tt| {
                size + lockstep_iter_size(tt, r)
            })
        },
        TokenTree::Token(_, SubstNt(name)) | TokenTree::Token(_, MatchNt(name, _)) =>
            match lookup_cur_matched(r, name) {
                Some(matched) => match *matched {
                    MatchedNonterminal(_) => LisUnconstrained,
                    MatchedSeq(ref ads, _) => LisConstraint(ads.len(), name),
                },
                _ => LisUnconstrained
            },
        TokenTree::Token(..) => LisUnconstrained,
    }
}

/// Return the next token from the TtReader.
/// EFFECT: advances the reader's token field
fn tt_next_token(r: &mut TtReader, prev_span: Span) -> Option<TokenTree> {
    loop {
        let tree = match r.stack.last_mut() {
            Some(frame) => frame.next(),
            None => return None,
        };

        let tree = if let Some(tree) = tree {
            tree
        } else {
            if let Frame::Sequence { ref mut idx, ref sep, .. } = *r.stack.last_mut().unwrap() {
                if *r.repeat_idx.last().unwrap() < *r.repeat_len.last().unwrap() - 1 {
                    *r.repeat_idx.last_mut().unwrap() += 1;
                    *idx = 0;
                    if let Some(sep) = sep.clone() {
                        return Some(TokenTree::Token(prev_span, sep)); // repeat same span, I guess
                    }
                    continue
                }
            }

            if let Frame::Sequence { .. } = r.stack.pop().unwrap() {
                r.repeat_idx.pop();
                r.repeat_len.pop();
            }
            continue
        };

        match tree {
            TokenTree::Sequence(sp, seq) => {
                // FIXME(pcwalton): Bad copy.
                match lockstep_iter_size(&TokenTree::Sequence(sp, seq.clone()),
                                         r) {
                    LisUnconstrained => {
                        panic!(r.sp_diag.span_fatal(
                            sp.clone(), /* blame macro writer */
                            "attempted to repeat an expression \
                             containing no syntax \
                             variables matched as repeating at this depth"));
                    }
                    LisContradiction(ref msg) => {
                        // FIXME #2887 blame macro invoker instead
                        panic!(r.sp_diag.span_fatal(sp.clone(), &msg[..]));
                    }
                    LisConstraint(len, _) => {
                        if len == 0 {
                            if seq.op == tokenstream::KleeneOp::OneOrMore {
                                // FIXME #2887 blame invoker
                                panic!(r.sp_diag.span_fatal(sp.clone(),
                                                     "this must repeat at least once"));
                            }

                            return tt_next_token(r, prev_span);
                        }
                        r.repeat_len.push(len);
                        r.repeat_idx.push(0);
                        r.stack.push(Frame::Sequence {
                            idx: 0,
                            sep: seq.separator.clone(),
                            forest: seq,
                        });
                    }
                }
            }
            // FIXME #2887: think about span stuff here
            TokenTree::Token(sp, SubstNt(ident)) => {
                match lookup_cur_matched(r, ident) {
                    None => {
                        return Some(TokenTree::Token(sp, SubstNt(ident)));
                        // this can't be 0 length, just like TokenTree::Delimited
                    }
                    Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched {
                        match **nt {
                            // sidestep the interpolation tricks for ident because
                            // (a) idents can be in lots of places, so it'd be a pain
                            // (b) we actually can, since it's a token.
                            NtIdent(ref sn) => {
                                return Some(TokenTree::Token(sn.span, token::Ident(sn.node)));
                            }
                            NtTT(ref tt) => return Some(tt.clone()),
                            _ => {
                                // FIXME(pcwalton): Bad copy
                                return Some(TokenTree::Token(sp, token::Interpolated(nt.clone())));
                            }
                        }
                    } else {
                        panic!(r.sp_diag.span_fatal(
                            sp, /* blame the macro writer */
                            &format!("variable '{}' is still repeating at this depth", ident)));
                    }
                }
            }
            TokenTree::Delimited(span, delimited) => {
                r.stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span });
            }
            TokenTree::Token(span, MatchNt(name, kind)) => {
                r.stack.push(Frame::MatchNt { name: name, kind: kind, idx: 0, span: span });
            }
            tt @ TokenTree::Token(..) => return Some(tt),
        }
    }
}
<commit_msg>Remove `ext::tt::transcribe::tt_next_token`.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast::Ident;
use errors::Handler;
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
use parse::token::{self, MatchNt, SubstNt, Token, NtIdent, NtTT};
use syntax_pos::{Span, DUMMY_SP};
use tokenstream::{self, TokenTree, Delimited, SequenceRepetition};
use util::small_vector::SmallVector;

use std::rc::Rc;
use std::ops::Add;
use std::collections::HashMap;

// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
enum Frame {
    Delimited {
        forest: Rc<Delimited>,
        idx: usize,
        span: Span,
    },
    MatchNt {
        name: Ident,
        kind: Ident,
        idx: usize,
        span: Span,
    },
    Sequence {
        forest: Rc<SequenceRepetition>,
        idx: usize,
        sep: Option<Token>,
    },
}

impl Frame {
    fn new(tts: Vec<TokenTree>) -> Frame {
        let forest = Rc::new(tokenstream::Delimited { delim: token::NoDelim, tts: tts });
        Frame::Delimited { forest: forest, idx: 0, span: DUMMY_SP }
    }
}

impl Iterator for Frame {
    type Item = TokenTree;

    fn next(&mut self) -> Option<TokenTree> {
        match *self {
            Frame::Delimited { ref forest, ref mut idx, span } => {
                *idx += 1;
                if *idx == forest.delim.len() {
                    Some(forest.open_tt(span))
                } else if let Some(tree) = forest.tts.get(*idx - forest.delim.len() - 1) {
                    Some(tree.clone())
                } else if *idx == forest.tts.len() + 2 * forest.delim.len() {
                    Some(forest.close_tt(span))
                } else {
                    None
                }
            }
            Frame::Sequence { ref forest, ref mut idx, .. } => {
                *idx += 1;
                forest.tts.get(*idx - 1).cloned()
            }
            Frame::MatchNt { ref mut idx, name, kind, span } => {
                *idx += 1;
                match *idx {
                    1 => Some(TokenTree::Token(span, token::SubstNt(name))),
                    2 => Some(TokenTree::Token(span, token::Colon)),
                    3 => Some(TokenTree::Token(span, token::Ident(kind))),
                    _ => None,
                }
            }
        }
    }
}

/// This can do Macro-By-Example transcription. On the other hand, if
/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
/// (and should) be None.
pub fn transcribe(sp_diag: &Handler,
                  interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
                  src: Vec<tokenstream::TokenTree>)
                  -> Vec<TokenTree> {
    let mut stack = SmallVector::one(Frame::new(src));
    let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */
    let mut repeat_idx = Vec::new();
    let mut repeat_len = Vec::new();
    let mut result = Vec::new();

    loop {
        let tree = if let Some(tree) = stack.last_mut().unwrap().next() {
            tree
        } else {
            if let Frame::Sequence { ref mut idx, ref sep, .. } = *stack.last_mut().unwrap() {
                if *repeat_idx.last().unwrap() < *repeat_len.last().unwrap() - 1 {
                    *repeat_idx.last_mut().unwrap() += 1;
                    *idx = 0;
                    if let Some(sep) = sep.clone() {
                        // repeat same span, I guess
                        let prev_span = result.last().map(TokenTree::span).unwrap_or(DUMMY_SP);
                        result.push(TokenTree::Token(prev_span, sep));
                    }
                    continue
                }
            }

            if let Frame::Sequence { .. } = stack.pop().unwrap() {
                repeat_idx.pop();
                repeat_len.pop();
            }
            if stack.is_empty() {
                return result;
            }
            continue
        };

        match tree {
            TokenTree::Sequence(sp, seq) => {
                // FIXME(pcwalton): Bad copy.
                match lockstep_iter_size(&TokenTree::Sequence(sp, seq.clone()),
                                         &interpolations,
                                         &repeat_idx) {
                    LockstepIterSize::Unconstrained => {
                        panic!(sp_diag.span_fatal(
                            sp.clone(), /* blame macro writer */
                            "attempted to repeat an expression \
                             containing no syntax \
                             variables matched as repeating at this depth"));
                    }
                    LockstepIterSize::Contradiction(ref msg) => {
                        // FIXME #2887 blame macro invoker instead
                        panic!(sp_diag.span_fatal(sp.clone(), &msg[..]));
                    }
                    LockstepIterSize::Constraint(len, _) => {
                        if len == 0 {
                            if seq.op == tokenstream::KleeneOp::OneOrMore {
                                // FIXME #2887 blame invoker
                                panic!(sp_diag.span_fatal(sp.clone(),
                                                          "this must repeat at least once"));
                            }
                        } else {
                            repeat_len.push(len);
                            repeat_idx.push(0);
                            stack.push(Frame::Sequence {
                                idx: 0,
                                sep: seq.separator.clone(),
                                forest: seq,
                            });
                        }
                    }
                }
            }
            // FIXME #2887: think about span stuff here
            TokenTree::Token(sp, SubstNt(ident)) => {
                match lookup_cur_matched(ident, &interpolations, &repeat_idx) {
                    None => result.push(TokenTree::Token(sp, SubstNt(ident))),
                    Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched {
                        match **nt {
                            // sidestep the interpolation tricks for ident because
                            // (a) idents can be in lots of places, so it'd be a pain
                            // (b) we actually can, since it's a token.
                            NtIdent(ref sn) => {
                                result.push(TokenTree::Token(sn.span, token::Ident(sn.node)));
                            }
                            NtTT(ref tt) => result.push(tt.clone()),
                            _ => {
                                // FIXME(pcwalton): Bad copy
                                result.push(TokenTree::Token(sp, token::Interpolated(nt.clone())));
                            }
                        }
                    } else {
                        panic!(sp_diag.span_fatal(
                            sp, /* blame the macro writer */
                            &format!("variable '{}' is still repeating at this depth", ident)));
                    }
                }
            }
            TokenTree::Delimited(span, delimited) => {
                stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span });
            }
            TokenTree::Token(span, MatchNt(name, kind)) => {
                stack.push(Frame::MatchNt { name: name, kind: kind, idx: 0, span: span });
            }
            tt @ TokenTree::Token(..) => result.push(tt),
        }
    }
}

fn lookup_cur_matched(ident: Ident,
                      interpolations: &HashMap<Ident, Rc<NamedMatch>>,
                      repeat_idx: &[usize])
                      -> Option<Rc<NamedMatch>> {
    interpolations.get(&ident).map(|matched| {
        repeat_idx.iter().fold(matched.clone(), |ad, idx| {
            match *ad {
                MatchedNonterminal(_) => {
                    // end of the line; duplicate henceforth
                    ad.clone()
                }
                MatchedSeq(ref ads, _) => ads[*idx].clone()
            }
        })
    })
}

#[derive(Clone)]
enum LockstepIterSize {
    Unconstrained,
    Constraint(usize, Ident),
    Contradiction(String),
}

impl Add for LockstepIterSize {
    type Output = LockstepIterSize;

    fn add(self, other: LockstepIterSize) -> LockstepIterSize {
        match self {
            LockstepIterSize::Unconstrained => other,
            LockstepIterSize::Contradiction(_) => self,
            LockstepIterSize::Constraint(l_len, ref l_id) => match other {
                LockstepIterSize::Unconstrained => self.clone(),
                LockstepIterSize::Contradiction(_) => other,
                LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self.clone(),
                LockstepIterSize::Constraint(r_len, r_id) => {
                    let msg = format!("inconsistent lockstep iteration: \
                                       '{}' has {} items, but '{}' has {}",
                                      l_id, l_len, r_id, r_len);
                    LockstepIterSize::Contradiction(msg)
                }
            },
        }
    }
}

fn lockstep_iter_size(tree: &TokenTree,
                      interpolations: &HashMap<Ident, Rc<NamedMatch>>,
                      repeat_idx: &[usize])
                      -> LockstepIterSize {
    match *tree {
        TokenTree::Delimited(_, ref delimed) => {
            delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
                size + lockstep_iter_size(tt, interpolations, repeat_idx)
            })
        },
        TokenTree::Sequence(_, ref seq) => {
            seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
                size + lockstep_iter_size(tt, interpolations, repeat_idx)
            })
        },
        TokenTree::Token(_, SubstNt(name)) | TokenTree::Token(_, MatchNt(name, _)) =>
            match lookup_cur_matched(name, interpolations, repeat_idx) {
                Some(matched) => match *matched {
                    MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
                    MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name),
                },
                _ => LockstepIterSize::Unconstrained
            },
        TokenTree::Token(..) => LockstepIterSize::Unconstrained,
    }
}
<|endoftext|>