<commit_before>use std::old_io::File;
use std::old_io::BufferedReader;

use racer;
use racer::util;
use racer::codecleaner;
use racer::codeiter;
use racer::typeinf;
use racer::ast;

pub fn find_closing_paren(src:&str, mut pos:usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0] as u8;
    let closeparen: u8 = ")".as_bytes()[0] as u8;
    let src_bytes = src.as_bytes();

    let mut levels = 0i32;
    loop {
        if src_bytes[pos] == closeparen {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if src_bytes[pos] == openparen {
            levels += 1;
        }
        pos += 1;
    }
    return pos;
}

pub fn scope_start(src:&str, point:usize) -> usize {
    let masked_src = mask_comments(src);
    let s = &masked_src[..point];
    let mut pt = point;
    let mut levels = 0i32;
    for c in s.chars().rev() {
        if c == '{' {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if c == '}' {
            levels += 1;
        }
        pt -= 1;
    }
    return pt;
}

pub fn find_stmt_start(msrc: &str, point: usize) -> Option<usize> {
    // iterate the scope to find the start of the statement
    let scopestart = scope_start(msrc, point);
    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            return Some(scopestart+start);
        }
    }
    return None;
}

pub fn get_local_module_path(msrc: &str, point: usize) -> Vec<String> {
    let mut v = Vec::new();
    get_local_module_path_(msrc, point, &mut v);
    return v;
}

fn get_local_module_path_(msrc: &str, point: usize, out: &mut Vec<String>) {
    for (start, end) in codeiter::iter_stmts(msrc) {
        if start < point && end > point {
            let blob = &msrc[start..end];
            if blob.starts_with("pub mod "){
                let p = typeinf::generate_skeleton_for_parsing(blob);
                ast::parse_mod(p).name.map(|name|{

                    let newstart = blob.find_str("{").unwrap() + 1;
                    out.push(name);
                    get_local_module_path_(&blob[newstart..],
                                       point - start - newstart, out);
                });
            }
        }
    }
}

pub fn find_impl_start(msrc: &str, point: usize, scopestart: usize) -> Option<usize> {

    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            let blob = &msrc[(scopestart + start)..];
            // TODO:: the following is a bit weak at matching traits. make this better
            if blob.starts_with("impl") ||
                blob.starts_with("trait") || blob.starts_with("pub trait") {
                return Some(scopestart + start);
            } else {
                let newstart = blob.find_str("{").unwrap() + 1;
                return find_impl_start(msrc, point, scopestart+start+newstart);
            }
        }
    }
    return None;
}

#[test]
fn finds_subnested_module() {
    let src = "
    pub mod foo {
        pub mod bar {
            here
        }
    }";
    let point = coords_to_point(src, 4, 12);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
    assert_eq!("bar", &v[1][]);

    let point = coords_to_point(src, 2, 8);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
}

pub fn split_into_context_and_completion<'a>(s: &'a str) -> (&'a str, &'a str, racer::CompletionType) {

    let mut start = 0;
    let s_bytes = s.as_bytes();
    let colon: u8 = ":".as_bytes()[0];
    let dot: u8 = ".".as_bytes()[0];

    for (i, c) in s.char_indices().rev() {
        if ! util::is_ident_char(c) {
            start = i+1;
            break;
        }
    }

    if start != 0 && s_bytes[start-1] == dot {    // field completion
        return (&s[..(start-1)], &s[start..], racer::CompletionType::CompleteField);
    }

    if start > 0 && s_bytes[start-1] == colon {  // path completion
        return (&s[..(start-2)], &s[start..], racer::CompletionType::CompletePath);
    }

    (&s[..start], &s[start..], racer::CompletionType::CompletePath)
}

pub fn get_start_of_search_expr(msrc: &str, point: usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0];
    let closeparen: u8 = ")".as_bytes()[0];
    let msrc_bytes = msrc.as_bytes();
    let mut levels = 0i32;
    let mut i = point-1;
    loop {
        if i == -1 {
            i = 0;
            break;
        }

        if msrc_bytes[i] == closeparen {
            levels += 1;
        }
        if levels == 0 && (!util::is_search_expr_char(msrc.char_at(i)) ||
                           util::is_double_dot(msrc,i)) {
            i += 1;
            break;
        }
        if msrc_bytes[i] == openparen && levels > 0 {
            levels -= 1;
        }

        i -= 1;
    }
    return i;
}

pub fn get_start_of_pattern(msrc: &str, point: usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0];
    let closeparen: u8 = ")".as_bytes()[0];
    let msrc_bytes = msrc.as_bytes();
    let mut levels = 0i32;
    let mut i = point-1;
    loop {
        if i == -1 {
            i = 0;
            break;
        }

        if msrc_bytes[i] == closeparen {
            levels += 1;
        }
        if levels == 0 && !util::is_pattern_char(msrc.char_at(i)) {
            i += 1;
            break;
        }
        if msrc_bytes[i] == openparen && levels > 0 {
            levels -= 1;
        }

        i -= 1;
    }
    return i;
}

#[test]
fn get_start_of_pattern_handles_variant() {
    assert_eq!(4, get_start_of_pattern("foo, Some(a) =>",13));
}

#[test]
fn get_start_of_pattern_handles_variant2() {
    assert_eq!(4, get_start_of_pattern("bla, ast::PatTup(ref tuple_elements) => {",36));
}

pub fn expand_search_expr(msrc: &str, point: usize) -> (usize,usize) {
    let start = get_start_of_search_expr(msrc, point);
    return (start, util::find_ident_end(msrc, point));
}

#[test]
fn expand_search_expr_finds_ident() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 5))
}

#[test]
fn expand_search_expr_handles_chained_calls() {
    assert_eq!((0, 20), expand_search_expr("yeah::blah.foo().bar", 18))
}

#[test]
fn expand_search_expr_handles_inline_closures() {
    assert_eq!((0, 24), expand_search_expr("yeah::blah.foo(||{}).bar", 22))
}
#[test]
fn expand_search_expr_handles_a_function_arg() {
    assert_eq!((5, 25), expand_search_expr("myfn(foo::new().baz().com)", 23))
}

#[test]
fn expand_search_expr_handles_pos_at_end_of_search_str() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 7))
}

pub fn mask_comments(src: &str) -> String {
    let mut result = String::new();
    let space = " ";

    let mut prev: usize = 0;
    for (start, end) in codecleaner::code_chunks(src) {
        for _ in ::std::iter::range(prev, start) {
            result.push_str(space);
        }
        result.push_str(&src[start..end]);
        prev = end;
    }
    return result;
}

pub fn mask_sub_scopes(src:&str) -> String {
    let mut result = String::new();
    let mut levels = 0i32;

    for c in src.chars() {
        if c == '}' {
            levels -= 1;
        }

        if c == '\n' {
            result.push(c);
        } else if levels > 0 {
            result.push(' ');
        } else {
            result.push(c);
        }

        if c == '{' {
            levels += 1;
        }
    }
    return result;
}

pub fn end_of_next_scope<'a>(src: &'a str) -> &'a str {
    let mut level = 0i32;
    let mut end = 0;
    for (i,c) in src.char_indices() {
        if c == '}' {
            level -= 1;
            if level == 0 {
                end = i + 1;
                break;
            }
        } else if c == '{' {
            level += 1;
        }
    }
    &src[..end]
}

pub fn coords_to_point(src: &str, mut linenum: usize, col: usize) -> usize {
    let mut point=0;
    for line in src.lines() {
        linenum -= 1;
        if linenum == 0 { break }
        point+=line.len() + 1;  // +1 for the \n
    }
    return point + col;
}

pub fn point_to_coords(src:&str, point:usize) -> (usize, usize) {
    let mut i = 0;
    let mut linestart = 0;
    let mut nlines = 1;  // lines start at 1
    while i != point {
        if src.char_at(i) == '\n' {
            nlines += 1;
            linestart = i+1;
        }
        i+=1;
    }
    return (nlines, point - linestart);
}

pub fn point_to_coords_from_file(path: &Path, point:usize) -> Option<(usize, usize)> {
    let mut lineno = 0;
    let mut file = BufferedReader::new(File::open(path));
    let mut p = 0;
    for line_r in file.lines() {
        let line = line_r.unwrap();
        lineno += 1;
        if point < (p + line.len()) {
            return Some((lineno, point - p));
        }
        p += line.len();
    }
    return None;
}

#[test]
fn coords_to_point_works() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}";
    assert!(coords_to_point(src, 3, 5) == 18);
}

