<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use rocksdb::DBCompressionType;

quick_error! {
    #[derive(Debug)]
    pub enum ParseConfigError {
        MalformedRocksDB
        MalformedReadableNumber
    }
}

pub fn parse_rocksdb_compression(tp: &str) -> Result<DBCompressionType, ParseConfigError> {
    match &*tp.to_lowercase() {
        "no" => Ok(DBCompressionType::DBNo),
        "snappy" => Ok(DBCompressionType::DBSnappy),
        "zlib" => Ok(DBCompressionType::DBZlib),
        "bzip2" => Ok(DBCompressionType::DBBz2),
        "lz4" => Ok(DBCompressionType::DBLz4),
        "lz4hc" => Ok(DBCompressionType::DBLz4hc),
        _ => Err(ParseConfigError::MalformedRocksDB),
    }
}

pub fn parse_rocksdb_per_level_compression(tp: &str)
                                           -> Result<Vec<DBCompressionType>, ParseConfigError> {
    let mut result: Vec<DBCompressionType> = vec![];
    let v: Vec<&str> = tp.split(':').collect();
    for i in &v {
        match &*i.to_lowercase() {
            "no" => result.push(DBCompressionType::DBNo),
            "snappy" => result.push(DBCompressionType::DBSnappy),
            "zlib" => result.push(DBCompressionType::DBZlib),
            "bzip2" => result.push(DBCompressionType::DBBz2),
            "lz4" => result.push(DBCompressionType::DBLz4),
            "lz4hc" => result.push(DBCompressionType::DBLz4hc),
            _ => return Err(ParseConfigError::MalformedRocksDB),
        }
    }

    Ok(result)
}

fn split_property(property: &str) -> Result<(f64, &str), ParseConfigError> {
    let mut indx = 0;
    for s in property.chars() {
        match s {
            '0'...'9' | '.' => {
                indx += 1;
            }
            _ => {
                break;
            }
        }
    }

    let (num, unit) = property.split_at(indx);
    num.parse::<f64>().map(|f| (f, unit)).or(Err(ParseConfigError::MalformedReadableNumber))
}

const UNIT: usize = 1;
const DATA_MAGNITUDE: usize = 1024;
const KB: usize = UNIT * DATA_MAGNITUDE;
const MB: usize = KB * DATA_MAGNITUDE;
const GB: usize = MB * DATA_MAGNITUDE;

// Make sure it will not overflow.
const TB: u64 = (GB as u64) * (DATA_MAGNITUDE as u64);
const PB: u64 = (TB as u64) * (DATA_MAGNITUDE as u64);

const TIME_MAGNITUDE_1: usize = 1000;
const TIME_MAGNITUDE_2: usize = 60;
const MS: usize = UNIT;
const SECOND: usize = MS * TIME_MAGNITUDE_1;
const MINTUE: usize = SECOND * TIME_MAGNITUDE_2;
const HOUR: usize = MINTUE * TIME_MAGNITUDE_2;

pub fn parse_readable_int(size: &str) -> Result<i64, ParseConfigError> {
    let (num, unit) = try!(split_property(size));

    match &*unit.to_lowercase() {
        // file size
        "kb" => Ok((num * (KB as f64)) as i64),
        "mb" => Ok((num * (MB as f64)) as i64),
        "gb" => Ok((num * (GB as f64)) as i64),
        "tb" => Ok((num * (TB as f64)) as i64),
        "pb" => Ok((num * (PB as f64)) as i64),

        // time
        "ms" => Ok((num * (MS as f64)) as i64),
        "s" => Ok((num * (SECOND as f64)) as i64),
        "m" => Ok((num * (MINTUE as f64)) as i64),
        "h" => Ok((num * (HOUR as f64)) as i64),

        _ => Err(ParseConfigError::MalformedReadableNumber),
    }
}

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

    #[test]
    fn test_parse_readable_int() {
        // file size
        assert!(1_024 == parse_readable_int("1KB").unwrap());
        assert!(1_048_576 == parse_readable_int("1MB").unwrap());
        assert!(1_073_741_824 == parse_readable_int("1GB").unwrap());
        assert!(1_099_511_627_776 == parse_readable_int("1TB").unwrap());
        assert!(1_125_899_906_842_624 == parse_readable_int("1PB").unwrap());

        assert!(1_024 == parse_readable_int("1kb").unwrap());
        assert!(1_048_576 == parse_readable_int("1mb").unwrap());
        assert!(1_073_741_824 == parse_readable_int("1gb").unwrap());
        assert!(1_099_511_627_776 == parse_readable_int("1tb").unwrap());
        assert!(1_125_899_906_842_624 == parse_readable_int("1pb").unwrap());

        assert!(1_536 == parse_readable_int("1.5KB").unwrap());
        assert!(1_572_864 == parse_readable_int("1.5MB").unwrap());
        assert!(1_610_612_736 == parse_readable_int("1.5GB").unwrap());
        assert!(1_649_267_441_664 == parse_readable_int("1.5TB").unwrap());
        assert!(1_688_849_860_263_936 == parse_readable_int("1.5PB").unwrap());

        assert!(100_663_296 == parse_readable_int("96MB").unwrap());

        assert!(1_429_365_116_108 == parse_readable_int("1.3TB").unwrap());
        assert!(1_463_669_878_895_411 == parse_readable_int("1.3PB").unwrap());

        assert!(parse_readable_int("KB").is_err());
        assert!(parse_readable_int("MB").is_err());
        assert!(parse_readable_int("GB").is_err());
        assert!(parse_readable_int("TB").is_err());
        assert!(parse_readable_int("PB").is_err());

        // time
        assert!(1 == parse_readable_int("1ms").unwrap());
        assert!(1_000 == parse_readable_int("1s").unwrap());
        assert!(60_000 == parse_readable_int("1m").unwrap());
        assert!(3_600_000 == parse_readable_int("1h").unwrap());

        assert!(1 == parse_readable_int("1.3ms").unwrap());
        assert!(1_000 == parse_readable_int("1000ms").unwrap());
        assert!(1_300 == parse_readable_int("1.3s").unwrap());
        assert!(1_500 == parse_readable_int("1.5s").unwrap());
        assert!(10_000 == parse_readable_int("10s").unwrap());
        assert!(78_000 == parse_readable_int("1.3m").unwrap());
        assert!(90_000 == parse_readable_int("1.5m").unwrap());
        assert!(4_680_000 == parse_readable_int("1.3h").unwrap());
        assert!(5_400_000 == parse_readable_int("1.5h").unwrap());

        assert!(parse_readable_int("ms").is_err());
        assert!(parse_readable_int("s").is_err());
        assert!(parse_readable_int("m").is_err());
        assert!(parse_readable_int("h").is_err());

        assert!(parse_readable_int("1").is_err());
        assert!(parse_readable_int("foo").is_err());
    }
}
<commit_msg>util: make clippy happy. (#797)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use rocksdb::DBCompressionType;

quick_error! {
    #[derive(Debug)]
    pub enum ParseConfigError {
        RocksDB
        ReadableNumber
    }
}

pub fn parse_rocksdb_compression(tp: &str) -> Result<DBCompressionType, ParseConfigError> {
    match &*tp.to_lowercase() {
        "no" => Ok(DBCompressionType::DBNo),
        "snappy" => Ok(DBCompressionType::DBSnappy),
        "zlib" => Ok(DBCompressionType::DBZlib),
        "bzip2" => Ok(DBCompressionType::DBBz2),
        "lz4" => Ok(DBCompressionType::DBLz4),
        "lz4hc" => Ok(DBCompressionType::DBLz4hc),
        _ => Err(ParseConfigError::RocksDB),
    }
}

pub fn parse_rocksdb_per_level_compression(tp: &str)
                                           -> Result<Vec<DBCompressionType>, ParseConfigError> {
    let mut result: Vec<DBCompressionType> = vec![];
    let v: Vec<&str> = tp.split(':').collect();
    for i in &v {
        match &*i.to_lowercase() {
            "no" => result.push(DBCompressionType::DBNo),
            "snappy" => result.push(DBCompressionType::DBSnappy),
            "zlib" => result.push(DBCompressionType::DBZlib),
            "bzip2" => result.push(DBCompressionType::DBBz2),
            "lz4" => result.push(DBCompressionType::DBLz4),
            "lz4hc" => result.push(DBCompressionType::DBLz4hc),
            _ => return Err(ParseConfigError::RocksDB),
        }
    }

    Ok(result)
}

fn split_property(property: &str) -> Result<(f64, &str), ParseConfigError> {
    let mut indx = 0;
    for s in property.chars() {
        match s {
            '0'...'9' | '.' => {
                indx += 1;
            }
            _ => {
                break;
            }
        }
    }

    let (num, unit) = property.split_at(indx);
    num.parse::<f64>().map(|f| (f, unit)).or(Err(ParseConfigError::ReadableNumber))
}

const UNIT: usize = 1;
const DATA_MAGNITUDE: usize = 1024;
const KB: usize = UNIT * DATA_MAGNITUDE;
const MB: usize = KB * DATA_MAGNITUDE;
const GB: usize = MB * DATA_MAGNITUDE;

// Make sure it will not overflow.
const TB: u64 = (GB as u64) * (DATA_MAGNITUDE as u64);
const PB: u64 = (TB as u64) * (DATA_MAGNITUDE as u64);

const TIME_MAGNITUDE_1: usize = 1000;
const TIME_MAGNITUDE_2: usize = 60;
const MS: usize = UNIT;
const SECOND: usize = MS * TIME_MAGNITUDE_1;
const MINTUE: usize = SECOND * TIME_MAGNITUDE_2;
const HOUR: usize = MINTUE * TIME_MAGNITUDE_2;

pub fn parse_readable_int(size: &str) -> Result<i64, ParseConfigError> {
    let (num, unit) = try!(split_property(size));

    match &*unit.to_lowercase() {
        // file size
        "kb" => Ok((num * (KB as f64)) as i64),
        "mb" => Ok((num * (MB as f64)) as i64),
        "gb" => Ok((num * (GB as f64)) as i64),
        "tb" => Ok((num * (TB as f64)) as i64),
        "pb" => Ok((num * (PB as f64)) as i64),

        // time
        "ms" => Ok((num * (MS as f64)) as i64),
        "s" => Ok((num * (SECOND as f64)) as i64),
        "m" => Ok((num * (MINTUE as f64)) as i64),
        "h" => Ok((num * (HOUR as f64)) as i64),

        _ => Err(ParseConfigError::ReadableNumber),
    }
}

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

    #[test]
    fn test_parse_readable_int() {
        // file size
        assert!(1_024 == parse_readable_int("1KB").unwrap());
        assert!(1_048_576 == parse_readable_int("1MB").unwrap());
        assert!(1_073_741_824 == parse_readable_int("1GB").unwrap());
        assert!(1_099_511_627_776 == parse_readable_int("1TB").unwrap());
        assert!(1_125_899_906_842_624 == parse_readable_int("1PB").unwrap());

        assert!(1_024 == parse_readable_int("1kb").unwrap());
        assert!(1_048_576 == parse_readable_int("1mb").unwrap());
        assert!(1_073_741_824 == parse_readable_int("1gb").unwrap());
        assert!(1_099_511_627_776 == parse_readable_int("1tb").unwrap());
        assert!(1_125_899_906_842_624 == parse_readable_int("1pb").unwrap());

        assert!(1_536 == parse_readable_int("1.5KB").unwrap());
        assert!(1_572_864 == parse_readable_int("1.5MB").unwrap());
        assert!(1_610_612_736 == parse_readable_int("1.5GB").unwrap());
        assert!(1_649_267_441_664 == parse_readable_int("1.5TB").unwrap());
        assert!(1_688_849_860_263_936 == parse_readable_int("1.5PB").unwrap());

        assert!(100_663_296 == parse_readable_int("96MB").unwrap());

        assert!(1_429_365_116_108 == parse_readable_int("1.3TB").unwrap());
        assert!(1_463_669_878_895_411 == parse_readable_int("1.3PB").unwrap());

        assert!(parse_readable_int("KB").is_err());
        assert!(parse_readable_int("MB").is_err());
        assert!(parse_readable_int("GB").is_err());
        assert!(parse_readable_int("TB").is_err());
        assert!(parse_readable_int("PB").is_err());

        // time
        assert!(1 == parse_readable_int("1ms").unwrap());
        assert!(1_000 == parse_readable_int("1s").unwrap());
        assert!(60_000 == parse_readable_int("1m").unwrap());
        assert!(3_600_000 == parse_readable_int("1h").unwrap());

        assert!(1 == parse_readable_int("1.3ms").unwrap());
        assert!(1_000 == parse_readable_int("1000ms").unwrap());
        assert!(1_300 == parse_readable_int("1.3s").unwrap());
        assert!(1_500 == parse_readable_int("1.5s").unwrap());
        assert!(10_000 == parse_readable_int("10s").unwrap());
        assert!(78_000 == parse_readable_int("1.3m").unwrap());
        assert!(90_000 == parse_readable_int("1.5m").unwrap());
        assert!(4_680_000 == parse_readable_int("1.3h").unwrap());
        assert!(5_400_000 == parse_readable_int("1.5h").unwrap());

        assert!(parse_readable_int("ms").is_err());
        assert!(parse_readable_int("s").is_err());
        assert!(parse_readable_int("m").is_err());
        assert!(parse_readable_int("h").is_err());

        assert!(parse_readable_int("1").is_err());
        assert!(parse_readable_int("foo").is_err());
    }
}
<|endoftext|>


