<commit_before>#![crate_name = "wc"]
#![feature(collections, old_io, old_path, rustc_private, str_words)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Boden Garman <bpgarman@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::ascii::AsciiExt;
use std::str::from_utf8;
use std::old_io::{print, File, BufferedReader};
use std::old_io::fs::PathExtensions;
use std::old_io::stdio::stdin_raw;
use std::result::Result as StdResult;
use std::borrow::IntoCow;
use getopts::Matches;

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

struct Result {
    filename: String,
    bytes: usize,
    chars: usize,
    lines: usize,
    words: usize,
    max_line_length: usize,
}

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

pub fn uumain(args: Vec<String>) -> i32 {
    let program = &args[0][..];
    let opts = [
        getopts::optflag("c", "bytes", "print the byte counts"),
        getopts::optflag("m", "chars", "print the character counts"),
        getopts::optflag("l", "lines", "print the newline counts"),
        getopts::optflag("L", "max-line-length", "print the length of the longest line"),
        getopts::optflag("w", "words", "print the word counts"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "Invalid options\n{}", f)
        }
    };

    if matches.opt_present("help") {
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", program);
        println!("");
        print(&getopts::usage("Print newline, word and byte counts for each FILE", &opts)[..]);
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return 0;
    }

    if matches.opt_present("version") {
        println!("wc 1.0.0");
        return 0;
    }

    let files = if matches.free.is_empty() {
        vec!["-".to_string()].into_cow()
    } else {
        matches.free[..].into_cow()
    };

    match wc(&files[..], &matches) {
        Ok(()) => ( /* pass */ ),
        Err(e) => return e
    }

    0
}

const CR: u8 = '\r' as u8;
const LF: u8 = '\n' as u8;
const SPACE: u8 = ' ' as u8;
const TAB: u8 = '\t' as u8;
const SYN: u8 = 0x16 as u8;
const FF: u8 = 0x0C as u8;

#[inline(always)]
fn is_word_seperator(byte: u8) -> bool {
    byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF
}

pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
    let mut total_line_count: usize = 0;
    let mut total_word_count: usize = 0;
    let mut total_char_count: usize = 0;
    let mut total_byte_count: usize = 0;
    let mut total_longest_line_length: usize = 0;

    let mut results = vec!();
    let mut max_str_len: usize = 0;

    for path in files.iter() {
        let mut reader = try!(open(&path[..]));

        let mut line_count: usize = 0;
        let mut word_count: usize = 0;
        let mut byte_count: usize = 0;
        let mut char_count: usize = 0;
        let mut longest_line_length: usize = 0;

        // reading from a TTY seems to raise a condition on, rather than return Some(0) like a file.
        // hence the option wrapped in a result here
        while let Ok(raw_line) = reader.read_until(LF) {
            // GNU 'wc' only counts lines that end in LF as lines
            if *raw_line.last().unwrap() == LF {
                line_count += 1;
            }

            byte_count += raw_line.len();

            // try and convert the bytes to UTF-8 first
            let current_char_count;
            match from_utf8(&raw_line[..]) {
                Ok(line) => {
                    word_count += line.words().count();
                    current_char_count = line.chars().count();
                },
                Err(..) => {
                    word_count += raw_line.split(|&x| is_word_seperator(x)).count();
                    current_char_count = raw_line.iter().filter(|c|c.is_ascii()).count()
                }
            }
            char_count += current_char_count;

            if current_char_count > longest_line_length {
                // we subtract one here because `line.len()` includes the LF
                // matches GNU 'wc' behaviour
                longest_line_length = current_char_count - 1;
            }
        }

        results.push(Result {
            filename: path.to_string(),
            bytes: byte_count,
            chars: char_count,
            lines: line_count,
            words: word_count,
            max_line_length: longest_line_length,
        });

        total_line_count += line_count;
        total_word_count += word_count;
        total_char_count += char_count;
        total_byte_count += byte_count;

        if longest_line_length > total_longest_line_length {
            total_longest_line_length = longest_line_length;
        }

        // used for formatting
        max_str_len = total_byte_count.to_string().len();
    }

    for result in results.iter() {
        print_stats(&result.filename[..], result.lines, result.words, result.chars, result.bytes, result.max_line_length, matches, max_str_len);
    }

    if files.len() > 1 {
        print_stats("total", total_line_count, total_word_count, total_char_count, total_byte_count, total_longest_line_length, matches, max_str_len);
    }

    Ok(())
}

fn print_stats(filename: &str, line_count: usize, word_count: usize, char_count: usize,
    byte_count: usize, longest_line_length: usize, matches: &Matches, max_str_len: usize) {
    if matches.opt_present("lines") {
        print!("{:1$}", line_count, max_str_len);
    }
    if matches.opt_present("words") {
        print!("{:1$}", word_count, max_str_len);
    }
    if matches.opt_present("bytes") {
        print!("{:1$}", byte_count, max_str_len);
    }
    if matches.opt_present("chars") {
        print!("{:1$}", char_count, max_str_len);
    }
    if matches.opt_present("max-line-length") {
        print!("{:1$}", longest_line_length, max_str_len);
    }

    // defaults
    if !matches.opt_present("bytes")
        && !matches.opt_present("chars")
        && !matches.opt_present("lines")
        && !matches.opt_present("words")
        && !matches.opt_present("max-line-length") {
        print!("{:1$}", line_count, max_str_len);
        print!("{:1$}", word_count, max_str_len + 1);
        print!("{:1$}", byte_count, max_str_len + 1);
    }

    if filename != "-" {
        println!(" {}", filename);
    }
    else {
        println!("");
    }
}

fn open(path: &str) -> StdResult<BufferedReader<Box<Reader+'static>>, i32> {
    if "-" == path {
        let reader = Box::new(stdin_raw()) as Box<Reader>;
        return Ok(BufferedReader::new(reader));
    }

    let fpath = Path::new(path);
    if fpath.is_dir() {
        show_info!("{}: is a directory", path);
    }
    match File::open(&fpath) {
        Ok(fd) => {
            let reader = Box::new(fd) as Box<Reader>;
            Ok(BufferedReader::new(reader))
        }
        Err(e) => {
            show_error!("wc: {}: {}", path, e);
            Err(1)
        }
    }
}
<commit_msg>fix `wc`<commit_after>#![crate_name = "wc"]
#![feature(rustc_private, path_ext)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Boden Garman <bpgarman@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use getopts::Matches;

use std::ascii::AsciiExt;
use std::fs::{File, PathExt};
use std::io::{stdin, BufRead, BufReader, Read, Write};
use std::path::Path;
use std::result::Result as StdResult;
use std::str::from_utf8;

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

struct Result {
    filename: String,
    bytes: usize,
    chars: usize,
    lines: usize,
    words: usize,
    max_line_length: usize,
}

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

pub fn uumain(args: Vec<String>) -> i32 {
    let program = &args[0][..];
    let opts = [
        getopts::optflag("c", "bytes", "print the byte counts"),
        getopts::optflag("m", "chars", "print the character counts"),
        getopts::optflag("l", "lines", "print the newline counts"),
        getopts::optflag("L", "max-line-length", "print the length of the longest line"),
        getopts::optflag("w", "words", "print the word counts"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let mut matches = match getopts::getopts(&args[1..], &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "Invalid options\n{}", f)
        }
    };

    if matches.opt_present("help") {
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", program);
        println!("");
        println!("{}", getopts::usage("Print newline, word and byte counts for each FILE", &opts));
        println!("With no FILE, or when FILE is -, read standard input.");
        return 0;
    }

    if matches.opt_present("version") {
        println!("wc 1.0.0");
        return 0;
    }

    if matches.free.is_empty() {
        matches.free.push("-".to_string());
    }

    match wc(&matches) {
        Ok(()) => ( /* pass */ ),
        Err(e) => return e
    }

    0
}

const CR: u8 = '\r' as u8;
const LF: u8 = '\n' as u8;
const SPACE: u8 = ' ' as u8;
const TAB: u8 = '\t' as u8;
const SYN: u8 = 0x16 as u8;
const FF: u8 = 0x0C as u8;

#[inline(always)]
fn is_word_seperator(byte: u8) -> bool {
    byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF
}

pub fn wc(matches: &Matches) -> StdResult<(), i32> {
    let mut total_line_count: usize = 0;
    let mut total_word_count: usize = 0;
    let mut total_char_count: usize = 0;
    let mut total_byte_count: usize = 0;
    let mut total_longest_line_length: usize = 0;

    let mut results = vec!();
    let mut max_str_len: usize = 0;

    for path in matches.free.iter() {
        let mut reader = try!(open(&path[..]));

        let mut line_count: usize = 0;
        let mut word_count: usize = 0;
        let mut byte_count: usize = 0;
        let mut char_count: usize = 0;
        let mut longest_line_length: usize = 0;
        let mut raw_line = Vec::new();

        // reading from a TTY seems to raise a condition on, rather than return Some(0) like a file.
        // hence the option wrapped in a result here
        while match reader.read_until(LF, &mut raw_line) {
            Ok(n) if n > 0 => true,
            Err(ref e) if raw_line.len() > 0 => {
                show_warning!("Error while reading {}: {}", path, e);
                raw_line.len() > 0
            },
            _ => false,
        } {
            // GNU 'wc' only counts lines that end in LF as lines
            if *raw_line.last().unwrap() == LF {
                line_count += 1;
            }

            byte_count += raw_line.len();

            // try and convert the bytes to UTF-8 first
            let current_char_count;
            match from_utf8(&raw_line[..]) {
                Ok(line) => {
                    word_count += line.split_whitespace().count();
                    current_char_count = line.chars().count();
                },
                Err(..) => {
                    word_count += raw_line.split(|&x| is_word_seperator(x)).count();
                    current_char_count = raw_line.iter().filter(|c|c.is_ascii()).count()
                }
            }
            char_count += current_char_count;

            if current_char_count > longest_line_length {
                // we subtract one here because `line.len()` includes the LF
                // matches GNU 'wc' behaviour
                longest_line_length = current_char_count - 1;
            }

            raw_line.truncate(0);
        }

        results.push(Result {
            filename: path.to_string(),
            bytes: byte_count,
            chars: char_count,
            lines: line_count,
            words: word_count,
            max_line_length: longest_line_length,
        });

        total_line_count += line_count;
        total_word_count += word_count;
        total_char_count += char_count;
        total_byte_count += byte_count;

        if longest_line_length > total_longest_line_length {
            total_longest_line_length = longest_line_length;
        }

        // used for formatting
        max_str_len = total_byte_count.to_string().len();
    }

    for result in results.iter() {
        print_stats(&result.filename[..], result.lines, result.words, result.chars, result.bytes, result.max_line_length, matches, max_str_len);
    }

    if matches.free.len() > 1 {
        print_stats("total", total_line_count, total_word_count, total_char_count, total_byte_count, total_longest_line_length, matches, max_str_len);
    }

    Ok(())
}

