<commit_before>use super::mode;
use super::util;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;
type Cmd<'a> = (uint,mode::Mode,&'a Doc);

#[inline(always)]
fn fitting(mut cmds:Vec<Cmd>, mut rem:int) -> bool {
    let mut fits = true;

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match cmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(box ref ldoc, box ref rdoc) => {
                    cmds.push((ind, mode, rdoc));
                    cmds.push((ind, mode, ldoc));
                },
                &Group(box ref doc) => {
                    cmds.push((ind, mode, doc));
                },
                &Nest(off, box ref doc) => {
                    cmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as int;
                },
            }
        }
    }

    fits
}

impl Doc {

    #[inline]
    pub fn nil() -> Doc {
        Nil
    }

    #[inline]
    pub fn append(self, that:Doc) -> Doc {
        match self {
            Nil => {
                that
            },
            ldoc => match that {
                Nil => {
                    ldoc
                },
                rdoc => {
                    Append(box ldoc, box rdoc)
                },
            }
        }
    }

    #[inline]
    pub fn as_string<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc {
        Group(box self)
    }

    #[inline]
    pub fn nest(self, off:uint) -> Doc {
        Nest(off, box self)
    }

    #[inline]
    pub fn newline() -> Doc {
        Newline
    }

    #[inline]
    pub fn render(&self, width:uint) -> String {
        let mut pos = 0u;
        let mut cmds = vec![];
        let mut result = String::new();

        cmds.push((0, mode::Break, self));

        loop {
            match cmds.pop() {
                None => {
                    break;
                },
                Some((ind, mode, doc)) => match doc {
                    &Nil => {
                    },
                    &Append(box ref ldoc, box ref rdoc) => {
                        cmds.push((ind, mode, rdoc));
                        cmds.push((ind, mode, ldoc));
                    },
                    &Group(box ref doc) => match mode {
                        mode::Flat => {
                            cmds.push((ind, mode::Flat, doc));
                        },
                        mode::Break => {
                            // FIXME: fitting() modifies cmds so we must either
                            // take a clone and pass it or rewrite fitting()
                            // to modify a separate cmd stack and only observe
                            // this one.
                            let mut cmds_dup = cmds.clone();
                            let next = (ind, mode::Flat, doc);
                            cmds_dup.push(next);
                            if fitting(cmds_dup, width as int - pos as int) {
                                cmds.push(next);
                            } else {
                                cmds.push((ind, mode::Break, doc));
                            }
                        }
                    },
                    &Nest(off, box ref doc) => {
                        cmds.push((ind + off, mode, doc));
                    },
                    &Newline => {
                        result.push_str(util::string::nl_spaces(ind).as_slice());
                        pos = ind;
                    },
                    &Text(ref str) => {
                        result.push_str(str.as_slice());
                        pos += str.len();
                    },
                }
            }
        }

        result
    }

    #[inline]
    pub fn text<T:Str>(str:T) -> Doc {
        Text(String::from_str(str.as_slice()))
    }

}
<commit_msg>Actually just inline best instead<commit_after>use super::mode;
use super::util;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;
type Cmd<'a> = (uint,mode::Mode,&'a Doc);

#[inline(always)]
fn fitting(mut cmds:Vec<Cmd>, mut rem:int) -> bool {
    let mut fits = true;

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match cmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(box ref ldoc, box ref rdoc) => {
                    cmds.push((ind, mode, rdoc));
                    cmds.push((ind, mode, ldoc));
                },
                &Group(box ref doc) => {
                    cmds.push((ind, mode, doc));
                },
                &Nest(off, box ref doc) => {
                    cmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as int;
                },
            }
        }
    }

    fits
}

#[inline(always)]
fn best(doc:&Doc, width:uint) -> String {
    let mut pos = 0u;
    let mut cmds = vec![];
    let mut result = String::new();

    cmds.push((0, mode::Break, doc));

    loop {
        match cmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(box ref ldoc, box ref rdoc) => {
                    cmds.push((ind, mode, rdoc));
                    cmds.push((ind, mode, ldoc));
                },
                &Group(box ref doc) => match mode {
                    mode::Flat => {
                        cmds.push((ind, mode::Flat, doc));
                    },
                    mode::Break => {
                        // FIXME: fitting() modifies cmds so we must either
                        // take a clone and pass it or rewrite fitting()
                        // to modify a separate cmd stack and only observe
                        // this one.
                        let mut cmds_dup = cmds.clone();
                        let next = (ind, mode::Flat, doc);
                        cmds_dup.push(next);
                        if fitting(cmds_dup, width as int - pos as int) {
                            cmds.push(next);
                        } else {
                            cmds.push((ind, mode::Break, doc));
                        }
                    }
                },
                &Nest(off, box ref doc) => {
                    cmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    result.push_str(util::string::nl_spaces(ind).as_slice());
                    pos = ind;
                },
                &Text(ref str) => {
                    result.push_str(str.as_slice());
                    pos += str.len();
                },
            }
        }
    }

    result
}

impl Doc {

    #[inline]
    pub fn nil() -> Doc {
        Nil
    }

    #[inline]
    pub fn append(self, that:Doc) -> Doc {
        match self {
            Nil => {
                that
            },
            ldoc => match that {
                Nil => {
                    ldoc
                },
                rdoc => {
                    Append(box ldoc, box rdoc)
                },
            }
        }
    }

    #[inline]
    pub fn as_string<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc {
        Group(box self)
    }

    #[inline]
    pub fn nest(self, off:uint) -> Doc {
        Nest(off, box self)
    }

    #[inline]
    pub fn newline() -> Doc {
        Newline
    }

    #[inline]
    pub fn render(&self, width:uint) -> String {
        best(self, width)
    }

