<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32`
//! from `next_u64` in little-endian order, one should use `next_u64() as u32`.
//!
//! Byte-swapping (like the std `to_le` functions) is only needed to convert
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.

use crate::RngCore;
use core::cmp::min;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    // Use LE; we explicitly generate one value before the next.
    let x = u64::from(rng.next_u32());
    let y = u64::from(rng.next_u32());
    (y << 32) | x
}

/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order.
///
/// The fastest way to fill a slice is usually to work as long as possible with
/// integers. That is why this method mostly uses `next_u64`, and only when
/// there are 4 or less bytes remaining at the end of the slice it uses
/// `next_u32` once.
pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
    let mut left = dest;
    while left.len() >= 8 {
        let (l, r) = { left }.split_at_mut(8);
        left = r;
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        l.copy_from_slice(&chunk);
    }
    let n = left.len();
    if n > 4 {
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    } else if n > 0 {
        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    }
}

macro_rules! fill_via_chunks {
    ($src:expr, $dst:expr, $ty:ty, $size:expr) => {{
        let chunk_size_u8 = min($src.len() * $size, $dst.len());
        let chunk_size = (chunk_size_u8 + $size - 1) / $size;

        for (&n, chunk) in $src.iter().zip($dst.chunks_mut($size)) {
            chunk.clone_from_slice(&n.to_le_bytes());
        }

        (chunk_size, chunk_size_u8)
    }};
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u32, filled_u8)`.
///
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u32` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 4` rounded up.
///
/// # Example
/// (from `IsaacRng`)
///
/// ```ignore
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
///     let mut read_len = 0;
///     while read_len < dest.len() {
///         if self.index >= self.rsl.len() {
///             self.isaac();
///         }
///
///         let (consumed_u32, filled_u8) =
///             impls::fill_via_u32_chunks(&mut self.rsl[self.index..],
///                                        &mut dest[read_len..]);
///
///         self.index += consumed_u32;
///         read_len += filled_u8;
///     }
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u32, 4)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u64, filled_u8)`.
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u64` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 8` rounded up.
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u64, 8)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
    let mut buf = [0; 4];
    rng.fill_bytes(&mut buf);
    u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    let mut buf = [0; 8];
    rng.fill_bytes(&mut buf);
    u64::from_ne_bytes(buf)
}

// TODO: implement tests for the above
<commit_msg>Fix `fill_via_chunks` and add tests<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32`
//! from `next_u64` in little-endian order, one should use `next_u64() as u32`.
//!
//! Byte-swapping (like the std `to_le` functions) is only needed to convert
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.

use crate::RngCore;
use core::cmp::min;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    // Use LE; we explicitly generate one value before the next.
    let x = u64::from(rng.next_u32());
    let y = u64::from(rng.next_u32());
    (y << 32) | x
}

/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order.
///
/// The fastest way to fill a slice is usually to work as long as possible with
/// integers. That is why this method mostly uses `next_u64`, and only when
/// there are 4 or less bytes remaining at the end of the slice it uses
/// `next_u32` once.
pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
    let mut left = dest;
    while left.len() >= 8 {
        let (l, r) = { left }.split_at_mut(8);
        left = r;
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        l.copy_from_slice(&chunk);
    }
    let n = left.len();
    if n > 4 {
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    } else if n > 0 {
        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    }
}

