<commit_before>extern crate getopts;
use getopts::{optflag,getopts,OptGroup,usage};
use std::os;

use std::num::FromPrimitive;
use std::num::Int;
use std::char;
use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                linenum = cat_file(file, options, linenum);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut linenum = 1u32;
    let mut printempty: bool = false;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line.unwrap(), &mut printempty, linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file<'a>(
    mut file: old_io::BufferedReader<std::old_io::fs::File>,
    options: &getopts::Matches,
    mut linenum: u32,
    ) -> u32 {
    let mut printempty: bool = false;
    let mut read_buf = [0, 4096];
    let mut out_buf: Vec<u8> = vec![];
    loop {
        match file.read(&mut read_buf) {
            Ok(n) => {
                for c in read_buf[..n].iter() {
                    out_buf.push(*c);
                    if is_nl(c) {
                        let (a, b) = handle_buf(&out_buf, &mut printempty, linenum, options);
                        printempty = a;
                        linenum = b;
                        out_buf.clear();
                    }
                }
            },
            Err(f) => {
                let mut o = 0u32;
                if out_buf.len() > 0 {
                    handle_buf(&out_buf, &mut printempty, linenum, options);
                }
                break
            }
        }
    }
    linenum
}

fn handle_line<'a>(
    linestr: String,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            linenum = print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_string(&linestr, linenum, options);
    }
    (*printempty, linenum)
}

fn handle_buf<'a>(
    out_buf: &Vec<u8>,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty_out_buf(out_buf) {
            if *printempty == true {
                if options.opt_present("n") {
                    println!("     {}\t", linenum);
                    linenum = linenum + 1;
                }
                else {
                    println!("");
                }
            }
            linenum = print_buf(&out_buf, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_buf(&out_buf, linenum, options);
    }
    (*printempty, linenum)
}

fn print_string<'a>(s: &String, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_buf<'a>(out_buf: &Vec<u8>, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty_out_buf(out_buf) {
            print_numbered_buf(out_buf, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered_buf(out_buf, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered_buf(out_buf, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered_buf(out_buf, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_numbered_buf<'a>(out_buf: &Vec<u8>, linenum: u32, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        let mut t = 0u8;
        for b in out_buf.iter() {
            if t > 0 {
                t = t + *b;
                // print!("t: {} ", t);
                print!("{}", t as char);
                t = 0;
            }
            else {
                if *b > 160 {
                    t = *b;
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn print_unnumbered_buf(out_buf: &Vec<u8>, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        let mut t = 0;
        let mut buf: Vec<u8> = vec![];
        for b in out_buf.iter() {
            if t > 0 {
                buf.push(*b);
                t = t - 1;
                if t == 0 {
                    print_u8_buf(&mut buf, options);
                    buf.clear();
                }
            }
            else {
                if *b >= 240 {
                    //4th byte
                    t = 3;
                    buf.push(*b);
                }
                else if *b >= 224 {
                    t = 2;
                    buf.push(*b);
                }
                else if *b >= 192 {
                    t = 1;
                    buf.push(*b);
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
    // else {
        // print!("{}", s);
    // }
}

fn print_u8_buf(buf: &mut Vec<u8>, options: &getopts::Matches) {
    match convert_buf_to_codepoint(buf) {
        Ok(codepoint) => {
            match char::from_u32(codepoint) {
                Some(c) => print!("{}", c),
                None => {
                    for b in buf.iter() {
                        print_byte(b, options);
                    }
                }

            }
        },
        Err(_) => {
            for b in buf.iter() {
                print_byte(b, options);
            }
        }
    }
}

fn convert_buf_to_codepoint(buf: &mut Vec<u8>) -> Result<u32, String> {
    let mut s = 0u32;
    let mut l = buf.len();
    let orig_l = l;
    for b in buf.iter() {
        if l == 4 {
            s = s + ((*b as u32 | 240) - 240) << 19;
        }
        else if l == 3 {
            if orig_l == 4 && *b > 191 {
                return Err("Couldn't parse".to_string());
            }
            else {
                s = s + ((*b as u32 | 224) - 224) << 12;
            }
        }
        else if l == 2 {
            if (orig_l == 4 || orig_l == 3) && *b > 191 {
                return Err("Couldn't parse".to_string());
            }
            else {
                s = s + (((*b as u32 | 192) - 192) << 6);
            }
        }
        else if l == 1 {
            if orig_l > 1 {
                if *b > 191 {
                    return Err("Couldn't parse".to_string());
                }
                else {
                    s = s + ((*b as u32 | 128) - 128);
                }
            }
            else {
                s = s + ((*b as u32 | 192) - 192);
            }
        }
        l = l - 1;
    }
    Ok(s)
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn is_empty_out_buf(v: &Vec<u8>) -> bool {
    if v.len() > 1 {
        false
    }
    else if is_nl(&v[0]) {
        true
    }
    else {
        false
    }
}

fn is_nl(c: &u8) -> bool {
    *c == 10u8
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if (*b > 31 && *b < 127) || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print_tab();
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        if options.opt_present("v") || options.opt_present("t") {
            if *b < 32 {
                print!("^{}", (*b + 64) as char);
            }
            else if *b == 127 {
                // del char
                print!("^?");
            }
            else if *b > 127 {
                if *b == 255 {
                    print!("M-^?");
                }
                else {
                    let x = *b - 128;
                    if x < 32 {
                        print!("M-^{}", (x + 64) as char);
                    }
                    else {
                        print!("M-{}", (*b - 128) as char);
                    }
                }
            }
        }
    }
}

fn print_tab() {
    print!("^I");
}

#[cfg(test)]
mod tests {
    use super::is_empty;
    use super::convert_buf_to_codepoint;

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_buf_to_codepoint_24() {
        let mut b = vec![24u8];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 24u32);
    }

    #[test]
    fn assert_buf_to_codepoint_36() {
        let mut b = vec![164u8];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 36);
    }

    #[test]
    fn assert_buf_to_codepoint_162() {
        // ¢
        // C2 A2
        // 11000010 10100010
        // 00010100010
        let mut b = vec![194u8, 162];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 162);
    }

    #[test]
    fn assert_buf_to_codepoint_8364() {
        // €
        // E2 82 AC
        // 11100010 10000010 10101100
        // 0010000010101100
        let mut b = vec![226u8, 130, 172];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 8364);
    }

    #[test]
    fn assert_buf_to_codepoint_294() {
        // c4 a6
        // 11000100 10100110
        // 00100100110
        let mut b = vec![196u8, 166];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 294);
    }

    #[test]
    fn assert_buf_to_codepoint_66376() {
        // F0 90 8D 88
        // 11110000 10010000 10001101 10001000
        // 00001 00000011 01001000
        let mut b = vec![240u8, 144, 141, 136];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 66376);
    }

    #[test]
    #[should_fail]
    fn assert_buf_to_codepoint_192193_err() {
        let mut b = vec![192u8, 193];
        convert_buf_to_codepoint(&mut b).unwrap();
    }

}
<commit_msg>Use assert! with is_err() instead of should_fail<commit_after>extern crate getopts;
use getopts::{optflag,getopts,OptGroup,usage};
use std::os;

use std::num::FromPrimitive;
use std::num::Int;
use std::char;
use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                linenum = cat_file(file, options, linenum);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut linenum = 1u32;
    let mut printempty: bool = false;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line.unwrap(), &mut printempty, linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file<'a>(
    mut file: old_io::BufferedReader<std::old_io::fs::File>,
    options: &getopts::Matches,
    mut linenum: u32,
    ) -> u32 {
    let mut printempty: bool = false;
    let mut read_buf = [0, 4096];
    let mut out_buf: Vec<u8> = vec![];
    loop {
        match file.read(&mut read_buf) {
            Ok(n) => {
                for c in read_buf[..n].iter() {
                    out_buf.push(*c);
                    if is_nl(c) {
                        let (a, b) = handle_buf(&out_buf, &mut printempty, linenum, options);
                        printempty = a;
                        linenum = b;
                        out_buf.clear();
                    }
                }
            },
            Err(f) => {
                let mut o = 0u32;
                if out_buf.len() > 0 {
                    handle_buf(&out_buf, &mut printempty, linenum, options);
                }
                break
            }
        }
    }
    linenum
}

fn handle_line<'a>(
    linestr: String,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            linenum = print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_string(&linestr, linenum, options);
    }
    (*printempty, linenum)
}

fn handle_buf<'a>(
    out_buf: &Vec<u8>,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty_out_buf(out_buf) {
            if *printempty == true {
                if options.opt_present("n") {
                    println!("     {}\t", linenum);
                    linenum = linenum + 1;
                }
                else {
                    println!("");
                }
            }
            linenum = print_buf(&out_buf, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_buf(&out_buf, linenum, options);
    }
    (*printempty, linenum)
}

fn print_string<'a>(s: &String, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_buf<'a>(out_buf: &Vec<u8>, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty_out_buf(out_buf) {
            print_numbered_buf(out_buf, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered_buf(out_buf, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered_buf(out_buf, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered_buf(out_buf, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_numbered_buf<'a>(out_buf: &Vec<u8>, linenum: u32, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        let mut t = 0u8;
        for b in out_buf.iter() {
            if t > 0 {
                t = t + *b;
                // print!("t: {} ", t);
                print!("{}", t as char);
                t = 0;
            }
            else {
                if *b > 160 {
                    t = *b;
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn print_unnumbered_buf(out_buf: &Vec<u8>, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        let mut t = 0;
        let mut buf: Vec<u8> = vec![];
        for b in out_buf.iter() {
            if t > 0 {
                buf.push(*b);
                t = t - 1;
                if t == 0 {
                    print_u8_buf(&mut buf, options);
                    buf.clear();
                }
            }
            else {
                if *b >= 240 {
                    //4th byte
                    t = 3;
                    buf.push(*b);
                }
                else if *b >= 224 {
                    t = 2;
                    buf.push(*b);
                }
                else if *b >= 192 {
                    t = 1;
                    buf.push(*b);
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
    // else {
        // print!("{}", s);
    // }
}

fn print_u8_buf(buf: &mut Vec<u8>, options: &getopts::Matches) {
    match convert_buf_to_codepoint(buf) {
        Ok(codepoint) => {
            match char::from_u32(codepoint) {
                Some(c) => print!("{}", c),
                None => {
                    for b in buf.iter() {
                        print_byte(b, options);
                    }
                }

            }
        },
        Err(_) => {
            for b in buf.iter() {
                print_byte(b, options);
            }
        }
    }
}

fn convert_buf_to_codepoint(buf: &mut Vec<u8>) -> Result<u32, String> {
    let mut s = 0u32;
    let mut l = buf.len();
    let orig_l = l;
    for b in buf.iter() {
        if l == 4 {
            s = s + ((*b as u32 | 240) - 240) << 19;
        }
        else if l == 3 {
            if orig_l == 4 && *b > 191 {
                return Err("Couldn't parse".to_string());
            }
            else {
                s = s + ((*b as u32 | 224) - 224) << 12;
            }
        }
        else if l == 2 {
            if (orig_l == 4 || orig_l == 3) && *b > 191 {
                return Err("Couldn't parse".to_string());
            }
            else {
                s = s + (((*b as u32 | 192) - 192) << 6);
            }
        }
        else if l == 1 {
            if orig_l > 1 {
                if *b > 191 {
                    return Err("Couldn't parse".to_string());
                }
                else {
                    s = s + ((*b as u32 | 128) - 128);
                }
            }
            else {
                s = s + ((*b as u32 | 192) - 192);
            }
        }
        l = l - 1;
    }
    Ok(s)
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn is_empty_out_buf(v: &Vec<u8>) -> bool {
    if v.len() > 1 {
        false
    }
    else if is_nl(&v[0]) {
        true
    }
    else {
        false
    }
}

fn is_nl(c: &u8) -> bool {
    *c == 10u8
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if (*b > 31 && *b < 127) || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print_tab();
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        if options.opt_present("v") || options.opt_present("t") {
            if *b < 32 {
                print!("^{}", (*b + 64) as char);
            }
            else if *b == 127 {
                // del char
                print!("^?");
            }
            else if *b > 127 {
                if *b == 255 {
                    print!("M-^?");
                }
                else {
                    let x = *b - 128;
                    if x < 32 {
                        print!("M-^{}", (x + 64) as char);
                    }
                    else {
                        print!("M-{}", (*b - 128) as char);
                    }
                }
            }
        }
    }
}

fn print_tab() {
    print!("^I");
}

#[cfg(test)]
mod tests {
    use super::is_empty;
    use super::convert_buf_to_codepoint;

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_buf_to_codepoint_24() {
        let mut b = vec![24u8];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 24u32);
    }

    #[test]
    fn assert_buf_to_codepoint_36() {
        let mut b = vec![164u8];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 36);
    }

    #[test]
    fn assert_buf_to_codepoint_162() {
        // ¢
        // C2 A2
        // 11000010 10100010
        // 00010100010
        let mut b = vec![194u8, 162];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 162);
    }

    #[test]
    fn assert_buf_to_codepoint_8364() {
        // €
        // E2 82 AC
        // 11100010 10000010 10101100
        // 0010000010101100
        let mut b = vec![226u8, 130, 172];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 8364);
    }

    #[test]
    fn assert_buf_to_codepoint_294() {
        // c4 a6
        // 11000100 10100110
        // 00100100110
        let mut b = vec![196u8, 166];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 294);
    }

    #[test]
    fn assert_buf_to_codepoint_66376() {
        // F0 90 8D 88
        // 11110000 10010000 10001101 10001000
        // 00001 00000011 01001000
        let mut b = vec![240u8, 144, 141, 136];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 66376);
    }

    #[test]
    fn assert_buf_to_codepoint_192193_err() {
        let mut b = vec![192u8, 193];
        assert!(convert_buf_to_codepoint(&mut b).is_err());
    }

}
<|endoftext|>


<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<i32>(), name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<u32>(), name); }
}

pub fn i64(data: *const i64, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<i64>(), name); }
}

pub fn u64(data: *const u64, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<u64>(), name); }
}

pub fn str(data: &str, name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}

pub fn bytes(data: &[u8], name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<i32>(), name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<u32>(), name); }
}