#[test]
fn test_scope_start() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}
";
    let point = coords_to_point(src, 4, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn test_scope_start_handles_sub_scopes() {
    let src = "
fn myfn() {
    let a = 3;
    {
      let b = 4;
    }
    print(a);
}
";
    let point = coords_to_point(src, 7, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn masks_out_comments() {
    let src = "
this is some code
this is a line // with a comment
some more
";
    let r = mask_comments(src);

    assert!(src.len() == r.len());
    // characters at the start are the same
    assert!(src.as_bytes()[5] == r.as_bytes()[5]);
    // characters in the comments are masked
    let commentoffset = coords_to_point(src,3,23);
    assert!((&r[]).char_at(commentoffset) == ' ');
    assert!(src.as_bytes()[commentoffset] != r.as_bytes()[commentoffset]);
    // characters afterwards are the same
    assert!(src.as_bytes()[src.len()-3] == r.as_bytes()[src.len()-3]);
}

#[test]
fn test_point_to_coords() {
    let src = "
fn myfn(b:usize) {
   let a = 3;
   if b == 12 {
       let a = 24;
       do_something_with(a);
   }
   do_something_with(a);
}
";
    round_trip_point_and_coords(src, 4, 5);
}

pub fn round_trip_point_and_coords(src:&str, lineno:usize, charno:usize) {
    let (a,b) = point_to_coords(src, coords_to_point(src, lineno, charno));
     assert_eq!((a,b),(lineno,charno));
}

#[test]
fn finds_end_of_struct_scope() {
    let src="
struct foo {
   a: usize,
   blah: ~str
}
Some other junk";

    let expected="
struct foo {
   a: usize,
   blah: ~str
}";
    let s = end_of_next_scope(src);
    assert_eq!(expected, s);
}

<commit_msg>Review scopes.rs<commit_after>use std::old_io::{File, BufferedReader};
use std::str::from_utf8;
use std::iter::Iterator;

use racer;
use racer::util;
use racer::codecleaner;
use racer::codeiter;
use racer::typeinf;
use racer::ast;

fn find_close<'a, A>(mut iter: A, open: u8, close: u8, level_end: u32) -> Option<usize>
    where A: Iterator<Item=&'a u8> {

    let mut count = 0us;
    let mut levels = 0u32;
    for &b in iter {
        if b == close {
            if levels == level_end { return Some(count); }
            levels -= 1;
        } else if b == open { levels += 1; }
        count += 1;
    }
    None
}

pub fn find_closing_paren(src:&str, pos:usize) -> usize {
    match find_close(src.as_bytes()[pos..].iter(), b'(', b')', 0) {
        Some(count) => pos + count,
        None => src.len()
    }
}

pub fn scope_start(src:&str, point:usize) -> usize {
    let masked_src = mask_comments(&src[..point]);
    match find_close(masked_src.as_bytes().iter().rev(), b'}', b'{', 0) {
        Some(count) => point - count,
        None => 0
    }
}

pub fn find_stmt_start(msrc: &str, point: usize) -> Option<usize> {
    // iterate the scope to find the start of the statement
    let scopestart = scope_start(msrc, point);
    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            return Some(scopestart+start);
        }
    }
    None
}

pub fn get_local_module_path(msrc: &str, point: usize) -> Vec<String> {
    let mut v = Vec::new();
    get_local_module_path_(msrc, point, &mut v);
    v
}

fn get_local_module_path_(msrc: &str, point: usize, out: &mut Vec<String>) {
    for (start, end) in codeiter::iter_stmts(msrc) {
        if start < point && end > point {
            let blob = &msrc[start..end];
            if blob.starts_with("pub mod "){
                let p = typeinf::generate_skeleton_for_parsing(blob);
                ast::parse_mod(p).name.map(|name|{

                    let newstart = blob.find_str("{").unwrap() + 1;
                    out.push(name);
                    get_local_module_path_(&blob[newstart..],
                                       point - start - newstart, out);
                });
            }
        }
    }
}

pub fn find_impl_start(msrc: &str, point: usize, scopestart: usize) -> Option<usize> {

    let len = point-scopestart;
    match codeiter::iter_stmts(&msrc[scopestart..]).find(|&(_, end)| end > len) {
        Some((start, _)) => {
            let blob = &msrc[(scopestart + start)..];
            // TODO:: the following is a bit weak at matching traits. make this better
            if blob.starts_with("impl") ||
                blob.starts_with("trait") || blob.starts_with("pub trait") {
                Some(scopestart + start)
            } else {
                let newstart = blob.find_str("{").unwrap() + 1;
                find_impl_start(msrc, point, scopestart+start+newstart)
            }
        },
        None => None
    }
}

#[test]
fn finds_subnested_module() {
    let src = "
    pub mod foo {
        pub mod bar {
            here
        }
    }";
    let point = coords_to_point(src, 4, 12);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
    assert_eq!("bar", &v[1][]);

    let point = coords_to_point(src, 2, 8);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
}

pub fn split_into_context_and_completion<'a>(s: &'a str) -> (&'a str, &'a str, racer::CompletionType) {

    match s.char_indices().rev().find(|&(i, c)| !util::is_ident_char(c)) {
        Some((i,c)) => {
            match c {
                '.' => (&s[..i], &s[(i+1)..], racer::CompletionType::CompleteField),
                ':' => (&s[..(i-1)], &s[(i+1)..], racer::CompletionType::CompletePath),
                _   => (&s[..(i+1)], &s[(i+1)..], racer::CompletionType::CompletePath)
            }
        },
        None => ("", s, racer::CompletionType::CompletePath)
    }

}

pub fn get_start_of_search_expr(src: &str, point: usize) -> usize {

    let mut i = point-1;
    let mut levels = 0u32;
    for &b in src.as_bytes()[..point].iter().rev() {
        match b {
            b'(' => {
                if levels == 0 { return i+1; }
                levels -= 1;
            },
            b')' => { levels += 1; },
            _ => {
                if levels == 0 &&
                    !util::is_search_expr_char(src.char_at(i)) ||
                    util::is_double_dot(src,i) {
                    return i+1;
                }
            }
        }
        i -= 1;
    }
    0
}

pub fn get_start_of_pattern(src: &str, point: usize) -> usize {
    let mut i = point-1;
    let mut levels = 0u32;
    for &b in src.as_bytes()[..point].iter().rev() {
        match b {
            b'(' => {
                if levels == 0 { return i+1; }
                levels -= 1;
            },
            b')' => { levels += 1; },
            _ => {
                if levels == 0 &&
                    !util::is_pattern_char(src.char_at(i)) {
                    return i+1;
                }
            }
        }
        i -= 1;
    }
    0
}

#[test]
fn get_start_of_pattern_handles_variant() {
    assert_eq!(4, get_start_of_pattern("foo, Some(a) =>",13));
}

#[test]
fn get_start_of_pattern_handles_variant2() {
    assert_eq!(4, get_start_of_pattern("bla, ast::PatTup(ref tuple_elements) => {",36));
}

pub fn expand_search_expr(msrc: &str, point: usize) -> (usize,usize) {
    let start = get_start_of_search_expr(msrc, point);
    return (start, util::find_ident_end(msrc, point));
}

#[test]
fn expand_search_expr_finds_ident() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 5))
}

#[test]
fn expand_search_expr_handles_chained_calls() {
    assert_eq!((0, 20), expand_search_expr("yeah::blah.foo().bar", 18))
}

#[test]
fn expand_search_expr_handles_inline_closures() {
    assert_eq!((0, 24), expand_search_expr("yeah::blah.foo(||{}).bar", 22))
}
#[test]
fn expand_search_expr_handles_a_function_arg() {
    assert_eq!((5, 25), expand_search_expr("myfn(foo::new().baz().com)", 23))
}

#[test]
fn expand_search_expr_handles_pos_at_end_of_search_str() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 7))
}

pub fn mask_comments(src: &str) -> String {
    let mut result = String::with_capacity(src.len());
    let buf_byte = &[b' '; 128][];
    let buffer = &from_utf8(buf_byte).unwrap()[];
    let mut prev: usize = 0;
    for (start, end) in codecleaner::code_chunks(src) {
        for _ in 0..((start-prev)/128) { result.push_str(buffer); }
        result.push_str(&buffer[..((start-prev)%128)]);
        result.push_str(&src[start..end]);
        prev = end;
    }
    result
}

pub fn mask_sub_scopes(src:&str) -> String {
    let mut result = String::with_capacity(src.len());
    let buf_byte = &[b' '; 128][];
    let buffer = &from_utf8(buf_byte).unwrap()[];
    let mut levels = 0i32;
    let mut start = 0us;
    let mut pos = 0us;

    for &b in src.as_bytes().iter() {
        pos += 1;
        match b {
            b'{' => {
                if levels == 0 {
                    result.push_str(&src[start..(pos-1)]);
                    start = pos;
                }
                levels += 1;
            },
            b'}' => {
                if levels == 1 {
                    for _ in 0..((pos-start)/128) { result.push_str(buffer); }
                    result.push_str(&buffer[..((pos-start)%128)]);
                    start = pos+1;
                }
                levels -= 1;
            },
            b'\n' if levels > 0 => {
                for _ in 0..((pos-start-1)/128) { result.push_str(buffer); }
                result.push_str(&buffer[..((pos-start-1)%128)]);
                result.push('\n');
                start = pos;
            },
            _ => {}
        }
    }
    if levels > 0 {
        for _ in 0..((pos - start)/128) { result.push_str(buffer); }
        result.push_str(&buffer[..((pos-start)%128)]);
    } else {
        result.push_str(&src[start..pos]);
    }
    result
}

