<commit_before>#![feature(test)]

use compiletest_rs as compiletest;
use libtest::TestDescAndFn;

use std::env::{set_var, var};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        let s: String = name.to_owned();
        config.filter = Some(s)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.target_rustcflags = Some(format!(
        "-L {0} -L {0}/deps -Dwarnings -Zui-testing",
        host_libs().display()
    ));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    let cfg = config(mode, dir);
    // clean rmeta data, otherwise "cargo check; cargo test" fails (#2896)
    cfg.clean_rmeta();
    compiletest::run_tests(&cfg);
}

fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir_path = dir.unwrap().path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests
                .iter()
                .position(|test| test.desc.name.to_string() == test_name.to_string())
                .expect("The test should be in there");
            let opts = libtest::TestOpts {
                list: opts.list,
                filter: opts.filter.clone(),
                filter_exact: opts.filter_exact,
                exclude_should_panic: Default::default(),
                run_ignored: libtest::RunIgnored::No,
                run_tests: opts.run_tests,
                bench_benchmarks: opts.bench_benchmarks,
                logfile: opts.logfile.clone(),
                nocapture: opts.nocapture,
                color: libtest::ColorConfig::AutoColor,
                format: libtest::OutputFormat::Pretty,
                test_threads: opts.test_threads,
                skip: opts.skip.clone(),
                options: libtest::Options::new(),
            };
            result &= libtest::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let tests = tests
        .into_iter()
        .map(|test| {
            libtest::TestDescAndFn {
                desc: libtest::TestDesc {
                    name: libtest::TestName::DynTestName(test.desc.name.to_string()),
                    ignore: test.desc.ignore,
                    allow_fail: test.desc.allow_fail,
                    should_panic: libtest::ShouldPanic::No,
                },
                // oli obk giving up
                testfn: unsafe { std::mem::transmute(test.testfn) },
            }
        })
        .collect();

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {},
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        },
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<commit_msg>Set level of identity_conversion FP to warn<commit_after>#![feature(test)]

use compiletest_rs as compiletest;
use libtest::TestDescAndFn;

use std::env::{set_var, var};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        let s: String = name.to_owned();
        config.filter = Some(s)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.target_rustcflags = Some(format!(
        "-L {0} -L {0}/deps -Dwarnings -Zui-testing",
        host_libs().display()
    ));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    let cfg = config(mode, dir);
    // clean rmeta data, otherwise "cargo check; cargo test" fails (#2896)
    cfg.clean_rmeta();
    compiletest::run_tests(&cfg);
}

#[warn(clippy::identity_conversion)]
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir_path = dir.unwrap().path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests
                .iter()
                .position(|test| test.desc.name.to_string() == test_name.to_string())
                .expect("The test should be in there");
            let opts = libtest::TestOpts {
                list: opts.list,
                filter: opts.filter.clone(),
                filter_exact: opts.filter_exact,
                exclude_should_panic: Default::default(),
                run_ignored: libtest::RunIgnored::No,
                run_tests: opts.run_tests,
                bench_benchmarks: opts.bench_benchmarks,
                logfile: opts.logfile.clone(),
                nocapture: opts.nocapture,
                color: libtest::ColorConfig::AutoColor,
                format: libtest::OutputFormat::Pretty,
                test_threads: opts.test_threads,
                skip: opts.skip.clone(),
                options: libtest::Options::new(),
            };
            result &= libtest::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let tests = tests
        .into_iter()
        .map(|test| {
            libtest::TestDescAndFn {
                desc: libtest::TestDesc {
                    name: libtest::TestName::DynTestName(test.desc.name.to_string()),
                    ignore: test.desc.ignore,
                    allow_fail: test.desc.allow_fail,
                    should_panic: libtest::ShouldPanic::No,
                },
                // oli obk giving up
                testfn: unsafe { std::mem::transmute(test.testfn) },
            }
        })
        .collect();

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {},
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        },
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<|endoftext|>


<commit_before>extern crate rosc;

use rosc::{encoder, decoder};
use rosc::types::{OscMessage, OscMidiMessage, OscPacket, OscType};

#[test]
fn test_encode_message_wo_args() {
    let msg = OscMessage {
        addr: "/some/addr".to_string(),
        args: None,
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(dec_msg) => assert_eq!(msg.addr, dec_msg.addr),
        _ => panic!("Expected OSC message!"),
    }
}

#[test]
fn test_encode_message_with_args() {
    let addr = "/another/address/1";
    let string_arg = "This is a string";
    let blob_arg = vec![1u8, 2u8, 3u8];
    let time_arg = (123, 456);
    let int_arg = 4;
    let float_arg = 3.14;
    let long_arg = 42;
    let double_arg = 3.1415;
    let char_arg = 'c';
    let midi_arg = OscMidiMessage {
        port: 12,
        status: 14,
        data1: 120,
        data2: 53,
    };
    let args = vec![OscType::Int(int_arg),
                    OscType::Float(float_arg),
                    OscType::String(string_arg.to_string()),
                    OscType::Blob(blob_arg.iter().cloned().collect()),
                    OscType::Time(time_arg.0, time_arg.1),
                    OscType::Long(long_arg),
                    OscType::Double(double_arg),
                    OscType::Char(char_arg),
                    OscType::Bool(false),
                    OscType::Bool(true),
                    OscType::Nil,
                    OscType::Inf,
                    OscType::Midi(OscMidiMessage {
                        port: midi_arg.port,
                        status: midi_arg.status,
                        data1: midi_arg.data1,
                        data2: midi_arg.data2,
                    })];
    let arg_cnt = args.len();

    let msg = OscMessage {
        addr: addr.to_string(),
        args: Some(args),
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    let dec_msg: OscMessage = match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(m) => m,
        _ => panic!("Expected OscMessage!"),
    };

    // check if osc address is equal
    assert_eq!(addr, dec_msg.addr);
    // check if there are arguments
    assert!(dec_msg.args.is_some());
    let dec_args = dec_msg.args.unwrap();

    // check if argument count is equal
    assert_eq!(arg_cnt, dec_args.len());

    for arg in dec_args {
        match arg {
            OscType::Int(x) => assert_eq!(int_arg, x),
            OscType::Long(x) => assert_eq!(long_arg, x),
            OscType::Float(x) => assert_eq!(float_arg, x),
            OscType::Double(x) => assert_eq!(double_arg, x),
            OscType::String(x) => assert_eq!(string_arg, x),
            OscType::Blob(x) => assert_eq!(blob_arg, x),
            OscType::Time(x, y) => assert_eq!(time_arg, (x, y)),
            OscType::Char(x) => assert_eq!(char_arg, x),
            OscType::Bool(_) => (),
            OscType::Inf => (),
            OscType::Nil => (),
            OscType::Midi(x) => {
                assert_eq!(midi_arg.port, x.port);
                assert_eq!(midi_arg.status, x.status);
                assert_eq!(midi_arg.data1, x.data1);
                assert_eq!(midi_arg.data2, x.data2);
            }
            _ => panic!("Unexpected OSC argument!"),
        }
    }
}
<commit_msg>Test color argument in encoder (and decoder)<commit_after>extern crate rosc;

use rosc::{encoder, decoder};
use rosc::types::{OscMessage, OscMidiMessage, OscColor, OscPacket, OscType};

#[test]
fn test_encode_message_wo_args() {
    let msg = OscMessage {
        addr: "/some/addr".to_string(),
        args: None,
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(dec_msg) => assert_eq!(msg.addr, dec_msg.addr),
        _ => panic!("Expected OSC message!"),
    }
}

#[test]
fn test_encode_message_with_args() {
    let addr = "/another/address/1";
    let string_arg = "This is a string";
    let blob_arg = vec![1u8, 2u8, 3u8];
    let time_arg = (123, 456);
    let int_arg = 4;
    let float_arg = 3.14;
    let long_arg = 42;
    let double_arg = 3.1415;
    let char_arg = 'c';
    let midi_arg = OscMidiMessage {
        port: 12,
        status: 14,
        data1: 120,
        data2: 53,
    };
    let color_arg = OscColor {
        red: 255u8,
        green: 192u8,
        blue: 42u8,
        alpha: 13u8,
    };
    let args = vec![OscType::Int(int_arg),
                    OscType::Float(float_arg),
                    OscType::String(string_arg.to_string()),
                    OscType::Blob(blob_arg.iter().cloned().collect()),
                    OscType::Time(time_arg.0, time_arg.1),
                    OscType::Long(long_arg),
                    OscType::Double(double_arg),
                    OscType::Char(char_arg),
                    OscType::Bool(false),
                    OscType::Bool(true),
                    OscType::Nil,
                    OscType::Inf,
                    OscType::Midi(OscMidiMessage {
                        port: midi_arg.port,
                        status: midi_arg.status,
                        data1: midi_arg.data1,
                        data2: midi_arg.data2,
                    })];
    let arg_cnt = args.len();

    let msg = OscMessage {
        addr: addr.to_string(),
        args: Some(args),
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    let dec_msg: OscMessage = match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(m) => m,
        _ => panic!("Expected OscMessage!"),
    };

    // check if osc address is equal
    assert_eq!(addr, dec_msg.addr);
    // check if there are arguments
    assert!(dec_msg.args.is_some());
    let dec_args = dec_msg.args.unwrap();

    // check if argument count is equal
    assert_eq!(arg_cnt, dec_args.len());

    for arg in dec_args {
        match arg {
            OscType::Int(x) => assert_eq!(int_arg, x),
            OscType::Long(x) => assert_eq!(long_arg, x),
            OscType::Float(x) => assert_eq!(float_arg, x),
            OscType::Double(x) => assert_eq!(double_arg, x),
            OscType::String(x) => assert_eq!(string_arg, x),
            OscType::Blob(x) => assert_eq!(blob_arg, x),
            OscType::Time(x, y) => assert_eq!(time_arg, (x, y)),
            OscType::Color(x) => {
                assert_eq!(color_arg.red, x.red);
                assert_eq!(color_arg.green, x.green);
                assert_eq!(color_arg.blue, x.blue);
                assert_eq!(color_arg.alpha, x.alpha);
            }
            OscType::Char(x) => assert_eq!(char_arg, x),
            OscType::Bool(_) => (),
            OscType::Inf => (),
            OscType::Nil => (),
            OscType::Midi(x) => {
                assert_eq!(midi_arg.port, x.port);
                assert_eq!(midi_arg.status, x.status);
                assert_eq!(midi_arg.data1, x.data1);
                assert_eq!(midi_arg.data2, x.data2);
            }
            _ => panic!("Unexpected OSC argument!"),
        }
    }
}
<|endoftext|>


