<commit_before>#![feature(try_trait)]

extern crate pgn_reader;
extern crate memmap;
extern crate madvise;
extern crate btoi;
extern crate rand;

use std::env;
use std::str;
use std::fs::File;
use std::option::NoneError;

use memmap::Mmap;
use madvise::{AccessPattern, AdviseMemory};
use pgn_reader::{Visitor, Skip, Reader, San};
use btoi::ParseIntegerError;
use rand::{random, Closed01};

#[derive(Debug)]
enum TimeControl {
    UltraBullet,
    Bullet,
    Blitz,
    Classical,
    Correspondence,
}

#[derive(Debug)]
struct TimeControlError;

impl From<NoneError> for TimeControlError {
    fn from(_: NoneError) -> TimeControlError {
        TimeControlError { }
    }
}

impl From<ParseIntegerError> for TimeControlError {
    fn from(_: ParseIntegerError) -> TimeControlError {
        TimeControlError { }
    }
}

impl TimeControl {
    fn from_seconds_and_increment(seconds: u64, increment: u64) -> TimeControl {
        let total = seconds + 40 * increment;

        if total < 30 {
            TimeControl::UltraBullet
        } else if total < 180 {
            TimeControl::Bullet
        } else if total < 480 {
            TimeControl::Blitz
        } else if total < 21600 {
            TimeControl::Classical
        } else {
            TimeControl::Correspondence
        }
    }

    fn from_bytes(bytes: &[u8]) -> Result<TimeControl, TimeControlError> {
        if bytes == b"-" {
            return Ok(TimeControl::Correspondence);
        }

        let mut parts = bytes.splitn(2, |ch| *ch == b'+');
        let seconds = btoi::btou(parts.next()?)?;
        let increment = btoi::btou(parts.next()?)?;
        Ok(TimeControl::from_seconds_and_increment(seconds, increment))
    }
}

struct Indexer {
    white_elo: i16,
    black_elo: i16,
    time_control: TimeControl,
    skip: bool,
}

impl Indexer {
    fn new() -> Indexer {
        Indexer {
            white_elo: 0,
            black_elo: 0,
            time_control: TimeControl::Correspondence,
            skip: true,
        }
    }
}

impl<'pgn> Visitor<'pgn> for Indexer {
    type Result = ();

    fn begin_headers(&mut self) {
        self.white_elo = 0;
        self.black_elo = 0;
        self.time_control = TimeControl::Correspondence;
    }

    fn header(&mut self, key: &'pgn [u8], value: &'pgn [u8]) {
        if key == b"WhiteElo" {
            self.white_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("WhiteElo") };
        } else if key == b"BlackElo" {
            self.black_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("BlackElo") };
        } else if key == b"TimeControl" {
            self.time_control = TimeControl::from_bytes(value).expect("TimeControl");
        }
    }

    fn end_headers(&mut self) -> Skip {
        let rating = (self.white_elo + self.black_elo) / 2;

        let probability = match self.time_control {
            TimeControl::Correspondence => 1.0,
            TimeControl::Classical if rating >= 2000 => 1.0,
            TimeControl::Classical if rating >= 1800 => 2.0 / 5.0,
            TimeControl::Classical => 1.0 / 8.0,
            TimeControl::Blitz if rating >= 2000 => 1.0,
            TimeControl::Blitz if rating >= 1800 => 1.0 / 4.0,
            TimeControl::Blitz => 1.0 / 15.0,
            TimeControl::Bullet if rating >= 2300 => 1.0,
            TimeControl::Bullet if rating >= 2200 => 4.0 / 5.0,
            TimeControl::Bullet if rating >= 2000 => 1.0 / 4.0,
            TimeControl::Bullet if rating >= 1800 => 1.0 / 7.0,
            _ => 1.0 / 20.0,
        };

        let Closed01(rnd) = random::<Closed01<f64>>();
        self.skip = probability < rnd;
        Skip(self.skip)
    }

    fn san(&mut self, _san: San) { }

    fn begin_variation(&mut self) -> Skip {
        Skip(true) // stay in the mainline
    }

    fn end_game(&mut self, game: &'pgn [u8]) {
        println!("{}", str::from_utf8(game).expect("utf8"));
    }
}

fn main() {
    for arg in env::args().skip(1) {
        eprintln!("% indexing {} ...", arg);
        let file = File::open(&arg).expect("fopen");
        let pgn = unsafe { Mmap::map(&file).expect("mmap") };
        pgn.advise_memory_access(AccessPattern::Sequential).expect("madvise");

        let mut indexer = Indexer::new();
        Reader::new(&mut indexer, &pgn[..]).read_all();
    }
}
<commit_msg>prepare sending fast pgn in batches<commit_after>#![feature(try_trait)]

extern crate pgn_reader;
extern crate memmap;
extern crate madvise;
extern crate btoi;
extern crate rand;

use std::env;
use std::str;
use std::fs::File;
use std::option::NoneError;

use memmap::Mmap;
use madvise::{AccessPattern, AdviseMemory};
use pgn_reader::{Visitor, Skip, Reader, San};
use btoi::ParseIntegerError;
use rand::{random, Closed01};

const BATCH_SIZE: usize = 50;

const MAX_PLIES: usize = 50;

#[derive(Debug)]
enum TimeControl {
    UltraBullet,
    Bullet,
    Blitz,
    Classical,
    Correspondence,
}

#[derive(Debug)]
struct TimeControlError;

impl From<NoneError> for TimeControlError {
    fn from(_: NoneError) -> TimeControlError {
        TimeControlError { }
    }
}

impl From<ParseIntegerError> for TimeControlError {
    fn from(_: ParseIntegerError) -> TimeControlError {
        TimeControlError { }
    }
}

impl TimeControl {
    fn from_seconds_and_increment(seconds: u64, increment: u64) -> TimeControl {
        let total = seconds + 40 * increment;

        if total < 30 {
            TimeControl::UltraBullet
        } else if total < 180 {
            TimeControl::Bullet
        } else if total < 480 {
            TimeControl::Blitz
        } else if total < 21600 {
            TimeControl::Classical
        } else {
            TimeControl::Correspondence
        }
    }

    fn from_bytes(bytes: &[u8]) -> Result<TimeControl, TimeControlError> {
        if bytes == b"-" {
            return Ok(TimeControl::Correspondence);
        }

        let mut parts = bytes.splitn(2, |ch| *ch == b'+');
        let seconds = btoi::btou(parts.next()?)?;
        let increment = btoi::btou(parts.next()?)?;
        Ok(TimeControl::from_seconds_and_increment(seconds, increment))
    }
}

struct Indexer {
    white_elo: i16,
    black_elo: i16,
    time_control: TimeControl,
    skip: bool,
    current_game: Vec<u8>,
    plies: usize,
    batch: Vec<u8>,
    batch_size: usize,
}

impl Indexer {
    fn new() -> Indexer {
        Indexer {
            white_elo: 0,
            black_elo: 0,
            time_control: TimeControl::Correspondence,
            skip: true,
            current_game: Vec::new(),
            plies: 0,
            batch: Vec::new(),
            batch_size: 0,
        }
    }

    fn send(&mut self) {
        if self.batch_size > 0 {
            // TODO: Send
            println!("{}", str::from_utf8(&self.batch).expect("utf8"));

            self.batch_size = 0;
            self.batch.clear();
        }
    }
}

impl<'pgn> Visitor<'pgn> for Indexer {
    type Result = ();

    fn begin_headers(&mut self) {
        self.white_elo = 0;
        self.black_elo = 0;
        self.time_control = TimeControl::Correspondence;
        self.current_game.clear();
        self.plies = 0;
    }

    fn header(&mut self, key: &'pgn [u8], value: &'pgn [u8]) {
        if key == b"WhiteElo" {
            self.white_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("WhiteElo") };
        } else if key == b"BlackElo" {
            self.black_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("BlackElo") };
        } else if key == b"TimeControl" {
            self.time_control = TimeControl::from_bytes(value).expect("TimeControl");
        }

        let (key, value) = if key == b"Site" {
            (&b"LichessID"[..], value.rsplitn(2, |ch| *ch == b'/').next().expect("Site"))
        } else {
            (key, value)
        };

        self.current_game.push(b'[');
        self.current_game.extend(key);
        self.current_game.extend(b" \"");
        self.current_game.extend(value);
        self.current_game.extend(b"\"]\n");
    }

    fn end_headers(&mut self) -> Skip {
        self.current_game.push(b'\n');

        let rating = (self.white_elo + self.black_elo) / 2;

        let probability = match self.time_control {
            TimeControl::Correspondence => 1.0,
            TimeControl::Classical if rating >= 2000 => 1.0,
            TimeControl::Classical if rating >= 1800 => 2.0 / 5.0,
            TimeControl::Classical => 1.0 / 8.0,
            TimeControl::Blitz if rating >= 2000 => 1.0,
            TimeControl::Blitz if rating >= 1800 => 1.0 / 4.0,
            TimeControl::Blitz => 1.0 / 15.0,
            TimeControl::Bullet if rating >= 2300 => 1.0,
            TimeControl::Bullet if rating >= 2200 => 4.0 / 5.0,
            TimeControl::Bullet if rating >= 2000 => 1.0 / 4.0,
            TimeControl::Bullet if rating >= 1800 => 1.0 / 7.0,
            _ => 1.0 / 20.0,
        };

        let Closed01(rnd) = random::<Closed01<f64>>();
        self.skip = probability < rnd;
        Skip(self.skip)
    }

    fn san(&mut self, san: San) {
        if self.plies < MAX_PLIES {
            if self.plies > 0 {
                self.current_game.push(b' ');
            }

            self.current_game.extend(san.to_string().as_bytes());
            self.plies += 1;
        }
    }

    fn begin_variation(&mut self) -> Skip {
        Skip(true) // stay in the mainline
    }

    fn end_game(&mut self, _game: &'pgn [u8]) {
        if !self.skip {
            if self.batch_size > BATCH_SIZE {
                self.send();
            }

            if self.batch_size > 0 {
                self.batch.extend(b"\n\n\n");
            }

            self.batch.extend(&self.current_game);
            self.batch_size += 1;
        }
    }
}