pub fn end_of_next_scope<'a>(src: &'a str) -> &'a str {
    match find_close(src.as_bytes().iter(), b'{', b'}', 1) {
        Some(count) => &src[..count+1],
        None => ""
    }
}

pub fn coords_to_point(src: &str, mut linenum: usize, col: usize) -> usize {
    let mut point=0;
    for line in src.lines() {
        linenum -= 1;
        if linenum == 0 { break }
        point+=line.len() + 1;  // +1 for the \n
    }
    point + col
}

pub fn point_to_coords(src:&str, point:usize) -> (usize, usize) {
    let mut i = 0;
    let mut linestart = 0;
    let mut nlines = 1;  // lines start at 1
    for &b in src[..point].as_bytes().iter() {
        i += 1;
        if b == b'\n' {
            nlines += 1;
            linestart = i;
        }
    }
    (nlines, point - linestart)
}

pub fn point_to_coords_from_file(path: &Path, point:usize) -> Option<(usize, usize)> {
    let mut lineno = 0;
    let mut file = BufferedReader::new(File::open(path));
    let mut p = 0;
    for line_r in file.lines() {
        let line = line_r.unwrap();
        lineno += 1;
        if point < (p + line.len()) {
            return Some((lineno, point - p));
        }
        p += line.len();
    }
    None
}

#[test]
fn coords_to_point_works() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}";
    assert!(coords_to_point(src, 3, 5) == 18);
}

#[test]
fn test_scope_start() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}
";
    let point = coords_to_point(src, 4, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn test_scope_start_handles_sub_scopes() {
    let src = "
fn myfn() {
    let a = 3;
    {
      let b = 4;
    }
    print(a);
}
";
    let point = coords_to_point(src, 7, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn masks_out_comments() {
    let src = "
this is some code
this is a line // with a comment
some more
";
    let r = mask_comments(src);

    assert!(src.len() == r.len());
    // characters at the start are the same
    assert!(src.as_bytes()[5] == r.as_bytes()[5]);
    // characters in the comments are masked
    let commentoffset = coords_to_point(src,3,23);
    assert!((&r[]).char_at(commentoffset) == ' ');
    assert!(src.as_bytes()[commentoffset] != r.as_bytes()[commentoffset]);
    // characters afterwards are the same
    assert!(src.as_bytes()[src.len()-3] == r.as_bytes()[src.len()-3]);
}

#[test]
fn test_point_to_coords() {
    let src = "
fn myfn(b:usize) {
   let a = 3;
   if b == 12 {
       let a = 24;
       do_something_with(a);
   }
   do_something_with(a);
}
";
    round_trip_point_and_coords(src, 4, 5);
}

pub fn round_trip_point_and_coords(src:&str, lineno:usize, charno:usize) {
    let (a,b) = point_to_coords(src, coords_to_point(src, lineno, charno));
     assert_eq!((a,b),(lineno,charno));
}

#[test]
fn finds_end_of_struct_scope() {
    let src="
struct foo {
   a: usize,
   blah: ~str
}
Some other junk";

    let expected="
struct foo {
   a: usize,
   blah: ~str
}";
    let s = end_of_next_scope(src);
    assert_eq!(expected, s);
}

<|endoftext|>


<commit_before>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&mut self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&mut self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if event.cycles_remaining > new_event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx + 1;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if self.has_next_event(cycles) {
            let event = self.events.pop_front().unwrap();
            Some((event.callback, cycles - event.cycles_remaining))
        } else {
            None
        }
    }
}
<commit_msg>Fix event scheduling order.<commit_after>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&mut self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&mut self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if new_event.cycles_remaining < event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if self.has_next_event(cycles) {
            let event = self.events.pop_front().unwrap();
            Some((event.callback, cycles - event.cycles_remaining))
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use std::prelude::v1::*;
use std::fmt;
use std::mem;

use task::NotifyContext;

use {Async, IntoFuture, Poll, Future};
use stream::{Stream, Fuse};
use stack::{Stack, Drain};

/// An adaptor for a stream of futures to execute the futures concurrently, if
/// possible, delivering results as they become available.
///
/// This adaptor will buffer up a list of pending futures, and then return their
/// results in the order that they complete. This is created by the
/// `Stream::buffer_unordered` method.
#[must_use = "streams do nothing unless polled"]
pub struct BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture,
{
    stream: Fuse<S>,

    // A slab of futures that are being executed. Each slot in this vector is
    // either an active future or a pointer to the next empty slot. This is used
    // to get O(1) deallocation in the slab and O(1) allocation.
    //
    // The `next_future` field is the next slot in the `futures` array that's a
    // `Slot::Next` variant. If it points to the end of the array then the array
    // is full.
    futures: Vec<Slot<<S::Item as IntoFuture>::Future>>,
    next_future: usize,

    // A list of events that will get pushed onto concurrently by our many
    // futures. This is filled in and used with the `with_unpark_event`
    // function. The `pending` list here is the last time we drained events from
    // our stack.
    stack: NotifyContext<Stack<usize>>,
    pending: Drain<usize>,

    // Number of active futures running in the `futures` slab
    active: usize,
}

impl<S> fmt::Debug for BufferUnordered<S>
    where S: Stream + fmt::Debug,
          S::Item: IntoFuture,
          <<S as Stream>::Item as IntoFuture>::Future: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("BufferUnordered")
            .field("stream", &self.stream)
            .field("futures", &self.futures)
            .field("next_future", &self.next_future)
            .field("stack", &self.stack)
            .field("pending", &self.pending)
            .field("active", &self.active)
            .finish()
    }
}

#[derive(Debug)]
enum Slot<T> {
    Next(usize),
    Data(T),
}

pub fn new<S>(s: S, amt: usize) -> BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture<Error=<S as Stream>::Error>,
{
    BufferUnordered {
        stream: super::fuse::new(s),
        futures: (0..amt).map(|i| Slot::Next(i + 1)).collect(),
        next_future: 0,
        pending: Stack::new().drain(),
        stack: NotifyContext::new(Stack::new()),
        active: 0,
    }
}

impl<S> BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture<Error=<S as Stream>::Error>,
{
    fn poll_pending(&mut self)
                    -> Option<Poll<Option<<S::Item as IntoFuture>::Item>,
                                   S::Error>> {
        while let Some(idx) = self.pending.next() {
            let result = match self.futures[idx] {
                Slot::Data(ref mut f) => {
                    match self.stack.with(idx as u64, || f.poll()) {
                        Ok(Async::NotReady) => continue,
                        Ok(Async::Ready(e)) => Ok(Async::Ready(Some(e))),
                        Err(e) => Err(e),
                    }
                },
                Slot::Next(_) => continue,
            };
            self.active -= 1;
            self.futures[idx] = Slot::Next(self.next_future);
            self.next_future = idx;
            return Some(result)
        }
        None
    }

    /// Acquires a reference to the underlying stream that this combinator is
    /// pulling from.
    pub fn get_ref(&self) -> &S {
        self.stream.get_ref()
    }

    /// Acquires a mutable reference to the underlying stream that this
    /// combinator is pulling from.
    ///
    /// Note that care must be taken to avoid tampering with the state of the
    /// stream which may otherwise confuse this combinator.
    pub fn get_mut(&mut self) -> &mut S {
        self.stream.get_mut()
    }

    /// Consumes this combinator, returning the underlying stream.
    ///
    /// Note that this may discard intermediate state of this combinator, so
    /// care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> S {
        self.stream.into_inner()
    }
}

impl<S> Stream for BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture<Error=<S as Stream>::Error>,
{
    type Item = <S::Item as IntoFuture>::Item;
    type Error = <S as Stream>::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // First up, try to spawn off as many futures as possible by filling up
        // our slab of futures.
        while self.next_future < self.futures.len() {
            let future = match try!(self.stream.poll()) {
                Async::Ready(Some(s)) => s.into_future(),
                Async::Ready(None) |
                Async::NotReady => break,
            };
            self.active += 1;
            self.stack.get_ref().push(self.next_future);
            match mem::replace(&mut self.futures[self.next_future],
                               Slot::Data(future)) {
                Slot::Next(next) => self.next_future = next,
                Slot::Data(_) => panic!(),
            }
        }

        // Next, see if our list of `pending` events from last time has any
        // items, and if so process them here.
        if let Some(ret) = self.poll_pending() {
            return ret
        }

        // And finally, take a look at our stack of events, attempting to
        // process all of those.
        assert!(self.pending.next().is_none());
        self.pending = self.stack.get_ref().drain();
        if let Some(ret) = self.poll_pending() {
            return ret
        }

        // If we've gotten this far then there's no events for us to process and
        // nothing was ready, so figure out if we're not done yet or if we've
        // reached the end.
        Ok(if self.active > 0 || !self.stream.is_done() {
            Async::NotReady
        } else {
            Async::Ready(None)
        })
    }
}

// Forwarding impl of Sink from the underlying stream
impl<S> ::sink::Sink for BufferUnordered<S>
    where S: ::sink::Sink + Stream,
          S::Item: IntoFuture,
{
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: S::SinkItem) -> ::StartSend<S::SinkItem, S::SinkError> {
        self.stream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), S::SinkError> {
        self.stream.poll_complete()
    }

    fn close(&mut self) -> Poll<(), S::SinkError> {
        self.stream.close()
    }
}
<commit_msg>Update BufferUnordered to use ReadyQueue<commit_after>use std::prelude::v1::*;
use std::fmt;

