<commit_before>#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(not(expandtest), ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn expandtest() {
    macrotest::expand("tests/expand/*.rs");
}
<commit_msg>Suppress unused_attributes warning in test suite<commit_after>#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(not(expandtest), ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[allow(unused_attributes)]
#[test]
fn expandtest() {
    macrotest::expand("tests/expand/*.rs");
}
<|endoftext|>


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

#[test]
fn test_current_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg(".").run().stdout;
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_current_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Create a 256-character path to current directory
    let dir = path_concat!(".", ..128);
    let actual = ucmd.arg(dir).run().stdout;
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_root() {
    // Create a 255-character path to root
    let dir = path_concat!("..", ..85);
    let actual = new_ucmd!().arg(dir).run().stdout;
    let expect = get_root_path().to_owned() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}
<commit_msg>test(realpath): improve the coverage<commit_after>use crate::common::util::*;

#[test]
fn test_current_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg(".").run().stdout;
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_current_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Create a 256-character path to current directory
    let dir = path_concat!(".", ..128);
    let actual = ucmd.arg(dir).run().stdout;
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_root() {
    // Create a 255-character path to root
    let dir = path_concat!("..", ..85);
    let actual = new_ucmd!().arg(dir).run().stdout;
    let expect = get_root_path().to_owned() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_file_and_links() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let result = scene.ucmd().run();

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo\n"));

    let actual = scene.ucmd().arg("bar").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo\n"));
}

#[test]
fn test_file_and_links_zero() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let result = scene.ucmd().run();

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo"));
    assert!(!actual.contains("\n"));

    let actual = scene.ucmd().arg("bar").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo"));
    assert!(!actual.contains("\n"));
}

#[test]
fn test_file_and_links_strip() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let result = scene.ucmd().run();

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").arg("-s").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo\n"));

    let actual = scene.ucmd().arg("bar").arg("-s").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("bar\n"));
}

#[test]
fn test_file_and_links_strip_zero() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let result = scene.ucmd().run();

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").arg("-s").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo"));
    assert!(!actual.contains("\n"));

    let actual = scene.ucmd().arg("bar").arg("-s").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("bar"));
    assert!(!actual.contains("\n"));
}
<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

macro_rules! impl_object_for_object_types {
    ( $( $objtype:ident ),* ) => {
        impl Info for Object {
            fn status(&self, download_dir: &std::path::Path) -> crate::object::Result<Status> {
                match *self {
                    $( Object::$objtype(ref o) => Ok(o.status(download_dir)?), )*
                }
            }

            fn filename(&self) -> &str {
                match *self {
                    $( Object::$objtype(ref o) => o.filename(), )*
                }
            }

            fn len(&self) -> u64 {
                match *self {
                    $( Object::$objtype(ref o) => o.len(), )*
                }
            }

            fn sha256sum(&self) -> &str {
                match *self {
                    $( Object::$objtype(ref o) => o.sha256sum(), )*
                }
            }

            fn required_install_size(&self) -> u64 {
                match *self {
                    $( Object::$objtype(ref o) => o.required_install_size(), )*
                }
            }
        }
    };
}

macro_rules! impl_object_info {
    ($objtype:ty) => {
        impl Info for $objtype {
            fn filename(&self) -> &str {
                &self.filename
            }

            fn len(&self) -> u64 {
                self.size
            }

            fn sha256sum(&self) -> &str {
                &self.sha256sum
            }

            fn required_install_size(&self) -> u64 {
                self.size
            }
        }
    };
}

macro_rules! impl_compressed_object_info {
    ($objtype:ty) => {
        impl Info for $objtype {
            fn filename(&self) -> &str {
                &self.filename
            }

            fn len(&self) -> u64 {
                self.size
            }

            fn sha256sum(&self) -> &str {
                &self.sha256sum
            }

            fn required_install_size(&self) -> u64 {
                self.required_uncompressed_size
            }
        }
    };
}

macro_rules! for_any_object {
    ($mode:ident, $alias:ident, $code:block) => {
        match $mode {
            Object::Copy($alias) => $code,
            Object::Flash($alias) => $code,
            Object::Imxkobs($alias) => $code,
            Object::Raw($alias) => $code,
            Object::Tarball($alias) => $code,
            Object::Test($alias) => $code,
            Object::Ubifs($alias) => $code,
        }
    };
}

// This wil execute the block only if the $rule is present, if so, the block
// must return a `R` that implements `Read` and `Seek`. If the
// `check_if_different` reports `Ok(true)` for `R` return is called.
macro_rules! handle_install_if_different {
    ($rule:expr, $sha256sum:expr, $handler:block) => {
        match $rule {
            Some(ref rule) => match $handler.and_then(|mut h| {
                crate::object::installer::check_if_different(&mut h, rule, $sha256sum)
            }) {
                Ok(true) => {
                    slog_scope::info!(
                        "installation has been skipped (install if different): {}",
                        $rule.as_ref().unwrap()
                    );
                    return Ok(());
                }
                Ok(false) => {
                    slog_scope::debug!(
                        "installation will proceed (installation if different): {}",
                        $rule.as_ref().unwrap()
                    );
                }
                Err(e) => {
                    slog_scope::error!(
                        "install if different check ({}) check failed, error: {}",
                        $rule.as_ref().unwrap(),
                        e
                    );
                }
            },
            None => slog_scope::trace!("no install if different rule set, proceeding"),
        }
    };
}
<commit_msg>updatehub: Add context when logging the skip due to install if different<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

macro_rules! impl_object_for_object_types {
    ( $( $objtype:ident ),* ) => {
        impl Info for Object {
            fn status(&self, download_dir: &std::path::Path) -> crate::object::Result<Status> {
                match *self {
                    $( Object::$objtype(ref o) => Ok(o.status(download_dir)?), )*
                }
            }

            fn filename(&self) -> &str {
                match *self {
                    $( Object::$objtype(ref o) => o.filename(), )*
                }
            }

            fn len(&self) -> u64 {
                match *self {
                    $( Object::$objtype(ref o) => o.len(), )*
                }
            }

            fn sha256sum(&self) -> &str {
                match *self {
                    $( Object::$objtype(ref o) => o.sha256sum(), )*
                }
            }

            fn required_install_size(&self) -> u64 {
                match *self {
                    $( Object::$objtype(ref o) => o.required_install_size(), )*
                }
            }
        }
    };
}

macro_rules! impl_object_info {
    ($objtype:ty) => {
        impl Info for $objtype {
            fn filename(&self) -> &str {
                &self.filename
            }

            fn len(&self) -> u64 {
                self.size
            }

            fn sha256sum(&self) -> &str {
                &self.sha256sum
            }

            fn required_install_size(&self) -> u64 {
                self.size
            }
        }
    };
}

macro_rules! impl_compressed_object_info {
    ($objtype:ty) => {
        impl Info for $objtype {
            fn filename(&self) -> &str {
                &self.filename
            }

            fn len(&self) -> u64 {
                self.size
            }

            fn sha256sum(&self) -> &str {
                &self.sha256sum
            }

            fn required_install_size(&self) -> u64 {
                self.required_uncompressed_size
            }
        }
    };
}

macro_rules! for_any_object {
    ($mode:ident, $alias:ident, $code:block) => {
        match $mode {
            Object::Copy($alias) => $code,
            Object::Flash($alias) => $code,
            Object::Imxkobs($alias) => $code,
            Object::Raw($alias) => $code,
            Object::Tarball($alias) => $code,
            Object::Test($alias) => $code,
            Object::Ubifs($alias) => $code,
        }
    };
}

// This wil execute the block only if the $rule is present, if so, the block
// must return a `R` that implements `Read` and `Seek`. If the
// `check_if_different` reports `Ok(true)` for `R` return is called.
macro_rules! handle_install_if_different {
    ($rule:expr, $sha256sum:expr, $handler:block) => {
        match $rule {
            Some(ref rule) => match $handler.and_then(|mut h| {
                crate::object::installer::check_if_different(&mut h, rule, $sha256sum)
            }) {
                Ok(true) => {
                    slog_scope::info!(
                        "installation of {} has been skipped (install if different): {}",
                        $sha256sum,
                        $rule.as_ref().unwrap()
                    );
                    return Ok(());
                }
                Ok(false) => {
                    slog_scope::debug!(
                        "installation will proceed (installation if different): {}",
                        $rule.as_ref().unwrap()
                    );
                }
                Err(e) => {
                    slog_scope::error!(
                        "install if different check ({}) check failed, error: {}",
                        $rule.as_ref().unwrap(),
                        e
                    );
                }
            },
            None => slog_scope::trace!("no install if different rule set, proceeding"),
        }
    };
}
<|endoftext|>


<commit_before>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use nix::sys::stat;
use std::{env, iter};
use std::ffi::CString;
use std::fs::File;
use std::io::Write;
use std::os::unix::prelude::*;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::{_exit, off_t};