fn main() {
    for arg in env::args().skip(1) {
        eprintln!("% indexing {} ...", arg);
        let file = File::open(&arg).expect("fopen");
        let pgn = unsafe { Mmap::map(&file).expect("mmap") };
        pgn.advise_memory_access(AccessPattern::Sequential).expect("madvise");

        let mut indexer = Indexer::new();
        Reader::new(&mut indexer, &pgn[..]).read_all();
        indexer.send(); // send last
    }
}
<|endoftext|>


<commit_before>extern crate secp256k1;
extern crate rand;
extern crate sha3;
extern crate sha2;
extern crate byteorder;
extern crate crypto;
extern crate etcommon_bigint as bigint;
extern crate etcommon_crypto as hash;
extern crate etcommon_rlp as rlp;
extern crate etcommon_util;
extern crate bytes;
#[macro_use]
extern crate futures;
extern crate tokio_io;
extern crate tokio_core;

mod util;
pub mod ecies;
pub mod peer;
mod mac;
mod errors;

pub use peer::{PeerStream, CapabilityInfo};

use bigint::H512;
use util::pk2id;
use hash::SECP256K1;
use secp256k1::key::{PublicKey, SecretKey};
use futures::future;
use futures::{Poll, Async, StartSend, AsyncSink, Future, Stream, Sink};
use std::io;
use std::net::SocketAddr;
use tokio_core::reactor::Handle;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};

pub struct RLPxStream {
    streams: Vec<PeerStream>,
    secret_key: SecretKey,
    protocol_version: usize,
    client_version: String,
    capabilities: Vec<CapabilityInfo>,
    port: usize,
}

impl RLPxStream {
    pub fn new(secret_key: SecretKey, protocol_version: usize,
               client_version: String, capabilities: Vec<CapabilityInfo>,
               port: usize) -> RLPxStream {
        RLPxStream {
            streams: Vec::new(),
            secret_key, protocol_version, client_version,
            capabilities, port
        }
    }

    pub fn add_peer(
        mut self, addr: &SocketAddr, handle: &Handle, remote_id: H512
    ) -> Box<Future<Item = RLPxStream, Error = io::Error>> {
        let fu = PeerStream::connect(addr, handle, self.secret_key.clone(),
                            remote_id, self.protocol_version,
                            self.client_version.clone(),
                            self.capabilities.clone(), self.port)
            .then(move |peer_result| {
                match peer_result {
                    Ok(peer) => {
                        self.streams.push(peer);
                        future::ok(self)
                    },
                    Err(_) => {
                        future::ok(self)
                    },
                }
            });

        Box::new(fu)
    }
}

impl Stream for RLPxStream {
    type Item = (CapabilityInfo, usize, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        'outer: loop {
            let mut full_iter = true;
            let mut start_index = 0;

            'inner: for i in start_index..self.streams.len() {
                match self.streams[i].poll() {
                    Ok(Async::NotReady) => (),
                    Ok(Async::Ready(None)) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    },
                    Ok(Async::Ready(Some(val))) =>
                        return Ok(Async::Ready(Some(val))),
                    Err(e) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    },
                }
            }

            if full_iter {
                break 'outer;
            }
        }
        Ok(Async::NotReady)
    }
}

impl Sink for RLPxStream {
    type SinkItem = (CapabilityInfo, usize, Vec<u8>);
    type SinkError = io::Error;

    fn start_send(&mut self, (cap, id, data): (CapabilityInfo, usize, Vec<u8>)) -> StartSend<Self::SinkItem, Self::SinkError> {
        let mut any_ready = false;

        'outer: loop {
            let mut full_iter = true;
            let mut start_index = 0;

            'inner: for i in 0..self.streams.len() {
                match self.streams[i].start_send((cap.clone(), id, data.clone())) {
                    Ok(AsyncSink::Ready) => {
                        any_ready = true;
                    },
                    Ok(AsyncSink::NotReady(_)) => (),
                    Err(e) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    }
                }
            }

            if full_iter {
                break 'outer;
            }
        }

        if any_ready {
            Ok(AsyncSink::Ready)
        } else {
            Ok(AsyncSink::NotReady((cap, id, data)))
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        let mut all_ready = true;

        'outer: loop {
            let mut full_iter = true;
            let mut start_index = 0;

            'inner: for i in 0..self.streams.len() {
                match self.streams[i].poll_complete() {
                    Ok(Async::Ready(())) => (),
                    Ok(Async::NotReady) => {
                        all_ready = false;
                    },
                    Err(e) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    }
                }
            }

            if full_iter {
                break 'outer;
            }
        }

        if all_ready {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>rlpx: make peer mod private<commit_after>extern crate secp256k1;
extern crate rand;
extern crate sha3;
extern crate sha2;
extern crate byteorder;
extern crate crypto;
extern crate etcommon_bigint as bigint;
extern crate etcommon_crypto as hash;
extern crate etcommon_rlp as rlp;
extern crate etcommon_util;
extern crate bytes;
#[macro_use]
extern crate futures;
extern crate tokio_io;
extern crate tokio_core;

mod util;
pub mod ecies;
mod peer;
mod mac;
mod errors;

pub use peer::{PeerStream, CapabilityInfo};

use bigint::H512;
use util::pk2id;
use hash::SECP256K1;
use secp256k1::key::{PublicKey, SecretKey};
use futures::future;
use futures::{Poll, Async, StartSend, AsyncSink, Future, Stream, Sink};
use std::io;
use std::net::SocketAddr;
use tokio_core::reactor::Handle;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};

pub struct RLPxStream {
    streams: Vec<PeerStream>,
    secret_key: SecretKey,
    protocol_version: usize,
    client_version: String,
    capabilities: Vec<CapabilityInfo>,
    port: usize,
}

impl RLPxStream {
    pub fn new(secret_key: SecretKey, protocol_version: usize,
               client_version: String, capabilities: Vec<CapabilityInfo>,
               port: usize) -> RLPxStream {
        RLPxStream {
            streams: Vec::new(),
            secret_key, protocol_version, client_version,
            capabilities, port
        }
    }

    pub fn add_peer(
        mut self, addr: &SocketAddr, handle: &Handle, remote_id: H512
    ) -> Box<Future<Item = RLPxStream, Error = io::Error>> {
        let fu = PeerStream::connect(addr, handle, self.secret_key.clone(),
                            remote_id, self.protocol_version,
                            self.client_version.clone(),
                            self.capabilities.clone(), self.port)
            .then(move |peer_result| {
                match peer_result {
                    Ok(peer) => {
                        self.streams.push(peer);
                        future::ok(self)
                    },
                    Err(_) => {
                        future::ok(self)
                    },
                }
            });

        Box::new(fu)
    }
}

impl Stream for RLPxStream {
    type Item = (CapabilityInfo, usize, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        'outer: loop {
            let mut full_iter = true;
            let mut start_index = 0;

            'inner: for i in start_index..self.streams.len() {
                match self.streams[i].poll() {
                    Ok(Async::NotReady) => (),
                    Ok(Async::Ready(None)) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    },
                    Ok(Async::Ready(Some(val))) =>
                        return Ok(Async::Ready(Some(val))),
                    Err(e) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    },
                }
            }

            if full_iter {
                break 'outer;
            }
        }
        Ok(Async::NotReady)
    }
}

impl Sink for RLPxStream {
    type SinkItem = (CapabilityInfo, usize, Vec<u8>);
    type SinkError = io::Error;