pub fn i64(data: *const i64, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<i64>(), name); }
}

pub fn u64(data: *const u64, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<u64>(), name); }
}

pub fn str(data: &str, name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}

pub fn bytes(data: &[u8], name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}
<|endoftext|>


<commit_before>extern crate byteorder;
use std::io::Read;
use std::fs;
use std::path::Path;
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use std::collections::HashMap;

struct Decoder {
    file_name: String,
    fit_buf: Vec<u8>,
    header: FitHeader,
    global_mesage_table: GlobalMessage
}

#[derive(Debug)]
struct FitHeader {
    size: u8,
    protocol_version: u8,
    profile_version: u16,
    data_size: u32,
    fit_str: String,
    crc: u16
}

impl Default for FitHeader {
    fn default() -> FitHeader {
        return FitHeader{
                fit_str: String::new(),
                profile_version: 0,
                protocol_version: 0,
                data_size: 0,
                crc: 0,
                size: 0
            }
    }
}

struct FieldDefinition {
    field_number: u8,
    size: u8,
    base_type_number: u8
}

struct GlobalMessage {
    table: HashMap<u16, &'static str>
}

impl GlobalMessage {
    fn new() -> GlobalMessage {
        let global_table = GlobalMessage::make_global_table();
        return GlobalMessage {
            table: global_table
        }
    }

    fn get(&self, key: u16) -> &'static str {
        let result = self.table.get(&key);

        match result {
            Some(r) => return r,
            None => panic!("Unregcognized Global Message Number: {}", key)
        };
    }

    fn make_global_table() -> HashMap<u16, &'static str> {
        let mut global_table = HashMap::new();
        global_table.insert(0, "file_id");
        global_table.insert(1, "capabilities");
        global_table.insert(2, "device_settings");
        global_table.insert(3, "user_profile");
        global_table.insert(4, "hrm_profile");
        global_table.insert(5, "sdm_profile");
        global_table.insert(6, "bike_profile");
        global_table.insert(7, "zones_target");
        global_table.insert(8, "hr_zone");
        global_table.insert(9, "power_zone");
        global_table.insert(10, "met_zone");
        global_table.insert(12, "sport");
        global_table.insert(15, "goal");
        global_table.insert(18, "session");
        global_table.insert(19, "lap");
        global_table.insert(20, "record");
        global_table.insert(21, "event");
        global_table.insert(23, "device_info");
        global_table.insert(26, "workout");
        global_table.insert(27, "workout_step");
        global_table.insert(28, "schedule");
        global_table.insert(30, "weight_scale");
        global_table.insert(31, "course");
        global_table.insert(32, "course_point");
        global_table.insert(33, "totals");
        global_table.insert(34, "activity");
        global_table.insert(35, "software");
        global_table.insert(37, "file_capabilities");
        global_table.insert(38, "mesg_capabilities");
        global_table.insert(39, "field_capabilities");
        global_table.insert(49, "file_creator");
        global_table.insert(51, "blood_pressure");
        global_table.insert(53, "speed_zone");
        global_table.insert(55, "monitoring");
        global_table.insert(72, "training_file");
        global_table.insert(78, "hrv");
        global_table.insert(80, "ant_rx");
        global_table.insert(81, "ant_tx");
        global_table.insert(82, "ant_channel_id");
        global_table.insert(101, "length");
        global_table.insert(103, "monitoring_info");
        global_table.insert(105, "pad");
        global_table.insert(106, "slave_device");
        global_table.insert(131, "cadance_sonze");
        global_table.insert(132, "hr");
        global_table.insert(142, "segment_lap");
        global_table.insert(145, "memo_glob");
        global_table.insert(148, "segment_id");
        global_table.insert(149, "segment_leaderboard_entry");
        global_table.insert(150, "segment_point");
        global_table.insert(151, "segment_file");
        global_table.insert(160, "gps_metadata");
        global_table.insert(161, "camera_event");
        global_table.insert(162, "timestamp_correlation");
        global_table.insert(164, "gyroscope_data");
        global_table.insert(165, "accelerometer_data");
        global_table.insert(167, "three_d_sensor_calibration");
        global_table.insert(169, "video_frame");
        global_table.insert(174, "obdii_data");
        global_table.insert(177, "nmea_sentence");
        global_table.insert(178, "aviation_attitude");
        global_table.insert(184, "video");
        global_table.insert(185, "video_title");
        global_table.insert(186, "video_description");
        global_table.insert(187, "video_clip");
        global_table.insert(0xFF00, "mfg_range_min");
        global_table.insert(0xFFFE, "mfg_range_max");

        return global_table;
    }
}

impl Decoder {
    pub fn new(file_name: String) -> Decoder {
        return Decoder {
            file_name: file_name,
            fit_buf: Vec::new(),
            header: FitHeader::default(),
            global_mesage_table: GlobalMessage::new()
        }
    }

    pub fn decode(&mut self) {
        self.fit_buf = read_bin(&self.file_name);

        /*for w in &self.fit_buf {
            println!("{}", w);
        }
        */
        self.decode_header();
        self.decode_records();
    }

    fn decode_header(&mut self) {
        let header = self.read_header();

        let header_size = header[0];

        let protocol_version = header[1];

        let protocol_profile_major = header[2];

        let protocol_profile_minor = header[3];

        let full_profile_version: u16 = (header[3] as u16) << 8 | (header[2] as u16);

        let record_size_in_bytes: u32 = (header[7] as u32) << 24 |
            (header[6] as u32) << 16 |
            (header[5] as u32) << 8 |
            (header[4] as u32);

        let mut fit_str = String::new();
        fit_str.push(header[8] as char);
        fit_str.push(header[9] as char);
        fit_str.push(header[10] as char);
        fit_str.push(header[11] as char);

        let crc: u16 = (header[13] as u16) << 8 | (header[12] as u16);

       self.header.size = header_size;
       self.header.protocol_version = protocol_version;
       self.header.profile_version = full_profile_version;
       self.header.fit_str = fit_str;
       self.header.data_size = record_size_in_bytes;
       self.header.crc = crc;

       println!("{:?}", self.header);
    }