#[test]
fn test_fork_and_waitpid() {
    #[allow(unused_variables)]
    let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");

    // Safe: Child only calls `_exit`, which is signal-safe
    let pid = fork();
    match pid {
        Ok(Child) => unsafe { _exit(0) },
        Ok(Parent { child }) => {
            // assert that child was created and pid > 0
            let child_raw: ::libc::pid_t = child.into();
            assert!(child_raw > 0);
            let wait_status = waitpid(child, None);
            match wait_status {
                // assert that waitpid returned correct status and the pid is the one of the child
                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

                // panic, must never happen
                s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),

                // panic, waitpid should never fail
                Err(s) => panic!("Error: waitpid returned Err({:?}", s)
            }

        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    // Grab FORK_MTX so wait doesn't reap a different test's child process
    #[allow(unused_variables)]
    let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");

    // Safe: Child only calls `_exit`, which is signal-safe
    let pid = fork();
    match pid {
        Ok(Child) => unsafe { _exit(0) },
        Ok(Parent { child }) => {
            let wait_status = wait();

            // just assert that (any) one child returns with WaitStatus::Exited
            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_mkstemp() {
    let mut path = env::temp_dir();
    path.push("nix_tempfile.XXXXXX");

    let result = mkstemp(&path);
    match result {
        Ok((fd, path)) => {
            close(fd).unwrap();
            unlink(path.as_path()).unwrap();
        },
        Err(e) => panic!("mkstemp failed: {}", e)
    }
}

#[test]
fn test_mkstemp_directory() {
    // mkstemp should fail if a directory is given
    assert!(mkstemp(&env::temp_dir()).is_err());
}

#[test]
fn test_getpid() {
    let pid: ::libc::pid_t = getpid().into();
    let ppid: ::libc::pid_t = getppid().into();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid: ::libc::pid_t = gettid().into();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        #[allow(unused_variables)]
        let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
        // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
        //       The tests make sure not to do that, though.
        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_fchdir() {
    // fchdir changes the process's cwd
    #[allow(unused_variables)]
    let m = ::CWD_MTX.lock().expect("Mutex got poisoned by another test");

    let tmpdir = TempDir::new("test_fchdir").unwrap();
    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
    let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();

    assert!(fchdir(tmpdir_fd).is_ok());
    assert_eq!(getcwd().unwrap(), tmpdir_path);

    assert!(close(tmpdir_fd).is_ok());
}

#[test]
fn test_getcwd() {
    // chdir changes the process's cwd
    #[allow(unused_variables)]
    let m = ::CWD_MTX.lock().expect("Mutex got poisoned by another test");

    let tmpdir = TempDir::new("test_getcwd").unwrap();
    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
    assert!(chdir(&tmpdir_path).is_ok());
    assert_eq!(getcwd().unwrap(), tmpdir_path);

    // make path 500 chars longer so that buffer doubling in getcwd
    // kicks in.  Note: One path cannot be longer than 255 bytes
    // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
    // 4096 on linux, 1024 on macos)
    let mut inner_tmp_dir = tmpdir_path.to_path_buf();
    for _ in 0..5 {
        let newdir = iter::repeat("a").take(100).collect::<String>();
        inner_tmp_dir.push(newdir);
        assert!(mkdir(inner_tmp_dir.as_path(), stat::S_IRWXU).is_ok());
    }
    assert!(chdir(inner_tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write_all(CONTENTS).unwrap();
    let tmpfd = tmp.into_raw_fd();

    let offset: off_t = 5;
    lseek(tmpfd, offset, Whence::SeekSet).unwrap();

    let mut buf = [0u8; 7];
    ::read_exact(tmpfd, &mut buf);
    assert_eq!(b"f123456", &buf);

    close(tmpfd).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();
    let tmpfd = tmp.into_raw_fd();

    lseek64(tmpfd, 5, Whence::SeekSet).unwrap();

    let mut buf = [0u8; 7];
    ::read_exact(tmpfd, &mut buf);
    assert_eq!(b"f123456", &buf);

    close(tmpfd).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[test]
fn test_fpathconf_limited() {
    let f = tempfile().unwrap();
    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
    let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX);
    assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0);
}

#[test]
fn test_pathconf_limited() {
    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
    let path_max = pathconf(".", PathconfVar::PATH_MAX);
    assert!(path_max.expect("pathconf failed").expect("PATH_MAX is unlimited") > 0);
}

#[test]
fn test_sysconf_limited() {
    // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
    let open_max = sysconf(SysconfVar::OPEN_MAX);
    assert!(open_max.expect("sysconf failed").expect("OPEN_MAX is unlimited") > 0);
}

#[cfg(target_os = "freebsd")]
#[test]
fn test_sysconf_unsupported() {
    // I know of no sysconf variables that are unsupported everywhere, but
    // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms
    // we test.
    let open_max = sysconf(SysconfVar::_XOPEN_CRYPT);
    assert!(open_max.expect("sysconf failed").is_none())
}
<commit_msg>Remove unneeded local<commit_after>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use nix::sys::stat;
use std::{env, iter};
use std::ffi::CString;
use std::fs::File;
use std::io::Write;
use std::os::unix::prelude::*;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::{_exit, off_t};

#[test]
fn test_fork_and_waitpid() {
    #[allow(unused_variables)]
    let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");

    // Safe: Child only calls `_exit`, which is signal-safe
    match fork() {
        Ok(Child) => unsafe { _exit(0) },
        Ok(Parent { child }) => {
            // assert that child was created and pid > 0
            let child_raw: ::libc::pid_t = child.into();
            assert!(child_raw > 0);
            let wait_status = waitpid(child, None);
            match wait_status {
                // assert that waitpid returned correct status and the pid is the one of the child
                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

                // panic, must never happen
                s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),

                // panic, waitpid should never fail
                Err(s) => panic!("Error: waitpid returned Err({:?}", s)
            }

        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    // Grab FORK_MTX so wait doesn't reap a different test's child process
    #[allow(unused_variables)]
    let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");

    // Safe: Child only calls `_exit`, which is signal-safe
    let pid = fork();
    match pid {
        Ok(Child) => unsafe { _exit(0) },
        Ok(Parent { child }) => {
            let wait_status = wait();

            // just assert that (any) one child returns with WaitStatus::Exited
            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_mkstemp() {
    let mut path = env::temp_dir();
    path.push("nix_tempfile.XXXXXX");

    let result = mkstemp(&path);
    match result {
        Ok((fd, path)) => {
            close(fd).unwrap();
            unlink(path.as_path()).unwrap();
        },
        Err(e) => panic!("mkstemp failed: {}", e)
    }
}

#[test]
fn test_mkstemp_directory() {
    // mkstemp should fail if a directory is given
    assert!(mkstemp(&env::temp_dir()).is_err());
}

#[test]
fn test_getpid() {
    let pid: ::libc::pid_t = getpid().into();
    let ppid: ::libc::pid_t = getppid().into();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid: ::libc::pid_t = gettid().into();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        #[allow(unused_variables)]
        let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
        // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
        //       The tests make sure not to do that, though.
        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_fchdir() {
    // fchdir changes the process's cwd
    #[allow(unused_variables)]
    let m = ::CWD_MTX.lock().expect("Mutex got poisoned by another test");

    let tmpdir = TempDir::new("test_fchdir").unwrap();
    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
    let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();

    assert!(fchdir(tmpdir_fd).is_ok());
    assert_eq!(getcwd().unwrap(), tmpdir_path);

    assert!(close(tmpdir_fd).is_ok());
}

#[test]
fn test_getcwd() {
    // chdir changes the process's cwd
    #[allow(unused_variables)]
    let m = ::CWD_MTX.lock().expect("Mutex got poisoned by another test");

    let tmpdir = TempDir::new("test_getcwd").unwrap();
    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
    assert!(chdir(&tmpdir_path).is_ok());
    assert_eq!(getcwd().unwrap(), tmpdir_path);

    // make path 500 chars longer so that buffer doubling in getcwd
    // kicks in.  Note: One path cannot be longer than 255 bytes
    // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
    // 4096 on linux, 1024 on macos)
    let mut inner_tmp_dir = tmpdir_path.to_path_buf();
    for _ in 0..5 {
        let newdir = iter::repeat("a").take(100).collect::<String>();
        inner_tmp_dir.push(newdir);
        assert!(mkdir(inner_tmp_dir.as_path(), stat::S_IRWXU).is_ok());
    }
    assert!(chdir(inner_tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write_all(CONTENTS).unwrap();
    let tmpfd = tmp.into_raw_fd();

    let offset: off_t = 5;
    lseek(tmpfd, offset, Whence::SeekSet).unwrap();

    let mut buf = [0u8; 7];
    ::read_exact(tmpfd, &mut buf);
    assert_eq!(b"f123456", &buf);

    close(tmpfd).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();
    let tmpfd = tmp.into_raw_fd();

    lseek64(tmpfd, 5, Whence::SeekSet).unwrap();

    let mut buf = [0u8; 7];
    ::read_exact(tmpfd, &mut buf);
    assert_eq!(b"f123456", &buf);

    close(tmpfd).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[test]
fn test_fpathconf_limited() {
    let f = tempfile().unwrap();
    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
    let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX);
    assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0);
}

#[test]
fn test_pathconf_limited() {
    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
    let path_max = pathconf(".", PathconfVar::PATH_MAX);
    assert!(path_max.expect("pathconf failed").expect("PATH_MAX is unlimited") > 0);
}

#[test]
fn test_sysconf_limited() {
    // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
    let open_max = sysconf(SysconfVar::OPEN_MAX);
    assert!(open_max.expect("sysconf failed").expect("OPEN_MAX is unlimited") > 0);
}

#[cfg(target_os = "freebsd")]
#[test]
fn test_sysconf_unsupported() {
    // I know of no sysconf variables that are unsupported everywhere, but
    // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms
    // we test.
    let open_max = sysconf(SysconfVar::_XOPEN_CRYPT);
    assert!(open_max.expect("sysconf failed").is_none())
}
<|endoftext|>


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

use binaryninjacore_sys::{
    BNBeginUndoActions,
    BNCloseFile,
    BNCommitUndoActions,
    BNCreateFileMetadata,
    BNFileMetadata,
    BNFreeFileMetadata,
    BNGetCurrentOffset,
    BNGetCurrentView,
    BNGetFileViewOfType,
    BNGetFilename,
    BNIsAnalysisChanged,
    BNIsBackedByDatabase,
    //BNSetFileMetadataNavigationHandler,
    BNIsFileModified,
    BNMarkFileModified,
    BNMarkFileSaved,
    BNNavigate,
    BNNewFileReference,
    BNOpenDatabaseForConfiguration,
    BNOpenExistingDatabase,
    BNRedo,
    BNSetFilename,
    BNUndo,
};

use crate::binaryview::BinaryView;

use crate::rc::*;
use crate::string::*;

#[derive(PartialEq, Eq, Hash)]
pub struct FileMetadata {
    pub(crate) handle: *mut BNFileMetadata,
}

unsafe impl Send for FileMetadata {}
unsafe impl Sync for FileMetadata {}

impl FileMetadata {
    pub(crate) fn from_raw(handle: *mut BNFileMetadata) -> Self {
        Self { handle }
    }

    pub fn new() -> Ref<Self> {
        unsafe {
            Ref::new(Self {
                handle: BNCreateFileMetadata(),
            })
        }
    }

    pub fn with_filename<S: BnStrCompatible>(name: S) -> Ref<Self> {
        let ret = FileMetadata::new();
        ret.set_filename(name);
        ret
    }

    pub fn close(&self) {
        unsafe {
            BNCloseFile(self.handle);
        }
    }

    pub fn filename(&self) -> BnString {
        unsafe {
            let raw = BNGetFilename(self.handle);
            BnString::from_raw(raw)
        }
    }

    pub fn set_filename<S: BnStrCompatible>(&self, name: S) {
        let name = name.as_bytes_with_nul();

        unsafe {
            BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _);
        }
    }

    pub fn is_modified(&self) -> bool {
        unsafe { BNIsFileModified(self.handle) }
    }

    pub fn mark_modified(&self) {
        unsafe {
            BNMarkFileModified(self.handle);
        }
    }

    pub fn is_analysis_changed(&self) -> bool {
        unsafe { BNIsAnalysisChanged(self.handle) }
    }

    pub fn mark_saved(&self) {
        unsafe {
            BNMarkFileSaved(self.handle);
        }
    }

    pub fn is_database_backed<S: BnStrCompatible>(&self, view_type: S) -> bool {
        let view_type = view_type.as_bytes_with_nul();

        unsafe { BNIsBackedByDatabase(self.handle, view_type.as_ref().as_ptr() as *const _) }
    }

    pub fn begin_undo_actions(&self) {
        unsafe {
            BNBeginUndoActions(self.handle);
        }
    }

    pub fn commit_undo_actions(&self) {
        unsafe {
            BNCommitUndoActions(self.handle);
        }
    }

    pub fn undo(&self) {
        unsafe {
            BNUndo(self.handle);
        }
    }

    pub fn redo(&self) {
        unsafe {
            BNRedo(self.handle);
        }
    }

    pub fn current_view(&self) -> BnString {
        unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) }
    }

    pub fn current_offset(&self) -> u64 {
        unsafe { BNGetCurrentOffset(self.handle) }
    }

    pub fn navigate_to<S: BnStrCompatible>(&self, view: S, offset: u64) -> Result<(), ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    pub fn get_view_of_type<S: BnStrCompatible>(&self, view: S) -> Result<Ref<BinaryView>, ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            let res = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _);

            if res.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(res))
            }
        }
    }

    pub fn open_database_for_configuration<S: BnStrCompatible>(
        &self,
        filename: S,
    ) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        unsafe {
            let bv =
                BNOpenDatabaseForConfiguration(self.handle, filename.as_ref().as_ptr() as *const _);

            if bv.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(bv))
            }
        }
    }

    pub fn open_database<S: BnStrCompatible>(&self, filename: S) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        let filename_ptr = filename.as_ref().as_ptr() as *mut _;

        let view = unsafe { BNOpenExistingDatabase(self.handle, filename_ptr) };

        // TODO : add optional progress function
        // let view = match progress_func {
        //     None => BNOpenExistingDatabase(self.handle, filename_ptr),
        //     _ => BNOpenExistingDatabaseWithProgress(self.handle, str(filename), None, ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, cur, total: progress_func(cur, total)))
        // };

        if view.is_null() {
            Err(())
        } else {
            Ok(unsafe { BinaryView::from_raw(view) })
        }
    }
}