use future::ReadyQueue;

use {Async, IntoFuture, Poll};
use stream::{Stream, Fuse};

/// An adaptor for a stream of futures to execute the futures concurrently, if
/// possible, delivering results as they become available.
///
/// This adaptor will buffer up a list of pending futures, and then return their
/// results in the order that they complete. This is created by the
/// `Stream::buffer_unordered` method.
#[must_use = "streams do nothing unless polled"]
pub struct BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture,
{
    stream: Fuse<S>,

    // Handles "in-flight" futures
    queue: ReadyQueue<<S::Item as IntoFuture>::Future>,

    // Max number of futures
    max: usize,
}

impl<S> fmt::Debug for BufferUnordered<S>
    where S: Stream + fmt::Debug,
          S::Item: IntoFuture,
          <<S as Stream>::Item as IntoFuture>::Future: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("BufferUnordered")
            .field("stream", &self.stream)
            .field("queue", &self.queue)
            .field("max", &self.max)
            .finish()
    }
}

pub fn new<S>(s: S, amt: usize) -> BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture<Error=<S as Stream>::Error>,
{
    BufferUnordered {
        stream: super::fuse::new(s),
        queue: ReadyQueue::new(),
        max: amt,
    }
}

impl<S> BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture<Error=<S as Stream>::Error>,
{
    /// Acquires a reference to the underlying stream that this combinator is
    /// pulling from.
    pub fn get_ref(&self) -> &S {
        self.stream.get_ref()
    }

    /// Acquires a mutable reference to the underlying stream that this
    /// combinator is pulling from.
    ///
    /// Note that care must be taken to avoid tampering with the state of the
    /// stream which may otherwise confuse this combinator.
    pub fn get_mut(&mut self) -> &mut S {
        self.stream.get_mut()
    }

    /// Consumes this combinator, returning the underlying stream.
    ///
    /// Note that this may discard intermediate state of this combinator, so
    /// care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> S {
        self.stream.into_inner()
    }
}

impl<S> Stream for BufferUnordered<S>
    where S: Stream,
          S::Item: IntoFuture<Error=<S as Stream>::Error>,
{
    type Item = <S::Item as IntoFuture>::Item;
    type Error = <S as Stream>::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // First up, try to spawn off as many futures as possible by filling up
        // our slab of futures.
        while self.queue.len() < self.max {
            let future = match try!(self.stream.poll()) {
                Async::Ready(Some(s)) => s.into_future(),
                Async::Ready(None) |
                Async::NotReady => break,
            };

            self.queue.push(future);
        }

        // Try polling a new future
        if let Some(val) = try_ready!(self.queue.poll()) {
            return Ok(Async::Ready(Some(val)));
        }

        // If we've gotten this far, then there are no events for us to process
        // and nothing was ready, so figure out if we're not done yet  or if
        // we've reached the end.
        if self.stream.is_done() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::NotReady)
        }
    }
}

// Forwarding impl of Sink from the underlying stream
impl<S> ::sink::Sink for BufferUnordered<S>
    where S: ::sink::Sink + Stream,
          S::Item: IntoFuture,
{
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: S::SinkItem) -> ::StartSend<S::SinkItem, S::SinkError> {
        self.stream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), S::SinkError> {
        self.stream.poll_complete()
    }

    fn close(&mut self) -> Poll<(), S::SinkError> {
        self.stream.close()
    }
}
<|endoftext|>


<commit_before>//! nalgebra trait implementation for primitive types.

#![allow(missing_docs)]
#![allow(non_camel_case_types)]

use traits::structure::Cast;

// Double dispatch traits to drive the Cast method for primitive types.
macro_rules! primitive_double_dispatch_cast_decl_trait(
    ($t: ident, $tcast: ident) => (
        pub trait $tcast {
            fn to(Self) -> $t;
        }
    )
);

macro_rules! primitive_double_dispatch_cast_impl(
    ($ttarget: ident, $tself: ident, $tcast: ident) => (
        impl $tcast for $tself{
            #[inline(always)]
            fn to(v: $tself) -> $ttarget {
                v as $ttarget
            }
        }
    )
);

macro_rules! primitive_cast_redispatch_impl(
    ($t:ident, $tcast: ident) => (
        impl<T: $tcast> Cast<T> for $t {
            #[inline(always)]
            fn from(t: T) -> $t {
                $tcast::to(t)
            }
        }
    )
);

primitive_double_dispatch_cast_decl_trait!(f64,  f64Cast);
primitive_double_dispatch_cast_decl_trait!(f32,  f32Cast);
primitive_double_dispatch_cast_decl_trait!(i64,  i64Cast);
primitive_double_dispatch_cast_decl_trait!(i32,  i32Cast);
primitive_double_dispatch_cast_decl_trait!(i16,  i16Cast);
primitive_double_dispatch_cast_decl_trait!(i8,   i8Cast);
primitive_double_dispatch_cast_decl_trait!(u64,  u64Cast);
primitive_double_dispatch_cast_decl_trait!(u32,  u32Cast);
primitive_double_dispatch_cast_decl_trait!(u16,  u16Cast);
primitive_double_dispatch_cast_decl_trait!(u8,   u8Cast);
primitive_double_dispatch_cast_decl_trait!(isize,  isizeCast);
primitive_double_dispatch_cast_decl_trait!(usize, usizeCast);

primitive_cast_redispatch_impl!(f64,  f64Cast);
primitive_cast_redispatch_impl!(f32,  f32Cast);
primitive_cast_redispatch_impl!(i64,  i64Cast);
primitive_cast_redispatch_impl!(i32,  i32Cast);
primitive_cast_redispatch_impl!(i16,  i16Cast);
primitive_cast_redispatch_impl!(i8,   i8Cast);
primitive_cast_redispatch_impl!(u64,  u64Cast);
primitive_cast_redispatch_impl!(u32,  u32Cast);
primitive_cast_redispatch_impl!(u16,  u16Cast);
primitive_cast_redispatch_impl!(u8,   u8Cast);
primitive_cast_redispatch_impl!(isize,  isizeCast);
primitive_cast_redispatch_impl!(usize, usizeCast);

primitive_double_dispatch_cast_impl!(f64, f64,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, f32,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, i64,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, i32,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, i16,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, i8,   f64Cast);
primitive_double_dispatch_cast_impl!(f64, u64,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, u32,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, u16,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, u8,   f64Cast);
primitive_double_dispatch_cast_impl!(f64, isize,  f64Cast);
primitive_double_dispatch_cast_impl!(f64, usize, f64Cast);

primitive_double_dispatch_cast_impl!(f32, f64,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, f32,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, i64,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, i32,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, i16,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, i8,   f32Cast);
primitive_double_dispatch_cast_impl!(f32, u64,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, u32,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, u16,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, u8,   f32Cast);
primitive_double_dispatch_cast_impl!(f32, isize,  f32Cast);
primitive_double_dispatch_cast_impl!(f32, usize, f32Cast);

primitive_double_dispatch_cast_impl!(i64, f64,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, f32,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, i64,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, i32,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, i16,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, i8,   i64Cast);
primitive_double_dispatch_cast_impl!(i64, u64,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, u32,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, u16,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, u8,   i64Cast);
primitive_double_dispatch_cast_impl!(i64, isize,  i64Cast);
primitive_double_dispatch_cast_impl!(i64, usize, i64Cast);

primitive_double_dispatch_cast_impl!(i32, f64,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, f32,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, i64,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, i32,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, i16,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, i8,   i32Cast);
primitive_double_dispatch_cast_impl!(i32, u64,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, u32,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, u16,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, u8,   i32Cast);
primitive_double_dispatch_cast_impl!(i32, isize,  i32Cast);
primitive_double_dispatch_cast_impl!(i32, usize, i32Cast);

primitive_double_dispatch_cast_impl!(i16, f64,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, f32,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, i64,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, i32,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, i16,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, i8,   i16Cast);
primitive_double_dispatch_cast_impl!(i16, u64,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, u32,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, u16,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, u8,   i16Cast);
primitive_double_dispatch_cast_impl!(i16, isize,  i16Cast);
primitive_double_dispatch_cast_impl!(i16, usize, i16Cast);

primitive_double_dispatch_cast_impl!(i8, f64,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, f32,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, i64,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, i32,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, i16,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, i8,   i8Cast);
primitive_double_dispatch_cast_impl!(i8, u64,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, u32,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, u16,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, u8,   i8Cast);
primitive_double_dispatch_cast_impl!(i8, isize,  i8Cast);
primitive_double_dispatch_cast_impl!(i8, usize, i8Cast);

primitive_double_dispatch_cast_impl!(u64, f64,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, f32,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, i64,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, i32,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, i16,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, i8,   u64Cast);
primitive_double_dispatch_cast_impl!(u64, u64,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, u32,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, u16,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, u8,   u64Cast);
primitive_double_dispatch_cast_impl!(u64, isize,  u64Cast);
primitive_double_dispatch_cast_impl!(u64, usize, u64Cast);