    fn read_header(&self) -> Vec<u8> {
        let word0 = self.fit_buf[0];
        let word1 = self.fit_buf[1];

        let headerVec: Vec<u8> = self.fit_buf.iter().take(14).map(|b| *b).collect();

        return headerVec;
    }

    fn decode_records(&self) {
        let record_header = self.fit_buf[14];
        println!("{:#b}", record_header);
        let arch = self.fit_buf[16];
        println!("{:#b}", arch);

        let global_message_number: u16 = (self.fit_buf[18] as u16) << 8 | (self.fit_buf[17] as u16);
        println!("Global Message Number: {}", global_message_number);

        let global_message = self.global_mesage_table.get(global_message_number);
        println!("Global Message: {}", global_message);

        let num_fields = self.fit_buf[19];
        println!("Number of Fields: {}", num_fields);

        let index: usize = 20;
        let fields: usize = num_fields as usize;
        for f in 0..fields {
            let current_index: usize = index + (3 * f);
            let field_def_num = self.fit_buf[current_index];
            let size = self.fit_buf[current_index + 1];
            let base_type = self.fit_buf[current_index + 2];

            println!("{}  {}  {}", field_def_num, size, base_type);
        }
    }
}

fn read_bin<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut file = fs::File::open(path).unwrap();
    let mut file_buf = Vec::new();
    file.read_to_end(&mut file_buf).unwrap();
    file_buf
}

#[test]
fn it_works() {
    let mut decoder = Decoder::new(String::from("./test_files/1025146781.fit"));
    decoder.decode();
}
<commit_msg>More Tables implemented and reading more data<commit_after>extern crate byteorder;
use std::io::Read;
use std::fs;
use std::path::Path;
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use std::collections::HashMap;

struct Decoder {
    file_name: String,
    fit_buf: Vec<u8>,
    header: FitHeader,
    global_mesage_table: GlobalMessage,
    file_id_table: FileIdMessage,
}

#[derive(Debug)]
struct FitHeader {
    size: u8,
    protocol_version: u8,
    profile_version: u16,
    data_size: u32,
    fit_str: String,
    crc: u16
}

impl Default for FitHeader {
    fn default() -> FitHeader {
        return FitHeader{
                fit_str: String::new(),
                profile_version: 0,
                protocol_version: 0,
                data_size: 0,
                crc: 0,
                size: 0
            }
    }
}

struct FieldDefinition {
    field_number: u8,
    size: u8,
    base_type_number: u8
}

struct FileIdMessage {
    table: HashMap<u8, &'static str>
}

struct GlobalMessage {
    table: HashMap<u16, &'static str>
}

impl GlobalMessage {
    fn new() -> GlobalMessage {
        let global_table = GlobalMessage::make_global_table();
        return GlobalMessage {
            table: global_table
        }
    }

    fn get(&self, key: u16) -> &'static str {
        let result = self.table.get(&key);

        match result {
            Some(r) => return r,
            None => panic!("Unregcognized Global Message Number: {}", key)
        };
    }

    fn make_global_table() -> HashMap<u16, &'static str> {
        let mut global_table = HashMap::new();
        global_table.insert(0, "file_id");
        global_table.insert(1, "capabilities");
        global_table.insert(2, "device_settings");
        global_table.insert(3, "user_profile");
        global_table.insert(4, "hrm_profile");
        global_table.insert(5, "sdm_profile");
        global_table.insert(6, "bike_profile");
        global_table.insert(7, "zones_target");
        global_table.insert(8, "hr_zone");
        global_table.insert(9, "power_zone");
        global_table.insert(10, "met_zone");
        global_table.insert(12, "sport");
        global_table.insert(15, "goal");
        global_table.insert(18, "session");
        global_table.insert(19, "lap");
        global_table.insert(20, "record");
        global_table.insert(21, "event");
        global_table.insert(23, "device_info");
        global_table.insert(26, "workout");
        global_table.insert(27, "workout_step");
        global_table.insert(28, "schedule");
        global_table.insert(30, "weight_scale");
        global_table.insert(31, "course");
        global_table.insert(32, "course_point");
        global_table.insert(33, "totals");
        global_table.insert(34, "activity");
        global_table.insert(35, "software");
        global_table.insert(37, "file_capabilities");
        global_table.insert(38, "mesg_capabilities");
        global_table.insert(39, "field_capabilities");
        global_table.insert(49, "file_creator");
        global_table.insert(51, "blood_pressure");
        global_table.insert(53, "speed_zone");
        global_table.insert(55, "monitoring");
        global_table.insert(72, "training_file");
        global_table.insert(78, "hrv");
        global_table.insert(80, "ant_rx");
        global_table.insert(81, "ant_tx");
        global_table.insert(82, "ant_channel_id");
        global_table.insert(101, "length");
        global_table.insert(103, "monitoring_info");
        global_table.insert(105, "pad");
        global_table.insert(106, "slave_device");
        global_table.insert(131, "cadance_sonze");
        global_table.insert(132, "hr");
        global_table.insert(142, "segment_lap");
        global_table.insert(145, "memo_glob");
        global_table.insert(148, "segment_id");
        global_table.insert(149, "segment_leaderboard_entry");
        global_table.insert(150, "segment_point");
        global_table.insert(151, "segment_file");
        global_table.insert(160, "gps_metadata");
        global_table.insert(161, "camera_event");
        global_table.insert(162, "timestamp_correlation");
        global_table.insert(164, "gyroscope_data");
        global_table.insert(165, "accelerometer_data");
        global_table.insert(167, "three_d_sensor_calibration");
        global_table.insert(169, "video_frame");
        global_table.insert(174, "obdii_data");
        global_table.insert(177, "nmea_sentence");
        global_table.insert(178, "aviation_attitude");
        global_table.insert(184, "video");
        global_table.insert(185, "video_title");
        global_table.insert(186, "video_description");
        global_table.insert(187, "video_clip");
        global_table.insert(0xFF00, "mfg_range_min");
        global_table.insert(0xFFFE, "mfg_range_max");

        return global_table;
    }
}

impl FileIdMessage {
    fn new() -> FileIdMessage {
        return FileIdMessage {
            table: FileIdMessage::make_table()
        }
    }

    fn get(&self, key: u8) -> &'static str {
        let result = self.table.get(&key);

        match result {
            Some(r) => return r,
            None => panic!("Unrecognized File ID Key: {}", key)
        };
    }

    fn make_table() -> HashMap<u8, &'static str> {
        let mut table = HashMap::new();
        table.insert(0, "type");
        table.insert(1, "manufacturer");
        table.insert(2, "product");
        table.insert(3, "serial_number");
        table.insert(4, "time_created");
        table.insert(5, "number");
        table.insert(7, "product_name");

        return table;
    }
}

impl Decoder {
    pub fn new(file_name: String) -> Decoder {
        return Decoder {
            file_name: file_name,
            fit_buf: Vec::new(),
            header: FitHeader::default(),
            global_mesage_table: GlobalMessage::new(),
            file_id_table: FileIdMessage::new(),
        }
    }

    pub fn decode(&mut self) {
        self.fit_buf = read_bin(&self.file_name);

        /*for w in &self.fit_buf {
            println!("{}", w);
        }
        */
        self.decode_header();
        self.decode_records();
    }

    fn decode_header(&mut self) {
        let header = self.read_header();

        let header_size = header[0];

        let protocol_version = header[1];

        let protocol_profile_major = header[2];

        let protocol_profile_minor = header[3];

        let full_profile_version: u16 = (header[3] as u16) << 8 | (header[2] as u16);

        let record_size_in_bytes: u32 = (header[7] as u32) << 24 |
            (header[6] as u32) << 16 |
            (header[5] as u32) << 8 |
            (header[4] as u32);

        let mut fit_str = String::new();
        fit_str.push(header[8] as char);
        fit_str.push(header[9] as char);
        fit_str.push(header[10] as char);
        fit_str.push(header[11] as char);

        let crc: u16 = (header[13] as u16) << 8 | (header[12] as u16);

       self.header.size = header_size;
       self.header.protocol_version = protocol_version;
       self.header.profile_version = full_profile_version;
       self.header.fit_str = fit_str;
       self.header.data_size = record_size_in_bytes;
       self.header.crc = crc;

       println!("{:?}", self.header);
    }

    fn read_header(&self) -> Vec<u8> {
        let word0 = self.fit_buf[0];
        let word1 = self.fit_buf[1];

        let headerVec: Vec<u8> = self.fit_buf.iter().take(14).map(|b| *b).collect();

        return headerVec;
    }

    fn decode_records(&self) {
        let record_header = self.fit_buf[14];
        println!("{:#b}", record_header);
        let arch = self.fit_buf[16];
        println!("{:#b}", arch);

        let global_message_number: u16 = (self.fit_buf[18] as u16) << 8 | (self.fit_buf[17] as u16);
        println!("Global Message Number: {}", global_message_number);

        let global_message = self.global_mesage_table.get(global_message_number);
        println!("Global Message: {}", global_message);

        let num_fields = self.fit_buf[19];
        println!("Number of Fields: {}", num_fields);

        let index: usize = 20;
        let fields: usize = num_fields as usize;
        let mut pos = index;
        for f in 0..fields {
            let current_index: usize = index + (3 * f);
            let field_def_num = self.fit_buf[current_index];
            let size = self.fit_buf[current_index + 1];
            let base_type = self.fit_buf[current_index + 2];

            let field_kind = self.file_id_table.get(field_def_num);

            println!("{}: {}  {}  {}", field_kind, field_def_num, size, base_type);
            pos += 3;
        }

        let data_header = self.fit_buf[pos];
        pos += 1;
        println!("{:#b}", data_header);

        let type_value = self.fit_buf[pos];
        println!("Type: {}", type_value);
    }
}

fn read_bin<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut file = fs::File::open(path).unwrap();
    let mut file_buf = Vec::new();
    file.read_to_end(&mut file_buf).unwrap();
    file_buf
}