<commit_before>use anyhow::Result;
use async_ctrlc::CtrlC;
use async_std::channel::bounded;
use async_std::sync::{Arc, Mutex};
use async_std::task;
use clap::Parser;
use extendedmind_engine::{Bytes, Engine};
use futures::stream::StreamExt;
use log::info;
use std::path::PathBuf;
use std::process;
use std::sync::atomic::AtomicBool;
use std::time::Duration;

mod common;
mod http;
mod logging;
mod server;

use common::{ChannelSenderReceiver, State, SystemCommand};
use logging::setup_logging;
use server::start_server;

#[derive(Parser)]
#[clap(version = "0.1.0", author = "Timo Tiuraniemi <timo.tiuraniemi@iki.fi>")]
struct Opts {
    #[clap(short, long)]
    verbose: Option<bool>,
    #[clap(short, long)]
    data_root_dir: PathBuf,
    #[clap(short, long)]
    static_root_dir: Option<PathBuf>,
    #[clap(short, long)]
    http_port: Option<u16>,
    #[clap(long)]
    https_port: Option<u16>,
    #[clap(long)]
    domain: Option<String>,
    #[clap(long)]
    acme_email: Option<String>,
    #[clap(long)]
    acme_dir: Option<String>,
    #[clap(long)]
    acme_production: Option<bool>,
    #[clap(long)]
    hsts_max_age: Option<u64>,
    #[clap(long)]
    hsts_permanent_redirect: Option<bool>,
    #[clap(long)]
    hsts_preload: Option<bool>,
    #[clap(short, long)]
    tcp_port: Option<u16>,
    #[clap(short, long)]
    log_to_stderr: bool,
    #[clap(long)]
    log_dir: Option<PathBuf>,
    #[clap(long)]
    log_precision: Option<u8>,
    #[clap(long)]
    skip_compress_mime: Option<Vec<String>>,
    #[clap(long)]
    cache_ttl_sec: Option<u64>,
    #[clap(long)]
    cache_tti_sec: Option<u64>,
    #[clap(long)]
    inline_css_path: Option<Vec<String>>,
    #[clap(long)]
    immutable_path: Option<Vec<String>>,
}

fn main() -> Result<()> {
    // Read in command line arguments and setup logging
    let opts: Opts = Opts::parse();
    setup_logging(
        opts.log_to_stderr,
        opts.verbose.unwrap_or(false),
        opts.log_dir,
        opts.log_precision,
    );
    info!("enter: hub");
    let data_root_dir = &opts.data_root_dir;

    // Initialize the engine blocking
    let engine =
        futures::executor::block_on(
            async move { Engine::new_disk(data_root_dir, false, None).await },
        );

    // Create channels
    let (system_command_sender, system_command_receiver): ChannelSenderReceiver = bounded(1000);

    // Create state for websocket
    let initial_state = State {
        engine,
        system_commands: system_command_receiver,
    };

    // Listen to ctrlc in a separate task
    let ctrlc = CtrlC::new().expect("cannot create Ctrl+C handler?");
    let disconnect_sender = system_command_sender.clone();
    let abort: Arc<Mutex<AtomicBool>> = Arc::new(Mutex::new(AtomicBool::new(false)));
    let abort_writer = abort.clone();
    task::spawn(async move {
        ctrlc.await;
        disconnect_sender
            .send(Ok(Bytes::from_static(&[SystemCommand::Disconnect as u8])))
            .await
            .unwrap();
        *abort_writer.as_ref().lock().await = AtomicBool::new(true);
        // Wait 200ms before killing, to allow time for file saving and closing sockets
        task::sleep(Duration::from_millis(200)).await;
        process::exit(0);
    });

    // Need to start a system executor to send the WakeUp command, we send it once per second so
    // that the listener will send a WS Ping when it wants to in a 1s delay.
    task::spawn(async move {
        let mut interval = async_std::stream::interval(Duration::from_secs(1));
        while interval.next().await.is_some() && !*abort.as_ref().lock().await.get_mut() {
            task::sleep(Duration::from_millis(1000)).await;
            system_command_sender
                .send(Ok(Bytes::from_static(&[SystemCommand::WakeUp as u8])))
                .await
                .unwrap();
        }
    });

    // Block server with initial state
    futures::executor::block_on(start_server(
        initial_state,
        opts.static_root_dir,
        opts.http_port,
        opts.https_port,
        opts.domain,
        opts.acme_email,
        opts.acme_dir,
        opts.acme_production.unwrap_or(false),
        opts.hsts_max_age,
        opts.hsts_permanent_redirect.unwrap_or(false),
        opts.hsts_preload.unwrap_or(false),
        opts.tcp_port,
        opts.skip_compress_mime,
        opts.cache_ttl_sec,
        opts.cache_tti_sec,
        opts.inline_css_path,
        opts.immutable_path,
    ))?;

    Ok(())
}
<commit_msg>Added info logs from exiting<commit_after>use anyhow::Result;
use async_ctrlc::CtrlC;
use async_std::channel::bounded;
use async_std::sync::{Arc, Mutex};
use async_std::task;
use clap::Parser;
use extendedmind_engine::{Bytes, Engine};
use futures::stream::StreamExt;
use log::info;
use std::path::PathBuf;
use std::process;
use std::sync::atomic::AtomicBool;
use std::time::Duration;

mod common;
mod http;
mod logging;
mod server;

use common::{ChannelSenderReceiver, State, SystemCommand};
use logging::setup_logging;
use server::start_server;

#[derive(Parser)]
#[clap(version = "0.1.0", author = "Timo Tiuraniemi <timo.tiuraniemi@iki.fi>")]
struct Opts {
    #[clap(short, long)]
    verbose: Option<bool>,
    #[clap(short, long)]
    data_root_dir: PathBuf,
    #[clap(short, long)]
    static_root_dir: Option<PathBuf>,
    #[clap(short, long)]
    http_port: Option<u16>,
    #[clap(long)]
    https_port: Option<u16>,
    #[clap(long)]
    domain: Option<String>,
    #[clap(long)]
    acme_email: Option<String>,
    #[clap(long)]
    acme_dir: Option<String>,
    #[clap(long)]
    acme_production: Option<bool>,
    #[clap(long)]
    hsts_max_age: Option<u64>,
    #[clap(long)]
    hsts_permanent_redirect: Option<bool>,
    #[clap(long)]
    hsts_preload: Option<bool>,
    #[clap(short, long)]
    tcp_port: Option<u16>,
    #[clap(short, long)]
    log_to_stderr: bool,
    #[clap(long)]
    log_dir: Option<PathBuf>,
    #[clap(long)]
    log_precision: Option<u8>,
    #[clap(long)]
    skip_compress_mime: Option<Vec<String>>,
    #[clap(long)]
    cache_ttl_sec: Option<u64>,
    #[clap(long)]
    cache_tti_sec: Option<u64>,
    #[clap(long)]
    inline_css_path: Option<Vec<String>>,
    #[clap(long)]
    immutable_path: Option<Vec<String>>,
}