primitive_double_dispatch_cast_impl!(u32, f64,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, f32,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, i64,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, i32,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, i16,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, i8,   u32Cast);
primitive_double_dispatch_cast_impl!(u32, u64,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, u32,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, u16,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, u8,   u32Cast);
primitive_double_dispatch_cast_impl!(u32, isize,  u32Cast);
primitive_double_dispatch_cast_impl!(u32, usize, u32Cast);

primitive_double_dispatch_cast_impl!(u16, f64,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, f32,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, i64,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, i32,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, i16,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, i8,   u16Cast);
primitive_double_dispatch_cast_impl!(u16, u64,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, u32,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, u16,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, u8,   u16Cast);
primitive_double_dispatch_cast_impl!(u16, isize,  u16Cast);
primitive_double_dispatch_cast_impl!(u16, usize, u16Cast);

primitive_double_dispatch_cast_impl!(u8, f64,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, f32,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, i64,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, i32,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, i16,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, i8,   u8Cast);
primitive_double_dispatch_cast_impl!(u8, u64,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, u32,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, u16,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, u8,   u8Cast);
primitive_double_dispatch_cast_impl!(u8, isize,  u8Cast);
primitive_double_dispatch_cast_impl!(u8, usize, u8Cast);

primitive_double_dispatch_cast_impl!(usize, f64,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, f32,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, i64,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, i32,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, i16,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, i8,   usizeCast);
primitive_double_dispatch_cast_impl!(usize, u64,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, u32,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, u16,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, u8,   usizeCast);
primitive_double_dispatch_cast_impl!(usize, isize,  usizeCast);
primitive_double_dispatch_cast_impl!(usize, usize, usizeCast);

primitive_double_dispatch_cast_impl!(isize, f64,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, f32,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, i64,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, i32,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, i16,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, i8,   isizeCast);
primitive_double_dispatch_cast_impl!(isize, u64,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, u32,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, u16,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, u8,   isizeCast);
primitive_double_dispatch_cast_impl!(isize, isize,  isizeCast);
primitive_double_dispatch_cast_impl!(isize, usize, isizeCast);
<commit_msg>Remove the double-dispatch trick for Cast implementations.<commit_after>//! nalgebra trait implementation for primitive types.

use traits::structure::Cast;

macro_rules! primitive_cast_impl(
    ($from: ty, $to: ty) => (
        impl Cast<$from> for $to {
            #[inline(always)]
            fn from(t: $from) -> $to {
                t as $to
            }
        }
    )
);

primitive_cast_impl!(f64, f64);
primitive_cast_impl!(f64, f32);
primitive_cast_impl!(f64, i64);
primitive_cast_impl!(f64, i32);
primitive_cast_impl!(f64, i16);
primitive_cast_impl!(f64, i8);
primitive_cast_impl!(f64, u64);
primitive_cast_impl!(f64, u32);
primitive_cast_impl!(f64, u16);
primitive_cast_impl!(f64, u8);
primitive_cast_impl!(f64, isize);
primitive_cast_impl!(f64, usize);

primitive_cast_impl!(f32, f64);
primitive_cast_impl!(f32, f32);
primitive_cast_impl!(f32, i64);
primitive_cast_impl!(f32, i32);
primitive_cast_impl!(f32, i16);
primitive_cast_impl!(f32, i8);
primitive_cast_impl!(f32, u64);
primitive_cast_impl!(f32, u32);
primitive_cast_impl!(f32, u16);
primitive_cast_impl!(f32, u8);
primitive_cast_impl!(f32, isize);
primitive_cast_impl!(f32, usize);

primitive_cast_impl!(i64, f64);
primitive_cast_impl!(i64, f32);
primitive_cast_impl!(i64, i64);
primitive_cast_impl!(i64, i32);
primitive_cast_impl!(i64, i16);
primitive_cast_impl!(i64, i8);
primitive_cast_impl!(i64, u64);
primitive_cast_impl!(i64, u32);
primitive_cast_impl!(i64, u16);
primitive_cast_impl!(i64, u8);
primitive_cast_impl!(i64, isize);
primitive_cast_impl!(i64, usize);

primitive_cast_impl!(i32, f64);
primitive_cast_impl!(i32, f32);
primitive_cast_impl!(i32, i64);
primitive_cast_impl!(i32, i32);
primitive_cast_impl!(i32, i16);
primitive_cast_impl!(i32, i8);
primitive_cast_impl!(i32, u64);
primitive_cast_impl!(i32, u32);
primitive_cast_impl!(i32, u16);
primitive_cast_impl!(i32, u8);
primitive_cast_impl!(i32, isize);
primitive_cast_impl!(i32, usize);

primitive_cast_impl!(i16, f64);
primitive_cast_impl!(i16, f32);
primitive_cast_impl!(i16, i64);
primitive_cast_impl!(i16, i32);
primitive_cast_impl!(i16, i16);
primitive_cast_impl!(i16, i8);
primitive_cast_impl!(i16, u64);
primitive_cast_impl!(i16, u32);
primitive_cast_impl!(i16, u16);
primitive_cast_impl!(i16, u8);
primitive_cast_impl!(i16, isize);
primitive_cast_impl!(i16, usize);

primitive_cast_impl!(i8, f64);
primitive_cast_impl!(i8, f32);
primitive_cast_impl!(i8, i64);
primitive_cast_impl!(i8, i32);
primitive_cast_impl!(i8, i16);
primitive_cast_impl!(i8, i8);
primitive_cast_impl!(i8, u64);
primitive_cast_impl!(i8, u32);
primitive_cast_impl!(i8, u16);
primitive_cast_impl!(i8, u8);
primitive_cast_impl!(i8, isize);
primitive_cast_impl!(i8, usize);

primitive_cast_impl!(u64, f64);
primitive_cast_impl!(u64, f32);
primitive_cast_impl!(u64, i64);
primitive_cast_impl!(u64, i32);
primitive_cast_impl!(u64, i16);
primitive_cast_impl!(u64, i8);
primitive_cast_impl!(u64, u64);
primitive_cast_impl!(u64, u32);
primitive_cast_impl!(u64, u16);
primitive_cast_impl!(u64, u8);
primitive_cast_impl!(u64, isize);
primitive_cast_impl!(u64, usize);

primitive_cast_impl!(u32, f64);
primitive_cast_impl!(u32, f32);
primitive_cast_impl!(u32, i64);
primitive_cast_impl!(u32, i32);
primitive_cast_impl!(u32, i16);
primitive_cast_impl!(u32, i8);
primitive_cast_impl!(u32, u64);
primitive_cast_impl!(u32, u32);
primitive_cast_impl!(u32, u16);
primitive_cast_impl!(u32, u8);
primitive_cast_impl!(u32, isize);
primitive_cast_impl!(u32, usize);

primitive_cast_impl!(u16, f64);
primitive_cast_impl!(u16, f32);
primitive_cast_impl!(u16, i64);
primitive_cast_impl!(u16, i32);
primitive_cast_impl!(u16, i16);
primitive_cast_impl!(u16, i8);
primitive_cast_impl!(u16, u64);
primitive_cast_impl!(u16, u32);
primitive_cast_impl!(u16, u16);
primitive_cast_impl!(u16, u8);
primitive_cast_impl!(u16, isize);
primitive_cast_impl!(u16, usize);

primitive_cast_impl!(u8, f64);
primitive_cast_impl!(u8, f32);
primitive_cast_impl!(u8, i64);
primitive_cast_impl!(u8, i32);
primitive_cast_impl!(u8, i16);
primitive_cast_impl!(u8, i8);
primitive_cast_impl!(u8, u64);
primitive_cast_impl!(u8, u32);
primitive_cast_impl!(u8, u16);
primitive_cast_impl!(u8, u8);
primitive_cast_impl!(u8, isize);
primitive_cast_impl!(u8, usize);

primitive_cast_impl!(usize, f64);
primitive_cast_impl!(usize, f32);
primitive_cast_impl!(usize, i64);
primitive_cast_impl!(usize, i32);
primitive_cast_impl!(usize, i16);
primitive_cast_impl!(usize, i8);
primitive_cast_impl!(usize, u64);
primitive_cast_impl!(usize, u32);
primitive_cast_impl!(usize, u16);
primitive_cast_impl!(usize, u8);
primitive_cast_impl!(usize, isize);
primitive_cast_impl!(usize, usize);

primitive_cast_impl!(isize, f64);
primitive_cast_impl!(isize, f32);
primitive_cast_impl!(isize, i64);
primitive_cast_impl!(isize, i32);
primitive_cast_impl!(isize, i16);
primitive_cast_impl!(isize, i8);
primitive_cast_impl!(isize, u64);
primitive_cast_impl!(isize, u32);
primitive_cast_impl!(isize, u16);
primitive_cast_impl!(isize, u8);
primitive_cast_impl!(isize, isize);
primitive_cast_impl!(isize, usize);
<|endoftext|>