fn print_stats(filename: &str, line_count: usize, word_count: usize, char_count: usize,
    byte_count: usize, longest_line_length: usize, matches: &Matches, max_str_len: usize) {
    if matches.opt_present("lines") {
        print!("{:1$}", line_count, max_str_len);
    }
    if matches.opt_present("words") {
        print!("{:1$}", word_count, max_str_len);
    }
    if matches.opt_present("bytes") {
        print!("{:1$}", byte_count, max_str_len);
    }
    if matches.opt_present("chars") {
        print!("{:1$}", char_count, max_str_len);
    }
    if matches.opt_present("max-line-length") {
        print!("{:1$}", longest_line_length, max_str_len);
    }

    // defaults
    if !matches.opt_present("bytes")
        && !matches.opt_present("chars")
        && !matches.opt_present("lines")
        && !matches.opt_present("words")
        && !matches.opt_present("max-line-length") {
        print!("{:1$}", line_count, max_str_len);
        print!("{:1$}", word_count, max_str_len + 1);
        print!("{:1$}", byte_count, max_str_len + 1);
    }

    if filename != "-" {
        println!(" {}", filename);
    }
    else {
        println!("");
    }
}

fn open(path: &str) -> StdResult<BufReader<Box<Read+'static>>, i32> {
    if "-" == path {
        let reader = Box::new(stdin()) as Box<Read>;
        return Ok(BufReader::new(reader));
    }

    let fpath = Path::new(path);
    if fpath.is_dir() {
        show_info!("{}: is a directory", path);
    }
    match File::open(&fpath) {
        Ok(fd) => {
            let reader = Box::new(fd) as Box<Read>;
            Ok(BufReader::new(reader))
        }
        Err(e) => {
            show_error!("wc: {}: {}", path, e);
            Err(1)
        }
    }
}
<|endoftext|>


<commit_before>extern crate pdb;

use std::env;
use std::ffi::OsStr;
use std::io::Write;

fn dump_stream_names(filename: &OsStr) -> pdb::Result<()> {
    let file = std::fs::File::open(filename)?;
    let mut pdb = pdb::PDB::open(file)?;
    let info = pdb.pdb_information()?;
    let names = info.stream_names()?;
    println!("index, name");
    for name in names.iter() {
        println!("{:5}, {}", name.stream_id, name.name);
    }
    Ok(())
}

fn main() {
    let filename = env::args_os().nth(1).expect("Missing PDB filename");

    match dump_stream_names(&filename) {
        Ok(_) => {}
        Err(e) => {
            writeln!(&mut std::io::stderr(), "error dumping PDB: {}", e)
                .expect("stderr write");
        }
    }
}
<commit_msg>Expand stream_names example a little bit<commit_after>extern crate pdb;

use std::env;
use std::ffi::OsStr;
use std::io::Write;

fn dump_stream_names(filename: &OsStr) -> pdb::Result<()> {
    let file = std::fs::File::open(filename)?;
    let mut pdb = pdb::PDB::open(file)?;
    let info = pdb.pdb_information()?;
    let names = info.stream_names()?;
    println!("index, name");
    for name in names.iter() {
        let stream = pdb.raw_stream(name.stream_id)?;
        println!("{:5}, {} {} bytes", name.stream_id, name.name, stream.parse_buffer().len());
    }
    Ok(())
}