fn main() -> Result<()> {
    // Read in command line arguments and setup logging
    let opts: Opts = Opts::parse();
    setup_logging(
        opts.log_to_stderr,
        opts.verbose.unwrap_or(false),
        opts.log_dir,
        opts.log_precision,
    );
    info!("enter: hub");
    let data_root_dir = &opts.data_root_dir;

    // Initialize the engine blocking
    let engine =
        futures::executor::block_on(
            async move { Engine::new_disk(data_root_dir, false, None).await },
        );

    // Create channels
    let (system_command_sender, system_command_receiver): ChannelSenderReceiver = bounded(1000);

    // Create state for websocket
    let initial_state = State {
        engine,
        system_commands: system_command_receiver,
    };

    // Listen to ctrlc in a separate task
    let ctrlc = CtrlC::new().expect("cannot create Ctrl+C handler?");
    let disconnect_sender = system_command_sender.clone();
    let abort: Arc<Mutex<AtomicBool>> = Arc::new(Mutex::new(AtomicBool::new(false)));
    let abort_writer = abort.clone();
    task::spawn(async move {
        ctrlc.await;
        info!("Received termination signal, sending disconnect");
        disconnect_sender
            .send(Ok(Bytes::from_static(&[SystemCommand::Disconnect as u8])))
            .await
            .unwrap();
        *abort_writer.as_ref().lock().await = AtomicBool::new(true);
        // Wait 200ms before killing, to allow time for file saving and closing sockets
        task::sleep(Duration::from_millis(200)).await;
        info!("Exiting process with 0");
        process::exit(0);
    });

    // Need to start a system executor to send the WakeUp command, we send it once per second so
    // that the listener will send a WS Ping when it wants to in a 1s delay.
    task::spawn(async move {
        let mut interval = async_std::stream::interval(Duration::from_secs(1));
        while interval.next().await.is_some() && !*abort.as_ref().lock().await.get_mut() {
            task::sleep(Duration::from_millis(1000)).await;
            system_command_sender
                .send(Ok(Bytes::from_static(&[SystemCommand::WakeUp as u8])))
                .await
                .unwrap();
        }
    });

    // Block server with initial state
    futures::executor::block_on(start_server(
        initial_state,
        opts.static_root_dir,
        opts.http_port,
        opts.https_port,
        opts.domain,
        opts.acme_email,
        opts.acme_dir,
        opts.acme_production.unwrap_or(false),
        opts.hsts_max_age,
        opts.hsts_permanent_redirect.unwrap_or(false),
        opts.hsts_preload.unwrap_or(false),
        opts.tcp_port,
        opts.skip_compress_mime,
        opts.cache_ttl_sec,
        opts.cache_tti_sec,
        opts.inline_css_path,
        opts.immutable_path,
    ))?;

    Ok(())
}
<|endoftext|>


<commit_before>//! Special x86_64 instructions.

pub mod interrupts;
pub mod port;
pub mod segmentation;
pub mod tables;
pub mod tlb;

/// Cause a breakpoint exception by invoking the `int3` instruction.
pub fn int3() {
    unsafe {
        asm!("int3");
    }
}
<commit_msg>Add hlt instruction<commit_after>//! Special x86_64 instructions.

pub mod interrupts;
pub mod port;
pub mod segmentation;
pub mod tables;
pub mod tlb;

/// Cause a breakpoint exception by invoking the `int3` instruction.
pub fn int3() {
    unsafe {
        asm!("int3");
    }
}

/// Halts the CPU until the next interrupt arrives.
#[inline(always)]
pub unsafe fn hlt() {
    asm!("hlt" :::: "volatile");
}
<|endoftext|>


<commit_before>/// Asserts that types are equal in alignment.
///
/// This is useful when ensuring that pointer arithmetic is done correctly, or
/// when [FFI] requires a type to have the same alignment as some foreign type.
///
/// # Examples
///
/// A `usize` has the same alignment as any pointer type:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!(usize, *const u8, *mut u8);
/// ```
///
/// The following passes because `[i32; 4]` has the same alignment as `i32`:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!([i32; 4], i32);
/// ```
///
/// The following example fails to compile because `i32x4` explicitly has 4
/// times the alignment as `[i32; 4]`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// # #[allow(non_camel_case_types)]
/// #[repr(align(16))]
/// struct i32x4([i32; 4]);
///
/// assert_align_eq!(i32x4, [i32; 4]);
/// ```
///
/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface
#[macro_export(local_inner_macros)]
macro_rules! assert_align_eq {
    ($x:ty, $($xs:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_eq_usize!(align_of::<$x>() $(, align_of::<$xs>())+);
        };
    };
}

/// Asserts that types are equal in alignment.
///
/// This macro has been deprecated in favor of
/// [`assert_align_eq!`](macro.assert_align_eq.html).
#[deprecated(
    since = "1.2.0",
    note = "Please use the 'assert_align_eq' macro instead",
)]
#[macro_export(local_inner_macros)]
macro_rules! assert_eq_align {
    ($($t:tt)*) => {
        assert_align_eq!($($t)*);
    };
}
<commit_msg>Rename `assert_align_eq!` repeated variables<commit_after>/// Asserts that types are equal in alignment.
///
/// This is useful when ensuring that pointer arithmetic is done correctly, or
/// when [FFI] requires a type to have the same alignment as some foreign type.
///
/// # Examples
///
/// A `usize` has the same alignment as any pointer type:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!(usize, *const u8, *mut u8);
/// ```
///
/// The following passes because `[i32; 4]` has the same alignment as `i32`:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!([i32; 4], i32);
/// ```
///
/// The following example fails to compile because `i32x4` explicitly has 4
/// times the alignment as `[i32; 4]`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// # #[allow(non_camel_case_types)]
/// #[repr(align(16))]
/// struct i32x4([i32; 4]);
///
/// assert_align_eq!(i32x4, [i32; 4]);
/// ```
///
/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface
#[macro_export(local_inner_macros)]
macro_rules! assert_align_eq {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_eq_usize!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that types are equal in alignment.
///
/// This macro has been deprecated in favor of
/// [`assert_align_eq!`](macro.assert_align_eq.html).
#[deprecated(
    since = "1.2.0",
    note = "Please use the 'assert_align_eq' macro instead",
)]
#[macro_export(local_inner_macros)]
macro_rules! assert_eq_align {
    ($($t:tt)*) => {
        assert_align_eq!($($t)*);
    };
}
<|endoftext|>


<commit_before>use crate::{
    AssumeRoleWithWebIdentityError, AssumeRoleWithWebIdentityRequest,
    AssumeRoleWithWebIdentityResponse, Sts, StsClient,
};
use futures::{Async, Future, Poll};
use rusoto_core::credential::{
    AwsCredentials, CredentialsError, ProvideAwsCredentials, Secret, Variable,
};
use rusoto_core::request::HttpClient;
use rusoto_core::{Client, Region, RusotoFuture};
use std::error::Error;

const AWS_WEB_IDENTITY_TOKEN_FILE: &str = "AWS_WEB_IDENTITY_TOKEN_FILE";

const AWS_ROLE_ARN: &str = "AWS_ROLE_ARN";

const AWS_ROLE_SESSION_NAME: &str = "AWS_ROLE_SESSION_NAME";

/// WebIdentityProvider using OpenID Connect bearer token to retrieve AWS IAM credentials.
///
/// See https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html for
/// more details.
#[derive(Debug, Clone)]
pub struct WebIdentityProvider {
    /// The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider.
    /// Your application must get this token by authenticating the user who is using your application
    /// with a web identity provider before the application makes an AssumeRoleWithWebIdentity call.
    pub web_identity_token: Variable<Secret, CredentialsError>,
    /// The Amazon Resource Name (ARN) of the role that the caller is assuming.
    pub role_arn: Variable<String, CredentialsError>,
    /// An identifier for the assumed role session. Typically, you pass the name or identifier that is
    /// associated with the user who is using your application. That way, the temporary security credentials
    /// that your application will use are associated with that user. This session name is included as part
    /// of the ARN and assumed role ID in the AssumedRoleUser response element.
    pub role_session_name: Variable<String, CredentialsError>,
}

impl WebIdentityProvider {
    /// Create new WebIdentityProvider by explicitly passing its configuration.
    pub fn new<A, B, C>(web_identity_token: A, role_arn: B, role_session_name: Option<C>) -> Self
    where
        A: Into<Variable<Secret, CredentialsError>>,
        B: Into<Variable<String, CredentialsError>>,
        C: Into<Variable<String, CredentialsError>>,
    {
        Self {
            web_identity_token: web_identity_token.into(),
            role_arn: role_arn.into(),
            role_session_name: role_session_name
                .map(|v| v.into())
                .unwrap_or_else(|| Variable::with_value(Self::create_session_name())),
        }
    }

    /// Creat a WebIdentityProvider from the following environment variables:
    ///
    /// - `AWS_WEB_IDENTITY_TOKEN_FILE` path to the web identity token file.
    /// - `AWS_ROLE_ARN` ARN of the role to assume.
    /// - `AWS_ROLE_SESSION_NAME` (optional) name applied to the assume-role session.
    ///
    /// See https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html
    /// for more information about how IAM Roles for Kubernetes Service Accounts works.
    pub fn from_k8s_env() -> Self {
        Self::_from_k8s_env(
            Variable::from_env_var(AWS_WEB_IDENTITY_TOKEN_FILE),
            Variable::from_env_var(AWS_ROLE_ARN),
            Some(Variable::from_env_var(AWS_ROLE_SESSION_NAME)),
        )
    }

    /// Used by unit testing
    pub(crate) fn _from_k8s_env(
        token_file: Variable<String, CredentialsError>,
        role: Variable<String, CredentialsError>,
        session_name: Option<Variable<String, CredentialsError>>,
    ) -> Self {
        Self::new(
            Variable::dynamic(move || Variable::from_text_file(token_file.resolve()?).resolve()),
            role,
            session_name,
        )
    }

    pub(crate) fn load_token(&self) -> Result<Secret, CredentialsError> {
        self.web_identity_token.resolve()
    }

    fn create_session_name() -> String {
        // TODO can we do better here?
        // - Pod service account, Pod name and Pod namespace
        // - EC2 Instance ID if available
        // - IP address if available
        // - ...
        // Having some information in the session name that identifies the client would enable
        // better correlation analysis in CloudTrail.
        "WebIdentitySession".to_string()
    }
}

impl ProvideAwsCredentials for WebIdentityProvider {
    type Future = WebIdentityProviderFuture;

    fn credentials(&self) -> Self::Future {
        WebIdentityProviderFuture {
            state: WebIdentityProviderFutureState::LoadBearerToken(
                self.load_token(),
                self.role_arn.resolve(),
                self.role_session_name.resolve(),
            ),
        }
    }
}