<commit_before>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};
use serde::Deserialize;

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        not(feature = "no_jemalloc"),
    ),
    global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &'static str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>] \
    [--async]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
    --async            Use a threadpool to perform disk IO in the background.
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
    flag_total_ops: Option<usize>,
    flag_async: bool,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
    flag_total_ops: None,
    flag_async: false,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret =
        old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let scan_max = cas_max + args.flag_scan_prop;
    let merge_max = scan_max + args.flag_merge_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.into_iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, merge_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.set(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.del(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                match tree.cas(&key, old, new) {
                    Ok(_) | Err(sled::Error::CasFailed(_)) => {}
                    other => panic!("operational error: {:?}", other),
                }
            }
            v if v > cas_max && v <= scan_max => {
                let _ = tree
                    .scan(&key)
                    .take(rng.gen_range(0, 15))
                    .map(|res| res.unwrap())
                    .collect::<Vec<_>>();
            }
            _ => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
        }
    }
}

fn main() {
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| {
                d.argv(std::env::args().into_iter()).deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::ConfigBuilder::new()
        .io_bufs(16)
        .io_buf_size(8_000_000)
        .async_io(args.flag_async)
        .async_io_threads(3)
        .blink_node_split_size(4096)
        .page_consolidation_threshold(10)
        .cache_bits(0)
        .cache_capacity(1_000_000_000)
        .flush_every_ms(Some(200))
        .snapshot_after_ops(100_000_000_000)
        .print_profile_on_drop(true)
        .merge_operator(concatenate_merge)
        .build();

    let tree = Arc::new(sled::Db::start(config).unwrap());

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..n_threads + 1 {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::spawn(move || report(shutdown))
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.flag_total_ops {
        assert!(
            !args.flag_burn_in,
            "don't set both --burn-in and --total-ops"
        );
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

pub fn setup_logger() {
    use std::io::Write;

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record
                    .module_path()
                    .unwrap()
                    .split("::")
                    .last()
                    .unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<commit_msg>Update stress2 for new result handling<commit_after>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};
use serde::Deserialize;

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        not(feature = "no_jemalloc"),
    ),
    global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &'static str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>] \
    [--async]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
    --async            Use a threadpool to perform disk IO in the background.
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
    flag_total_ops: Option<usize>,
    flag_async: bool,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
    flag_total_ops: None,
    flag_async: false,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret =
        old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let scan_max = cas_max + args.flag_scan_prop;
    let merge_max = scan_max + args.flag_merge_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.into_iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, merge_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.set(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.del(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                if let Err(e) = tree.cas(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= scan_max => {
                let _ = tree
                    .scan(&key)
                    .take(rng.gen_range(0, 15))
                    .map(|res| res.unwrap())
                    .collect::<Vec<_>>();
            }
            _ => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
        }
    }
}

fn main() {
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| {
                d.argv(std::env::args().into_iter()).deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::ConfigBuilder::new()
        .io_bufs(16)
        .io_buf_size(8_000_000)
        .async_io(args.flag_async)
        .async_io_threads(3)
        .blink_node_split_size(4096)
        .page_consolidation_threshold(10)
        .cache_bits(0)
        .cache_capacity(1_000_000_000)
        .flush_every_ms(Some(200))
        .snapshot_after_ops(100_000_000_000)
        .print_profile_on_drop(true)
        .merge_operator(concatenate_merge)
        .build();

    let tree = Arc::new(sled::Db::start(config).unwrap());

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..n_threads + 1 {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::spawn(move || report(shutdown))
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.flag_total_ops {
        assert!(
            !args.flag_burn_in,
            "don't set both --burn-in and --total-ops"
        );
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

pub fn setup_logger() {
    use std::io::Write;

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record
                    .module_path()
                    .unwrap()
                    .split("::")
                    .last()
                    .unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<|endoftext|>


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

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! enough, consensus-relevant constants and short functions should be kept
//! here.

use std::cmp;

use core::target::Target;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds, the network will tune its next_target for. Note
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: u8 = 60;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Origin Cuckoo Cycle size shift used by the genesis block.
pub const DEFAULT_SIZESHIFT: u8 = 25;

/// Maximum Cuckoo Cycle size shift we'll ever use. We adopt a schedule that
/// progressively increases the size as the target becomes lower.
///   Start => 25
///   MAX_TARGET >> 12 => 26
///   MAX_TARGET >> 20 => 27
///   MAX_TARGET >> 28 => 28
///   MAX_TARGET >> 36 => 29
pub const MAX_SIZESHIFT: u8 = 29;

/// Default Cuckoo Cycle easiness, high enough to have good likeliness to find
/// a solution.
pub const EASINESS: u32 = 50;

/// Difficulty adjustment somewhat inspired by Ethereum's. Tuned to add or
/// remove 1/1024th of the target for each 10 seconds of deviation from the 30
/// seconds block time. Increases Cuckoo size shift by one when next_target
/// reaches soft max.
pub fn next_target(ts: i64, prev_ts: i64, prev_target: Target, prev_cuckoo_sz: u8) -> (Target, u8) {
	// increase the cuckoo size when the target gets lower than the soft min as
	// long as we're not at the max size already; target gets 2x to compensate for
	// increased next_target
	let soft_min = SOFT_MIN_TARGET >> (((prev_cuckoo_sz - cmp::min(DEFAULT_SIZESHIFT, prev_cuckoo_sz)) * 8) as usize);
	let (ptarget, clen) = if prev_target < soft_min && prev_cuckoo_sz < MAX_SIZESHIFT {
		(prev_target << 1, prev_cuckoo_sz + 1)
	} else {
		(prev_target, prev_cuckoo_sz)
	};

	// target is increased/decreased by multiples of 1/1024th of itself
	let incdec = ptarget >> 10;
	// signed deviation from desired value divided by ten and bounded in [-3, 3]
	let delta = cmp::max(cmp::min((ts - prev_ts - (BLOCK_TIME_SEC as i64)) / 10, 3),
	                     -3);
	// increase or decrease the target based on the sign of delta by a shift of
	// |delta|-1; keep as-is for delta of zero
	let new_target = match delta {
		1...3 => ptarget + (incdec << ((delta - 1) as usize)),
		-3...-1 => ptarget - (incdec << ((-delta - 1) as usize)),
		_ => ptarget,
	};

	// cannot exceed the maximum target
	if new_target > MAX_TARGET {
		(MAX_TARGET, clen)
	} else {
		(new_target.truncate(), clen)
	}
}

/// Max target hash, lowest next_target
pub const MAX_TARGET: Target = Target([0xf, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0]);

/// Target limit under which we start increasing the size shift on Cuckoo cycle.
pub const SOFT_MIN_TARGET: Target = Target([0, 0, 0xf, 0xff, 0xff, 0xff, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0]);

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg.
/// Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 48h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);

/// The maximum number of inputs or outputs a transaction may have
/// and be deserializable. Only for DoS protection.
pub const MAX_IN_OUT_LEN: u64 = 50000;

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

	#[test]
	/// Checks different next_target adjustments and difficulty boundaries
	fn next_target_adjustment() {
		// can't do lower than min
		assert_eq!(next_target(60, 0, MAX_TARGET, 26), (MAX_TARGET, 26));
		assert_eq!(next_target(90, 30, MAX_TARGET, 26), (MAX_TARGET, 26));
		assert_eq!(next_target(60, 0, MAX_TARGET, 26), (MAX_TARGET, 26));

		// lower next_target if gap too short, even negative
		assert_eq!(next_target(50, 0, MAX_TARGET, 26).0,
		           MAX_TARGET - (MAX_TARGET >> 10));
		assert_eq!(next_target(40, 0, MAX_TARGET, 26).0,
		           MAX_TARGET - ((MAX_TARGET >> 10) << 1));
		assert_eq!(next_target(0, 20, MAX_TARGET, 26).0,
		           MAX_TARGET - ((MAX_TARGET >> 10) << 2));

		// raise next_target if gap too wide
		let lower_target = MAX_TARGET >> 8;
		assert_eq!(next_target(70, 0, lower_target, 26).0,
		           lower_target + (lower_target >> 10));
		assert_eq!(next_target(80, 0, lower_target, 26).0,
		           lower_target + ((lower_target >> 10) << 1));
		assert_eq!(next_target(200, 0, lower_target, 26).0,
		           lower_target + ((lower_target >> 10) << 2));

		// close enough, no adjustment
		assert_eq!(next_target(65, 0, lower_target, 26).0, lower_target);
		assert_eq!(next_target(55, 0, lower_target, 26).0, lower_target);

		// increase cuckoo size if next_target goes above soft max, target is doubled,
		// up to 29
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 1, 25),
		           ((SOFT_MIN_TARGET >> 1) << 1, 26));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 9, 26),
		           ((SOFT_MIN_TARGET >> 9) << 1, 27));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 17, 27),
		           ((SOFT_MIN_TARGET >> 17) << 1, 28));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 25, 28),
		           ((SOFT_MIN_TARGET >> 25) << 1, 29));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 33, 29),
		           (SOFT_MIN_TARGET >> 33, 29));

		// should only increase on the according previous size
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 1, 26),
		           (SOFT_MIN_TARGET >> 1, 26));
	}
}
<commit_msg>Fixed retargeting tests for truncation.<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! enough, consensus-relevant constants and short functions should be kept
//! here.