    fn start_send(&mut self, (cap, id, data): (CapabilityInfo, usize, Vec<u8>)) -> StartSend<Self::SinkItem, Self::SinkError> {
        let mut any_ready = false;

        'outer: loop {
            let mut full_iter = true;
            let mut start_index = 0;

            'inner: for i in 0..self.streams.len() {
                match self.streams[i].start_send((cap.clone(), id, data.clone())) {
                    Ok(AsyncSink::Ready) => {
                        any_ready = true;
                    },
                    Ok(AsyncSink::NotReady(_)) => (),
                    Err(e) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    }
                }
            }

            if full_iter {
                break 'outer;
            }
        }

        if any_ready {
            Ok(AsyncSink::Ready)
        } else {
            Ok(AsyncSink::NotReady((cap, id, data)))
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        let mut all_ready = true;

        'outer: loop {
            let mut full_iter = true;
            let mut start_index = 0;

            'inner: for i in 0..self.streams.len() {
                match self.streams[i].poll_complete() {
                    Ok(Async::Ready(())) => (),
                    Ok(Async::NotReady) => {
                        all_ready = false;
                    },
                    Err(e) => {
                        self.streams.swap_remove(i);
                        full_iter = false;
                        start_index = i;
                        break 'inner;
                    }
                }
            }

            if full_iter {
                break 'outer;
            }
        }

        if all_ready {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


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

use std::prelude::*;
use std::rand;
use std::rand::Rng;
use test::Bencher;

pub fn insert_rand_n<M>(n: uint, map: &mut M, b: &mut Bencher,
                        insert: |&mut M, uint|,
                        remove: |&mut M, uint|) {
    // setup
    let mut rng = rand::weak_rng();

    for _ in range(0, n) {
        insert(map, rng.gen::<uint>() % n);
    }

    // measure
    b.iter(|| {
        let k = rng.gen::<uint>() % n;
        insert(map, k);
        remove(map, k);
    })
}

pub fn insert_seq_n<M>(n: uint, map: &mut M, b: &mut Bencher,
                       insert: |&mut M, uint|,
                       remove: |&mut M, uint|) {
    // setup
    for i in range(0u, n) {
        insert(map, i * 2);
    }

    // measure
    let mut i = 1;
    b.iter(|| {
        insert(map, i);
        remove(map, i);
        i = (i + 2) % n;
    })
}

pub fn find_rand_n<M, T>(n: uint, map: &mut M, b: &mut Bencher,
                         insert: |&mut M, uint|,
                         find: |&M, uint| -> T) {
    // setup
    let mut rng = rand::weak_rng();
    let mut keys = Vec::from_fn(n, |_| rng.gen::<uint>() % n);

    for k in keys.iter() {
        insert(map, *k);
    }

    rng.shuffle(keys.as_mut_slice());

    // measure
    let mut i = 0;
    b.iter(|| {
        let t = find(map, keys[i]);
        i = (i + 1) % n;
        t
    })
}

pub fn find_seq_n<M, T>(n: uint, map: &mut M, b: &mut Bencher,
                        insert: |&mut M, uint|,
                        find: |&M, uint| -> T) {
    // setup
    for i in range(0u, n) {
        insert(map, i);
    }

    // measure
    let mut i = 0;
    b.iter(|| {
        let x = find(map, i);
        i = (i + 1) % n;
        x
    })
}
<commit_msg>libcollections: use unboxed closures<commit_after>// Copyright 2013-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.

use std::prelude::*;
use std::rand;
use std::rand::Rng;
use test::Bencher;

pub fn insert_rand_n<M, I, R>(n: uint,
                              map: &mut M,
                              b: &mut Bencher,
                              mut insert: I,
                              mut remove: R) where
    I: FnMut(&mut M, uint),
    R: FnMut(&mut M, uint),
{
    // setup
    let mut rng = rand::weak_rng();

    for _ in range(0, n) {
        insert(map, rng.gen::<uint>() % n);
    }

    // measure
    b.iter(|| {
        let k = rng.gen::<uint>() % n;
        insert(map, k);
        remove(map, k);
    })
}

pub fn insert_seq_n<M, I, R>(n: uint,
                             map: &mut M,
                             b: &mut Bencher,
                             mut insert: I,
                             mut remove: R) where
    I: FnMut(&mut M, uint),
    R: FnMut(&mut M, uint),
{
    // setup
    for i in range(0u, n) {
        insert(map, i * 2);
    }

    // measure
    let mut i = 1;
    b.iter(|| {
        insert(map, i);
        remove(map, i);
        i = (i + 2) % n;
    })
}

pub fn find_rand_n<M, T, I, F>(n: uint,
                               map: &mut M,
                               b: &mut Bencher,
                               mut insert: I,
                               mut find: F) where
    I: FnMut(&mut M, uint),
    F: FnMut(&M, uint) -> T,
{
    // setup
    let mut rng = rand::weak_rng();
    let mut keys = Vec::from_fn(n, |_| rng.gen::<uint>() % n);

    for k in keys.iter() {
        insert(map, *k);
    }

    rng.shuffle(keys.as_mut_slice());

    // measure
    let mut i = 0;
    b.iter(|| {
        let t = find(map, keys[i]);
        i = (i + 1) % n;
        t
    })
}

pub fn find_seq_n<M, T, I, F>(n: uint,
                              map: &mut M,
                              b: &mut Bencher,
                              mut insert: I,
                              mut find: F) where
    I: FnMut(&mut M, uint),
    F: FnMut(&M, uint) -> T,
{
    // setup
    for i in range(0u, n) {
        insert(map, i);
    }

    // measure
    let mut i = 0;
    b.iter(|| {
        let x = find(map, i);
        i = (i + 1) % n;
        x
    })
}
<|endoftext|>


<commit_before>use crate::mem;
use crate::slice;

pub fn hashmap_random_keys() -> (u64, u64) {
    let mut v = (0, 0);
    unsafe {
        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8, mem::size_of_val(&v));
        imp::fill_bytes(view);
    }
    v
}

#[cfg(all(
    unix,
    not(target_os = "ios"),
    not(target_os = "openbsd"),
    not(target_os = "freebsd"),
    not(target_os = "netbsd"),
    not(target_os = "fuchsia"),
    not(target_os = "redox")
))]
mod imp {
    use crate::fs::File;
    use crate::io::Read;

    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        unsafe {
            libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK)
        }
    }

    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
        false
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
        use crate::sync::atomic::{AtomicBool, Ordering};
        use crate::sys::os::errno;

        static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
        if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
            return false;
        }

        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else if err == libc::ENOSYS || err == libc::EPERM {
                    // Fall back to reading /dev/urandom if `getrandom` is not
                    // supported on the current kernel.
                    //
                    // Also fall back in case it is disabled by something like
                    // seccomp or inside of virtual machines.
                    GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
                    return false;
                } else if err == libc::EAGAIN {
                    return false;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
        true
    }

    pub fn fill_bytes(v: &mut [u8]) {
        // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN,
        // meaning it would have blocked because the non-blocking pool (urandom)
        // has not initialized in the kernel yet due to a lack of entropy. The
        // fallback we do here is to avoid blocking applications which could
        // depend on this call without ever knowing they do and don't have a
        // work around. The PRNG of /dev/urandom will still be used but over a
        // possibly predictable entropy pool.
        if getrandom_fill_bytes(v) {
            return;
        }

        // getrandom failed because it is permanently or temporarily (because
        // of missing entropy) unavailable. Open /dev/urandom, read from it,
        // and close it again.
        let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
        file.read_exact(v).expect("failed to read /dev/urandom")
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use crate::sys::os::errno;

    pub fn fill_bytes(v: &mut [u8]) {
        // getentropy(2) permits a maximum buffer size of 256 bytes
        for s in v.chunks_mut(256) {
            let ret = unsafe { libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len()) };
            if ret == -1 {
                panic!("unexpected getentropy error: {}", errno());
            }
        }
    }
}

// On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with
// `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded
// from `/dev/random` and which runs on its own thread accessed via GCD.
// This seems needlessly heavyweight for the purposes of generating two u64s
// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
// only used on iOS where direct access to `/dev/urandom` is blocked by the
// sandbox.
#[cfg(target_os = "ios")]
mod imp {
    use crate::io;
    use crate::ptr;
    use libc::{c_int, size_t};

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom, count: size_t, bytes: *mut u8) -> c_int;
    }

    pub fn fill_bytes(v: &mut [u8]) {
        let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, v.len(), v.as_mut_ptr()) };
        if ret == -1 {
            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
mod imp {
    use crate::ptr;

    pub fn fill_bytes(v: &mut [u8]) {
        let mib = [libc::CTL_KERN, libc::KERN_ARND];
        // kern.arandom permits a maximum buffer size of 256 bytes
        for s in v.chunks_mut(256) {
            let mut s_len = s.len();
            let ret = unsafe {
                libc::sysctl(
                    mib.as_ptr(),
                    mib.len() as libc::c_uint,
                    s.as_mut_ptr() as *mut _,
                    &mut s_len,
                    ptr::null(),
                    0,
                )
            };
            if ret == -1 || s_len != s.len() {
                panic!(
                    "kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
                    ret,
                    s.len(),
                    s_len
                );
            }
        }
    }
}

#[cfg(target_os = "fuchsia")]
mod imp {
    #[link(name = "zircon")]
    extern "C" {
        fn zx_cprng_draw(buffer: *mut u8, len: usize);
    }

    pub fn fill_bytes(v: &mut [u8]) {
        unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
    }
}

#[cfg(target_os = "redox")]
mod imp {
    use crate::fs::File;
    use crate::io::Read;

    pub fn fill_bytes(v: &mut [u8]) {
        // Open rand:, read from it, and close it again.
        let mut file = File::open("rand:").expect("failed to open rand:");
        file.read_exact(v).expect("failed to read rand:")
    }
}
<commit_msg>Use getentropy(2) on macos<commit_after>use crate::mem;
use crate::slice;

pub fn hashmap_random_keys() -> (u64, u64) {
    let mut v = (0, 0);
    unsafe {
        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8, mem::size_of_val(&v));
        imp::fill_bytes(view);
    }
    v
}