macro_rules! fill_via_chunks {
    ($src:expr, $dst:expr, $ty:ty, $size:expr) => {{
        debug_assert_eq!(core::mem::size_of::<$ty>(), $size);
        let chunk_size_u8 = min($src.len() * $size, $dst.len());
        let chunk_size = (chunk_size_u8 + $size - 1) / $size;

        for (&n, chunk) in $src.iter().zip($dst.chunks_mut($size)) {
            chunk.copy_from_slice(&n.to_le_bytes()[..chunk.len()]);
        }

        (chunk_size, chunk_size_u8)
    }};
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u32, filled_u8)`.
///
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u32` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 4` rounded up.
///
/// # Example
/// (from `IsaacRng`)
///
/// ```ignore
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
///     let mut read_len = 0;
///     while read_len < dest.len() {
///         if self.index >= self.rsl.len() {
///             self.isaac();
///         }
///
///         let (consumed_u32, filled_u8) =
///             impls::fill_via_u32_chunks(&mut self.rsl[self.index..],
///                                        &mut dest[read_len..]);
///
///         self.index += consumed_u32;
///         read_len += filled_u8;
///     }
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u32, 4)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u64, filled_u8)`.
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u64` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 8` rounded up.
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u64, 8)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
    let mut buf = [0; 4];
    rng.fill_bytes(&mut buf);
    u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    let mut buf = [0; 8];
    rng.fill_bytes(&mut buf);
    u64::from_ne_bytes(buf)
}

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

    #[test]
    fn test_fill_via_u32_chunks() {
        let src = [1, 2, 3];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);

        let mut dst = [0u8; 13];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
        assert_eq!(dst, [1, 0, 0, 0, 2]);
    }

    #[test]
    fn test_fill_via_u64_chunks() {
        let src = [1, 2];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);

        let mut dst = [0u8; 17];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
        assert_eq!(dst, [1, 0, 0, 0, 0]);
    }
}
<|endoftext|>


<commit_before>extern crate pgn_reader;
extern crate memmap;
extern crate madvise;
extern crate reqwest;

use std::env;
use std::fs::File;

use memmap::Mmap;
use madvise::{AccessPattern, AdviseMemory};
use pgn_reader::{Visitor, Skip, Reader};

struct Indexer;

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

    fn end_headers(&mut self) -> Skip {
        Skip(true)
    }

    fn end_game(&mut self, game: &'pgn [u8]) {
        let res = reqwest::blocking::Client::new()
            .put("http://localhost:9000/import/master")
            .body(game.to_owned())
            .send().expect("send game");

        let answer = res.text().expect("decode response");
        println!("-> {}", answer);
    }
}

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

        Reader::new(&mut Indexer, &pgn[..]).read_all();
    }
}
<commit_msg>explicitly specify charset of put request body<commit_after>extern crate pgn_reader;
extern crate memmap;
extern crate madvise;
extern crate reqwest;

use std::env;
use std::fs::File;

use memmap::Mmap;
use madvise::{AccessPattern, AdviseMemory};
use pgn_reader::{Visitor, Skip, Reader};

struct Indexer;

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

    fn end_headers(&mut self) -> Skip {
        Skip(true)
    }

    fn end_game(&mut self, game: &'pgn [u8]) {

        let res = reqwest::blocking::Client::new()
            .put("http://localhost:9000/import/master")
            .header("Content-Type", "application/vnd.chess-pgn;charset=utf-8")
            .body(game.to_owned())
            .send().expect("send game");

        let answer = res.text().expect("decode response");
        println!("-> {}", answer);
    }
}

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

        Reader::new(&mut Indexer, &pgn[..]).read_all();
    }
}
<|endoftext|>


<commit_before>use libc::{c_double, c_int};

extern {
    pub fn erf(x: c_double) -> c_double;
    pub fn erfc(x: c_double) -> c_double;
    pub fn lgamma_r(x: c_double, sign: &mut c_int) -> c_double;
}
<commit_msg>Compare libm’s erf with MATLAB’s one<commit_after>use libc::{c_double, c_int};

extern {
    pub fn erf(x: c_double) -> c_double;
    pub fn erfc(x: c_double) -> c_double;
    pub fn lgamma_r(x: c_double, sign: &mut c_int) -> c_double;
}

#[cfg(test)]
mod tests {
    use assert;

    #[test]
    fn erf() {
        let x = vec![
            -2.632984211817266e+00, -2.363273199619327e+00, -2.094834420999714e+00,
            -1.827652978390535e+00, -1.561714251393564e+00, -1.297003889738660e+00,
            -1.033507806468575e+00, -7.712121713408920e-01, -5.101034044390804e-01,
            -2.501681699844875e-01,  8.606629658243489e-03,  2.662338597896692e-01,
             5.227261590049689e-01,  7.780959446508342e-01,  1.032355418116290e+00,
             1.285516569963673e+00,  1.537591184905182e+00,  1.788590846631104e+00,
             2.038526942494747e+00,  2.287410668059257e+00,
        ];
        let y = vec![
            4.231914082376952e-03, 9.057155208654155e-03, 1.809285705645609e-02,
            3.380082467503698e-02, 5.917765997943183e-02, 9.731492422005782e-02,
            1.506831595865132e-01, 2.202905905012284e-01, 3.049895101174467e-01,
            4.012286497130861e-01, 5.034335060734141e-01, 6.049704463017676e-01,
            6.994175842035349e-01, 7.817437733581876e-01, 8.490471756668190e-01,
            9.006940849004457e-01, 9.379256979186316e-01, 9.631596334645754e-01,
            9.792513684346750e-01, 9.889140679020433e-01,
        ];

        let z = x.iter().map(|&x| gaussian(x)).collect::<Vec<_>>();
        assert::close(&z, &y, 1e-14);
    }

    fn gaussian(x: f64) -> f64 {
        use std::f64::consts::FRAC_1_SQRT_2;
        0.5 * (1.0 + unsafe { super::erf(FRAC_1_SQRT_2 * x) })
    }
}
<|endoftext|>


<commit_before>use crate::error::{ParseError, ParseErrorKind::*};
use std::fmt;
use std::iter;
use std::str::{self, FromStr};

/// A cfg expression.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum CfgExpr {
    Not(Box<CfgExpr>),
    All(Vec<CfgExpr>),
    Any(Vec<CfgExpr>),
    Value(Cfg),
}

/// A cfg value.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum Cfg {
    /// A named cfg value, like `unix`.
    Name(String),
    /// A key/value cfg pair, like `target_os = "linux"`.
    KeyPair(String, String),
}

#[derive(PartialEq)]
enum Token<'a> {
    LeftParen,
    RightParen,
    Ident(&'a str),
    Comma,
    Equals,
    String(&'a str),
}

#[derive(Clone)]
struct Tokenizer<'a> {
    s: iter::Peekable<str::CharIndices<'a>>,
    orig: &'a str,
}

struct Parser<'a> {
    t: Tokenizer<'a>,
}

impl FromStr for Cfg {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Cfg, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.cfg()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for Cfg {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Cfg::Name(ref s) => s.fmt(f),
            Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v),
        }
    }
}

impl CfgExpr {
    /// Utility function to check if the key, "cfg(..)" matches the `target_cfg`
    pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool {
        if key.starts_with("cfg(") && key.ends_with(')') {
            let cfg = &key[4..key.len() - 1];

            CfgExpr::from_str(cfg)
                .ok()
                .map(|ce| ce.matches(target_cfg))
                .unwrap_or(false)
        } else {
            false
        }
    }

    pub fn matches(&self, cfg: &[Cfg]) -> bool {
        match *self {
            CfgExpr::Not(ref e) => !e.matches(cfg),
            CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),
            CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),
            CfgExpr::Value(ref e) => cfg.contains(e),
        }
    }
}

impl FromStr for CfgExpr {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<CfgExpr, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.expr()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for CfgExpr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            CfgExpr::Not(ref e) => write!(f, "not({})", e),
            CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)),
            CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)),
            CfgExpr::Value(ref e) => write!(f, "{}", e),
        }
    }
}

struct CommaSep<'a, T>(&'a [T]);

impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for (i, v) in self.0.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }
            write!(f, "{}", v)?;
        }
        Ok(())
    }
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            t: Tokenizer {
                s: s.char_indices().peekable(),
                orig: s,
            },
        }
    }

    fn expr(&mut self) -> Result<CfgExpr, ParseError> {
        match self.peek() {
            Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => {
                self.t.next();
                let mut e = Vec::new();
                self.eat(&Token::LeftParen)?;
                while !self.r#try(&Token::RightParen) {
                    e.push(self.expr()?);
                    if !self.r#try(&Token::Comma) {
                        self.eat(&Token::RightParen)?;
                        break;
                    }
                }
                if op == "all" {
                    Ok(CfgExpr::All(e))
                } else {
                    Ok(CfgExpr::Any(e))
                }
            }
            Some(Ok(Token::Ident("not"))) => {
                self.t.next();
                self.eat(&Token::LeftParen)?;
                let e = self.expr()?;
                self.eat(&Token::RightParen)?;
                Ok(CfgExpr::Not(Box::new(e)))
            }
            Some(Ok(..)) => self.cfg().map(CfgExpr::Value),
            Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr("start of a cfg expression"),
            )),
        }
    }

    fn cfg(&mut self) -> Result<Cfg, ParseError> {
        match self.t.next() {
            Some(Ok(Token::Ident(name))) => {
                let e = if self.r#try(&Token::Equals) {
                    let val = match self.t.next() {
                        Some(Ok(Token::String(s))) => s,
                        Some(Ok(t)) => {
                            return Err(ParseError::new(
                                self.t.orig,
                                UnexpectedToken {
                                    expected: "a string",
                                    found: t.classify(),
                                },
                            ))
                        }
                        Some(Err(e)) => return Err(e),
                        None => {
                            return Err(ParseError::new(self.t.orig, IncompleteExpr("a string")))
                        }
                    };
                    Cfg::KeyPair(name.to_string(), val.to_string())
                } else {
                    Cfg::Name(name.to_string())
                };
                Ok(e)
            }
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: "identifier",
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))),
        }
    }

    fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        self.t.clone().next()
    }

    fn r#try(&mut self, token: &Token<'a>) -> bool {
        match self.peek() {
            Some(Ok(ref t)) if token == t => {}
            _ => return false,
        }
        self.t.next();
        true
    }

    fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> {
        match self.t.next() {
            Some(Ok(ref t)) if token == t => Ok(()),
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: token.classify(),
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr(token.classify()),
            )),
        }
    }

    /// Returns the rest of the input from the current location.
    fn rest(&self) -> Option<&str> {
        let mut s = self.t.s.clone();
        loop {
            match s.next() {
                Some((_, ' ')) => {}
                Some((start, _ch)) => return Some(&self.t.orig[start..]),
                None => return None,
            }
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Result<Token<'a>, ParseError>;

    fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        loop {
            match self.s.next() {
                Some((_, ' ')) => {}
                Some((_, '(')) => return Some(Ok(Token::LeftParen)),
                Some((_, ')')) => return Some(Ok(Token::RightParen)),
                Some((_, ',')) => return Some(Ok(Token::Comma)),
                Some((_, '=')) => return Some(Ok(Token::Equals)),
                Some((start, '"')) => {
                    while let Some((end, ch)) = self.s.next() {
                        if ch == '"' {
                            return Some(Ok(Token::String(&self.orig[start + 1..end])));
                        }
                    }
                    return Some(Err(ParseError::new(self.orig, UnterminatedString)));
                }
                Some((start, ch)) if is_ident_start(ch) => {
                    while let Some(&(end, ch)) = self.s.peek() {
                        if !is_ident_rest(ch) {
                            return Some(Ok(Token::Ident(&self.orig[start..end])));
                        } else {
                            self.s.next();
                        }
                    }
                    return Some(Ok(Token::Ident(&self.orig[start..])));
                }
                Some((_, ch)) => {
                    return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch))));
                }
                None => return None,
            }
        }
    }
}

fn is_ident_start(ch: char) -> bool {
    ch == '_' || ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')
}

fn is_ident_rest(ch: char) -> bool {
    is_ident_start(ch) || ('0' <= ch && ch <= '9')
}

impl<'a> Token<'a> {
    fn classify(&self) -> &'static str {
        match *self {
            Token::LeftParen => "`(`",
            Token::RightParen => "`)`",
            Token::Ident(..) => "an identifier",
            Token::Comma => "`,`",
            Token::Equals => "`=`",
            Token::String(..) => "a string",
        }
    }
}
<commit_msg>trivial char range check<commit_after>use crate::error::{ParseError, ParseErrorKind::*};
use std::fmt;
use std::iter;
use std::str::{self, FromStr};

/// A cfg expression.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum CfgExpr {
    Not(Box<CfgExpr>),
    All(Vec<CfgExpr>),
    Any(Vec<CfgExpr>),
    Value(Cfg),
}

/// A cfg value.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum Cfg {
    /// A named cfg value, like `unix`.
    Name(String),
    /// A key/value cfg pair, like `target_os = "linux"`.
    KeyPair(String, String),
}

#[derive(PartialEq)]
enum Token<'a> {
    LeftParen,
    RightParen,
    Ident(&'a str),
    Comma,
    Equals,
    String(&'a str),
}

#[derive(Clone)]
struct Tokenizer<'a> {
    s: iter::Peekable<str::CharIndices<'a>>,
    orig: &'a str,
}

struct Parser<'a> {
    t: Tokenizer<'a>,
}

impl FromStr for Cfg {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Cfg, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.cfg()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for Cfg {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Cfg::Name(ref s) => s.fmt(f),
            Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v),
        }
    }
}

impl CfgExpr {
    /// Utility function to check if the key, "cfg(..)" matches the `target_cfg`
    pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool {
        if key.starts_with("cfg(") && key.ends_with(')') {
            let cfg = &key[4..key.len() - 1];

            CfgExpr::from_str(cfg)
                .ok()
                .map(|ce| ce.matches(target_cfg))
                .unwrap_or(false)
        } else {
            false
        }
    }

    pub fn matches(&self, cfg: &[Cfg]) -> bool {
        match *self {
            CfgExpr::Not(ref e) => !e.matches(cfg),
            CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),
            CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),
            CfgExpr::Value(ref e) => cfg.contains(e),
        }
    }
}

impl FromStr for CfgExpr {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<CfgExpr, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.expr()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for CfgExpr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            CfgExpr::Not(ref e) => write!(f, "not({})", e),
            CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)),
            CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)),
            CfgExpr::Value(ref e) => write!(f, "{}", e),
        }
    }
}

struct CommaSep<'a, T>(&'a [T]);

impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for (i, v) in self.0.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }
            write!(f, "{}", v)?;
        }
        Ok(())
    }
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            t: Tokenizer {
                s: s.char_indices().peekable(),
                orig: s,
            },
        }
    }

    fn expr(&mut self) -> Result<CfgExpr, ParseError> {
        match self.peek() {
            Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => {
                self.t.next();
                let mut e = Vec::new();
                self.eat(&Token::LeftParen)?;
                while !self.r#try(&Token::RightParen) {
                    e.push(self.expr()?);
                    if !self.r#try(&Token::Comma) {
                        self.eat(&Token::RightParen)?;
                        break;
                    }
                }
                if op == "all" {
                    Ok(CfgExpr::All(e))
                } else {
                    Ok(CfgExpr::Any(e))
                }
            }
            Some(Ok(Token::Ident("not"))) => {
                self.t.next();
                self.eat(&Token::LeftParen)?;
                let e = self.expr()?;
                self.eat(&Token::RightParen)?;
                Ok(CfgExpr::Not(Box::new(e)))
            }
            Some(Ok(..)) => self.cfg().map(CfgExpr::Value),
            Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr("start of a cfg expression"),
            )),
        }
    }

    fn cfg(&mut self) -> Result<Cfg, ParseError> {
        match self.t.next() {
            Some(Ok(Token::Ident(name))) => {
                let e = if self.r#try(&Token::Equals) {
                    let val = match self.t.next() {
                        Some(Ok(Token::String(s))) => s,
                        Some(Ok(t)) => {
                            return Err(ParseError::new(
                                self.t.orig,
                                UnexpectedToken {
                                    expected: "a string",
                                    found: t.classify(),
                                },
                            ))
                        }
                        Some(Err(e)) => return Err(e),
                        None => {
                            return Err(ParseError::new(self.t.orig, IncompleteExpr("a string")))
                        }
                    };
                    Cfg::KeyPair(name.to_string(), val.to_string())
                } else {
                    Cfg::Name(name.to_string())
                };
                Ok(e)
            }
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: "identifier",
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))),
        }
    }

    fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        self.t.clone().next()
    }

    fn r#try(&mut self, token: &Token<'a>) -> bool {
        match self.peek() {
            Some(Ok(ref t)) if token == t => {}
            _ => return false,
        }
        self.t.next();
        true
    }

    fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> {
        match self.t.next() {
            Some(Ok(ref t)) if token == t => Ok(()),
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: token.classify(),
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr(token.classify()),
            )),
        }
    }

    /// Returns the rest of the input from the current location.
    fn rest(&self) -> Option<&str> {
        let mut s = self.t.s.clone();
        loop {
            match s.next() {
                Some((_, ' ')) => {}
                Some((start, _ch)) => return Some(&self.t.orig[start..]),
                None => return None,
            }
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Result<Token<'a>, ParseError>;

    fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        loop {
            match self.s.next() {
                Some((_, ' ')) => {}
                Some((_, '(')) => return Some(Ok(Token::LeftParen)),
                Some((_, ')')) => return Some(Ok(Token::RightParen)),
                Some((_, ',')) => return Some(Ok(Token::Comma)),
                Some((_, '=')) => return Some(Ok(Token::Equals)),
                Some((start, '"')) => {
                    while let Some((end, ch)) = self.s.next() {
                        if ch == '"' {
                            return Some(Ok(Token::String(&self.orig[start + 1..end])));
                        }
                    }
                    return Some(Err(ParseError::new(self.orig, UnterminatedString)));
                }
                Some((start, ch)) if is_ident_start(ch) => {
                    while let Some(&(end, ch)) = self.s.peek() {
                        if !is_ident_rest(ch) {
                            return Some(Ok(Token::Ident(&self.orig[start..end])));
                        } else {
                            self.s.next();
                        }
                    }
                    return Some(Ok(Token::Ident(&self.orig[start..])));
                }
                Some((_, ch)) => {
                    return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch))));
                }
                None => return None,
            }
        }
    }
}

fn is_ident_start(ch: char) -> bool {
    ch == '_' || ch.is_ascii_alphabetic()
}

fn is_ident_rest(ch: char) -> bool {
    is_ident_start(ch) || ch.is_ascii_digit()
}

impl<'a> Token<'a> {
    fn classify(&self) -> &'static str {
        match *self {
            Token::LeftParen => "`(`",
            Token::RightParen => "`)`",
            Token::Ident(..) => "an identifier",
            Token::Comma => "`,`",
            Token::Equals => "`=`",
            Token::String(..) => "a string",
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
#[cfg(not(feature = "http"))]
use std::fs::File;
use std::path::{Path, PathBuf};

#[cfg(feature = "http")]
use bytes::buf::Buf;
#[cfg(feature = "http")]
use reqwest::Client;
#[cfg(feature = "http")]
use tokio::{fs::File, io::AsyncReadExt};
use url::Url;

#[cfg(feature = "http")]
use crate::error::{Error, Result};

/// Enum that allows a user to pass a [`Path`] or a [`File`] type to [`send_files`]
///
/// [`send_files`]: crate::model::id::ChannelId::send_files
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum AttachmentType<'a> {
    /// Indicates that the [`AttachmentType`] is a byte slice with a filename.
    Bytes { data: Cow<'a, [u8]>, filename: String },
    /// Indicates that the [`AttachmentType`] is a [`File`]
    File { file: &'a File, filename: String },
    /// Indicates that the [`AttachmentType`] is a [`Path`]
    Path(&'a Path),
    /// Indicates that the [`AttachmentType`] is an image URL.
    Image(Url),
}

#[cfg(feature = "http")]
impl<'a> AttachmentType<'a> {
    pub(crate) async fn data(&self, client: &Client) -> Result<Vec<u8>> {
        let data = match self {
            AttachmentType::Bytes {
                data, ..
            } => data.clone().into_owned(),
            AttachmentType::File {
                file, ..
            } => {
                let mut buf = Vec::new();
                file.try_clone().await?.read_to_end(&mut buf).await?;
                buf
            },
            AttachmentType::Path(path) => {
                let mut file = File::open(path).await?;
                let mut buf = Vec::new();
                file.read_to_end(&mut buf).await?;
                buf
            },
            AttachmentType::Image(url) => {
                let response = client.get(url.clone()).send().await?;
                let mut bytes = response.bytes().await?;
                let mut picture: Vec<u8> = Vec::with_capacity(bytes.len());
                bytes.copy_to_slice(&mut picture);
                picture
            },
        };
        Ok(data)
    }

    pub(crate) fn filename(&self) -> Result<Option<String>> {
        match self {
            AttachmentType::Bytes {
                filename, ..
            }
            | AttachmentType::File {
                filename, ..
            } => Ok(Some(filename.to_string())),
            AttachmentType::Path(path) => {
                Ok(path.file_name().map(|filename| filename.to_string_lossy().to_string()))
            },
            AttachmentType::Image(url) => {
                match url.path_segments().and_then(|segments| segments.last()) {
                    Some(filename) => Ok(Some(filename.to_string())),
                    None => Err(Error::Url(url.to_string())),
                }
            },
        }
    }
}

impl<'a> From<(&'a [u8], &str)> for AttachmentType<'a> {
    fn from(params: (&'a [u8], &str)) -> AttachmentType<'a> {
        AttachmentType::Bytes {
            data: Cow::Borrowed(params.0),
            filename: params.1.to_string(),
        }
    }
}

impl<'a> From<&'a str> for AttachmentType<'a> {
    /// Constructs an [`AttachmentType`] from a string.
    /// This string may refer to the path of a file on disk, or the http url to an image on the internet.
    fn from(s: &'a str) -> AttachmentType<'_> {
        match Url::parse(s) {
            Ok(url) => AttachmentType::Image(url),
            Err(_) => AttachmentType::Path(Path::new(s)),
        }
    }
}

impl<'a> From<&'a Path> for AttachmentType<'a> {
    fn from(path: &'a Path) -> AttachmentType<'_> {
        AttachmentType::Path(path)
    }
}

impl<'a> From<&'a PathBuf> for AttachmentType<'a> {
    fn from(pathbuf: &'a PathBuf) -> AttachmentType<'_> {
        AttachmentType::Path(pathbuf.as_path())
    }
}

impl<'a> From<(&'a File, &str)> for AttachmentType<'a> {
    fn from(f: (&'a File, &str)) -> AttachmentType<'a> {
        AttachmentType::File {
            file: f.0,
            filename: f.1.to_string(),
        }
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;

    use super::AttachmentType;

    #[test]
    fn test_attachment_type() {
        assert!(matches!(
            AttachmentType::from(Path::new("./dogs/corgis/kona.png")),
            AttachmentType::Path(_)
        ));
        assert!(matches!(
            AttachmentType::from(Path::new("./cats/copycat.png")),
            AttachmentType::Path(_)
        ));
        assert!(matches!(
            AttachmentType::from("./mascots/crabs/ferris.png"),
            AttachmentType::Path(_)
        ));
        assert!(matches!(
            AttachmentType::from("https://test.url/test.jpg"),
            AttachmentType::Image(_)
        ))
    }
}
<commit_msg>Fix broken resolving logic for `AttachmentType::Image` (#1718)<commit_after>use std::borrow::Cow;
#[cfg(not(feature = "http"))]
use std::fs::File;
use std::path::{Path, PathBuf};

#[cfg(feature = "http")]
use reqwest::Client;
#[cfg(feature = "http")]
use tokio::{fs::File, io::AsyncReadExt};
use url::Url;

#[cfg(feature = "http")]
use crate::error::{Error, Result};

/// Enum that allows a user to pass a [`Path`] or a [`File`] type to [`send_files`]
///
/// [`send_files`]: crate::model::id::ChannelId::send_files
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum AttachmentType<'a> {
    /// Indicates that the [`AttachmentType`] is a byte slice with a filename.
    Bytes { data: Cow<'a, [u8]>, filename: String },
    /// Indicates that the [`AttachmentType`] is a [`File`]
    File { file: &'a File, filename: String },
    /// Indicates that the [`AttachmentType`] is a [`Path`]
    Path(&'a Path),
    /// Indicates that the [`AttachmentType`] is an image URL.
    Image(Url),
}

#[cfg(feature = "http")]
impl<'a> AttachmentType<'a> {
    pub(crate) async fn data(&self, client: &Client) -> Result<Vec<u8>> {
        let data = match self {
            AttachmentType::Bytes {
                data, ..
            } => data.clone().into_owned(),
            AttachmentType::File {
                file, ..
            } => {
                let mut buf = Vec::new();
                file.try_clone().await?.read_to_end(&mut buf).await?;
                buf
            },
            AttachmentType::Path(path) => {
                let mut file = File::open(path).await?;
                let mut buf = Vec::new();
                file.read_to_end(&mut buf).await?;
                buf
            },
            AttachmentType::Image(url) => {
                let response = client.get(url.clone()).send().await?;
                response.bytes().await?.to_vec()
            },
        };
        Ok(data)
    }

    pub(crate) fn filename(&self) -> Result<Option<String>> {
        match self {
            AttachmentType::Bytes {
                filename, ..
            }
            | AttachmentType::File {
                filename, ..
            } => Ok(Some(filename.to_string())),
            AttachmentType::Path(path) => {
                Ok(path.file_name().map(|filename| filename.to_string_lossy().to_string()))
            },
            AttachmentType::Image(url) => {
                match url.path_segments().and_then(|segments| segments.last()) {
                    Some(filename) => Ok(Some(filename.to_string())),
                    None => Err(Error::Url(url.to_string())),
                }
            },
        }
    }
}

impl<'a> From<(&'a [u8], &str)> for AttachmentType<'a> {
    fn from(params: (&'a [u8], &str)) -> AttachmentType<'a> {
        AttachmentType::Bytes {
            data: Cow::Borrowed(params.0),
            filename: params.1.to_string(),
        }
    }
}

impl<'a> From<&'a str> for AttachmentType<'a> {
    /// Constructs an [`AttachmentType`] from a string.
    /// This string may refer to the path of a file on disk, or the http url to an image on the internet.
    fn from(s: &'a str) -> AttachmentType<'_> {
        match Url::parse(s) {
            Ok(url) => AttachmentType::Image(url),
            Err(_) => AttachmentType::Path(Path::new(s)),
        }
    }
}

impl<'a> From<&'a Path> for AttachmentType<'a> {
    fn from(path: &'a Path) -> AttachmentType<'_> {
        AttachmentType::Path(path)
    }
}

impl<'a> From<&'a PathBuf> for AttachmentType<'a> {
    fn from(pathbuf: &'a PathBuf) -> AttachmentType<'_> {
        AttachmentType::Path(pathbuf.as_path())
    }
}

impl<'a> From<(&'a File, &str)> for AttachmentType<'a> {
    fn from(f: (&'a File, &str)) -> AttachmentType<'a> {
        AttachmentType::File {
            file: f.0,
            filename: f.1.to_string(),
        }
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;

    use super::AttachmentType;

    #[test]
    fn test_attachment_type() {
        assert!(matches!(
            AttachmentType::from(Path::new("./dogs/corgis/kona.png")),
            AttachmentType::Path(_)
        ));
        assert!(matches!(
            AttachmentType::from(Path::new("./cats/copycat.png")),
            AttachmentType::Path(_)
        ));
        assert!(matches!(
            AttachmentType::from("./mascots/crabs/ferris.png"),
            AttachmentType::Path(_)
        ));
        assert!(matches!(
            AttachmentType::from("https://test.url/test.jpg"),
            AttachmentType::Image(_)
        ))
    }
}
<|endoftext|>


<commit_before>use std::io;

enum Operator {
	Add,
	Subtract,
	Push,
	Pop,
	None,
}

fn parse(s: &str) -> Operator {
	match s {
		"+" => Operator::Add,
		"-" => Operator::Subtract,
		"pop" => Operator::Pop,
		_ => Operator::None,
	}
}

fn process(s: String) {
	for o in s.split(" "){
		let b = parse(o.trim());
		println!("{}",match b {
			Operator::Add => "addition!",
			Operator::Subtract => "subtraction!",
			Operator::Pop => "popped!",
			_ => "other!",
		});
	}
}

fn main() {

	let mut x = io::stdin();

	loop{
		let mut y: String = "".to_string();
		let _ = x.read_line(&mut y);

	    process(y);
	}
}
<commit_msg>operators, setting up vm struct (broken)<commit_after>use std::io;
use std::str::FromStr;

struct VM {
	stack: Vec<Operator>,
}

impl VM {
	fn pop(&self, ret: &mut Operator) {
		let mut transfer = move |op: Operator| op;
		ret = transfer(self.stack.pop().expect("gg reinstall"));
	}

	fn push(&self, op: Operator) {
		self.stack.push(op);
	}
}

enum Operator {
	//stack
	Dup,
	Drop,
	Swap,
	Over,
	Rot,

	//debug
	Print,

	//math
	Add,
	Subtract,
	Multiply,
	Divide,
	Mod,
	And,
	Or,
	Xor,
	Lshift,
	Rshift,
	Abs,
	Max,
	Min,
	Invert,
	Negate,

	//custom
	Define,

	//values and custom calls
	Value(i32),
	Other,
}

fn parse(s: &str) -> Operator {
	match s {
		//stack operations:
		"dup" => Operator::Dup,
		"drop" => Operator::Drop,
		"swap" => Operator::Swap,
		"over" => Operator::Over,
		"rot" => Operator::Rot,

		//debug operations:
		"." => Operator::Print,

		//math operations:
		"+" => Operator::Add,
		"-" => Operator::Subtract,
		"*" => Operator::Multiply,
		"/" => Operator::Divide,
		"mod" => Operator::Mod,
		"and" => Operator::And,
		"or" => Operator::Or,
		"xor" => Operator::Xor,
		"lshift" => Operator::Lshift,
		"<<" => Operator::Lshift,
		"rshift" => Operator::Rshift,
		">>" => Operator::Rshift,
		"abs" => Operator::Abs,
		"max" => Operator::Max,
		"min" => Operator::Min,
		"invert" => Operator::Invert,
		"negate" => Operator::Negate,

		//custom definitions
		":" => Operator::Define,

		//value or custom operator
		x => {
			let y: Option<i32> = FromStr::from_str(x).ok();
			match y{
				Some(i) => Operator::Value(i),
				None => Operator::Other,
			}
		},
	}
}

fn process(s: String) {
	for o in s.split(" "){
		let b = parse(o.trim());
		println!("{}",match b {
			Operator::Add => "addition!",
			Operator::Subtract => "subtraction!",
			Operator::Value(_) => "value!",
			_ => "other!",
		});
	}
}

fn main() {

	let mut x = io::stdin();
	let vm = VM {stack: vec![Operator::Print]};

	loop{
		let mut y: String = "".to_string();
		let _ = x.read_line(&mut y);

	    process(y);
	}
}
<|endoftext|>


<commit_before>extern crate puzrs;
extern crate rand;
extern crate getopts;

use getopts::Options;
use getopts::Matches;
use std::env;

use puzrs::*;
use std::io;
use std::time::Instant;
use rand::Rng;

use std::thread;
use std::sync::Mutex;
use std::io::Write;

macro_rules! run_timed {
    ($timer: ident, $flag: ident, $e: expr) => {
        if $flag {
            let start = Instant::now();
            let ret = $e;
            let end = start.elapsed();
            let cost_time = end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64;

            let mut timer_lock = $timer.lock().unwrap();
            *timer_lock += cost_time;

            ret
        } else {
            $e
        }
    };
}
fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    no_adjacent_clues: bool,
    symmetry_clue: bool,
    minimum_path_length: i32,
    empty_width: i32,
    max_clue: Option<i32>,
    corner: Option<(i32, i32)>,
    use_profiler: bool,
    prioritized_extension: bool,
}

fn run_generator(opts: GeneratorOption) {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = std::sync::Arc::new(Mutex::new(0i64));

    // profiling
    let use_profiler = opts.use_profiler;
    let cost_genenerator = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_pretest = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_exact_test = std::sync::Arc::new(Mutex::new(0.0f64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();
        let cost_genenerator = cost_genenerator.clone();
        let cost_pretest = cost_pretest.clone();
        let cost_exact_test = cost_exact_test.clone();

        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();

            let mut generator = numberlink::PlacementGenerator::new(height, width);

            let mut rng = rand::thread_rng();
            loop {
                let mut end = Grid::new(height, width, numberlink::Endpoint::Any);

                let trans = move |x: i32, y: i32, d: i32| {
                    let mut x = x;
                    let mut y = y;
                    if d == 1 || d == 3 {
                        x = width - 1 - x;
                    }
                    if d == 2 || d == 3 {
                        y = height - 1 - y;
                    }
                    (Y(y), X(x))
                };
                let fr = opts.empty_width;
                for y in 0..height {
                    for x in 0..width {
                        if y < fr || y >= height - fr || x < fr || x >= width - fr {
                            end[(Y(y), X(x))] = numberlink::Endpoint::Prohibited;
                        }
                    }
                }
                if let Some((lo, hi)) = opts.corner {
                    if opts.symmetry_clue {
                        for d in 0..2 {
                            let i = rng.gen_range(lo, hi + 1);
                            let (d0, d1) = if d == 0 { (0, 3) } else { (1, 2) };

                            end[trans(i, i, d0)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d0)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d0)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d0)] = numberlink::Endpoint::Prohibited;
                            }
                            end[trans(i, i, d1)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d1)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d1)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d1)] = numberlink::Endpoint::Prohibited;
                            }
                        }
                    } else {
                        for d in 0..4 {
                            let i = rng.gen_range(lo, hi + 1);
                            end[trans(i, i, d)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d)] = numberlink::Endpoint::Prohibited;
                            }
                        }
                    }
                }
                let opt = numberlink::GeneratorOption {
                    chain_threshold: opts.minimum_path_length,
                    endpoint_constraint: Some(&end),
                    forbid_adjacent_clue: opts.no_adjacent_clues,
                    symmetry_clue: opts.symmetry_clue,
                    clue_limit: opts.max_clue,
                };

                let placement = run_timed!(cost_genenerator, use_profiler, generator.generate(&opt, &mut rng));
                if let Some(placement) = placement {
                    // pretest
                    let pretest_res = run_timed!(cost_pretest, use_profiler, numberlink::uniqueness_pretest(&placement));
                    if !pretest_res { continue; }

                    let problem = numberlink::extract_problem(&placement, &mut rng);

                    let ans = run_timed!(cost_exact_test, use_profiler, numberlink::solve2(&problem, Some(2), false, true));

                    if ans.len() == 1 && !ans.found_not_fully_filled {
                        let stdin = io::stdout();
                        let handle = &mut stdin.lock();

                        let end = start.elapsed();
                        let cost_time = (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                        let mut cnt = gen_probs.lock().unwrap();
                        *cnt += 1;
                        eprintln!("{} problem(s) in {:.3}[min] ({:.3} [prob/min])", *cnt, cost_time, (*cnt) as f64 / cost_time);
                        if use_profiler {
                            let cost_genenerator = *(cost_genenerator.lock().unwrap());
                            let cost_pretest = *(cost_pretest.lock().unwrap());
                            let cost_exact_test = *(cost_exact_test.lock().unwrap());
                            let cost_total = cost_genenerator + cost_pretest + cost_exact_test;

                            eprintln!("Generator: {:.3}[s] ({:.2}%) / Pretest: {:.3}[s] ({:.2}%) / Exact test: {:.3}[s] ({:.2}%)",
                                cost_genenerator, cost_genenerator / cost_total * 100.0f64,
                                cost_pretest, cost_pretest / cost_total * 100.0f64,
                                cost_exact_test, cost_exact_test / cost_total * 100.0f64);
                        }

                        writeln!(handle, "{} {}", height, width).unwrap();
                        for y in 0..height {
                            for x in 0..width {
                                let numberlink::Clue(c) = problem[(Y(y), X(x))];
                                if c >= 1 {
                                    write!(handle, "{}{}", c, if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                } else {
                                    write!(handle, ".{}", if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                }
                            }
                        }
                        writeln!(handle).unwrap();
                    }
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
}

fn parse_options(matches: Matches) -> Result<GeneratorOption, &'static str> {
    let height = try!(
        matches.opt_str("h")
            .ok_or("'height' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'height'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'height' must be a positive integer") }));
    let width = try!(
        matches.opt_str("w")
            .ok_or("'width' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'width'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'width' must be a positive integer") }));
    let jobs = try!(
        matches.opt_str("j").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'jobs'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'jobs' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let no_adjacent_clues = matches.opt_present("no-adjacent-clues");
    let symmetry_clue = matches.opt_present("symmetry");
    let minimum_path_length = try!(
        matches.opt_str("minimum-path-length").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'minimum-path-length'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'minimum-path-length' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let empty_width = try!(
        matches.opt_str("empty-width").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'empty-width'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'empty-width' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let max_clue = try!(
        matches.opt_str("max-clue").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'max-clue'")
                .and_then(|arg| if arg > 0 { Ok(Some(arg)) } else { Err("'max-clue' must be a positive integer") })
        ).unwrap_or(Ok(None)));
    let use_profiler = matches.opt_present("use-profiler");
    let prioritized_extension = matches.opt_present("prioritized-extension");
    let corner = match matches.opt_str("corner") {
        Some(s) => {
            let split = s.split(",").collect::<Vec<&str>>();
            if split.len() != 2 {
                return Err("Could not parse value for 'corner'");
            }
            let lo = try!(split[0].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            let hi = try!(split[1].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            if !(1 <= lo && lo <= hi) {
                return Err("'corner' must be a valid range on positive integers");
            }
            Some((lo, hi))
        },
        None => None,
    };
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        no_adjacent_clues,
        symmetry_clue,
        minimum_path_length,
        empty_width,
        max_clue,
        corner,
        use_profiler,
        prioritized_extension,
    })
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("a", "no-adjacent-clues", "Disallow adjacent clues");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optopt("m", "minimum-path-length", "Minimum length of paths in the answer", "12");
    options.optopt("e", "empty-width", "Disallow clues on n cell(s) from the outer border", "1");
    options.optopt("c", "corner", "Put one clue within specified range from each corner", "1,3");
    options.optopt("x", "max-clue", "Maximum value of clues", "10");
    options.optflag("p", "use-profiler", "Enable profiler");
    options.optflag("r", "prioritized-extension", "Use prioritized extension in generator");

    let matches = match options.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };

    if matches.opt_present("help") {
        print_usage(&program, options);
        return;
    }

    let opt = match parse_options(matches) {
        Ok(opt) => opt,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };
    run_generator(opt);
}
<commit_msg>Numberlink: fix nl_generator<commit_after>extern crate puzrs;
extern crate rand;
extern crate getopts;

use getopts::Options;
use getopts::Matches;
use std::env;

use puzrs::*;
use std::io;
use std::time::Instant;
use rand::Rng;

use std::thread;
use std::sync::Mutex;
use std::io::Write;

macro_rules! run_timed {
    ($timer: ident, $flag: ident, $e: expr) => {
        if $flag {
            let start = Instant::now();
            let ret = $e;
            let end = start.elapsed();
            let cost_time = end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64;

            let mut timer_lock = $timer.lock().unwrap();
            *timer_lock += cost_time;

            ret
        } else {
            $e
        }
    };
}
fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    no_adjacent_clues: bool,
    symmetry_clue: bool,
    minimum_path_length: i32,
    empty_width: i32,
    max_clue: Option<i32>,
    corner: Option<(i32, i32)>,
    use_profiler: bool,
    prioritized_extension: bool,
}

fn run_generator(opts: GeneratorOption) {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = std::sync::Arc::new(Mutex::new(0i64));

    // profiling
    let use_profiler = opts.use_profiler;
    let cost_genenerator = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_pretest = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_exact_test = std::sync::Arc::new(Mutex::new(0.0f64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();
        let cost_genenerator = cost_genenerator.clone();
        let cost_pretest = cost_pretest.clone();
        let cost_exact_test = cost_exact_test.clone();

        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();

            let mut generator = numberlink::PlacementGenerator::new(height, width);

            let mut rng = rand::thread_rng();
            loop {
                let mut end = Grid::new(height, width, numberlink::Endpoint::Any);

                let trans = move |x: i32, y: i32, d: i32| {
                    let mut x = x;
                    let mut y = y;
                    if d == 1 || d == 3 {
                        x = width - 1 - x;
                    }
                    if d == 2 || d == 3 {
                        y = height - 1 - y;
                    }
                    (Y(y), X(x))
                };
                let fr = opts.empty_width;
                for y in 0..height {
                    for x in 0..width {
                        if y < fr || y >= height - fr || x < fr || x >= width - fr {
                            end[(Y(y), X(x))] = numberlink::Endpoint::Prohibited;
                        }
                    }
                }
                if let Some((lo, hi)) = opts.corner {
                    if opts.symmetry_clue {
                        for d in 0..2 {
                            let i = rng.gen_range(lo, hi + 1);
                            let (d0, d1) = if d == 0 { (0, 3) } else { (1, 2) };

                            end[trans(i, i, d0)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d0)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d0)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d0)] = numberlink::Endpoint::Prohibited;
                            }
                            end[trans(i, i, d1)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d1)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d1)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d1)] = numberlink::Endpoint::Prohibited;
                            }
                        }
                    } else {
                        for d in 0..4 {
                            let i = rng.gen_range(lo, hi + 1);
                            end[trans(i, i, d)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d)] = numberlink::Endpoint::Prohibited;
                            }
                        }
                    }
                }
                let opt = numberlink::GeneratorOption {
                    chain_threshold: opts.minimum_path_length,
                    endpoint_constraint: Some(&end),
                    forbid_adjacent_clue: opts.no_adjacent_clues,
                    symmetry_clue: opts.symmetry_clue,
                    clue_limit: opts.max_clue,
                    prioritized_extension: opts.prioritized_extension,
                };

                let placement = run_timed!(cost_genenerator, use_profiler, generator.generate(&opt, &mut rng));
                if let Some(placement) = placement {
                    // pretest
                    let pretest_res = run_timed!(cost_pretest, use_profiler, numberlink::uniqueness_pretest(&placement));
                    if !pretest_res { continue; }

                    let problem = numberlink::extract_problem(&placement, &mut rng);

                    let ans = run_timed!(cost_exact_test, use_profiler, numberlink::solve2(&problem, Some(2), false, true));

                    if ans.len() == 1 && !ans.found_not_fully_filled {
                        let stdin = io::stdout();
                        let handle = &mut stdin.lock();

                        let end = start.elapsed();
                        let cost_time = (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                        let mut cnt = gen_probs.lock().unwrap();
                        *cnt += 1;
                        eprintln!("{} problem(s) in {:.3}[min] ({:.3} [prob/min])", *cnt, cost_time, (*cnt) as f64 / cost_time);
                        if use_profiler {
                            let cost_genenerator = *(cost_genenerator.lock().unwrap());
                            let cost_pretest = *(cost_pretest.lock().unwrap());
                            let cost_exact_test = *(cost_exact_test.lock().unwrap());
                            let cost_total = cost_genenerator + cost_pretest + cost_exact_test;

                            eprintln!("Generator: {:.3}[s] ({:.2}%) / Pretest: {:.3}[s] ({:.2}%) / Exact test: {:.3}[s] ({:.2}%)",
                                cost_genenerator, cost_genenerator / cost_total * 100.0f64,
                                cost_pretest, cost_pretest / cost_total * 100.0f64,
                                cost_exact_test, cost_exact_test / cost_total * 100.0f64);
                        }

                        writeln!(handle, "{} {}", height, width).unwrap();
                        for y in 0..height {
                            for x in 0..width {
                                let numberlink::Clue(c) = problem[(Y(y), X(x))];
                                if c >= 1 {
                                    write!(handle, "{}{}", c, if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                } else {
                                    write!(handle, ".{}", if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                }
                            }
                        }
                        writeln!(handle).unwrap();
                    }
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
}

fn parse_options(matches: Matches) -> Result<GeneratorOption, &'static str> {
    let height = try!(
        matches.opt_str("h")
            .ok_or("'height' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'height'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'height' must be a positive integer") }));
    let width = try!(
        matches.opt_str("w")
            .ok_or("'width' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'width'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'width' must be a positive integer") }));
    let jobs = try!(
        matches.opt_str("j").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'jobs'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'jobs' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let no_adjacent_clues = matches.opt_present("no-adjacent-clues");
    let symmetry_clue = matches.opt_present("symmetry");
    let minimum_path_length = try!(
        matches.opt_str("minimum-path-length").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'minimum-path-length'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'minimum-path-length' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let empty_width = try!(
        matches.opt_str("empty-width").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'empty-width'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'empty-width' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let max_clue = try!(
        matches.opt_str("max-clue").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'max-clue'")
                .and_then(|arg| if arg > 0 { Ok(Some(arg)) } else { Err("'max-clue' must be a positive integer") })
        ).unwrap_or(Ok(None)));
    let use_profiler = matches.opt_present("use-profiler");
    let prioritized_extension = matches.opt_present("prioritized-extension");
    let corner = match matches.opt_str("corner") {
        Some(s) => {
            let split = s.split(",").collect::<Vec<&str>>();
            if split.len() != 2 {
                return Err("Could not parse value for 'corner'");
            }
            let lo = try!(split[0].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            let hi = try!(split[1].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            if !(1 <= lo && lo <= hi) {
                return Err("'corner' must be a valid range on positive integers");
            }
            Some((lo, hi))
        },
        None => None,
    };
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        no_adjacent_clues,
        symmetry_clue,
        minimum_path_length,
        empty_width,
        max_clue,
        corner,
        use_profiler,
        prioritized_extension,
    })
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("a", "no-adjacent-clues", "Disallow adjacent clues");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optopt("m", "minimum-path-length", "Minimum length of paths in the answer", "12");
    options.optopt("e", "empty-width", "Disallow clues on n cell(s) from the outer border", "1");
    options.optopt("c", "corner", "Put one clue within specified range from each corner", "1,3");
    options.optopt("x", "max-clue", "Maximum value of clues", "10");
    options.optflag("p", "use-profiler", "Enable profiler");
    options.optflag("r", "prioritized-extension", "Use prioritized extension in generator");

    let matches = match options.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };

    if matches.opt_present("help") {
        print_usage(&program, options);
        return;
    }

    let opt = match parse_options(matches) {
        Ok(opt) => opt,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };
    run_generator(opt);
}
<|endoftext|>


<commit_before>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
       trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
       unused_qualifications)]

extern crate docopt;
extern crate pad;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

use std::error::Error;
use std::io::{self, Write};
use std::process::{self, Command};

extern crate cargo_edit;
use cargo_edit::{get_latest_dependency, Manifest};

static USAGE: &'static str = r"
Upgrade all dependencies in a manifest file to the latest version.

Usage:
    cargo upgrade [--all] [--dependency <dep>...] [--manifest-path <path>]
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                       Upgrade all packages in the workspace.
    -d --dependency <dep>       Specific dependency to upgrade. If this option is used, only the
                                specified dependencies will be upgraded.
    --manifest-path <path>      Path to the manifest to upgrade.
    --allow-prerelease          Include prerelease versions when fetching from crates.io (e.g.
                                '0.6.0-alpha'). Defaults to false.
    -h --help                   Show this help page.
    -V --version                Show version.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `--dependency -d <dep>`
    flag_dependency: Vec<String>,
    /// `--manifest-path <path>`
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
}

fn is_version_dependency(dep: &toml::Value) -> bool {
    if let Some(table) = dep.as_table() {
        !table.contains_key("git") && !table.contains_key("path")
    } else {
        true
    }
}

fn update_manifest(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<(), Box<Error>> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path).unwrap();

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = get_latest_dependency(name, allow_prerelease)?;

                manifest.update_table_entry(&table_path, &latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest.write_to_file(&mut file)
}

/// Get a list of the paths of all the (non-virtual) manifests in the workspace.
fn get_workspace_manifests(manifest_path: &Option<String>) -> Result<Vec<String>, Box<Error>> {
    let mut metadata_gatherer = Command::new("cargo");
    metadata_gatherer.args(&["metadata", "--no-deps", "--format-version", "1", "-q"]);

    if let Some(ref manifest_path) = *manifest_path {
        metadata_gatherer.args(&["--manifest-path", manifest_path]);
    }

    let output = metadata_gatherer.output()?;

    if output.status.success() {
        let metadata: serde_json::Value =
            serde_json::from_str(&String::from_utf8_lossy(&output.stdout))?;

        let workspace_members = metadata["packages"]
            .as_array()
            .ok_or("No packages in workspace")?;

        workspace_members
            .iter()
            .map(|package| {
                package["manifest_path"]
                    .as_str()
                    .map(Into::into)
                    .ok_or_else(|| "Invalid manifest path".into())
            })
            .collect()
    } else {
        Err(
            format!(
                "Failed to get metadata: {}",
                String::from_utf8_lossy(&output.stderr)
            ).into(),
        )
    }
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    let output = if args.flag_all {
        get_workspace_manifests(&args.flag_manifest_path).and_then(|manifests| {
            for manifest in manifests {
                update_manifest(&Some(manifest), &args.flag_dependency, args.flag_allow_prerelease)?
            }

            Ok(())
        })
    } else {
        update_manifest(&args.flag_manifest_path, &args.flag_dependency, args.flag_allow_prerelease)
    };

    if let Err(err) = output {
        writeln!(
            io::stderr(),
            "Command failed due to unhandled error: {}\n",
            err
        ).unwrap();
        process::exit(1);
    }
}
<commit_msg>Fix upgrade command docopt USAGE string.<commit_after>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
       trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
       unused_qualifications)]

extern crate docopt;
extern crate pad;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

use std::error::Error;
use std::io::{self, Write};
use std::process::{self, Command};

extern crate cargo_edit;
use cargo_edit::{get_latest_dependency, Manifest};

static USAGE: &'static str = r"
Upgrade all dependencies in a manifest file to the latest version.

Usage:
    cargo upgrade [--all] [--dependency <dep>...] [--manifest-path <path>] [options]
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                       Upgrade all packages in the workspace.
    -d --dependency <dep>       Specific dependency to upgrade. If this option is used, only the
                                specified dependencies will be upgraded.
    --manifest-path <path>      Path to the manifest to upgrade.
    --allow-prerelease          Include prerelease versions when fetching from crates.io (e.g.
                                '0.6.0-alpha'). Defaults to false.
    -h --help                   Show this help page.
    -V --version                Show version.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `--dependency -d <dep>`
    flag_dependency: Vec<String>,
    /// `--manifest-path <path>`
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
}

fn is_version_dependency(dep: &toml::Value) -> bool {
    if let Some(table) = dep.as_table() {
        !table.contains_key("git") && !table.contains_key("path")
    } else {
        true
    }
}

fn update_manifest(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<(), Box<Error>> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path).unwrap();

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = get_latest_dependency(name, allow_prerelease)?;

                manifest.update_table_entry(&table_path, &latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest.write_to_file(&mut file)
}

/// Get a list of the paths of all the (non-virtual) manifests in the workspace.
fn get_workspace_manifests(manifest_path: &Option<String>) -> Result<Vec<String>, Box<Error>> {
    let mut metadata_gatherer = Command::new("cargo");
    metadata_gatherer.args(&["metadata", "--no-deps", "--format-version", "1", "-q"]);

    if let Some(ref manifest_path) = *manifest_path {
        metadata_gatherer.args(&["--manifest-path", manifest_path]);
    }

    let output = metadata_gatherer.output()?;

    if output.status.success() {
        let metadata: serde_json::Value =
            serde_json::from_str(&String::from_utf8_lossy(&output.stdout))?;

        let workspace_members = metadata["packages"]
            .as_array()
            .ok_or("No packages in workspace")?;

        workspace_members
            .iter()
            .map(|package| {
                package["manifest_path"]
                    .as_str()
                    .map(Into::into)
                    .ok_or_else(|| "Invalid manifest path".into())
            })
            .collect()
    } else {
        Err(
            format!(
                "Failed to get metadata: {}",
                String::from_utf8_lossy(&output.stderr)
            ).into(),
        )
    }
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    let output = if args.flag_all {
        get_workspace_manifests(&args.flag_manifest_path).and_then(|manifests| {
            for manifest in manifests {
                update_manifest(&Some(manifest), &args.flag_dependency, args.flag_allow_prerelease)?
            }

            Ok(())
        })
    } else {
        update_manifest(&args.flag_manifest_path, &args.flag_dependency, args.flag_allow_prerelease)
    };

    if let Err(err) = output {
        writeln!(
            io::stderr(),
            "Command failed due to unhandled error: {}\n",
            err
        ).unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
       trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
       unused_qualifications)]

extern crate cargo_metadata;
extern crate docopt;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::collections::HashMap;
use std::io::{self, Write};
use std::path::Path;
use std::process;

extern crate cargo_edit;
use cargo_edit::{get_latest_dependency, Dependency, Manifest};

mod errors {
    error_chain!{
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
        }

        foreign_links {
            // cargo-metadata doesn't (yet) export `ErrorKind`)
            Metadata(::cargo_metadata::Error);
        }
    }
}
use errors::*;

static USAGE: &'static str = r"
Upgrade all dependencies in a manifest file to the latest version.

Usage:
    cargo upgrade [--all] [--dependency <dep>...] [--manifest-path <path>] [options]
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                       Upgrade all packages in the workspace.
    -d --dependency <dep>       Specific dependency to upgrade. If this option is used, only the
                                specified dependencies will be upgraded.
    --manifest-path <path>      Path to the manifest to upgrade.
    --allow-prerelease          Include prerelease versions when fetching from crates.io (e.g.
                                '0.6.0-alpha'). Defaults to false.
    -h --help                   Show this help page.
    -V --version                Show version.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `--dependency -d <dep>`
    flag_dependency: Vec<String>,
    /// `--manifest-path <path>`
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
}

fn is_version_dependency(dep: &toml::Value) -> bool {
    if let Some(table) = dep.as_table() {
        !table.contains_key("git") && !table.contains_key("path")
    } else {
        true
    }
}

fn update_manifest(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = get_latest_dependency(name, allow_prerelease)?;

                manifest.update_table_entry(&table_path, &latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest.write_to_file(&mut file)?;

    Ok(())
}

fn update_manifest_from_cache(
    manifest_path: &Option<String>,
    only_update: &[String],
    new_deps: &HashMap<String, Dependency>,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = &new_deps[name];

                manifest.update_table_entry(&table_path, latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest
        .write_to_file(&mut file)
        .chain_err(|| "Failed to write new manifest contents")
}

/// Get a list of the paths of all the (non-virtual) manifests in the workspace.
fn get_workspace_manifests(manifest_path: &Option<String>) -> Result<Vec<String>> {
    Ok(
        cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
            .chain_err(|| "Failed to get metadata")?
            .packages
            .iter()
            .map(|p| p.manifest_path.clone())
            .collect(),
    )
}

/// Look up all current direct crates.io dependencies in the workspace. Then get the latest version
/// for each.
fn get_all_new_deps(
    manifest_path: &Option<String>,
    allow_prerelease: bool,
) -> Result<HashMap<String, Dependency>> {
    let mut new_deps = HashMap::new();

    cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
        .chain_err(|| "Failed to get metadata")?
        .packages
        .iter()
        .flat_map(|package| package.dependencies.to_owned())
        .map(|dependency| {
            if !new_deps.contains_key(&dependency.name) {
                new_deps.insert(
                    dependency.name.clone(),
                    get_latest_dependency(&dependency.name, allow_prerelease)?,
                );
            }
            Ok(())
        })
        .collect::<Result<Vec<()>>>()?;

    Ok(new_deps)
}

/// Get the latest versions of the specified crates.io dependencies.
fn get_specified_new_deps(
    depedencies: &[String],
    allow_prerelease: bool,
) -> Result<HashMap<String, Dependency>> {
    depedencies
        .into_iter()
        .map(|dep| {
            Ok((
                dep.to_owned(),
                get_latest_dependency(dep, allow_prerelease)?,
            ))
        })
        .collect()
}

fn update_workspace_manifests(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let new_deps = if !only_update.is_empty() {
        get_specified_new_deps(only_update, allow_prerelease)?
    } else {
        get_all_new_deps(manifest_path, allow_prerelease)?
    };

    get_workspace_manifests(manifest_path).and_then(|manifests| {
        for manifest in manifests {
            update_manifest_from_cache(&Some(manifest), only_update, &new_deps)?
        }

        Ok(())
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    let output = if args.flag_all {
        update_workspace_manifests(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    } else {
        update_manifest(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    };

    if let Err(err) = output {
        let mut stderr = io::stderr();

        writeln!(stderr, "Command failed due to unhandled error: {}\n", err).unwrap();

        for e in err.iter().skip(1) {
            writeln!(stderr, "Caused by: {}", e).unwrap();
        }

        if let Some(backtrace) = err.backtrace() {
            writeln!(stderr, "Backtrace: {:?}", backtrace).unwrap();
        }

        process::exit(1);
    }
}
<commit_msg>Remove specialised handling for specific deps<commit_after>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
       trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
       unused_qualifications)]

extern crate cargo_metadata;
extern crate docopt;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::collections::HashMap;
use std::io::{self, Write};
use std::path::Path;
use std::process;

extern crate cargo_edit;
use cargo_edit::{get_latest_dependency, Dependency, Manifest};

mod errors {
    error_chain!{
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
        }

        foreign_links {
            // cargo-metadata doesn't (yet) export `ErrorKind`)
            Metadata(::cargo_metadata::Error);
        }
    }
}
use errors::*;

static USAGE: &'static str = r"
Upgrade all dependencies in a manifest file to the latest version.

Usage:
    cargo upgrade [--all] [--dependency <dep>...] [--manifest-path <path>] [options]
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                       Upgrade all packages in the workspace.
    -d --dependency <dep>       Specific dependency to upgrade. If this option is used, only the
                                specified dependencies will be upgraded.
    --manifest-path <path>      Path to the manifest to upgrade.
    --allow-prerelease          Include prerelease versions when fetching from crates.io (e.g.
                                '0.6.0-alpha'). Defaults to false.
    -h --help                   Show this help page.
    -V --version                Show version.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `--dependency -d <dep>`
    flag_dependency: Vec<String>,
    /// `--manifest-path <path>`
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
}

fn is_version_dependency(dep: &toml::Value) -> bool {
    if let Some(table) = dep.as_table() {
        !table.contains_key("git") && !table.contains_key("path")
    } else {
        true
    }
}

fn update_manifest(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = get_latest_dependency(name, allow_prerelease)?;

                manifest.update_table_entry(&table_path, &latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest
        .write_to_file(&mut file)
        .chain_err(|| "Failed to write new manifest contents")
}

fn update_manifest_from_cache(
    manifest_path: &Option<String>,
    only_update: &[String],
    new_deps: &HashMap<String, Dependency>,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = &new_deps[name];

                manifest.update_table_entry(&table_path, latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest
        .write_to_file(&mut file)
        .chain_err(|| "Failed to write new manifest contents")
}

/// Get a list of the paths of all the (non-virtual) manifests in the workspace.
fn get_workspace_manifests(manifest_path: &Option<String>) -> Result<Vec<String>> {
    Ok(
        cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
            .chain_err(|| "Failed to get metadata")?
            .packages
            .iter()
            .map(|p| p.manifest_path.clone())
            .collect(),
    )
}

/// Look up all current direct crates.io dependencies in the workspace. Then get the latest version
/// for each.
fn get_new_workspace_deps(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<HashMap<String, Dependency>> {
    let mut new_deps = HashMap::new();

    cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
        .chain_err(|| "Failed to get metadata")?
        .packages
        .iter()
        .flat_map(|package| package.dependencies.to_owned())
        .filter(|dependency| {
            only_update.is_empty() || only_update.contains(&dependency.name)
        })
        .map(|dependency| {
            if !new_deps.contains_key(&dependency.name) {
                new_deps.insert(
                    dependency.name.clone(),
                    get_latest_dependency(&dependency.name, allow_prerelease)?,
                );
            }
            Ok(())
        })
        .collect::<Result<Vec<()>>>()?;

    Ok(new_deps)
}

fn update_workspace_manifests(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let new_deps = get_new_workspace_deps(manifest_path, only_update, allow_prerelease)?;

    get_workspace_manifests(manifest_path).and_then(|manifests| {
        for manifest in manifests {
            update_manifest_from_cache(&Some(manifest), only_update, &new_deps)?
        }

        Ok(())
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    let output = if args.flag_all {
        update_workspace_manifests(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    } else {
        update_manifest(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    };

    if let Err(err) = output {
        let mut stderr = io::stderr();

        writeln!(stderr, "Command failed due to unhandled error: {}\n", err).unwrap();

        for e in err.iter().skip(1) {
            writeln!(stderr, "Caused by: {}", e).unwrap();
        }

        if let Some(backtrace) = err.backtrace() {
            writeln!(stderr, "Backtrace: {:?}", backtrace).unwrap();
        }

        process::exit(1);
    }
}
<|endoftext|>