    #[inline]
    pub fn text<T:Str>(str:T) -> Doc {
        Text(String::from_str(str.as_slice()))
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 Drew Short <drew@sothr.com>.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::iter::range_step_inclusive;

/**
    Determines if a specified number is prime.

    # Arguments

    * 'num' - The number to check for primality

    # Examples

    ```rust
    use sothr_lib::prime_util::is_prime;
    assert_eq!(true, is_prime(1));
    assert_eq!(true, is_prime(5));
    assert_eq!(false, is_prime(6));
    assert_eq!(true, is_prime(6857));
    assert_eq!(false, is_prime(75031));
    ```
*/
pub fn is_prime(num: u64) -> bool {
    // 1-3 are prime numbers
    if num <= 3 {
        return true;
    }

    // numbers divisible by 2 and 3, but greater than 3 are not prime
    if num % 2 == 0 || num % 3 == 0 {
        return false;
    }

    // Check every number between i=5 and the square of i than is less than the
    // desired number
    let mut i = 5;
    while i*i < num {
    	// If the number is evenly divisible by i or i+2 it is not prime
        if num % i == 0 || num % (i+2) == 0 {
            return false;
        }
        // Increment by 6 because it is the product of 2 and 3. Therefore of
        // the numbers between 5 and 11 (i and i+6) only 5 and 7 could be prime
        // values. 6, 8, 9 and 10 are products or sums of 2 and 3.
        i += 6;
    }
    // If this far, then the number is definitively prime
    true
}

/**
  Generate a list of primes between 0 and the end value.

  # Arguments

  * 'look_until' - The end of the range to look for primes within

  # Examples

  ```rust
  use sothr_lib::prime_util::list_of_primes;
  let prime_list = vec![2,3,5,7,11];
  assert_eq!(prime_list, list_of_primes(12).expect("No Primes?!?!?"));
  ```
*/
pub fn list_of_primes(look_until: u64) -> Option<Vec<u64>> {
  if look_until < 2u64 {
    return None
  }

  let end = look_until as usize;

  //prepopulate the sieve
  let mut sieve: Vec<bool> = Vec::with_capacity(end);
  let mut i: usize = 0;
  while i < end {
    sieve.push(true);
    i += 1;
  }

  let f_look_until = look_until as f64;
  let estimate_of_primes = ((f_look_until / f_look_until.ln()) * (1f64 + (1.2762 / f_look_until.ln()))) as usize;
  let mut primes: Vec<u64> = Vec::with_capacity(estimate_of_primes);
  primes.push(2u64);

  let limit = (f_look_until.sqrt() as usize) + 1;

  for i in range_step_inclusive(3usize, end-1, 2usize) {
    if sieve[i] {
      primes.push(i as u64);
      if i < limit {
        for j in range_step_inclusive(i*i, end-1, i) {
          sieve[j] = false;
        }
      }
    }
  }

  Some(primes)
}<commit_msg>Halved the list_of_primes() memory requirement by pre-optimizing the sieve to only search odd numbers instead of all.<commit_after>// Copyright 2015 Drew Short <drew@sothr.com>.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::iter::range_step_inclusive;

/**
    Determines if a specified number is prime.

    # Arguments

    * 'num' - The number to check for primality

    # Examples

    ```rust
    use sothr_lib::prime_util::is_prime;
    assert_eq!(true, is_prime(1));
    assert_eq!(true, is_prime(5));
    assert_eq!(false, is_prime(6));
    assert_eq!(true, is_prime(6857));
    assert_eq!(false, is_prime(75031));
    ```
*/
pub fn is_prime(num: u64) -> bool {
    // 1-3 are prime numbers
    if num <= 3 {
        return true;
    }

    // numbers divisible by 2 and 3, but greater than 3 are not prime
    if num % 2 == 0 || num % 3 == 0 {
        return false;
    }

    // Check every number between i=5 and the square of i than is less than the
    // desired number
    let mut i = 5;
    while i*i < num {
    	// If the number is evenly divisible by i or i+2 it is not prime
        if num % i == 0 || num % (i+2) == 0 {
            return false;
        }
        // Increment by 6 because it is the product of 2 and 3. Therefore of
        // the numbers between 5 and 11 (i and i+6) only 5 and 7 could be prime
        // values. 6, 8, 9 and 10 are products or sums of 2 and 3.
        i += 6;
    }
    // If this far, then the number is definitively prime
    true
}

/**
  Generate a list of primes between 0 and the end value.

  # Arguments

  * 'look_until' - The end of the range to look for primes within

  # Examples

  ```rust
  use sothr_lib::prime_util::list_of_primes;
  let prime_list = vec![2,3,5,7,11];
  assert_eq!(prime_list, list_of_primes(12).expect("No Primes?!?!?"));
  ```
*/
pub fn list_of_primes(look_until: u64) -> Option<Vec<u64>> {
  if look_until < 2u64 {
    return None
  }

  let end = look_until as usize;

  //prepopulate the sieve
  let mut sieve: Vec<bool> = Vec::with_capacity(end/2);
  let mut i: usize = 0;
  while i < end {
    sieve.push(true);
    i += 1;
  }

  let f_look_until = look_until as f64;
  let estimate_of_primes = ((f_look_until / f_look_until.ln()) * (1f64 + (1.2762 / f_look_until.ln()))) as usize;
  let mut primes: Vec<u64> = Vec::with_capacity(estimate_of_primes);
  primes.push(2u64);

  let limit = ((f_look_until/2).sqrt() as usize) + 1;

  // in this lineup index 0 == 3
  // therefore index 1 == 5, 2 == 7, 3 == 9, etc...
  for i in 0..end/2 {
    if sieve[i] {
      primes.push((i+i+3) as u64);
      if i < limit {
        // selectively sieve out non primes. We're only concerned with odds as
        // we've already removed even values from the list.
        // i = 0, therefore i represents 3
        // i+i+3 = 3
        // simple proofs of odd counts
        // 0 1 2 3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
        //[3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49]
        //0,3,6,9,12 = <3>,9,15,21,27
        //1,6,11,16 = <5>,15,25,35
        //2,9,16,23 = <7>,21,35,49
        for j in range_step_inclusive(i+i+3, end-1, i+i+3) {
          sieve[j] = false;
        }
      }
    }
  }

  Some(primes)
}
<|endoftext|>


<commit_before>use common::util::*;

#[test]
fn test_hostname() {
    let ls_default_res = new_ucmd!().succeeds();
    let ls_short_res = new_ucmd!().arg("-s").succeeds();
    let ls_domain_res = new_ucmd!().arg("-d").succeeds();

    assert!(ls_default_res.stdout.len() >= ls_short_res.stdout.len());
    assert!(ls_default_res.stdout.len() >= ls_domain_res.stdout.len());
}
<commit_msg>test(hostname): Test more options (#1515)<commit_after>use common::util::*;

#[test]
fn test_hostname() {
    let ls_default_res = new_ucmd!().succeeds();
    let ls_short_res = new_ucmd!().arg("-s").succeeds();
    let ls_domain_res = new_ucmd!().arg("-d").succeeds();

    assert!(ls_default_res.stdout.len() >= ls_short_res.stdout.len());
    assert!(ls_default_res.stdout.len() >= ls_domain_res.stdout.len());
}

#[test]
fn test_hostname_ip() {
    let result = new_ucmd!().arg("-i").succeeds();
    assert!(!result.stdout.trim().is_empty());
}

#[test]
fn test_hostname_full() {
    let result = new_ucmd!().arg("-f").succeeds();
    assert!(!result.stdout.trim().is_empty());

    let ls_short_res = new_ucmd!().arg("-s").succeeds();
    assert!(result.stdout.trim().contains(ls_short_res.stdout.trim()));
}
<|endoftext|>


<commit_before>///Lazy git tool
use std::env::args as cmd_args;
use std::process::Command;

///Executes git command with arguments
macro_rules! exec_git_cmd {
    ($args:expr) => {
        Command::new("git").args($args).status().unwrap();
    }
}

#[inline(always)]
fn usage() {
    println!("lgit [option]\n");
    println!("options:");
    println!("  amend [edit] - amend all changes into last commit");
    println!("  add - add all changes");
    println!("  clean - undo all changes");
    println!("  push [force] - push current branch");
    println!("  fetch - get updates from upstream\n");
}

///Amend changes
fn git_amend(args: &[String]) {
    git_add();
    if args.len() != 0 && args[0] == "edit" { exec_git_cmd!(&["commit", "--amend"]); }
    else { exec_git_cmd!(&["commit", "--amend", "--no-edit"]); }
}

///Fetch changes from upstream
fn git_fetch() {
    exec_git_cmd!(&["checkout", "master"]);
    exec_git_cmd!(&["fetch", "upstream"]);
    exec_git_cmd!(&["merge", "upstream/master"]);
}

///Push the current branch
fn git_push(args: &[String]) {
    if args.len() != 0 && args[0] =="force" { exec_git_cmd!(&["push", "--force", "origin", "HEAD"]); }
    else { exec_git_cmd!(&["push", "origin", "HEAD"]); }
}

///Add all changes
fn git_add() {
    exec_git_cmd!(&["add", "--all"]);
}

///Undo all changes
fn git_clean() {
    exec_git_cmd!(&["checkout", "-f"]);
    exec_git_cmd!(&["clean", "-fdq"]);
}

///Unexpected argument handler
fn unexpected(arg: &str) {
    println!("Unexpected argument: {}", arg);
    usage();
}

fn main() {
    let args: Vec<String> = cmd_args().collect();
    //exclude file name
    let s_args = &args[1..];
    let is_repo = Command::new("git").arg("rev-parse").arg("-q").output().unwrap();

    if is_repo.status.code().unwrap() != 0 {
        println!("Not a git repository");
        return;
    }
    else if s_args.len() == 0 {
        usage();
        return;
    }

    match s_args[0].as_ref() {
        "amend" => git_amend(&args[2..]),
        "fetch" => git_fetch(),
        "push"  => git_push(&args[2..]),
        "add"   => git_add(),
        "clean" => git_clean(),
        _       => unexpected(&s_args[0]),
    }
}
<commit_msg>Update git macro for lgit script<commit_after>///Lazy git tool
use std::env::args as cmd_args;
use std::process::Command;

///Executes git command with arguments
///Building sequence of arguments like .arg(@arg)
macro_rules! exec_git_cmd {
    ($($arg:expr),*) => { Command::new("git")$(.arg($arg))*.status().unwrap(); }
}

#[inline(always)]
fn usage() {
    println!("lgit [option]\n");
    println!("options:");
    println!("  amend [edit] - amend all changes into last commit");
    println!("  add - add all changes");
    println!("  clean - undo all changes");
    println!("  push [force] - push current branch");
    println!("  fetch - get updates from upstream\n");
}

///Amend changes
fn git_amend(args: &[String]) {
    git_add();
    if args.len() != 0 && args[0] == "edit" { exec_git_cmd!("commit", "--amend"); }
    else { exec_git_cmd!("commit", "--amend", "--no-edit"); }
}

///Fetch changes from upstream
fn git_fetch() {
    exec_git_cmd!("checkout", "master");
    exec_git_cmd!("fetch", "upstream");
    exec_git_cmd!("merge", "upstream/master");
}

///Push the current branch
fn git_push(args: &[String]) {
    if args.len() != 0 && args[0] =="force" { exec_git_cmd!("push", "--force", "origin", "HEAD"); }
    else { exec_git_cmd!("push", "origin", "HEAD"); }
}

///Add all changes
fn git_add() {
    exec_git_cmd!("add", "--all");
}

///Undo all changes
fn git_clean() {
    exec_git_cmd!("checkout", "-f");
    exec_git_cmd!("clean", "-fdq");
}

///Unexpected argument handler
fn unexpected(arg: &str) {
    println!("Unexpected argument: {}", arg);
    usage();
}

fn main() {
    let args: Vec<String> = cmd_args().collect();
    //exclude file name
    let is_repo = Command::new("git").arg("rev-parse").arg("-q").output().unwrap();

    if is_repo.status.code().unwrap() != 0 {
        println!("Not a git repository");
        return;
    }
    else if args.len() == 1 {
        usage();
        return;
    }

    match args[1].as_ref() {
        "amend" => git_amend(&args[2..]),
        "fetch" => git_fetch(),
        "push"  => git_push(&args[2..]),
        "add"   => git_add(),
        "clean" => git_clean(),
        _       => unexpected(&args[1]),
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

#[macro_use] extern crate cookie_factory;
#[macro_use] extern crate nom;
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

mod types;
mod value;

pub use types::*;
pub use value::*;

///! Helpers to handle AMQP flags.
pub mod flags;
///! Generation utilities for the various AMQP types.
pub mod generation;
///! Parsing utilities for the various AMQP types.
pub mod parsing;
<commit_msg>types: add crate documentation<commit_after>#![deny(missing_docs)]

//! # AMQP types manipulation library
//!
//! amq-protocol-types is a library aiming at providing an implementation/abstraction
//! around AMQP types.
//!
//! It implements the list of the different kind of types available, a value holder and
//! serialization.deserialization facilities.

#[macro_use] extern crate cookie_factory;
#[macro_use] extern crate nom;
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

mod types;
mod value;

pub use types::*;
pub use value::*;

///! Helpers to handle AMQP flags.
pub mod flags;
///! Generation utilities for the various AMQP types.
pub mod generation;
///! Parsing utilities for the various AMQP types.
pub mod parsing;
<|endoftext|>


<commit_before>use actix_web::{server, test::TestServer};
use failure::{Error, Fail};
use kv;
use potboiler;
use potboiler_common::{server_id, ServerThread};
use pretty_assertions::assert_eq;
use reqwest::{Client, StatusCode};
use serde_json::json;
use serial_test_derive::serial;
use std::env;
use std::{thread, time};

#[derive(Debug, Fail)]
enum IntegrationError {
    #[fail(display = "IoError")]
    IoError {
        #[cause]
        cause: std::io::Error,
    },
}

fn boot_potboiler() -> Result<ServerThread, Error> {
    let _ = env_logger::try_init();
    let pool = potboiler::db_setup()?;
    let app_state = potboiler::AppState::new(pool, server_id::test()).unwrap();
    return ServerThread::new({
        move || server::new(move || potboiler::app_router(app_state.clone()).unwrap()).bind("0.0.0.0:8000")
    })
    .map_err(|e| IntegrationError::IoError { cause: e }.into());
}

fn test_setup() -> Result<(ServerThread, TestServer), Error> {
    let _ = env_logger::try_init();
    let pool = kv::db_setup().unwrap();
    pool.wipe_db()?;
    let pb_server = boot_potboiler()?;
    env::set_var("SERVER_URL", "http://localhost:8000/log");
    let client = reqwest::Client::new();
    let app_state = kv::AppState::new(pool, client.clone()).unwrap();
    let kv_server = TestServer::with_factory(move || kv::app_router(app_state.clone()).unwrap());
    env::set_var("KV_ROOT", kv_server.url("/"));
    kv::register(&client).unwrap();
    return Ok((pb_server, kv_server));
}

#[test]
#[serial]
fn test_empty_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let mut response = client.get(&kv_server.url("/kv/_config/test")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such key 'test'");
}

#[test]
#[serial]
fn test_no_such_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let mut response = client.get(&kv_server.url("/kv/test/foo")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such table 'test'");
}

#[test]
#[serial]
fn test_create_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let mut response = client.get(&kv_server.url("/kv/test/foo")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such table 'test'");

    let args = json!({
        "op": "set",
        "change": {"crdt": "LWW"}
    });
    response = client
        .post(&kv_server.url("/kv/_config/test"))
        .json(&args)
        .send()
        .unwrap();
    assert_eq!(response.status(), StatusCode::OK);

    // give it some time to build the table
    thread::sleep(time::Duration::from_millis(100));

    response = client.get(&kv_server.url("/kv/test/foo")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such key 'foo'");
}
<commit_msg>Add basic ORSet test<commit_after>use actix_web::{server, test::TestServer};
use failure::{Error, Fail};
use kv;
use potboiler;
use potboiler_common::{server_id, ServerThread};
use pretty_assertions::assert_eq;
use reqwest::{Client, StatusCode};
use serde_json::json;
use serial_test_derive::serial;
use std::env;
use std::{thread, time};

#[derive(Debug, Fail)]
enum IntegrationError {
    #[fail(display = "IoError")]
    IoError {
        #[cause]
        cause: std::io::Error,
    },
}

fn boot_potboiler() -> Result<ServerThread, Error> {
    let _ = env_logger::try_init();
    let pool = potboiler::db_setup()?;
    let app_state = potboiler::AppState::new(pool, server_id::test()).unwrap();
    return ServerThread::new({
        move || server::new(move || potboiler::app_router(app_state.clone()).unwrap()).bind("0.0.0.0:8000")
    })
    .map_err(|e| IntegrationError::IoError { cause: e }.into());
}

fn test_setup() -> Result<(ServerThread, TestServer), Error> {
    let _ = env_logger::try_init();
    let pool = kv::db_setup().unwrap();
    pool.wipe_db()?;
    let pb_server = boot_potboiler()?;
    env::set_var("SERVER_URL", "http://localhost:8000/log");
    let client = reqwest::Client::new();
    let app_state = kv::AppState::new(pool, client.clone()).unwrap();
    let kv_server = TestServer::with_factory(move || kv::app_router(app_state.clone()).unwrap());
    env::set_var("KV_ROOT", kv_server.url("/"));
    kv::register(&client).unwrap();
    return Ok((pb_server, kv_server));
}

#[test]
#[serial]
fn test_empty_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let mut response = client.get(&kv_server.url("/kv/_config/test")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such key 'test'");
}

#[test]
#[serial]
fn test_no_such_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let mut response = client.get(&kv_server.url("/kv/test/foo")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such table 'test'");
}

#[test]
#[serial]
fn test_create_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let mut response = client.get(&kv_server.url("/kv/test/foo")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such table 'test'");

    let args = json!({
        "op": "set",
        "change": {"crdt": "LWW"}
    });
    response = client
        .post(&kv_server.url("/kv/_config/test"))
        .json(&args)
        .send()
        .unwrap();
    assert_eq!(response.status(), StatusCode::OK);

    // give it some time to build the table
    thread::sleep(time::Duration::from_millis(100));

    response = client.get(&kv_server.url("/kv/test/foo")).send().unwrap();
    assert_eq!(response.status(), StatusCode::NOT_FOUND);
    assert_eq!(response.text().unwrap(), "No such key 'foo'");
}

#[test]
#[serial]
fn test_create_orset_table() {
    let (_pb_server, kv_server) = test_setup().unwrap();
    let client = Client::new();
    let args = json!({
        "op": "set",
        "change": {"crdt": "ORSET"}
    });
    let mut response = client
        .post(&kv_server.url("/kv/_config/test"))
        .json(&args)
        .send()
        .unwrap();
    assert_eq!(response.status(), StatusCode::OK);

    // give it some time to build the table
    thread::sleep(time::Duration::from_millis(100));

    let new_key = json!({
        "op": "add",
        "change": {
            "key": "[key]",
            "item":"[item]",
            "metadata": "[metadata]"
        }
    });

    response = client
        .post(&kv_server.url("/kv/test/foo"))
        .json(&new_key)
        .send()
        .unwrap();
    assert_eq!(response.status(), StatusCode::OK);
}
<|endoftext|>


<commit_before>use cairo::{self, ImageSurface};
use cssparser::{CowRcStr, Parser, Token};
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::drawing_ctx::DrawingCtx;
use crate::error::{AttributeResultExt, ValueErrorKind};
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{self, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::Pixels,
    shared_surface::SharedImageSurface,
    ImageSurfaceDataExt,
    Pixel,
};
use crate::util::clamp;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::input::Input;
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible compositing operations.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum Operator {
    Over,
    In,
    Out,
    Atop,
    Xor,
    Arithmetic,
}

/// The `feComposite` filter primitive.
pub struct FeComposite {
    base: PrimitiveWithInput,
    in2: Option<Input>,
    operator: Operator,
    k1: f64,
    k2: f64,
    k3: f64,
    k4: f64,
}

impl Default for FeComposite {
    /// Constructs a new `Composite` with empty properties.
    #[inline]
    fn default() -> FeComposite {
        FeComposite {
            base: PrimitiveWithInput::new::<Self>(),
            in2: None,
            operator: Operator::Over,
            k1: 0.0,
            k2: 0.0,
            k3: 0.0,
            k4: 0.0,
        }
    }
}

impl NodeTrait for FeComposite {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!(svg "in2") => self.in2 = Some(Input::parse(attr, value)?),
                expanded_name!(svg "operator") => self.operator = attr.parse(value)?,
                expanded_name!(svg "k1") => self.k1 = parsers::number(value).attribute(attr)?,
                expanded_name!(svg "k2") => self.k2 = parsers::number(value).attribute(attr)?,
                expanded_name!(svg "k3") => self.k3 = parsers::number(value).attribute(attr)?,
                expanded_name!(svg "k4") => self.k4 = parsers::number(value).attribute(attr)?,
                _ => (),
            }
        }

        Ok(())
    }
}

/// Performs the arithmetic composite operation. Public for benchmarking.
#[inline]
pub fn composite_arithmetic(
    input_surface: &SharedImageSurface,
    input_2_surface: &SharedImageSurface,
    output_surface: &mut cairo::ImageSurface,
    bounds: IRect,
    k1: f64,
    k2: f64,
    k3: f64,
    k4: f64,
) {
    let output_stride = output_surface.get_stride() as usize;
    {
        let mut output_data = output_surface.get_data().unwrap();

        for (x, y, pixel, pixel_2) in Pixels::new(input_surface, bounds)
            .map(|(x, y, p)| (x, y, p, input_2_surface.get_pixel(x, y)))
        {
            let i1a = f64::from(pixel.a) / 255f64;
            let i2a = f64::from(pixel_2.a) / 255f64;
            let oa = k1 * i1a * i2a + k2 * i1a + k3 * i2a + k4;
            let oa = clamp(oa, 0f64, 1f64);

            // Contents of image surfaces are transparent by default, so if the resulting pixel is
            // transparent there's no need to do anything.
            if oa > 0f64 {
                let compute = |i1, i2| {
                    let i1 = f64::from(i1) / 255f64;
                    let i2 = f64::from(i2) / 255f64;

                    let o = k1 * i1 * i2 + k2 * i1 + k3 * i2 + k4;
                    let o = clamp(o, 0f64, oa);

                    ((o * 255f64) + 0.5) as u8
                };

                let output_pixel = Pixel {
                    r: compute(pixel.r, pixel_2.r),
                    g: compute(pixel.g, pixel_2.g),
                    b: compute(pixel.b, pixel_2.b),
                    a: ((oa * 255f64) + 0.5) as u8,
                };
                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }
    }
}

impl FilterEffect for FeComposite {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let input_2 = ctx.get_input(draw_ctx, self.in2.as_ref())?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .add_input(&input_2)
            .into_irect(draw_ctx);

        // If we're combining two alpha-only surfaces, the result is alpha-only. Otherwise the
        // result is whatever the non-alpha-only type we're working on (which can be either sRGB or
        // linear sRGB depending on color-interpolation-filters).
        let surface_type = if input.surface().is_alpha_only() {
            input_2.surface().surface_type()
        } else {
            if !input_2.surface().is_alpha_only() {
                // All surface types should match (this is enforced by get_input()).
                assert_eq!(
                    input_2.surface().surface_type(),
                    input.surface().surface_type()
                );
            }

            input.surface().surface_type()
        };

        let output_surface = if self.operator == Operator::Arithmetic {
            let mut output_surface = ImageSurface::create(
                cairo::Format::ARgb32,
                input.surface().width(),
                input.surface().height(),
            )?;

            composite_arithmetic(
                input.surface(),
                input_2.surface(),
                &mut output_surface,
                bounds,
                self.k1,
                self.k2,
                self.k3,
                self.k4,
            );

            output_surface
        } else {
            let output_surface = input_2.surface().copy_surface(bounds)?;

            let cr = cairo::Context::new(&output_surface);
            let r = cairo::Rectangle::from(bounds);
            cr.rectangle(r.x, r.y, r.width, r.height);
            cr.clip();

            input.surface().set_as_source_surface(&cr, 0f64, 0f64);
            cr.set_operator(self.operator.into());
            cr.paint();

            output_surface
        };

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, surface_type)?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Parse for Operator {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
        let loc = parser.current_source_location();

        parser
            .expect_ident()
            .and_then(|cow| match cow.as_ref() {
                "over" => Ok(Operator::Over),
                "in" => Ok(Operator::In),
                "out" => Ok(Operator::Out),
                "atop" => Ok(Operator::Atop),
                "xor" => Ok(Operator::Xor),
                "arithmetic" => Ok(Operator::Arithmetic),
                _ => Err(
                    loc.new_basic_unexpected_token_error(Token::Ident(CowRcStr::from(
                        cow.as_ref().to_string(),
                    ))),
                ),
            })
            .map_err(|_| ValueErrorKind::Value("invalid operator value".to_string()))
    }
}

impl From<Operator> for cairo::Operator {
    #[inline]
    fn from(x: Operator) -> Self {
        match x {
            Operator::Over => cairo::Operator::Over,
            Operator::In => cairo::Operator::In,
            Operator::Out => cairo::Operator::Out,
            Operator::Atop => cairo::Operator::Atop,
            Operator::Xor => cairo::Operator::Xor,
            _ => panic!("can't convert Operator::Arithmetic to a cairo::Operator"),
        }
    }
}
<commit_msg>Operator: simplify parsing<commit_after>use cairo::{self, ImageSurface};
use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{self, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::Pixels,
    shared_surface::SharedImageSurface,
    ImageSurfaceDataExt,
    Pixel,
};
use crate::util::clamp;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::input::Input;
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible compositing operations.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum Operator {
    Over,
    In,
    Out,
    Atop,
    Xor,
    Arithmetic,
}

/// The `feComposite` filter primitive.
pub struct FeComposite {
    base: PrimitiveWithInput,
    in2: Option<Input>,
    operator: Operator,
    k1: f64,
    k2: f64,
    k3: f64,
    k4: f64,
}

impl Default for FeComposite {
    /// Constructs a new `Composite` with empty properties.
    #[inline]
    fn default() -> FeComposite {
        FeComposite {
            base: PrimitiveWithInput::new::<Self>(),
            in2: None,
            operator: Operator::Over,
            k1: 0.0,
            k2: 0.0,
            k3: 0.0,
            k4: 0.0,
        }
    }
}

impl NodeTrait for FeComposite {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!(svg "in2") => self.in2 = Some(Input::parse(attr, value)?),
                expanded_name!(svg "operator") => self.operator = attr.parse(value)?,
                expanded_name!(svg "k1") => self.k1 = parsers::number(value).attribute(attr)?,
                expanded_name!(svg "k2") => self.k2 = parsers::number(value).attribute(attr)?,
                expanded_name!(svg "k3") => self.k3 = parsers::number(value).attribute(attr)?,
                expanded_name!(svg "k4") => self.k4 = parsers::number(value).attribute(attr)?,
                _ => (),
            }
        }

        Ok(())
    }
}