#[test]
fn it_works() {
    let mut decoder = Decoder::new(String::from("./test_files/1025146781.fit"));
    decoder.decode();
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::{parse_expr, parse_item, Abi, BareFnArg, BareFnTy, Block, Constness, Expr, ExprKind,
          FnArg, FnDecl, Generics, Ident, Item, ItemKind, Pat, Path, PathSegment, UnOp, Unsafety,
          Visibility};
use quote::{Tokens, ToTokens};
use std::option::Option;

#[proc_macro_attribute]
pub fn runtime_target_feature(features: TokenStream, function: TokenStream) -> TokenStream {
    let features_string = features.to_string();

    let features_str = strip_quotes(strip_parens(features_string.as_str()))
        .split(";")
        .map(str::trim)
        .collect::<Vec<_>>();

    let features = features_str
        .iter()
        .map(|x| {
                 x.split(",")
                     .map(str::trim)
                     .map(Feature::new)
                     .collect::<Vec<_>>()
             })
        .collect::<Vec<_>>();

    let have_features = features
        .iter()
        .map(|x| x.iter().map(|ref x| x.checker_expr()).collect::<Vec<_>>())
        .collect::<Vec<_>>();

    let function_string = function.to_string();

    let function_item = syn::parse_item(&function_string).unwrap();
    let function_type = function_item_to_type(&function_item.node);

    let (function_decl, function_unsafety, function_constness, function_abi, function_generics) =
        match function_item.node {
            ItemKind::Fn(ref a, b, c, ref d, ref e, _) => (a.as_ref(), b, c, d, e),
            _ => panic!("item must be a function"),
        };

    let args = function_decl
        .inputs
        .iter()
        .map(fn_arg_to_expr)
        .collect::<Vec<_>>();

    let setup_ident = Ident::new("setup");
    let default_ident = Ident::new("default");
    let features_ident: Vec<Ident> = features
        .iter()
        .map(|x| {
                 x.iter()
                     .map(|x| x.to_ident_string())
                     .fold("with".to_string(), |acc, x| acc + "_" + &x)
                     .into()
             })
        .collect();

    let function_item_default = Item {
        ident: default_ident.clone(),
        vis: Visibility::Inherited,
        attrs: function_item.attrs.clone(),
        node: function_item.node.clone(),
    };

    let function_item_with_features = features_ident
        .iter()
        .map(|x| {
                 Item {
                     ident: x.clone(),
                     vis: Visibility::Inherited,
                     attrs: function_item.attrs.clone(),
                     node: function_item.node.clone(),
                 }
             })
        .collect::<Vec<_>>();

    let setup_args = args.clone();

    let setup_block_tokens = quote! {
        {
            let chosen_function = #(if #(#have_features)&&* {
                #features_ident
            } else )*{
                #default_ident
            };

            PTR.store(chosen_function, rt::atomic::Ordering::Relaxed);

            chosen_function(#(#setup_args),*)
        }
    };

    let setup_block = parse_block(setup_block_tokens.as_str());
    let setup_node = ItemKind::Fn(Box::new(function_decl.clone()),
                                  function_unsafety,
                                  function_constness,
                                  function_abi.clone(),
                                  function_generics.clone(),
                                  setup_block);

    let function_item_setup = Item {
        ident: setup_ident.clone(),
        vis: Visibility::Inherited,
        attrs: function_item.attrs.clone(),
        node: setup_node,
    };

    let dispatch_function_block_tokens = quote! {
        {
            pub extern crate runtime_target_feature_rt as rt;

            static PTR: rt::atomic::Atomic<#function_type> = rt::atomic::Atomic::new(#setup_ident);

            #function_item_setup

            #function_item_default

            #(#[target_feature = #features_str]
            #function_item_with_features)*

            PTR.load(rt::atomic::Ordering::Relaxed)(#(#args),*)
        }
    };

    let dispatch_function_block = parse_block(dispatch_function_block_tokens.as_str());

    let dispatch_function_node = ItemKind::Fn(Box::new(function_decl.clone()),
                                              function_unsafety,
                                              function_constness,
                                              function_abi.clone(),
                                              function_generics.clone(),
                                              dispatch_function_block);

    let dispatch_function = Item {
        ident: function_item.ident.clone(),
        vis: function_item.vis,
        attrs: function_item.attrs.clone(),
        node: dispatch_function_node,
    };

    let mut tokens = Tokens::new();
    dispatch_function.to_tokens(&mut tokens);
    println!("{}", tokens);
    tokens.parse().unwrap()
}

fn parse_block(input: &str) -> Box<Block> {
    Box::new(match parse_expr(input).unwrap().node {
                 ExprKind::Block(_, block) => block,
                 _ => unreachable!(),
             })
}

fn strip_parens(str_with_parens: &str) -> &str {
    if !(str_with_parens.starts_with("(") || str_with_parens.ends_with(")")) {
        panic!("attribute arguments must begin with '(' and end with ')'");
    }

    &str_with_parens[1..str_with_parens.len() - 1].trim()
}

fn strip_quotes(str_with_quotes: &str) -> &str {
    if !(str_with_quotes.starts_with("\"") || str_with_quotes.ends_with("\"")) {
        panic!("attribute arguments must be a string literal");
    }

    &str_with_quotes[1..str_with_quotes.len() - 1].trim()
}

fn function_item_to_type(item_kind: &ItemKind) -> BareFnTy {
    let (decl, unsafety, abi, generics): (&FnDecl, Unsafety, &Option<Abi>, &Generics) =
        match *item_kind {
            ItemKind::Fn(ref a, b, _, ref d, ref e, _) => (&*a, b, d, e),
            _ => panic!("item must be a function"),
        };

    let inputs = decl.inputs
        .iter()
        .map(|x| match *x {
                 FnArg::Captured(_, ref ty) => ty,
                 FnArg::Ignored(ref ty) => ty,
                 _ => panic!("self not supported"),
             })
        .map(|ty| {
                 BareFnArg {
                     name: Option::None,
                     ty: ty.clone(),
                 }
             })
        .collect::<Vec<_>>();

    let lifetimes = Vec::new(); // TODO

    BareFnTy {
        unsafety: unsafety,
        abi: abi.clone(),
        lifetimes: lifetimes,
        inputs: inputs,
        output: decl.output.clone(),
        variadic: decl.variadic,
    }
}

fn fn_arg_to_expr(arg: &FnArg) -> Expr {
    match *arg {
        FnArg::Captured(ref pat, _) => {
            match *pat {
                Pat::Ident(_, ref ident, _) => {
                    Expr {
                        node: ExprKind::Path(Option::None, Path::from(ident.clone())),
                        attrs: Vec::new(),
                    }
                }
                _ => panic!("pattern must be identifier"),
            }
        }
        _ => panic!("argument must be captured"),
    }
}

enum Feature<'a> {
    Enable(&'a str),
    Disable(&'a str),
}

impl<'a> Feature<'a> {
    fn new(feature_str: &'a str) -> Self {
        if feature_str.starts_with("+") {
            Feature::Enable(&feature_str[1..])
        } else if feature_str.starts_with("-") {
            Feature::Disable(&feature_str[1..])
        } else {
            panic!("feature must begin with '+' or '-'");
        }
    }

    fn name(&self) -> String {
        match *self {
                Feature::Enable(x) => x,
                Feature::Disable(x) => x,
            }
            .replace(|c| c == '.' || c == '-', "_")
    }

    fn to_ident_string(&self) -> String {
        match *self {
                Feature::Enable(_) => "enable_",
                Feature::Disable(_) => "disable_",
            }
            .to_string() + &self.name()
    }

    fn checker_expr(&self) -> Expr {
        let segments = ["rt", &("have_".to_string() + &self.name())]
            .iter()
            .map(|x| PathSegment::from(*x))
            .collect();
        let path = Path {
            global: false,
            segments: segments,
        };
        let function = Expr {
            node: ExprKind::Path(Option::None, path),
            attrs: Vec::new(),
        };
        let call = Expr {
            node: ExprKind::Call(Box::new(function), Vec::new()),
            attrs: Vec::new(),
        };
        match *self {
            Feature::Enable(_) => call,
            Feature::Disable(_) => {
                Expr {
                    node: ExprKind::Unary(UnOp::Not, Box::new(call)),
                    attrs: Vec::new(),
                }
            }
        }
    }
}
<commit_msg>tidy up<commit_after>#![feature(proc_macro)]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::{parse_expr, Abi, BareFnArg, BareFnTy, Block, Expr, ExprKind, FnArg, FnDecl, Generics,
          Ident, Item, ItemKind, Pat, Path, PathSegment, UnOp, Unsafety, Visibility};
use quote::{Tokens, ToTokens};
use std::option::Option;

#[proc_macro_attribute]
pub fn runtime_target_feature(features: TokenStream, function: TokenStream) -> TokenStream {
    let features_string = features.to_string();

    let features_str = strip_quotes(strip_parens(features_string.as_str()))
        .split(";")
        .map(str::trim)
        .collect::<Vec<_>>();

    let features = features_str
        .iter()
        .map(|x| {
                 x.split(",")
                     .map(str::trim)
                     .map(Feature::new)
                     .collect::<Vec<_>>()
             })
        .collect::<Vec<_>>();

    let have_features = features
        .iter()
        .map(|x| x.iter().map(|ref x| x.checker_expr()).collect::<Vec<_>>())
        .collect::<Vec<_>>();

    let function_string = function.to_string();

    let function_item = syn::parse_item(&function_string).unwrap();
    let function_type = function_item_to_type(&function_item.node);

    let (function_decl, function_unsafety, function_constness, function_abi, function_generics) =
        match function_item.node {
            ItemKind::Fn(ref a, b, c, ref d, ref e, _) => (a.as_ref(), b, c, d, e),
            _ => panic!("item must be a function"),
        };

    let args = function_decl
        .inputs
        .iter()
        .map(fn_arg_to_expr)
        .collect::<Vec<_>>();

    let setup_ident = Ident::new("setup");
    let default_ident = Ident::new("default");
    let features_ident: Vec<Ident> = features
        .iter()
        .map(|x| {
                 x.iter()
                     .map(|x| x.to_ident_string())
                     .fold("with".to_string(), |acc, x| acc + "_" + &x)
                     .into()
             })
        .collect();

    let function_item_default = Item {
        ident: default_ident.clone(),
        vis: Visibility::Inherited,
        attrs: function_item.attrs.clone(),
        node: function_item.node.clone(),
    };

    let function_item_with_features = features_ident
        .iter()
        .map(|x| {
                 Item {
                     ident: x.clone(),
                     vis: Visibility::Inherited,
                     attrs: function_item.attrs.clone(),
                     node: function_item.node.clone(),
                 }
             })
        .collect::<Vec<_>>();

    let setup_args = args.clone();

    let setup_block_tokens = quote! {
        {
            let chosen_function = #(if #(#have_features)&&* {
                #features_ident
            } else )*{
                #default_ident
            };

            PTR.store(chosen_function, rt::atomic::Ordering::Relaxed);

            chosen_function(#(#setup_args),*)
        }
    };

    let setup_block = parse_block(setup_block_tokens.as_str());
    let setup_node = ItemKind::Fn(Box::new(function_decl.clone()),
                                  function_unsafety,
                                  function_constness,
                                  function_abi.clone(),
                                  function_generics.clone(),
                                  setup_block);

    let function_item_setup = Item {
        ident: setup_ident.clone(),
        vis: Visibility::Inherited,
        attrs: function_item.attrs.clone(),
        node: setup_node,
    };

    let dispatch_function_block_tokens = quote! {
        {
            pub extern crate runtime_target_feature_rt as rt;

            static PTR: rt::atomic::Atomic<#function_type> = rt::atomic::Atomic::new(#setup_ident);

            #function_item_setup

            #function_item_default

            #(#[target_feature = #features_str]
            #function_item_with_features)*

            PTR.load(rt::atomic::Ordering::Relaxed)(#(#args),*)
        }
    };

    let dispatch_function_block = parse_block(dispatch_function_block_tokens.as_str());

    let dispatch_function_node = ItemKind::Fn(Box::new(function_decl.clone()),
                                              function_unsafety,
                                              function_constness,
                                              function_abi.clone(),
                                              function_generics.clone(),
                                              dispatch_function_block);

    let dispatch_function = Item {
        ident: function_item.ident.clone(),
        vis: function_item.vis,
        attrs: function_item.attrs.clone(),
        node: dispatch_function_node,
    };

    let mut tokens = Tokens::new();
    dispatch_function.to_tokens(&mut tokens);
    // println!("{}", tokens);
    tokens.parse().unwrap()
}

fn parse_block(input: &str) -> Box<Block> {
    Box::new(match parse_expr(input).unwrap().node {
                 ExprKind::Block(_, block) => block,
                 _ => unreachable!(),
             })
}

fn strip_parens(str_with_parens: &str) -> &str {
    if !(str_with_parens.starts_with("(") || str_with_parens.ends_with(")")) {
        panic!("attribute arguments must begin with '(' and end with ')'");
    }

    &str_with_parens[1..str_with_parens.len() - 1].trim()
}

fn strip_quotes(str_with_quotes: &str) -> &str {
    if !(str_with_quotes.starts_with("\"") || str_with_quotes.ends_with("\"")) {
        panic!("attribute arguments must be a string literal");
    }

    &str_with_quotes[1..str_with_quotes.len() - 1].trim()
}

fn function_item_to_type(item_kind: &ItemKind) -> BareFnTy {
    // TODO: handle generics
    let (decl, unsafety, abi, _): (&FnDecl, Unsafety, &Option<Abi>, &Generics) = match *item_kind {
        ItemKind::Fn(ref a, b, _, ref d, ref e, _) => (&*a, b, d, e),
        _ => panic!("item must be a function"),
    };

    let inputs = decl.inputs
        .iter()
        .map(|x| match *x {
                 FnArg::Captured(_, ref ty) => ty,
                 FnArg::Ignored(ref ty) => ty,
                 _ => panic!("self not supported"),
             })
        .map(|ty| {
                 BareFnArg {
                     name: Option::None,
                     ty: ty.clone(),
                 }
             })
        .collect::<Vec<_>>();

    let lifetimes = Vec::new(); // TODO

    BareFnTy {
        unsafety: unsafety,
        abi: abi.clone(),
        lifetimes: lifetimes,
        inputs: inputs,
        output: decl.output.clone(),
        variadic: decl.variadic,
    }
}

fn fn_arg_to_expr(arg: &FnArg) -> Expr {
    match *arg {
        FnArg::Captured(ref pat, _) => {
            match *pat {
                Pat::Ident(_, ref ident, _) => {
                    Expr {
                        node: ExprKind::Path(Option::None, Path::from(ident.clone())),
                        attrs: Vec::new(),
                    }
                }
                _ => panic!("pattern must be identifier"),
            }
        }
        _ => panic!("argument must be captured"),
    }
}

enum Feature<'a> {
    Enable(&'a str),
    Disable(&'a str),
}

impl<'a> Feature<'a> {
    fn new(feature_str: &'a str) -> Self {
        if feature_str.starts_with("+") {
            Feature::Enable(&feature_str[1..])
        } else if feature_str.starts_with("-") {
            Feature::Disable(&feature_str[1..])
        } else {
            panic!("feature must begin with '+' or '-'");
        }
    }

    fn name(&self) -> String {
        match *self {
                Feature::Enable(x) => x,
                Feature::Disable(x) => x,
            }
            .replace(|c| c == '.' || c == '-', "_")
    }

    fn to_ident_string(&self) -> String {
        match *self {
                Feature::Enable(_) => "enable_",
                Feature::Disable(_) => "disable_",
            }
            .to_string() + &self.name()
    }

    fn checker_expr(&self) -> Expr {
        let segments = ["rt", &("have_".to_string() + &self.name())]
            .iter()
            .map(|x| PathSegment::from(*x))
            .collect();
        let path = Path {
            global: false,
            segments: segments,
        };
        let function = Expr {
            node: ExprKind::Path(Option::None, path),
            attrs: Vec::new(),
        };
        let call = Expr {
            node: ExprKind::Call(Box::new(function), Vec::new()),
            attrs: Vec::new(),
        };
        match *self {
            Feature::Enable(_) => call,
            Feature::Disable(_) => {
                Expr {
                    node: ExprKind::Unary(UnOp::Not, Box::new(call)),
                    attrs: Vec::new(),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate librsync_sys as raw;

mod job;

use job::{Job, JobDriver};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, Read};
use std::ops::Deref;
use std::ptr;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureType {
    MD4,
    Blake2,
}

#[derive(Debug)]
pub enum Error {
    Blocked,
    Io(io::Error),
    Syntax,
    Mem,
    InputEnded,
    BadMagic,
    Unimplemented,
    Corrupt,
    Internal,
    Param,
    Unknown(i32),
}

pub type Result<T> = std::result::Result<T, Error>;

pub struct Signature<R: Read> {
    driver: JobDriver<R>,
}

pub struct Delta<R: Read> {
    driver: JobDriver<R>,
    _sumset: Sumset,
}

struct Sumset(*mut raw::rs_signature_t);

impl<R: Read> Signature<R> {
    pub fn new(old: R,
               new_block_len: usize,
               strong_len: usize,
               sig_magic: SignatureType)
               -> Result<Self> {
        let job = unsafe { raw::rs_sig_begin(new_block_len, strong_len, sig_magic.as_raw()) };
        if job.is_null() {
            return Err(Error::BadMagic);
        }
        Ok(Signature { driver: JobDriver::new(old, Job(job)), })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Signature<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<R: Read> Delta<R> {
    pub fn new<R2: Read>(input: R, signature: R2) -> Result<Self> {
        // load the signature
        let sumset = unsafe {
            let mut sumset = ptr::null_mut();
            let job = raw::rs_loadsig_begin(&mut sumset);
            assert!(!job.is_null());
            let mut job = JobDriver::new(signature, Job(job));
            try!(job.consume_input());
            let sumset = Sumset(sumset);
            let res = raw::rs_build_hash_table(*sumset);
            if res != raw::RS_DONE {
                return Err(Error::from(res));
            }
            sumset
        };
        let job = unsafe { raw::rs_delta_begin(*sumset) };
        assert!(!job.is_null());
        Ok(Delta {
            driver: JobDriver::new(input, Job(job)),
            _sumset: sumset,
        })
    }
}

impl<R: Read> Read for Delta<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Blocked => "blocked waiting for more data",
            Error::Io(ref err) => err.description(),
            Error::Syntax => "syntax error",
            Error::Mem => "out of memory",
            Error::InputEnded => "unexpected end of input file",
            Error::BadMagic => "bad magic number given",
            Error::Unimplemented => "unimplemented feature",
            Error::Corrupt => "unbelievable value in stream",
            Error::Internal => "internal error",
            Error::Param => "bad parameter",
            Error::Unknown(_) => "unknown error from librsync",
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref e) => write!(fmt, "{}", e),
            Error::Unknown(n) => write!(fmt, "unknown error {} from native library", n),
            _ => write!(fmt, "{}", std::error::Error::description(self)),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<raw::rs_result> for Error {
    fn from(err: raw::rs_result) -> Error {
        match err {
            raw::RS_BLOCKED => Error::Blocked,
            raw::RS_IO_ERROR => Error::Io(other_io_err("Unknown IO error from librsync")),
            raw::RS_SYNTAX_ERROR => Error::Syntax,
            raw::RS_MEM_ERROR => Error::Mem,
            raw::RS_INPUT_ENDED => Error::InputEnded,
            raw::RS_BAD_MAGIC => Error::BadMagic,
            raw::RS_UNIMPLEMENTED => Error::Unimplemented,
            raw::RS_CORRUPT => Error::Corrupt,
            raw::RS_INTERNAL_ERROR => Error::Internal,
            raw::RS_PARAM_ERROR => Error::Param,
            n => Error::Unknown(n),
        }
    }
}

impl SignatureType {
    pub fn from_raw(raw: raw::rs_magic_number) -> Option<Self> {
        match raw {
            raw::RS_MD4_SIG_MAGIC => Some(SignatureType::MD4),
            raw::RS_BLAKE2_SIG_MAGIC => Some(SignatureType::Blake2),
            _ => None,
        }
    }

    fn as_raw(&self) -> raw::rs_magic_number {
        match *self {
            SignatureType::MD4 => raw::RS_MD4_SIG_MAGIC,
            SignatureType::Blake2 => raw::RS_BLAKE2_SIG_MAGIC,
        }
    }
}

impl Drop for Sumset {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                raw::rs_free_sumset(self.0);
            }
        }
    }
}

impl Deref for Sumset {
    type Target = *mut raw::rs_signature_t;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn other_io_err<T: AsRef<str>>(msg: T) -> io::Error {
    io::Error::new(io::ErrorKind::Other, msg.as_ref())
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Cursor, Read};

    const DATA: &'static str = "this is a string to be tested";
    const DATA2: &'static str = "this is another string to be tested";

    fn data_signature() -> Vec<u8> {
        vec![0x72, 0x73, 0x01, 0x36, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x1b, 0x21,
             0x04, 0x8b, 0xad, 0x3c, 0xbd, 0x19, 0x09, 0x1d, 0x1b, 0x04, 0xf0, 0x9d, 0x1f, 0x64,
             0x31, 0xde, 0x15, 0xf4, 0x04, 0x87, 0x60, 0x96, 0x19, 0x50, 0x39]
    }

    #[test]
    fn signature() {
        let cursor = Cursor::new(DATA);
        let mut sig = Signature::new(cursor, 10, 5, SignatureType::MD4).unwrap();
        let mut signature = Vec::new();
        let read = sig.read_to_end(&mut signature).unwrap();
        assert_eq!(read, signature.len());
        assert_eq!(signature, data_signature());
    }

    #[test]
    fn delta() {
        let sig = data_signature();
        let sig = Cursor::new(sig);
        let input = Cursor::new(DATA2);
        let mut job = Delta::new(input, sig).unwrap();
        let mut delta = Vec::new();
        let read = job.read_to_end(&mut delta).unwrap();
        assert_eq!(read, delta.len());
    }
}
<commit_msg>Moved some errors into io::Error<commit_after>extern crate librsync_sys as raw;

mod job;

use job::{Job, JobDriver};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, Read};
use std::ops::Deref;
use std::ptr;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureType {
    MD4,
    Blake2,
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Syntax,
    Mem,
    InputEnded,
    BadMagic,
    Unimplemented,
    Internal,
    Param,
    Unknown(i32),
}

pub type Result<T> = std::result::Result<T, Error>;

pub struct Signature<R: Read> {
    driver: JobDriver<R>,
}

pub struct Delta<R: Read> {
    driver: JobDriver<R>,
    _sumset: Sumset,
}

struct Sumset(*mut raw::rs_signature_t);

impl<R: Read> Signature<R> {
    pub fn new(old: R,
               new_block_len: usize,
               strong_len: usize,
               sig_magic: SignatureType)
               -> Result<Self> {
        let job = unsafe { raw::rs_sig_begin(new_block_len, strong_len, sig_magic.as_raw()) };
        if job.is_null() {
            return Err(Error::BadMagic);
        }
        Ok(Signature { driver: JobDriver::new(old, Job(job)) })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Signature<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<R: Read> Delta<R> {
    pub fn new<R2: Read>(input: R, signature: R2) -> Result<Self> {
        // load the signature
        let sumset = unsafe {
            let mut sumset = ptr::null_mut();
            let job = raw::rs_loadsig_begin(&mut sumset);
            assert!(!job.is_null());
            let mut job = JobDriver::new(signature, Job(job));
            try!(job.consume_input());
            let sumset = Sumset(sumset);
            let res = raw::rs_build_hash_table(*sumset);
            if res != raw::RS_DONE {
                return Err(Error::from(res));
            }
            sumset
        };
        let job = unsafe { raw::rs_delta_begin(*sumset) };
        assert!(!job.is_null());
        Ok(Delta {
            driver: JobDriver::new(input, Job(job)),
            _sumset: sumset,
        })
    }
}

impl<R: Read> Read for Delta<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Syntax => "syntax error",
            Error::Mem => "out of memory",
            Error::InputEnded => "unexpected end of input file",
            Error::BadMagic => "bad magic number given",
            Error::Unimplemented => "unimplemented feature",
            Error::Internal => "internal error",
            Error::Param => "bad parameter",
            Error::Unknown(_) => "unknown error from librsync",
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref e) => write!(fmt, "{}", e),
            Error::Unknown(n) => write!(fmt, "unknown error {} from native library", n),
            _ => write!(fmt, "{}", std::error::Error::description(self)),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<raw::rs_result> for Error {
    fn from(err: raw::rs_result) -> Error {
        match err {
            raw::RS_BLOCKED => {
                Error::Io(io::Error::new(io::ErrorKind::WouldBlock,
                                         "blocked waiting for more data"))
            }
            raw::RS_IO_ERROR => Error::Io(other_io_err("unknown IO error from librsync")),
            raw::RS_SYNTAX_ERROR => Error::Syntax,
            raw::RS_MEM_ERROR => Error::Mem,
            raw::RS_INPUT_ENDED => Error::InputEnded,
            raw::RS_BAD_MAGIC => Error::BadMagic,
            raw::RS_UNIMPLEMENTED => Error::Unimplemented,
            raw::RS_CORRUPT => {
                Error::Io(io::Error::new(io::ErrorKind::InvalidData,
                                         "unbelievable value in stream"))
            }
            raw::RS_INTERNAL_ERROR => Error::Internal,
            raw::RS_PARAM_ERROR => Error::Param,
            n => Error::Unknown(n),
        }
    }
}

impl SignatureType {
    pub fn from_raw(raw: raw::rs_magic_number) -> Option<Self> {
        match raw {
            raw::RS_MD4_SIG_MAGIC => Some(SignatureType::MD4),
            raw::RS_BLAKE2_SIG_MAGIC => Some(SignatureType::Blake2),
            _ => None,
        }
    }

    fn as_raw(&self) -> raw::rs_magic_number {
        match *self {
            SignatureType::MD4 => raw::RS_MD4_SIG_MAGIC,
            SignatureType::Blake2 => raw::RS_BLAKE2_SIG_MAGIC,
        }
    }
}

impl Drop for Sumset {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                raw::rs_free_sumset(self.0);
            }
        }
    }
}

impl Deref for Sumset {
    type Target = *mut raw::rs_signature_t;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn other_io_err<T: AsRef<str>>(msg: T) -> io::Error {
    io::Error::new(io::ErrorKind::Other, msg.as_ref())
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Cursor, Read};

    const DATA: &'static str = "this is a string to be tested";
    const DATA2: &'static str = "this is another string to be tested";

    fn data_signature() -> Vec<u8> {
        vec![0x72, 0x73, 0x01, 0x36, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x1b, 0x21,
             0x04, 0x8b, 0xad, 0x3c, 0xbd, 0x19, 0x09, 0x1d, 0x1b, 0x04, 0xf0, 0x9d, 0x1f, 0x64,
             0x31, 0xde, 0x15, 0xf4, 0x04, 0x87, 0x60, 0x96, 0x19, 0x50, 0x39]
    }

    #[test]
    fn signature() {
        let cursor = Cursor::new(DATA);
        let mut sig = Signature::new(cursor, 10, 5, SignatureType::MD4).unwrap();
        let mut signature = Vec::new();
        let read = sig.read_to_end(&mut signature).unwrap();
        assert_eq!(read, signature.len());
        assert_eq!(signature, data_signature());
    }

    #[test]
    fn delta() {
        let sig = data_signature();
        let sig = Cursor::new(sig);
        let input = Cursor::new(DATA2);
        let mut job = Delta::new(input, sig).unwrap();
        let mut delta = Vec::new();
        let read = job.read_to_end(&mut delta).unwrap();
        assert_eq!(read, delta.len());
    }
}
<|endoftext|>


<commit_before>
extern crate core;
extern crate debug;

pub use poly::{
    Quad,
    Triangle,
    Polygon,
    PolyTri,
    PolyQuad,
    Vertices,
    VerticesIterator,
    MapToVertices
};

pub use triangulate::{
    EmitTriangles,
    Triangulate,
    TriangulateIterator
};

mod triangulate;
mod poly;

mod cube;
mod plane;

pub mod generators {
    pub use cube::Cube;
    pub use plane::Plane;
}
<commit_msg>forgot to add header to lib.rs<commit_after>//   Copyright Colin Sherratt 2014
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

extern crate core;
extern crate debug;

pub use poly::{
    Quad,
    Triangle,
    Polygon,
    PolyTri,
    PolyQuad,
    Vertices,
    VerticesIterator,
    MapToVertices
};

pub use triangulate::{
    EmitTriangles,
    Triangulate,
    TriangulateIterator
};

mod triangulate;
mod poly;

mod cube;
mod plane;

pub mod generators {
    pub use cube::Cube;
    pub use plane::Plane;
}
<|endoftext|>


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

#![crate_name = "core_graphics"]
#![crate_type = "rlib"]

extern crate libc;
extern crate std;
extern crate core_foundation;

#[cfg(target_os="macos")]
pub mod base;
#[cfg(target_os="macos")]
pub mod data_provider;
#[cfg(target_os="macos")]
pub mod font;
#[cfg(target_os="macos")]
pub mod geometry;
<commit_msg>Rust upgrade<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "core_graphics"]
#![crate_type = "rlib"]