impl ToOwned for FileMetadata {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for FileMetadata {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewFileReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreeFileMetadata(handle.handle);
    }
}

/*
BNCreateDatabase,
BNCreateDatabaseWithProgress,
*/
<commit_msg>Rust API : Add filemetadata::FileMetadata::create_database and filemetadata::FileMetadata::save_auto_snapshot<commit_after>// Copyright 2021 Vector 35 Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use binaryninjacore_sys::{
    BNBeginUndoActions,
    BNCloseFile,
    BNCloseProject,
    BNCommitUndoActions,
    BNCreateDatabase,
    BNCreateFileMetadata,
    BNFileMetadata,
    BNFreeFileMetadata,
    BNGetCurrentOffset,
    BNGetCurrentView,
    BNGetFileViewOfType,
    BNGetFilename,
    BNIsAnalysisChanged,
    BNIsBackedByDatabase,
    //BNSetFileMetadataNavigationHandler,
    BNIsFileModified,
    BNIsProjectOpen,
    BNMarkFileModified,
    BNMarkFileSaved,
    BNNavigate,
    BNNewFileReference,
    BNOpenDatabaseForConfiguration,
    BNOpenExistingDatabase,
    BNOpenProject,
    BNRedo,
    BNSaveAutoSnapshot,
    BNSetFilename,
    BNUndo,
};

use crate::binaryview::BinaryView;

use crate::rc::*;
use crate::string::*;

use std::ptr;

#[derive(PartialEq, Eq, Hash)]
pub struct FileMetadata {
    pub(crate) handle: *mut BNFileMetadata,
}

unsafe impl Send for FileMetadata {}
unsafe impl Sync for FileMetadata {}

impl FileMetadata {
    pub(crate) fn from_raw(handle: *mut BNFileMetadata) -> Self {
        Self { handle }
    }

    pub fn new() -> Ref<Self> {
        unsafe {
            Ref::new(Self {
                handle: BNCreateFileMetadata(),
            })
        }
    }

    pub fn with_filename<S: BnStrCompatible>(name: S) -> Ref<Self> {
        let ret = FileMetadata::new();
        ret.set_filename(name);
        ret
    }

    pub fn close(&self) {
        unsafe {
            BNCloseFile(self.handle);
        }
    }

    pub fn filename(&self) -> BnString {
        unsafe {
            let raw = BNGetFilename(self.handle);
            BnString::from_raw(raw)
        }
    }

    pub fn set_filename<S: BnStrCompatible>(&self, name: S) {
        let name = name.as_bytes_with_nul();

        unsafe {
            BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _);
        }
    }

    pub fn modified(&self) -> bool {
        unsafe { BNIsFileModified(self.handle) }
    }

    pub fn mark_modified(&self) {
        unsafe {
            BNMarkFileModified(self.handle);
        }
    }

    pub fn mark_saved(&self) {
        unsafe {
            BNMarkFileSaved(self.handle);
        }
    }

    pub fn is_analysis_changed(&self) -> bool {
        unsafe { BNIsAnalysisChanged(self.handle) }
    }

    pub fn is_database_backed<S: BnStrCompatible>(&self, view_type: S) -> bool {
        let view_type = view_type.as_bytes_with_nul();

        unsafe { BNIsBackedByDatabase(self.handle, view_type.as_ref().as_ptr() as *const _) }
    }

    pub fn begin_undo_actions(&self) {
        unsafe {
            BNBeginUndoActions(self.handle);
        }
    }

    pub fn commit_undo_actions(&self) {
        unsafe {
            BNCommitUndoActions(self.handle);
        }
    }

    pub fn undo(&self) {
        unsafe {
            BNUndo(self.handle);
        }
    }

    pub fn redo(&self) {
        unsafe {
            BNRedo(self.handle);
        }
    }

    pub fn current_view(&self) -> BnString {
        unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) }
    }

    pub fn current_offset(&self) -> u64 {
        unsafe { BNGetCurrentOffset(self.handle) }
    }

    pub fn navigate_to<S: BnStrCompatible>(&self, view: S, offset: u64) -> Result<(), ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    pub fn get_view_of_type<S: BnStrCompatible>(&self, view: S) -> Result<Ref<BinaryView>, ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            let res = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _);

            if res.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(res))
            }
        }
    }

    pub fn create_database<S: BnStrCompatible>(&self, filename: S) -> bool {
        let filename = filename.as_bytes_with_nul();
        let raw = "Raw";

        unsafe {
            BNCreateDatabase(
                BNGetFileViewOfType(self.handle, raw.as_ptr() as *mut _),
                filename.as_ref().as_ptr() as *mut _,
                ptr::null_mut() as *mut _,
            )
        }
    }

    pub fn save_auto_snapshot(&self) -> bool {
        let raw = "Raw";
        unsafe {
            BNSaveAutoSnapshot(
                BNGetFileViewOfType(self.handle, raw.as_ptr() as *mut _),
                ptr::null_mut() as *mut _,
            )
        }
    }

    pub fn open_database_for_configuration<S: BnStrCompatible>(
        &self,
        filename: S,
    ) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        unsafe {
            let bv =
                BNOpenDatabaseForConfiguration(self.handle, filename.as_ref().as_ptr() as *const _);

            if bv.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(bv))
            }
        }
    }

    pub fn open_database<S: BnStrCompatible>(&self, filename: S) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        let filename_ptr = filename.as_ref().as_ptr() as *mut _;

        let view = unsafe { BNOpenExistingDatabase(self.handle, filename_ptr) };

        // TODO : add optional progress function
        // let view = match progress_func {
        //     None => BNOpenExistingDatabase(self.handle, filename_ptr),
        //     _ => BNOpenExistingDatabaseWithProgress(self.handle, str(filename), None, ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, cur, total: progress_func(cur, total)))
        // };

        if view.is_null() {
            Err(())
        } else {
            Ok(unsafe { BinaryView::from_raw(view) })
        }
    }

    pub fn open_project(&self) -> bool {
        unsafe { BNOpenProject(self.handle) }
    }

    pub fn close_project(&self) {
        unsafe {
            BNCloseProject(self.handle);
        }
    }

    pub fn is_project_open(&self) -> bool {
        unsafe { BNIsProjectOpen(self.handle) }
    }
}