<commit_before>mod null {
    use std::io::Cursor;

    use rustc_serialize::Decodable;

    use msgpack::Decoder;

    #[test]
    fn pass() {
        let buf = [0xc0];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!((), Decodable::decode(&mut decoder).ok().unwrap());
    }

    mod fail {
        use std::io::Cursor;
        use std::result;

        use rustc_serialize::Decodable;

        use msgpack::Decoder;
        use msgpack::core::decode::serialize::Error;

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

        #[test]
        fn from_reserved() {
            let buf = [0xc1];
            let cur = Cursor::new(&buf[..]);

            let mut decoder = Decoder::new(cur);

            let res: Result<()> = Decodable::decode(&mut decoder);
            assert_eq!(Error::TypeMismatch, res.err().unwrap());
        }
    } // mod fail
} // mod null

mod bool {
    use std::io::Cursor;

    use rustc_serialize::Decodable;

    use msgpack::Decoder;

    #[test]
    fn pass() {
        let buf = [0xc2, 0xc3];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(false, Decodable::decode(&mut decoder).ok().unwrap());
        assert_eq!(true,  Decodable::decode(&mut decoder).ok().unwrap());
    }

    mod fail {
        use std::io::Cursor;
        use std::result;

        use rustc_serialize::Decodable;

        use msgpack::Decoder;
        use msgpack::core::decode::serialize::Error;

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

        #[test]
        fn from_fixint() {
            let buf = [0x00];
            let cur = Cursor::new(&buf[..]);

            let mut decoder = Decoder::new(cur);

            let res: Result<bool> = Decodable::decode(&mut decoder);
            assert_eq!(Error::TypeMismatch, res.err().unwrap());
        }
    }
}

mod unspecified {
    use std::io::Cursor;
    use std::result;

    use rustc_serialize::Decodable;

    use msgpack::Decoder;
    use msgpack::core::decode::serialize::Error;

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