use std::cmp;

use core::target::Target;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds, the network will tune its next_target for. Note
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: u8 = 60;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Origin Cuckoo Cycle size shift used by the genesis block.
pub const DEFAULT_SIZESHIFT: u8 = 25;

/// Maximum Cuckoo Cycle size shift we'll ever use. We adopt a schedule that
/// progressively increases the size as the target becomes lower.
///   Start => 25
///   MAX_TARGET >> 12 => 26
///   MAX_TARGET >> 20 => 27
///   MAX_TARGET >> 28 => 28
///   MAX_TARGET >> 36 => 29
pub const MAX_SIZESHIFT: u8 = 29;

/// Default Cuckoo Cycle easiness, high enough to have good likeliness to find
/// a solution.
pub const EASINESS: u32 = 50;

/// Difficulty adjustment somewhat inspired by Ethereum's. Tuned to add or
/// remove 1/1024th of the target for each 10 seconds of deviation from the 30
/// seconds block time. Increases Cuckoo size shift by one when next_target
/// reaches soft max.
pub fn next_target(ts: i64, prev_ts: i64, prev_target: Target, prev_cuckoo_sz: u8) -> (Target, u8) {
	// increase the cuckoo size when the target gets lower than the soft min as
	// long as we're not at the max size already; target gets 2x to compensate for
	// increased next_target
	let soft_min = SOFT_MIN_TARGET >> (((prev_cuckoo_sz - cmp::min(DEFAULT_SIZESHIFT, prev_cuckoo_sz)) * 8) as usize);
	let (ptarget, clen) = if prev_target < soft_min && prev_cuckoo_sz < MAX_SIZESHIFT {
		(prev_target << 1, prev_cuckoo_sz + 1)
	} else {
		(prev_target, prev_cuckoo_sz)
	};

	// target is increased/decreased by multiples of 1/1024th of itself
	let incdec = ptarget >> 10;
	// signed deviation from desired value divided by ten and bounded in [-3, 3]
	let delta = cmp::max(cmp::min((ts - prev_ts - (BLOCK_TIME_SEC as i64)) / 10, 3),
	                     -3);
	// increase or decrease the target based on the sign of delta by a shift of
	// |delta|-1; keep as-is for delta of zero
	let new_target = match delta {
		1...3 => ptarget + (incdec << ((delta - 1) as usize)),
		-3...-1 => ptarget - (incdec << ((-delta - 1) as usize)),
		_ => ptarget,
	};

	// cannot exceed the maximum target
	if new_target > MAX_TARGET {
		(MAX_TARGET, clen)
	} else {
		(new_target.truncate(), clen)
	}
}

/// Max target hash, lowest next_target
pub const MAX_TARGET: Target = Target([0xf, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0]);

/// Target limit under which we start increasing the size shift on Cuckoo cycle.
pub const SOFT_MIN_TARGET: Target = Target([0, 0, 0xf, 0xff, 0xff, 0xff, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0, 0, 0, 0, 0, 0,
                                       0, 0, 0, 0]);

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg.
/// Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 48h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);

/// The maximum number of inputs or outputs a transaction may have
/// and be deserializable. Only for DoS protection.
pub const MAX_IN_OUT_LEN: u64 = 50000;

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

	#[test]
	/// Checks different next_target adjustments and difficulty boundaries
	fn next_target_adjustment() {
		// can't do lower than min
		assert_eq!(next_target(60, 0, MAX_TARGET, 26), (MAX_TARGET, 26));
		assert_eq!(next_target(90, 30, MAX_TARGET, 26), (MAX_TARGET, 26));
		assert_eq!(next_target(60, 0, MAX_TARGET, 26), (MAX_TARGET, 26));

		// lower next_target if gap too short, even negative
		assert_eq!(next_target(50, 0, MAX_TARGET, 26).0,
		           (MAX_TARGET - (MAX_TARGET >> 10)).truncate());
		assert_eq!(next_target(40, 0, MAX_TARGET, 26).0,
		           (MAX_TARGET - ((MAX_TARGET >> 10) << 1)).truncate());
		assert_eq!(next_target(0, 20, MAX_TARGET, 26).0,
		           (MAX_TARGET - ((MAX_TARGET >> 10) << 2)).truncate());

		// raise next_target if gap too wide
		let lower_target = MAX_TARGET >> 8;
		assert_eq!(next_target(70, 0, lower_target, 26).0,
		           (lower_target + (lower_target >> 10)).truncate());
		assert_eq!(next_target(80, 0, lower_target, 26).0,
		           (lower_target + ((lower_target >> 10) << 1)).truncate());
		assert_eq!(next_target(200, 0, lower_target, 26).0,
		           (lower_target + ((lower_target >> 10) << 2)).truncate());

		// close enough, no adjustment
		assert_eq!(next_target(65, 0, lower_target, 26).0, lower_target);
		assert_eq!(next_target(55, 0, lower_target, 26).0, lower_target);

		// increase cuckoo size if next_target goes above soft max, target is doubled,
		// up to 29
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 1, 25),
		           ((SOFT_MIN_TARGET >> 1) << 1, 26));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 9, 26),
		           ((SOFT_MIN_TARGET >> 9) << 1, 27));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 17, 27),
		           ((SOFT_MIN_TARGET >> 17) << 1, 28));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 25, 28),
		           ((SOFT_MIN_TARGET >> 25) << 1, 29));
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 33, 29),
		           (SOFT_MIN_TARGET >> 33, 29));

		// should only increase on the according previous size
		assert_eq!(next_target(60, 0, SOFT_MIN_TARGET >> 1, 26),
		           (SOFT_MIN_TARGET >> 1, 26));
	}
}
<|endoftext|>


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

fn main() {
    let x = Some(1);
    let Some(y) = x; //~ ERROR E0005
}
<commit_msg>Update E0005 Unit-Test<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    let x = Some(1);
    let Some(y) = x; //~ ERROR E0005
    //~| NOTE pattern `None` not covered
}
<|endoftext|>


<commit_before>extern crate tropix;
extern crate rustc_serialize;
extern crate time;

use tropix::bittrex::bittrex::*;

use rustc_serialize::{Decodable, Decoder};
use rustc_serialize::json::{self, ToJson, Json};

use std::io;
use std::io::Read;
use std::thread::sleep;
use std::time::Duration;
use std::io::{BufRead};

fn main() {

	let pair_vec = vec!["SEC", "ETH", "MAID", "ETC"];

	println!("Enter Your Bittrex Api Key");
    let mut input1 = String::new();
    let stdin1 = io::stdin();
    stdin1.lock().read_line(&mut input1).unwrap();

    let next_string = &input1.trim_right_matches("\n");

	let the_api_key = &next_string;
//secret Key
	println!("Enter Your Bittrex Secret Key");
    let mut input2 = String::new();
    let stdin2 = io::stdin();
    stdin2.lock().read_line(&mut input2).unwrap();

    let the_secret_trimmed = input2.trim_right_matches("\n");

	let mut intd = 0;
     for pair in &pair_vec {
    	println!("{:?}, : {:?}", intd, pair);
    	intd += 1;
    }

    let firstcoin = "BTC".to_string();

    println!("choose a currency to trade by its index., enter the number before the currency you want to trade");
    let mut input5 = String::new();
    let stdin5 = io::stdin();
    stdin5.lock().read_line(&mut input5).unwrap();

    let pair_ind = input5.trim_right_matches("\n");

    let pair_ind2: usize = pair_ind.parse().ok().expect("currency index is not a number");

    let secondcoin = pair_vec[pair_ind2];

    println!("Enter a maximum position limit in the alt coin quantity \n the bot will buy only up to this much at a time");
    let mut input3 = String::new();
    let stdin3 = io::stdin();
    stdin3.lock().read_line(&mut input3).unwrap();

    let maxposition = input3.trim_right_matches("\n").to_string();
    let position_clone = maxposition.clone().parse().ok().expect("max position turned out to not be a number either");

    println!("Enter a buy frequency in seconds a value of 60 will mean 1 minute");
    let mut input4 = String::new();
    let stdin4 = io::stdin();
    stdin4.lock().read_line(&mut input4).unwrap();

    let frequency = input4.trim_right_matches("\n").to_string();

    let frequency: u64 = frequency.parse().ok().expect("frequency is not a number");

    println!("pair {} / {}", &firstcoin, &secondcoin);
    println!("max position {}", &maxposition);
    println!("frequency {} seconds", &frequency);
    let mut xyz = 0;
	while xyz == 0 {

    	let order_book = get_orderbook(&the_secret_trimmed, &firstcoin, &secondcoin, "500");
    	for sell in order_book.sell {

			if sell.Quantity > position_clone {
    			let the_trade = buy_limit(&the_api_key, &the_secret_trimmed, &firstcoin, &secondcoin, &position_clone.to_string(), &sell.Rate.to_string());
    			println!("bought {}, {}", position_clone, the_trade);
    			break;
			} else {
				let the_trade = buy_limit(&the_api_key, &the_secret_trimmed, &firstcoin, &secondcoin, &sell.Quantity.to_string(), &sell.Rate.to_string());
				println!("bought {}, {}", &sell.Quantity, the_trade);
				break;
			}
    	}

		let the_seconds = Duration::new(frequency, 0);
		sleep(the_seconds);

	}
}<commit_msg>fix ticker in bittrex to SAFEX<commit_after>extern crate tropix;
extern crate rustc_serialize;
extern crate time;