impl ToOwned for FileMetadata {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for FileMetadata {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewFileReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreeFileMetadata(handle.handle);
    }
}

/*
BNCreateDatabase,
BNCreateDatabaseWithProgress,
*/
<|endoftext|>


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

// ignore-tidy-linelength
// min-lldb-version: 310

// compile-flags:-g

// === GDB TESTS ===================================================================================
// gdb-command:run

// gdb-command:print eight_bytes1
// gdb-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}}
// gdb-command:print four_bytes1
// gdb-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}}
// gdb-command:print two_bytes1
// gdb-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}}
// gdb-command:print one_byte1
// gdb-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}}

// gdb-command:print eight_bytes2
// gdb-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}}
// gdb-command:print four_bytes2
// gdb-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}}
// gdb-command:print two_bytes2
// gdb-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}}
// gdb-command:print one_byte2
// gdb-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}}

// gdb-command:continue

// === LLDB TESTS ==================================================================================
// lldb-command:run

// lldb-command:print eight_bytes1
// lldb-check:[...]$0 = Variant1(100)
// lldb-command:print four_bytes1
// lldb-check:[...]$1 = Variant1(101)
// lldb-command:print two_bytes1
// lldb-check:[...]$2 = Variant1(102)
// lldb-command:print one_byte1
// lldb-check:[...]$3 = Variant1('A')

// lldb-command:print eight_bytes2
// lldb-check:[...]$4 = Variant2(100)
// lldb-command:print four_bytes2
// lldb-check:[...]$5 = Variant2(101)
// lldb-command:print two_bytes2
// lldb-check:[...]$6 = Variant2(102)
// lldb-command:print one_byte2
// lldb-check:[...]$7 = Variant2('A')

// lldb-command:continue

#![allow(unused_variables)]
#![allow(dead_code)]
#![omit_gdb_pretty_printer_section]

// This test case makes sure that we get correct type descriptions for the enum
// discriminant of different instantiations of the same generic enum type where,
// dependending on the generic type parameter(s), the discriminant has a
// different size in memory.

enum Enum<T> {
    Variant1(T),
    Variant2(T)
}

fn main() {
    // These are ordered for descending size on purpose
    let eight_bytes1 = Enum::Variant1(100.0f64);
    let four_bytes1 = Enum::Variant1(101i32);
    let two_bytes1 = Enum::Variant1(102i16);
    let one_byte1 = Enum::Variant1(65u8);

    let eight_bytes2 = Enum::Variant2(100.0f64);
    let four_bytes2 = Enum::Variant2(101i32);
    let two_bytes2 = Enum::Variant2(102i16);
    let one_byte2 = Enum::Variant2(65u8);

    zzz(); // #break
}

fn zzz() { () }
<commit_msg>test: Ignore a failing test on LLDB<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength
// ignore-lldb: FIXME(#27089)
// min-lldb-version: 310

// compile-flags:-g

// === GDB TESTS ===================================================================================
// gdb-command:run

// gdb-command:print eight_bytes1
// gdb-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}}
// gdb-command:print four_bytes1
// gdb-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}}
// gdb-command:print two_bytes1
// gdb-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}}
// gdb-command:print one_byte1
// gdb-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}}

// gdb-command:print eight_bytes2
// gdb-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}}
// gdb-command:print four_bytes2
// gdb-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}}
// gdb-command:print two_bytes2
// gdb-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}}
// gdb-command:print one_byte2
// gdb-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}}

// gdb-command:continue

// === LLDB TESTS ==================================================================================
// lldb-command:run

// lldb-command:print eight_bytes1
// lldb-check:[...]$0 = Variant1(100)
// lldb-command:print four_bytes1
// lldb-check:[...]$1 = Variant1(101)
// lldb-command:print two_bytes1
// lldb-check:[...]$2 = Variant1(102)
// lldb-command:print one_byte1
// lldb-check:[...]$3 = Variant1('A')

// lldb-command:print eight_bytes2
// lldb-check:[...]$4 = Variant2(100)
// lldb-command:print four_bytes2
// lldb-check:[...]$5 = Variant2(101)
// lldb-command:print two_bytes2
// lldb-check:[...]$6 = Variant2(102)
// lldb-command:print one_byte2
// lldb-check:[...]$7 = Variant2('A')

// lldb-command:continue

#![allow(unused_variables)]
#![allow(dead_code)]
#![omit_gdb_pretty_printer_section]

// This test case makes sure that we get correct type descriptions for the enum
// discriminant of different instantiations of the same generic enum type where,
// dependending on the generic type parameter(s), the discriminant has a
// different size in memory.

enum Enum<T> {
    Variant1(T),
    Variant2(T)
}

fn main() {
    // These are ordered for descending size on purpose
    let eight_bytes1 = Enum::Variant1(100.0f64);
    let four_bytes1 = Enum::Variant1(101i32);
    let two_bytes1 = Enum::Variant1(102i16);
    let one_byte1 = Enum::Variant1(65u8);

    let eight_bytes2 = Enum::Variant2(100.0f64);
    let four_bytes2 = Enum::Variant2(101i32);
    let two_bytes2 = Enum::Variant2(102i16);
    let one_byte2 = Enum::Variant2(65u8);

    zzz(); // #break
}

fn zzz() { () }
<|endoftext|>


<commit_before>//! Types to represent positions inside source file.

/// Represents a position inside a source file. Both lines and columns
/// are 0-indexed.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, Clone)]
pub struct Position {
    #[allow(missing_docs)]
    pub line: u32,
    #[allow(missing_docs)]
    pub column: u32,
}

impl Position {
    /// Create a new position with given line and column.
    pub fn new(line: u32, column: u32) -> Position {
        Position {
            line,
            column,
        }
    }

    /// Create a span that starts here, and goes to given position. If
    /// `self == to`, then the span is considered empty.
    ///
    /// # Panics
    ///
    /// Panics if `to < self`.
    pub fn span_to(self, to: Position) -> Span {
        Span::new(self, to)
    }

    /// Create a new position that is `amount` columns to the right.
    pub fn forward(mut self, amount: u32) -> Position {
        self.column += amount;
        self
    }

    /// Create a new position that is `amount` columns to the left.
    ///
    /// # Panics
    ///
    /// Panics if resulting column is negative.
    pub fn backwards(mut self, amount: u32) -> Position {
        assert!(self.column >= amount, "going back too far");
        self.column -= amount;
        self
    }
}

/// Represents a range inside source file. You can think of it as a selection
/// inside the editor.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, Clone)]
pub struct Span {
    #[allow(missing_docs)]
    pub start: Position,
    #[allow(missing_docs)]
    pub end: Position,
}

impl Span {
    /// Create a span that is between given positions.
    ///
    /// # Panics
    ///
    /// Panics if `start > end`.
    pub fn new(start: Position, end: Position) -> Span {
        assert!(start <= end);
        Span {
            start,
            end,
        }
    }

    /// Return the smallest span that contains both `self` and `other` spans.
    pub fn merge(self, other: Span) -> Span {
        use std::cmp;
        let start = cmp::min(self.start, other.start);
        let end = cmp::max(self.end, other.end);
        Span::new(start, end)
    }
}
<commit_msg>"start from" make way more sense than "indexed"<commit_after>//! Types to represent positions inside source file.

/// Represents a position inside a source file. Both lines and columns start
/// from zero.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, Clone)]
pub struct Position {
    #[allow(missing_docs)]
    pub line: u32,
    #[allow(missing_docs)]
    pub column: u32,
}

impl Position {
    /// Create a new position with given line and column.
    pub fn new(line: u32, column: u32) -> Position {
        Position {
            line,
            column,
        }
    }

    /// Create a span that starts here, and goes to given position. If
    /// `self == to`, then the span is considered empty.
    ///
    /// # Panics
    ///
    /// Panics if `to < self`.
    pub fn span_to(self, to: Position) -> Span {
        Span::new(self, to)
    }

    /// Create a new position that is `amount` columns to the right.
    pub fn forward(mut self, amount: u32) -> Position {
        self.column += amount;
        self
    }

    /// Create a new position that is `amount` columns to the left.
    ///
    /// # Panics
    ///
    /// Panics if resulting column is negative.
    pub fn backwards(mut self, amount: u32) -> Position {
        assert!(self.column >= amount, "going back too far");
        self.column -= amount;
        self
    }
}

/// Represents a range inside source file. You can think of it as a selection
/// inside the editor.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, Clone)]
pub struct Span {
    #[allow(missing_docs)]
    pub start: Position,
    #[allow(missing_docs)]
    pub end: Position,
}

impl Span {
    /// Create a span that is between given positions.
    ///
    /// # Panics
    ///
    /// Panics if `start > end`.
    pub fn new(start: Position, end: Position) -> Span {
        assert!(start <= end);
        Span {
            start,
            end,
        }
    }

    /// Return the smallest span that contains both `self` and `other` spans.
    pub fn merge(self, other: Span) -> Span {
        use std::cmp;
        let start = cmp::min(self.start, other.start);
        let end = cmp::max(self.end, other.end);
        Span::new(start, end)
    }
}
<|endoftext|>


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