    #[test]
    fn pass_u64() {
        let buf = [0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(18446744073709551615u64, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_u32() {
        let buf = [0xce, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(4294967295u32, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn fail_u32_from_u64() {
        let buf = [0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        let res: Result<u32> = Decodable::decode(&mut decoder);
        assert_eq!(Error::TypeMismatch, res.err().unwrap());
    }

    #[test]
    fn pass_u16() {
        let buf = [0xcd, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(65535u16, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_u8() {
        let buf = [0xcc, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(255u8, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_usize() {
        let buf = [0xcc, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(255us, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i64() {
        let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(9223372036854775807i64, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i32() {
        let buf = [0xd2, 0x7f, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(2147483647i32, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i16() {
        let buf = [0xd1, 0x7f, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(32767i16, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i8() {
        let buf = [0xd0, 0x7f];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(127i8, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_isize() {
        let buf = [0xd0, 0x7f];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(127is, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_f32() {
        let buf = [0xca, 0x7f, 0x7f, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(3.4028234e38_f32, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_f64() {
        let buf = [0xcb, 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(42f64, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_string() {
        let buf = [0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: String = Decodable::decode(&mut decoder).unwrap();

        assert_eq!("le message".to_string(), actual);
    }

    #[test]
    fn pass_tuple() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: (u32, u32) = Decodable::decode(&mut decoder).unwrap();

        assert_eq!((42, 100500), actual);
    }

    #[test]
    fn fail_tuple_len_mismatch() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: Result<(u32,)> = Decodable::decode(&mut decoder);

        assert_eq!(Error::LengthMismatch(2), actual.err().unwrap());
    }

    #[test]
    fn pass_tuple_struct() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        #[derive(Debug, PartialEq, RustcDecodable)]
        struct Decoded(u32, u32);

        let mut decoder = Decoder::new(cur);
        let actual: Decoded = Decodable::decode(&mut decoder).unwrap();

        assert_eq!(Decoded(42, 100500), actual);
    }

    #[test]
    fn pass_struct() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        #[derive(Debug, PartialEq, RustcDecodable)]
        struct Decoded { id: u32, value: u32 };

        let mut decoder = Decoder::new(cur);
        let actual: Decoded = Decodable::decode(&mut decoder).unwrap();

        assert_eq!(Decoded { id: 42, value: 100500 }, actual);
    }
}
<commit_msg>[UT] Added option decoding tests (fails now).<commit_after>mod null {
    use std::io::Cursor;

    use rustc_serialize::Decodable;

    use msgpack::Decoder;

    #[test]
    fn pass() {
        let buf = [0xc0];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!((), Decodable::decode(&mut decoder).ok().unwrap());
    }

    mod fail {
        use std::io::Cursor;
        use std::result;

        use rustc_serialize::Decodable;

        use msgpack::Decoder;
        use msgpack::core::decode::serialize::Error;

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

        #[test]
        fn from_reserved() {
            let buf = [0xc1];
            let cur = Cursor::new(&buf[..]);

            let mut decoder = Decoder::new(cur);

            let res: Result<()> = Decodable::decode(&mut decoder);
            assert_eq!(Error::TypeMismatch, res.err().unwrap());
        }
    } // mod fail
} // mod null

mod bool {
    use std::io::Cursor;

    use rustc_serialize::Decodable;

    use msgpack::Decoder;

    #[test]
    fn pass() {
        let buf = [0xc2, 0xc3];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(false, Decodable::decode(&mut decoder).ok().unwrap());
        assert_eq!(true,  Decodable::decode(&mut decoder).ok().unwrap());
    }

    mod fail {
        use std::io::Cursor;
        use std::result;

        use rustc_serialize::Decodable;

        use msgpack::Decoder;
        use msgpack::core::decode::serialize::Error;

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

        #[test]
        fn from_fixint() {
            let buf = [0x00];
            let cur = Cursor::new(&buf[..]);

            let mut decoder = Decoder::new(cur);

            let res: Result<bool> = Decodable::decode(&mut decoder);
            assert_eq!(Error::TypeMismatch, res.err().unwrap());
        }
    }
}

mod unspecified {
    use std::io::Cursor;
    use std::result;

    use rustc_serialize::Decodable;

    use msgpack::Decoder;
    use msgpack::core::decode::serialize::Error;

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

    #[test]
    fn pass_u64() {
        let buf = [0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(18446744073709551615u64, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_u32() {
        let buf = [0xce, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(4294967295u32, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn fail_u32_from_u64() {
        let buf = [0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        let res: Result<u32> = Decodable::decode(&mut decoder);
        assert_eq!(Error::TypeMismatch, res.err().unwrap());
    }

    #[test]
    fn pass_u16() {
        let buf = [0xcd, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(65535u16, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_u8() {
        let buf = [0xcc, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(255u8, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_usize() {
        let buf = [0xcc, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(255us, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i64() {
        let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(9223372036854775807i64, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i32() {
        let buf = [0xd2, 0x7f, 0xff, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(2147483647i32, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i16() {
        let buf = [0xd1, 0x7f, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(32767i16, Decodable::decode(&mut decoder).ok().unwrap());
    }

    #[test]
    fn pass_i8() {
        let buf = [0xd0, 0x7f];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(127i8, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_isize() {
        let buf = [0xd0, 0x7f];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(127is, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_f32() {
        let buf = [0xca, 0x7f, 0x7f, 0xff, 0xff];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(3.4028234e38_f32, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_f64() {
        let buf = [0xcb, 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);

        assert_eq!(42f64, Decodable::decode(&mut decoder).unwrap());
    }

    #[test]
    fn pass_string() {
        let buf = [0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: String = Decodable::decode(&mut decoder).unwrap();

        assert_eq!("le message".to_string(), actual);
    }

    #[test]
    fn pass_tuple() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: (u32, u32) = Decodable::decode(&mut decoder).unwrap();

        assert_eq!((42, 100500), actual);
    }

    #[test]
    fn fail_tuple_len_mismatch() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: Result<(u32,)> = Decodable::decode(&mut decoder);

        assert_eq!(Error::LengthMismatch(2), actual.err().unwrap());
    }

    #[test]
    fn pass_tuple_struct() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        #[derive(Debug, PartialEq, RustcDecodable)]
        struct Decoded(u32, u32);

        let mut decoder = Decoder::new(cur);
        let actual: Decoded = Decodable::decode(&mut decoder).unwrap();

        assert_eq!(Decoded(42, 100500), actual);
    }

    #[test]
    fn pass_struct() {
        let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
        let cur = Cursor::new(&buf[..]);

        #[derive(Debug, PartialEq, RustcDecodable)]
        struct Decoded { id: u32, value: u32 };

        let mut decoder = Decoder::new(cur);
        let actual: Decoded = Decodable::decode(&mut decoder).unwrap();

        assert_eq!(Decoded { id: 42, value: 100500 }, actual);
    }

    #[test]
    fn pass_option_some() {
        let buf = [0x1f];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: Option<u8> = Decodable::decode(&mut decoder).unwrap();
        assert_eq!(Some(31), actual);
    }

    #[test]
    fn pass_option_none() {
        let buf = [0xc0];
        let cur = Cursor::new(&buf[..]);

        let mut decoder = Decoder::new(cur);
        let actual: Option<u8> = Decodable::decode(&mut decoder).unwrap();
        assert_eq!(None, actual);
    }
}
<|endoftext|>


<commit_before>use syntax::ast::expr::*;
use syntax::ast::constant::*;
use syntax::ast::op::*;
use syntax::ast::types::*;
use JSType = syntax::ast::types::Type;
use stdlib::value::{Value, VNull, ResultValue, to_value};
use stdlib::*;
use run::exec::Executor;
use std::gc::Gc;
use std::c_str::CString;
use jit::{Context, Function, Type, Types, Compilable};
use jit::{UByte, SysChar, SysBool, Int, UInt, Pointer, Float64};
use jit;

fn compile_type(js_type:&JSType) -> Type {
	match *js_type {
		UndefinedType | NullType | NativeObjectType | ObjectType | AnyType => jit_type!(*()),
		FunctionType => jit_type!(*() -> ()),
		StringType => jit_type!(String),
		BooleanType => jit_type!(bool),
		NumberType => jit_type!(f64),
		IntegerType => jit_type!(i32),
		AnyOfType(ref types) => {
			fail!("Unknown types: {}", types)
		}
	}
}
/// A Javascript JIT compiler
pub struct JITCompiler {
	/// The JIT Context
	context: Context,
	/// An object representing the global object
	pub global: Value
}
impl Executor<Function> for JITCompiler {
	fn new() -> JITCompiler {
		debug!("Initialising LibJIT...");
		jit::init();
		debug!("JIT supports threads? {}", jit::supports_threads());
		debug!("JIT supports virtual memory? {}", jit::supports_virtual_memory());
		debug!("JIT using interpreter? {}", jit::uses_interpreter());
		debug!("Initialising global object...");
		let global = Value::new_obj(None);
		object::init(global);
		console::init(global);
		math::init(global);
		array::init(global);
		function::init(global);
		json::init(global);
		number::init(global);
		error::init(global);
		string::init(global);
		uri::init(global);
		JITCompiler {
			context: Context::new(),
			global: global
		}
	}
	#[inline(always)]
	fn set_global(&mut self, name:String, val:Value) -> Value {
		self.global.set_field(name, val)
	}
	#[inline(always)]
	fn get_global(&self, name:String) -> Value {
		self.global.get_field(name)
	}
	fn compile(&self, expr: &Expr) -> Function {
		debug!("Compiling {} in builder", expr);
		self.context.build(|| {
			let value_t = jit_type!(*int);
			let default_sig_t = jit_type!(($value_t, $value_t, $value_t) -> $value_t);
			let func = Function::new(&self.context, &default_sig_t);
			let value = compile_value(&func, expr);
			func.insn_return(&convert_to_value(&func, &value));
			func.set_optimization_level(5);
			func.set_recompilable();
			func.compile();
			func
		})
	}
	fn run(&mut self, comp:&Function) -> ResultValue {
		debug!("Running function");
		debug!("There are {} functions in context", self.context.iter_funcs().size_hint());
		let func: fn(Value, Value, Value) -> Value = comp.closure();
		return Ok(func(self.global, self.global, self.global));
	}
}

fn convert_to_value(func:&Function, val:&jit::Value) -> jit::Value {
	let value_t = jit_type!(*int);
	let undef_value = Value::undefined;
	let val_type = val.get_type();
	let val_kind = val_type.get_kind();
	debug!("Converting JIT value of kind {} to Javascript value", val_kind.bits());
	if val_kind.contains(SysBool) || val_kind.contains(UByte) {
		let bool_value = to_value::<bool>;
		let sig = jit_type!((bool) -> $value_t);
		func.insn_call_native1("bool_value", bool_value, &sig, &mut [val])
	} else if val_kind.contains(Pointer) {
		let ref_t = val_type.get_ref();
		if ref_t.get_kind().contains(SysChar) {
			fn string_value(val: *i8) -> Value {
				unsafe {
					let text = CString::new(val, false);
					to_value(text.as_str().unwrap().into_string())
				}
			}
			let sig = jit_type!((String) -> $value_t);
			func.insn_call_native1("string_value", string_value, &sig, &mut [val])
		} else {
			fn ptr_value(ptr: *i8) -> Value {
				match ptr.to_uint() {
					0u => Value::undefined(),
					1u => Value {
						ptr: Gc::new(VNull)
					},
					ptr => fail!("Invalid pointer: {}", ptr)
				}
			}
			let sig = jit_type!(($val_type) -> $value_t);
			func.insn_call_native1("ptr_value", ptr_value, &sig, &mut [val])
		}
	} else if val_kind.contains(Int) || val_kind.contains(UInt) {
		let int_value = to_value::<i32>;
		let sig = jit_type!((i32) -> $value_t);
		func.insn_call_native1("int_value", int_value, &sig, &mut [val])
	} else if val_kind.contains(Float64) {
		let float_value = to_value::<f64>;
		let sig = jit_type!((f64) -> $value_t);
		func.insn_call_native1("float_value", float_value, &sig, &mut [val])
	} else {
		fail!("Invalid kind {}", val_kind.bits())
	}
}

fn compile_value(func:&Function, expr: &Expr) -> jit::Value {
	let value_t = jit_type!(*int);
	let cstring_t = jit_type!(*char);
	let create_value_sig = jit_type!(() -> $value_t);
	let undefined = || {
		let ptr = jit::Value::new(func, &Types::get_void_ptr());
		let val = 0u8.compile(func);
		func.insn_store(&ptr, &val);
		ptr
	};
	let global = func.get_param(0);
	let scope = func.get_param(1);
	let this = func.get_param(2);
	debug!("Compiling {} into a LibJIT value", expr);
	match expr.def {
		ConstExpr(CNull) => {
			let ptr = jit::Value::new(func, &jit_type!(*void));
			let val = 1u8.compile(func);
			func.insn_store(&ptr, &val);
			ptr
		},
		ConstExpr(CUndefined) => {
			undefined()
		},
		ConstExpr(CBool(v)) => {
			v.compile(func)
		},
		ConstExpr(CNum(n)) => {
			n.compile(func)
		},
		ConstExpr(CString(ref s)) => {
			s.compile(func)
		},
		BinOpExpr(BinNum(OpAdd), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_add(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpSub), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_sub(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpMul), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_mul(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpDiv), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_div(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpMod), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_rem(&i_a, &i_b)
		},
		BinOpExpr(BinBit(BitAnd), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_and(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitOr), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_or(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitXor), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_xor(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitShl), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_shl(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitShr), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_shr(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinComp(CompEqual), ref a, ref b) | BinOpExpr(BinComp(CompStrictEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_eq(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompNotEqual), ref a, ref b) | BinOpExpr(BinComp(CompStrictNotEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_neq(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompLessThan), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_lt(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompLessThanOrEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_leq(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompGreaterThan), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_gt(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompGreaterThanOrEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_geq(&i_a, &i_b), &jit_type!(bool), false)
		},
		UnaryOpExpr(UnaryMinus, ref a) => {
			func.insn_neg(&compile_value(func, *a))
		},
		UnaryOpExpr(UnaryNot, ref a) => {
			let mut val = compile_value(func, *a);
			val = func.insn_convert(&val, &jit_type!(bool), false);
			val = func.insn_neg(&val);
			func.insn_convert(&val, &jit_type!(bool), false)
		},
		UnaryOpExpr(UnaryPlus, ref a) => {
			compile_value(func, *a)
		},
		BlockExpr(ref exprs) => {
			let mut result = undefined();
			let last = exprs.last();
			for expr in exprs.iter() {
				let res = compile_value(func, expr);
				if expr == last.unwrap() {
					result = res;
				}
			}
			result
		},
		ReturnExpr(Some(ref ex)) => {
			let ret = compile_value(func, *ex);
			func.insn_return(&convert_to_value(func, &ret));
			ret
		}
		_ => fail!("Unimplemented {}", expr)
	}
}<commit_msg>Import all functions from LibJIT wrappers instead of using their whole name<commit_after>use syntax::ast::expr::*;
use syntax::ast::constant::*;
use syntax::ast::op::*;
use syntax::ast::types::*;
use JSType = syntax::ast::types::Type;
use stdlib::value::{Value, VNull, ResultValue, to_value};
use stdlib::*;
use run::exec::Executor;
use std::gc::Gc;
use std::c_str::CString;
use jit::{Context, Function, Type, Types, Compilable};
use jit::{UByte, SysChar, SysBool, Int, UInt, Pointer, Float64};
use jit::{init, supports_threads, supports_virtual_memory, uses_interpreter};
use JitValue = jit::Value;

fn compile_type(js_type:&JSType) -> Type {
	match *js_type {
		UndefinedType | NullType | NativeObjectType | ObjectType | AnyType => jit_type!(*()),
		FunctionType => jit_type!(*() -> ()),
		StringType => jit_type!(String),
		BooleanType => jit_type!(bool),
		NumberType => jit_type!(f64),
		IntegerType => jit_type!(i32),
		AnyOfType(ref types) => {
			fail!("Unknown types: {}", types)
		}
	}
}
/// A Javascript JIT compiler
pub struct JITCompiler {
	/// The JIT Context
	context: Context,
	/// An object representing the global object
	pub global: Value
}
impl Executor<Function> for JITCompiler {
	fn new() -> JITCompiler {
		debug!("Initialising LibJIT...");
		init();
		debug!("JIT supports threads? {}", supports_threads());
		debug!("JIT supports virtual memory? {}", supports_virtual_memory());
		debug!("JIT using interpreter? {}", uses_interpreter());
		debug!("Initialising global object...");
		let global = Value::new_obj(None);
		object::init(global);
		console::init(global);
		math::init(global);
		array::init(global);
		function::init(global);
		json::init(global);
		number::init(global);
		error::init(global);
		string::init(global);
		uri::init(global);
		JITCompiler {
			context: Context::new(),
			global: global
		}
	}
	#[inline(always)]
	fn set_global(&mut self, name:String, val:Value) -> Value {
		self.global.set_field(name, val)
	}
	#[inline(always)]
	fn get_global(&self, name:String) -> Value {
		self.global.get_field(name)
	}
	fn compile(&self, expr: &Expr) -> Function {
		debug!("Compiling {} in builder", expr);
		self.context.build(|| {
			let value_t = jit_type!(*int);
			let default_sig_t = jit_type!(($value_t, $value_t, $value_t) -> $value_t);
			let func = Function::new(&self.context, &default_sig_t);
			let value = compile_value(&func, expr);
			func.insn_return(&convert_to_value(&func, &value));
			func.set_optimization_level(5);
			func.set_recompilable();
			func.compile();
			func
		})
	}
	fn run(&mut self, comp:&Function) -> ResultValue {
		debug!("Running function");
		debug!("There are {} functions in context", self.context.iter_funcs().size_hint());
		let func: fn(Value, Value, Value) -> Value = comp.closure();
		return Ok(func(self.global, self.global, self.global));
	}
}

fn convert_to_value(func:&Function, val:&JitValue) -> JitValue {
	let value_t = jit_type!(*int);
	let undef_value = Value::undefined;
	let val_type = val.get_type();
	let val_kind = val_type.get_kind();
	debug!("Converting JIT value of kind {} to Javascript value", val_kind.bits());
	if val_kind.contains(SysBool) || val_kind.contains(UByte) {
		let bool_value = to_value::<bool>;
		let sig = jit_type!((bool) -> $value_t);
		func.insn_call_native1("bool_value", bool_value, &sig, &mut [val])
	} else if val_kind.contains(Pointer) {
		let ref_t = val_type.get_ref();
		if ref_t.get_kind().contains(SysChar) {
			fn string_value(val: *i8) -> Value {
				unsafe {
					let text = CString::new(val, false);
					to_value(text.as_str().unwrap().into_string())
				}
			}
			let sig = jit_type!((String) -> $value_t);
			func.insn_call_native1("string_value", string_value, &sig, &mut [val])
		} else {
			fn ptr_value(ptr: *i8) -> Value {
				match ptr.to_uint() {
					0u => Value::undefined(),
					1u => Value {
						ptr: Gc::new(VNull)
					},
					ptr => fail!("Invalid pointer: {}", ptr)
				}
			}
			let sig = jit_type!(($val_type) -> $value_t);
			func.insn_call_native1("ptr_value", ptr_value, &sig, &mut [val])
		}
	} else if val_kind.contains(Int) || val_kind.contains(UInt) {
		let int_value = to_value::<i32>;
		let sig = jit_type!((i32) -> $value_t);
		func.insn_call_native1("int_value", int_value, &sig, &mut [val])
	} else if val_kind.contains(Float64) {
		let float_value = to_value::<f64>;
		let sig = jit_type!((f64) -> $value_t);
		func.insn_call_native1("float_value", float_value, &sig, &mut [val])
	} else {
		fail!("Invalid kind {}", val_kind.bits())
	}
}

fn compile_value(func:&Function, expr: &Expr) -> JitValue {
	let value_t = jit_type!(*int);
	let cstring_t = jit_type!(*char);
	let create_value_sig = jit_type!(() -> $value_t);
	let undefined = || {
		let ptr = JitValue::new(func, &Types::get_void_ptr());
		let val = 0u8.compile(func);
		func.insn_store(&ptr, &val);
		ptr
	};
	let global = func.get_param(0);
	let scope = func.get_param(1);
	let this = func.get_param(2);
	debug!("Compiling {} into a LibJIT value", expr);
	match expr.def {
		ConstExpr(CNull) => {
			let ptr = JitValue::new(func, &jit_type!(*void));
			let val = 1u8.compile(func);
			func.insn_store(&ptr, &val);
			ptr
		},
		ConstExpr(CUndefined) => {
			undefined()
		},
		ConstExpr(CBool(v)) => {
			v.compile(func)
		},
		ConstExpr(CNum(n)) => {
			n.compile(func)
		},
		ConstExpr(CString(ref s)) => {
			s.compile(func)
		},
		BinOpExpr(BinNum(OpAdd), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_add(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpSub), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_sub(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpMul), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_mul(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpDiv), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_div(&i_a, &i_b)
		},
		BinOpExpr(BinNum(OpMod), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_rem(&i_a, &i_b)
		},
		BinOpExpr(BinBit(BitAnd), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_and(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitOr), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_or(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitXor), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_xor(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitShl), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_shl(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinBit(BitShr), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_shr(&i_a, &i_b), &jit_type!(i32), false)
		},
		BinOpExpr(BinComp(CompEqual), ref a, ref b) | BinOpExpr(BinComp(CompStrictEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_eq(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompNotEqual), ref a, ref b) | BinOpExpr(BinComp(CompStrictNotEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_neq(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompLessThan), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_lt(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompLessThanOrEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_leq(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompGreaterThan), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_gt(&i_a, &i_b), &jit_type!(bool), false)
		},
		BinOpExpr(BinComp(CompGreaterThanOrEqual), ref a, ref b) => {
			let i_a = compile_value(func, *a);
			let i_b = compile_value(func, *b);
			func.insn_convert(&func.insn_geq(&i_a, &i_b), &jit_type!(bool), false)
		},
		UnaryOpExpr(UnaryMinus, ref a) => {
			func.insn_neg(&compile_value(func, *a))
		},
		UnaryOpExpr(UnaryNot, ref a) => {
			let mut val = compile_value(func, *a);
			val = func.insn_convert(&val, &jit_type!(bool), false);
			val = func.insn_neg(&val);
			func.insn_convert(&val, &jit_type!(bool), false)
		},
		UnaryOpExpr(UnaryPlus, ref a) => {
			compile_value(func, *a)
		},
		BlockExpr(ref exprs) => {
			let mut result = undefined();
			let last = exprs.last();
			for expr in exprs.iter() {
				let res = compile_value(func, expr);
				if expr == last.unwrap() {
					result = res;
				}
			}
			result
		},
		ReturnExpr(Some(ref ex)) => {
			let ret = compile_value(func, *ex);
			func.insn_return(&convert_to_value(func, &ret));
			ret
		}
		_ => fail!("Unimplemented {}", expr)
	}
}<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::io::{IoError, EndOfFile};
use std::io::BufferedReader;
use std::ptr::null;
use std::io::fs::File;
use std::from_str::FromStr;
use libc::{c_ulong, c_int};

// sys/mount.h
static MS_RDONLY: c_ulong = 1;                /* Mount read-only.  */
static MS_NOSUID: c_ulong = 2;                /* Ignore suid and sgid bits.  */
static MS_NODEV: c_ulong = 4;                 /* Disallow access to device special files.  */
static MS_NOEXEC: c_ulong = 8;                /* Disallow program execution.  */
static MS_SYNCHRONOUS: c_ulong = 16;          /* Writes are synced at once.  */
static MS_REMOUNT: c_ulong = 32;              /* Alter flags of a mounted FS.  */
static MS_MANDLOCK: c_ulong = 64;             /* Allow mandatory locks on an FS.  */
static MS_DIRSYNC: c_ulong = 128;             /* Directory modifications are synchronous.  */
static MS_NOATIME: c_ulong = 1024;            /* Do not update access times.  */
static MS_NODIRATIME: c_ulong = 2048;         /* Do not update directory access times.  */
static MS_BIND: c_ulong = 4096;               /* Bind directory at different place.  */
static MS_MOVE: c_ulong = 8192;
static MS_REC: c_ulong = 16384;
static MS_SILENT: c_ulong = 32768;
static MS_POSIXACL: c_ulong = 1 << 16;        /* VFS does not apply the umask.  */
static MS_UNBINDABLE: c_ulong = 1 << 17;      /* Change to unbindable.  */
static MS_PRIVATE: c_ulong = 1 << 18;         /* Change to private.  */
static MS_SLAVE: c_ulong = 1 << 19;           /* Change to slave.  */
static MS_SHARED: c_ulong = 1 << 20;          /* Change to shared.  */
static MS_RELATIME: c_ulong = 1 << 21;        /* Update atime relative to mtime/ctime.  */
static MS_KERNMOUNT: c_ulong = 1 << 22;       /* This is a kern_mount call.  */
static MS_I_VERSION: c_ulong =  1 << 23;      /* Update inode I_version field.  */
static MS_STRICTATIME: c_ulong = 1 << 24;     /* Always perform atime updates.  */
static MS_ACTIVE: c_ulong = 1 << 30;
static MS_NOUSER: c_ulong = 1 << 31;

extern {
    fn mount(source: *const u8, target: *const u8,
        filesystemtype: *const u8, flags: c_ulong,
        data: *const u8) -> c_int;
    fn umount(target: *const u8) -> c_int;
}

pub struct MountRecord<'a> {
    pub mount_id: uint,
    pub parent_id: uint,
    _device: &'a str,  // TODO(tailhook) parse if ever need
    pub relative_root: &'a str,
    pub mount_point: &'a str,
    pub mount_options: &'a str,
    pub tag_shared: Option<uint>,
    pub tag_master: Option<uint>,
    pub tag_propagate_from: Option<uint>,
    pub tag_unbindable: Option<()>,
    pub fstype: &'a str,
    pub mount_source: &'a str,
    pub super_options: &'a str,
}

impl<'a> MountRecord<'a> {
    pub fn from_str<'x>(line: &'x str) -> Option<MountRecord<'x>> {
        let mut parts = line.words();
        let mount_id = try_opt!(parts.next().and_then(FromStr::from_str));
        let parent_id = try_opt!(parts.next().and_then(FromStr::from_str));
        let device = try_opt!(parts.next());
        let relative_root = try_opt!(parts.next());
        let mount_point = try_opt!(parts.next());
        let mount_options = try_opt!(parts.next());
        let mut tag_shared = None;
        let mut tag_master = None;
        let mut tag_propagate_from = None;
        let mut tag_unbindable = None;

        for name in parts {
            if name == "-" { break; }
            let mut pair = name.splitn(1, ':');
            let key = pair.next();
            let value = pair.next();
            match key {
                Some("shared") => {
                    tag_shared = Some(try_opt!(
                        value.and_then(FromStr::from_str)));
                }
                Some("master") => {
                    tag_master = Some(try_opt!(
                        value.and_then(FromStr::from_str)));
                }
                Some("propagate_from") => {
                    tag_propagate_from = Some(try_opt!(
                        value.and_then(FromStr::from_str)));
                }
                Some("unbindable") => tag_unbindable = Some(()),
                _ => {}
            }
        }

        let fstype = try_opt!(parts.next());
        let mount_source = try_opt!(parts.next());
        let super_options = try_opt!(parts.next());

        return Some(MountRecord {
            mount_id: mount_id,
            parent_id: parent_id,
            _device: device,
            relative_root: relative_root,
            mount_point: mount_point,
            mount_options: mount_options,
            tag_shared: tag_shared,
            tag_master: tag_master,
            tag_propagate_from: tag_propagate_from,
            tag_unbindable: tag_unbindable,
            fstype: fstype,
            mount_source: mount_source,
            super_options: super_options,
            });
    }
    pub fn is_private(&self) -> bool {
        return self.tag_shared.is_none()
            && self.tag_master.is_none()
            && self.tag_propagate_from.is_none()
            && self.tag_unbindable.is_none();
    }
}

pub fn check_mount_point(dir: &str, fun: |MountRecord|)
    -> Result<(), String>
{
    let f = try_str!(File::open(&Path::new("/proc/self/mountinfo")));
    let mut buf = BufferedReader::new(f);
    for line in buf.lines() {
        let line = try_str!(line);
        match MountRecord::from_str(line.as_slice()) {
            Some(rec) => {
                if rec.mount_point == dir {
                    fun(rec);
                }
            }
            None => {
                return Err(format!("Can't parse mountinfo line: {}", line));
            }
        }
    }
    return Ok(());
}

pub fn mount_ro_recursive(target: &Path) -> Result<(), String> {
    let none = "none".to_c_str();
    //  Must recursively remount readonly
    //  TODO(tailhook) fix double and overlapping bind mounts
    let file = try_str!(File::open(&Path::new("/proc/mounts")));
    let mut buf = BufferedReader::new(file);
    loop {
        let line = match buf.read_line() {
            Ok(line) => line,
            Err(ref e) if e.kind == EndOfFile => break,
            Err(e) => {
                return Err(format!("Error reading /proc/mounts: {}", e));
            }
        };
        let mut iter = line.as_slice().splitn(2, ' ');
        let cur_source = match iter.next() {
            Some(src) => src,
            None => {
                warn!("Wrong line in /proc/mounts: {}", line);
                continue;
            }
        };
        let cur_target = match iter.next() {
            Some(target) => Path::new(target),
            None => {
                warn!("Wrong line in /proc/mounts: {}", line);
                continue;
            }
        };
        if cur_source.as_slice() == "cgroup" {
            // Can't remount readonly cgroup filesystem
            continue;
        }
        if target.is_ancestor_of(&cur_target) {
            let c_target = cur_target.to_c_str();
            debug!("Remount readonly {} ({})",
                cur_target.display(), cur_source);
            let rc = unsafe { mount(
               none.as_bytes().as_ptr(),
               c_target.as_bytes().as_ptr(),
               null(), MS_BIND|MS_REMOUNT|MS_RDONLY, null()) };
            if rc != 0 {
                let err = IoError::last_error();
                return Err(format!("Remount readonly {}: {}",
                    cur_target.display(), err));
            }
            try_str!(mount_private(&cur_target));
        }
    }
    return Ok(());
}

pub fn mount_private(target: &Path) -> Result<(), String> {
    let none = "none".to_c_str();
    let c_target = target.to_c_str();
    debug!("Making private {}", target.display());
    let rc = unsafe { mount(
        none.as_bytes().as_ptr(),
        c_target.as_bytes().as_ptr(),
        null(), MS_PRIVATE, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't make {} a slave: {}",
            target.display(), err));
    }
}

pub fn bind_mount(source: &Path, target: &Path) -> Result<(), String> {
    let c_source = source.to_c_str();
    let c_target = target.to_c_str();
    debug!("Bind mount {} -> {}", source.display(), target.display());
    let rc = unsafe {
        mount(c_source.as_bytes().as_ptr(), c_target.as_bytes().as_ptr(),
        null(), MS_BIND|MS_REC, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't mount bind {} to {}: {}",
            source.display(), target.display(), err));
    }
}

pub fn mount_pseudo(target: &Path, name: &str, options: &str, readonly: bool)
    -> Result<(), String>
{
    let c_name = name.to_c_str();
    let c_target = target.to_c_str();
    let c_opts = options.to_c_str();
    let mut flags = MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_NOATIME;
    if readonly {
        flags |= MS_RDONLY;
    }
    debug!("Pseusofs mount {} {} {}", target.display(), name, options);
    let rc = unsafe { mount(
        c_name.as_bytes().as_ptr(),
        c_target.as_bytes().as_ptr(),
        c_name.as_bytes().as_ptr(),
        flags,
        c_opts.as_bytes().as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't mount pseudofs {} ({}, options: {}): {}",
            target.display(), options, name, err));
    }
}

pub fn mount_tmpfs(target: &Path, options: &str) -> Result<(), String> {
    let c_tmpfs = "tmpfs".to_c_str();
    let c_target = target.to_c_str();
    let c_opts = options.to_c_str();
    debug!("Tmpfs mount {} {}", target.display(), options);
    let rc = unsafe { mount(
        c_tmpfs.as_bytes().as_ptr(),
        c_target.as_bytes().as_ptr(),
        c_tmpfs.as_bytes().as_ptr(),
        MS_NOSUID | MS_NODEV | MS_NOATIME,
        c_opts.as_bytes().as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't mount tmpfs {} (options: {}): {}",
            target.display(), options, err));
    }
}

pub fn unmount(target: &Path) -> Result<(), String> {
    let c_target = target.to_c_str();
    let rc = unsafe { umount(c_target.as_bytes().as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't unmount {} : {}", target.display(), err));
    }
}

<commit_msg>Improvement of mount utils<commit_after>#![allow(dead_code)]
use std::io::{IoError, EndOfFile};
use std::io::BufferedReader;
use std::ptr::null;
use std::io::fs::File;
use std::from_str::FromStr;
use libc::{c_ulong, c_int};

// sys/mount.h
static MS_RDONLY: c_ulong = 1;                /* Mount read-only.  */
static MS_NOSUID: c_ulong = 2;                /* Ignore suid and sgid bits.  */
static MS_NODEV: c_ulong = 4;                 /* Disallow access to device special files.  */
static MS_NOEXEC: c_ulong = 8;                /* Disallow program execution.  */
static MS_SYNCHRONOUS: c_ulong = 16;          /* Writes are synced at once.  */
static MS_REMOUNT: c_ulong = 32;              /* Alter flags of a mounted FS.  */
static MS_MANDLOCK: c_ulong = 64;             /* Allow mandatory locks on an FS.  */
static MS_DIRSYNC: c_ulong = 128;             /* Directory modifications are synchronous.  */
static MS_NOATIME: c_ulong = 1024;            /* Do not update access times.  */
static MS_NODIRATIME: c_ulong = 2048;         /* Do not update directory access times.  */
static MS_BIND: c_ulong = 4096;               /* Bind directory at different place.  */
static MS_MOVE: c_ulong = 8192;
static MS_REC: c_ulong = 16384;
static MS_SILENT: c_ulong = 32768;
static MS_POSIXACL: c_ulong = 1 << 16;        /* VFS does not apply the umask.  */
static MS_UNBINDABLE: c_ulong = 1 << 17;      /* Change to unbindable.  */
static MS_PRIVATE: c_ulong = 1 << 18;         /* Change to private.  */
static MS_SLAVE: c_ulong = 1 << 19;           /* Change to slave.  */
static MS_SHARED: c_ulong = 1 << 20;          /* Change to shared.  */
static MS_RELATIME: c_ulong = 1 << 21;        /* Update atime relative to mtime/ctime.  */
static MS_KERNMOUNT: c_ulong = 1 << 22;       /* This is a kern_mount call.  */
static MS_I_VERSION: c_ulong =  1 << 23;      /* Update inode I_version field.  */
static MS_STRICTATIME: c_ulong = 1 << 24;     /* Always perform atime updates.  */
static MS_ACTIVE: c_ulong = 1 << 30;
static MS_NOUSER: c_ulong = 1 << 31;

static MNT_FORCE: c_int = 1;           /* Force unmounting.  */
static MNT_DETACH: c_int = 2;          /* Just detach from the tree.  */
static MNT_EXPIRE: c_int = 4;          /* Mark for expiry.  */
static UMOUNT_NOFOLLOW: c_int = 8;     /* Don't follow symlink on umount.  */

extern {
    fn mount(source: *const u8, target: *const u8,
        filesystemtype: *const u8, flags: c_ulong,
        data: *const u8) -> c_int;
    fn umount(target: *const u8) -> c_int;
    fn umount2(target: *const u8, flags: c_int) -> c_int;
}

pub struct MountRecord<'a> {
    pub mount_id: uint,
    pub parent_id: uint,
    _device: &'a str,  // TODO(tailhook) parse if ever need
    pub relative_root: &'a str,
    pub mount_point: &'a str,
    pub mount_options: &'a str,
    pub tag_shared: Option<uint>,
    pub tag_master: Option<uint>,
    pub tag_propagate_from: Option<uint>,
    pub tag_unbindable: Option<()>,
    pub fstype: &'a str,
    pub mount_source: &'a str,
    pub super_options: &'a str,
}

impl<'a> MountRecord<'a> {
    pub fn from_str<'x>(line: &'x str) -> Option<MountRecord<'x>> {
        let mut parts = line.words();
        let mount_id = try_opt!(parts.next().and_then(FromStr::from_str));
        let parent_id = try_opt!(parts.next().and_then(FromStr::from_str));
        let device = try_opt!(parts.next());
        let relative_root = try_opt!(parts.next());
        let mount_point = try_opt!(parts.next());
        let mount_options = try_opt!(parts.next());
        let mut tag_shared = None;
        let mut tag_master = None;
        let mut tag_propagate_from = None;
        let mut tag_unbindable = None;

        for name in parts {
            if name == "-" { break; }
            let mut pair = name.splitn(1, ':');
            let key = pair.next();
            let value = pair.next();
            match key {
                Some("shared") => {
                    tag_shared = Some(try_opt!(
                        value.and_then(FromStr::from_str)));
                }
                Some("master") => {
                    tag_master = Some(try_opt!(
                        value.and_then(FromStr::from_str)));
                }
                Some("propagate_from") => {
                    tag_propagate_from = Some(try_opt!(
                        value.and_then(FromStr::from_str)));
                }
                Some("unbindable") => tag_unbindable = Some(()),
                _ => {}
            }
        }

        let fstype = try_opt!(parts.next());
        let mount_source = try_opt!(parts.next());
        let super_options = try_opt!(parts.next());

        return Some(MountRecord {
            mount_id: mount_id,
            parent_id: parent_id,
            _device: device,
            relative_root: relative_root,
            mount_point: mount_point,
            mount_options: mount_options,
            tag_shared: tag_shared,
            tag_master: tag_master,
            tag_propagate_from: tag_propagate_from,
            tag_unbindable: tag_unbindable,
            fstype: fstype,
            mount_source: mount_source,
            super_options: super_options,
            });
    }
    pub fn is_private(&self) -> bool {
        return self.tag_shared.is_none()
            && self.tag_master.is_none()
            && self.tag_propagate_from.is_none()
            && self.tag_unbindable.is_none();
    }
}

pub fn check_mount_point(dir: &str, fun: |MountRecord|)
    -> Result<(), String>
{
    let f = try_str!(File::open(&Path::new("/proc/self/mountinfo")));
    let mut buf = BufferedReader::new(f);
    for line in buf.lines() {
        let line = try_str!(line);
        match MountRecord::from_str(line.as_slice()) {
            Some(rec) => {
                if rec.mount_point == dir {
                    fun(rec);
                }
            }
            None => {
                return Err(format!("Can't parse mountinfo line: {}", line));
            }
        }
    }
    return Ok(());
}

pub fn get_submounts_of(dir: &Path)
    -> Result<Vec<Path>, String>
{
    let f = try_str!(File::open(&Path::new("/proc/self/mountinfo")));
    let mut buf = BufferedReader::new(f);
    let mut result = vec!();
    for line in buf.lines() {
        let line = try_str!(line);
        match MountRecord::from_str(line.as_slice()) {
            Some(rec) => {
                let mut path = Path::new(rec.mount_point);
                if dir.is_ancestor_of(&path) {
                    result.push(path);
                }
            }
            None => {
                return Err(format!("Can't parse mountinfo line: {}", line));
            }
        }
    }
    return Ok(result);
}

pub fn mount_ro_recursive(target: &Path) -> Result<(), String> {
    let none = "none".to_c_str();
    //  Must recursively remount readonly
    //  TODO(tailhook) fix double and overlapping bind mounts
    let file = try_str!(File::open(&Path::new("/proc/mounts")));
    let mut buf = BufferedReader::new(file);
    loop {
        let line = match buf.read_line() {
            Ok(line) => line,
            Err(ref e) if e.kind == EndOfFile => break,
            Err(e) => {
                return Err(format!("Error reading /proc/mounts: {}", e));
            }
        };
        let mut iter = line.as_slice().splitn(2, ' ');
        let cur_source = match iter.next() {
            Some(src) => src,
            None => {
                warn!("Wrong line in /proc/mounts: {}", line);
                continue;
            }
        };
        let cur_target = match iter.next() {
            Some(target) => Path::new(target),
            None => {
                warn!("Wrong line in /proc/mounts: {}", line);
                continue;
            }
        };
        if cur_source.as_slice() == "cgroup" {
            // Can't remount readonly cgroup filesystem
            continue;
        }
        if target.is_ancestor_of(&cur_target) {
            let c_target = cur_target.to_c_str();
            debug!("Remount readonly {} ({})",
                cur_target.display(), cur_source);
            let rc = unsafe { mount(
               none.as_bytes().as_ptr(),
               c_target.as_bytes().as_ptr(),
               null(), MS_BIND|MS_REMOUNT|MS_RDONLY, null()) };
            if rc != 0 {
                let err = IoError::last_error();
                return Err(format!("Remount readonly {}: {}",
                    cur_target.display(), err));
            }
            try_str!(mount_private(&cur_target));
        }
    }
    return Ok(());
}

pub fn mount_private(target: &Path) -> Result<(), String> {
    let none = "none".to_c_str();
    let c_target = target.to_c_str();
    debug!("Making private {}", target.display());
    let rc = unsafe { mount(
        none.as_bytes().as_ptr(),
        c_target.as_bytes().as_ptr(),
        null(), MS_PRIVATE, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't make {} a slave: {}",
            target.display(), err));
    }
}

pub fn bind_mount(source: &Path, target: &Path) -> Result<(), String> {
    let c_source = source.to_c_str();
    let c_target = target.to_c_str();
    debug!("Bind mount {} -> {}", source.display(), target.display());
    let rc = unsafe {
        mount(c_source.as_bytes().as_ptr(), c_target.as_bytes().as_ptr(),
        null(), MS_BIND|MS_REC, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't mount bind {} to {}: {}",
            source.display(), target.display(), err));
    }
}

pub fn mount_pseudo(target: &Path, name: &str, options: &str, readonly: bool)
    -> Result<(), String>
{
    let c_name = name.to_c_str();
    let c_target = target.to_c_str();
    let c_opts = options.to_c_str();
    let mut flags = MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_NOATIME;
    if readonly {
        flags |= MS_RDONLY;
    }
    debug!("Pseusofs mount {} {} {}", target.display(), name, options);
    let rc = unsafe { mount(
        c_name.as_bytes().as_ptr(),
        c_target.as_bytes().as_ptr(),
        c_name.as_bytes().as_ptr(),
        flags,
        c_opts.as_bytes().as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't mount pseudofs {} ({}, options: {}): {}",
            target.display(), options, name, err));
    }
}

pub fn mount_tmpfs(target: &Path, options: &str) -> Result<(), String> {
    let c_tmpfs = "tmpfs".to_c_str();
    let c_target = target.to_c_str();
    let c_opts = options.to_c_str();
    debug!("Tmpfs mount {} {}", target.display(), options);
    let rc = unsafe { mount(
        c_tmpfs.as_bytes().as_ptr(),
        c_target.as_bytes().as_ptr(),
        c_tmpfs.as_bytes().as_ptr(),
        MS_NOSUID | MS_NODEV | MS_NOATIME,
        c_opts.as_bytes().as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't mount tmpfs {} (options: {}): {}",
            target.display(), options, err));
    }
}

pub fn unmount(target: &Path) -> Result<(), String> {
    let c_target = target.to_c_str();
    let rc = unsafe { umount2(c_target.as_bytes().as_ptr(), MNT_DETACH) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_error();
        return Err(format!("Can't unmount {} : {}", target.display(), err));
    }
}

<|endoftext|>


<commit_before>//! Contains methods for initializing the lua config

use std::fs::{OpenOptions, File};
use std::env;
use std::path::Path;

use std::io::Result as IOResult;

pub const INIT_FILE: &'static str = "init.lua";
pub const INIT_FILE_FALLBACK_PATH: &'static str = "/etc/way-cooler/";

#[inline]
fn read_file<P: AsRef<Path>>(path: P) -> IOResult<File> {
    OpenOptions::new().read(true).open(path)
}

#[cfg(test)]
pub fn get_config() -> (bool, Result<File, &'static str>) {
    (false, "Loading config should be ignored during tests for now")
}

#[cfg(not(test))]
pub fn get_config() -> (bool, Result<File, &'static str>) {
    (true, get_config_file())
}

/// Parses environment variables
fn get_config_file() -> Result<File, &'static str> {
    if let Ok(path_env) = env::var("WAY_COOLER_CONFIG") {
        if let Ok(file) = read_file(Path::new(&path_env).join(INIT_FILE)) {
            info!("Reading init file from $WAY_COOLER_INIT_FILE: {}", path_env);
            return Ok(file)
        }
        warn!("Error reading from $WAY_COOLER_INIT_FILE, defaulting...");
    }

    if let Ok(xdg) = env::var("XDG_CONFIG_HOME") {
        if let Ok(file) = read_file(Path::new(&xdg).join(INIT_FILE)) {
            info!("Reading init file from $XDG_CONFIG_HOME: {}", xdg);
            return Ok(file)
        }
        warn!("Error reading from $XDG_CONFIG_HOME, defaulting...");
    }
    let dot_config = Path::new(&env::var("HOME")
                               .expect("HOME environment variable not defined!"))
        .join(".config").join("way-cooler").join(INIT_FILE);
    trace!("Looking at {:?}", dot_config);
    if let Ok(file) = read_file(&dot_config) {
        info!("Reading init file from {:?}", &dot_config);
        return Ok(file)
    }

    let etc_config = Path::new(INIT_FILE_FALLBACK_PATH).join(INIT_FILE);

    if let Ok(file) = read_file(&etc_config) {
        info!("Reading init file from fallback {:?}", &etc_config);
        return Ok(file)
    }

    return Err("Could not find an init file in any path!")
}
<commit_msg>Fixed test version of init path<commit_after>//! Contains methods for initializing the lua config

use std::fs::{OpenOptions, File};
use std::env;
use std::path::Path;

use std::io::Result as IOResult;

pub const INIT_FILE: &'static str = "init.lua";
pub const INIT_FILE_FALLBACK_PATH: &'static str = "/etc/way-cooler/";

#[inline]
fn read_file<P: AsRef<Path>>(path: P) -> IOResult<File> {
    OpenOptions::new().read(true).open(path)
}

#[cfg(test)]
pub fn get_config() -> (bool, Result<File, &'static str>) {
    (false, Err("Loading config should be ignored during tests for now"))
}

#[cfg(not(test))]
pub fn get_config() -> (bool, Result<File, &'static str>) {
    (true, get_config_file())
}

/// Parses environment variables
fn get_config_file() -> Result<File, &'static str> {
    if let Ok(path_env) = env::var("WAY_COOLER_CONFIG") {
        if let Ok(file) = read_file(Path::new(&path_env).join(INIT_FILE)) {
            info!("Reading init file from $WAY_COOLER_INIT_FILE: {}", path_env);
            return Ok(file)
        }
        warn!("Error reading from $WAY_COOLER_INIT_FILE, defaulting...");
    }

    if let Ok(xdg) = env::var("XDG_CONFIG_HOME") {
        if let Ok(file) = read_file(Path::new(&xdg).join(INIT_FILE)) {
            info!("Reading init file from $XDG_CONFIG_HOME: {}", xdg);
            return Ok(file)
        }
        warn!("Error reading from $XDG_CONFIG_HOME, defaulting...");
    }
    let dot_config = Path::new(&env::var("HOME")
                               .expect("HOME environment variable not defined!"))
        .join(".config").join("way-cooler").join(INIT_FILE);
    trace!("Looking at {:?}", dot_config);
    if let Ok(file) = read_file(&dot_config) {
        info!("Reading init file from {:?}", &dot_config);
        return Ok(file)
    }

    let etc_config = Path::new(INIT_FILE_FALLBACK_PATH).join(INIT_FILE);

    if let Ok(file) = read_file(&etc_config) {
        info!("Reading init file from fallback {:?}", &etc_config);
        return Ok(file)
    }

    return Err("Could not find an init file in any path!")
}
<|endoftext|>


<commit_before>use cocoa::appkit::{NSPasteboard, NSPasteboardTypeString};
use cocoa::base::{id, nil};
use cocoa::foundation::{NSArray, NSData, NSString, NSUInteger};
use std::ffi::CStr;
use {Clipboard, Item, Result};

pub trait ClipboardExt: Clipboard {
    fn clipboard_with_name(&self, name: &str) -> Self;

    fn get_clipboard_text_as_nsstring(&self) -> id;
    fn get_raw_clipboard(&self) -> id;
}

#[derive(Debug)]
pub struct CocoaClipboard(id);

impl Clipboard for CocoaClipboard {
    fn get() -> Result<Self> where Self: Sized {
        let pboard = unsafe { NSPasteboard::generalPasteboard(nil) };
        if pboard.is_null() {
            Err(From::from("could not get pasteboard"))
        } else {
            Ok(CocoaClipboard(pboard))
        }
    }

    fn copy(&mut self, item: Item) -> Result<()> {
        unsafe {
            let item = match item {
                Item::Text(ref text) => NSString::alloc(nil).init_str(text),
                Item::Image(ref image) => {
                    let slice = image.bytes();
                    let _data = NSData::dataWithBytes_length_(nil,
                                                              slice.as_ptr() as *const _,
                                                              slice.len() as NSUInteger);
                    unimplemented!();
                }
                _ => return Ok(())
            };

            self.0.clearContents();
            self.0.declareTypes_owner(NSArray::arrayWithObject(nil, NSPasteboardTypeString), nil);
            NSPasteboard::setString_forType(self.0, item, NSPasteboardTypeString);
            Ok(())
        }
    }

    fn copy_items(&mut self, items: Vec<Item>) -> Result<()> {
        unimplemented!();
    }

    fn get_paste_text(&self)  -> Result<&str> {
        unsafe {
            let text = NSPasteboard::stringForType(self.0, NSPasteboardTypeString);
            Ok(CStr::from_ptr(text.UTF8String()).to_str().unwrap_or(""))
        }
    }
}

impl ClipboardExt for CocoaClipboard {
    fn clipboard_with_name(&self, name: &str) -> Self {
        unimplemented!();
    }

    fn get_clipboard_text_as_nsstring(&self) -> id {
        unimplemented!();
    }

    fn get_raw_clipboard(&self) -> id {
        unimplemented!();
    }
}
<commit_msg>Implement CocoaClipboard::copy_items<commit_after>use cocoa::appkit::{NSPasteboard, NSPasteboardTypeString};
use cocoa::base::{id, nil};
use cocoa::foundation::{NSArray, NSData, NSString, NSUInteger};
use std::borrow::Cow;
use std::ffi::CStr;
use {Clipboard, Item, Result};

pub trait ClipboardExt: Clipboard {
    fn clipboard_with_name(&self, name: &str) -> Self;

    fn get_clipboard_text_as_nsstring(&self) -> id;
    fn get_raw_clipboard(&self) -> id;
}

#[derive(Debug)]
pub struct CocoaClipboard(id);

impl Clipboard for CocoaClipboard {
    fn get() -> Result<Self> where Self: Sized {
        let pboard = unsafe { NSPasteboard::generalPasteboard(nil) };
        if pboard.is_null() {
            Err(From::from("could not get pasteboard"))
        } else {
            Ok(CocoaClipboard(pboard))
        }
    }

    fn copy(&mut self, item: Item) -> Result<()> {
        unsafe {
            let item = item.native_representation();
            if item.is_null() {
                return Ok(())
            }

            self.0.clearContents();
            self.0.declareTypes_owner(NSArray::arrayWithObject(nil, NSPasteboardTypeString), nil);
            NSPasteboard::setString_forType(self.0, item, NSPasteboardTypeString);
            Ok(())
        }
    }

    fn copy_items(&mut self, items: Vec<Item>) -> Result<()> {
        let items = items.iter().map(|i| i.native_representation()).collect::<Cow<[_]>>();
        let array = unsafe { NSArray::arrayWithObjects(nil, &items) };
        unsafe {
            self.0.clearContents();
            self.0.writeObjects(array);
        }
        Ok(())
    }

    fn get_paste_text(&self)  -> Result<&str> {
        unsafe {
            let text = NSPasteboard::stringForType(self.0, NSPasteboardTypeString);
            Ok(CStr::from_ptr(text.UTF8String()).to_str().unwrap_or(""))
        }
    }
}

impl ClipboardExt for CocoaClipboard {
    fn clipboard_with_name(&self, name: &str) -> Self {
        unimplemented!();
    }

    fn get_clipboard_text_as_nsstring(&self) -> id {
        unimplemented!();
    }

    fn get_raw_clipboard(&self) -> id {
        unimplemented!();
    }
}

impl<'a> Item<'a> {
    fn native_representation(&self) -> id {
        match *self {
            Item::Text(text) => unsafe { NSString::alloc(nil).init_str(text) },
            Item::Image(image) => unsafe {
                let slice = image.bytes();
                let _data = NSData::dataWithBytes_length_(nil,
                                                          slice.as_ptr() as *const _,
                                                          slice.len() as NSUInteger);
                unimplemented!();
            },
            Item::Sound(sound) => {
                unimplemented!();
            }
            _ => nil
        }
    }
}
<|endoftext|>


<commit_before>// xfail-test FIXME #5985 Doesn't typecheck on x86

use core::cast::transmute;
use core::from_str::FromStr;
use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite};
use core::uint::{min, range};
use core::vec::bytes::copy_memory;

static LINE_LEN: uint = 60;
static LOOKUP_SIZE: uint = 4 * 1024;
static LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32;

// Random number generator constants
static IM: u32 = 139968;
static IA: u32 = 3877;
static IC: u32 = 29573;

static ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\
                            GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\
                            GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\
                            AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\
                            CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\
                            CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\
                            CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";

static NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 };

static MESSAGE_1: &'static str = ">ONE Homo sapiens alu\n";
static MESSAGE_2: &'static str = ">TWO IUB ambiguity codes\n";
static MESSAGE_3: &'static str = ">THREE Homo sapiens frequency\n";

static IUB: [AminoAcid, ..15] = [
    AminoAcid { c: 'a' as u8, p: 0.27 },
    AminoAcid { c: 'c' as u8, p: 0.12 },
    AminoAcid { c: 'g' as u8, p: 0.12 },
    AminoAcid { c: 't' as u8, p: 0.27 },
    AminoAcid { c: 'B' as u8, p: 0.02 },
    AminoAcid { c: 'D' as u8, p: 0.02 },
    AminoAcid { c: 'H' as u8, p: 0.02 },
    AminoAcid { c: 'K' as u8, p: 0.02 },
    AminoAcid { c: 'M' as u8, p: 0.02 },
    AminoAcid { c: 'N' as u8, p: 0.02 },
    AminoAcid { c: 'R' as u8, p: 0.02 },
    AminoAcid { c: 'S' as u8, p: 0.02 },
    AminoAcid { c: 'V' as u8, p: 0.02 },
    AminoAcid { c: 'W' as u8, p: 0.02 },
    AminoAcid { c: 'Y' as u8, p: 0.02 },
];

static HOMO_SAPIENS: [AminoAcid, ..4] = [
    AminoAcid { c: 'a' as u8, p: 0.3029549426680 },
    AminoAcid { c: 'c' as u8, p: 0.1979883004921 },
    AminoAcid { c: 'g' as u8, p: 0.1975473066391 },
    AminoAcid { c: 't' as u8, p: 0.3015094502008 },
];

// XXX: Use map().
fn sum_and_scale(a: &'static [AminoAcid]) -> ~[AminoAcid] {
    let mut result = ~[];
    let mut p = 0f32;
    for a.each |a_i| {
        let mut a_i = *a_i;
        p += a_i.p;
        a_i.p = p * LOOKUP_SCALE;
        result.push(a_i);
    }
    result[result.len() - 1].p = LOOKUP_SCALE;
    result
}

struct AminoAcid {
    c: u8,
    p: f32,
}

struct RepeatFasta {
    alu: &'static str,
    stdout: *FILE,
}

impl RepeatFasta {
    fn new(stdout: *FILE, alu: &'static str) -> RepeatFasta {
        RepeatFasta {
            alu: alu,
            stdout: stdout,
        }
    }

    fn make(&mut self, n: uint) {
        unsafe {
            let stdout = self.stdout;
            let alu_len = self.alu.len();
            let mut buf = vec::from_elem(alu_len + LINE_LEN, 0u8);
            let alu: &[u8] = str::byte_slice_no_callback(self.alu);

            copy_memory(buf, alu, alu_len);
            copy_memory(vec::mut_slice(buf, alu_len, buf.len()),
                        alu,
                        LINE_LEN);

            let mut pos = 0, bytes, n = n;
            while n > 0 {
                bytes = min(LINE_LEN, n);
                fwrite(transmute(&buf[pos]), bytes as u64, 1, stdout);
                fputc('\n' as c_int, stdout);
                pos += bytes;
                if pos > alu_len {
                    pos -= alu_len;
                }
                n -= bytes;
            }
        }
    }
}

struct RandomFasta {
    seed: u32,
    stdout: *FILE,
    lookup: [AminoAcid, ..LOOKUP_SIZE],
}

impl RandomFasta {
    fn new(stdout: *FILE, a: &[AminoAcid]) -> RandomFasta {
        RandomFasta {
            seed: 42,
            stdout: stdout,
            lookup: RandomFasta::make_lookup(a),
        }
    }

    fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] {
        let mut lookup = [ NULL_AMINO_ACID, ..LOOKUP_SIZE ];
        let mut j = 0;
        for vec::eachi_mut(lookup) |i, slot| {
            while a[j].p < (i as f32) {
                j += 1;
            }
            *slot = a[j];
        }
        lookup
    }

    fn rng(&mut self, max: f32) -> f32 {
        self.seed = (self.seed * IA + IC) % IM;
        max * (self.seed as f32) / (IM as f32)
    }

    fn nextc(&mut self) -> u8 {
        let r = self.rng(1.0);
        for self.lookup.each |a| {
            if a.p >= r {
                return a.c;
            }
        }
        0
    }

    fn make(&mut self, n: uint) {
        unsafe {
            let lines = n / LINE_LEN, chars_left = n % LINE_LEN;
            let mut buf = [0, ..LINE_LEN + 1];

            for lines.times {
                for range(0, LINE_LEN) |i| {
                    buf[i] = self.nextc();
                }
                buf[LINE_LEN] = '\n' as u8;
                fwrite(transmute(&buf[0]),
                       LINE_LEN as u64 + 1,
                       1,
                       self.stdout);
            }
            for range(0, chars_left) |i| {
                buf[i] = self.nextc();
            }
            fwrite(transmute(&buf[0]), chars_left as u64, 1, self.stdout);
        }
    }
}

#[fixed_stack_segment]
fn main() {
    let n: uint = FromStr::from_str(os::args()[1]).get();

    unsafe {
        let mode = "w";
        let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));

        fputs(transmute(&MESSAGE_1[0]), stdout);
        let mut repeat = RepeatFasta::new(stdout, ALU);
        repeat.make(n * 2);

        fputs(transmute(&MESSAGE_2[0]), stdout);
        let iub = sum_and_scale(IUB);
        let mut random = RandomFasta::new(stdout, iub);
        random.make(n * 3);

        fputs(transmute(&MESSAGE_3[0]), stdout);
        let homo_sapiens = sum_and_scale(HOMO_SAPIENS);
        random.lookup = RandomFasta::make_lookup(homo_sapiens);
        random.make(n * 5);

        fputc('\n' as c_int, stdout);
    }
}

<commit_msg>auto merge of #5989 : Thiez/rust/fixbench, r=catamorphism<commit_after>use core::cast::transmute;
use core::from_str::FromStr;
use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite, size_t};
use core::uint::{min, range};
use core::vec::bytes::copy_memory;

static LINE_LEN: uint = 60;
static LOOKUP_SIZE: uint = 4 * 1024;
static LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32;

// Random number generator constants
static IM: u32 = 139968;
static IA: u32 = 3877;
static IC: u32 = 29573;

static ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\
                            GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\
                            GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\
                            AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\
                            CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\
                            CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\
                            CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";

static NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 };

static MESSAGE_1: &'static str = ">ONE Homo sapiens alu\n";
static MESSAGE_2: &'static str = ">TWO IUB ambiguity codes\n";
static MESSAGE_3: &'static str = ">THREE Homo sapiens frequency\n";

static IUB: [AminoAcid, ..15] = [
    AminoAcid { c: 'a' as u8, p: 0.27 },
    AminoAcid { c: 'c' as u8, p: 0.12 },
    AminoAcid { c: 'g' as u8, p: 0.12 },
    AminoAcid { c: 't' as u8, p: 0.27 },
    AminoAcid { c: 'B' as u8, p: 0.02 },
    AminoAcid { c: 'D' as u8, p: 0.02 },
    AminoAcid { c: 'H' as u8, p: 0.02 },
    AminoAcid { c: 'K' as u8, p: 0.02 },
    AminoAcid { c: 'M' as u8, p: 0.02 },
    AminoAcid { c: 'N' as u8, p: 0.02 },
    AminoAcid { c: 'R' as u8, p: 0.02 },
    AminoAcid { c: 'S' as u8, p: 0.02 },
    AminoAcid { c: 'V' as u8, p: 0.02 },
    AminoAcid { c: 'W' as u8, p: 0.02 },
    AminoAcid { c: 'Y' as u8, p: 0.02 },
];

static HOMO_SAPIENS: [AminoAcid, ..4] = [
    AminoAcid { c: 'a' as u8, p: 0.3029549426680 },
    AminoAcid { c: 'c' as u8, p: 0.1979883004921 },
    AminoAcid { c: 'g' as u8, p: 0.1975473066391 },
    AminoAcid { c: 't' as u8, p: 0.3015094502008 },
];

// XXX: Use map().
fn sum_and_scale(a: &'static [AminoAcid]) -> ~[AminoAcid] {
    let mut result = ~[];
    let mut p = 0f32;
    for a.each |a_i| {
        let mut a_i = *a_i;
        p += a_i.p;
        a_i.p = p * LOOKUP_SCALE;
        result.push(a_i);
    }
    result[result.len() - 1].p = LOOKUP_SCALE;
    result
}

struct AminoAcid {
    c: u8,
    p: f32,
}

struct RepeatFasta {
    alu: &'static str,
    stdout: *FILE,
}

impl RepeatFasta {
    fn new(stdout: *FILE, alu: &'static str) -> RepeatFasta {
        RepeatFasta {
            alu: alu,
            stdout: stdout,
        }
    }

    fn make(&mut self, n: uint) {
        unsafe {
            let stdout = self.stdout;
            let alu_len = self.alu.len();
            let mut buf = vec::from_elem(alu_len + LINE_LEN, 0u8);
            let alu: &[u8] = str::byte_slice_no_callback(self.alu);

            copy_memory(buf, alu, alu_len);
            copy_memory(vec::mut_slice(buf, alu_len, buf.len()),
                        alu,
                        LINE_LEN);

            let mut pos = 0, bytes, n = n;
            while n > 0 {
                bytes = min(LINE_LEN, n);
                fwrite(transmute(&buf[pos]), bytes as size_t, 1, stdout);
                fputc('\n' as c_int, stdout);
                pos += bytes;
                if pos > alu_len {
                    pos -= alu_len;
                }
                n -= bytes;
            }
        }
    }
}

struct RandomFasta {
    seed: u32,
    stdout: *FILE,
    lookup: [AminoAcid, ..LOOKUP_SIZE],
}

impl RandomFasta {
    fn new(stdout: *FILE, a: &[AminoAcid]) -> RandomFasta {
        RandomFasta {
            seed: 42,
            stdout: stdout,
            lookup: RandomFasta::make_lookup(a),
        }
    }

    fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] {
        let mut lookup = [ NULL_AMINO_ACID, ..LOOKUP_SIZE ];
        let mut j = 0;
        for vec::eachi_mut(lookup) |i, slot| {
            while a[j].p < (i as f32) {
                j += 1;
            }
            *slot = a[j];
        }
        lookup
    }

    fn rng(&mut self, max: f32) -> f32 {
        self.seed = (self.seed * IA + IC) % IM;
        max * (self.seed as f32) / (IM as f32)
    }

    fn nextc(&mut self) -> u8 {
        let r = self.rng(1.0);
        for self.lookup.each |a| {
            if a.p >= r {
                return a.c;
            }
        }
        0
    }

    fn make(&mut self, n: uint) {
        unsafe {
            let lines = n / LINE_LEN, chars_left = n % LINE_LEN;
            let mut buf = [0, ..LINE_LEN + 1];

            for lines.times {
                for range(0, LINE_LEN) |i| {
                    buf[i] = self.nextc();
                }
                buf[LINE_LEN] = '\n' as u8;
                fwrite(transmute(&buf[0]),
                       LINE_LEN as size_t + 1,
                       1,
                       self.stdout);
            }
            for range(0, chars_left) |i| {
                buf[i] = self.nextc();
            }
            fwrite(transmute(&buf[0]), chars_left as size_t, 1, self.stdout);
        }
    }
}

#[fixed_stack_segment]
fn main() {
    let n: uint = FromStr::from_str(os::args()[1]).get();

    unsafe {
        let mode = "w";
        let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));

        fputs(transmute(&MESSAGE_1[0]), stdout);
        let mut repeat = RepeatFasta::new(stdout, ALU);
        repeat.make(n * 2);

        fputs(transmute(&MESSAGE_2[0]), stdout);
        let iub = sum_and_scale(IUB);
        let mut random = RandomFasta::new(stdout, iub);
        random.make(n * 3);

        fputs(transmute(&MESSAGE_3[0]), stdout);
        let homo_sapiens = sum_and_scale(HOMO_SAPIENS);
        random.lookup = RandomFasta::make_lookup(homo_sapiens);
        random.make(n * 5);

        fputc('\n' as c_int, stdout);
    }
}

<|endoftext|>