enum WebIdentityProviderFutureState {
    LoadBearerToken(
        Result<Secret, CredentialsError>,
        Result<String, CredentialsError>,
        Result<String, CredentialsError>,
    ),
    ExchangeToken(RusotoFuture<AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError>),
}

/// Provides AWS credentials from environment variables as a Future.
pub struct WebIdentityProviderFuture {
    state: WebIdentityProviderFutureState,
}

impl Future for WebIdentityProviderFuture {
    type Item = AwsCredentials;
    type Error = CredentialsError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        use crate::custom::credential::NewAwsCredsForStsCreds;
        use WebIdentityProviderFutureState::*;
        match &mut self.state {
            LoadBearerToken(Err(e), _, _) => Err(e.clone()),
            LoadBearerToken(_, Err(e), _) => Err(e.clone()),
            LoadBearerToken(_, _, Err(e)) => Err(e.clone()),
            LoadBearerToken(Ok(token), Ok(role), Ok(session)) => match HttpClient::new() {
                Err(e) => Err(CredentialsError::new(e.description().to_string())),
                Ok(c) => {
                    let client = Client::new_not_signing(c);
                    let sts = StsClient::new_with_client(client, Region::default());
                    let mut req = AssumeRoleWithWebIdentityRequest::default();
                    req.role_arn = role.clone();
                    req.web_identity_token = token.as_ref().to_string();
                    req.role_session_name = session.clone();
                    self.state = ExchangeToken(sts.assume_role_with_web_identity(req));
                    self.poll()
                }
            },
            ExchangeToken(ref mut future) => match future.poll() {
                Ok(Async::Ready(r)) => match r.credentials {
                    Some(c) => AwsCredentials::new_for_credentials(c).map(|c| Async::Ready(c)),
                    None => Err(CredentialsError::new(format!(
                        "No credentials found in AssumeRoleWithWebIdentityResponse: {:?}",
                        r
                    ))),
                },
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Err(e) => Err(CredentialsError::new(e.to_string())),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;
    use tempfile::NamedTempFile;

    #[test]
    fn api_ergonomy() {
        WebIdentityProvider::new(Secret::from("".to_string()), "", Some("".to_string()));
    }

    #[test]
    fn from_k8s_env() -> Result<(), CredentialsError> {
        const TOKEN_VALUE: &str = "secret";
        const ROLE_ARN: &str = "role";
        const SESSION_NAME: &str = "session";
        let mut file = NamedTempFile::new()?;
        // We use writeln to add an extra newline at the end of the token, which should be
        // removed by Variable::from_text_file.
        writeln!(file, "{}", TOKEN_VALUE)?;
        let p = WebIdentityProvider::_from_k8s_env(
            Variable::with_value(file.path().to_string_lossy().to_string()),
            Variable::with_value(ROLE_ARN.to_string()),
            Some(Variable::with_value(SESSION_NAME.to_string())),
        );
        let token = p.load_token()?;
        assert_eq!(token.as_ref(), TOKEN_VALUE);
        Ok(())
    }
}
<commit_msg>cleanup depricated description in custom sts<commit_after>use crate::{
    AssumeRoleWithWebIdentityError, AssumeRoleWithWebIdentityRequest,
    AssumeRoleWithWebIdentityResponse, Sts, StsClient,
};
use futures::{Async, Future, Poll};
use rusoto_core::credential::{
    AwsCredentials, CredentialsError, ProvideAwsCredentials, Secret, Variable,
};
use rusoto_core::request::HttpClient;
use rusoto_core::{Client, Region, RusotoFuture};
use std::error::Error;

const AWS_WEB_IDENTITY_TOKEN_FILE: &str = "AWS_WEB_IDENTITY_TOKEN_FILE";

const AWS_ROLE_ARN: &str = "AWS_ROLE_ARN";

const AWS_ROLE_SESSION_NAME: &str = "AWS_ROLE_SESSION_NAME";

/// WebIdentityProvider using OpenID Connect bearer token to retrieve AWS IAM credentials.
///
/// See https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html for
/// more details.
#[derive(Debug, Clone)]
pub struct WebIdentityProvider {
    /// The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider.
    /// Your application must get this token by authenticating the user who is using your application
    /// with a web identity provider before the application makes an AssumeRoleWithWebIdentity call.
    pub web_identity_token: Variable<Secret, CredentialsError>,
    /// The Amazon Resource Name (ARN) of the role that the caller is assuming.
    pub role_arn: Variable<String, CredentialsError>,
    /// An identifier for the assumed role session. Typically, you pass the name or identifier that is
    /// associated with the user who is using your application. That way, the temporary security credentials
    /// that your application will use are associated with that user. This session name is included as part
    /// of the ARN and assumed role ID in the AssumedRoleUser response element.
    pub role_session_name: Variable<String, CredentialsError>,
}

impl WebIdentityProvider {
    /// Create new WebIdentityProvider by explicitly passing its configuration.
    pub fn new<A, B, C>(web_identity_token: A, role_arn: B, role_session_name: Option<C>) -> Self
    where
        A: Into<Variable<Secret, CredentialsError>>,
        B: Into<Variable<String, CredentialsError>>,
        C: Into<Variable<String, CredentialsError>>,
    {
        Self {
            web_identity_token: web_identity_token.into(),
            role_arn: role_arn.into(),
            role_session_name: role_session_name
                .map(|v| v.into())
                .unwrap_or_else(|| Variable::with_value(Self::create_session_name())),
        }
    }

    /// Creat a WebIdentityProvider from the following environment variables:
    ///
    /// - `AWS_WEB_IDENTITY_TOKEN_FILE` path to the web identity token file.
    /// - `AWS_ROLE_ARN` ARN of the role to assume.
    /// - `AWS_ROLE_SESSION_NAME` (optional) name applied to the assume-role session.
    ///
    /// See https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html
    /// for more information about how IAM Roles for Kubernetes Service Accounts works.
    pub fn from_k8s_env() -> Self {
        Self::_from_k8s_env(
            Variable::from_env_var(AWS_WEB_IDENTITY_TOKEN_FILE),
            Variable::from_env_var(AWS_ROLE_ARN),
            Some(Variable::from_env_var(AWS_ROLE_SESSION_NAME)),
        )
    }

    /// Used by unit testing
    pub(crate) fn _from_k8s_env(
        token_file: Variable<String, CredentialsError>,
        role: Variable<String, CredentialsError>,
        session_name: Option<Variable<String, CredentialsError>>,
    ) -> Self {
        Self::new(
            Variable::dynamic(move || Variable::from_text_file(token_file.resolve()?).resolve()),
            role,
            session_name,
        )
    }

    pub(crate) fn load_token(&self) -> Result<Secret, CredentialsError> {
        self.web_identity_token.resolve()
    }

    fn create_session_name() -> String {
        // TODO can we do better here?
        // - Pod service account, Pod name and Pod namespace
        // - EC2 Instance ID if available
        // - IP address if available
        // - ...
        // Having some information in the session name that identifies the client would enable
        // better correlation analysis in CloudTrail.
        "WebIdentitySession".to_string()
    }
}

impl ProvideAwsCredentials for WebIdentityProvider {
    type Future = WebIdentityProviderFuture;

    fn credentials(&self) -> Self::Future {
        WebIdentityProviderFuture {
            state: WebIdentityProviderFutureState::LoadBearerToken(
                self.load_token(),
                self.role_arn.resolve(),
                self.role_session_name.resolve(),
            ),
        }
    }
}

enum WebIdentityProviderFutureState {
    LoadBearerToken(
        Result<Secret, CredentialsError>,
        Result<String, CredentialsError>,
        Result<String, CredentialsError>,
    ),
    ExchangeToken(RusotoFuture<AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError>),
}

/// Provides AWS credentials from environment variables as a Future.
pub struct WebIdentityProviderFuture {
    state: WebIdentityProviderFutureState,
}

impl Future for WebIdentityProviderFuture {
    type Item = AwsCredentials;
    type Error = CredentialsError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        use crate::custom::credential::NewAwsCredsForStsCreds;
        use WebIdentityProviderFutureState::*;
        match &mut self.state {
            LoadBearerToken(Err(e), _, _) => Err(e.clone()),
            LoadBearerToken(_, Err(e), _) => Err(e.clone()),
            LoadBearerToken(_, _, Err(e)) => Err(e.clone()),
            LoadBearerToken(Ok(token), Ok(role), Ok(session)) => match HttpClient::new() {
                Err(e) => Err(CredentialsError::new(e.to_string())),
                Ok(c) => {
                    let client = Client::new_not_signing(c);
                    let sts = StsClient::new_with_client(client, Region::default());
                    let mut req = AssumeRoleWithWebIdentityRequest::default();
                    req.role_arn = role.clone();
                    req.web_identity_token = token.as_ref().to_string();
                    req.role_session_name = session.clone();
                    self.state = ExchangeToken(sts.assume_role_with_web_identity(req));
                    self.poll()
                }
            },
            ExchangeToken(ref mut future) => match future.poll() {
                Ok(Async::Ready(r)) => match r.credentials {
                    Some(c) => AwsCredentials::new_for_credentials(c).map(|c| Async::Ready(c)),
                    None => Err(CredentialsError::new(format!(
                        "No credentials found in AssumeRoleWithWebIdentityResponse: {:?}",
                        r
                    ))),
                },
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Err(e) => Err(CredentialsError::new(e.to_string())),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;
    use tempfile::NamedTempFile;

    #[test]
    fn api_ergonomy() {
        WebIdentityProvider::new(Secret::from("".to_string()), "", Some("".to_string()));
    }

    #[test]
    fn from_k8s_env() -> Result<(), CredentialsError> {
        const TOKEN_VALUE: &str = "secret";
        const ROLE_ARN: &str = "role";
        const SESSION_NAME: &str = "session";
        let mut file = NamedTempFile::new()?;
        // We use writeln to add an extra newline at the end of the token, which should be
        // removed by Variable::from_text_file.
        writeln!(file, "{}", TOKEN_VALUE)?;
        let p = WebIdentityProvider::_from_k8s_env(
            Variable::with_value(file.path().to_string_lossy().to_string()),
            Variable::with_value(ROLE_ARN.to_string()),
            Some(Variable::with_value(SESSION_NAME.to_string())),
        );
        let token = p.load_token()?;
        assert_eq!(token.as_ref(), TOKEN_VALUE);
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Provides an utility trait. It's a helper for descriptor sets and framebuffer.
// TODO: better documentation

use std::iter::Empty;
use std::sync::Arc;

use buffer::traits::TrackedBuffer;
use command_buffer::std::ResourcesStates;
use command_buffer::submit::SubmitInfo;
use command_buffer::sys::PipelineBarrierBuilder;
use device::Queue;
use image::traits::TrackedImage;
use sync::AccessFlagBits;
use sync::Fence;
use sync::PipelineStages;
use sync::Semaphore;

// TODO: re-read docs
/// Collection of tracked resources. Makes it possible to treat multiple buffers and images as one.
pub unsafe trait ResourcesCollection {
    type State;
    type Finished;

    /// Iterator that returns the list of semaphores to wait upon before the command buffer is
    /// submitted.
    type SemaphoresWaitIterator: Iterator<Item = (Arc<Semaphore>, PipelineStages)>;

    /// Iterator that returns the list of semaphores to signal after the command buffer has
    /// finished execution.
    type SemaphoresSignalIterator: Iterator<Item = Arc<Semaphore>>;

    /// Extracts the states relevant to the buffers and images contained in the descriptor set.
    /// Then transitions them to the right state.
    // TODO: must return a Result if multiple elements conflict with one another
    unsafe fn extract_states_and_transition<L>(&self, num_command: usize, list: &mut L)
                                               -> (Self::State, usize, PipelineBarrierBuilder)
        where L: ResourcesStates;

    #[inline]
    unsafe fn extract_buffer_state<B>(&self, _: &mut Self::State, buffer: &B) -> Option<B::CommandListState>
        where B: TrackedBuffer;

    #[inline]
    unsafe fn extract_image_state<I>(&self, _: &mut Self::State, image: &I) -> Option<I::CommandListState>
        where I: TrackedImage;

    unsafe fn finish(&self, Self::State) -> (Self::Finished, PipelineBarrierBuilder);

    // TODO: write docs
    unsafe fn on_submit<F>(&self, &Self::Finished, queue: &Arc<Queue>, fence: F)
                           -> SubmitInfo<Self::SemaphoresWaitIterator,
                                         Self::SemaphoresSignalIterator>
        where F: FnMut() -> Arc<Fence>;
}

pub struct End;

unsafe impl ResourcesCollection for End {
    type State = ();
    type Finished = ();
    type SemaphoresWaitIterator = Empty<(Arc<Semaphore>, PipelineStages)>;
    type SemaphoresSignalIterator = Empty<Arc<Semaphore>>;

    #[inline]
    unsafe fn extract_states_and_transition<L>(&self, _num_command: usize, _list: &mut L)
                                               -> ((), usize, PipelineBarrierBuilder)
        where L: ResourcesStates
    {
        ((), 0, PipelineBarrierBuilder::new())
    }

    #[inline]
    unsafe fn extract_buffer_state<B>(&self, _: &mut (), buffer: &B) -> Option<B::CommandListState>
        where B: TrackedBuffer
    {
        None
    }

    #[inline]
    unsafe fn extract_image_state<I>(&self, _: &mut (), image: &I) -> Option<I::CommandListState>
        where I: TrackedImage
    {
        None
    }

    #[inline]
    unsafe fn finish(&self, _: ()) -> ((), PipelineBarrierBuilder) {
        ((), PipelineBarrierBuilder::new())
    }

    unsafe fn on_submit<F>(&self, _: &(), queue: &Arc<Queue>, fence: F)
                           -> SubmitInfo<Self::SemaphoresWaitIterator,
                                         Self::SemaphoresSignalIterator>
        where F: FnMut() -> Arc<Fence>
    {
        unimplemented!()        // FIXME:
    }
}

pub struct Buf<B, N> {
    pub buffer: B,
    pub offset: usize,
    pub size: usize,
    pub write: bool,
    pub stage: PipelineStages,
    pub access: AccessFlagBits,
    pub rest: N,
}

unsafe impl<B, N> ResourcesCollection for Buf<B, N>
    where B: TrackedBuffer, N: ResourcesCollection
{
    type State = BufState<B::CommandListState, N::State>;
    type Finished = BufFinished<B::FinishedState, N::Finished>;
    type SemaphoresWaitIterator = Empty<(Arc<Semaphore>, PipelineStages)>;
    type SemaphoresSignalIterator = Empty<Arc<Semaphore>>;

    #[inline]
    unsafe fn extract_states_and_transition<L>(&self, num_command: usize, list: &mut L)
                                               -> (Self::State, usize, PipelineBarrierBuilder)
        where L: ResourcesStates
    {
        /*let (mut next_state, next_loc, mut next_builder) = {
            self.rest.extract_states_and_transition(num_command, list)
        };

        let my_buf_state = ResourcesStatesJoin(list, &mut next_state)
                                .extract_buffer_state(&self.buffer)
                                .unwrap_or(self.buffer.initial_state());

        let (my_buf_state, my_builder) = {
            my_buf_state.transition(num_command, self.buffer.inner(), self.offset, self.size,
                                    self.write, self.stage, self.access)
        };

        // TODO: return Err instead
        assert!(my_builder.as_ref().map(|b| b.after_command_num).unwrap_or(0) <= num_command);
        let command_num = cmp::max(my_builder.as_ref().map(|b| b.after_command_num).unwrap_or(0), next_loc);

        if let Some(my_builder) = my_builder {
            next_builder.add_buffer_barrier_request(self.buffer.inner(), my_builder);
        }

        (BufState(Some(my_buf_state), next_state), command_num, next_builder)*/
        unimplemented!()
    }

    #[inline]
    unsafe fn extract_buffer_state<Ob>(&self, _: &mut Self::State, buffer: &Ob) -> Option<Ob::CommandListState>
        where Ob: TrackedBuffer
    {
        // TODO:
        unimplemented!()
    }

    #[inline]
    unsafe fn extract_image_state<I>(&self, _: &mut Self::State, image: &I) -> Option<I::CommandListState>
        where I: TrackedImage
    {
        // TODO:
        unimplemented!()
    }

    #[inline]
    unsafe fn finish(&self, _: Self::State) -> (Self::Finished, PipelineBarrierBuilder) {
        // TODO:
        unimplemented!()
    }

    unsafe fn on_submit<F>(&self, _: &Self::Finished, queue: &Arc<Queue>, fence: F)
                           -> SubmitInfo<Self::SemaphoresWaitIterator,
                                         Self::SemaphoresSignalIterator>
        where F: FnMut() -> Arc<Fence>
    {
        unimplemented!()        // FIXME:
    }
}

pub struct BufState<B, N>(pub Option<B>, pub N);

pub struct BufFinished<B, N>(pub Option<B>, pub N);
<commit_msg>Rework resources collection to be easier to use<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Provides an utility trait. It's a helper for descriptor sets and framebuffer.
// TODO: better documentation

use std::iter::Empty;
use std::sync::Arc;

use buffer::traits::TrackedBuffer;
use command_buffer::std::ResourcesStates;
use command_buffer::submit::SubmitInfo;
use command_buffer::sys::PipelineBarrierBuilder;
use device::Queue;
use image::traits::TrackedImage;
use sync::AccessFlagBits;
use sync::Fence;
use sync::PipelineStages;
use sync::Semaphore;

// TODO: re-read docs
/// Collection of tracked resources. Makes it possible to treat multiple buffers and images as one.
pub unsafe trait ResourcesCollection {
    type State;
    type Finished;

    /// Iterator that returns the list of semaphores to wait upon before the command buffer is
    /// submitted.
    type SemaphoresWaitIterator: Iterator<Item = (Arc<Semaphore>, PipelineStages)>;

    /// Iterator that returns the list of semaphores to signal after the command buffer has
    /// finished execution.
    type SemaphoresSignalIterator: Iterator<Item = Arc<Semaphore>>;

    /// Extracts the states relevant to the buffers and images contained in the descriptor set.
    /// Then transitions them to the right state.
    // TODO: must return a Result if multiple elements conflict with one another
    unsafe fn extract_states_and_transition<L>(&self, num_command: usize, list: &mut L)
                                               -> (Self::State, usize, PipelineBarrierBuilder)
        where L: ResourcesStates;

    #[inline]
    unsafe fn extract_buffer_state<B>(&self, _: &mut Self::State, buffer: &B) -> Option<B::CommandListState>
        where B: TrackedBuffer;

    #[inline]
    unsafe fn extract_image_state<I>(&self, _: &mut Self::State, image: &I) -> Option<I::CommandListState>
        where I: TrackedImage;

    unsafe fn finish(&self, Self::State) -> (Self::Finished, PipelineBarrierBuilder);

    // TODO: write docs
    unsafe fn on_submit<F>(&self, &Self::Finished, queue: &Arc<Queue>, fence: F)
                           -> SubmitInfo<Self::SemaphoresWaitIterator,
                                         Self::SemaphoresSignalIterator>
        where F: FnMut() -> Arc<Fence>;
}

unsafe impl ResourcesCollection for () {
    type State = ();
    type Finished = ();
    type SemaphoresWaitIterator = Empty<(Arc<Semaphore>, PipelineStages)>;
    type SemaphoresSignalIterator = Empty<Arc<Semaphore>>;

    #[inline]
    unsafe fn extract_states_and_transition<L>(&self, _num_command: usize, _list: &mut L)
                                               -> ((), usize, PipelineBarrierBuilder)
        where L: ResourcesStates
    {
        ((), 0, PipelineBarrierBuilder::new())
    }

    #[inline]
    unsafe fn extract_buffer_state<B>(&self, _: &mut (), buffer: &B) -> Option<B::CommandListState>
        where B: TrackedBuffer
    {
        None
    }

    #[inline]
    unsafe fn extract_image_state<I>(&self, _: &mut (), image: &I) -> Option<I::CommandListState>
        where I: TrackedImage
    {
        None
    }

    #[inline]
    unsafe fn finish(&self, _: ()) -> ((), PipelineBarrierBuilder) {
        ((), PipelineBarrierBuilder::new())
    }

    unsafe fn on_submit<F>(&self, _: &(), queue: &Arc<Queue>, fence: F)
                           -> SubmitInfo<Self::SemaphoresWaitIterator,
                                         Self::SemaphoresSignalIterator>
        where F: FnMut() -> Arc<Fence>
    {
        unimplemented!()        // FIXME:
    }
}

pub struct Buf<B> {
    pub buffer: B,
    pub offset: usize,
    pub size: usize,
    pub write: bool,
    pub stage: PipelineStages,
    pub access: AccessFlagBits,
}

unsafe impl<B> ResourcesCollection for Buf<B>
    where B: TrackedBuffer
{
    type State = B::CommandListState;
    type Finished = B::FinishedState;
    type SemaphoresWaitIterator = Empty<(Arc<Semaphore>, PipelineStages)>;
    type SemaphoresSignalIterator = Empty<Arc<Semaphore>>;

    #[inline]
    unsafe fn extract_states_and_transition<L>(&self, num_command: usize, list: &mut L)
                                               -> (Self::State, usize, PipelineBarrierBuilder)
        where L: ResourcesStates
    {
        /*let (mut next_state, next_loc, mut next_builder) = {
            self.rest.extract_states_and_transition(num_command, list)
        };

        let my_buf_state = ResourcesStatesJoin(list, &mut next_state)
                                .extract_buffer_state(&self.buffer)
                                .unwrap_or(self.buffer.initial_state());

        let (my_buf_state, my_builder) = {
            my_buf_state.transition(num_command, self.buffer.inner(), self.offset, self.size,
                                    self.write, self.stage, self.access)
        };

        // TODO: return Err instead
        assert!(my_builder.as_ref().map(|b| b.after_command_num).unwrap_or(0) <= num_command);
        let command_num = cmp::max(my_builder.as_ref().map(|b| b.after_command_num).unwrap_or(0), next_loc);

        if let Some(my_builder) = my_builder {
            next_builder.add_buffer_barrier_request(self.buffer.inner(), my_builder);
        }

        (BufState(Some(my_buf_state), next_state), command_num, next_builder)*/
        unimplemented!()
    }

    #[inline]
    unsafe fn extract_buffer_state<Ob>(&self, _: &mut Self::State, buffer: &Ob) -> Option<Ob::CommandListState>
        where Ob: TrackedBuffer
    {
        // TODO:
        unimplemented!()
    }

    #[inline]
    unsafe fn extract_image_state<I>(&self, _: &mut Self::State, image: &I) -> Option<I::CommandListState>
        where I: TrackedImage
    {
        // TODO:
        unimplemented!()
    }

    #[inline]
    unsafe fn finish(&self, _: Self::State) -> (Self::Finished, PipelineBarrierBuilder) {
        // TODO:
        unimplemented!()
    }

    unsafe fn on_submit<F>(&self, _: &Self::Finished, queue: &Arc<Queue>, fence: F)
                           -> SubmitInfo<Self::SemaphoresWaitIterator,
                                         Self::SemaphoresSignalIterator>
        where F: FnMut() -> Arc<Fence>
    {
        unimplemented!()        // FIXME:
    }
}

macro_rules! tuple_impl {
    ($first:ident, $($rest:ident),+) => (
        unsafe impl<$first, $($rest),+> ResourcesCollection for ($first $(, $rest)+)
            where $first: ResourcesCollection, $($rest: ResourcesCollection),+
        {
            type State = (<$first as ResourcesCollection>::State,
                          <($($rest),+) as ResourcesCollection>::State);
            type Finished = (<$first as ResourcesCollection>::Finished,
                             <($($rest),+) as ResourcesCollection>::Finished);
            type SemaphoresWaitIterator = Empty<(Arc<Semaphore>, PipelineStages)>;
            type SemaphoresSignalIterator = Empty<Arc<Semaphore>>;

            #[inline]
            unsafe fn extract_states_and_transition<L>(&self, _num_command: usize, _list: &mut L)
                                                    -> (Self::State, usize, PipelineBarrierBuilder)
                where L: ResourcesStates
            {
                unimplemented!()
            }

            #[inline]
            unsafe fn extract_buffer_state<B>(&self, _: &mut Self::State, buffer: &B) -> Option<B::CommandListState>
                where B: TrackedBuffer
            {
                unimplemented!()
            }

            #[inline]
            unsafe fn extract_image_state<I>(&self, _: &mut Self::State, image: &I) -> Option<I::CommandListState>
                where I: TrackedImage
            {
                unimplemented!()
            }

            #[inline]
            unsafe fn finish(&self, _: Self::State) -> (Self::Finished, PipelineBarrierBuilder) {
                unimplemented!()
            }

            unsafe fn on_submit<F>(&self, _: &Self::Finished, queue: &Arc<Queue>, fence: F)
                                -> SubmitInfo<Self::SemaphoresWaitIterator,
                                                Self::SemaphoresSignalIterator>
                where F: FnMut() -> Arc<Fence>
            {
                unimplemented!()
            }
        }

        tuple_impl!($($rest),+);
    );

    ($first:ident) => ();
}

tuple_impl!(A, C, D, E, G, H, J, K, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
<|endoftext|>


<commit_before>use std::rc::Rc;

use crate::{
    prelude::*,
    shell::{Key, KeyEvent},
};

use super::{Event, EventBox, EventHandler};

#[derive(Event)]
pub struct KeyDownEvent {
    pub event: KeyEvent,
}

#[derive(Event)]
pub struct KeyUpEvent {
    pub event: KeyEvent,
}

pub type KeyHandler = dyn Fn(&mut StatesContext, KeyEvent) -> bool + 'static;

/// Used to handle key down events. Could be attached to a widget.
pub struct KeyDownEventHandler {
    handler: Rc<KeyHandler>,
}

impl Into<Rc<dyn EventHandler>> for KeyDownEventHandler {
    fn into(self) -> Rc<dyn EventHandler> {
        Rc::new(self)
    }
}

impl EventHandler for KeyDownEventHandler {
    fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
        event
            .downcast_ref::<KeyDownEvent>()
            .ok()
            .map_or(false, |event| {
                (self.handler)(state_context, event.event.clone())
            })
    }

    fn handles_event(&self, event: &EventBox) -> bool {
        event.is_type::<KeyDownEvent>()
    }
}

pub trait KeyDownHandler: Sized + Widget {
    /// Inserts a handler.
    fn on_key_down<H: Fn(&mut StatesContext, KeyEvent) -> bool + 'static>(
        self,
        handler: H,
    ) -> Self {
        self.insert_handler(KeyDownEventHandler {
            handler: Rc::new(handler),
        })
    }

    // Handles events triggered by a specific key.
    fn on_key_down_key<H: Fn() -> bool + 'static>(self, key: Key, handler: H) -> Self {
        self.on_key_down(
            move |_, event| {
                if event.key == key {
                    handler()
                } else {
                    false
                }
            },
        )
    }
}
<commit_msg>Turned comment into doc comment<commit_after>use std::rc::Rc;

use crate::{
    prelude::*,
    shell::{Key, KeyEvent},
};

use super::{Event, EventBox, EventHandler};

#[derive(Event)]
pub struct KeyDownEvent {
    pub event: KeyEvent,
}

#[derive(Event)]
pub struct KeyUpEvent {
    pub event: KeyEvent,
}

pub type KeyHandler = dyn Fn(&mut StatesContext, KeyEvent) -> bool + 'static;

/// Used to handle key down events. Could be attached to a widget.
pub struct KeyDownEventHandler {
    handler: Rc<KeyHandler>,
}

impl Into<Rc<dyn EventHandler>> for KeyDownEventHandler {
    fn into(self) -> Rc<dyn EventHandler> {
        Rc::new(self)
    }
}

impl EventHandler for KeyDownEventHandler {
    fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
        event
            .downcast_ref::<KeyDownEvent>()
            .ok()
            .map_or(false, |event| {
                (self.handler)(state_context, event.event.clone())
            })
    }

    fn handles_event(&self, event: &EventBox) -> bool {
        event.is_type::<KeyDownEvent>()
    }
}

pub trait KeyDownHandler: Sized + Widget {
    /// Inserts a handler.
    fn on_key_down<H: Fn(&mut StatesContext, KeyEvent) -> bool + 'static>(
        self,
        handler: H,
    ) -> Self {
        self.insert_handler(KeyDownEventHandler {
            handler: Rc::new(handler),
        })
    }

    /// Handles events triggered by a specific key.
    fn on_key_down_key<H: Fn() -> bool + 'static>(self, key: Key, handler: H) -> Self {
        self.on_key_down(
            move |_, event| {
                if event.key == key {
                    handler()
                } else {
                    false
                }
            },
        )
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(path)]
#![feature(rustc_private)]

extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::collections::HashMap;
use std::old_io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory,Expression};

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options] FILE...", program);
    print!("{}", usage(&brief, opts));
}

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {:?}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml(filename: &str) -> document::Package {
    let p = Parser::new();
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>() -> xpath::Variables<'a> {
    HashMap::new()
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();
    for ns_defn in arguments.opt_strs("namespace").iter() {
        let parts: Vec<_> = ns_defn.splitn(2, ':').collect();
        if parts.len() < 2 {
            panic!("Namespace definition '{}' is malformed", ns_defn);
        }

        namespaces.insert(parts[0].to_string(), parts[1].to_string());
    }
    namespaces
}