/// Performs the arithmetic composite operation. Public for benchmarking.
#[inline]
pub fn composite_arithmetic(
    input_surface: &SharedImageSurface,
    input_2_surface: &SharedImageSurface,
    output_surface: &mut cairo::ImageSurface,
    bounds: IRect,
    k1: f64,
    k2: f64,
    k3: f64,
    k4: f64,
) {
    let output_stride = output_surface.get_stride() as usize;
    {
        let mut output_data = output_surface.get_data().unwrap();

        for (x, y, pixel, pixel_2) in Pixels::new(input_surface, bounds)
            .map(|(x, y, p)| (x, y, p, input_2_surface.get_pixel(x, y)))
        {
            let i1a = f64::from(pixel.a) / 255f64;
            let i2a = f64::from(pixel_2.a) / 255f64;
            let oa = k1 * i1a * i2a + k2 * i1a + k3 * i2a + k4;
            let oa = clamp(oa, 0f64, 1f64);

            // Contents of image surfaces are transparent by default, so if the resulting pixel is
            // transparent there's no need to do anything.
            if oa > 0f64 {
                let compute = |i1, i2| {
                    let i1 = f64::from(i1) / 255f64;
                    let i2 = f64::from(i2) / 255f64;

                    let o = k1 * i1 * i2 + k2 * i1 + k3 * i2 + k4;
                    let o = clamp(o, 0f64, oa);

                    ((o * 255f64) + 0.5) as u8
                };

                let output_pixel = Pixel {
                    r: compute(pixel.r, pixel_2.r),
                    g: compute(pixel.g, pixel_2.g),
                    b: compute(pixel.b, pixel_2.b),
                    a: ((oa * 255f64) + 0.5) as u8,
                };
                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }
    }
}

impl FilterEffect for FeComposite {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let input_2 = ctx.get_input(draw_ctx, self.in2.as_ref())?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .add_input(&input_2)
            .into_irect(draw_ctx);

        // If we're combining two alpha-only surfaces, the result is alpha-only. Otherwise the
        // result is whatever the non-alpha-only type we're working on (which can be either sRGB or
        // linear sRGB depending on color-interpolation-filters).
        let surface_type = if input.surface().is_alpha_only() {
            input_2.surface().surface_type()
        } else {
            if !input_2.surface().is_alpha_only() {
                // All surface types should match (this is enforced by get_input()).
                assert_eq!(
                    input_2.surface().surface_type(),
                    input.surface().surface_type()
                );
            }

            input.surface().surface_type()
        };

        let output_surface = if self.operator == Operator::Arithmetic {
            let mut output_surface = ImageSurface::create(
                cairo::Format::ARgb32,
                input.surface().width(),
                input.surface().height(),
            )?;

            composite_arithmetic(
                input.surface(),
                input_2.surface(),
                &mut output_surface,
                bounds,
                self.k1,
                self.k2,
                self.k3,
                self.k4,
            );

            output_surface
        } else {
            let output_surface = input_2.surface().copy_surface(bounds)?;

            let cr = cairo::Context::new(&output_surface);
            let r = cairo::Rectangle::from(bounds);
            cr.rectangle(r.x, r.y, r.width, r.height);
            cr.clip();

            input.surface().set_as_source_surface(&cr, 0f64, 0f64);
            cr.set_operator(self.operator.into());
            cr.paint();

            output_surface
        };

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, surface_type)?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Parse for Operator {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
        parse_identifiers!(
            parser,
            "over" => Operator::Over,
            "in" => Operator::In,
            "out" => Operator::Out,
            "atop" => Operator::Atop,
            "xor" => Operator::Xor,
            "arithmetic" => Operator::Arithmetic,
        ).map_err(|_: ParseError| ValueErrorKind::parse_error("parse error"))
    }
}