#[cfg(all(
    unix,
    not(target_os = "macos"),
    not(target_os = "ios"),
    not(target_os = "openbsd"),
    not(target_os = "freebsd"),
    not(target_os = "netbsd"),
    not(target_os = "fuchsia"),
    not(target_os = "redox")
))]
mod imp {
    use crate::fs::File;
    use crate::io::Read;

    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        unsafe {
            libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK)
        }
    }

    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
        false
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
        use crate::sync::atomic::{AtomicBool, Ordering};
        use crate::sys::os::errno;

        static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
        if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
            return false;
        }

        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else if err == libc::ENOSYS || err == libc::EPERM {
                    // Fall back to reading /dev/urandom if `getrandom` is not
                    // supported on the current kernel.
                    //
                    // Also fall back in case it is disabled by something like
                    // seccomp or inside of virtual machines.
                    GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
                    return false;
                } else if err == libc::EAGAIN {
                    return false;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
        true
    }

    pub fn fill_bytes(v: &mut [u8]) {
        // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN,
        // meaning it would have blocked because the non-blocking pool (urandom)
        // has not initialized in the kernel yet due to a lack of entropy. The
        // fallback we do here is to avoid blocking applications which could
        // depend on this call without ever knowing they do and don't have a
        // work around. The PRNG of /dev/urandom will still be used but over a
        // possibly predictable entropy pool.
        if getrandom_fill_bytes(v) {
            return;
        }

        // getrandom failed because it is permanently or temporarily (because
        // of missing entropy) unavailable. Open /dev/urandom, read from it,
        // and close it again.
        let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
        file.read_exact(v).expect("failed to read /dev/urandom")
    }
}

#[cfg(target_os = "macos")]
mod imp {
    use crate::fs::File;
    use crate::io::Read;
    use crate::sys::os::errno;
    use libc::{c_int, c_void, size_t};

    fn getentropy_fill_bytes(v: &mut [u8]) -> bool {
        weak!(fn getentropy(*mut c_void, size_t) -> c_int);

        getentropy
            .get()
            .map(|f| {
                // getentropy(2) permits a maximum buffer size of 256 bytes
                for s in v.chunks_mut(256) {
                    let ret = unsafe { f(s.as_mut_ptr() as *mut c_void, s.len()) };
                    if ret == -1 {
                        panic!("unexpected getentropy error: {}", errno());
                    }
                }
                true
            })
            .unwrap_or(false)
    }

    pub fn fill_bytes(v: &mut [u8]) {
        if getentropy_fill_bytes(v) {
            return;
        }

        // for older macos which doesn't support getentropy
        let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
        file.read_exact(v).expect("failed to read /dev/urandom")
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use crate::sys::os::errno;

    pub fn fill_bytes(v: &mut [u8]) {
        // getentropy(2) permits a maximum buffer size of 256 bytes
        for s in v.chunks_mut(256) {
            let ret = unsafe { libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len()) };
            if ret == -1 {
                panic!("unexpected getentropy error: {}", errno());
            }
        }
    }
}