#[allow(dead_code)]
fn main() {
    let args = std::os::args();
    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name, opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(&xpath_str);

    for filename in arguments.free.iter() {
        let package = load_xml(filename);
        let doc = package.as_document();
        let root = doc.root().to_node();

        let functions = build_functions();
        let variables = build_variables();
        let namespaces = build_namespaces(&arguments);

        let context = EvaluationContext::new(
            root,
            &functions,
            &variables,
            &namespaces,
        );

        let res = xpath.evaluate(&context);

        println!("{:?}", res);
    }
}
<commit_msg>Update for new command-line argument access<commit_after>#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(env)]
#![feature(path)]
#![feature(rustc_private)]

extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::env;
use std::collections::HashMap;
use std::old_io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory,Expression};

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options] FILE...", program);
    print!("{}", usage(&brief, opts));
}

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {:?}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml(filename: &str) -> document::Package {
    let p = Parser::new();
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>() -> xpath::Variables<'a> {
    HashMap::new()
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();
    for ns_defn in arguments.opt_strs("namespace").iter() {
        let parts: Vec<_> = ns_defn.splitn(2, ':').collect();
        if parts.len() < 2 {
            panic!("Namespace definition '{}' is malformed", ns_defn);
        }

        namespaces.insert(parts[0].to_string(), parts[1].to_string());
    }
    namespaces
}