impl From<Operator> for cairo::Operator {
    #[inline]
    fn from(x: Operator) -> Self {
        match x {
            Operator::Over => cairo::Operator::Over,
            Operator::In => cairo::Operator::In,
            Operator::Out => cairo::Operator::Out,
            Operator::Atop => cairo::Operator::Atop,
            Operator::Xor => cairo::Operator::Xor,
            _ => panic!("can't convert Operator::Arithmetic to a cairo::Operator"),
        }
    }
}
<|endoftext|>


<commit_before>use super::book::Deal;
use std::ops;
use std::fmt;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct TradeStats {
  pub sum_sell: f64,
  pub sum_buy: f64,
  pub sum_sell_dest: f64,
  pub sum_buy_dest: f64,
  pub num_sell: u16,
  pub num_buy: u16,
}

// TradeStats operations

impl Default for TradeStats {
  fn default() -> TradeStats {
    TradeStats { sum_sell: 0.0, sum_sell_dest: 0.0, sum_buy: 0.0, sum_buy_dest: 0.0, num_sell: 0, num_buy: 0 }
  }
}

impl TradeStats {
  pub fn new(deals: Vec<&Deal>) -> TradeStats {
    deals.into_iter().fold(TradeStats::default(), |acc, deal| acc + deal)
  }
}