/*!
A GPU based renderer for the web.

It serves as an experimental render backend for [Servo](https://servo.org/),
but it can also be used as such in a standalone application.

# External dependencies
WebRender currently depends on [FreeType](https://www.freetype.org/)

# Api Structure
The main entry point to WebRender is the `webrender::Renderer`.

By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
Your `Renderer` is responsible to render the previously processed frames onto the screen.

By calling `yourRenderApiSender.create_api()`, you'll get a `RenderApi` instance,
which is responsible for managing resources and documents. A worker thread is used internally
to untie the workload from the application thread and therefore be able to make better use of
multicore systems.

## Frame

What is referred to as a `frame`, is the current geometry on the screen.
A new Frame is created by calling [`set_display_list()`][newframe] on the `RenderApi`.
When the geometry is processed, the application will be informed via a `RenderNotifier`,
a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
More information about [stacking contexts][stacking_contexts].

`set_display_list()` also needs to be supplied with `BuiltDisplayList`s.
These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
But it doesn't only contain trivial geometry, it can also store another StackingContext, as
they're nestable.

[stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
[newframe]: ../webrender_api/struct.RenderApi.html#method.set_display_list
[notifier]: renderer/struct.Renderer.html#method.set_render_notifier
*/

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod border;
mod clip;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
mod ellipse;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod glyph_cache;
mod glyph_rasterizer;
mod gpu_cache;
mod gpu_types;
mod internal_types;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod spring;
mod texture_allocator;
mod texture_cache;
mod tiling;
mod util;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fxhash;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
pub extern crate webrender_api;
extern crate byteorder;
extern crate rayon;
extern crate plane_split;
#[cfg(feature = "debugger")]
extern crate ws;
#[cfg(feature = "debugger")]
extern crate serde_json;
#[cfg(feature = "debugger")]
#[macro_use]
extern crate serde_derive;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{GraphicsApi, GraphicsApiInfo, ReadPixelsFormat, Renderer, RendererOptions};
pub use renderer::{CpuProfile, GpuProfile, DebugFlags, OutputImageHandler, RendererKind};
pub use renderer::{PROFILER_DBG, RENDER_TARGET_DBG, TEXTURE_CACHE_DBG, ALPHA_PRIM_DBG};
pub use renderer::MAX_VERTEX_TEXTURE_WIDTH;

pub use webrender_api as api;

#[doc(hidden)]
pub use device::build_shader_strings;
<commit_msg>Remove unused 'extern crate notify' line<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*!
A GPU based renderer for the web.

It serves as an experimental render backend for [Servo](https://servo.org/),
but it can also be used as such in a standalone application.

# External dependencies
WebRender currently depends on [FreeType](https://www.freetype.org/)

# Api Structure
The main entry point to WebRender is the `webrender::Renderer`.

By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
Your `Renderer` is responsible to render the previously processed frames onto the screen.

By calling `yourRenderApiSender.create_api()`, you'll get a `RenderApi` instance,
which is responsible for managing resources and documents. A worker thread is used internally
to untie the workload from the application thread and therefore be able to make better use of
multicore systems.

## Frame

What is referred to as a `frame`, is the current geometry on the screen.
A new Frame is created by calling [`set_display_list()`][newframe] on the `RenderApi`.
When the geometry is processed, the application will be informed via a `RenderNotifier`,
a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
More information about [stacking contexts][stacking_contexts].

`set_display_list()` also needs to be supplied with `BuiltDisplayList`s.
These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
But it doesn't only contain trivial geometry, it can also store another StackingContext, as
they're nestable.

[stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
[newframe]: ../webrender_api/struct.RenderApi.html#method.set_display_list
[notifier]: renderer/struct.Renderer.html#method.set_render_notifier
*/

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod border;
mod clip;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
mod ellipse;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod glyph_cache;
mod glyph_rasterizer;
mod gpu_cache;
mod gpu_types;
mod internal_types;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod spring;
mod texture_allocator;
mod texture_cache;
mod tiling;
mod util;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fxhash;
extern crate gleam;
extern crate num_traits;
extern crate time;
pub extern crate webrender_api;
extern crate byteorder;
extern crate rayon;
extern crate plane_split;
#[cfg(feature = "debugger")]
extern crate ws;
#[cfg(feature = "debugger")]
extern crate serde_json;
#[cfg(feature = "debugger")]
#[macro_use]
extern crate serde_derive;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{GraphicsApi, GraphicsApiInfo, ReadPixelsFormat, Renderer, RendererOptions};
pub use renderer::{CpuProfile, GpuProfile, DebugFlags, OutputImageHandler, RendererKind};
pub use renderer::{PROFILER_DBG, RENDER_TARGET_DBG, TEXTURE_CACHE_DBG, ALPHA_PRIM_DBG};
pub use renderer::MAX_VERTEX_TEXTURE_WIDTH;

pub use webrender_api as api;

#[doc(hidden)]
pub use device::build_shader_strings;
<|endoftext|>


<commit_before>extern crate bindgen;
#[cfg(feature = "static")]
extern crate cmake;

static LIBRARIES: &'static [&'static str] =
    &["wlr-common", "wlr-wayland", "wlr-backend", "wlr-session", "wlr-types"];

fn main() {
    let generated = bindgen::builder()
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_function(r"^wlr_.*$")
        .no_unstable_rust()
        .ctypes_prefix("libc")
        .clang_arg("-I")
        .clang_arg("wlroots/include")
        .generate().unwrap();

    if cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wayland-server");
        println!("cargo:rustc-link-lib=dylib=EGL");
        println!("cargo:rustc-link-lib=dylib=GL");
        println!("cargo:rustc-link-lib=dylib=gbm");
        println!("cargo:rustc-link-lib=dylib=drm");
        println!("cargo:rustc-link-lib=dylib=input");
        println!("cargo:rustc-link-lib=dylib=udev");
        println!("cargo:rustc-link-lib=dylib=systemd");
        println!("cargo:rustc-link-lib=dylib=dbus-1");
    } else {
        for library in LIBRARIES {
            println!("cargo:rustc-link-lib=dylib={}", library);
        }
    }

    // generate the bindings
    generated.write_to_file("src/gen.rs").unwrap();

    cmake();
}

#[cfg(not(feature = "static"))]
fn cmake() {}

#[cfg(feature = "static")]
fn cmake() {
    use cmake::Config;

    let dst = Config::new("wlroots")
                // TODO Eventually change to Release, once the warnings stop
                .define("CMAKE_BUILD_TYPE", "Debug")
                // TODO Remove "all" once "install" is valid
                .build_target("all")
                .build();

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-search=native={}/lib64", dst.display());
    println!("cargo:rustc-link-search=native={}/build/", dst.display());
    // TODO May not be needed to specify the directiories directly,
    // wait until the library output stabilizes and look into it later
    println!("cargo:rustc-link-search=native={}/build/types", dst.display());
    println!("cargo:rustc-link-search=native={}/build/session", dst.display());
    println!("cargo:rustc-link-search=native={}/build/common", dst.display());
    println!("cargo:rustc-link-search=native={}/build/wayland", dst.display());
    println!("cargo:rustc-link-search=native={}/build/backend", dst.display());

    for library in LIBRARIES {
        println!("cargo:rustc-link-lib=static={}", library);
    }
}
<commit_msg>derive_debug(true) for wlroots-sys<commit_after>extern crate bindgen;
#[cfg(feature = "static")]
extern crate cmake;

static LIBRARIES: &'static [&'static str] =
    &["wlr-common", "wlr-wayland", "wlr-backend", "wlr-session", "wlr-types"];

fn main() {
    let generated = bindgen::builder()
        .derive_debug(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_function(r"^wlr_.*$")
        .no_unstable_rust()
        .ctypes_prefix("libc")
        .clang_arg("-I")
        .clang_arg("wlroots/include")
        .generate().unwrap();

    if cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wayland-server");
        println!("cargo:rustc-link-lib=dylib=EGL");
        println!("cargo:rustc-link-lib=dylib=GL");
        println!("cargo:rustc-link-lib=dylib=gbm");
        println!("cargo:rustc-link-lib=dylib=drm");
        println!("cargo:rustc-link-lib=dylib=input");
        println!("cargo:rustc-link-lib=dylib=udev");
        println!("cargo:rustc-link-lib=dylib=systemd");
        println!("cargo:rustc-link-lib=dylib=dbus-1");
    } else {
        for library in LIBRARIES {
            println!("cargo:rustc-link-lib=dylib={}", library);
        }
    }

    // generate the bindings
    generated.write_to_file("src/gen.rs").unwrap();

    cmake();
}

#[cfg(not(feature = "static"))]
fn cmake() {}