#[allow(dead_code)]
fn main() {
    let args: Result<Vec<_>, _> = env::args().map(|a| a.into_string()).collect();
    let args = args.unwrap();

    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name, opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(&xpath_str);

    for filename in arguments.free.iter() {
        let package = load_xml(filename);
        let doc = package.as_document();
        let root = doc.root().to_node();

        let functions = build_functions();
        let variables = build_variables();
        let namespaces = build_namespaces(&arguments);

        let context = EvaluationContext::new(
            root,
            &functions,
            &variables,
            &namespaces,
        );

        let res = xpath.evaluate(&context);

        println!("{:?}", res);
    }
}
<|endoftext|>


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

//! Generic hashing support.
//!
//! This module provides a generic way to compute the hash of a value. The
//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
//!
//! # Examples
//!
//! ```rust
//! # #![feature(hash)]
//! use std::hash::{hash, Hash, SipHasher};
//!
//! #[derive(Hash)]
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert!(hash::<_, SipHasher>(&person1) != hash::<_, SipHasher>(&person2));
//! ```
//!
//! If you need more control over how a value is hashed, you need to implement
//! the trait `Hash`:
//!
//! ```rust
//! # #![feature(hash)]
//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! impl Hash for Person {
//!     fn hash<H: Hasher>(&self, state: &mut H) {
//!         self.id.hash(state);
//!         self.phone.hash(state);
//!     }
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;