extern crate libc;
extern crate core_foundation;

#[cfg(target_os="macos")]
pub mod base;
#[cfg(target_os="macos")]
pub mod data_provider;
#[cfg(target_os="macos")]
pub mod font;
#[cfg(target_os="macos")]
pub mod geometry;
<|endoftext|>


<commit_before>//! The `lonlat_bng` crate provides a function that converts decimal longitude
//! and latitude coordinates into British National Grid Coordinates
//!
//! Examples
//!
//!```
//! assert_eq!((516276, 173141), lonlat_bng::convert(-0.32824866, 51.44533267));
//!```

#[allow(non_snake_case)]
use std::f32::consts;
use std::mem;
use std::vec;
use std::boxed;

extern crate libc;
use libc::{c_int, c_float, size_t, uint32_t};
use std::slice;

#[repr(C)]
pub struct fTuple {
    a: c_float,
    b: c_float,
}

#[repr(C)]
pub struct iTuple {
    a: uint32_t,
    b: uint32_t,
}

#[repr(C)]
pub struct Array {
    data: *const libc::c_void,
    len: libc::size_t,
}

impl Array {
    unsafe fn as_u32_slice(&self) -> &[u32] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const u32, self.len as usize)
    }

    unsafe fn as_f32_slice(&self) -> &[f32] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f32, self.len as usize)
    }

    fn from_vec<T>(mut vec: Vec<T>) -> Array {
        // Important to make length and capacity match
        // A better solution is to track both length and capacity
        vec.shrink_to_fit();

        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t
        };

        // Whee! Leak the memory, and now the raw pointer (and
        // eventually C) is the owner.
        mem::forget(vec);

        array
    }
}