// On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with
// `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded
// from `/dev/random` and which runs on its own thread accessed via GCD.
// This seems needlessly heavyweight for the purposes of generating two u64s
// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
// only used on iOS where direct access to `/dev/urandom` is blocked by the
// sandbox.
#[cfg(target_os = "ios")]
mod imp {
    use crate::io;
    use crate::ptr;
    use libc::{c_int, size_t};

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom, count: size_t, bytes: *mut u8) -> c_int;
    }

    pub fn fill_bytes(v: &mut [u8]) {
        let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, v.len(), v.as_mut_ptr()) };
        if ret == -1 {
            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
mod imp {
    use crate::ptr;

    pub fn fill_bytes(v: &mut [u8]) {
        let mib = [libc::CTL_KERN, libc::KERN_ARND];
        // kern.arandom permits a maximum buffer size of 256 bytes
        for s in v.chunks_mut(256) {
            let mut s_len = s.len();
            let ret = unsafe {
                libc::sysctl(
                    mib.as_ptr(),
                    mib.len() as libc::c_uint,
                    s.as_mut_ptr() as *mut _,
                    &mut s_len,
                    ptr::null(),
                    0,
                )
            };
            if ret == -1 || s_len != s.len() {
                panic!(
                    "kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
                    ret,
                    s.len(),
                    s_len
                );
            }
        }
    }
}

#[cfg(target_os = "fuchsia")]
mod imp {
    #[link(name = "zircon")]
    extern "C" {
        fn zx_cprng_draw(buffer: *mut u8, len: usize);
    }

    pub fn fill_bytes(v: &mut [u8]) {
        unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
    }
}

#[cfg(target_os = "redox")]
mod imp {
    use crate::fs::File;
    use crate::io::Read;

    pub fn fill_bytes(v: &mut [u8]) {
        // Open rand:, read from it, and close it again.
        let mut file = File::open("rand:").expect("failed to open rand:");
        file.read_exact(v).expect("failed to read rand:")
    }
}
<|endoftext|>


<commit_before>
use super::*;
use crate::type_system::TypeSystem;

/// Reference counted handle to the `ComBox` data.
///
/// Provides a safe way to handle the unsafe `ComBox` values.
pub struct ComRc<T : ComInterface + ?Sized> {
    itf : ComItf<T>
}

impl<T: ComInterface + ?Sized> std::fmt::Debug for ComRc<T> {
    fn fmt( &self, f : &mut std::fmt::Formatter ) -> std::fmt::Result {
        (**self).fmt(f)
    }
}

impl<T: ComInterface + ?Sized> Clone for ComRc<T> {
    fn clone( &self ) -> Self {
        ComRc::from( &self.itf )
    }
}

impl<T: ComInterface + ?Sized> From<&ComItf<T>> for ComRc<T> {
    fn from(source: &ComItf<T>) -> Self {
        ComItf::as_rc(source)
    }
}

impl<T : ComInterface + ?Sized> ComRc<T> {

    /// Attaches a floating ComItf reference and brings it under managed
    /// reference counting.
    ///
    /// Does not increment the reference count.
    pub unsafe fn attach( itf : ComItf<T> ) -> ComRc<T> {
        ComRc { itf }
    }

    /// Attaches a floating ComItf reference and brings it under managed
    /// reference counting.
    ///
    /// Does not increment the reference count.
    pub fn detach( mut rc : ComRc<T> ) -> ComItf<T> {
        unsafe {
            std::mem::replace(&mut rc.itf, ComItf::null_itf())
        }
    }

    /// Creates a `ComItf<T>` from a raw type system COM interface pointer..
    ///
    /// Does not increment the reference count.
    ///
    /// # Safety
    ///
    /// The `ptr` __must__ be a valid COM interface pointer for an interface
    /// of type `T`.
    pub unsafe fn wrap<TS: TypeSystem>(
        ptr : raw::InterfacePtr<TS, T>
    ) -> Option<ComRc<T>> {
        ComItf::maybe_wrap( ptr ).map( |itf| ComRc::attach(itf) )
    }

    // ComRc is a smart pointer and shouldn't introduce methods on 'self'.
    #[allow(clippy::wrong_self_convention)]
    pub fn into_unknown( mut other : ComRc<T> ) -> ComRc<dyn IUnknown> {

        // We'll steal the interface off the current ComRc. This prevents the
        // current ComRc from releasing it so we are free to do attach here.
        unsafe {
            let itf = std::mem::replace( &mut other.itf, ComItf::null_itf() );
            ComRc::attach( ComItf::as_unknown( &itf ) )
        }
    }
}

#[cfg(windows)]
impl<T: ComInterface + ?Sized> ComRc<T>
{
    pub fn create( clsid : GUID ) -> crate::ComResult< ComRc<T> > {

        // Only needed on Windows so have these here.
        use crate::type_system::{TypeSystemName, AutomationTypeSystem};

        // Get the IID.
        //
        // The IID we are getting here is the Automation type system ID.
        // This is the one that plays well with Windows' CoCreateInstance, etc.
        let iid = match T::iid( TypeSystemName::Automation ) {
            Some( iid ) => iid,
            None => return Err( ComError::E_NOINTERFACE ),
        };

        unsafe {

            // Invoke CoCreateInstance and return a result based on the return
            // value.
            let mut out = ::std::ptr::null_mut();
            match CoCreateInstance(
                    clsid,
                    std::ptr::null_mut(),
                    1, // in-proc server.
                    iid,
                    &mut out ) {

                // On success construct the ComRc. We are using Automation type
                // system as that's the IID we used earlier.
                crate::raw::S_OK => {

                    // Wrap the pointer into ComItf. This takes care of null checks.
                    let itf = ComItf::maybe_wrap::<AutomationTypeSystem>(
                                    raw::InterfacePtr::new( out ) )
                            .ok_or_else( || ComError::E_POINTER )?;

                    Ok( ComRc::attach( itf ) )
                },
                e => Err( e.into() ),
            }
        }
    }
}

impl<T : ComInterface + ?Sized > ::std::ops::Deref for ComRc< T > {
    type Target = ComItf< T >;
    fn deref( &self ) -> &Self::Target {
        &self.itf
    }
}

impl<T : ComInterface + ?Sized> Drop for ComRc<T> {
    fn drop( &mut self ) {
        if ! ComItf::is_null( &self.itf ) {
            self.itf.as_ref().release();
        }
    }
}

impl<T: ComInterface + ?Sized> AsRef<ComItf<T>> for ComRc<T> {
    fn as_ref( &self ) -> &ComItf<T> {
        &self.itf
    }
}
<commit_msg>Fix clippy warning<commit_after>
use super::*;
use crate::type_system::TypeSystem;

/// Reference counted handle to the `ComBox` data.
///
/// Provides a safe way to handle the unsafe `ComBox` values.
pub struct ComRc<T : ComInterface + ?Sized> {
    itf : ComItf<T>
}

impl<T: ComInterface + ?Sized> std::fmt::Debug for ComRc<T> {
    fn fmt( &self, f : &mut std::fmt::Formatter ) -> std::fmt::Result {
        (**self).fmt(f)
    }
}

impl<T: ComInterface + ?Sized> Clone for ComRc<T> {
    fn clone( &self ) -> Self {
        ComRc::from( &self.itf )
    }
}

impl<T: ComInterface + ?Sized> From<&ComItf<T>> for ComRc<T> {
    fn from(source: &ComItf<T>) -> Self {
        ComItf::as_rc(source)
    }
}

impl<T : ComInterface + ?Sized> ComRc<T> {

    /// Attaches a floating ComItf reference and brings it under managed
    /// reference counting.
    ///
    /// Does not increment the reference count.
    ///
    /// # Safety
    ///
    /// Given this does not increment the reference count, it must be used
    /// only if the `ComItf` is one that would leave the reference dangling.
    /// If something already owns the `ComItf` and will do `release` on it,
    /// the drop of the returned `ComRc` will result in a double-release.
    pub unsafe fn attach( itf : ComItf<T> ) -> ComRc<T> {
        ComRc { itf }
    }

    /// Attaches a floating ComItf reference and brings it under managed
    /// reference counting.
    ///
    /// Does not increment the reference count.
    pub fn detach( mut rc : ComRc<T> ) -> ComItf<T> {
        unsafe {
            std::mem::replace(&mut rc.itf, ComItf::null_itf())
        }
    }

    /// Creates a `ComItf<T>` from a raw type system COM interface pointer..
    ///
    /// Does not increment the reference count.
    ///
    /// # Safety
    ///
    /// The `ptr` __must__ be a valid COM interface pointer for an interface
    /// of type `T`.
    pub unsafe fn wrap<TS: TypeSystem>(
        ptr : raw::InterfacePtr<TS, T>
    ) -> Option<ComRc<T>> {
        ComItf::maybe_wrap( ptr ).map( |itf| ComRc::attach(itf) )
    }

    // ComRc is a smart pointer and shouldn't introduce methods on 'self'.
    #[allow(clippy::wrong_self_convention)]
    pub fn into_unknown( mut other : ComRc<T> ) -> ComRc<dyn IUnknown> {

        // We'll steal the interface off the current ComRc. This prevents the
        // current ComRc from releasing it so we are free to do attach here.
        unsafe {
            let itf = std::mem::replace( &mut other.itf, ComItf::null_itf() );
            ComRc::attach( ComItf::as_unknown( &itf ) )
        }
    }
}

#[cfg(windows)]
impl<T: ComInterface + ?Sized> ComRc<T>
{
    pub fn create( clsid : GUID ) -> crate::ComResult< ComRc<T> > {

        // Only needed on Windows so have these here.
        use crate::type_system::{TypeSystemName, AutomationTypeSystem};

        // Get the IID.
        //
        // The IID we are getting here is the Automation type system ID.
        // This is the one that plays well with Windows' CoCreateInstance, etc.
        let iid = match T::iid( TypeSystemName::Automation ) {
            Some( iid ) => iid,
            None => return Err( ComError::E_NOINTERFACE ),
        };

        unsafe {

            // Invoke CoCreateInstance and return a result based on the return
            // value.
            let mut out = ::std::ptr::null_mut();
            match CoCreateInstance(
                    clsid,
                    std::ptr::null_mut(),
                    1, // in-proc server.
                    iid,
                    &mut out ) {

                // On success construct the ComRc. We are using Automation type
                // system as that's the IID we used earlier.
                crate::raw::S_OK => {

                    // Wrap the pointer into ComItf. This takes care of null checks.
                    let itf = ComItf::maybe_wrap::<AutomationTypeSystem>(
                                    raw::InterfacePtr::new( out ) )
                            .ok_or_else( || ComError::E_POINTER )?;

                    Ok( ComRc::attach( itf ) )
                },
                e => Err( e.into() ),
            }
        }
    }
}

impl<T : ComInterface + ?Sized > ::std::ops::Deref for ComRc< T > {
    type Target = ComItf< T >;
    fn deref( &self ) -> &Self::Target {
        &self.itf
    }
}

impl<T : ComInterface + ?Sized> Drop for ComRc<T> {
    fn drop( &mut self ) {
        if ! ComItf::is_null( &self.itf ) {
            self.itf.as_ref().release();
        }
    }
}

impl<T: ComInterface + ?Sized> AsRef<ComItf<T>> for ComRc<T> {
    fn as_ref( &self ) -> &ComItf<T> {
        &self.itf
    }
}
<|endoftext|>


<commit_before>/*!
A push button is a rectangle containing an application-defined text label, an icon, or a bitmap
that indicates what the button does when the user selects it.
*/

use winapi::um::winuser::{WS_VISIBLE, WS_DISABLED};
use winapi::um::commctrl::{PBS_MARQUEE, PBS_VERTICAL};
use crate::win32::window_helper as wh;
use crate::win32::base_helper::check_hwnd;
use crate::NwgError;
use super::{ControlHandle, ControlBase};
use std::ops::Range;

const NOT_BOUND: &'static str = "Progress bar is not yet bound to a winapi object";
const BAD_HANDLE: &'static str = "INTERNAL ERROR: Progress bar handle is not HWND!";

bitflags! {
    pub struct ProgressBarFlags: u32 {
        const VISIBLE = WS_VISIBLE;
        const DISABLED = WS_DISABLED;
        const VERTICAL = PBS_VERTICAL;
        const MARQUEE = PBS_MARQUEE;
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum ProgressBarState {
    Normal,
    Error,
    Paused
}

/**
A progress bar is a window that an application can use to indicate the progress of a lengthy operation.

Requires the `progress-bar` feature.

**Builder parameters:**
  * `parent`:         **Required.** The progress bar parent container.
  * `size`:           The progress bar size.
  * `position`:       The progress bar position.
  * `state`:          The initial state of the progress bar.
  * `step`:           The value in which the progress bar value increase when `advance` is used.
  * `pos`:            The initial value of the progress bar.
  * `range`:          The minimum and maximum value in the progress bar.
  * `enabled`:        If the progress bar is enabled.
  * `flags`:          A combination of the ProgressBarFlags values.
  * `marquee`:        Enable of disable the marquee animation (only used with the MARQUEE flags)
  * `marquee_update`: The update interval of the marquee mode

**Control events:**
  * `MousePress(_)`: Generic mouse press events on the progress bar
  * `OnMouseMove`: Generic mouse mouse event
  * `OnMouseWheel`: Generic mouse wheel event

```rust
use native_windows_gui as nwg;
fn build_progress_bar(bar: &mut nwg::ProgressBar, window: &nwg::Window) {
    nwg::ProgressBar::builder()
        .state(nwg::ProgressBarState::Paused)
        .step(10)
        .range(0..100)
        .parent(window)
        .build(bar);
}
```

*/
#[derive(Default, PartialEq, Eq)]
pub struct ProgressBar {
    pub handle: ControlHandle
}

impl ProgressBar {

    pub fn builder() -> ProgressBarBuilder {
        ProgressBarBuilder {
            size: (100, 40),
            position: (0, 0),
            flags: None,
            state: ProgressBarState::Normal,
            step: 1,
            pos: 0,
            range: 0..100,
            marquee_enable: false,
            marquee_update: 0,
            parent: None
        }
    }

    /// Return the current state of the progress bar
    pub fn state(&self) -> ProgressBarState {
        use winapi::um::commctrl::{PBM_GETSTATE, PBST_NORMAL, PBST_ERROR, PBST_PAUSED};

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);

        match wh::send_message(handle, PBM_GETSTATE, 0, 0) as i32 {
            PBST_NORMAL => ProgressBarState::Normal,
            PBST_ERROR => ProgressBarState::Error,
            PBST_PAUSED => ProgressBarState::Paused,
            _ => panic!("Unkown progress bar state")
        }
    }

    /// Set the state of the progress bar
    pub fn set_state(&self, state: ProgressBarState) {
        use winapi::um::commctrl::{PBM_SETSTATE, PBST_NORMAL, PBST_ERROR, PBST_PAUSED};
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);

        let state = match state {
            ProgressBarState::Normal => PBST_NORMAL,
            ProgressBarState::Error => PBST_ERROR,
            ProgressBarState::Paused => PBST_PAUSED
        };

        wh::send_message(handle, PBM_SETSTATE, state as WPARAM, 0);
    }

    /// Increase the bar value by the step value
    pub fn advance(&self) {
        use winapi::um::commctrl::PBM_STEPIT;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_STEPIT, 0, 0);
    }

    /// Increase the bar value by a value
    pub fn advance_delta(&self, v: u32) {
        use winapi::um::commctrl::PBM_DELTAPOS;
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_DELTAPOS, v as WPARAM, 0);
    }

    /// Return the step of the progress bar.
    pub fn step(&self) -> u32 {
        use winapi::um::commctrl::PBM_GETSTEP;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_GETSTEP, 0, 0) as u32
    }

    /// Set the step of the progress bar.
    pub fn set_step(&self, s: u32) {
        use winapi::um::commctrl::PBM_SETSTEP;
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETSTEP, s as WPARAM, 0);
    }

    /// Return the position of the progress bar.
    pub fn pos(&self) -> u32 {
        use winapi::um::commctrl::PBM_GETPOS;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_GETPOS, 0, 0) as u32
    }

    /// Set the position of the progress bar. If the value is outside of range
    /// sets the value to the nearest bound.
    pub fn set_pos(&self, p: u32) {
        use winapi::um::commctrl::PBM_SETPOS;
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETPOS, p as WPARAM, 0);
    }

    /// Get the range of the progress bar
    pub fn range(&self) -> Range<u32> {
        use winapi::um::commctrl::PBM_GETRANGE;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);

        let low = wh::send_message(handle, PBM_GETRANGE, 1, 0) as u32;
        let high = wh::send_message(handle, PBM_GETRANGE, 0, 0) as u32;

        low..high
    }

    /// Set the range of the progress bar
    pub fn set_range(&self, range: Range<u32>) {
        use winapi::um::commctrl::PBM_SETRANGE32;
        use winapi::shared::minwindef::{WPARAM, LPARAM};

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETRANGE32, range.start as WPARAM, range.end as LPARAM);
    }

    /// Set the progress bar marquee mode
    pub fn set_marquee(&self, enable: bool, update_interval: u32) {
        use winapi::shared::minwindef::{LPARAM, WPARAM};
        use winapi::um::commctrl::PBM_SETMARQUEE;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETMARQUEE, enable as WPARAM, update_interval as LPARAM);
    }

    /// Return true if the control currently has the keyboard focus
    pub fn focus(&self) -> bool {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_focus(handle) }
    }

    /// Set the keyboard focus on the button.
    pub fn set_focus(&self) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_focus(handle); }
    }

    /// Return true if the control user can interact with the control, return false otherwise
    pub fn enabled(&self) -> bool {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_enabled(handle) }
    }

    /// Enable or disable the control
    pub fn set_enabled(&self, v: bool) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_enabled(handle, v) }
    }

    /// Return true if the control is visible to the user. Will return true even if the
    /// control is outside of the parent client view (ex: at the position (10000, 10000))
    pub fn visible(&self) -> bool {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_visibility(handle) }
    }

    /// Show or hide the control to the user
    pub fn set_visible(&self, v: bool) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_visibility(handle, v) }
    }

    /// Return the size of the button in the parent window
    pub fn size(&self) -> (u32, u32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_size(handle) }
    }

    /// Set the size of the button in the parent window
    pub fn set_size(&self, x: u32, y: u32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_size(handle, x, y, false) }
    }

    /// Return the position of the button in the parent window
    pub fn position(&self) -> (i32, i32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_position(handle) }
    }

    /// Set the position of the button in the parent window
    pub fn set_position(&self, x: i32, y: i32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_position(handle, x, y) }
    }

    /// Winapi class name used during control creation
    pub fn class_name(&self) -> &'static str {
        "msctls_progress32"
    }

    /// Winapi base flags used during window creation
    pub fn flags(&self) -> u32 {
        ::winapi::um::winuser::WS_VISIBLE
    }

    /// Winapi flags required by the control
    pub fn forced_flags(&self) -> u32 {
        use winapi::um::winuser::{WS_CHILD};

        WS_CHILD
    }

}