use default::Default;
use mem;

pub use self::sip::SipHasher;

mod sip;

/// A hashable type.
///
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
    /// Feeds this value into the state given, updating the hasher as necessary.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
        for piece in data {
            piece.hash(state);
        }
    }
}

/// A trait which represents the ability to hash an arbitrary stream of bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
    /// Completes a round of hashing, producing the output hash generated.
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn finish(&self) -> u64;

    /// Writes some data into this `Hasher`
    #[stable(feature = "rust1", since = "1.0.0")]
    fn write(&mut self, bytes: &[u8]);

    /// Write a single `u8` into this hasher
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u8(&mut self, i: u8) { self.write(&[i]) }
    /// Write a single `u16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u16(&mut self, i: u16) {
        self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
    }
    /// Write a single `u32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u32(&mut self, i: u32) {
        self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
    }
    /// Write a single `u64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u64(&mut self, i: u64) {
        self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
    }
    /// Write a single `usize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_usize(&mut self, i: usize) {
        if cfg!(target_pointer_width = "32") {
            self.write_u32(i as u32)
        } else {
            self.write_u64(i as u64)
        }
    }

    /// Write a single `i8` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
    /// Write a single `i16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
    /// Write a single `i32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
    /// Write a single `i64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
    /// Write a single `isize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
}

/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
///
/// The specified value will be hashed with this hasher and then the resulting
/// hash will be returned.
#[unstable(feature = "hash", reason = "module was recently redesigned")]
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
    let mut h: H = Default::default();
    value.hash(&mut h);
    h.finish()
}

//////////////////////////////////////////////////////////////////////////////

mod impls {
    use prelude::*;

    use slice;
    use super::*;

    macro_rules! impl_write {
        ($(($ty:ident, $meth:ident),)*) => {$(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for $ty {
                fn hash<H: Hasher>(&self, state: &mut H) {
                    state.$meth(*self)
                }

                fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
                    let newlen = data.len() * ::$ty::BYTES as usize;
                    let ptr = data.as_ptr() as *const u8;
                    state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
                }
            }
        )*}
    }

    impl_write! {
        (u8, write_u8),
        (u16, write_u16),
        (u32, write_u32),
        (u64, write_u64),
        (usize, write_usize),
        (i8, write_i8),
        (i16, write_i16),
        (i32, write_i32),
        (i64, write_i64),
        (isize, write_isize),
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for bool {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u8(*self as u8)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for char {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u32(*self as u32)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for str {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write(self.as_bytes());
            state.write_u8(0xff)
        }
    }

    macro_rules! impl_hash_tuple {
        () => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for () {
                fn hash<H: Hasher>(&self, _state: &mut H) {}
            }
        );

        ( $($name:ident)+) => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<$($name: Hash),*> Hash for ($($name,)*) {
                #[allow(non_snake_case)]
                fn hash<S: Hasher>(&self, state: &mut S) {
                    let ($(ref $name,)*) = *self;
                    $($name.hash(state);)*
                }
            }
        );
    }

    impl_hash_tuple! {}
    impl_hash_tuple! { A }
    impl_hash_tuple! { A B }
    impl_hash_tuple! { A B C }
    impl_hash_tuple! { A B C D }
    impl_hash_tuple! { A B C D E }
    impl_hash_tuple! { A B C D E F }
    impl_hash_tuple! { A B C D E F G }
    impl_hash_tuple! { A B C D E F G H }
    impl_hash_tuple! { A B C D E F G H I }
    impl_hash_tuple! { A B C D E F G H I J }
    impl_hash_tuple! { A B C D E F G H I J K }
    impl_hash_tuple! { A B C D E F G H I J K L }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: Hash> Hash for [T] {
        fn hash<H: Hasher>(&self, state: &mut H) {
            self.len().hash(state);
            Hash::hash_slice(self, state)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *const T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }
}
<commit_msg>rollup merge of #23652: alexcrichton/stabilize-hasher-finish<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Generic hashing support.
//!
//! This module provides a generic way to compute the hash of a value. The
//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
//!
//! # Examples
//!
//! ```rust
//! # #![feature(hash)]
//! use std::hash::{hash, Hash, SipHasher};
//!
//! #[derive(Hash)]
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert!(hash::<_, SipHasher>(&person1) != hash::<_, SipHasher>(&person2));
//! ```
//!
//! If you need more control over how a value is hashed, you need to implement
//! the trait `Hash`:
//!
//! ```rust
//! # #![feature(hash)]
//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! impl Hash for Person {
//!     fn hash<H: Hasher>(&self, state: &mut H) {
//!         self.id.hash(state);
//!         self.phone.hash(state);
//!     }
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;

use default::Default;
use mem;

pub use self::sip::SipHasher;

mod sip;

/// A hashable type.
///
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
    /// Feeds this value into the state given, updating the hasher as necessary.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
        for piece in data {
            piece.hash(state);
        }
    }
}

/// A trait which represents the ability to hash an arbitrary stream of bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
    /// Completes a round of hashing, producing the output hash generated.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn finish(&self) -> u64;

    /// Writes some data into this `Hasher`
    #[stable(feature = "rust1", since = "1.0.0")]
    fn write(&mut self, bytes: &[u8]);

    /// Write a single `u8` into this hasher
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u8(&mut self, i: u8) { self.write(&[i]) }
    /// Write a single `u16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u16(&mut self, i: u16) {
        self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
    }
    /// Write a single `u32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u32(&mut self, i: u32) {
        self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
    }
    /// Write a single `u64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u64(&mut self, i: u64) {
        self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
    }
    /// Write a single `usize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_usize(&mut self, i: usize) {
        if cfg!(target_pointer_width = "32") {
            self.write_u32(i as u32)
        } else {
            self.write_u64(i as u64)
        }
    }

    /// Write a single `i8` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
    /// Write a single `i16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
    /// Write a single `i32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
    /// Write a single `i64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
    /// Write a single `isize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
}

/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
///
/// The specified value will be hashed with this hasher and then the resulting
/// hash will be returned.
#[unstable(feature = "hash", reason = "module was recently redesigned")]
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
    let mut h: H = Default::default();
    value.hash(&mut h);
    h.finish()
}

//////////////////////////////////////////////////////////////////////////////

mod impls {
    use prelude::*;

    use slice;
    use super::*;

    macro_rules! impl_write {
        ($(($ty:ident, $meth:ident),)*) => {$(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for $ty {
                fn hash<H: Hasher>(&self, state: &mut H) {
                    state.$meth(*self)
                }

                fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
                    let newlen = data.len() * ::$ty::BYTES as usize;
                    let ptr = data.as_ptr() as *const u8;
                    state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
                }
            }
        )*}
    }

    impl_write! {
        (u8, write_u8),
        (u16, write_u16),
        (u32, write_u32),
        (u64, write_u64),
        (usize, write_usize),
        (i8, write_i8),
        (i16, write_i16),
        (i32, write_i32),
        (i64, write_i64),
        (isize, write_isize),
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for bool {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u8(*self as u8)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for char {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u32(*self as u32)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for str {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write(self.as_bytes());
            state.write_u8(0xff)
        }
    }

    macro_rules! impl_hash_tuple {
        () => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for () {
                fn hash<H: Hasher>(&self, _state: &mut H) {}
            }
        );

        ( $($name:ident)+) => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<$($name: Hash),*> Hash for ($($name,)*) {
                #[allow(non_snake_case)]
                fn hash<S: Hasher>(&self, state: &mut S) {
                    let ($(ref $name,)*) = *self;
                    $($name.hash(state);)*
                }
            }
        );
    }

    impl_hash_tuple! {}
    impl_hash_tuple! { A }
    impl_hash_tuple! { A B }
    impl_hash_tuple! { A B C }
    impl_hash_tuple! { A B C D }
    impl_hash_tuple! { A B C D E }
    impl_hash_tuple! { A B C D E F }
    impl_hash_tuple! { A B C D E F G }
    impl_hash_tuple! { A B C D E F G H }
    impl_hash_tuple! { A B C D E F G H I }
    impl_hash_tuple! { A B C D E F G H I J }
    impl_hash_tuple! { A B C D E F G H I J K }
    impl_hash_tuple! { A B C D E F G H I J K L }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: Hash> Hash for [T] {
        fn hash<H: Hasher>(&self, state: &mut H) {
            self.len().hash(state);
            Hash::hash_slice(self, state)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *const T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }
}
<|endoftext|>


<commit_before>
static POPCNT8: &'static [u8] = &[
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
];

const DEBRUIJ_M: u64 = 0x03f7_9d71_b4cb_0a89;

// BitScanForward: Djuin:            9 s
// BitScanForward: PopCount - Old : 18 s
// BitScanForward: PopCount - Rust: 26 s

// PopCount: Rust:  22 s
// PopCount: Old :  37 s

/// Counts the number of bits
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(popcount64(0b1001), 2);
/// ```
#[inline(always)]
pub fn popcount64(x: u64) -> u8 {
    x.count_ones() as u8
}