impl<'a> ops::Add<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &TradeStats) -> TradeStats {
    TradeStats {
      sum_sell: self.sum_sell + other.sum_sell,
      sum_sell_dest: self.sum_sell_dest + other.sum_sell_dest,
      sum_buy: self.sum_buy + other.sum_buy,
      sum_buy_dest: self.sum_buy_dest + other.sum_buy_dest,
      num_sell: self.num_sell + other.num_sell,
      num_buy: self.num_buy + other.num_buy,
    }
  }
}

impl<'a> ops::Add<&'a Deal> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &Deal) -> TradeStats {
    let (buy, num_buy, buy_dest, sell, num_sell, sell_dest) =
      if other.amount > 0.0 { (other.amount, 1, other.amount*other.rate, 0.0, 0, 0.0) }
      else                  { (0.0, 0, 0.0, -other.amount, 0, -other.amount*other.rate) };
    TradeStats {
      sum_sell: self.sum_sell + sell,
      sum_sell_dest: self.sum_sell_dest + sell_dest,
      sum_buy: self.sum_buy + buy,
      sum_buy_dest: self.sum_buy_dest + buy_dest,
      num_sell: self.num_sell + num_sell,
      num_buy: self.num_buy + num_buy,
    }
  }
}

impl<'a> ops::Sub<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn sub(self, other: &TradeStats) -> TradeStats {
    TradeStats {
      sum_sell: self.sum_sell - other.sum_sell,
      sum_sell_dest: self.sum_sell_dest - other.sum_sell_dest,
      sum_buy: self.sum_buy - other.sum_buy,
      sum_buy_dest: self.sum_buy_dest - other.sum_buy_dest,
      num_sell: self.num_sell - other.num_sell,
      num_buy: self.num_buy - other.num_buy,
    }
  }
}

impl fmt::Display for TradeStats {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "SELL {} to {} rate {} num {} | BUY {} to {} rate {} num {}",
      self.sum_sell, self.sum_sell_dest, self.sum_sell_dest/self.sum_sell, self.num_sell,
      self.sum_buy, self.sum_buy_dest, self.sum_buy_dest/self.sum_buy, self.num_buy)
  }
}

pub trait TimeStats {
  fn update_stats_1s(&mut self);
}

/**
 ** TESTS TESTS TESTS
 **/

#[cfg(test)]
mod tests {
  use super::TradeStats;
  use ::data::book::Deal;

  #[test]
  fn stats_default() {
    let default = TradeStats::default();
    assert_eq!(default.sum_buy, 0.0);
  }

  #[test]
  fn stats_new() {
    let deal = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deals = vec![&deal];
    let stats = TradeStats::new(deals);
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_add_deal() {
    let deal = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let stats = TradeStats::default() + &deal;
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_deals() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats = TradeStats::new(vec![&deal1, &deal2]);
    assert_eq!(stats.sum_buy, 10.0);
    assert_eq!(stats.sum_sell, 10.0);
  }

  #[test]
  fn stats_sub() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(vec![&deal1, &deal2]);
    let stats2 = TradeStats::new(vec![&deal2]);
    let stats = stats1 - &stats2;
    assert_eq!(stats.sum_buy, 10.0);
    assert_eq!(stats.sum_sell, 0.0);
  }

  #[test]
  fn stats_sub_exact() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(vec![&deal1, &deal2]);
    let stats2 = stats1.clone();
    let stats = stats1 - &stats2;
    assert_eq!(stats, TradeStats::default());
  }
}<commit_msg>more tests, fix stats<commit_after>use super::book::Deal;
use std::ops;
use std::fmt;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct TradeStats {
  pub sum_sell: f64,
  pub sum_buy: f64,
  pub sum_sell_dest: f64,
  pub sum_buy_dest: f64,
  pub num_sell: u16,
  pub num_buy: u16,
}

// TradeStats operations

impl Default for TradeStats {
  fn default() -> TradeStats {
    TradeStats { sum_sell: 0.0, sum_sell_dest: 0.0, sum_buy: 0.0, sum_buy_dest: 0.0, num_sell: 0, num_buy: 0 }
  }
}

impl TradeStats {
  pub fn new(deals: Vec<&Deal>) -> TradeStats {
    deals.into_iter().fold(TradeStats::default(), |acc, deal| acc + deal)
  }
}

impl<'a> ops::Add<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &TradeStats) -> TradeStats {
    TradeStats {
      sum_sell: self.sum_sell + other.sum_sell,
      sum_sell_dest: self.sum_sell_dest + other.sum_sell_dest,
      sum_buy: self.sum_buy + other.sum_buy,
      sum_buy_dest: self.sum_buy_dest + other.sum_buy_dest,
      num_sell: self.num_sell + other.num_sell,
      num_buy: self.num_buy + other.num_buy,
    }
  }
}

impl<'a> ops::Add<&'a Deal> for TradeStats {
  type Output = TradeStats;
  fn add(self, other: &Deal) -> TradeStats {
    let (buy, num_buy, buy_dest, sell, num_sell, sell_dest) =
      if other.amount > 0.0 { (other.amount, 1, other.amount*other.rate, 0.0, 0, 0.0) }
      else                  { (0.0, 0, 0.0, -other.amount, 1, -other.amount*other.rate) };
    TradeStats {
      sum_sell: self.sum_sell + sell,
      sum_sell_dest: self.sum_sell_dest + sell_dest,
      sum_buy: self.sum_buy + buy,
      sum_buy_dest: self.sum_buy_dest + buy_dest,
      num_sell: self.num_sell + num_sell,
      num_buy: self.num_buy + num_buy,
    }
  }
}

impl<'a> ops::Sub<&'a TradeStats> for TradeStats {
  type Output = TradeStats;
  fn sub(self, other: &TradeStats) -> TradeStats {
    TradeStats {
      sum_sell: self.sum_sell - other.sum_sell,
      sum_sell_dest: self.sum_sell_dest - other.sum_sell_dest,
      sum_buy: self.sum_buy - other.sum_buy,
      sum_buy_dest: self.sum_buy_dest - other.sum_buy_dest,
      num_sell: self.num_sell - other.num_sell,
      num_buy: self.num_buy - other.num_buy,
    }
  }
}

impl fmt::Display for TradeStats {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "SELL {} to {} rate {} num {} | BUY {} to {} rate {} num {}",
      self.sum_sell, self.sum_sell_dest, self.sum_sell_dest/self.sum_sell, self.num_sell,
      self.sum_buy, self.sum_buy_dest, self.sum_buy_dest/self.sum_buy, self.num_buy)
  }
}

pub trait TimeStats {
  fn update_stats_1s(&mut self);
}

/**
 ** TESTS TESTS TESTS
 **/

#[cfg(test)]
mod tests {
  use super::TradeStats;
  use ::data::book::Deal;

  #[test]
  fn stats_default() {
    let default = TradeStats::default();
    assert_eq!(default.sum_buy, 0.0);
  }

  #[test]
  fn stats_new() {
    let deal = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deals = vec![&deal];
    let stats = TradeStats::new(deals);
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_add_deal() {
    let deal = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let stats = TradeStats::default() + &deal;
    assert_eq!(stats.sum_buy, 10.0);
  }

  #[test]
  fn stats_deals() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats = TradeStats::new(vec![&deal1, &deal2]);
    assert_eq!((stats.sum_buy, stats.num_buy, stats.sum_buy_dest), (10.0, 1, 1.0));
    assert_eq!((stats.sum_sell, stats.num_sell, stats.sum_sell_dest), (10.0, 1, 1.0));
  }