impl Drop for ProgressBar {
    fn drop(&mut self) {
        self.handle.destroy();
    }
}

pub struct ProgressBarBuilder {
    size: (i32, i32),
    position: (i32, i32),
    flags: Option<ProgressBarFlags>,
    state: ProgressBarState,
    step: u32,
    pos: u32,
    range: Range<u32>,
    marquee_enable: bool,
    marquee_update: u32,
    parent: Option<ControlHandle>
}

impl ProgressBarBuilder {

    pub fn flags(mut self, flags: ProgressBarFlags) -> ProgressBarBuilder {
        self.flags = Some(flags);
        self
    }

    pub fn size(mut self, size: (i32, i32)) -> ProgressBarBuilder {
        self.size = size;
        self
    }

    pub fn position(mut self, pos: (i32, i32)) -> ProgressBarBuilder {
        self.position = pos;
        self
    }

    pub fn state(mut self, state: ProgressBarState) -> ProgressBarBuilder {
        self.state = state;
        self
    }

    pub fn step(mut self, step: u32) -> ProgressBarBuilder {
        self.step = step;
        self
    }

    pub fn pos(mut self, pos: u32) -> ProgressBarBuilder {
        self.pos = pos;
        self
    }

    pub fn range(mut self, range: Range<u32>) -> ProgressBarBuilder {
        self.range = range;
        self
    }

    pub fn marquee(mut self, enable: bool) -> ProgressBarBuilder {
        self.marquee_enable = enable;
        self
    }

    pub fn marquee_update(mut self, update_interval: u32) -> ProgressBarBuilder {
        self.marquee_update = update_interval;
        self
    }

    pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> ProgressBarBuilder {
        self.parent = Some(p.into());
        self
    }

    pub fn build(self, out: &mut ProgressBar) -> Result<(), NwgError> {
        let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());

        let parent = match self.parent {
            Some(p) => Ok(p),
            None => Err(NwgError::no_parent("Progress Bar"))
        }?;

        out.handle = ControlBase::build_hwnd()
            .class_name(out.class_name())
            .forced_flags(out.forced_flags())
            .flags(flags)
            .size(self.size)
            .position(self.position)
            .parent(Some(parent))
            .build()?;

        out.set_state(self.state);
        out.set_step(self.step);
        out.set_pos(self.pos);
        out.set_range(self.range);
        out.set_marquee(self.marquee_enable, self.marquee_update);

        Ok(())
    }

}
<commit_msg>update progress bar flags at runtime<commit_after>/*!
A push button is a rectangle containing an application-defined text label, an icon, or a bitmap
that indicates what the button does when the user selects it.
*/

use winapi::um::winuser::{WS_VISIBLE, WS_DISABLED};
use winapi::um::commctrl::{PBS_MARQUEE, PBS_VERTICAL};
use crate::win32::window_helper as wh;
use crate::win32::base_helper::check_hwnd;
use crate::NwgError;
use super::{ControlHandle, ControlBase};
use std::ops::Range;

const NOT_BOUND: &'static str = "Progress bar is not yet bound to a winapi object";
const BAD_HANDLE: &'static str = "INTERNAL ERROR: Progress bar handle is not HWND!";