/// Returns index of the Least Significant Bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(bit_scan_forward(0b10100),2)
/// ```
///
#[inline(always)]
pub fn bit_scan_forward(bits: u64) -> u8 {
    assert_ne!(bits, 0);
    DEBRUIJ_T[(((bits ^ bits.wrapping_sub(1)).wrapping_mul(DEBRUIJ_M)).wrapping_shr(58)) as usize]
}

/// Returns index of the Least Significant Bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(bit_scan_forward(0b100),2);
/// ```
///
#[inline(always)]
pub fn bit_scan_forward_rust_trailing(bits: u64) -> u8 {
    assert_ne!(bits, 0);
    bits.trailing_zeros() as u8
}

/// Returns index of the Most Significant Bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(bit_scan_reverse(0b101),2);
/// ```
///
#[inline(always)]
pub fn bit_scan_reverse(mut bb: u64) -> u8 {
    assert_ne!(bb, 0);
    bb |= bb >> 1;
    bb |= bb >> 2;
    bb |= bb >> 4;
    bb |= bb >> 8;
    bb |= bb >> 16;
    bb |= bb >> 32;
    DEBRUIJ_T[(bb.wrapping_mul(DEBRUIJ_M)).wrapping_shr(58) as usize]
}

/// Returns if there are more than one bits in a u64
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert!(more_than_one(0b1111));
///
/// assert!(!more_than_one(0b0001))
///
/// ```
#[inline(always)]
pub fn more_than_one(x: u64) -> bool {
    (x & (x.wrapping_sub(1))) != 0
}

/// Returns the least significant bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(lsb(0b1001), 0b0001);
/// ```
#[inline(always)]
pub fn lsb(bits: u64) -> u64 {
    (1 as u64).wrapping_shl(bits.trailing_zeros())
}

// Returns the most significant bit
//
// # Examples
//
// ```
// use pleco::bit_twiddles::*;
//
// assert_eq!(msb(0b1001), 0b1000);
// ```
#[inline(always)]
pub fn msb(bits: u64) -> u64 {
    // BAD CODE DO NOT USE
    (1 as u64).wrapping_shl(bits.leading_zeros())
}

/// Counts the number of bits
#[inline(always)]
fn popcount_old(x: u64) -> u8 {
    let x = x as usize;
    if x == 0 {
        return 0;
    }
    if x & (x.wrapping_sub(1)) == 0 {
        return 1;
    }
    POPCNT8[x >> 56] + POPCNT8[(x >> 48) & 0xFF] + POPCNT8[(x >> 40) & 0xFF] +
        POPCNT8[(x >> 32) & 0xFF] + POPCNT8[(x >> 24) & 0xFF] + POPCNT8[(x >> 16) & 0xFF] +
        POPCNT8[(x >> 8) & 0xFF] + POPCNT8[x & 0xFF]
}

#[cfg(test)]
mod tests {

    use bit_twiddles;

    #[test]
    fn test_bit_scan() {
        assert_eq!(bit_twiddles::bit_scan_forward(2), 1);
        assert_eq!(bit_twiddles::bit_scan_forward(4), 2);
        assert_eq!(bit_twiddles::bit_scan_forward(8), 3);
        assert_eq!(bit_twiddles::bit_scan_forward(16), 4);
        assert_eq!(bit_twiddles::bit_scan_forward(32), 5);
        assert_eq!(bit_twiddles::bit_scan_forward(31), 0);
        assert_eq!(bit_twiddles::bit_scan_forward(0b000000000000001), 0);
        assert_eq!(bit_twiddles::bit_scan_forward(0b000000000000010), 1);
        assert_eq!(bit_twiddles::bit_scan_forward(0b110011100000010), 1);
        assert_eq!(bit_twiddles::bit_scan_forward(0b110011100000010), 1);
    }

    #[test]
    fn popcount() {
        assert_eq!(bit_twiddles::popcount64(0b000000000000000), 0);
        assert_eq!(bit_twiddles::popcount64(0b11111100000001), 7);
        assert_eq!(bit_twiddles::popcount64(0b1000010000), 2);
        assert_eq!(bit_twiddles::popcount64(0xFFFFFFFF), 32);
        assert_eq!(bit_twiddles::popcount64(0x55555555), 16);
    }

    #[test]
    fn lsb() {
        assert_eq!(bit_twiddles::lsb(0b110011100000010), 0b10);
        assert_eq!(bit_twiddles::lsb(0b1010000000000000), 0b10000000000000);
        assert_eq!(bit_twiddles::lsb(0b11001110000), 0b10000);
        assert_eq!(bit_twiddles::lsb(0b100001000000), 0b1000000);
        assert_eq!(bit_twiddles::lsb(0b1), 0b1);
    }

}<commit_msg>Forgot a file<commit_after>
static POPCNT8: &'static [u8] = &[
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
];

static DEBRUIJ_T: &'static [u8] = &[
    0, 47,  1, 56, 48, 27,  2, 60,
    57, 49, 41, 37, 28, 16,  3, 61,
    54, 58, 35, 52, 50, 42, 21, 44,
    38, 32, 29, 23, 17, 11,  4, 62,
    46, 55, 26, 59, 40, 36, 15, 53,
    34, 51, 20, 43, 31, 22, 10, 45,
    25, 39, 14, 33, 19, 30,  9, 24,
    13, 18,  8, 12,  7,  6,  5, 63
];

const DEBRUIJ_M: u64 = 0x03f7_9d71_b4cb_0a89;

// BitScanForward: Djuin:            9 s
// BitScanForward: PopCount - Old : 18 s
// BitScanForward: PopCount - Rust: 26 s

// PopCount: Rust:  22 s
// PopCount: Old :  37 s

/// Counts the number of bits
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(popcount64(0b1001), 2);
/// ```
#[inline(always)]
pub fn popcount64(x: u64) -> u8 {
    x.count_ones() as u8
}

/// Returns index of the Least Significant Bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(bit_scan_forward(0b10100),2)
/// ```
///
#[inline(always)]
pub fn bit_scan_forward(bits: u64) -> u8 {
    assert_ne!(bits, 0);
    DEBRUIJ_T[(((bits ^ bits.wrapping_sub(1)).wrapping_mul(DEBRUIJ_M)).wrapping_shr(58)) as usize]
}

/// Returns index of the Least Significant Bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(bit_scan_forward(0b100),2);
/// ```
///
#[inline(always)]
pub fn bit_scan_forward_rust_trailing(bits: u64) -> u8 {
    assert_ne!(bits, 0);
    bits.trailing_zeros() as u8
}

/// Returns index of the Most Significant Bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(bit_scan_reverse(0b101),2);
/// ```
///
#[inline(always)]
pub fn bit_scan_reverse(mut bb: u64) -> u8 {
    assert_ne!(bb, 0);
    bb |= bb >> 1;
    bb |= bb >> 2;
    bb |= bb >> 4;
    bb |= bb >> 8;
    bb |= bb >> 16;
    bb |= bb >> 32;
    DEBRUIJ_T[(bb.wrapping_mul(DEBRUIJ_M)).wrapping_shr(58) as usize]
}

/// Returns if there are more than one bits in a u64
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert!(more_than_one(0b1111));
///
/// assert!(!more_than_one(0b0001))
///
/// ```
#[inline(always)]
pub fn more_than_one(x: u64) -> bool {
    (x & (x.wrapping_sub(1))) != 0
}

/// Returns the least significant bit
///
/// # Examples
///
/// ```
/// use pleco::bit_twiddles::*;
///
/// assert_eq!(lsb(0b1001), 0b0001);
/// ```
#[inline(always)]
pub fn lsb(bits: u64) -> u64 {
    (1 as u64).wrapping_shl(bits.trailing_zeros())
}

// Returns the most significant bit
//
// # Examples
//
// ```
// use pleco::bit_twiddles::*;
//
// assert_eq!(msb(0b1001), 0b1000);
// ```
#[inline(always)]
pub fn msb(bits: u64) -> u64 {
    // BAD CODE DO NOT USE
    (1 as u64).wrapping_shl(bits.leading_zeros())
}

/// Counts the number of bits
#[inline(always)]
fn popcount_old(x: u64) -> u8 {
    let x = x as usize;
    if x == 0 {
        return 0;
    }
    if x & (x.wrapping_sub(1)) == 0 {
        return 1;
    }
    POPCNT8[x >> 56] + POPCNT8[(x >> 48) & 0xFF] + POPCNT8[(x >> 40) & 0xFF] +
        POPCNT8[(x >> 32) & 0xFF] + POPCNT8[(x >> 24) & 0xFF] + POPCNT8[(x >> 16) & 0xFF] +
        POPCNT8[(x >> 8) & 0xFF] + POPCNT8[x & 0xFF]
}

#[cfg(test)]
mod tests {

    use bit_twiddles;

    #[test]
    fn test_bit_scan() {
        assert_eq!(bit_twiddles::bit_scan_forward(2), 1);
        assert_eq!(bit_twiddles::bit_scan_forward(4), 2);
        assert_eq!(bit_twiddles::bit_scan_forward(8), 3);
        assert_eq!(bit_twiddles::bit_scan_forward(16), 4);
        assert_eq!(bit_twiddles::bit_scan_forward(32), 5);
        assert_eq!(bit_twiddles::bit_scan_forward(31), 0);
        assert_eq!(bit_twiddles::bit_scan_forward(0b000000000000001), 0);
        assert_eq!(bit_twiddles::bit_scan_forward(0b000000000000010), 1);
        assert_eq!(bit_twiddles::bit_scan_forward(0b110011100000010), 1);
        assert_eq!(bit_twiddles::bit_scan_forward(0b110011100000010), 1);
    }

    #[test]
    fn popcount() {
        assert_eq!(bit_twiddles::popcount64(0b000000000000000), 0);
        assert_eq!(bit_twiddles::popcount64(0b11111100000001), 7);
        assert_eq!(bit_twiddles::popcount64(0b1000010000), 2);
        assert_eq!(bit_twiddles::popcount64(0xFFFFFFFF), 32);
        assert_eq!(bit_twiddles::popcount64(0x55555555), 16);
    }

    #[test]
    fn lsb() {
        assert_eq!(bit_twiddles::lsb(0b110011100000010), 0b10);
        assert_eq!(bit_twiddles::lsb(0b1010000000000000), 0b10000000000000);
        assert_eq!(bit_twiddles::lsb(0b11001110000), 0b10000);
        assert_eq!(bit_twiddles::lsb(0b100001000000), 0b1000000);
        assert_eq!(bit_twiddles::lsb(0b1), 0b1);
    }

}<|endoftext|>