  #[test]
  fn stats_sub() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(vec![&deal1, &deal2]);
    let stats2 = TradeStats::new(vec![&deal2]);
    let stats = stats1 - &stats2;
    assert_eq!((stats.sum_buy, stats.num_buy), (10.0, 1));
    assert_eq!((stats.sum_sell, stats.num_sell), (0.0, 0));
  }

  #[test]
  fn stats_sub_exact() {
    let deal1 = Deal { id: 1, rate: 0.1, amount: 10.0 };
    let deal2 = Deal { id: 2, rate: 0.1, amount: -10.0 };
    let stats1 = TradeStats::new(vec![&deal1, &deal2]);
    let stats2 = stats1.clone();
    let stats = stats1 - &stats2;
    assert_eq!(stats, TradeStats::default());
  }
}<|endoftext|>


<commit_before>extern crate tempfile;

use std::fmt::{ Display, Formatter, Error };
use std::iter::Iterator;
use std::collections::HashMap;
use std::collections::HashSet;
use std::vec::Vec;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use std::clone::Clone;

/**
 * test can be deleted.
 * clauses will house all clauses, key is int so that we can use occurrences
 * ID for simplifications later
 * occurrences tracks which clauses literals are used in
 */
#[derive(Debug)]
pub struct CNF {
    pub nvar        : i32,
    pub nclause     : i32,
    pub clauses     : HashMap<i32, Vec<i32>>,
    pub occurrences : HashMap<i32, Vec<i32>>,
    pub units       : HashSet<i32>
}

impl CNF {
    pub fn new(nvar: i32, nclause: i32) -> CNF {
        CNF {
            nvar        : nvar,
            nclause     : nclause,
            clauses     : HashMap::new(),
            occurrences : HashMap::new(),
            units       : HashSet::new(),
        }
    }

    /// Add a clause, return the ID of the inserted clause
    /// Right now, this isn't public; api is odd as we have an odd representation of literals.
    /// TODO: Mask this with public function?
    fn add_clause(&mut self, clause: Vec<i32>) -> i32 {
        assert!(clause.len() > 0);
        let id: i32 = self.clauses.len() as i32;
        if clause.len() == 1 { self.units.insert(id); }
        for var in &clause {
            let occ = self.occurrences.entry(*var).or_insert(Vec::new());
            occ.push(id);
        }
        self.clauses.insert(id, clause);
        id
    }

    /// Unit propagation: propagate the literal associated with the clause id `clause`, and remove
    /// it from `self.units`.
    pub fn unit_propagate(&mut self, unit: i32) {
        // Remove clauses with lit and remove lit from occurrences.
        let lit = self.clauses.get(&unit).expect("unit clause not found")[0];
        self.propagate(lit);
        // This needs to be true, i.e. unit clause id needs to be in the unit clauses
        assert!(self.units.remove(&unit));
    }

    /// Remove all clauses containing literal `lit` from the CNF, and remove the negation of `lit`
    /// from the remaining clauses.
    /// TODO: unit_propagate and propagate should return true/false
    /// depending on whether the updated CNF problem is satisfiable
    pub fn propagate(&mut self, lit: i32) {
        // Remove clauses with lit and remove lit from occurrences.
        for occ in &self.occurrences.remove(&lit).unwrap() {
            self.clauses.remove(occ);
        }
    }
}

impl Clone for CNF {
    fn clone(&self) -> CNF {
        CNF {
            nvar        : self.nvar,
            nclause     : self.nclause,
            clauses     : self.clauses.clone(),
            occurrences : self.occurrences.clone(),
            units       : self.units.clone()
        }
    }
}

impl Display for CNF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Nvar: {:?} Nclause: {:?}\nClauses: {:?}\nOccurrrences: {:?}",
                self.nvar, self.nclause,
                self.clauses, self.occurrences);
        write!(f, "{}", formatted)
    }
}

// End CNF

// Begin Assignemnts

pub type Assignment = Vec<bool>;

pub struct PartialAssignment {
    pub assignment : Vec<Option<bool>>,
    pub unassigned : HashSet<i32>
}

impl PartialAssignment {
    pub fn new(n: usize) -> PartialAssignment {
        PartialAssignment {
            assignment : vec!(None; n),
            unassigned : (0..n as i32).collect()
        }
    }

    pub fn assign(&mut self, v: usize, assn: bool) {
        // TODO: Error check
        self.assignment[v] = Some(assn);
    }

    pub fn assign_literal(&mut self, lit: i32){
        let polarity: bool = lit & 1 == 0;
        let v: usize = (lit >> 1) as usize;
        println!("{}", v);
        self.assign(v, polarity);
    }

    pub fn unassign(&mut self, v: usize) {
        self.assignment[v] = None;
    }

    pub fn unassign_literal(&mut self, lit: i32){
        let v: usize = (lit >> 1) as usize;
        self.unassign(v);
    }
}

// TODO: Implement Display
impl Display for PartialAssignment {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Assignemnts: {:?}\nUnassigned: {:?}",
                self.assignment, self.unassigned);
        write!(f, "{}", formatted)
    }
}

// End Assignments

// Begin Parsing

// TODO: rename to from_dimacs or somehow isolate parsing
fn parse_dimacs(reader: &mut BufReader<File>) -> Result<CNF, &'static str> {
    let mut line_iterator = reader.lines();

    let mut nvar: i32 = -1;
    let mut nclause: i32 = -1;
    // DIMACS file must have a problem statement before other lines.
    // This first loop searches for the problem statement.
    for line in &mut line_iterator {
        let line = line.expect("could not read file");  // Unwrap result
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; } // Ignore empty lines
        match words[0] {
            "c" => { }
            "p" => { // Problem statement
                // Must have format "p cnf nvar nclause"
                if words.len() != 4 || words[1] != "cnf" {
                    return Err("invalid problem statement");
                }
                nvar = words[2].parse()
                    .expect(&format!("invalid number of variables {}", words[2]));
                nclause = words[3].parse()
                    .expect(&format!("invalid number of clauses {}", words[3]));
                break;
            }
            // TODO: Add words[0] to this error message
            _ => { return Err("unknown statement beginning"); }
        }
    }
    // Then nvar, nclause were never initialized
    if nvar == -1 || nclause == -1 {
       return Err("no problem statement found");
    }
    // TODO: Different errors for different descriptions (hence why I've split up this if
    // statement)
    if nvar == 0 || nclause == 0 {
        return Err("invalid number of literals in problem")
    }

    // Initialize CNF and parse the rest of the file
    let mut cnf = CNF::new(nvar, nclause);
    let mut clauses_read: i32 = 0;
    for line in &mut line_iterator {
        let line = line.unwrap();
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; }
        match words[0] {
            "c" => { }
            "p" => { return Err("duplicate problem statement"); }
            _   => {
                clauses_read = clauses_read + 1;
                if clauses_read > nclause { return Err("too many clauses in file"); }
                let tokens: Vec<i32> = words.iter()
                    .filter_map(|s| {
                        let n = s.parse::<i32>().unwrap();
                        // FIXME: This ignores zeros not just as line enders but in the formulas
                        // themselves. Split on zeros at the end here.
                        if n == 0 { return None; }
                        // FIXME: This should return an error instead of
                        // panicking, but I can't return an error
                        // in a closure
                        if n > nvar { panic!("variable out of range: {}", n); }
                        Some(if n < 0 { (-n) << 1 | 1 } else { n << 1 })
                    })
                    .collect();
                cnf.add_clause(tokens);
            }
        }
    }
    // Double check that the number of clauses read is equal
    if clauses_read != nclause { return Err("too few clauses in file"); }
    Ok(cnf)
}