#[no_mangle]
pub extern fn convert_vec_c(lon: Array, lat: Array) -> Array {
    // we're receiving floats
    let lon = unsafe { lon.as_f32_slice() };
    let lat = unsafe { lat.as_f32_slice() };

    let vec: Vec<(i32, i32)> =
        lon.iter().zip(lat.iter())
        .map(|(&lon, &lat)| convert(lon, lat))
        .collect();
    let nvec = vec.iter()
        .map(|ints| iTuple { a: ints.0 as u32, b: ints.1 as u32 })
        .collect();

    Array::from_vec(nvec)
}

// http://stackoverflow.com/a/28124775/155423
fn round(x: f32) -> f32 {
    let y = x.floor();
    if x == y {
        x
    } else {
        let z = (2.0*x-y).floor();
        z * x.signum() // Should use copysign, but not stably-available
    }
}

/// This function performs lon, lat to BNG conversion
///
/// Examples
///
/// ```
/// use lonlat_bng::convert;
/// assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
#[no_mangle]
pub extern fn convert(input_lon: f32, input_lat: f32) -> (i32, i32) {

    // if not all([0 <= input_lat <= 90, -180 <= input_lon <= 180]):
    match input_lon {
        -180.0...180.0 => input_lon,
        _ => panic!("Out of bounds! Longitude must be between -180 and 180.")
    };
    match input_lat {
        -90.0...90.0 => input_lat,
        _ => panic!("Out of bounds! Latitude must be between -90 and 90.")
    };
    let pi: f32 = consts::PI;
    //Convert input to degrees
    let lat_1: f32 = input_lat * pi / 180.;
    let lon_1: f32 = input_lon * pi / 180.;
    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a_1: f32 = 6378137.;
    let b_1: f32 = 6356752.3141;
    // The eccentricity (squared) of the GRS80 ellipsoid
    let e2_1: f32 = 1. - (b_1.powf(2.)) / (a_1.powf(2.));
    // Transverse radius of curvature
    let nu_1: f32 = a_1 / (1. - e2_1 * lat_1.sin().powf(2.)).sqrt();
    // Third spherical coordinate is 0, in this case
    let H: f32 = 0.;
    let x_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.cos();
    let y_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.sin();
    let z_1: f32 = ((1. - e2_1) * nu_1 + H) * lat_1.sin();

    // Perform Helmert transform (to go between Airy 1830 (_1) and GRS80 (_2))
    let small: f32 = 10.;
    let cst: f32 = 20.4894;
    let s: f32 =  cst * small.powf(-6.);
    // The translations along x, y, z axes respectively
    let tx: f32 = -446.448;
    let ty: f32 = 125.157;
    let tz: f32 = -542.060;
    // The rotations along x, y, z respectively, in seconds
    let rxs: f32 = -0.1502;
    let rys: f32 = -0.2470;
    let rzs: f32 = -0.8421;
    // In radians
    let rx: f32 = rxs * pi / (180. * 3600.);
    let ry: f32 = rys * pi / (180. * 3600.);
    let rz: f32 = rzs * pi / (180. * 3600.);
    // panic begins on line 46
    let x_2: f32 = tx + (1. + s) * x_1 + -rz * y_1 + ry * z_1;
    let y_2: f32 = ty + rz * x_1 + (1. + s) * y_1 + -rx * z_1;
    let z_2: f32 = tz + -ry * x_1 + rx * y_1 + (1. + s) * z_1;

    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a: f32 = 6377563.396;
    let b: f32 = 6356256.909;
    // The eccentricity of the Airy 1830 ellipsoid
    let e2: f32 = 1. - b.powf(2.) / a.powf(2.);
    let p: f32 = (x_2.powf(2.) + y_2.powf(2.)).sqrt();
    // Initial value
    let mut lat: f32 = z_2.atan2((p * (1. - e2)));
    let mut latold: f32 = 2. * pi;
    // this is cheating, but not sure how else to initialise nu
    let mut nu: f32 = 1.;
    // Latitude is obtained by iterative procedure
    while (lat - latold).abs() > small.powf(-16.) {
        mem::swap(&mut lat, &mut latold);
        nu = a / (1. - e2 * latold.sin().powf(2.)).sqrt();
        lat = (z_2 + e2 * nu * latold.sin()).atan2(p);
    };
    let lon: f32 = y_2.atan2(x_2);
    // Scale factor on the central meridian
    let F0: f32 = 0.9996012717;
    // Latitude of true origin (radians)
    let lat0: f32 = 49. * pi / 180.;
    // Longtitude of true origin and central meridian (radians)
    let lon0: f32 = -2. * pi / 180.;
    // Northing & easting of true origin (m)
    let N0: f32 = -100000.;
    let E0: f32 = 400000.;
    let n: f32 = (a - b) / (a + b);
    // Meridional radius of curvature
    let rho: f32 = a * F0 * (1. - e2) * (1. - e2 * lat.sin().powf(2.)).powf(-1.5);
    let eta2: f32 = nu * F0 / rho - 1.;

    let M1: f32 = (1. + n + (5. / 4.) * n.powf(2.) + (5. / 4.) * n.powf(3.)) * (lat - lat0);
    let M2: f32 = (3. * n + 3. * n.powf(2.) + (21. / 8.) * n.powf(3.)) * (lat - lat0).sin() * (lat + lat0).cos();
    let M3: f32 = ((15. / 8.) * n.powf(2.) + (15. / 8.) * n.powf(3.)) * (2. * (lat-lat0)).sin() * (2. * (lat + lat0)).cos();
    let M4: f32 = (35. / 24.) * n.powf(3.) * (3. * (lat - lat0)).sin() * (3. * (lat + lat0)).cos();
    let M: f32 = b * F0 * (M1 - M2 + M3 - M4);

    let I: f32 = M + N0;
    let II: f32 = nu * F0 * lat.sin() * lat.cos() / 2.;
    let III: f32 = nu * F0 * lat.sin() * lat.cos().powf(3.) * (5. - lat.tan().powf(2.) + 9. * eta2) / 24.;
    let IIIA: f32 = nu * F0 * lat.sin() * lat.cos().powf(5.) * (61. - 58. * lat.tan().powf(2.) + lat.tan().powf(4.)) / 720.;
    let IV: f32 = nu * F0 * lat.cos();
    let V: f32 = nu * F0 * lat.cos().powf(3.) * (nu / rho - lat.tan().powf(2.)) / 6.;
    let VI: f32 = nu * F0 * lat.cos().powf(5.) * (5. - 18. * lat.tan().powf(2.) + lat.tan().powf(4.) + 14. * eta2 - 58. * eta2 * lat.tan().powf(2.)) / 120.;
    let N: f32 = I + II * (lon - lon0).powf(2.) + III * (lon - lon0).powf(4.) + IIIA * (lon - lon0).powf(6.);
    let E: f32 = E0 + IV * (lon - lon0) + V * (lon - lon0).powf(3.) + VI * (lon - lon0).powf(5.);
    return (round(E) as i32, round(N) as i32);
}