#[cfg(feature = "static")]
fn cmake() {
    use cmake::Config;

    let dst = Config::new("wlroots")
                // TODO Eventually change to Release, once the warnings stop
                .define("CMAKE_BUILD_TYPE", "Debug")
                // TODO Remove "all" once "install" is valid
                .build_target("all")
                .build();

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-search=native={}/lib64", dst.display());
    println!("cargo:rustc-link-search=native={}/build/", dst.display());
    // TODO May not be needed to specify the directiories directly,
    // wait until the library output stabilizes and look into it later
    println!("cargo:rustc-link-search=native={}/build/types", dst.display());
    println!("cargo:rustc-link-search=native={}/build/session", dst.display());
    println!("cargo:rustc-link-search=native={}/build/common", dst.display());
    println!("cargo:rustc-link-search=native={}/build/wayland", dst.display());
    println!("cargo:rustc-link-search=native={}/build/backend", dst.display());

    for library in LIBRARIES {
        println!("cargo:rustc-link-lib=static={}", library);
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate sync;

#[cfg(test)]
extern crate test;

use std::{cmp, str, fmt, rt, option, io};
use std::rand::{task_rng, Rng};
use sync::{Arc, Future};

#[cfg(test)]
use test::Bencher;

static LIVE_CELL: char = '@';
static DEAD_CELL: char = '.';

fn main() {
  let mut brd = Board::new(65, 248).random();
  let mut timer = io::Timer::new().unwrap();

  let periodic = timer.periodic(64);
  loop {
    println!("\x1b[H\x1b[2J{}", brd);
    periodic.recv();
    brd = brd.parallel_next_generation();
  }
}

#[deriving(PartialEq, Eq, Clone)]
struct Board {
  board: Vec<bool>,
  survive: Vec<uint>,
  born: Vec<uint>,
  rows: uint,
  cols: uint
}

impl Board {
  fn new(rows: uint, cols: uint) -> Board {
    let born = vec![3];
    let survive = vec![2, 3];

    Board::new_with_custom_rules(rows, cols, born, survive)
  }

  fn new_with_custom_rules(rows: uint, cols: uint, born: Vec<uint>, survive: Vec<uint>) -> Board {
    let new_board = Vec::from_elem(rows * cols, false);

    Board { board  : new_board,
            born   : born,
            survive: survive,
            rows   : rows,
            cols   : cols }
  }

  fn len(&self) -> uint {
    self.rows * self.cols
  }

  fn next_board(&self, new_board: Vec<bool>) -> Board {
    assert!(new_board.len() == self.len());

    Board { board  : new_board,
            born   : self.born.clone(),
            survive: self.survive.clone(),
            rows   : self.rows,
            cols   : self.cols }
  }

  fn random(&self) -> Board {
    let board = task_rng().gen_iter::<bool>().take(self.len()).collect();

    self.next_board(board)
  }

  fn next_generation(&self) -> Board {
    let new_brd = Vec::from_fn(self.len(), |cell| self.successor_cell(cell));

    self.next_board(new_brd)
  }

  fn parallel_next_generation(&self) -> Board {
    let length = self.len();
    let num_tasks = cmp::min(rt::default_sched_threads(), length);
    let shared_brd = Arc::new(self.clone());
    let all_tasks: Vec<uint> = range(0, length).collect();
    let tasks: Vec<&[uint]> = all_tasks.as_slice().chunks(length / num_tasks).collect();

    fn future_batch(task_brd: Arc<Board>, task: ~[uint]) -> Future<Vec<bool>> {
      Future::spawn(proc()
        task.iter().map(|&idx| task_brd.successor_cell(idx)).collect()
      )
    }

    let future_batches: Vec<Future<Vec<bool>>> = tasks.move_iter().map(|task| {
      future_batch(shared_brd.clone(), task.to_owned())
    }).collect();

    let mut new_brd: Vec<bool> = Vec::with_capacity(length);

    for b in future_batches.move_iter() {
      new_brd.push_all_move(b.unwrap());
    }

    self.next_board(new_brd)
  }

  fn cell_live(&self, x: uint, y: uint) -> bool {
    !(x >= self.cols || y >= self.rows) && *self.board.get(y * self.cols + x)
  }

  fn living_neighbors(&self, x: uint, y: uint) -> uint {
    let neighbors = [
      self.cell_live(x-1, y-1), self.cell_live(x, y-1), self.cell_live(x+1, y-1),
      self.cell_live(x-1, y+0),                         self.cell_live(x+1, y+0),
      self.cell_live(x-1, y+1), self.cell_live(x, y+1), self.cell_live(x+1, y+1),
    ];
    neighbors.iter().filter(|&x| *x).count()
  }

  fn successor_cell(&self, cell:uint) -> bool {
    self.successor(cell % self.cols, cell / self.cols)
  }

  fn successor(&self, x:uint, y:uint) -> bool {
    let neighbors = self.living_neighbors(x, y);
    if self.cell_live(x, y) {
      self.survive.contains(&neighbors)
    } else {
      self.born.contains(&neighbors)
    }
  }

  fn from_str(string: &str) -> Option<Board> {
    let rows: Vec<&str> = string.split_terminator('\n').collect();
    let (row_cnt, col_cnt) = (rows.get(0).len(), rows.len());

    if rows.iter().any(|x| x.len() != row_cnt) { return None; };

    let brd = option::collect(
      rows.concat().into_bytes().move_iter().map(|c| match c as char {
        LIVE_CELL => Some(true),
        DEAD_CELL => Some(false),
        _         => None
      })
    );

    match brd {
      Some(board) => Some(Board::new(row_cnt, col_cnt).next_board(board)),
      None        => None
    }
  }
}

impl fmt::Show for Board {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

    fn row_to_str(row: &[bool]) -> String {
      let chars: Vec<char> = row.iter().map(|&cell|
        if cell {LIVE_CELL} else {DEAD_CELL}
      ).collect();
      str::from_chars(chars.as_slice())
    }

    let rows: Vec<String> = self.board.as_slice().chunks(self.cols).map(|row|
      row_to_str(row)
    ).collect();

    write!(f, "{}", rows.connect("\n"))
  }
}

#[cfg(test)]
static test_boards: [&'static str, ..3] = [
  ".@.\n.@@\n.@@",
  "...\n@@@\n...",
  ".@.\n.@.\n.@."
];

#[cfg(test)]
fn testing_board(n: uint) -> Board {
  Board::from_str(test_boards[n]).unwrap()
}

#[test]
fn test_board_str_conversion() {
  assert_eq!(testing_board(0).to_str(), test_boards[0].to_string());
}

#[test]
fn test_cell_live() {
  let brd = testing_board(0);
  assert!(!brd.cell_live(0, 0));
  assert!(brd.cell_live(2, 2));
}

#[test]
fn test_live_count() {
  let brd = testing_board(0);
  assert_eq!(brd.living_neighbors(0, 0), 2);
  assert_eq!(brd.living_neighbors(2, 2), 3);
}

#[test]
fn test_next_generation() {
  assert_eq!(testing_board(1).next_generation(), testing_board(2));
}

#[test]
fn test_parallel_next_generation() {
  assert_eq!(testing_board(1).parallel_next_generation(), testing_board(2));
}

#[bench]
fn bench_random(b: &mut Bencher) {
  let brd = Board::new(200,200);
  b.iter(|| brd.random());
}

#[bench]
fn bench_ten_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,10) { brd = brd.next_generation() }
  );
}

#[bench]
fn bench_ten_parallel_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,10) { brd = brd.parallel_next_generation() }
  );
}
<commit_msg>remove last usage of ~[T]; the sync trait moved<commit_after>extern crate rand;
extern crate sync;

#[cfg(test)]
extern crate test;

use std::{cmp, str, fmt, rt, option, io};
use std::rand::{task_rng, Rng};
use std::sync::{Arc, Future};

#[cfg(test)]
use test::Bencher;

static LIVE_CELL: char = '@';
static DEAD_CELL: char = '.';

fn main() {
  let mut brd = Board::new(65, 248).random();
  let mut timer = io::Timer::new().unwrap();

  let periodic = timer.periodic(64);
  loop {
    println!("\x1b[H\x1b[2J{}", brd);
    periodic.recv();
    brd = brd.parallel_next_generation();
  }
}

#[deriving(PartialEq, Eq, Clone)]
struct Board {
  board: Vec<bool>,
  survive: Vec<uint>,
  born: Vec<uint>,
  rows: uint,
  cols: uint
}

impl Board {
  fn new(rows: uint, cols: uint) -> Board {
    let born = vec![3];
    let survive = vec![2, 3];

    Board::new_with_custom_rules(rows, cols, born, survive)
  }

  fn new_with_custom_rules(rows: uint, cols: uint, born: Vec<uint>, survive: Vec<uint>) -> Board {
    let new_board = Vec::from_elem(rows * cols, false);

    Board { board  : new_board,
            born   : born,
            survive: survive,
            rows   : rows,
            cols   : cols }
  }

  fn len(&self) -> uint {
    self.rows * self.cols
  }

  fn next_board(&self, new_board: Vec<bool>) -> Board {
    assert!(new_board.len() == self.len());

    Board { board  : new_board,
            born   : self.born.clone(),
            survive: self.survive.clone(),
            rows   : self.rows,
            cols   : self.cols }
  }

  fn random(&self) -> Board {
    let board = task_rng().gen_iter::<bool>().take(self.len()).collect();

    self.next_board(board)
  }

  fn next_generation(&self) -> Board {
    let new_brd = Vec::from_fn(self.len(), |cell| self.successor_cell(cell));

    self.next_board(new_brd)
  }

  fn parallel_next_generation(&self) -> Board {
    let length = self.len();
    let num_tasks = cmp::min(rt::default_sched_threads(), length);
    let shared_brd = Arc::new(self.clone());
    let all_tasks: Vec<uint> = range(0, length).collect();
    let tasks: Vec<&[uint]> = all_tasks.as_slice().chunks(length / num_tasks).collect();

    fn future_batch(task_brd: Arc<Board>, task: Vec<uint>) -> Future<Vec<bool>> {
      Future::spawn(proc()
        task.iter().map(|&idx| task_brd.successor_cell(idx)).collect()
      )
    }

    let future_batches: Vec<Future<Vec<bool>>> = tasks.move_iter().map(|task| {
      future_batch(shared_brd.clone(), task.to_owned())
    }).collect();

    let mut new_brd: Vec<bool> = Vec::with_capacity(length);

    for b in future_batches.move_iter() {
      new_brd.push_all_move(b.unwrap());
    }

    self.next_board(new_brd)
  }