pub fn parse_dimacs_file(f: File) -> Result<CNF, &'static str> {
    // Read the file
    let mut reader = BufReader::new(f);

    // TODO: This is definitely not the correct way to handle errors.
    // Should parse_dimacs have options for returning an error AND panicking?
    let line = parse_dimacs(&mut reader);
    line
}

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::SeekFrom;

    use super::parse_dimacs_file;

    macro_rules! create_tempfile {
        ($x: expr) => {{
            let mut tmpfile: File = tempfile::tempfile().unwrap();
            let _ = write!(tmpfile, $x);
            tmpfile.seek(SeekFrom::Start(0)).unwrap();

            tmpfile
        }};
    }

    #[test]
    #[should_panic(expected = "out of range")]
    fn variable_out_of_range() {
        let tmpfile = create_tempfile!("
            p cnf 2 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nvar() {
        let tmpfile = create_tempfile!("
            p cnf gd 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nclause() {
        let tmpfile = create_tempfile!("
            p cnf 2 gdd
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too many")]
    fn too_many_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
            4 5 0
            1 3 0
            2 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too few")]
    fn too_little_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_work() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_ignore_comments() {
        let tmpfile = create_tempfile!("
            c comment
            p cnf 3 3
            c comment
            1 2 0
            2 3 0
            c comment
            1 -3 0
            c comment
            c comment
            c comment
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            p cnf 3 3
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement_2() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn adds_unit_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 3 4
            1 0
            2 0
            3 0
            -1 -3 0
        ");
        let cnf = parse_dimacs_file(tmpfile).unwrap();
        assert_eq!(cnf.units.len(), 3);
    }

    // TODO: Make this doc test (with unit propagate); create_tempfile may need to be an importable
    // macro up there
    #[test]
    fn unit_propagate_works() {
        let tmpfile = create_tempfile!("
            p cnf 2 2
            1 0
            1 2 0
        ");
        let mut cnf = parse_dimacs_file(tmpfile).unwrap();
        cnf.unit_propagate(0);
        assert!(cnf.units.is_empty());
    }

    #[test]
    fn unit_propagate_works_2() {
        let tmpfile = create_tempfile!("
            p cnf 4 4
            1 0
            1 2 0
            2 3 0
            4 0
        ");
        let mut cnf = parse_dimacs_file(tmpfile).unwrap();
        cnf.unit_propagate(0);
        // Only one unit clause left
        assert_eq!(cnf.units.len(), 1);
        cnf.unit_propagate(3);
        // No more unit clauses
        assert!(cnf.units.is_empty());
    }

    #[test]
    #[should_panic(expected = "unit clause not found")]
    fn unit_clause_not_found() {
        let tmpfile = create_tempfile!("
            p cnf 2 2
            1 0
            1 2 0
        ");
        let mut cnf = parse_dimacs_file(tmpfile).unwrap();
        cnf.unit_propagate(2);
    }
}
<commit_msg>Increment/decrement assign literals<commit_after>extern crate tempfile;

use std::fmt::{ Display, Formatter, Error };
use std::iter::Iterator;
use std::collections::HashMap;
use std::collections::HashSet;
use std::vec::Vec;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use std::clone::Clone;

/**
 * test can be deleted.
 * clauses will house all clauses, key is int so that we can use occurrences
 * ID for simplifications later
 * occurrences tracks which clauses literals are used in
 */
#[derive(Debug)]
pub struct CNF {
    pub nvar        : i32,
    pub nclause     : i32,
    pub clauses     : HashMap<i32, Vec<i32>>,
    pub occurrences : HashMap<i32, Vec<i32>>,
    pub units       : HashSet<i32>
}

impl CNF {
    pub fn new(nvar: i32, nclause: i32) -> CNF {
        CNF {
            nvar        : nvar,
            nclause     : nclause,
            clauses     : HashMap::new(),
            occurrences : HashMap::new(),
            units       : HashSet::new(),
        }
    }

    /// Add a clause, return the ID of the inserted clause
    /// Right now, this isn't public; api is odd as we have an odd representation of literals.
    /// TODO: Mask this with public function?
    fn add_clause(&mut self, clause: Vec<i32>) -> i32 {
        assert!(clause.len() > 0);
        let id: i32 = self.clauses.len() as i32;
        if clause.len() == 1 { self.units.insert(id); }
        for var in &clause {
            let occ = self.occurrences.entry(*var).or_insert(Vec::new());
            occ.push(id);
        }
        self.clauses.insert(id, clause);
        id
    }

    /// Unit propagation: propagate the literal associated with the clause id `clause`, and remove
    /// it from `self.units`.
    pub fn unit_propagate(&mut self, unit: i32) {
        // Remove clauses with lit and remove lit from occurrences.
        let lit = self.clauses.get(&unit).expect("unit clause not found")[0];
        self.propagate(lit);
        // This needs to be true, i.e. unit clause id needs to be in the unit clauses
        assert!(self.units.remove(&unit));
    }

    /// Remove all clauses containing literal `lit` from the CNF, and remove the negation of `lit`
    /// from the remaining clauses.
    /// TODO: unit_propagate and propagate should return true/false
    /// depending on whether the updated CNF problem is satisfiable
    pub fn propagate(&mut self, lit: i32) {
        // Remove clauses with lit and remove lit from occurrences.
        for occ in &self.occurrences.remove(&lit).unwrap() {
            self.clauses.remove(occ);
        }
    }
}

impl Clone for CNF {
    fn clone(&self) -> CNF {
        CNF {
            nvar        : self.nvar,
            nclause     : self.nclause,
            clauses     : self.clauses.clone(),
            occurrences : self.occurrences.clone(),
            units       : self.units.clone()
        }
    }
}

impl Display for CNF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Nvar: {:?} Nclause: {:?}\nClauses: {:?}\nOccurrrences: {:?}",
                self.nvar, self.nclause,
                self.clauses, self.occurrences);
        write!(f, "{}", formatted)
    }
}

// End CNF

// Begin Assignemnts

pub type Assignment = Vec<bool>;

pub struct PartialAssignment {
    pub assignment : Vec<Option<bool>>,
    pub unassigned : HashSet<i32>
}

impl PartialAssignment {
    pub fn new(n: usize) -> PartialAssignment {
        PartialAssignment {
            assignment : vec!(None; n),
            unassigned : (0..n as i32).collect()
        }
    }

    fn assign(&mut self, v: usize, assn: bool) {
        // TODO: Error check
        self.assignment[v] = Some(assn);
    }

    pub fn assign_literal(&mut self, lit: i32){
        let polarity: bool = lit & 1 == 0;
        let v: usize = (lit >> 1) as usize;
        self.assign(v - 1, polarity);
    }

    fn unassign(&mut self, v: usize) {
        self.assignment[v] = None;
    }

    pub fn unassign_literal(&mut self, lit: i32){
        let v: usize = (lit >> 1) as usize;
        self.unassign(v - 1);
    }
}

// TODO: Implement Display
impl Display for PartialAssignment {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Assignemnts: {:?}\nUnassigned: {:?}",
                self.assignment, self.unassigned);
        write!(f, "{}", formatted)
    }
}

// End Assignments

// Begin Parsing

// TODO: rename to from_dimacs or somehow isolate parsing
fn parse_dimacs(reader: &mut BufReader<File>) -> Result<CNF, &'static str> {
    let mut line_iterator = reader.lines();

    let mut nvar: i32 = -1;
    let mut nclause: i32 = -1;
    // DIMACS file must have a problem statement before other lines.
    // This first loop searches for the problem statement.
    for line in &mut line_iterator {
        let line = line.expect("could not read file");  // Unwrap result
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; } // Ignore empty lines
        match words[0] {
            "c" => { }
            "p" => { // Problem statement
                // Must have format "p cnf nvar nclause"
                if words.len() != 4 || words[1] != "cnf" {
                    return Err("invalid problem statement");
                }
                nvar = words[2].parse()
                    .expect(&format!("invalid number of variables {}", words[2]));
                nclause = words[3].parse()
                    .expect(&format!("invalid number of clauses {}", words[3]));
                break;
            }
            // TODO: Add words[0] to this error message
            _ => { return Err("unknown statement beginning"); }
        }
    }
    // Then nvar, nclause were never initialized
    if nvar == -1 || nclause == -1 {
       return Err("no problem statement found");
    }
    // TODO: Different errors for different descriptions (hence why I've split up this if
    // statement)
    if nvar == 0 || nclause == 0 {
        return Err("invalid number of literals in problem")
    }

    // Initialize CNF and parse the rest of the file
    let mut cnf = CNF::new(nvar, nclause);
    let mut clauses_read: i32 = 0;
    for line in &mut line_iterator {
        let line = line.unwrap();
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; }
        match words[0] {
            "c" => { }
            "p" => { return Err("duplicate problem statement"); }
            _   => {
                clauses_read = clauses_read + 1;
                if clauses_read > nclause { return Err("too many clauses in file"); }
                let tokens: Vec<i32> = words.iter()
                    .filter_map(|s| {
                        let n = s.parse::<i32>().unwrap();
                        // FIXME: This ignores zeros not just as line enders but in the formulas
                        // themselves. Split on zeros at the end here.
                        if n == 0 { return None; }
                        // FIXME: This should return an error instead of
                        // panicking, but I can't return an error
                        // in a closure
                        if n > nvar { panic!("variable out of range: {}", n); }
                        Some(if n < 0 { (-n) << 1 | 1 } else { n << 1 })
                    })
                    .collect();
                cnf.add_clause(tokens);
            }
        }
    }
    // Double check that the number of clauses read is equal
    if clauses_read != nclause { return Err("too few clauses in file"); }
    Ok(cnf)
}

pub fn parse_dimacs_file(f: File) -> Result<CNF, &'static str> {
    // Read the file
    let mut reader = BufReader::new(f);

    // TODO: This is definitely not the correct way to handle errors.
    // Should parse_dimacs have options for returning an error AND panicking?
    let line = parse_dimacs(&mut reader);
    line
}

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::SeekFrom;

    use super::parse_dimacs_file;

    macro_rules! create_tempfile {
        ($x: expr) => {{
            let mut tmpfile: File = tempfile::tempfile().unwrap();
            let _ = write!(tmpfile, $x);
            tmpfile.seek(SeekFrom::Start(0)).unwrap();

            tmpfile
        }};
    }

    #[test]
    #[should_panic(expected = "out of range")]
    fn variable_out_of_range() {
        let tmpfile = create_tempfile!("
            p cnf 2 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nvar() {
        let tmpfile = create_tempfile!("
            p cnf gd 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nclause() {
        let tmpfile = create_tempfile!("
            p cnf 2 gdd
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too many")]
    fn too_many_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
            4 5 0
            1 3 0
            2 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too few")]
    fn too_little_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_work() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_ignore_comments() {
        let tmpfile = create_tempfile!("
            c comment
            p cnf 3 3
            c comment
            1 2 0
            2 3 0
            c comment
            1 -3 0
            c comment
            c comment
            c comment
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            p cnf 3 3
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement_2() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn adds_unit_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 3 4
            1 0
            2 0
            3 0
            -1 -3 0
        ");
        let cnf = parse_dimacs_file(tmpfile).unwrap();
        assert_eq!(cnf.units.len(), 3);
    }

    // TODO: Make this doc test (with unit propagate); create_tempfile may need to be an importable
    // macro up there
    #[test]
    fn unit_propagate_works() {
        let tmpfile = create_tempfile!("
            p cnf 2 2
            1 0
            1 2 0
        ");
        let mut cnf = parse_dimacs_file(tmpfile).unwrap();
        cnf.unit_propagate(0);
        assert!(cnf.units.is_empty());
    }

    #[test]
    fn unit_propagate_works_2() {
        let tmpfile = create_tempfile!("
            p cnf 4 4
            1 0
            1 2 0
            2 3 0
            4 0
        ");
        let mut cnf = parse_dimacs_file(tmpfile).unwrap();
        cnf.unit_propagate(0);
        // Only one unit clause left
        assert_eq!(cnf.units.len(), 1);
        cnf.unit_propagate(3);
        // No more unit clauses
        assert!(cnf.units.is_empty());
    }

    #[test]
    #[should_panic(expected = "unit clause not found")]
    fn unit_clause_not_found() {
        let tmpfile = create_tempfile!("
            p cnf 2 2
            1 0
            1 2 0
        ");
        let mut cnf = parse_dimacs_file(tmpfile).unwrap();
        cnf.unit_propagate(2);
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::env;
use std::ffi::OsStr;

use clap::{App, Arg, ArgMatches};
use console::style;

use prelude::*;
use api::{Api, NewRelease};
use config::Config;
use utils::{ArgExt, SourceMapProcessor, get_codepush_package, get_codepush_release};

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("Upload react-native projects for CodePush.")
        .org_project_args()
        .arg(Arg::with_name("deployment")
            .long("deployment")
            .value_name("DEPLOYMENT")
            .help("The name of the deployment. [Production, Staging]"))
        .arg(Arg::with_name("bundle_id")
            .value_name("BUNDLE_ID")
            .long("bundle-id")
            .help("Explicitly provide the bundle ID instead of \
                   parsing the source projects.  This allows you to push \
                   codepush releases for iOS on platforms without Xcode."))
        .arg(Arg::with_name("print_release_name")
            .long("print-release-name")
            .help("Print the release name instead."))
        .arg(Arg::with_name("app_name")
            .value_name("APP_NAME")
            .index(1)
            .required(true)
            .help("The name of the CodePush application."))
        .arg(Arg::with_name("platform")
            .value_name("PLATFORM")
            .index(2)
            .required(true)
            .help("The name of the CodePush platform. [ios, android]"))
        .arg(Arg::with_name("paths")
            .value_name("PATH")
            .index(3)
            .required(true)
            .multiple(true)
            .help("A list of folders with assets that should be processed."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    let here = env::current_dir()?;
    let here_str: &str = &here.to_string_lossy();
    let (org, project) = config.get_org_and_project(matches)?;
    let app = matches.value_of("app_name").unwrap();
    let platform = matches.value_of("platform").unwrap();
    let deployment = matches.value_of("deployment").unwrap_or("Staging");
    let api = Api::new(config);
    let print_release_name = matches.is_present("print_release_name");

    if !print_release_name {
        println!("{} Fetching latest code-push package info", style(">").dim());
    }

    let package = get_codepush_package(app, deployment)?;
    let release = get_codepush_release(&package, platform, matches.value_of("bundle_id"))?;
    if print_release_name {
        println!("{}", release);
        return Ok(());
    }

    println!("{} Processing react-native code-push sourcemaps",
             style(">").dim());

    let mut processor = SourceMapProcessor::new();
    for path in matches.values_of("paths").unwrap() {
        for entry in fs::read_dir(path)? {
            if_chain! {
                if let Ok(entry) = entry;
                if let Some(filename) = entry.file_name().to_str();
                if let Some(ext) = entry.path().extension();
                if ext == OsStr::new("jsbundle") ||
                   ext == OsStr::new("map") ||
                   ext == OsStr::new("bundle");
                then {
                    let url = format!("~/{}", filename);
                    processor.add(&url, &entry.path())?;
                }
            }
        }
    }

    processor.rewrite(&vec![here_str])?;
    processor.add_sourcemap_references()?;

    let release = api.new_release(&org, &NewRelease {
        version: release.to_string(),
        projects: vec![project.to_string()],
        ..Default::default()
    })?;
    processor.upload(&api, &org, Some(&project), &release.version, None)?;

    Ok(())
}
<commit_msg>docs: Improve bundle ID docs for codepush.  Refs #143 (#148)<commit_after>use std::fs;
use std::env;
use std::ffi::OsStr;

use clap::{App, Arg, ArgMatches};
use console::style;

use prelude::*;
use api::{Api, NewRelease};
use config::Config;
use utils::{ArgExt, SourceMapProcessor, get_codepush_package, get_codepush_release};

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("Upload react-native projects for CodePush.")
        .org_project_args()
        .arg(Arg::with_name("deployment")
            .long("deployment")
            .value_name("DEPLOYMENT")
            .help("The name of the deployment. [Production, Staging]"))
        .arg(Arg::with_name("bundle_id")
            .value_name("BUNDLE_ID")
            .long("bundle-id")
            .help("Explicitly provide the bundle ID instead of \
                   parsing the source projects.  This allows you to push \
                   codepush releases for iOS on platforms without Xcode or \
                   codepush releases for Android when you use different \
                   bundle IDs for release and debug etc."))
        .arg(Arg::with_name("print_release_name")
            .long("print-release-name")
            .help("Print the release name instead."))
        .arg(Arg::with_name("app_name")
            .value_name("APP_NAME")
            .index(1)
            .required(true)
            .help("The name of the CodePush application."))
        .arg(Arg::with_name("platform")
            .value_name("PLATFORM")
            .index(2)
            .required(true)
            .help("The name of the CodePush platform. [ios, android]"))
        .arg(Arg::with_name("paths")
            .value_name("PATH")
            .index(3)
            .required(true)
            .multiple(true)
            .help("A list of folders with assets that should be processed."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    let here = env::current_dir()?;
    let here_str: &str = &here.to_string_lossy();
    let (org, project) = config.get_org_and_project(matches)?;
    let app = matches.value_of("app_name").unwrap();
    let platform = matches.value_of("platform").unwrap();
    let deployment = matches.value_of("deployment").unwrap_or("Staging");
    let api = Api::new(config);
    let print_release_name = matches.is_present("print_release_name");

    if !print_release_name {
        println!("{} Fetching latest code-push package info", style(">").dim());
    }

    let package = get_codepush_package(app, deployment)?;
    let release = get_codepush_release(&package, platform, matches.value_of("bundle_id"))?;
    if print_release_name {
        println!("{}", release);
        return Ok(());
    }

    println!("{} Processing react-native code-push sourcemaps",
             style(">").dim());

    let mut processor = SourceMapProcessor::new();
    for path in matches.values_of("paths").unwrap() {
        for entry in fs::read_dir(path)? {
            if_chain! {
                if let Ok(entry) = entry;
                if let Some(filename) = entry.file_name().to_str();
                if let Some(ext) = entry.path().extension();
                if ext == OsStr::new("jsbundle") ||
                   ext == OsStr::new("map") ||
                   ext == OsStr::new("bundle");
                then {
                    let url = format!("~/{}", filename);
                    processor.add(&url, &entry.path())?;
                }
            }
        }
    }

    processor.rewrite(&vec![here_str])?;
    processor.add_sourcemap_references()?;

    let release = api.new_release(&org, &NewRelease {
        version: release.to_string(),
        projects: vec![project.to_string()],
        ..Default::default()
    })?;
    processor.upload(&api, &org, Some(&project), &release.version, None)?;

    Ok(())
}
<|endoftext|>


<commit_before>#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];

extern crate getopts;

use std::os;
use std::cast::transmute;
use std::io::{print,File};
use std::libc::{time_t,c_double,c_int,size_t,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts));
        return;
    }

    print_time();
    print_uptime();
    print_nusers();
    print_loadavg();
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2f}{}", avg[n], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn print_nusers() {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                nusers += 1;
            }
        }

        endutxent();
    }

    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime() -> int {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return -1
    };

    match uptime_text.words().next() {
        Some(s) => match from_str(s.replace(".","")) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime() {
    let uptime = get_uptime() / 100;
    let updays = uptime / 86400;
    let uphours = (uptime - (updays * 86400)) / 3600;
    let upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<commit_msg>Remove unused import.<commit_after>#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];

extern crate getopts;

use std::os;
use std::cast::transmute;
use std::io::{print,File};
use std::libc::{time_t,c_double,c_int,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts));
        return;
    }

    print_time();
    print_uptime();
    print_nusers();
    print_loadavg();
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2f}{}", avg[n], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn print_nusers() {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                nusers += 1;
            }
        }

        endutxent();
    }

    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime() -> int {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return -1
    };

    match uptime_text.words().next() {
        Some(s) => match from_str(s.replace(".","")) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime() {
    let uptime = get_uptime() / 100;
    let updays = uptime / 86400;
    let uphours = (uptime - (updays * 86400)) / 3600;
    let upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<|endoftext|>