/// A wrapper for convert, which maps it over the zipped input vectors
pub fn convert_vec(input_lon: Vec<f32>, input_lat: Vec<f32>) -> Vec<(i32, i32)> {
    let combined: Vec<(i32, i32)> = input_lon
        .iter()
        .zip(input_lat.iter())
        .map(|each| convert(*each.0, *each.1))
        .collect();
    return combined
}

/// Essentially just a C-compatible wrapper for convert_vec
// http://stackoverflow.com/a/30511235/416626
#[no_mangle]
pub extern fn convert_vec_py(input_lon: *const c_float,
                            lon_size: size_t ,
                            input_lat: *const c_float,
                            lat_size: size_t) -> *const (i32, i32) {
    let input_lon = unsafe {
        slice::from_raw_parts(input_lon, lon_size as usize).to_owned()
    };
    let input_lat = unsafe {
        slice::from_raw_parts(input_lat, lat_size as usize).to_owned()
    };
    let res: Vec<(i32, i32)> = convert_vec(input_lon, input_lat).to_owned();
    let inter = res.as_ptr();
    mem::forget(res);
    inter
}

#[test]
fn test_vector_conversion() {
    let lons = vec![-0.32824866];
    let lats = vec![51.44533267];
    // let lon_s: size_t = 1;
    // let lat_s: size_t = 1;

    // let lons: Vec<f32> = vec![-0.32824866];
    // let lats: Vec<f32> = vec![51.44533267];
    assert_eq!(
        vec![(516276, 173141)],
        convert_vec(lons, lats,));
}