  fn cell_live(&self, x: uint, y: uint) -> bool {
    !(x >= self.cols || y >= self.rows) && *self.board.get(y * self.cols + x)
  }

  fn living_neighbors(&self, x: uint, y: uint) -> uint {
    let neighbors = [
      self.cell_live(x-1, y-1), self.cell_live(x, y-1), self.cell_live(x+1, y-1),
      self.cell_live(x-1, y+0),                         self.cell_live(x+1, y+0),
      self.cell_live(x-1, y+1), self.cell_live(x, y+1), self.cell_live(x+1, y+1),
    ];
    neighbors.iter().filter(|&x| *x).count()
  }

  fn successor_cell(&self, cell:uint) -> bool {
    self.successor(cell % self.cols, cell / self.cols)
  }

  fn successor(&self, x:uint, y:uint) -> bool {
    let neighbors = self.living_neighbors(x, y);
    if self.cell_live(x, y) {
      self.survive.contains(&neighbors)
    } else {
      self.born.contains(&neighbors)
    }
  }

  fn from_str(string: &str) -> Option<Board> {
    let rows: Vec<&str> = string.split_terminator('\n').collect();
    let (row_cnt, col_cnt) = (rows.get(0).len(), rows.len());

    if rows.iter().any(|x| x.len() != row_cnt) { return None; };

    let brd = option::collect(
      rows.concat().into_bytes().move_iter().map(|c| match c as char {
        LIVE_CELL => Some(true),
        DEAD_CELL => Some(false),
        _         => None
      })
    );

    match brd {
      Some(board) => Some(Board::new(row_cnt, col_cnt).next_board(board)),
      None        => None
    }
  }
}

impl fmt::Show for Board {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

    fn row_to_str(row: &[bool]) -> String {
      let chars: Vec<char> = row.iter().map(|&cell|
        if cell {LIVE_CELL} else {DEAD_CELL}
      ).collect();
      str::from_chars(chars.as_slice())
    }

    let rows: Vec<String> = self.board.as_slice().chunks(self.cols).map(|row|
      row_to_str(row)
    ).collect();

    write!(f, "{}", rows.connect("\n"))
  }
}

#[cfg(test)]
static test_boards: [&'static str, ..3] = [
  ".@.\n.@@\n.@@",
  "...\n@@@\n...",
  ".@.\n.@.\n.@."
];

#[cfg(test)]
fn testing_board(n: uint) -> Board {
  Board::from_str(test_boards[n]).unwrap()
}

#[test]
fn test_board_str_conversion() {
  assert_eq!(testing_board(0).to_str(), test_boards[0].to_string());
}

#[test]
fn test_cell_live() {
  let brd = testing_board(0);
  assert!(!brd.cell_live(0, 0));
  assert!(brd.cell_live(2, 2));
}

#[test]
fn test_live_count() {
  let brd = testing_board(0);
  assert_eq!(brd.living_neighbors(0, 0), 2);
  assert_eq!(brd.living_neighbors(2, 2), 3);
}

#[test]
fn test_next_generation() {
  assert_eq!(testing_board(1).next_generation(), testing_board(2));
}

#[test]
fn test_parallel_next_generation() {
  assert_eq!(testing_board(1).parallel_next_generation(), testing_board(2));
}

#[bench]
fn bench_random(b: &mut Bencher) {
  let brd = Board::new(200,200);
  b.iter(|| brd.random());
}

#[bench]
fn bench_ten_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,10) { brd = brd.next_generation() }
  );
}

#[bench]
fn bench_ten_parallel_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,10) { brd = brd.parallel_next_generation() }
  );
}
<|endoftext|>


<commit_before>extern crate rand;

#[cfg(test)]
extern crate test;

use std::vec;
use std::str;
use std::fmt;
use std::option;
use rand::{task_rng, Rng};

#[cfg(test)]
use test::BenchHarness;

static LIVE_CELL: char = '@';
static DEAD_CELL: char = '.';

fn main() {
  let mut brd = Board::new(65,250).random();
  loop {
    println!("\x1b[H\x1b[2J{}", brd);
    brd = brd.next_generation();
  }
}

#[deriving(Eq)]
struct Board {
  board: Vec<Vec<bool>>,
  rows: uint,
  cols: uint
}

impl Board {
  fn new(rows: uint, cols: uint) -> Board {
    let new_board = Vec::from_elem(rows, Vec::from_elem(cols, false));
    Board { board: new_board, rows: rows, cols: cols }
  }

  fn random(&self) -> Board {
    let mut rng = task_rng();
    let board = Vec::from_fn(self.rows, |_| {
      Vec::from_slice(task_rng().gen_vec(self.cols))
    });

    Board { board: board, rows: self.rows, cols: self.cols }
  }

  fn next_generation(&self) -> Board {
    let new_brd = Vec::from_fn(self.rows, |row| {
      Vec::from_fn(self.cols, |col| self.successor(col, row))
    });
    Board { board: new_brd, rows: self.rows, cols: self.cols }
  }

  fn cell_live(&self, x: uint, y: uint) -> bool {
    if x >= self.cols || y >= self.rows {
      false
    } else {
      *self.board.get(y).get(x)
    }
  }

  fn living_neighbors(&self, x: uint, y: uint) -> uint {
    let neighbors = [
      self.cell_live(x-1, y-1), self.cell_live(x, y-1), self.cell_live(x+1, y-1),
      self.cell_live(x-1, y+0),                         self.cell_live(x+1, y+0),
      self.cell_live(x-1, y+1), self.cell_live(x, y+1), self.cell_live(x+1, y+1),
    ];
    neighbors.iter().count(|x| *x)
  }

  fn successor(&self, x:uint, y:uint) -> bool {
    let neighbors = self.living_neighbors(x, y);
    if self.cell_live(x, y) {
      neighbors == 2 || neighbors == 3
    } else {
      neighbors == 3
    }
  }

  fn from_str(string: &str) -> Option<Board> {
    fn process_rows(string: &str) -> Option<Vec<Vec<bool>>> {
      let mut rows = string.split_terminator('\n').peekable();
      let col_count = match rows.peek() {
        Some(cols) => Some(cols.len()),
        None       => None
      };
      col_count.and(option::collect(rows.map(|row| {
        let len = row.len();
        if len != 0 && Some(len) == col_count {
          process_cells(row)
        } else {
          None
        }
      })))
    }

    fn process_cells(row: &str) -> Option<Vec<bool>> {
      option::collect(row.chars().map(process_cell))
    }

    fn process_cell(cell: char) -> Option<bool> {
      match cell {
        LIVE_CELL => Some(true),
        DEAD_CELL => Some(false),
        _         => None
      }
    }

    let board = process_rows(string);
    match board {
      Some(brd) => Some(Board { board: brd.clone(),
                                rows : brd.len(),
                                cols : brd.get(0).len() }),
      None      => None
    }
  }
}

impl fmt::Show for Board {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

    fn row_to_str(row: &Vec<bool>) -> ~str {
      let chars: ~[char] = row.iter().map(|cell|
        if *cell {LIVE_CELL} else {DEAD_CELL}
      ).collect();
      str::from_chars(chars)
    }

    let rows: ~[~str] = self.board.iter().map(|row|
      row_to_str(row)
    ).collect();

    write!(f.buf, "{}", rows.connect("\n"))
  }
}

#[cfg(test)]
fn testing_board(n: int) -> Board {
  let brds = [
    ".@.\n" +
    ".@@\n" +
    ".@@\n"
    ,
    "...\n" +
    "@@@\n" +
    "...\n"
    ,
    ".@.\n" +
    ".@.\n" +
    ".@.\n" ];
  Board::from_str(brds[n]).unwrap()
}

#[test]
fn test_cell_live() {
  let brd = testing_board(0);
  assert!(!brd.cell_live(0, 0));
  assert!(brd.cell_live(2, 2));
}

#[test]
fn test_live_count() {
  let brd = testing_board(0);
  assert!(brd.living_neighbors(0, 0) == 2);
  assert!(brd.living_neighbors(2, 2) == 3);
}

#[test]
fn test_next_generation() {
  assert!(testing_board(1).next_generation() == testing_board(2))
}

#[bench]
fn bench_random(b: &mut BenchHarness) {
  let brd = Board::new(200,200);
  b.iter(|| {brd.random();})
}

#[bench]
fn bench_hundred_generations(b: &mut BenchHarness) {
  let mut brd = Board::new(200,200).random();
  b.iter(|| {
    for _ in range(0,100) { brd = brd.next_generation() }
  });
}
<commit_msg>Limit framerate to reduce visual tearing<commit_after>extern crate rand;

#[cfg(test)]
extern crate test;

use std::vec;
use std::str;
use std::fmt;
use std::option;
use std::io::Timer;
use rand::{task_rng, Rng};

#[cfg(test)]
use test::BenchHarness;

static LIVE_CELL: char = '@';
static DEAD_CELL: char = '.';

fn main() {
  let mut brd = Board::new(65,250).random();
  let mut timer = Timer::new().unwrap();

  let periodic = timer.periodic(64);
  loop {
    println!("\x1b[H\x1b[2J{}", brd);
    periodic.recv();
    brd = brd.next_generation();
  }
}

#[deriving(Eq)]
struct Board {
  board: Vec<Vec<bool>>,
  rows: uint,
  cols: uint
}

impl Board {
  fn new(rows: uint, cols: uint) -> Board {
    let new_board = Vec::from_elem(rows, Vec::from_elem(cols, false));
    Board { board: new_board, rows: rows, cols: cols }
  }