bitflags! {
    pub struct ProgressBarFlags: u32 {
        const VISIBLE = WS_VISIBLE;
        const DISABLED = WS_DISABLED;
        const VERTICAL = PBS_VERTICAL;
        const MARQUEE = PBS_MARQUEE;
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum ProgressBarState {
    Normal,
    Error,
    Paused
}

/**
A progress bar is a window that an application can use to indicate the progress of a lengthy operation.

Requires the `progress-bar` feature.

**Builder parameters:**
  * `parent`:         **Required.** The progress bar parent container.
  * `size`:           The progress bar size.
  * `position`:       The progress bar position.
  * `state`:          The initial state of the progress bar.
  * `step`:           The value in which the progress bar value increase when `advance` is used.
  * `pos`:            The initial value of the progress bar.
  * `range`:          The minimum and maximum value in the progress bar.
  * `enabled`:        If the progress bar is enabled.
  * `flags`:          A combination of the ProgressBarFlags values.
  * `marquee`:        Enable of disable the marquee animation (only used with the MARQUEE flags)
  * `marquee_update`: The update interval of the marquee mode

**Control events:**
  * `MousePress(_)`: Generic mouse press events on the progress bar
  * `OnMouseMove`: Generic mouse mouse event
  * `OnMouseWheel`: Generic mouse wheel event

```rust
use native_windows_gui as nwg;
fn build_progress_bar(bar: &mut nwg::ProgressBar, window: &nwg::Window) {
    nwg::ProgressBar::builder()
        .state(nwg::ProgressBarState::Paused)
        .step(10)
        .range(0..100)
        .parent(window)
        .build(bar);
}
```

*/
#[derive(Default, PartialEq, Eq)]
pub struct ProgressBar {
    pub handle: ControlHandle
}

impl ProgressBar {

    pub fn builder() -> ProgressBarBuilder {
        ProgressBarBuilder {
            size: (100, 40),
            position: (0, 0),
            flags: None,
            state: ProgressBarState::Normal,
            step: 1,
            pos: 0,
            range: 0..100,
            marquee_enable: false,
            marquee_update: 0,
            parent: None
        }
    }

    /// Return the current state of the progress bar
    pub fn state(&self) -> ProgressBarState {
        use winapi::um::commctrl::{PBM_GETSTATE, PBST_NORMAL, PBST_ERROR, PBST_PAUSED};

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);

        match wh::send_message(handle, PBM_GETSTATE, 0, 0) as i32 {
            PBST_NORMAL => ProgressBarState::Normal,
            PBST_ERROR => ProgressBarState::Error,
            PBST_PAUSED => ProgressBarState::Paused,
            _ => panic!("Unkown progress bar state")
        }
    }

    /// Set the state of the progress bar
    pub fn set_state(&self, state: ProgressBarState) {
        use winapi::um::commctrl::{PBM_SETSTATE, PBST_NORMAL, PBST_ERROR, PBST_PAUSED};
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);

        let state = match state {
            ProgressBarState::Normal => PBST_NORMAL,
            ProgressBarState::Error => PBST_ERROR,
            ProgressBarState::Paused => PBST_PAUSED
        };

        wh::send_message(handle, PBM_SETSTATE, state as WPARAM, 0);
    }

    /// Increase the bar value by the step value
    pub fn advance(&self) {
        use winapi::um::commctrl::PBM_STEPIT;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_STEPIT, 0, 0);
    }

    /// Increase the bar value by a value
    pub fn advance_delta(&self, v: u32) {
        use winapi::um::commctrl::PBM_DELTAPOS;
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_DELTAPOS, v as WPARAM, 0);
    }

    /// Return the step of the progress bar.
    pub fn step(&self) -> u32 {
        use winapi::um::commctrl::PBM_GETSTEP;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_GETSTEP, 0, 0) as u32
    }

    /// Set the step of the progress bar.
    pub fn set_step(&self, s: u32) {
        use winapi::um::commctrl::PBM_SETSTEP;
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETSTEP, s as WPARAM, 0);
    }

    /// Return the position of the progress bar.
    pub fn pos(&self) -> u32 {
        use winapi::um::commctrl::PBM_GETPOS;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_GETPOS, 0, 0) as u32
    }

    /// Set the position of the progress bar. If the value is outside of range
    /// sets the value to the nearest bound.
    pub fn set_pos(&self, p: u32) {
        use winapi::um::commctrl::PBM_SETPOS;
        use winapi::shared::minwindef::WPARAM;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETPOS, p as WPARAM, 0);
    }

    /// Get the range of the progress bar
    pub fn range(&self) -> Range<u32> {
        use winapi::um::commctrl::PBM_GETRANGE;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);

        let low = wh::send_message(handle, PBM_GETRANGE, 1, 0) as u32;
        let high = wh::send_message(handle, PBM_GETRANGE, 0, 0) as u32;

        low..high
    }

    /// Set the range of the progress bar
    pub fn set_range(&self, range: Range<u32>) {
        use winapi::um::commctrl::PBM_SETRANGE32;
        use winapi::shared::minwindef::{WPARAM, LPARAM};

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETRANGE32, range.start as WPARAM, range.end as LPARAM);
    }

    /// Set the progress bar marquee mode
    pub fn set_marquee(&self, enable: bool, update_interval: u32) {
        use winapi::shared::minwindef::{LPARAM, WPARAM};
        use winapi::um::commctrl::PBM_SETMARQUEE;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        wh::send_message(handle, PBM_SETMARQUEE, enable as WPARAM, update_interval as LPARAM);
    }

    /// Updates the flags of the progress bar.
    pub fn add_flags(&self, styles: ProgressBarFlags) {
        use winapi::um::winuser::GWL_STYLE;

        let styles = styles.bits() as usize;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        let active_styles = wh::get_style(handle);

        wh::set_window_long(handle, GWL_STYLE, active_styles | styles);
    }

    /// Removes flags from the progress bar.
    pub fn remove_flags(&self, styles: ProgressBarFlags) {
        use winapi::um::winuser::GWL_STYLE;

        let styles = styles.bits() as usize;

        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        let active_styles = wh::get_window_long(handle, GWL_STYLE) as usize;

        wh::set_window_long(handle, GWL_STYLE, active_styles & !styles);
    }

    /// Return true if the control currently has the keyboard focus
    pub fn focus(&self) -> bool {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_focus(handle) }
    }

    /// Set the keyboard focus on the button.
    pub fn set_focus(&self) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_focus(handle); }
    }

    /// Return true if the control user can interact with the control, return false otherwise
    pub fn enabled(&self) -> bool {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_enabled(handle) }
    }

    /// Enable or disable the control
    pub fn set_enabled(&self, v: bool) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_enabled(handle, v) }
    }

    /// Return true if the control is visible to the user. Will return true even if the
    /// control is outside of the parent client view (ex: at the position (10000, 10000))
    pub fn visible(&self) -> bool {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_visibility(handle) }
    }

    /// Show or hide the control to the user
    pub fn set_visible(&self, v: bool) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_visibility(handle, v) }
    }

    /// Return the size of the button in the parent window
    pub fn size(&self) -> (u32, u32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_size(handle) }
    }

    /// Set the size of the button in the parent window
    pub fn set_size(&self, x: u32, y: u32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_size(handle, x, y, false) }
    }

    /// Return the position of the button in the parent window
    pub fn position(&self) -> (i32, i32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::get_window_position(handle) }
    }

    /// Set the position of the button in the parent window
    pub fn set_position(&self, x: i32, y: i32) {
        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
        unsafe { wh::set_window_position(handle, x, y) }
    }

    /// Winapi class name used during control creation
    pub fn class_name(&self) -> &'static str {
        "msctls_progress32"
    }

    /// Winapi base flags used during window creation
    pub fn flags(&self) -> u32 {
        ::winapi::um::winuser::WS_VISIBLE
    }

    /// Winapi flags required by the control
    pub fn forced_flags(&self) -> u32 {
        use winapi::um::winuser::{WS_CHILD};

        WS_CHILD
    }

}

impl Drop for ProgressBar {
    fn drop(&mut self) {
        self.handle.destroy();
    }
}

pub struct ProgressBarBuilder {
    size: (i32, i32),
    position: (i32, i32),
    flags: Option<ProgressBarFlags>,
    state: ProgressBarState,
    step: u32,
    pos: u32,
    range: Range<u32>,
    marquee_enable: bool,
    marquee_update: u32,
    parent: Option<ControlHandle>
}

impl ProgressBarBuilder {

    pub fn flags(mut self, flags: ProgressBarFlags) -> ProgressBarBuilder {
        self.flags = Some(flags);
        self
    }

    pub fn size(mut self, size: (i32, i32)) -> ProgressBarBuilder {
        self.size = size;
        self
    }

    pub fn position(mut self, pos: (i32, i32)) -> ProgressBarBuilder {
        self.position = pos;
        self
    }

    pub fn state(mut self, state: ProgressBarState) -> ProgressBarBuilder {
        self.state = state;
        self
    }

    pub fn step(mut self, step: u32) -> ProgressBarBuilder {
        self.step = step;
        self
    }

    pub fn pos(mut self, pos: u32) -> ProgressBarBuilder {
        self.pos = pos;
        self
    }

    pub fn range(mut self, range: Range<u32>) -> ProgressBarBuilder {
        self.range = range;
        self
    }

    pub fn marquee(mut self, enable: bool) -> ProgressBarBuilder {
        self.marquee_enable = enable;
        self
    }

    pub fn marquee_update(mut self, update_interval: u32) -> ProgressBarBuilder {
        self.marquee_update = update_interval;
        self
    }

    pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> ProgressBarBuilder {
        self.parent = Some(p.into());
        self
    }

    pub fn build(self, out: &mut ProgressBar) -> Result<(), NwgError> {
        let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());

        let parent = match self.parent {
            Some(p) => Ok(p),
            None => Err(NwgError::no_parent("Progress Bar"))
        }?;

        out.handle = ControlBase::build_hwnd()
            .class_name(out.class_name())
            .forced_flags(out.forced_flags())
            .flags(flags)
            .size(self.size)
            .position(self.position)
            .parent(Some(parent))
            .build()?;

        out.set_state(self.state);
        out.set_step(self.step);
        out.set_pos(self.pos);
        out.set_range(self.range);
        out.set_marquee(self.marquee_enable, self.marquee_update);

        Ok(())
    }

}
<|endoftext|>


<commit_before>use std::io::IoResult;
use std::io::fs;
use std::sync::atomics;
use std::{io, os};

use cargo::util::realpath;

static CARGO_INTEGRATION_TEST_DIR : &'static str = "cargo-integration-tests";

local_data_key!(task_id: uint)

static mut NEXT_ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;

pub fn root() -> Path {
    let my_id = *task_id.get().unwrap();
    let path = os::tmpdir().join(CARGO_INTEGRATION_TEST_DIR)
                           .join(format!("test-{}", my_id));
    realpath(&path).unwrap()
}

pub fn home() -> Path {
    root().join("home")
}

pub trait PathExt {
    fn rm_rf(&self) -> IoResult<()>;
    fn mkdir_p(&self) -> IoResult<()>;
}

impl PathExt for Path {
    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) -> IoResult<()> {
        if self.exists() {
            fs::rmdir_recursive(self)
        }
        else {
            Ok(())
        }
    }

    fn mkdir_p(&self) -> IoResult<()> {
        fs::mkdir_recursive(self, io::UserDir)
    }
}

/// Ensure required test directories exist and are empty
pub fn setup() {
    let my_id = unsafe { NEXT_ID.fetch_add(1, atomics::SeqCst) };
    task_id.replace(Some(my_id));
    debug!("path setup; root={}; home={}", root().display(), home().display());
    root().rm_rf().unwrap();
    home().mkdir_p().unwrap();
}
<commit_msg>Fix rm_rf on windows<commit_after>use std::io::IoResult;
use std::io::fs;
use std::sync::atomics;
use std::{io, os};

use cargo::util::realpath;

static CARGO_INTEGRATION_TEST_DIR : &'static str = "cargo-integration-tests";

local_data_key!(task_id: uint)

static mut NEXT_ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;

pub fn root() -> Path {
    let my_id = *task_id.get().unwrap();
    let path = os::tmpdir().join(CARGO_INTEGRATION_TEST_DIR)
                           .join(format!("test-{}", my_id));
    realpath(&path).unwrap()
}