#[test]
fn test_conversion() {
    // verified to be correct at http://www.bgs.ac.uk/data/webservices/convertForm.cfm
    assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lon() {
    assert_eq!((516276, 173141), convert(181., 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lat() {
    assert_eq!((516276, 173141), convert(-0.32824866, -90.01));
}
<commit_msg>Move safe conversion wrapper around for clarity<commit_after>//! The `lonlat_bng` crate provides a function that converts decimal longitude
//! and latitude coordinates into British National Grid Coordinates
//!
//! Examples
//!
//!```
//! assert_eq!((516276, 173141), lonlat_bng::convert(-0.32824866, 51.44533267));
//!```

#[allow(non_snake_case)]
use std::f32::consts;
use std::mem;
use std::vec;
use std::boxed;

extern crate libc;
use libc::{c_int, c_float, size_t, uint32_t};
use std::slice;

#[repr(C)]
pub struct fTuple {
    a: c_float,
    b: c_float,
}

#[repr(C)]
pub struct iTuple {
    a: uint32_t,
    b: uint32_t,
}

#[repr(C)]
pub struct Array {
    data: *const libc::c_void,
    len: libc::size_t,
}

impl Array {
    unsafe fn as_u32_slice(&self) -> &[u32] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const u32, self.len as usize)
    }

    unsafe fn as_f32_slice(&self) -> &[f32] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f32, self.len as usize)
    }

    fn from_vec<T>(mut vec: Vec<T>) -> Array {
        // Important to make length and capacity match
        // A better solution is to track both length and capacity
        vec.shrink_to_fit();

        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t
        };

        // Whee! Leak the memory, and now the raw pointer (and
        // eventually C) is the owner.
        mem::forget(vec);

        array
    }
}

// http://stackoverflow.com/a/28124775/155423
fn round(x: f32) -> f32 {
    let y = x.floor();
    if x == y {
        x
    } else {
        let z = (2.0*x-y).floor();
        z * x.signum() // Should use copysign, but not stably-available
    }
}

/// This function performs lon, lat to BNG conversion
///
/// Examples
///
/// ```
/// use lonlat_bng::convert;
/// assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
#[no_mangle]
pub extern fn convert(input_lon: f32, input_lat: f32) -> (i32, i32) {

    // if not all([0 <= input_lat <= 90, -180 <= input_lon <= 180]):
    match input_lon {
        -180.0...180.0 => input_lon,
        _ => panic!("Out of bounds! Longitude must be between -180 and 180.")
    };
    match input_lat {
        -90.0...90.0 => input_lat,
        _ => panic!("Out of bounds! Latitude must be between -90 and 90.")
    };
    let pi: f32 = consts::PI;
    //Convert input to degrees
    let lat_1: f32 = input_lat * pi / 180.;
    let lon_1: f32 = input_lon * pi / 180.;
    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a_1: f32 = 6378137.;
    let b_1: f32 = 6356752.3141;
    // The eccentricity (squared) of the GRS80 ellipsoid
    let e2_1: f32 = 1. - (b_1.powf(2.)) / (a_1.powf(2.));
    // Transverse radius of curvature
    let nu_1: f32 = a_1 / (1. - e2_1 * lat_1.sin().powf(2.)).sqrt();
    // Third spherical coordinate is 0, in this case
    let H: f32 = 0.;
    let x_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.cos();
    let y_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.sin();
    let z_1: f32 = ((1. - e2_1) * nu_1 + H) * lat_1.sin();

    // Perform Helmert transform (to go between Airy 1830 (_1) and GRS80 (_2))
    let small: f32 = 10.;
    let cst: f32 = 20.4894;
    let s: f32 =  cst * small.powf(-6.);
    // The translations along x, y, z axes respectively
    let tx: f32 = -446.448;
    let ty: f32 = 125.157;
    let tz: f32 = -542.060;
    // The rotations along x, y, z respectively, in seconds
    let rxs: f32 = -0.1502;
    let rys: f32 = -0.2470;
    let rzs: f32 = -0.8421;
    // In radians
    let rx: f32 = rxs * pi / (180. * 3600.);
    let ry: f32 = rys * pi / (180. * 3600.);
    let rz: f32 = rzs * pi / (180. * 3600.);
    // panic begins on line 46
    let x_2: f32 = tx + (1. + s) * x_1 + -rz * y_1 + ry * z_1;
    let y_2: f32 = ty + rz * x_1 + (1. + s) * y_1 + -rx * z_1;
    let z_2: f32 = tz + -ry * x_1 + rx * y_1 + (1. + s) * z_1;

    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a: f32 = 6377563.396;
    let b: f32 = 6356256.909;
    // The eccentricity of the Airy 1830 ellipsoid
    let e2: f32 = 1. - b.powf(2.) / a.powf(2.);
    let p: f32 = (x_2.powf(2.) + y_2.powf(2.)).sqrt();
    // Initial value
    let mut lat: f32 = z_2.atan2((p * (1. - e2)));
    let mut latold: f32 = 2. * pi;
    // this is cheating, but not sure how else to initialise nu
    let mut nu: f32 = 1.;
    // Latitude is obtained by iterative procedure
    while (lat - latold).abs() > small.powf(-16.) {
        mem::swap(&mut lat, &mut latold);
        nu = a / (1. - e2 * latold.sin().powf(2.)).sqrt();
        lat = (z_2 + e2 * nu * latold.sin()).atan2(p);
    };
    let lon: f32 = y_2.atan2(x_2);
    // Scale factor on the central meridian
    let F0: f32 = 0.9996012717;
    // Latitude of true origin (radians)
    let lat0: f32 = 49. * pi / 180.;
    // Longtitude of true origin and central meridian (radians)
    let lon0: f32 = -2. * pi / 180.;
    // Northing & easting of true origin (m)
    let N0: f32 = -100000.;
    let E0: f32 = 400000.;
    let n: f32 = (a - b) / (a + b);
    // Meridional radius of curvature
    let rho: f32 = a * F0 * (1. - e2) * (1. - e2 * lat.sin().powf(2.)).powf(-1.5);
    let eta2: f32 = nu * F0 / rho - 1.;

    let M1: f32 = (1. + n + (5. / 4.) * n.powf(2.) + (5. / 4.) * n.powf(3.)) * (lat - lat0);
    let M2: f32 = (3. * n + 3. * n.powf(2.) + (21. / 8.) * n.powf(3.)) * (lat - lat0).sin() * (lat + lat0).cos();
    let M3: f32 = ((15. / 8.) * n.powf(2.) + (15. / 8.) * n.powf(3.)) * (2. * (lat-lat0)).sin() * (2. * (lat + lat0)).cos();
    let M4: f32 = (35. / 24.) * n.powf(3.) * (3. * (lat - lat0)).sin() * (3. * (lat + lat0)).cos();
    let M: f32 = b * F0 * (M1 - M2 + M3 - M4);

    let I: f32 = M + N0;
    let II: f32 = nu * F0 * lat.sin() * lat.cos() / 2.;
    let III: f32 = nu * F0 * lat.sin() * lat.cos().powf(3.) * (5. - lat.tan().powf(2.) + 9. * eta2) / 24.;
    let IIIA: f32 = nu * F0 * lat.sin() * lat.cos().powf(5.) * (61. - 58. * lat.tan().powf(2.) + lat.tan().powf(4.)) / 720.;
    let IV: f32 = nu * F0 * lat.cos();
    let V: f32 = nu * F0 * lat.cos().powf(3.) * (nu / rho - lat.tan().powf(2.)) / 6.;
    let VI: f32 = nu * F0 * lat.cos().powf(5.) * (5. - 18. * lat.tan().powf(2.) + lat.tan().powf(4.) + 14. * eta2 - 58. * eta2 * lat.tan().powf(2.)) / 120.;
    let N: f32 = I + II * (lon - lon0).powf(2.) + III * (lon - lon0).powf(4.) + IIIA * (lon - lon0).powf(6.);
    let E: f32 = E0 + IV * (lon - lon0) + V * (lon - lon0).powf(3.) + VI * (lon - lon0).powf(5.);
    return (round(E) as i32, round(N) as i32);
}

/// A wrapper for convert, which maps it over the zipped input vectors
pub fn convert_vec(input_lon: Vec<f32>, input_lat: Vec<f32>) -> Vec<(i32, i32)> {
    let combined: Vec<(i32, i32)> = input_lon
        .iter()
        .zip(input_lat.iter())
        .map(|each| convert(*each.0, *each.1))
        .collect();
    return combined
}

/// Essentially just a C-compatible wrapper for convert_vec
// http://stackoverflow.com/a/30511235/416626
#[no_mangle]
pub extern fn convert_vec_py(input_lon: *const c_float,
                            lon_size: size_t ,
                            input_lat: *const c_float,
                            lat_size: size_t) -> *const (i32, i32) {
    let input_lon = unsafe {
        slice::from_raw_parts(input_lon, lon_size as usize).to_owned()
    };
    let input_lat = unsafe {
        slice::from_raw_parts(input_lat, lat_size as usize).to_owned()
    };
    let res: Vec<(i32, i32)> = convert_vec(input_lon, input_lat).to_owned();
    let inter = res.as_ptr();
    mem::forget(res);
    inter
}

/// A safer C-compatible wrapper for convert
#[no_mangle]
pub extern fn convert_vec_c(lon: Array, lat: Array) -> Array {
    // we're receiving floats
    let lon = unsafe { lon.as_f32_slice() };
    let lat = unsafe { lat.as_f32_slice() };
    // map convert over our slices. Returns vector of integer tuples
    let vec: Vec<(i32, i32)> =
        lon.iter().zip(lat.iter())
        .map(|(&lon, &lat)| convert(lon, lat))
        .collect();
    // convert back to vector of unsigned integer Tuples
    let nvec = vec.iter()
        .map(|ints| iTuple { a: ints.0 as u32, b: ints.1 as u32 })
        .collect();

    Array::from_vec(nvec)
}

#[test]
fn test_vector_conversion() {
    let lons = vec![-0.32824866];
    let lats = vec![51.44533267];
    // let lon_s: size_t = 1;
    // let lat_s: size_t = 1;

    // let lons: Vec<f32> = vec![-0.32824866];
    // let lats: Vec<f32> = vec![51.44533267];
    assert_eq!(
        vec![(516276, 173141)],
        convert_vec(lons, lats,));
}

#[test]
fn test_conversion() {
    // verified to be correct at http://www.bgs.ac.uk/data/webservices/convertForm.cfm
    assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lon() {
    assert_eq!((516276, 173141), convert(181., 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lat() {
    assert_eq!((516276, 173141), convert(-0.32824866, -90.01));
}
<|endoftext|>