  fn random(&self) -> Board {
    let board = Vec::from_fn(self.rows, |_| {
      Vec::from_slice(task_rng().gen_vec(self.cols))
    });

    Board { board: board, rows: self.rows, cols: self.cols }
  }

  fn next_generation(&self) -> Board {
    let new_brd = Vec::from_fn(self.rows, |row| {
      Vec::from_fn(self.cols, |col| self.successor(col, row))
    });
    Board { board: new_brd, rows: self.rows, cols: self.cols }
  }

  fn cell_live(&self, x: uint, y: uint) -> bool {
    if x >= self.cols || y >= self.rows {
      false
    } else {
      *self.board.get(y).get(x)
    }
  }

  fn living_neighbors(&self, x: uint, y: uint) -> uint {
    let neighbors = [
      self.cell_live(x-1, y-1), self.cell_live(x, y-1), self.cell_live(x+1, y-1),
      self.cell_live(x-1, y+0),                         self.cell_live(x+1, y+0),
      self.cell_live(x-1, y+1), self.cell_live(x, y+1), self.cell_live(x+1, y+1),
    ];
    neighbors.iter().count(|x| *x)
  }

  fn successor(&self, x:uint, y:uint) -> bool {
    let neighbors = self.living_neighbors(x, y);
    if self.cell_live(x, y) {
      neighbors == 2 || neighbors == 3
    } else {
      neighbors == 3
    }
  }

  fn from_str(string: &str) -> Option<Board> {
    fn process_rows(string: &str) -> Option<Vec<Vec<bool>>> {
      let mut rows = string.split_terminator('\n').peekable();
      let col_count = match rows.peek() {
        Some(cols) => Some(cols.len()),
        None       => None
      };
      col_count.and(option::collect(rows.map(|row| {
        let len = row.len();
        if len != 0 && Some(len) == col_count {
          process_cells(row)
        } else {
          None
        }
      })))
    }

    fn process_cells(row: &str) -> Option<Vec<bool>> {
      option::collect(row.chars().map(process_cell))
    }

    fn process_cell(cell: char) -> Option<bool> {
      match cell {
        LIVE_CELL => Some(true),
        DEAD_CELL => Some(false),
        _         => None
      }
    }

    let board = process_rows(string);
    match board {
      Some(brd) => Some(Board { board: brd.clone(),
                                rows : brd.len(),
                                cols : brd.get(0).len() }),
      None      => None
    }
  }
}

impl fmt::Show for Board {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

    fn row_to_str(row: &Vec<bool>) -> ~str {
      let chars: ~[char] = row.iter().map(|cell|
        if *cell {LIVE_CELL} else {DEAD_CELL}
      ).collect();
      str::from_chars(chars)
    }

    let rows: ~[~str] = self.board.iter().map(|row|
      row_to_str(row)
    ).collect();

    write!(f.buf, "{}", rows.connect("\n"))
  }
}

#[cfg(test)]
fn testing_board(n: int) -> Board {
  let brds = [
    ".@.\n" +
    ".@@\n" +
    ".@@\n"
    ,
    "...\n" +
    "@@@\n" +
    "...\n"
    ,
    ".@.\n" +
    ".@.\n" +
    ".@.\n" ];
  Board::from_str(brds[n]).unwrap()
}

#[test]
fn test_cell_live() {
  let brd = testing_board(0);
  assert!(!brd.cell_live(0, 0));
  assert!(brd.cell_live(2, 2));
}

#[test]
fn test_live_count() {
  let brd = testing_board(0);
  assert!(brd.living_neighbors(0, 0) == 2);
  assert!(brd.living_neighbors(2, 2) == 3);
}

#[test]
fn test_next_generation() {
  assert!(testing_board(1).next_generation() == testing_board(2))
}

#[bench]
fn bench_random(b: &mut BenchHarness) {
  let brd = Board::new(200,200);
  b.iter(|| {brd.random();})
}

#[bench]
fn bench_hundred_generations(b: &mut BenchHarness) {
  let mut brd = Board::new(200,200).random();
  b.iter(|| {
    for _ in range(0,100) { brd = brd.next_generation() }
  });
}
<|endoftext|>


<commit_before>fn main() {
    let mut doors = [false; 100];

    for p in 0..100 {
        doors[p] = !doors[p];
    }

    for d in 0..doors.len() {
        if doors[d] {
            println!("{}", d + 1);
        }
    }
}
<commit_msg>Working simple version<commit_after>fn main() {
    let mut doors = [false; 100];
    let mut d;

    for p in 0..100 {
        d = p;
        while d < doors.len() {
            doors[d] = !doors[d];
            d += (p + 1);
        }
    }

    for (i, &d) in doors.iter().enumerate() {
        if d {
            println!("{}", i + 1);
        }
    }
}
<|endoftext|>


<commit_before>use brainfuck::BrainfuckVM;
use std::os;
use std::io::File;

mod brainfuck;

fn main() {

    let args = os::args();

    if args.len() < 2 {
        print!("Usage: {} filename.bf\n", args[0]);
        return;
    }

    let file = args[1];

    //let mut reader = BufferedReader::new(File::open(&Path::new(file)));
    let mut reader = File::open(&Path::new(file));

    let vm = BrainfuckVM::new(&mut reader); // print 24
    vm.run();
}
<commit_msg>Take stdin or file<commit_after>use brainfuck::BrainfuckVM;
use std::os;
use std::io::{File, stdin};

mod brainfuck;

fn main() {

    let args = os::args();

    if args.len() < 2 {
        print!("Usage: {} filename.bf\n", args[0]);
        return;
    }

    let file = args[1];

    //let mut reader = BufferedReader::new(File::open(&Path::new(file)));
    let mut reader : ~Reader = if file == ~"-" {
        ~stdin() as ~Reader
    } else {
        ~File::open(&Path::new(file)) as ~Reader
    };

    let vm = BrainfuckVM::new(&mut reader); // print 24
    vm.run();
}
<|endoftext|>


<commit_before>fn main() {
    // sieve[i] == 1 stands for 2 * i + 1 is not prime
    // sieve[i] == 0 stands for 2 * i + 1 is prime
    let mut sieve = vec![0; 49999];
    let i_limit: u32 = ((100000 as f64).sqrt() as u32 - 1) / 2;
    for i in 1..i_limit {
        let index = i as usize;
        if sieve[index] == 0 {
            let mut j: usize = 2 * index * (index + 1);
            while j < 49999 {
                sieve[j] = 1;
                j = j + 2 * index + 1;
            }
        }
    }

    let mut i = 1;
    let mut count = 0;
    while count <= 500 {
        count = 1;
        let mut sum = i * (i + 1) / 2;

        // sieve does not contain factor 2
        let mut carry_2 = 0;
        while sum % 2 == 0 {
            sum = sum / 2;
            carry_2 = carry_2 + 1;
        }
        count = count * (carry_2 + 1);

        for j in 1..49999 {
            if (2 * j + 1) * (2 * j + 1) > sum {
                count = count * 2;
                break;
            }

            let mut carry_exp = 0;
            while sum % (2 * j + 1) == 0 {
                sum = sum / (2 * j + 1);
                carry_exp = carry_exp + 1;
            }
            count = count * (carry_exp + 1);

            if sum == 1 {
                break;
            }
        }

        i = i + 1;
    }

    println!("{}", i * (i - 1) /2);
}
<commit_msg>optimize rust solution for HighlyDivisibleTriangularNumber<commit_after>fn main() {
    // sieve[i] == 1 stands for 2 * i + 1 is not prime
    // sieve[i] == 0 stands for 2 * i + 1 is prime
    let mut sieve = vec![0; 49999];
    let i_limit: u32 = ((100000 as f64).sqrt() as u32 - 1) / 2;
    for i in 1..i_limit {
        let index = i as usize;
        if sieve[index] == 0 {
            let mut j: usize = 2 * index * (index + 1);
            while j < 49999 {
                sieve[j] = 1;
                j = j + 2 * index + 1;
            }
        }
    }

    let mut i = 6;
    let mut count = 0;
    let mut keep_factor_count = 2;  // D(3) == 2;
    while count <= 500 {
        //println!("----------------------------------------");
        //if i % 2 == 0 {
        //    println!("D(({} * {}) / 2) = D({}) * D({})", i, i + 1, i / 2, i + 1);
        //    println!("keep_factor_count aka D({}) is: {}", i / 2, keep_factor_count);
        //} else {
        //    println!("D(({} * {}) / 2) = D({}) * D({})", i, i + 1, (i + 1) / 2, i);
        //    println!("keep_factor_count aka D({}) is: {}", i, keep_factor_count);
        //}
        let mut cal_factor_count = 1;
        let mut sum = if i % 2 == 0 {
            i + 1
        } else {
            (i + 1) / 2
        };

        // sieve does not contain factor 2
        let mut carry_2 = 0;
        while sum % 2 == 0 {
            sum = sum / 2;
            carry_2 = carry_2 + 1;
        }
        cal_factor_count = cal_factor_count * (carry_2 + 1);

        if sum > 1 {
            for j in 1..49999 {
                if (2 * j + 1) * (2 * j + 1) > sum {
                    cal_factor_count = cal_factor_count * 2;
                    break;
                }

                let mut carry_exp = 0;
                while sum % (2 * j + 1) == 0 {
                    sum = sum / (2 * j + 1);
                    carry_exp = carry_exp + 1;
                }
                cal_factor_count = cal_factor_count * (carry_exp + 1);

                if sum == 1 {
                    break;
                }
            }
        }

        //println!("cal_factor_count: {}", cal_factor_count);
        count = keep_factor_count * cal_factor_count;
        keep_factor_count = cal_factor_count;
        i = i + 1;
    }

    println!("{}", i * (i - 1) / 2);
}
<|endoftext|>