use tropix::bittrex::bittrex::*;

use rustc_serialize::{Decodable, Decoder};
use rustc_serialize::json::{self, ToJson, Json};

use std::io;
use std::io::Read;
use std::thread::sleep;
use std::time::Duration;
use std::io::{BufRead};

fn main() {

	let pair_vec = vec!["SAFEX", "ETH", "MAID", "ETC", "BCC"];

	println!("Enter Your Bittrex Api Key");
    let mut input1 = String::new();
    let stdin1 = io::stdin();
    stdin1.lock().read_line(&mut input1).unwrap();

    let next_string = &input1.trim_right_matches("\n");

	let the_api_key = &next_string;
//secret Key
	println!("Enter Your Bittrex Secret Key");
    let mut input2 = String::new();
    let stdin2 = io::stdin();
    stdin2.lock().read_line(&mut input2).unwrap();

    let the_secret_trimmed = input2.trim_right_matches("\n");

	let mut intd = 0;
     for pair in &pair_vec {
    	println!("{:?}, : {:?}", intd, pair);
    	intd += 1;
    }

    let firstcoin = "BTC".to_string();

    println!("choose a currency to trade by its index., enter the number before the currency you want to trade");
    let mut input5 = String::new();
    let stdin5 = io::stdin();
    stdin5.lock().read_line(&mut input5).unwrap();

    let pair_ind = input5.trim_right_matches("\n");

    let pair_ind2: usize = pair_ind.parse().ok().expect("currency index is not a number");

    let secondcoin = pair_vec[pair_ind2];

    println!("Enter a maximum position limit in the alt coin quantity \n the bot will buy only up to this much at a time");
    let mut input3 = String::new();
    let stdin3 = io::stdin();
    stdin3.lock().read_line(&mut input3).unwrap();

    let maxposition = input3.trim_right_matches("\n").to_string();
    let position_clone = maxposition.clone().parse().ok().expect("max position turned out to not be a number either");

    println!("Enter a buy frequency in seconds a value of 60 will mean 1 minute");
    let mut input4 = String::new();
    let stdin4 = io::stdin();
    stdin4.lock().read_line(&mut input4).unwrap();

    let frequency = input4.trim_right_matches("\n").to_string();

    let frequency: u64 = frequency.parse().ok().expect("frequency is not a number");

    println!("pair {} / {}", &firstcoin, &secondcoin);
    println!("max position {}", &maxposition);
    println!("frequency {} seconds", &frequency);
    let mut xyz = 0;
	while xyz == 0 {

    	let order_book = get_orderbook(&the_secret_trimmed, &firstcoin, &secondcoin, "500");
    	for sell in order_book.sell {

			if sell.Quantity > position_clone {
    			let the_trade = buy_limit(&the_api_key, &the_secret_trimmed, &firstcoin, &secondcoin, &position_clone.to_string(), &sell.Rate.to_string());
    			println!("bought {}, {}", position_clone, the_trade);
    			break;
			} else {
				let the_trade = buy_limit(&the_api_key, &the_secret_trimmed, &firstcoin, &secondcoin, &sell.Quantity.to_string(), &sell.Rate.to_string());
				println!("bought {}, {}", &sell.Quantity, the_trade);
				break;
			}
    	}

		let the_seconds = Duration::new(frequency, 0);
		sleep(the_seconds);

	}
}<|endoftext|>


<commit_before><commit_msg>Make `BranchNode::join` private.<commit_after><|endoftext|>


<commit_before><commit_msg>Add support for listing all the files in all the subdirectories<commit_after><|endoftext|>


<commit_before><commit_msg>Use CLI args instead of hardcoded data for loading programs<commit_after><|endoftext|>


<commit_before><commit_msg>Appease clippy<commit_after><|endoftext|>


<commit_before><commit_msg>Create functions for parsing<commit_after><|endoftext|>


<commit_before><commit_msg>Updated call to opengl_graphics::Gl::new<commit_after><|endoftext|>


<commit_before><commit_msg>Removed `main.rs`<commit_after><|endoftext|>


<commit_before><commit_msg>convert replacements vector to global array; avoid cloning the style<commit_after><|endoftext|>


<commit_before>fn main() {
    let m = matrix_from_vec(vec!(
            2, -1, 5, 1,
            3, 2, 2, -6,
            1, 3, 3, -1,
            5, -2, -3, 3
            ),
            4);
    let mm = m.solve(&vec!(-3, -32, -47, 49));
    println!("{:?}", mm);
}

#[derive(Clone)]
struct Matrix {
    elts : Vec<Vec<i64>>,
    dim: usize
}

impl Matrix {
    // Compute determinant with the cofactor method
    // Using Gaussian elimination would have been more efficient, but it also solves the linear
    // system, so…
    fn det(&self) -> f64 {
        match self.dim {
            0 => 0.,
            1 => self.elts[0][0] as f64,
            2 => (self.elts[0][0] * self.elts[1][1] - self.elts[0][1] * self.elts[1][0]) as f64,
            d => {
                let mut acc = 0.;
                let mut coeff = 1.;
                for k in 0..d {
                    acc += coeff * self.elts[0][k] as f64 * self.comatrix(0, k).det();
                    coeff *= -1.
                }
                acc
            }
        }
    }

    // Solve linear systems using Cramer's method
    fn solve(&self, target : &Vec<i64>) -> Vec<f64> {
        let mut solution : Vec<f64> = vec!(0.; self.dim);
        let denominator = self.det();
        for j in 0..self.dim {
            let mut mm = self.clone();
            for i in 0..self.dim { mm.elts[i][j] = target[i] }
            solution[j] = mm.det() / denominator
        }
        solution
    }

    // Compute a cofactor matrix for determinant computation
    fn comatrix(&self, k : usize, l : usize) -> Matrix {
        let mut v : Vec<i64> = vec!();
        for i in 0..self.dim {
            for j in 0..self.dim {
                if i != k && j != l { v.push(self.elts[i][j]) }
            }
        }
        matrix_from_vec(v, self.dim-1)
    }

}

fn matrix_from_vec(v : Vec<i64>, dim : usize) -> Matrix {
    assert_eq!(v.len(), dim * dim);
    let mut elts = vec!(vec!(0; dim); dim);
    for i in 0..dim {
        for j in 0..dim {
            elts[i][j] = v[i * dim + j]
        }
    }
    Matrix { elts, dim }
}
<commit_msg>rustfmt<commit_after>fn main() {
    let m = matrix_from_vec(vec![2, -1, 5, 1, 3, 2, 2, -6, 1, 3, 3, -1, 5, -2, -3, 3], 4);
    let mm = m.solve(&vec![-3, -32, -47, 49]);
    println!("{:?}", mm);
}

#[derive(Clone)]
struct Matrix {
    elts: Vec<Vec<i64>>,
    dim: usize,
}

impl Matrix {
    // Compute determinant with the cofactor method
    // Using Gaussian elimination would have been more efficient, but it also solves the linear
    // system, so…
    fn det(&self) -> f64 {
        match self.dim {
            0 => 0.,
            1 => self.elts[0][0] as f64,
            2 => (self.elts[0][0] * self.elts[1][1] - self.elts[0][1] * self.elts[1][0]) as f64,
            d => {
                let mut acc = 0.;
                let mut coeff = 1.;
                for k in 0..d {
                    acc += coeff * self.elts[0][k] as f64 * self.comatrix(0, k).det();
                    coeff *= -1.
                }
                acc
            }
        }
    }

    // Solve linear systems using Cramer's method
    fn solve(&self, target: &Vec<i64>) -> Vec<f64> {
        let mut solution: Vec<f64> = vec![0.; self.dim];
        let denominator = self.det();
        for j in 0..self.dim {
            let mut mm = self.clone();
            for i in 0..self.dim {
                mm.elts[i][j] = target[i]
            }
            solution[j] = mm.det() / denominator
        }
        solution
    }

    // Compute a cofactor matrix for determinant computation
    fn comatrix(&self, k: usize, l: usize) -> Matrix {
        let mut v: Vec<i64> = vec![];
        for i in 0..self.dim {
            for j in 0..self.dim {
                if i != k && j != l {
                    v.push(self.elts[i][j])
                }
            }
        }
        matrix_from_vec(v, self.dim - 1)
    }
}

fn matrix_from_vec(v: Vec<i64>, dim: usize) -> Matrix {
    assert_eq!(v.len(), dim * dim);
    let mut elts = vec![vec!(0, dim); dim];
    for i in 0..dim {
        for j in 0..dim {
            elts[i][j] = v[i * dim + j]
        }
    }
    Matrix { elts, dim }
}
<|endoftext|>