pub fn home() -> Path {
    root().join("home")
}

pub trait PathExt {
    fn rm_rf(&self) -> IoResult<()>;
    fn mkdir_p(&self) -> IoResult<()>;
}

impl PathExt for Path {
    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) -> IoResult<()> {
        if self.exists() {
            // On windows, apparently git checks out the database with objects
            // set to the permission 444, and apparently you can't unlink a file
            // with permissions 444 because you don't have write permissions.
            // Whow knew!
            //
            // If the rmdir fails due to a permission denied error, then go back
            // and change everything to have write permissions, then remove
            // everything.
            match fs::rmdir_recursive(self) {
                Err(io::IoError { kind: io::PermissionDenied, .. }) => {}
                e => return e,
            }
            for path in try!(fs::walk_dir(self)) {
                try!(fs::chmod(&path, io::UserRWX));
            }
            fs::rmdir_recursive(self)
        } else {
            Ok(())
        }
    }

    fn mkdir_p(&self) -> IoResult<()> {
        fs::mkdir_recursive(self, io::UserDir)
    }
}

/// Ensure required test directories exist and are empty
pub fn setup() {
    let my_id = unsafe { NEXT_ID.fetch_add(1, atomics::SeqCst) };
    task_id.replace(Some(my_id));
    debug!("path setup; root={}; home={}", root().display(), home().display());
    root().rm_rf().unwrap();
    home().mkdir_p().unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn 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. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg(all(feature = "extra-traits", feature = "full"))]
#![feature(rustc_private)]

#[macro_use]
extern crate syn;
use syn::token::Group;
use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprLit, Lit};

extern crate proc_macro2;
use proc_macro2::*;

#[macro_use]
mod macros;

mod common;

fn expr<T: Into<Expr>>(t: T) -> Expr {
    t.into()
}

fn lit<T: Into<Literal>>(t: T) -> Expr {
    Expr::Lit(ExprLit {
        attrs: Vec::new(),
        lit: Lit::new(t.into()),
    })
}

#[test]
fn test_grouping() {
    let raw: TokenStream = vec![
        TokenTree::Literal(Literal::i32_suffixed(1)),
        TokenTree::Op(Op::new('+', Spacing::Alone)),
        TokenTree::Group(proc_macro2::Group::new(
            Delimiter::None,
            vec![
                TokenTree::Literal(Literal::i32_suffixed(2)),
                TokenTree::Op(Op::new('+', Spacing::Alone)),
                TokenTree::Literal(Literal::i32_suffixed(3)),
            ].into_iter()
                .collect(),
        )),
        TokenTree::Op(Op::new('*', Spacing::Alone)),
        TokenTree::Literal(Literal::i32_suffixed(4)),
    ].into_iter()
        .collect();

    assert_eq!(raw.to_string(), "1i32 +  2i32 + 3i32  * 4i32");

    assert_eq!(
        common::parse::syn::<Expr>(raw),
        expr(ExprBinary {
            attrs: Vec::new(),
            left: Box::new(lit(Literal::i32_suffixed(1))),
            op: BinOp::Add(<Token![+]>::default()),
            right: Box::new(expr(ExprBinary {
                attrs: Vec::new(),
                left: Box::new(expr(ExprGroup {
                    attrs: Vec::new(),
                    group_token: Group::default(),
                    expr: Box::new(expr(ExprBinary {
                        attrs: Vec::new(),
                        left: Box::new(lit(Literal::i32_suffixed(2))),
                        op: BinOp::Add(<Token![+]>::default()),
                        right: Box::new(lit(Literal::i32_suffixed(3))),
                    })),
                })),
                op: BinOp::Mul(<Token![*]>::default()),
                right: Box::new(lit(Literal::i32_suffixed(4))),
            })),
        })
    );
}

#[test]
fn test_invalid_grouping() {
    let raw: TokenStream = vec![
        TokenTree::Literal(Literal::i32_suffixed(1)),
        TokenTree::Op(Op::new('+', Spacing::Alone)),
        TokenTree::Group(proc_macro2::Group::new(
            Delimiter::None,
            vec![
                TokenTree::Literal(Literal::i32_suffixed(2)),
                TokenTree::Op(Op::new('+', Spacing::Alone)),
            ].into_iter()
                .collect(),
        )),
        TokenTree::Literal(Literal::i32_suffixed(3)),
        TokenTree::Op(Op::new('*', Spacing::Alone)),
        TokenTree::Literal(Literal::i32_suffixed(4)),
    ].into_iter()
        .collect();

    assert_eq!(raw.to_string(), "1i32 +  2i32 +  3i32 * 4i32");

    assert_eq!(
        common::parse::syn::<Expr>(raw),
        expr(ExprBinary {
            attrs: Vec::new(),
            left: Box::new(expr(ExprBinary {
                attrs: Vec::new(),
                left: Box::new(lit(Literal::i32_suffixed(1))),
                op: BinOp::Add(<Token![+]>::default()),
                right: Box::new(lit(Literal::i32_suffixed(2))),
            })),
            op: BinOp::Add(<Token![+]>::default()),
            right: Box::new(expr(ExprBinary {
                attrs: Vec::new(),
                left: Box::new(lit(Literal::i32_suffixed(3))),
                op: BinOp::Mul(<Token![*]>::default()),
                right: Box::new(lit(Literal::i32_suffixed(4))),
            })),
        })
    );
}
<commit_msg>Fix test_grouping<commit_after>// Copyright 2018 Syn 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. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg(all(feature = "extra-traits", feature = "full"))]
#![feature(rustc_private)]

#[macro_use]
extern crate syn;
use syn::token::Group;
use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprLit, Lit};

extern crate proc_macro2;
use proc_macro2::*;

#[macro_use]
mod macros;

mod common;

fn expr<T: Into<Expr>>(t: T) -> Expr {
    t.into()
}

fn lit<T: Into<Literal>>(t: T) -> Expr {
    Expr::Lit(ExprLit {
        attrs: Vec::new(),
        lit: Lit::new(t.into()),
    })
}

#[test]
fn test_grouping() {
    let raw: TokenStream = vec![
        TokenTree::Literal(Literal::i32_suffixed(1)),
        TokenTree::Punct(Punct::new('+', Spacing::Alone)),
        TokenTree::Group(proc_macro2::Group::new(
            Delimiter::None,
            vec![
                TokenTree::Literal(Literal::i32_suffixed(2)),
                TokenTree::Punct(Punct::new('+', Spacing::Alone)),
                TokenTree::Literal(Literal::i32_suffixed(3)),
            ].into_iter()
                .collect(),
        )),
        TokenTree::Punct(Punct::new('*', Spacing::Alone)),
        TokenTree::Literal(Literal::i32_suffixed(4)),
    ].into_iter()
        .collect();

    assert_eq!(raw.to_string(), "1i32 +  2i32 + 3i32  * 4i32");

    assert_eq!(
        common::parse::syn::<Expr>(raw),
        expr(ExprBinary {
            attrs: Vec::new(),
            left: Box::new(lit(Literal::i32_suffixed(1))),
            op: BinOp::Add(<Token![+]>::default()),
            right: Box::new(expr(ExprBinary {
                attrs: Vec::new(),
                left: Box::new(expr(ExprGroup {
                    attrs: Vec::new(),
                    group_token: Group::default(),
                    expr: Box::new(expr(ExprBinary {
                        attrs: Vec::new(),
                        left: Box::new(lit(Literal::i32_suffixed(2))),
                        op: BinOp::Add(<Token![+]>::default()),
                        right: Box::new(lit(Literal::i32_suffixed(3))),
                    })),
                })),
                op: BinOp::Mul(<Token![*]>::default()),
                right: Box::new(lit(Literal::i32_suffixed(4))),
            })),
        })
    );
}

#[test]
fn test_invalid_grouping() {
    let raw: TokenStream = vec![
        TokenTree::Literal(Literal::i32_suffixed(1)),
        TokenTree::Punct(Punct::new('+', Spacing::Alone)),
        TokenTree::Group(proc_macro2::Group::new(
            Delimiter::None,
            vec![
                TokenTree::Literal(Literal::i32_suffixed(2)),
                TokenTree::Punct(Punct::new('+', Spacing::Alone)),
            ].into_iter()
                .collect(),
        )),
        TokenTree::Literal(Literal::i32_suffixed(3)),
        TokenTree::Punct(Punct::new('*', Spacing::Alone)),
        TokenTree::Literal(Literal::i32_suffixed(4)),
    ].into_iter()
        .collect();

    assert_eq!(raw.to_string(), "1i32 +  2i32 +  3i32 * 4i32");

    assert_eq!(
        common::parse::syn::<Expr>(raw),
        expr(ExprBinary {
            attrs: Vec::new(),
            left: Box::new(expr(ExprBinary {
                attrs: Vec::new(),
                left: Box::new(lit(Literal::i32_suffixed(1))),
                op: BinOp::Add(<Token![+]>::default()),
                right: Box::new(lit(Literal::i32_suffixed(2))),
            })),
            op: BinOp::Add(<Token![+]>::default()),
            right: Box::new(expr(ExprBinary {
                attrs: Vec::new(),
                left: Box::new(lit(Literal::i32_suffixed(3))),
                op: BinOp::Mul(<Token![*]>::default()),
                right: Box::new(lit(Literal::i32_suffixed(4))),
            })),
        })
    );
}
<|endoftext|>