fn main() {
    let filename = env::args_os().nth(1).expect("Missing PDB filename");

    match dump_stream_names(&filename) {
        Ok(_) => {}
        Err(e) => {
            writeln!(&mut std::io::stderr(), "error dumping PDB: {}", e)
                .expect("stderr write");
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_list_t,cef_string_t};

//cef_string_list

#[no_mangle]
pub extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
    unsafe {
         let lt: Box<Vec<*mut cef_string_t>> = box vec!();
         mem::transmute(lt)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_size(lt: *const cef_string_list_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        v.len() as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *const cef_string_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let cs = cef_string_userfree_utf8_alloc();
        cef_string_utf8_set(mem::transmute((*value).str), (*value).length, cs, 1);
        v.push(cs);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if index as uint > v.len() - 1 { return 0; }
        let cs = v.get(index as uint);
        cef_string_utf8_set(mem::transmute((**cs).str), (**cs).length, value, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if v.len() == 0 { return; }
        let mut cs;
        while v.len() != 0 {
            cs = v.pop();
            cef_string_userfree_utf8_free(cs.unwrap());
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        cef_string_list_clear(lt);
        drop(v);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_copy(lt: *mut cef_string_list_t) -> *mut cef_string_list_t {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0 as *mut cef_string_list_t; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let lt2 = cef_string_list_alloc();
        for cs in v.iter() {
            cef_string_list_append(lt2, mem::transmute((*cs)));
        }
        lt2
    }
}
<commit_msg>auto merge of #3785 : zmike/servo/embedding-fixups-for-string_list, r=larsbergstrom<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_list_t,cef_string_t};

fn string_map_to_vec(lt: *mut cef_string_list_t) -> *mut Vec<*mut cef_string_t> {
    lt as *mut Vec<*mut cef_string_t>
}

//cef_string_list

#[no_mangle]
pub extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
    unsafe {
         let lt: Box<Vec<*mut cef_string_t>> = box vec!();
         mem::transmute(lt)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_size(lt: *mut cef_string_list_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0; }
        let v = string_map_to_vec(lt);
        (*v).len() as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *const cef_string_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let v = string_map_to_vec(lt);
        let cs = cef_string_userfree_utf8_alloc();
        cef_string_utf8_set(mem::transmute((*value).str), (*value).length, cs, 1);
        (*v).push(cs);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || fptr_is_null(mem::transmute(lt)) { return 0; }
        let v = string_map_to_vec(lt);
        if index as uint > (*v).len() - 1 { return 0; }
        let cs = (*v).get(index as uint);
        cef_string_utf8_set(mem::transmute((**cs).str), (**cs).length, value, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let v = string_map_to_vec(lt);
        if (*v).len() == 0 { return; }
        let mut cs;
        while (*v).len() != 0 {
            cs = (*v).pop();
            cef_string_userfree_utf8_free(cs.unwrap());
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        cef_string_list_clear(lt);
        drop(v);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_copy(lt: *mut cef_string_list_t) -> *mut cef_string_list_t {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0 as *mut cef_string_list_t; }
        let v = string_map_to_vec(lt);
        let lt2 = cef_string_list_alloc();
        for cs in (*v).iter() {
            cef_string_list_append(lt2, mem::transmute((*cs)));
        }
        lt2
    }
}
<|endoftext|>


<commit_before>use core::mem::*;

#[test]
fn size_of_basic() {
    assert_eq!(size_of::<u8>(), 1);
    assert_eq!(size_of::<u16>(), 2);
    assert_eq!(size_of::<u32>(), 4);
    assert_eq!(size_of::<u64>(), 8);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn size_of_16() {
    assert_eq!(size_of::<usize>(), 2);
    assert_eq!(size_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn size_of_32() {
    assert_eq!(size_of::<usize>(), 4);
    assert_eq!(size_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn size_of_64() {
    assert_eq!(size_of::<usize>(), 8);
    assert_eq!(size_of::<*const usize>(), 8);
}

#[test]
fn size_of_val_basic() {
    assert_eq!(size_of_val(&1u8), 1);
    assert_eq!(size_of_val(&1u16), 2);
    assert_eq!(size_of_val(&1u32), 4);
    assert_eq!(size_of_val(&1u64), 8);
}

#[test]
fn align_of_basic() {
    assert_eq!(align_of::<u8>(), 1);
    assert_eq!(align_of::<u16>(), 2);
    assert_eq!(align_of::<u32>(), 4);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn align_of_16() {
    assert_eq!(align_of::<usize>(), 2);
    assert_eq!(align_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn align_of_32() {
    assert_eq!(align_of::<usize>(), 4);
    assert_eq!(align_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn align_of_64() {
    assert_eq!(align_of::<usize>(), 8);
    assert_eq!(align_of::<*const usize>(), 8);
}

#[test]
fn align_of_val_basic() {
    assert_eq!(align_of_val(&1u8), 1);
    assert_eq!(align_of_val(&1u16), 2);
    assert_eq!(align_of_val(&1u32), 4);
}

#[test]
fn test_swap() {
    let mut x = 31337;
    let mut y = 42;
    swap(&mut x, &mut y);
    assert_eq!(x, 42);
    assert_eq!(y, 31337);
}

#[test]
fn test_replace() {
    let mut x = Some("test".to_string());
    let y = replace(&mut x, None);
    assert!(x.is_none());
    assert!(y.is_some());
}

#[test]
fn test_transmute_copy() {
    assert_eq!(1, unsafe { transmute_copy(&1) });
}

#[test]
fn test_transmute() {
    trait Foo {
        fn dummy(&self) {}
    }
    impl Foo for isize {}

    let a = box 100isize as Box<dyn Foo>;
    unsafe {
        let x: ::core::raw::TraitObject = transmute(a);
        assert!(*(x.data as *const isize) == 100);
        let _x: Box<dyn Foo> = transmute(x);
    }

    unsafe {
        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
    }
}

#[test]
#[allow(dead_code)]
fn test_discriminant_send_sync() {
    enum Regular {
        A,
        B(i32),
    }
    enum NotSendSync {
        A(*const i32),
    }

    fn is_send_sync<T: Send + Sync>() {}

    is_send_sync::<Discriminant<Regular>>();
    is_send_sync::<Discriminant<NotSendSync>>();
}

#[test]
fn test_const_forget() {
    const fn test_const_forget<T>(x: T) {
        forget(x);
    }

    // Writing this function signature without const-forget
    // triggers compiler errors:
    // 1) That we use a non-const fn inside a const fn
    // 2) without the forget, it complains about the destructor of Box
    const fn const_forget_box<T>(mut x: Box<T>) {
        forget(x);
    }

    const _: () = test_const_forget(0i32);
    const _: () = test_const_forget(Vec::<Vec<Box<i32>>>::new());
}
<commit_msg>remove unused mut, restructure the test<commit_after>use core::mem::*;

#[test]
fn size_of_basic() {
    assert_eq!(size_of::<u8>(), 1);
    assert_eq!(size_of::<u16>(), 2);
    assert_eq!(size_of::<u32>(), 4);
    assert_eq!(size_of::<u64>(), 8);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn size_of_16() {
    assert_eq!(size_of::<usize>(), 2);
    assert_eq!(size_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn size_of_32() {
    assert_eq!(size_of::<usize>(), 4);
    assert_eq!(size_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn size_of_64() {
    assert_eq!(size_of::<usize>(), 8);
    assert_eq!(size_of::<*const usize>(), 8);
}

#[test]
fn size_of_val_basic() {
    assert_eq!(size_of_val(&1u8), 1);
    assert_eq!(size_of_val(&1u16), 2);
    assert_eq!(size_of_val(&1u32), 4);
    assert_eq!(size_of_val(&1u64), 8);
}

#[test]
fn align_of_basic() {
    assert_eq!(align_of::<u8>(), 1);
    assert_eq!(align_of::<u16>(), 2);
    assert_eq!(align_of::<u32>(), 4);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn align_of_16() {
    assert_eq!(align_of::<usize>(), 2);
    assert_eq!(align_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn align_of_32() {
    assert_eq!(align_of::<usize>(), 4);
    assert_eq!(align_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn align_of_64() {
    assert_eq!(align_of::<usize>(), 8);
    assert_eq!(align_of::<*const usize>(), 8);
}

#[test]
fn align_of_val_basic() {
    assert_eq!(align_of_val(&1u8), 1);
    assert_eq!(align_of_val(&1u16), 2);
    assert_eq!(align_of_val(&1u32), 4);
}

#[test]
fn test_swap() {
    let mut x = 31337;
    let mut y = 42;
    swap(&mut x, &mut y);
    assert_eq!(x, 42);
    assert_eq!(y, 31337);
}

#[test]
fn test_replace() {
    let mut x = Some("test".to_string());
    let y = replace(&mut x, None);
    assert!(x.is_none());
    assert!(y.is_some());
}

#[test]
fn test_transmute_copy() {
    assert_eq!(1, unsafe { transmute_copy(&1) });
}

#[test]
fn test_transmute() {
    trait Foo {
        fn dummy(&self) {}
    }
    impl Foo for isize {}

    let a = box 100isize as Box<dyn Foo>;
    unsafe {
        let x: ::core::raw::TraitObject = transmute(a);
        assert!(*(x.data as *const isize) == 100);
        let _x: Box<dyn Foo> = transmute(x);
    }

    unsafe {
        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
    }
}

#[test]
#[allow(dead_code)]
fn test_discriminant_send_sync() {
    enum Regular {
        A,
        B(i32),
    }
    enum NotSendSync {
        A(*const i32),
    }

    fn is_send_sync<T: Send + Sync>() {}

    is_send_sync::<Discriminant<Regular>>();
    is_send_sync::<Discriminant<NotSendSync>>();
}

#[test]
fn test_const_forget() {
    const _: () = forget(0i32);
    const _: () = forget(Vec::<Vec<Box<i32>>>::new());

    // Writing this function signature without const-forget
    // triggers compiler errors:
    // 1) That we use a non-const fn inside a const fn
    // 2) without the forget, it complains about the destructor of Box
    const fn const_forget_box<T>(x: Box<T>) {
        forget(x);
    }

    // Call the forget_box at runtime,
    // as we can't const-construct a box yet.
    const_forget_box(Box::new(0i32));
}
<|endoftext|>


<commit_before>/* TOOD: Implement for other kqueue based systems
 */

use {Errno, Result};
#[cfg(not(target_os = "netbsd"))]
use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
#[cfg(target_os = "netbsd")]
use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
use libc;
use std::os::unix::io::RawFd;
use std::ptr;

// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct KEvent {
    pub ident: uintptr_t,
    pub filter: EventFilter,
    pub flags: EventFlag,
    pub fflags: FilterFlag,
    pub data: intptr_t,
    // libc defines udata as a pointer on most OSes.  But it's really
    // more like an arbitrary tag
    pub udata: uintptr_t
}

#[cfg(not(target_os = "netbsd"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_AIO = libc::EVFILT_AIO,
    #[cfg(target_os = "dragonfly")]
    EVFILT_EXCEPT = libc::EVFILT_EXCEPT,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_FS = libc::EVFILT_FS,
    #[cfg(target_os = "freebsd")]
    EVFILT_LIO = libc::EVFILT_LIO,
    #[cfg(target_os = "macos")]
    EVFILT_MACHPORT = libc::EVFILT_MACHPORT,
    EVFILT_PROC = libc::EVFILT_PROC,
    #[cfg(target_os = "freebsd")]
    EVFILT_PROCDESC = libc::EVFILT_PROCDESC,
    EVFILT_READ = libc::EVFILT_READ,
    #[cfg(target_os = "freebsd")]
    EVFILT_SENDFILE = libc::EVFILT_SENDFILE,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_SYSCOUNT = libc::EVFILT_SYSCOUNT,
    EVFILT_TIMER = libc::EVFILT_TIMER,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_USER = libc::EVFILT_USER,
    #[cfg(target_os = "macos")]
    EVFILT_VM = libc::EVFILT_VM,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_WRITE = libc::EVFILT_WRITE,
}

#[cfg(target_os = "netbsd")]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_WRITE = libc::EVFILT_WRITE,
    EVFILT_AIO = libc::EVFILT_AIO,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
    EVFILT_SYSCOUNT = libc::EVFILT_SYSCOUNT,
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly"))]
bitflags!(
    flags EventFlag: u16 {
        const EV_ADD       = libc::EV_ADD,
        const EV_CLEAR     = libc::EV_CLEAR,
        const EV_DELETE    = libc::EV_DELETE,
        const EV_DISABLE   = libc::EV_DISABLE,
        const EV_DISPATCH  = libc::EV_DISPATCH,
        #[cfg(target_os = "freebsd")]
        const EV_DROP      = libc::EV_DROP,
        const EV_ENABLE    = libc::EV_ENABLE,
        const EV_EOF       = libc::EV_EOF,
        const EV_ERROR     = libc::EV_ERROR,
        #[cfg(target_os = "macos")]
        const EV_FLAG0     = libc::EV_FLAG0,
        const EV_FLAG1     = libc::EV_FLAG1,
        #[cfg(target_os = "freebsd")]
        const EV_FLAG2     = libc::EV_FLAG2,
        #[cfg(target_os = "freebsd")]
        const EV_FORCEONESHOT = libc::EV_FORCEONESHOT,
        #[cfg(target_os = "dragonfly")]
        const EV_NODATA    = libc::EV_NODATA,
        const EV_ONESHOT   = libc::EV_ONESHOT,
        #[cfg(target_os = "macos")]
        const EV_OOBAND    = libc::EV_OOBAND,
        #[cfg(target_os = "macos")]
        const EV_POLL      = libc::EV_POLL,
        const EV_RECEIPT   = libc::EV_RECEIPT,
        const EV_SYSFLAGS  = libc::EV_SYSFLAGS,
    }
);

#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
bitflags!(
    flags EventFlag: u32 {
        const EV_ADD       = libc::EV_ADD,
        const EV_DELETE    = libc::EV_DELETE,
        const EV_ENABLE    = libc::EV_ENABLE,
        const EV_DISABLE   = libc::EV_DISABLE,
        const EV_ONESHOT   = libc::EV_ONESHOT,
        const EV_CLEAR     = libc::EV_CLEAR,
        #[cfg(target_os = "openbsd")]
        const EV_FLAG1     = libc::EV_FLAG1,
        #[cfg(target_os = "netbsd")]
        const EV_RECEIPT   = libc::EV_RECEIPT,
        const EV_DISPATCH  = libc::EV_DISPATCH,
        const EV_SYSFLAGS  = libc::EV_SYSFLAGS,
        const EV_FLAG1     = libc::EV_FLAG1,
        const EV_EOF       = libc::EV_EOF,
        const EV_ERROR     = libc::EV_ERROR,
    }
);

bitflags!(
    flags FilterFlag: u32 {
        #[cfg(target_os = "macos")]
        const NOTE_ABSOLUTE                        = libc::NOTE_ABSOLUTE,
        #[cfg(target_os = "macos")]
        const NOTE_APPACTIVE                       = libc::NOTE_APPACTIVE,
        #[cfg(target_os = "macos")]
        const NOTE_APPALLSTATES                    = libc::NOTE_APPALLSTATES,
        #[cfg(target_os = "macos")]
        const NOTE_APPBACKGROUND                   = libc::NOTE_APPBACKGROUND,
        #[cfg(target_os = "macos")]
        const NOTE_APPINACTIVE                     = libc::NOTE_APPINACTIVE,
        #[cfg(target_os = "macos")]
        const NOTE_APPNONUI                        = libc::NOTE_APPNONUI,
        const NOTE_ATTRIB                          = libc::NOTE_ATTRIB,
        const NOTE_CHILD                           = libc::NOTE_CHILD,
        #[cfg(target_os = "freebsd")]
        const NOTE_CLOSE                           = libc::NOTE_CLOSE,
        #[cfg(target_os = "freebsd")]
        const NOTE_CLOSE_WRITE                     = libc::NOTE_CLOSE_WRITE,
        const NOTE_DELETE                          = libc::NOTE_DELETE,
        #[cfg(target_os = "openbsd")]
        const NOTE_EOF                             = libc::NOTE_EOF,
        const NOTE_EXEC                            = libc::NOTE_EXEC,
        const NOTE_EXIT                            = libc::NOTE_EXIT,
        #[cfg(target_os = "macos")]
        const NOTE_EXIT_REPARENTED                 = libc::NOTE_EXIT_REPARENTED,
        #[cfg(target_os = "macos")]
        const NOTE_EXITSTATUS                      = libc::NOTE_EXITSTATUS,
        const NOTE_EXTEND                          = libc::NOTE_EXTEND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFAND                           = libc::NOTE_FFAND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCOPY                          = libc::NOTE_FFCOPY,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCTRLMASK                      = libc::NOTE_FFCTRLMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFLAGSMASK                      = libc::NOTE_FFLAGSMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFNOP                           = libc::NOTE_FFNOP,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFOR                            = libc::NOTE_FFOR,
        #[cfg(target_os = "freebsd")]
        const NOTE_FILE_POLL                       = libc::NOTE_FILE_POLL,
        const NOTE_FORK                            = libc::NOTE_FORK,
        const NOTE_LINK                            = libc::NOTE_LINK,
        const NOTE_LOWAT                           = libc::NOTE_LOWAT,
        #[cfg(target_os = "freebsd")]
        const NOTE_MSECONDS                        = libc::NOTE_MSECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_NONE                            = libc::NOTE_NONE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_NSECONDS                        = libc::NOTE_NSECONDS,
        #[cfg(target_os = "dragonfly")]
        const NOTE_OOB                             = libc::NOTE_OOB,
        #[cfg(target_os = "freebsd")]
        const NOTE_OPEN                            = libc::NOTE_OPEN,
        const NOTE_PCTRLMASK                       = libc::NOTE_PCTRLMASK,
        const NOTE_PDATAMASK                       = libc::NOTE_PDATAMASK,
        #[cfg(target_os = "freebsd")]
        const NOTE_READ                            = libc::NOTE_READ,
        #[cfg(target_os = "macos")]
        const NOTE_REAP                            = libc::NOTE_REAP,
        const NOTE_RENAME                          = libc::NOTE_RENAME,
        #[cfg(target_os = "macos")]
        const NOTE_RESOURCEEND                     = libc::NOTE_RESOURCEEND,
        const NOTE_REVOKE                          = libc::NOTE_REVOKE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_SECONDS                         = libc::NOTE_SECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_SIGNAL                          = libc::NOTE_SIGNAL,
        const NOTE_TRACK                           = libc::NOTE_TRACK,
        const NOTE_TRACKERR                        = libc::NOTE_TRACKERR,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_TRIGGER                         = libc::NOTE_TRIGGER,
        #[cfg(target_os = "openbsd")]
        const NOTE_TRUNCATE                        = libc::NOTE_TRUNCATE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_USECONDS                        = libc::NOTE_USECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_VM_ERROR                        = libc::NOTE_VM_ERROR,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE                     = libc::NOTE_VM_PRESSURE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_TERMINATE           = libc::NOTE_VM_PRESSURE_TERMINATE,
        const NOTE_WRITE                           = libc::NOTE_WRITE,
    }
);

pub fn kqueue() -> Result<RawFd> {
    let res = unsafe { libc::kqueue() };

    Errno::result(res)
}

pub fn kevent(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: usize) -> Result<usize> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    kevent_ts(kq, changelist, eventlist, Some(timeout))
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {

    let res = unsafe {
        libc::kevent(
            kq,
            changelist.as_ptr() as *const libc::kevent,
            changelist.len() as c_int,
            eventlist.as_mut_ptr() as *mut libc::kevent,
            eventlist.len() as c_int,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    Errno::result(res).map(|r| r as usize)
}

#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {

    let res = unsafe {
        libc::kevent(
            kq,
            changelist.as_ptr() as *const libc::kevent,
            changelist.len() as size_t,
            eventlist.as_mut_ptr() as *mut libc::kevent,
            eventlist.len() as size_t,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    Errno::result(res).map(|r| r as usize)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: usize,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: uintptr_t) {

    ev.ident  = ident as uintptr_t;
    ev.filter = filter;
    ev.flags  = flags;
    ev.fflags = fflags;
    ev.data   = 0;
    ev.udata  = udata;
}
<commit_msg>Reconcile with libc changes<commit_after>/* TOOD: Implement for other kqueue based systems
 */

use {Errno, Result};
#[cfg(not(target_os = "netbsd"))]
use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
#[cfg(target_os = "netbsd")]
use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
use libc;
use std::os::unix::io::RawFd;
use std::ptr;

// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct KEvent {
    pub ident: uintptr_t,
    pub filter: EventFilter,
    pub flags: EventFlag,
    pub fflags: FilterFlag,
    pub data: intptr_t,
    // libc defines udata as a pointer on most OSes.  But it's really
    // more like an arbitrary tag
    pub udata: uintptr_t
}

#[cfg(not(target_os = "netbsd"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_AIO = libc::EVFILT_AIO,
    #[cfg(target_os = "dragonfly")]
    EVFILT_EXCEPT = libc::EVFILT_EXCEPT,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_FS = libc::EVFILT_FS,
    #[cfg(target_os = "freebsd")]
    EVFILT_LIO = libc::EVFILT_LIO,
    #[cfg(target_os = "macos")]
    EVFILT_MACHPORT = libc::EVFILT_MACHPORT,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_USER = libc::EVFILT_USER,
    #[cfg(target_os = "macos")]
    EVFILT_VM = libc::EVFILT_VM,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_WRITE = libc::EVFILT_WRITE,
}

#[cfg(target_os = "netbsd")]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_WRITE = libc::EVFILT_WRITE,
    EVFILT_AIO = libc::EVFILT_AIO,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly"))]
bitflags!(
    flags EventFlag: u16 {
        const EV_ADD       = libc::EV_ADD,
        const EV_CLEAR     = libc::EV_CLEAR,
        const EV_DELETE    = libc::EV_DELETE,
        const EV_DISABLE   = libc::EV_DISABLE,
        const EV_DISPATCH  = libc::EV_DISPATCH,
        #[cfg(target_os = "freebsd")]
        const EV_DROP      = libc::EV_DROP,
        const EV_ENABLE    = libc::EV_ENABLE,
        const EV_EOF       = libc::EV_EOF,
        const EV_ERROR     = libc::EV_ERROR,
        #[cfg(target_os = "macos")]
        const EV_FLAG0     = libc::EV_FLAG0,
        const EV_FLAG1     = libc::EV_FLAG1,
        #[cfg(target_os = "dragonfly")]
        const EV_NODATA    = libc::EV_NODATA,
        const EV_ONESHOT   = libc::EV_ONESHOT,
        #[cfg(target_os = "macos")]
        const EV_OOBAND    = libc::EV_OOBAND,
        #[cfg(target_os = "macos")]
        const EV_POLL      = libc::EV_POLL,
        const EV_RECEIPT   = libc::EV_RECEIPT,
        const EV_SYSFLAGS  = libc::EV_SYSFLAGS,
    }
);

#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
bitflags!(
    flags EventFlag: u32 {
        const EV_ADD       = libc::EV_ADD,
        const EV_DELETE    = libc::EV_DELETE,
        const EV_ENABLE    = libc::EV_ENABLE,
        const EV_DISABLE   = libc::EV_DISABLE,
        const EV_ONESHOT   = libc::EV_ONESHOT,
        const EV_CLEAR     = libc::EV_CLEAR,
        #[cfg(target_os = "openbsd")]
        const EV_FLAG1     = libc::EV_FLAG1,
        #[cfg(target_os = "netbsd")]
        const EV_RECEIPT   = libc::EV_RECEIPT,
        const EV_DISPATCH  = libc::EV_DISPATCH,
        const EV_SYSFLAGS  = libc::EV_SYSFLAGS,
        const EV_FLAG1     = libc::EV_FLAG1,
        const EV_EOF       = libc::EV_EOF,
        const EV_ERROR     = libc::EV_ERROR,
    }
);

bitflags!(
    flags FilterFlag: u32 {
        #[cfg(target_os = "macos")]
        const NOTE_ABSOLUTE                        = libc::NOTE_ABSOLUTE,
        #[cfg(target_os = "macos")]
        const NOTE_APPACTIVE                       = libc::NOTE_APPACTIVE,
        #[cfg(target_os = "macos")]
        const NOTE_APPALLSTATES                    = libc::NOTE_APPALLSTATES,
        #[cfg(target_os = "macos")]
        const NOTE_APPBACKGROUND                   = libc::NOTE_APPBACKGROUND,
        #[cfg(target_os = "macos")]
        const NOTE_APPINACTIVE                     = libc::NOTE_APPINACTIVE,
        #[cfg(target_os = "macos")]
        const NOTE_APPNONUI                        = libc::NOTE_APPNONUI,
        const NOTE_ATTRIB                          = libc::NOTE_ATTRIB,
        const NOTE_CHILD                           = libc::NOTE_CHILD,
        const NOTE_DELETE                          = libc::NOTE_DELETE,
        #[cfg(target_os = "openbsd")]
        const NOTE_EOF                             = libc::NOTE_EOF,
        const NOTE_EXEC                            = libc::NOTE_EXEC,
        const NOTE_EXIT                            = libc::NOTE_EXIT,
        #[cfg(target_os = "macos")]
        const NOTE_EXIT_REPARENTED                 = libc::NOTE_EXIT_REPARENTED,
        #[cfg(target_os = "macos")]
        const NOTE_EXITSTATUS                      = libc::NOTE_EXITSTATUS,
        const NOTE_EXTEND                          = libc::NOTE_EXTEND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFAND                           = libc::NOTE_FFAND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCOPY                          = libc::NOTE_FFCOPY,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCTRLMASK                      = libc::NOTE_FFCTRLMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFLAGSMASK                      = libc::NOTE_FFLAGSMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFNOP                           = libc::NOTE_FFNOP,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFOR                            = libc::NOTE_FFOR,
        const NOTE_FORK                            = libc::NOTE_FORK,
        const NOTE_LINK                            = libc::NOTE_LINK,
        const NOTE_LOWAT                           = libc::NOTE_LOWAT,
        #[cfg(target_os = "freebsd")]
        const NOTE_MSECONDS                        = libc::NOTE_MSECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_NONE                            = libc::NOTE_NONE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_NSECONDS                        = libc::NOTE_NSECONDS,
        #[cfg(target_os = "dragonfly")]
        const NOTE_OOB                             = libc::NOTE_OOB,
        const NOTE_PCTRLMASK                       = libc::NOTE_PCTRLMASK,
        const NOTE_PDATAMASK                       = libc::NOTE_PDATAMASK,
        #[cfg(target_os = "macos")]
        const NOTE_REAP                            = libc::NOTE_REAP,
        const NOTE_RENAME                          = libc::NOTE_RENAME,
        #[cfg(target_os = "macos")]
        const NOTE_RESOURCEEND                     = libc::NOTE_RESOURCEEND,
        const NOTE_REVOKE                          = libc::NOTE_REVOKE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_SECONDS                         = libc::NOTE_SECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_SIGNAL                          = libc::NOTE_SIGNAL,
        const NOTE_TRACK                           = libc::NOTE_TRACK,
        const NOTE_TRACKERR                        = libc::NOTE_TRACKERR,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_TRIGGER                         = libc::NOTE_TRIGGER,
        #[cfg(target_os = "openbsd")]
        const NOTE_TRUNCATE                        = libc::NOTE_TRUNCATE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_USECONDS                        = libc::NOTE_USECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_VM_ERROR                        = libc::NOTE_VM_ERROR,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE                     = libc::NOTE_VM_PRESSURE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_TERMINATE           = libc::NOTE_VM_PRESSURE_TERMINATE,
        const NOTE_WRITE                           = libc::NOTE_WRITE,
    }
);

pub fn kqueue() -> Result<RawFd> {
    let res = unsafe { libc::kqueue() };

    Errno::result(res)
}

pub fn kevent(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: usize) -> Result<usize> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    kevent_ts(kq, changelist, eventlist, Some(timeout))
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd"))]
pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {

    let res = unsafe {
        libc::kevent(
            kq,
            changelist.as_ptr() as *const libc::kevent,
            changelist.len() as c_int,
            eventlist.as_mut_ptr() as *mut libc::kevent,
            eventlist.len() as c_int,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    Errno::result(res).map(|r| r as usize)
}

#[cfg(target_os = "netbsd")]
pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {

    let res = unsafe {
        libc::kevent(
            kq,
            changelist.as_ptr() as *const libc::kevent,
            changelist.len() as size_t,
            eventlist.as_mut_ptr() as *mut libc::kevent,
            eventlist.len() as size_t,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    Errno::result(res).map(|r| r as usize)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: usize,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: uintptr_t) {

    ev.ident  = ident as uintptr_t;
    ev.filter = filter;
    ev.flags  = flags;
    ev.fflags = fflags;
    ev.data   = 0;
    ev.udata  = udata;
}
<|endoftext|>


<commit_before>/// generates images used to test NMF

use std::ops::{Index, IndexMut, Mul, Add, Div};

use std;

use std::cmp::PartialOrd;

use std::ops::Range;
use std::iter::{Map, Rev, once, Once, Chain, Zip};

extern crate num;
use num::traits::{Zero, One, FromPrimitive, ToPrimitive, Float};

extern crate nalgebra;
use nalgebra::{DMat, DVec, Norm, BaseFloat};

extern crate image;
use self::image::{ImageBuffer, Luma, DynamicImage};

use partialmax::PartialMaxIteratorExt;

quick_error! {
    #[derive(Debug)]
    pub enum ImageSaveError {
        /// an error has occured when opening the file
        Io(err: std::io::Error) {}
        /// an error has occured when writing the image into the file
        Image(err: image::ImageError) {}
    }
}

// TODO suffix ReturnT
pub type Horizontal<T> = Map<Range<usize>, fn(usize) -> T>;
pub type Vertical<T> = Map<Rev<Range<usize>>, fn(usize) -> T>;
pub type Static<T> = Chain<Chain<Chain<Once<T>, Vertical<T>>, Once<T>>, Horizontal<T>>;
pub type Test<T> = Map<Zip<Horizontal<T>, Vertical<T>>, fn((T, T)) -> T>;

// TODO move the type constraints back up here
// TODO split into multiple traits
// normalize
// images
// creation
pub trait Testimage<T> {
    type Item;

    /// returns a testimage that has `1` in `row` for all `cols` and `0` everywhere else
    ///
    /// ```
    /// Testimage::new_horizontal_line(9, 0..5);
    /// ```
    fn new_horizontal_line<I: Iterator<Item = usize>>(row: usize, cols: I) -> Self where Self::Item: Clone + Copy + Zero + One;
    /// returns a testimage that has `1` in `col` for all `rows` and `0` everywhere else
    ///
    /// ```
    /// Testimage::new_vertical_line(5..10, 0);
    /// ```
    fn new_vertical_line<I: Iterator<Item = usize>>(rows: I, col: usize) -> Self where Self::Item: Clone + Copy + Zero + One;
    /// # Panics
    /// panics unless all the values in `self` are between
    /// `0` (inclusive) and `1` (inclusive)
    fn luma01_to_image(&self) -> DynamicImage where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float;
    /// # Panics
    /// panics unless all the values in `self` are between
    /// `0` (inclusive) and `1` (inclusive)
    fn save_luma01_to_png(&self, filename: &str) -> Result<(), ImageSaveError> where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float;
    fn static_factors() -> Static<Self>
        where Self: Sized,
              Self::Item: Clone + Copy + Zero + One;
    // TODO it's probably a much better idea to just use plain functions here
    fn horizontal_evolving_factors() -> Horizontal<Self> where Self::Item: Clone + Copy + Zero + One;
    fn vertical_evolving_factors() -> Vertical<Self> where Self::Item: Clone + Copy + Zero + One;
    // TODO trait
    fn linear_combination<C>(factors: &[Self], coefficients: &[C]) -> Self
        where C: Clone,
              Self: Sized + Mul<C, Output = Self>,
              Self::Item: Clone + Copy + Zero;
    fn normalize_mut(self) -> Self
        where Self::Item: Clone + Copy + BaseFloat,
              Self: Div<T, Output = Self>,
              Self: Sized;
    fn testimages() -> Test<Self> where Self::Item: Clone + Copy + Zero + One + BaseFloat;
}

impl<T> Testimage<T> for DMat<T> {
    // here's where we associate Self::Item and T
    type Item = T;

    fn new_horizontal_line<I: Iterator<Item = usize>>(row: usize, cols: I) -> Self
        where Self::Item: Clone + Copy + Zero + One
    {
        let mut factor: DMat<Self::Item> = DMat::new_zeros(10, 10);
        for col in cols {
            *factor.index_mut((row, col)) = Self::Item::one();
        }
        factor
    }

    fn new_vertical_line<I: Iterator<Item = usize>>(rows: I, col: usize) -> Self
        where Self::Item: Clone + Copy + Zero + One
    {
        let mut factor: DMat<Self::Item> = DMat::new_zeros(10, 10);
        for row in rows {
            *factor.index_mut((row, col)) = Self::Item::one();
        }
        factor
    }

    fn luma01_to_image(&self) -> DynamicImage
        where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float
    {
        let mut image_buffer = ImageBuffer::new(self.ncols() as u32, self.nrows() as u32);
        for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
            let value = self.index((y as usize, x as usize));
            assert!(Self::Item::zero() <= *value);
            assert!(*value <= Self::Item::one());
            let max = Self::Item::from_u8(std::u8::MAX).unwrap();
            let byte = (*value * max).round().to_u8().unwrap();
            *pixel = Luma([byte]);
        }
        DynamicImage::ImageLuma8(image_buffer)
    }

    fn save_luma01_to_png(&self, filename: &str) -> Result<(), ImageSaveError>
        where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float
    {
        let image = self.luma01_to_image();
        let path = std::path::Path::new(filename);
        let mut file = try!(std::fs::File::create(&path).map_err(ImageSaveError::Io));
        image.save(&mut file, image::PNG).map_err(ImageSaveError::Image)
    }

    fn static_factors() -> Static<Self>
        where Self::Item: Clone + Copy + Zero + One
    {
        fn helper_horizontal<U: Clone + Copy + Zero + One>(row: usize) -> DMat<U> {
            Testimage::new_horizontal_line(row, 0..10)
        }
        fn helper_vertical<U: Clone + Copy + Zero + One>(col: usize) -> DMat<U> {
            Testimage::new_vertical_line(0..10, col)
        }
        once(Testimage::new_horizontal_line(9, 0..5))
            .chain((0..9).rev().map(helper_horizontal as fn(usize) -> Self))
            .chain(once(Testimage::new_vertical_line(5..10, 0)))
            .chain((1..10).map(helper_vertical as fn(usize) -> Self))
    }

    fn horizontal_evolving_factors() -> Horizontal<Self>
        where Self::Item: Clone + Copy + Zero + One
    {
        fn helper<U: Clone + Copy + Zero + One>(start_col: usize) -> DMat<U> {
            Testimage::new_horizontal_line(9, start_col..(start_col + 5))
        }
        (0..6).map(helper)
    }

    fn vertical_evolving_factors() -> Vertical<Self>
        where Self::Item: Clone + Copy + Zero + One
    {
        fn helper<U: Clone + Copy + Zero + One>(start_row: usize) -> DMat<U> {
            Testimage::new_vertical_line(start_row..(start_row + 5), 0)
        }
        (0..6).rev().map(helper)
    }

    fn linear_combination<C>(factors: &[Self], coefficients: &[C]) -> Self
        where C: Clone,
              Self: Mul<C, Output = Self>,
              Self::Item: Clone + Copy + Zero
    {
        assert!(0 < factors.len());
        assert_eq!(factors.len(), coefficients.len());
        let nrows = factors[0].nrows();
        let ncols = factors[0].ncols();
        let mut result = DMat::new_zeros(nrows, ncols);
        for (factor, coefficient) in factors.iter().zip(coefficients.iter()) {
            assert_eq!(factor.nrows(), nrows);
            assert_eq!(factor.ncols(), ncols);
            result = result.add(factor.clone().mul(coefficient.clone()));
        }
        result
    }

    /// divide all values by max value
    // TODO put this into its own trait
    fn normalize_mut(self) -> Self
        where Self::Item: Clone + Copy + PartialOrd,
              Self: Div<T, Output = Self>,
              Self: Sized
    {
        let nrows = self.nrows();
        let ncols = self.ncols();
        let max = self.as_vec().iter().cloned().partial_max().unwrap();
        self.div(max)
    }

    fn testimages() -> Test<Self>
        where Self::Item: Clone + Copy + Zero + One + BaseFloat
    {
        fn helper<U, V, W, X>((a, b): (U, V)) -> W
            where U: Add<V, Output = W>,
                  W: Testimage<X>,
                  W::Item: Clone + BaseFloat,
                  W: Div<X, Output=W>
        {
            a.add(b).normalize_mut()
        }
        Testimage::horizontal_evolving_factors()
            .zip(Testimage::vertical_evolving_factors())
            .map(helper)

        //     horizontal
        //     .zip(vertical)
        //     .enumerate()
        //     .map(|(step, (horizontal, vertical))| {
        //         // let h: Self = horizontal;
        //         // // let cloned: Self = (*horizontal).clone::<Self>();
        //         // let foo = h.add(vertical);
        //         // let result: Self = foo.normalize::<Self>();
        //         // result
        //         horizontal.clone()
        //     }))
    }
}

// fn random_coefficient<R: Rng>(rng: &mut R) -> FloatType {
//     let Closed01(random) = rng.gen::<Closed01<FloatType>>();
//     random
// }
//
// fn random_coefficients<R: Rng>(rng: &mut R, count: usize) -> DVec<FloatType> {
//     let mut coefficients: DVec<FloatType> = DVec::new_zeros(count);
//     for i in 0..count {
//         coefficients[i] = random_coefficient(rng);
//     }
//     coefficients
// }
<commit_msg>remove dead code<commit_after>/// generates images used to test NMF

use std::ops::{Index, IndexMut, Mul, Add, Div};

use std;

use std::cmp::PartialOrd;

use std::ops::Range;
use std::iter::{Map, Rev, once, Once, Chain, Zip};

extern crate num;
use num::traits::{Zero, One, FromPrimitive, ToPrimitive, Float};

extern crate nalgebra;
use nalgebra::{DMat, DVec, Norm, BaseFloat};

extern crate image;
use self::image::{ImageBuffer, Luma, DynamicImage};

use partialmax::PartialMaxIteratorExt;

quick_error! {
    #[derive(Debug)]
    pub enum ImageSaveError {
        /// an error has occured when opening the file
        Io(err: std::io::Error) {}
        /// an error has occured when writing the image into the file
        Image(err: image::ImageError) {}
    }
}

// TODO suffix ReturnT
pub type Horizontal<T> = Map<Range<usize>, fn(usize) -> T>;
pub type Vertical<T> = Map<Rev<Range<usize>>, fn(usize) -> T>;
pub type Static<T> = Chain<Chain<Chain<Once<T>, Vertical<T>>, Once<T>>, Horizontal<T>>;
pub type Test<T> = Map<Zip<Horizontal<T>, Vertical<T>>, fn((T, T)) -> T>;

// TODO move the type constraints back up here
// TODO split into multiple traits
// normalize
// images
// creation
pub trait Testimage<T> {
    type Item;

    /// returns a testimage that has `1` in `row` for all `cols` and `0` everywhere else
    ///
    /// ```
    /// Testimage::new_horizontal_line(9, 0..5);
    /// ```
    fn new_horizontal_line<I: Iterator<Item = usize>>(row: usize, cols: I) -> Self where Self::Item: Clone + Copy + Zero + One;
    /// returns a testimage that has `1` in `col` for all `rows` and `0` everywhere else
    ///
    /// ```
    /// Testimage::new_vertical_line(5..10, 0);
    /// ```
    fn new_vertical_line<I: Iterator<Item = usize>>(rows: I, col: usize) -> Self where Self::Item: Clone + Copy + Zero + One;
    /// # Panics
    /// panics unless all the values in `self` are between
    /// `0` (inclusive) and `1` (inclusive)
    fn luma01_to_image(&self) -> DynamicImage where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float;
    /// # Panics
    /// panics unless all the values in `self` are between
    /// `0` (inclusive) and `1` (inclusive)
    fn save_luma01_to_png(&self, filename: &str) -> Result<(), ImageSaveError> where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float;
    fn static_factors() -> Static<Self>
        where Self: Sized,
              Self::Item: Clone + Copy + Zero + One;
    // TODO it's probably a much better idea to just use plain functions here
    fn horizontal_evolving_factors() -> Horizontal<Self> where Self::Item: Clone + Copy + Zero + One;
    fn vertical_evolving_factors() -> Vertical<Self> where Self::Item: Clone + Copy + Zero + One;
    // TODO trait
    fn linear_combination<C>(factors: &[Self], coefficients: &[C]) -> Self
        where C: Clone,
              Self: Sized + Mul<C, Output = Self>,
              Self::Item: Clone + Copy + Zero;
    fn normalize_mut(self) -> Self
        where Self::Item: Clone + Copy + BaseFloat,
              Self: Div<T, Output = Self>,
              Self: Sized;
    fn testimages() -> Test<Self> where Self::Item: Clone + Copy + Zero + One + BaseFloat;
}

impl<T> Testimage<T> for DMat<T> {
    // here's where we associate Self::Item and T
    type Item = T;

    fn new_horizontal_line<I: Iterator<Item = usize>>(row: usize, cols: I) -> Self
        where Self::Item: Clone + Copy + Zero + One
    {
        let mut factor: DMat<Self::Item> = DMat::new_zeros(10, 10);
        for col in cols {
            *factor.index_mut((row, col)) = Self::Item::one();
        }
        factor
    }

    fn new_vertical_line<I: Iterator<Item = usize>>(rows: I, col: usize) -> Self
        where Self::Item: Clone + Copy + Zero + One
    {
        let mut factor: DMat<Self::Item> = DMat::new_zeros(10, 10);
        for row in rows {
            *factor.index_mut((row, col)) = Self::Item::one();
        }
        factor
    }

    fn luma01_to_image(&self) -> DynamicImage
        where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float
    {
        let mut image_buffer = ImageBuffer::new(self.ncols() as u32, self.nrows() as u32);
        for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
            let value = self.index((y as usize, x as usize));
            assert!(Self::Item::zero() <= *value);
            assert!(*value <= Self::Item::one());
            let max = Self::Item::from_u8(std::u8::MAX).unwrap();
            let byte = (*value * max).round().to_u8().unwrap();
            *pixel = Luma([byte]);
        }
        DynamicImage::ImageLuma8(image_buffer)
    }

    fn save_luma01_to_png(&self, filename: &str) -> Result<(), ImageSaveError>
        where Self::Item: Zero + One + FromPrimitive + ToPrimitive + PartialOrd + Float
    {
        let image = self.luma01_to_image();
        let path = std::path::Path::new(filename);
        let mut file = try!(std::fs::File::create(&path).map_err(ImageSaveError::Io));
        image.save(&mut file, image::PNG).map_err(ImageSaveError::Image)
    }

    fn static_factors() -> Static<Self>
        where Self::Item: Clone + Copy + Zero + One
    {
        fn helper_horizontal<U: Clone + Copy + Zero + One>(row: usize) -> DMat<U> {
            Testimage::new_horizontal_line(row, 0..10)
        }
        fn helper_vertical<U: Clone + Copy + Zero + One>(col: usize) -> DMat<U> {
            Testimage::new_vertical_line(0..10, col)
        }
        once(Testimage::new_horizontal_line(9, 0..5))
            .chain((0..9).rev().map(helper_horizontal as fn(usize) -> Self))
            .chain(once(Testimage::new_vertical_line(5..10, 0)))
            .chain((1..10).map(helper_vertical as fn(usize) -> Self))
    }

    fn horizontal_evolving_factors() -> Horizontal<Self>
        where Self::Item: Clone + Copy + Zero + One
    {
        fn helper<U: Clone + Copy + Zero + One>(start_col: usize) -> DMat<U> {
            Testimage::new_horizontal_line(9, start_col..(start_col + 5))
        }
        (0..6).map(helper)
    }

    fn vertical_evolving_factors() -> Vertical<Self>
        where Self::Item: Clone + Copy + Zero + One
    {
        fn helper<U: Clone + Copy + Zero + One>(start_row: usize) -> DMat<U> {
            Testimage::new_vertical_line(start_row..(start_row + 5), 0)
        }
        (0..6).rev().map(helper)
    }

    fn linear_combination<C>(factors: &[Self], coefficients: &[C]) -> Self
        where C: Clone,
              Self: Mul<C, Output = Self>,
              Self::Item: Clone + Copy + Zero
    {
        assert!(0 < factors.len());
        assert_eq!(factors.len(), coefficients.len());
        let nrows = factors[0].nrows();
        let ncols = factors[0].ncols();
        let mut result = DMat::new_zeros(nrows, ncols);
        for (factor, coefficient) in factors.iter().zip(coefficients.iter()) {
            assert_eq!(factor.nrows(), nrows);
            assert_eq!(factor.ncols(), ncols);
            result = result.add(factor.clone().mul(coefficient.clone()));
        }
        result
    }

    /// divide all values by max value
    // TODO put this into its own trait
    fn normalize_mut(self) -> Self
        where Self::Item: Clone + Copy + PartialOrd,
              Self: Div<T, Output = Self>,
              Self: Sized
    {
        let max = self.as_vec().iter().cloned().partial_max().unwrap();
        self.div(max)
    }

    fn testimages() -> Test<Self>
        where Self::Item: Clone + Copy + Zero + One + BaseFloat
    {
        fn helper<U, V, W, X>((a, b): (U, V)) -> W
            where U: Add<V, Output = W>,
                  W: Testimage<X>,
                  W::Item: Clone + BaseFloat,
                  W: Div<X, Output=W>
        {
            a.add(b).normalize_mut()
        }
        Testimage::horizontal_evolving_factors()
            .zip(Testimage::vertical_evolving_factors())
            .map(helper)

        //     horizontal
        //     .zip(vertical)
        //     .enumerate()
        //     .map(|(step, (horizontal, vertical))| {
        //         // let h: Self = horizontal;
        //         // // let cloned: Self = (*horizontal).clone::<Self>();
        //         // let foo = h.add(vertical);
        //         // let result: Self = foo.normalize::<Self>();
        //         // result
        //         horizontal.clone()
        //     }))
    }
}

// fn random_coefficient<R: Rng>(rng: &mut R) -> FloatType {
//     let Closed01(random) = rng.gen::<Closed01<FloatType>>();
//     random
// }
//
// fn random_coefficients<R: Rng>(rng: &mut R, count: usize) -> DVec<FloatType> {
//     let mut coefficients: DVec<FloatType> = DVec::new_zeros(count);
//     for i in 0..count {
//         coefficients[i] = random_coefficient(rng);
//     }
//     coefficients
// }
<|endoftext|>


<commit_before>extern crate time;
extern crate serde_json;

use std::io::prelude::*;

use std::time::{SystemTime, UNIX_EPOCH};

use std::fs;
use std::path::Path;
use std::error::Error;
use std::fs::OpenOptions;

use std::process::Command;

#[derive(Serialize, Deserialize, Debug)]
pub enum Event {
    Pause { time: u64 },
    MetaPause { time: u64, reason: String },
    Proceed { time: u64 },
    Meta { time: u64, text: String },
    Commit { time: u64, hash: u64 },
    Branch { time: u64, name: String },
}

#[derive(Serialize, Deserialize, Debug)]
struct Session {
    start: u64,
    end: u64,
    events: Vec<Event>,
}

impl Session {
    fn new() -> Session {
        let seconds = get_seconds();
        Session {
            start: seconds,
            end: seconds - 1,
            events: Vec::<Event>::new(),
        }
    }

    fn in_progress(&self) -> bool {
        self.start == (self.end + 1)
    }

    fn finalize(&mut self) {
        self.end = get_seconds();
    }

    fn status(&self) -> String {
        format!("{:?}", self)
    }

    fn is_paused(&self) -> bool {
        match self.events.len() {
            0 => false,
            n => {
                match self.events[n - 1] {
                    Event::Pause { .. } |
                    Event::MetaPause { .. } => true,
                    _ => false,
                }
            }
        }
    }

    fn push_event(&mut self, event: Event) -> bool {
        /* Cannot push if session is already finalized! */
        if !self.in_progress() {
            println!("Already finalized, cannot push event");
            return false;
        }
        /* TODO: add logic */
        match event {
            Event::Pause { .. } |
            Event::MetaPause { .. } => {
                if !self.is_paused() {
                    self.events.push(event);
                    true
                } else {
                    println!("Already paused!");
                    false
                }
            }
            Event::Proceed { .. } => {
                if self.is_paused() {
                    self.events.push(event);
                    true
                } else {
                    println!("Currently not paused!");
                    false
                }
            }
            Event::Meta { time: ref metatime, text: ref metatext } => {
                if self.is_paused() {
                    /* morph last pause into a MetaPause */
                    let pause = self.events.pop().unwrap();
                    match pause {
                        Event::Pause {time: pausetime} => {
                            self.push_event(Event::MetaPause { time: pausetime, reason: metatext.to_string()})
                        }
                        Event::MetaPause { time: mp_time, reason } => {
                            /* Concat? */
                            let reason_concat = reason + metatext;
                            self.push_event(Event::MetaPause { time: mp_time, reason: reason_concat.to_string()})
                        }
                        _ => unreachable!(),
                    };
                } else {
                    self.events.push(Event::Meta {time: *metatime, text: metatext.clone()} )
                };
                true
            }
            Event::Commit { .. } |
            Event::Branch { .. } => {
                if self.is_paused() {
                    let now = get_seconds();
                    self.push_event(Event::Proceed { time: now });
                }
                self.events.push(event);
                true
            }
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Timesheet {
    start: u64,
    end: u64,
    user: String,
    sessions: Vec<Session>,
}

impl Timesheet {
    /** Initializes the .trk/sessions.trk file which holds
     * the serialized timesheet
     * Returns Some(newTimesheet) if operation succeeded */
    pub fn init(author_name: Option<&str>) -> Option<Timesheet> {
        /* Check if file already exists (no init permitted) */
        if Timesheet::is_init() {
            None
        } else {
            /* File does not exist, initialize */
            let git_author_name = &git_author().unwrap_or("".to_string());
            let author_name = match author_name {
                Some(name) => name,
                None => git_author_name,
            };
            let sheet = Timesheet {
                start: get_seconds(),
                end: get_seconds() - 1,
                user: author_name.to_string(),
                sessions: Vec::<Session>::new(),
            };
            if sheet.save_to_file() {
                Some(sheet)
            } else {
                None
            }
        }
    }

    fn is_init() -> bool {
        if Path::new("./.trk/sessions.trk").exists() {
            match Timesheet::load_from_file() {
                Some(..) => true,
                /* else, loading failed */
                None => false,
            }
        } else {
            /* File doesn't even exist */
            false
        }
    }

    fn get_last_session(&mut self) -> Option<&mut Session> {
        match self.sessions.len() {
            0 => None,
            n => Some(&mut self.sessions[n - 1]),
        }
    }

    pub fn new_session(&mut self) -> bool {

        let nsessions = self.sessions.len();
        let pushed = match nsessions {
            0 => true,
            _ => {
                if !self.sessions[nsessions - 1].in_progress() {
                    true
                } else {
                    println!("Last session is still running!");
                    false
                }
            }
        };
        if pushed {
            self.sessions.push(Session::new());
            self.save_to_file();
        }
        pushed
    }

    pub fn end_session(&mut self) {
        match self.get_last_session() {
            Some(session) => session.finalize(),
            None => println!("No session to finalize!"),
        }
        self.save_to_file();
    }

    pub fn pause(&mut self, metatext: Option<String>) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                match metatext {
                    Some(reason) => {
                        session.push_event(Event::MetaPause {
                                               time: now,
                                               reason: reason.to_string(),
                                           });

                    }
                    None => {
                        session.push_event(Event::Pause { time: now });
                    }
                }
            }
            None => println!("No session to pause!"),
        }
        self.save_to_file();
    }

    pub fn proceed(&mut self) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Proceed { time: now });
            }
            None => println!("No session to pause!"),
        }
        self.save_to_file();
    }

    pub fn push_meta(&mut self, metatext: String) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Meta {
                                       time: now,
                                       text: metatext,
                                   });
            }
            None => println!("No session to add meta to!"),
        }
        self.save_to_file();
    }

    pub fn push_commit(&mut self, hash: u64) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Commit {
                                       time: now,
                                       hash: hash,
                                   });
            }
            None => println!("No session to add commit to!"),
        }
        self.save_to_file();
    }

    pub fn push_branch(&mut self, name: String) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Branch {
                                       time: now,
                                       name: name,
                                   });
            }
            None => println!("No session to change branch in!"),
        }
        self.save_to_file();
    }

    fn save_to_file(&self) -> bool {
        /* TODO: avoid time-of-check-to-time-of-use race risk */
        /* TODO: make all commands run regardless of where trk is executed
         * (and not just in root which is assumed here */
        let path = Path::new("./.trk/sessions.trk");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        match file {
            Ok(mut file) => {
                /* Convert the sheet to a JSON string. */
                let serialized =
                    serde_json::to_string(&self).expect("Could not write serialized time sheet!");
                file.write_all(serialized.as_bytes()).unwrap();
                /* save was successful */
                true
            }
            Err(why) => {
                println!("{}", why.description());
                false
            }
        }
    }

    /** Return a Some(Timesheet) struct if a sessions.trk file is present and valid
     * in the .trk directory, and None otherwise.
     * TODO: improve error handling
     * */
    pub fn load_from_file() -> Option<Timesheet> {
        let path = Path::new("./.trk/sessions.trk");
        let file = OpenOptions::new().read(true).open(&path);
        match file {
            Ok(mut file) => {
                let mut serialized = String::new();
                match file.read_to_string(&mut serialized) {
                    Ok(..) => serde_json::from_str(&serialized).unwrap_or(None),
                    Err(..) => {
                        println!("Reading the string failed!");
                        None
                    }
                }
            }
            Err(..) => {
                // println!("{}", why.description());
                None
            }
        }
    }

    pub fn clear_sessions() {
        /* Try to get name */
        let sheet = Timesheet::load_from_file();
        let name: Option<String> = sheet.map(|s| s.user.clone());

        let path = Path::new("./.trk/sessions.trk");
        if path.exists() {
            match fs::remove_file(&path) {
                Ok(..) => {}
                Err(why) => println!("Could not remove sessions file: {}", why.description()),
            }
        }
        match name {
            Some(name) => {
                /* Will overwrite file */
                Timesheet::init(Some(&name));
            }
            None => {
                Timesheet::init(None);
            }
        }
    }

    pub fn timesheet_status(&self) -> String {
        format!("{:?}", self)
    }

    pub fn last_session_status(&self) -> Option<String> {
        let nsessions = self.sessions.len();
        match nsessions {
            0 => None,
            n => Some(self.sessions[n - 1].status()),
        }
    }
}

fn get_seconds() -> u64 {
    SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()
}

fn git_author() -> Option<String> {
    if let Ok(output) = Command::new("git").arg("config").arg("user.name").output() {
        if output.status.success() {
            let output = String::from_utf8_lossy(&output.stdout);
            /* remove trailing newline character */
            let mut output = output.to_string();
            output.pop().expect("Empty name in git config!?!");
            Some(output)
        } else {
            let output = String::from_utf8_lossy(&output.stderr);
            println!("git config user.name failed! {}", output);
            None
        }
    } else {
        None
    }
}
<commit_msg>refactor timesheet to make retropause simpler<commit_after>extern crate time;
extern crate serde_json;

use std::io::prelude::*;

use std::time::{SystemTime, UNIX_EPOCH};

use std::fs;
use std::path::Path;
use std::error::Error;
use std::fs::OpenOptions;

use std::process::Command;

#[derive(Serialize, Deserialize, Debug)]
pub enum Event {
    Pause { time: u64 },
    MetaPause { time: u64, meta_info: String },
    Resume { time: u64 },
    Meta { time: u64, text: String },
    Commit { time: u64, hash: u64 },
    Branch { time: u64, name: String },
}

#[derive(Serialize, Deserialize, Debug)]
struct Session {
    start: u64,
    end: u64,
    running: bool,
    events: Vec<Event>,
}

impl Session {
    fn new() -> Session {
        let seconds = get_seconds();
        Session {
            start: seconds,
            end: seconds - 1,
            running: true,
            events: Vec::<Event>::new(),
        }
    }

    fn update_end(&mut self) {
        self.end = get_seconds();
    }

    pub fn is_running(&self) -> bool {
        self.running
    }

    fn finalize(&mut self) {
        self.running = false;
    }

    fn status(&self) -> String {
        format!("{:?}", self)
    }

    fn is_paused(&self) -> bool {
        match self.events.len() {
            0 => false,
            n => {
                match self.events[n - 1] {
                    Event::Pause { .. } |
                    Event::MetaPause { .. } => true,
                    _ => false,
                }
            }
        }
    }

    fn push_event(&mut self, event: Event) -> bool {
        /* Cannot push if session is already finalized! */
        if !self.is_running() {
            println!("Already finalized, cannot push event");
            return false;
        }
        /* TODO: add logic */
        match event {
            Event::Pause { .. } |
            Event::MetaPause { .. } => {
                if !self.is_paused() {
                    self.events.push(event);
                    true
                } else {
                    println!("Already paused!");
                    false
                }
            }
            Event::Resume { .. } => {
                if self.is_paused() {
                    self.events.push(event);
                    true
                } else {
                    println!("Currently not paused!");
                    false
                }
            }
            Event::Meta { time: ref metatime, text: ref metatext } => {
                if self.is_paused() {
                    /* morph last pause into a MetaPause */
                    let pause = self.events.pop().unwrap();
                    match pause {
                        Event::Pause { time: pausetime } => {
                            self.push_event(Event::MetaPause {
                                                time: pausetime,
                                                meta_info: metatext.to_string(),
                                            })
                        }
                        Event::MetaPause { time: pausetime, meta_info } => {
                            let meta_info = meta_info + "\n" + metatext;
                            self.push_event(Event::MetaPause {
                                                time: pausetime,
                                                meta_info: meta_info.to_string(),
                                            })
                        }
                        _ => unreachable!(),
                    };
                } else {
                    self.events.push(Event::Meta {
                                         time: *metatime,
                                         text: metatext.clone(),
                                     })
                };
                true
            }
            Event::Commit { .. } |
            Event::Branch { .. } => {
                if self.is_paused() {
                    let now = get_seconds();
                    self.push_event(Event::Resume { time: now });
                }
                self.events.push(event);
                true
            }
        }
    }
}

// Maybe every event added to a session should set the end date? And begin just always opens a new
// session?
#[derive(Serialize, Deserialize, Debug)]
pub struct Timesheet {
    start: u64,
    end: u64,
    user: String,
    sessions: Vec<Session>,
}

impl Timesheet {
    /** Initializes the .trk/sessions.trk file which holds
     * the serialized timesheet
     * Returns Some(newTimesheet) if operation succeeded */
    pub fn init(author_name: Option<&str>) -> Option<Timesheet> {
        /* Check if file already exists (no init permitted) */
        if Timesheet::is_init() {
            None
        } else {
            /* File does not exist, initialize */
            let git_author_name = &git_author().unwrap_or("".to_string());
            let author_name = match author_name {
                Some(name) => name,
                None => git_author_name,
            };
            let sheet = Timesheet {
                start: get_seconds(),
                end: get_seconds() - 1,
                user: author_name.to_string(),
                sessions: Vec::<Session>::new(),
            };
            if sheet.save_to_file() {
                Some(sheet)
            } else {
                None
            }
        }
    }

    fn is_init() -> bool {
        if Path::new("./.trk/sessions.trk").exists() {
            match Timesheet::load_from_file() {
                Some(..) => true,
                /* else, loading failed */
                None => false,
            }
        } else {
            /* File doesn't even exist */
            false
        }
    }

    fn get_last_session(&mut self) -> Option<&mut Session> {
        match self.sessions.len() {
            0 => None,
            n => Some(&mut self.sessions[n - 1]),
        }
    }

    fn update_end(&mut self) {
        match self.get_last_session().map(|s| s.end = get_seconds()) {
            Some(_) => {}
            None => println!("Warning: called Timesheet::update_end() but there are no sessions!"),
        }
    }

    pub fn new_session(&mut self) -> bool {
        let n_sessions = self.sessions.len();
        let push = match n_sessions {
            0 => true,
            _ => {
                if self.sessions[n_sessions - 1].is_running() {
                    println!("Last session is still running!");
                    false
                } else {
                    true
                }
            }
        };
        if push {
            self.sessions.push(Session::new());
            self.save_to_file();
        }
        push
    }

    pub fn end_session(&mut self) {
        match self.get_last_session() {
            Some(session) => {
                session.update_end();
                session.finalize();
            }
            None => println!("No session to finalize!"),
        }
        self.save_to_file();
    }

    pub fn pause(&mut self, metatext: Option<String>) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                match metatext {
                    Some(meta_info) => {
                        session.push_event(Event::MetaPause {
                                               time: now,
                                               meta_info: meta_info.to_string(),
                                           });

                    }
                    None => {
                        session.push_event(Event::Pause { time: now });
                    }
                }
            }
            None => println!("No session to pause!"),
        }
        self.update_end();
        self.save_to_file();
    }

    pub fn retropause(&mut self, time_ago: u64, metatext: Option<String>) {
        /* match self.get_last_session() {
            Some(session) => {
                if session.is_paused()
            }
            None => println!("No session to pause!"),
        }
        self.update_end();
        self.save_to_file(); */
    }

    pub fn resume(&mut self) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Resume { time: now });
            }
            None => println!("No session to pause!"),
        }
        self.update_end();
        self.save_to_file();
    }

    pub fn push_meta(&mut self, metatext: String) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Meta {
                                       time: now,
                                       text: metatext,
                                   });
            }
            None => println!("No session to add meta to!"),
        }
        self.update_end();
        self.save_to_file();
    }

    pub fn push_commit(&mut self, hash: u64) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Commit {
                                       time: now,
                                       hash: hash,
                                   });
            }
            None => println!("No session to add commit to!"),
        }
        self.update_end();
        self.save_to_file();
    }

    pub fn push_branch(&mut self, name: String) {
        match self.get_last_session() {
            Some(session) => {
                let now = get_seconds();
                session.push_event(Event::Branch {
                                       time: now,
                                       name: name,
                                   });
            }
            None => println!("No session to change branch in!"),
        }
        self.save_to_file();
    }

    fn save_to_file(&self) -> bool {
        /* TODO: avoid time-of-check-to-time-of-use race risk */
        /* TODO: make all commands run regardless of where trk is executed
         * (and not just in root which is assumed here */

        let path = Path::new("./.trk/sessions.trk");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        match file {
            Ok(mut file) => {
                /* Convert the sheet to a JSON string. */
                let serialized =
                    serde_json::to_string(&self).expect("Could not write serialized time sheet!");
                file.write_all(serialized.as_bytes()).unwrap();
                /* save was successful */
                true
            }
            Err(why) => {
                println!("{}", why.description());
                false
            }
        }
    }

    /** Return a Some(Timesheet) struct if a sessions.trk file is present and valid
     * in the .trk directory, and None otherwise.
     * TODO: improve error handling
     * */
    pub fn load_from_file() -> Option<Timesheet> {
        let path = Path::new("./.trk/sessions.trk");
        let file = OpenOptions::new().read(true).open(&path);
        match file {
            Ok(mut file) => {
                let mut serialized = String::new();
                match file.read_to_string(&mut serialized) {
                    Ok(..) => serde_json::from_str(&serialized).unwrap_or(None),
                    Err(..) => {
                        println!("Reading the string failed!");
                        None
                    }
                }
            }
            Err(..) => {
                // println!("{}", why.description());
                None
            }
        }
    }

    pub fn clear_sessions() {
        /* Try to get name */
        let sheet = Timesheet::load_from_file();
        let name: Option<String> = sheet.map(|s| s.user.clone());

        let path = Path::new("./.trk/sessions.trk");
        if path.exists() {
            match fs::remove_file(&path) {
                Ok(..) => {}
                Err(why) => println!("Could not remove sessions file: {}", why.description()),
            }
        }
        match name {
            Some(name) => {
                /* Will overwrite file */
                Timesheet::init(Some(&name));
            }
            None => {
                Timesheet::init(None);
            }
        }
    }

    pub fn timesheet_status(&self) -> String {
        format!("{:?}", self)
    }

    pub fn last_session_status(&self) -> Option<String> {
        let n_sessions = self.sessions.len();
        match n_sessions {
            0 => None,
            n => Some(self.sessions[n - 1].status()),
        }
    }
}

fn get_seconds() -> u64 {
    SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()
}

fn git_author() -> Option<String> {
    if let Ok(output) = Command::new("git").arg("config").arg("user.name").output() {
        if output.status.success() {
            let output = String::from_utf8_lossy(&output.stdout);
            /* remove trailing newline character */
            let mut output = output.to_string();
            output.pop().expect("Empty name in git config!?!");
            Some(output)
        } else {
            let output = String::from_utf8_lossy(&output.stderr);
            println!("git config user.name failed! {}", output);
            None
        }
    } else {
        None
    }
}
<|endoftext|>