<commit_before>//! Tests for `[alias]` config command aliases.

use std::env;

use cargo_test_support::tools::echo_subcommand;
use cargo_test_support::{basic_bin_manifest, project};

#[cargo_test]
fn alias_incorrect_config_type() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                b-cargo-test = 5
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_status(101)
        .with_stderr_contains(
            "\
[ERROR] invalid configuration for key `alias.b-cargo-test`
expected a list, but found a integer for [..]",
        )
        .run();
}

#[cargo_test]
fn alias_config() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                b-cargo-test = "build"
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_stderr_contains(
            "\
[COMPILING] foo v0.5.0 [..]
[RUNNING] `rustc --crate-name foo [..]",
        )
        .run();
}

#[cargo_test]
fn dependent_alias() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                b-cargo-test = "build"
                a-cargo-test = ["b-cargo-test", "-v"]
            "#,
        )
        .build();

    p.cargo("a-cargo-test")
        .with_stderr_contains(
            "\
[COMPILING] foo v0.5.0 [..]
[RUNNING] `rustc --crate-name foo [..]",
        )
        .run();
}

#[cargo_test]
fn default_args_alias() {
    let echo = echo_subcommand();
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                echo = "echo --flag1 --flag2"
                test-1 = "echo"
                build = "build --verbose"
            "#,
        )
        .build();

    let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
    paths.push(echo.target_debug_dir());
    let path = env::join_paths(paths).unwrap();

    p.cargo("echo")
        .env("PATH", &path)
        .with_status(101)
        .with_stderr("error: alias echo has unresolvable recursive definition: echo -> echo")
        .run();

    p.cargo("test-1")
        .env("PATH", &path)
        .with_status(101)
        .with_stderr(
            "error: alias test-1 has unresolvable recursive definition: test-1 -> echo -> echo",
        )
        .run();

    // Builtins are not expanded by rule
    p.cargo("build")
        .with_stderr(
            "\
[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command
[COMPILING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn corecursive_alias() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                test-1 = "test-2 --flag1"
                test-2 = "test-3 --flag2"
                test-3 = "test-1 --flag3"
            "#,
        )
        .build();

    p.cargo("test-1")
        .with_status(101)
        .with_stderr(
            "error: alias test-1 has unresolvable recursive definition: test-1 -> test-2 -> test-3 -> test-1",
        )
        .run();

    p.cargo("test-2")
        .with_status(101)
        .with_stderr(
            "error: alias test-2 has unresolvable recursive definition: test-2 -> test-3 -> test-1 -> test-2",
        )
        .run();
}

#[cargo_test]
fn alias_list_test() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               b-cargo-test = ["build", "--release"]
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_stderr_contains("[COMPILING] foo v0.5.0 [..]")
        .with_stderr_contains("[RUNNING] `rustc --crate-name [..]")
        .run();
}

#[cargo_test]
fn alias_with_flags_config() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               b-cargo-test = "build --release"
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_stderr_contains("[COMPILING] foo v0.5.0 [..]")
        .with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]")
        .run();
}

#[cargo_test]
fn alias_cannot_shadow_builtin_command() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               build = "fetch"
            "#,
        )
        .build();

    p.cargo("build")
        .with_stderr(
            "\
[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command
[COMPILING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn alias_override_builtin_alias() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               b = "run"
            "#,
        )
        .build();

    p.cargo("b")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `target/debug/foo[EXE]`
",
        )
        .run();
}

#[cargo_test]
fn builtin_alias_takes_options() {
    // #6381
    let p = project()
        .file("src/lib.rs", "")
        .file(
            "examples/ex1.rs",
            r#"fn main() { println!("{}", std::env::args().skip(1).next().unwrap()) }"#,
        )
        .build();

    p.cargo("r --example ex1 -- asdf").with_stdout("asdf").run();
}

#[cargo_test]
fn global_options_with_alias() {
    // Check that global options are passed through.
    let p = project().file("src/lib.rs", "").build();

    p.cargo("-v c")
        .with_stderr(
            "\
[CHECKING] foo [..]
[RUNNING] `rustc [..]
[FINISHED] dev [..]
",
        )
        .run();
}

#[cargo_test]
fn weird_check() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("-- check --invalid_argument -some-other-argument")
        .with_stderr(
            "\
[WARNING] trailing arguments after built-in command `check` are ignored: `--invalid_argument -some-other-argument`
[CHECKING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}
<commit_msg>Update test for warning for alias shadowing an external subcommand<commit_after>//! Tests for `[alias]` config command aliases.

use std::env;

use cargo_test_support::tools::echo_subcommand;
use cargo_test_support::{basic_bin_manifest, project};

#[cargo_test]
fn alias_incorrect_config_type() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                b-cargo-test = 5
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_status(101)
        .with_stderr_contains(
            "\
[ERROR] invalid configuration for key `alias.b-cargo-test`
expected a list, but found a integer for [..]",
        )
        .run();
}

#[cargo_test]
fn alias_config() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                b-cargo-test = "build"
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_stderr_contains(
            "\
[COMPILING] foo v0.5.0 [..]
[RUNNING] `rustc --crate-name foo [..]",
        )
        .run();
}

#[cargo_test]
fn dependent_alias() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                b-cargo-test = "build"
                a-cargo-test = ["b-cargo-test", "-v"]
            "#,
        )
        .build();

    p.cargo("a-cargo-test")
        .with_stderr_contains(
            "\
[COMPILING] foo v0.5.0 [..]
[RUNNING] `rustc --crate-name foo [..]",
        )
        .run();
}

#[cargo_test]
fn default_args_alias() {
    let echo = echo_subcommand();
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                echo = "echo --flag1 --flag2"
                test-1 = "echo"
                build = "build --verbose"
            "#,
        )
        .build();

    let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
    paths.push(echo.target_debug_dir());
    let path = env::join_paths(paths).unwrap();

    p.cargo("echo")
        .env("PATH", &path)
        .with_status(101)
        .with_stderr("\
warning: user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo`
error: alias echo has unresolvable recursive definition: echo -> echo
",
        )
        .run();

    p.cargo("test-1")
        .env("PATH", &path)
        .with_status(101)
        .with_stderr("\
warning: user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo`
error: alias test-1 has unresolvable recursive definition: test-1 -> echo -> echo
",
        )
        .run();

    // Builtins are not expanded by rule
    p.cargo("build")
        .with_stderr(
            "\
[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command
[COMPILING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn corecursive_alias() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
                [alias]
                test-1 = "test-2 --flag1"
                test-2 = "test-3 --flag2"
                test-3 = "test-1 --flag3"
            "#,
        )
        .build();

    p.cargo("test-1")
        .with_status(101)
        .with_stderr(
            "error: alias test-1 has unresolvable recursive definition: test-1 -> test-2 -> test-3 -> test-1",
        )
        .run();

    p.cargo("test-2")
        .with_status(101)
        .with_stderr(
            "error: alias test-2 has unresolvable recursive definition: test-2 -> test-3 -> test-1 -> test-2",
        )
        .run();
}

#[cargo_test]
fn alias_list_test() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               b-cargo-test = ["build", "--release"]
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_stderr_contains("[COMPILING] foo v0.5.0 [..]")
        .with_stderr_contains("[RUNNING] `rustc --crate-name [..]")
        .run();
}

#[cargo_test]
fn alias_with_flags_config() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               b-cargo-test = "build --release"
            "#,
        )
        .build();

    p.cargo("b-cargo-test -v")
        .with_stderr_contains("[COMPILING] foo v0.5.0 [..]")
        .with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]")
        .run();
}

#[cargo_test]
fn alias_cannot_shadow_builtin_command() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               build = "fetch"
            "#,
        )
        .build();

    p.cargo("build")
        .with_stderr(
            "\
[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command
[COMPILING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn alias_override_builtin_alias() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
               [alias]
               b = "run"
            "#,
        )
        .build();

    p.cargo("b")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `target/debug/foo[EXE]`
",
        )
        .run();
}

#[cargo_test]
fn builtin_alias_takes_options() {
    // #6381
    let p = project()
        .file("src/lib.rs", "")
        .file(
            "examples/ex1.rs",
            r#"fn main() { println!("{}", std::env::args().skip(1).next().unwrap()) }"#,
        )
        .build();

    p.cargo("r --example ex1 -- asdf").with_stdout("asdf").run();
}

#[cargo_test]
fn global_options_with_alias() {
    // Check that global options are passed through.
    let p = project().file("src/lib.rs", "").build();

    p.cargo("-v c")
        .with_stderr(
            "\
[CHECKING] foo [..]
[RUNNING] `rustc [..]
[FINISHED] dev [..]
",
        )
        .run();
}

#[cargo_test]
fn weird_check() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("-- check --invalid_argument -some-other-argument")
        .with_stderr(
            "\
[WARNING] trailing arguments after built-in command `check` are ignored: `--invalid_argument -some-other-argument`
[CHECKING] foo v0.5.0 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}
<|endoftext|>


<commit_before>// linked list implementation in rust
use std::rc::Rc;

// implementing linked list via pointers.
#[derive(Debug)]
enum Node<T> {
    Empty,
    Elem(T, Box<Node<T>>)
}

struct NodeIterator<'a, T: 'a> {
    // whenever a struct has a reference as its field
    // it needs a lifetime specifier.
    node: &'a Node<T>,
}

// implementing linked list via reference counting pointers.
#[derive(Debug, Clone)]
enum RCNode<T: Copy> {
    // in order to have multiple reference, we either need:
    // T:Copy, or
    // Box<T>
    // For this case, I chose to use T:Copy.
    Empty,
    Elem(T, Rc<RCNode<T>>)
}

struct RCNodeIterator<'a, T: 'a + Copy> {
    node: &'a RCNode<T>,
}

// doubly linked list
enum DLNode<T> {
    Empty,
    Elem(T, Box<DLNode<T>>, Box<DLNode<T>>),
}

impl<'a, T> Iterator for NodeIterator<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        match *self.node {
            Node::Empty => None,
            Node::Elem(ref v, ref next) => {
                self.node = &**next;
                Some(v)
            },
        }
    }
}

impl<'a, T: Copy> Iterator for RCNodeIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        match *self.node {
            RCNode::Empty => None,
            RCNode::Elem(ref v, ref next) => {
                self.node = &**next;
                Some(v)
            },
        }
    }
}

impl<T> Node<T> {
    pub fn len(&self) -> usize {
        match self {
            &Node::Empty => 0,
            &Node::Elem(_, ref boxed) => 1 + boxed.len(),
        }
    }

    pub fn prepend(self, v: T) -> Node<T> {
        // TODO - this one does not borrow self.
        return Node::Elem(
            v,
            Box::new(self),
        );
    }

    pub fn iter<'a>(&'a self) -> NodeIterator<'a, T> {
        // lifetime needs to be propagated.
        return NodeIterator {
            node: self,
        };
    }
}

impl<T:Copy> RCNode<T> {
    pub fn len(&self) -> usize {
        match self {
            &RCNode::Empty => 0,
            &RCNode::Elem(_, ref rc) => 1 + rc.len(),
        }
    }

    pub fn prepend(&self, v: T) -> RCNode<T> {
        // notice "borrow" here.
        return RCNode::Elem(
            v,
            Rc::new(self.clone())
        )
    }

    pub fn iter<'a>(&'a self) -> RCNodeIterator<'a, T> {
        // lifetime needs to be propagated.
        return RCNodeIterator {
            node: self,
        };
    }
}

impl<T> DLNode<T> {
    pub fn len(&self) -> usize {
        match self {
            &DLNode::Empty => 0,
            &DLNode::Elem(_, _, ref next) => 1 + next.len(),
        }
    }
}

#[cfg(test)]
mod tests {
    use linkedlist::Node;
    use linkedlist::RCNode;
    use linkedlist::DLNode;
    use std::rc::Rc;

    #[test]
    fn test_simple() {
        assert_eq!(Node::Empty::<i32>.len(), 0);
        assert_eq!(Node::Elem(32, Box::new(Node::Empty)).len(), 1);
        assert_eq!(Node::Elem(32, Box::new(Node::Elem(10, Box::new(Node::Empty)))).len(), 2);
    }

    #[test]
    fn test_rcnode_simple() {
        assert_eq!(RCNode::Empty::<i32>.len(), 0);
        assert_eq!(RCNode::Elem(1, Rc::new(RCNode::Empty)).len(), 1);
    }

    #[test]
    fn test_dlnode_simple() {
        assert_eq!(DLNode::Empty::<i32>.len(), 0);

    }

    #[test]
    fn test_prepend() {
        let n1 = Node::Empty::<i32>;
        let n2 = n1.prepend(1);
        let n3 = n2.prepend(2);
        let n4 = n3.prepend(3);
        assert_eq!(n4.len(), 3);
        let mut it = n4.iter();
        assert_eq!(it.next(), Some(3).as_ref());
        assert_eq!(it.next(), Some(2).as_ref());
        assert_eq!(it.next(), Some(1).as_ref());
        assert_eq!(it.next(), None);
    }

    #[test]
    fn test_rcnode_prepend() {
        let n1 = RCNode::Empty;
        let n2 = n1.prepend(1);
        match n2 {
            RCNode::Elem(_, ref next) => assert_eq!(Rc::strong_count(next), 1),
            RCNode::Empty => assert!(false),
        }
        let n3 = n2.prepend(2);
        match n2 {
            RCNode::Elem(_, ref next) => assert_eq!(Rc::strong_count(next), 2),
            RCNode::Empty => assert!(false),
        }
        let n4 = n3.prepend(3);
        assert_eq!(n4.len(), 3);
        assert_eq!(n1.len(), 0); // this can be called as prepend does not move.
        let mut it = n4.iter();
        assert_eq!(it.next(), Some(3).as_ref());
        assert_eq!(it.next(), Some(2).as_ref());
        assert_eq!(it.next(), Some(1).as_ref());
        assert_eq!(it.next(), None);
    }

    #[test]
    fn test_build_iterative() {
        let mut n = Node::Empty;
        n = n.prepend(1);
        n = n.prepend(2);
        n = n.prepend(3);
        n = n.prepend(4);
        assert_eq!(n.len(), 4);
    }
}<commit_msg>Remove DLNode<commit_after>// linked list implementation in rust
use std::rc::Rc;

// implementing linked list via pointers.
#[derive(Debug)]
enum Node<T> {
    Empty,
    Elem(T, Box<Node<T>>)
}

struct NodeIterator<'a, T: 'a> {
    // whenever a struct has a reference as its field
    // it needs a lifetime specifier.
    node: &'a Node<T>,
}

// implementing linked list via reference counting pointers.
#[derive(Debug, Clone)]
enum RCNode<T: Copy> {
    // in order to have multiple reference, we either need:
    // T:Copy, or
    // Box<T>
    // For this case, I chose to use T:Copy.
    Empty,
    Elem(T, Rc<RCNode<T>>)
}

struct RCNodeIterator<'a, T: 'a + Copy> {
    node: &'a RCNode<T>,
}

impl<'a, T> Iterator for NodeIterator<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        match *self.node {
            Node::Empty => None,
            Node::Elem(ref v, ref next) => {
                self.node = &**next;
                Some(v)
            },
        }
    }
}

impl<'a, T: Copy> Iterator for RCNodeIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        match *self.node {
            RCNode::Empty => None,
            RCNode::Elem(ref v, ref next) => {
                self.node = &**next;
                Some(v)
            },
        }
    }
}

impl<T> Node<T> {
    pub fn len(&self) -> usize {
        match self {
            &Node::Empty => 0,
            &Node::Elem(_, ref boxed) => 1 + boxed.len(),
        }
    }

    pub fn prepend(self, v: T) -> Node<T> {
        // TODO - this one does not borrow self.
        return Node::Elem(
            v,
            Box::new(self),
        );
    }

    pub fn iter<'a>(&'a self) -> NodeIterator<'a, T> {
        // lifetime needs to be propagated.
        return NodeIterator {
            node: self,
        };
    }
}

impl<T:Copy> RCNode<T> {
    pub fn len(&self) -> usize {
        match self {
            &RCNode::Empty => 0,
            &RCNode::Elem(_, ref rc) => 1 + rc.len(),
        }
    }

    pub fn prepend(&self, v: T) -> RCNode<T> {
        // notice "borrow" here.
        return RCNode::Elem(
            v,
            Rc::new(self.clone())
        )
    }

    pub fn iter<'a>(&'a self) -> RCNodeIterator<'a, T> {
        // lifetime needs to be propagated.
        return RCNodeIterator {
            node: self,
        };
    }
}

#[cfg(test)]
mod tests {
    use linkedlist::Node;
    use linkedlist::RCNode;
    use std::rc::Rc;

    #[test]
    fn test_simple() {
        assert_eq!(Node::Empty::<i32>.len(), 0);
        assert_eq!(Node::Elem(32, Box::new(Node::Empty)).len(), 1);
        assert_eq!(Node::Elem(32, Box::new(Node::Elem(10, Box::new(Node::Empty)))).len(), 2);
    }

    #[test]
    fn test_rcnode_simple() {
        assert_eq!(RCNode::Empty::<i32>.len(), 0);
        assert_eq!(RCNode::Elem(1, Rc::new(RCNode::Empty)).len(), 1);
    }

    #[test]
    fn test_prepend() {
        let n1 = Node::Empty::<i32>;
        let n2 = n1.prepend(1);
        let n3 = n2.prepend(2);
        let n4 = n3.prepend(3);
        assert_eq!(n4.len(), 3);
        let mut it = n4.iter();
        assert_eq!(it.next(), Some(3).as_ref());
        assert_eq!(it.next(), Some(2).as_ref());
        assert_eq!(it.next(), Some(1).as_ref());
        assert_eq!(it.next(), None);
    }

    #[test]
    fn test_rcnode_prepend() {
        let n1 = RCNode::Empty;
        let n2 = n1.prepend(1);
        match n2 {
            RCNode::Elem(_, ref next) => assert_eq!(Rc::strong_count(next), 1),
            RCNode::Empty => assert!(false),
        }
        let n3 = n2.prepend(2);
        match n2 {
            RCNode::Elem(_, ref next) => assert_eq!(Rc::strong_count(next), 2),
            RCNode::Empty => assert!(false),
        }
        let n4 = n3.prepend(3);
        assert_eq!(n4.len(), 3);
        assert_eq!(n1.len(), 0); // this can be called as prepend does not move.
        let mut it = n4.iter();
        assert_eq!(it.next(), Some(3).as_ref());
        assert_eq!(it.next(), Some(2).as_ref());
        assert_eq!(it.next(), Some(1).as_ref());
        assert_eq!(it.next(), None);
    }

    #[test]
    fn test_build_iterative() {
        let mut n = Node::Empty;
        n = n.prepend(1);
        n = n.prepend(2);
        n = n.prepend(3);
        n = n.prepend(4);
        assert_eq!(n.len(), 4);
    }
}<|endoftext|>


<commit_before>use std::f32::consts;

static RAD : f32 = 3.14;

fn get_radius() -> Option<f32> {
Some(3.45)
}

fn main() {
let rad = get_radius().unwrap_or(RAD);
println!("The Area of Circle is {:?} (m)^2",consts::PI*rad*rad);
}
<commit_msg>refactored method inside mod<commit_after>use std::f32::consts;
static RAD : f32 = 3.14;

mod circle_util {
pub fn get_radius() -> Option<f32> {
Some(3.45)
}

}

fn main() {
let rad = ::circle_util::get_radius().unwrap_or(RAD);
println!("The Area of Circle is {:?} (m)^2",consts::PI*rad*rad);

println!("{:?}",u32::from_str_radix(&"34",10).unwrap());

}
<|endoftext|>


<commit_before>extern crate base32;
extern crate ci_capnp;
extern crate lz4;
extern crate num_cpus;
extern crate sha2;
extern crate tempfile;
extern crate thread_pool;

use std::fs;
use std::io;

use sha2::Digest;

use std::ascii::AsciiExt;
use std::io::Read;
use std::io::Write;

fn tools() -> (
    sha2::Sha256,
    lz4::EncoderBuilder,
) {
    (
        sha2::Sha256::default(),
        lz4::EncoderBuilder::new(),
    )
}

fn hash_compress_write_from_slice<W>(buf: &[u8], to: W) -> [u8; 256 / 8]
    where W: Write {
    let (mut hasher, lz4) = tools();
    let mut lz4 = lz4.build(to).expect("lz4 writer");

    hasher.input(buf);
    lz4.write_all(buf).expect("lz4 writing");
    lz4.finish();

    to_bytes(&hasher.result()[..])
}

fn hash_compress_write_from_reader<R, W>(mut from: R, to: W) -> (u64, [u8; 256 / 8])
    where W: Write,
          R: Read
{
    let (mut hasher, lz4) = tools();
    let mut lz4 = lz4.build(to).expect("lz4 writer");

    let mut total_read = 0u64;
    loop {
        let mut buf = [0u8; 4096 * 16];

        let read = from.read(&mut buf).expect("reading");
        if 0 == read {
            break
        }

        total_read += read as u64;

        hasher.input(&buf[0..read]);
        lz4.write_all(&buf[0..read]).expect("lz4 written");
    }
    let (_, result) = lz4.finish();
    result.expect("lz4 finished");

    (total_read, to_bytes(&hasher.result()[..]))
}

fn to_bytes(slice: &[u8]) -> [u8; 256 / 8] {
    let mut hash = [0u8; 256 / 8];
    hash.clone_from_slice(slice);
    hash
}

fn main() {
    let args = std::env::args().collect::<Vec<String>>();
    assert_eq!(2, args.len());
    let out_dir = args[1].to_string();

    {
        let alphabet_chars = "abcdefghijklmnopqrstuvwxyz234567";
        for first in alphabet_chars.chars() {
            for second in alphabet_chars.chars() {
                fs::create_dir_all(format!("{}/{}{}", out_dir, first, second)).expect("intermediate dir");
            }
        }
    }

    let (sender, pool) = thread_pool::Builder::new()
        .work_queue_capacity(num_cpus::get() * 2)
        .build();

    let mut stdin = io::stdin();
    while let Some(en) = ci_capnp::read_entry(&mut stdin).expect("capnp") {
        if 0 == en.len {
            continue;
        }

        let mut temp = tempfile::NamedTempFileOptions::new().suffix(".tmp").
            create_in(&out_dir)
            .expect("temp file");

        if en.len < 16 * 1024 * 1024 * 1024 {
            let mut buf = vec![0u8; en.len as usize];
            stdin.read_exact(&mut buf).expect("read");

            let out_dir = out_dir.clone();
            sender.send(move || {

                let hash = hash_compress_write_from_slice(&buf, &mut temp);

                complete(temp, &hash, out_dir.as_str());

            }).expect("offloading");

        } else {

            let file_data = (&mut stdin).take(en.len);
            let (total_read, hash) = hash_compress_write_from_reader(file_data, &mut temp);
            assert_eq!(en.len, total_read);

            complete(temp, &hash, out_dir.as_str());
        }
    }

    pool.shutdown();
    pool.await_termination();
}

fn complete(temp: tempfile::NamedTempFile, hash: &[u8], out_dir: &str) {
    let mut encoded_hash = base32::encode(base32::Alphabet::RFC4648 { padding: false }, hash);
    encoded_hash.make_ascii_lowercase();
    let written_to = format!("{}/{}/1-{}.lz4", out_dir, &encoded_hash[0..2], &encoded_hash[2..]);
    temp.persist(written_to).expect("rename");
}
<commit_msg>16MB, not 16GB<commit_after>extern crate base32;
extern crate ci_capnp;
extern crate lz4;
extern crate num_cpus;
extern crate sha2;
extern crate tempfile;
extern crate thread_pool;

use std::fs;
use std::io;

use sha2::Digest;

use std::ascii::AsciiExt;
use std::io::Read;
use std::io::Write;

fn tools() -> (
    sha2::Sha256,
    lz4::EncoderBuilder,
) {
    (
        sha2::Sha256::default(),
        lz4::EncoderBuilder::new(),
    )
}

fn hash_compress_write_from_slice<W>(buf: &[u8], to: W) -> [u8; 256 / 8]
    where W: Write {
    let (mut hasher, lz4) = tools();
    let mut lz4 = lz4.build(to).expect("lz4 writer");

    hasher.input(buf);
    lz4.write_all(buf).expect("lz4 writing");
    lz4.finish();

    to_bytes(&hasher.result()[..])
}

fn hash_compress_write_from_reader<R, W>(mut from: R, to: W) -> (u64, [u8; 256 / 8])
    where W: Write,
          R: Read
{
    let (mut hasher, lz4) = tools();
    let mut lz4 = lz4.build(to).expect("lz4 writer");

    let mut total_read = 0u64;
    loop {
        let mut buf = [0u8; 4096 * 16];

        let read = from.read(&mut buf).expect("reading");
        if 0 == read {
            break
        }

        total_read += read as u64;

        hasher.input(&buf[0..read]);
        lz4.write_all(&buf[0..read]).expect("lz4 written");
    }
    let (_, result) = lz4.finish();
    result.expect("lz4 finished");

    (total_read, to_bytes(&hasher.result()[..]))
}

fn to_bytes(slice: &[u8]) -> [u8; 256 / 8] {
    let mut hash = [0u8; 256 / 8];
    hash.clone_from_slice(slice);
    hash
}

fn main() {
    let args = std::env::args().collect::<Vec<String>>();
    assert_eq!(2, args.len());
    let out_dir = args[1].to_string();

    {
        let alphabet_chars = "abcdefghijklmnopqrstuvwxyz234567";
        for first in alphabet_chars.chars() {
            for second in alphabet_chars.chars() {
                fs::create_dir_all(format!("{}/{}{}", out_dir, first, second)).expect("intermediate dir");
            }
        }
    }

    let (sender, pool) = thread_pool::Builder::new()
        .work_queue_capacity(num_cpus::get() * 2)
        .build();

    let mut stdin = io::stdin();
    while let Some(en) = ci_capnp::read_entry(&mut stdin).expect("capnp") {
        if 0 == en.len {
            continue;
        }

        let mut temp = tempfile::NamedTempFileOptions::new().suffix(".tmp").
            create_in(&out_dir)
            .expect("temp file");

        if en.len < 16 * 1024 * 1024 {
            let mut buf = vec![0u8; en.len as usize];
            stdin.read_exact(&mut buf).expect("read");

            let out_dir = out_dir.clone();
            sender.send(move || {

                let hash = hash_compress_write_from_slice(&buf, &mut temp);

                complete(temp, &hash, out_dir.as_str());

            }).expect("offloading");

        } else {

            let file_data = (&mut stdin).take(en.len);
            let (total_read, hash) = hash_compress_write_from_reader(file_data, &mut temp);
            assert_eq!(en.len, total_read);

            complete(temp, &hash, out_dir.as_str());
        }
    }

    pool.shutdown();
    pool.await_termination();
}

fn complete(temp: tempfile::NamedTempFile, hash: &[u8], out_dir: &str) {
    let mut encoded_hash = base32::encode(base32::Alphabet::RFC4648 { padding: false }, hash);
    encoded_hash.make_ascii_lowercase();
    let written_to = format!("{}/{}/1-{}.lz4", out_dir, &encoded_hash[0..2], &encoded_hash[2..]);
    temp.persist(written_to).expect("rename");
}
<|endoftext|>


<commit_before>#[cfg(not(target_os = "redox"))]
use libc::{c_char, c_int, link, rename, unlink, O_CLOEXEC, O_CREAT, O_EXCL, O_RDWR};
use std::ffi::CString;
use std::fs::{self, File, OpenOptions};
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::path::Path;
use util;

#[cfg(all(lfs_support, target_os = "linux"))]
use libc::{fstat64 as fstat, open64 as open, stat64 as stat_t};

#[cfg(not(any(all(lfs_support, target_os = "linux"), target_os = "redox")))]
use libc::{fstat, open, stat as stat_t};

#[cfg(target_os = "redox")]
use syscall::{self, fstat, open, Stat as stat_t, O_CLOEXEC, O_CREAT, O_EXCL, O_RDWR};

#[cfg(not(target_os = "redox"))]
#[inline(always)]
pub fn cvt_err(result: c_int) -> io::Result<c_int> {
    if result == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(result)
    }
}

#[cfg(target_os = "redox")]
#[inline(always)]
pub fn cvt_err(result: Result<usize, syscall::Error>) -> io::Result<usize> {
    result.map_err(|err| io::Error::from_raw_os_error(err.errno))
}

// Stolen from std.
pub fn cstr(path: &Path) -> io::Result<CString> {
    CString::new(path.as_os_str().as_bytes())
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "path contained a null"))
}

#[cfg(not(target_os = "redox"))]
pub fn create_named(path: &Path) -> io::Result<File> {
    unsafe {
        let path = cstr(path)?;
        let fd = cvt_err(open(
            path.as_ptr() as *const c_char,
            O_CLOEXEC | O_EXCL | O_RDWR | O_CREAT,
            0o600,
        ))?;
        Ok(FromRawFd::from_raw_fd(fd))
    }
}

#[cfg(target_os = "redox")]
pub fn create_named(path: PathBuf) -> io::Result<File> {
    unsafe {
        let fd = cvt_err(open(
            path.as_os_str().as_bytes(),
            O_CLOEXEC | O_EXCL | O_RDWR | O_CREAT | 0o600,
        ))?;
        Ok(FromRawFd::from_raw_fd(fd))
    }
}

fn create_unlinked(path: &Path) -> io::Result<File> {
    let f = create_named(path)?;
    // don't care whether the path has already been unlinked,
    // but perhaps there are some IO error conditions we should send up?
    let _ = fs::remove_file(path);
    Ok(f)
}

#[cfg(target_os = "linux")]
pub fn create(dir: &Path) -> io::Result<File> {
    use libc::O_TMPFILE;
    match unsafe {
        let path = cstr(dir)?;
        open(
            path.as_ptr() as *const c_char,
            O_CLOEXEC | O_EXCL | O_TMPFILE | O_RDWR,
            0o600,
        )
    } {
        -1 => create_unix(dir),
        fd => Ok(unsafe { FromRawFd::from_raw_fd(fd) }),
    }
}

#[cfg(not(target_os = "linux"))]
pub fn create(dir: &Path) -> io::Result<File> {
    create_unix(dir)
}

fn create_unix(dir: &Path) -> io::Result<File> {
    util::create_helper(dir, ".tmp", "", ::NUM_RAND_CHARS, |path| {
        create_unlinked(&path)
    })
}

unsafe fn stat(fd: RawFd) -> io::Result<stat_t> {
    let mut meta: stat_t = ::std::mem::zeroed();
    cvt_err(fstat(fd, &mut meta))?;
    Ok(meta)
}

pub fn reopen(file: &File, path: &Path) -> io::Result<File> {
    let new_file = OpenOptions::new().read(true).write(true).open(path)?;
    unsafe {
        let old_meta = stat(file.as_raw_fd())?;
        let new_meta = stat(new_file.as_raw_fd())?;
        if old_meta.st_dev != new_meta.st_dev || old_meta.st_ino != new_meta.st_ino {
            return Err(io::Error::new(
                io::ErrorKind::NotFound,
                "original tempfile has been replaced",
            ));
        }
        Ok(new_file)
    }
}

#[cfg(not(target_os = "redox"))]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
    unsafe {
        let old_path = cstr(old_path)?;
        let new_path = cstr(new_path)?;
        if overwrite {
            cvt_err(rename(
                old_path.as_ptr() as *const c_char,
                new_path.as_ptr() as *const c_char,
            ))?;
        } else {
            cvt_err(link(
                old_path.as_ptr() as *const c_char,
                new_path.as_ptr() as *const c_char,
            ))?;
            // Ignore unlink errors. Can we do better?
            // On recent linux, we can use renameat2 to do this atomically.
            let _ = unlink(old_path.as_ptr() as *const c_char);
        }
        Ok(())
    }
}

#[cfg(target_os = "redox")]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
    // XXX implement when possible
    Err(io::Error::from_raw_os_error(syscall::ENOSYS))
}
<commit_msg>Redox: Fix type definition for create_named<commit_after>#[cfg(not(target_os = "redox"))]
use libc::{c_char, c_int, link, rename, unlink, O_CLOEXEC, O_CREAT, O_EXCL, O_RDWR};
use std::ffi::CString;
use std::fs::{self, File, OpenOptions};
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::path::Path;
use util;

#[cfg(all(lfs_support, target_os = "linux"))]
use libc::{fstat64 as fstat, open64 as open, stat64 as stat_t};

#[cfg(not(any(all(lfs_support, target_os = "linux"), target_os = "redox")))]
use libc::{fstat, open, stat as stat_t};

#[cfg(target_os = "redox")]
use syscall::{self, fstat, open, Stat as stat_t, O_CLOEXEC, O_CREAT, O_EXCL, O_RDWR};

#[cfg(not(target_os = "redox"))]
#[inline(always)]
pub fn cvt_err(result: c_int) -> io::Result<c_int> {
    if result == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(result)
    }
}

#[cfg(target_os = "redox")]
#[inline(always)]
pub fn cvt_err(result: Result<usize, syscall::Error>) -> io::Result<usize> {
    result.map_err(|err| io::Error::from_raw_os_error(err.errno))
}

// Stolen from std.
pub fn cstr(path: &Path) -> io::Result<CString> {
    CString::new(path.as_os_str().as_bytes())
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "path contained a null"))
}

#[cfg(not(target_os = "redox"))]
pub fn create_named(path: &Path) -> io::Result<File> {
    unsafe {
        let path = cstr(path)?;
        let fd = cvt_err(open(
            path.as_ptr() as *const c_char,
            O_CLOEXEC | O_EXCL | O_RDWR | O_CREAT,
            0o600,
        ))?;
        Ok(FromRawFd::from_raw_fd(fd))
    }
}

#[cfg(target_os = "redox")]
pub fn create_named(path: &Path) -> io::Result<File> {
    unsafe {
        let fd = cvt_err(open(
            path.as_os_str().as_bytes(),
            O_CLOEXEC | O_EXCL | O_RDWR | O_CREAT | 0o600,
        ))?;
        Ok(FromRawFd::from_raw_fd(fd))
    }
}

fn create_unlinked(path: &Path) -> io::Result<File> {
    let f = create_named(path)?;
    // don't care whether the path has already been unlinked,
    // but perhaps there are some IO error conditions we should send up?
    let _ = fs::remove_file(path);
    Ok(f)
}

#[cfg(target_os = "linux")]
pub fn create(dir: &Path) -> io::Result<File> {
    use libc::O_TMPFILE;
    match unsafe {
        let path = cstr(dir)?;
        open(
            path.as_ptr() as *const c_char,
            O_CLOEXEC | O_EXCL | O_TMPFILE | O_RDWR,
            0o600,
        )
    } {
        -1 => create_unix(dir),
        fd => Ok(unsafe { FromRawFd::from_raw_fd(fd) }),
    }
}

#[cfg(not(target_os = "linux"))]
pub fn create(dir: &Path) -> io::Result<File> {
    create_unix(dir)
}

fn create_unix(dir: &Path) -> io::Result<File> {
    util::create_helper(dir, ".tmp", "", ::NUM_RAND_CHARS, |path| {
        create_unlinked(&path)
    })
}

unsafe fn stat(fd: RawFd) -> io::Result<stat_t> {
    let mut meta: stat_t = ::std::mem::zeroed();
    cvt_err(fstat(fd, &mut meta))?;
    Ok(meta)
}

pub fn reopen(file: &File, path: &Path) -> io::Result<File> {
    let new_file = OpenOptions::new().read(true).write(true).open(path)?;
    unsafe {
        let old_meta = stat(file.as_raw_fd())?;
        let new_meta = stat(new_file.as_raw_fd())?;
        if old_meta.st_dev != new_meta.st_dev || old_meta.st_ino != new_meta.st_ino {
            return Err(io::Error::new(
                io::ErrorKind::NotFound,
                "original tempfile has been replaced",
            ));
        }
        Ok(new_file)
    }
}

#[cfg(not(target_os = "redox"))]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
    unsafe {
        let old_path = cstr(old_path)?;
        let new_path = cstr(new_path)?;
        if overwrite {
            cvt_err(rename(
                old_path.as_ptr() as *const c_char,
                new_path.as_ptr() as *const c_char,
            ))?;
        } else {
            cvt_err(link(
                old_path.as_ptr() as *const c_char,
                new_path.as_ptr() as *const c_char,
            ))?;
            // Ignore unlink errors. Can we do better?
            // On recent linux, we can use renameat2 to do this atomically.
            let _ = unlink(old_path.as_ptr() as *const c_char);
        }
        Ok(())
    }
}

#[cfg(target_os = "redox")]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
    // XXX implement when possible
    Err(io::Error::from_raw_os_error(syscall::ENOSYS))
}
<|endoftext|>


<commit_before>//
//
//
use core::iter::range;
use core::iter::{FromIterator,Iterator};
use core::slice::{SlicePrelude,AsSlice,Items,MutItems};
use core::option::{Option,Some,None};
use core::ptr::RawPtr;
use core::num::Int;
use core::ops::{Drop,Index};
use lib::clone::Clone;
use lib::collections::{MutableSeq};

pub struct Vec<T>
{
	data: *mut T,
	size: uint,
	capacity: uint,
}

impl<T> Vec<T>
{
	pub fn new() -> Vec<T>
	{
		Vec::with_capacity(0)
	}
	pub fn with_capacity(size: uint) -> Vec<T>
	{
		Vec {
			data: unsafe { ::memory::heap::alloc_array::<T>( size ) },
			size: 0,
			capacity: size,
		}
	}
	pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T>
	{
		let mut ret = Vec::with_capacity(length);
		for i in range(0, length) {
			ret.push( op(i) );
		}
		ret
	}

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

	pub fn get_mut<'s>(&'s mut self, index: uint) -> &'s mut T
	{
		if index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &mut *self.data.offset(index as int) }
	}
	pub fn iter<'s>(&'s self) -> Items<'s,T>
	{
		self.as_slice().iter()
	}
	pub fn iter_mut<'s>(&'s mut self) -> MutItems<'s,T>
	{
		self.slice_mut().iter_mut()
	}

	fn reserve(&mut self, size: uint)
	{
		let newcap = ::lib::num::round_up(size, 1 << (64-size.leading_zeros()));
		if newcap > self.capacity
		{
			unsafe {
				let newptr = ::memory::heap::alloc_array::<T>( newcap );
				for i in range(0, self.size)
				{
					::core::ptr::write(newptr.offset(i as int), self.move_ent(i as uint));
				}
				if self.capacity > 0 {
					::memory::heap::deallocate( self.data );
				}
				self.data = newptr;
				self.capacity = newcap;
			}
		}
	}

	pub fn slice_mut<'a>(&'a mut self) -> &'a mut [T]
	{
		unsafe { ::core::mem::transmute( ::core::raw::Slice { data: self.data as *const T, len: self.size } ) }
	}

	/// Move out of a slot in the vector, leaving unitialise memory in its place
	unsafe fn move_ent(&mut self, pos: uint) -> T
	{
		::core::ptr::replace(self.data.offset(pos as int), ::core::mem::uninitialized())
	}
}

impl<T:Clone> Vec<T>
{
	pub fn from_elem(size: uint, elem: T) -> Vec<T>
	{
		Vec::from_fn( size, |_| elem.clone() )
	}

	pub fn push_all(&mut self, other: &[T])
	{
		let newlen = self.size + other.len();
		self.reserve(newlen);
		for v in other.iter() {
			self.push(v.clone());
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for Vec<T>
{
	fn drop(&mut self)
	{
		if self.capacity > 0
		{
			unsafe {
				for i in range(0, self.size) {
					*self.get_mut(i) = ::core::mem::uninitialized();
				}
				::memory::heap::deallocate( self.data );
			}
		}
	}
}

impl<T> Index<uint, T> for Vec<T>
{
	fn index<'a>(&'a self, index: &uint) -> &'a T
	{
		if *index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &*self.data.offset(*index as int) }
	}
}

impl<T> ::core::slice::AsSlice<T> for Vec<T>
{
	fn as_slice<'a>(&'a self) -> &'a [T]
	{
		let rawslice = ::core::raw::Slice { data: self.data as *const T, len: self.size };
		unsafe { ::core::mem::transmute( rawslice ) }
	}
}

impl<T> ::core::fmt::Show for Vec<T>
where
	T: ::core::fmt::Show
{
	fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::result::Result<(),::core::fmt::FormatError>
	{
		write!(f, "{}", self.as_slice())
	}
}

impl<T> MutableSeq<T> for Vec<T>
{
	fn push(&mut self, t: T)
	{
		let pos = self.size;
		self.reserve(pos + 1);
		self.size += 1;
		let ptr = self.get_mut(pos);
		unsafe { ::core::ptr::write(ptr, t); }
	}
	fn pop(&mut self) -> Option<T>
	{
		if self.size == 0
		{
			None
		}
		else
		{
			self.size -= 1;
			let pos = self.size;
			Some( unsafe { self.move_ent(pos) } )
		}
	}
}

impl<T> FromIterator<T> for Vec<T>
{
	fn from_iter<IT: Iterator<T>>(mut iterator: IT) -> Vec<T>
	{
		let mut ret = Vec::new();
		for val in iterator
		{
			ret.push(val);
		}
		ret
	}
}

// vim: ft=rust
<commit_msg>Core/Vec - Implement into_iter<commit_after>//
//
//
use core::iter::range;
use core::iter::{FromIterator,Iterator};
use core::slice::{SlicePrelude,AsSlice,Items,MutItems};
use core::option::{Option,Some,None};
use core::ptr::RawPtr;
use core::num::Int;
use core::ops::{Drop,Index};
use lib::clone::Clone;
use lib::collections::{MutableSeq};

pub struct Vec<T>
{
	data: *mut T,
	size: uint,
	capacity: uint,
}

pub struct MoveItems<T>
{
	data: *mut T,
	count: uint,
	ofs: uint,
}

impl<T> Vec<T>
{
	pub fn new() -> Vec<T>
	{
		Vec::with_capacity(0)
	}
	pub fn with_capacity(size: uint) -> Vec<T>
	{
		Vec {
			data: unsafe { ::memory::heap::alloc_array::<T>( size ) },
			size: 0,
			capacity: size,
		}
	}
	pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T>
	{
		let mut ret = Vec::with_capacity(length);
		for i in range(0, length) {
			ret.push( op(i) );
		}
		ret
	}

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

	pub fn get_mut<'s>(&'s mut self, index: uint) -> &'s mut T
	{
		if index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &mut *self.data.offset(index as int) }
	}
	pub fn iter<'s>(&'s self) -> Items<'s,T>
	{
		self.as_slice().iter()
	}
	pub fn iter_mut<'s>(&'s mut self) -> MutItems<'s,T>
	{
		self.slice_mut().iter_mut()
	}
	pub fn into_iter(self) -> MoveItems<T>
	{
		MoveItems {
			data: self.data,
			ofs: 0,
			count: self.size,
		}
	}

	fn reserve(&mut self, size: uint)
	{
		let newcap = ::lib::num::round_up(size, 1 << (64-size.leading_zeros()));
		if newcap > self.capacity
		{
			unsafe {
				let newptr = ::memory::heap::alloc_array::<T>( newcap );
				for i in range(0, self.size)
				{
					::core::ptr::write(newptr.offset(i as int), self.move_ent(i as uint));
				}
				if self.capacity > 0 {
					::memory::heap::deallocate( self.data );
				}
				self.data = newptr;
				self.capacity = newcap;
			}
		}
	}

	pub fn slice_mut<'a>(&'a mut self) -> &'a mut [T]
	{
		unsafe { ::core::mem::transmute( ::core::raw::Slice { data: self.data as *const T, len: self.size } ) }
	}

	/// Move out of a slot in the vector, leaving unitialise memory in its place
	unsafe fn move_ent(&mut self, pos: uint) -> T
	{
		::core::ptr::replace(self.data.offset(pos as int), ::core::mem::uninitialized())
	}
}

impl<T:Clone> Vec<T>
{
	pub fn from_elem(size: uint, elem: T) -> Vec<T>
	{
		Vec::from_fn( size, |_| elem.clone() )
	}

	pub fn push_all(&mut self, other: &[T])
	{
		let newlen = self.size + other.len();
		self.reserve(newlen);
		for v in other.iter() {
			self.push(v.clone());
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for Vec<T>
{
	fn drop(&mut self)
	{
		unsafe {
			for i in range(0, self.size) {
				*self.get_mut(i) = ::core::mem::uninitialized();
			}
			::memory::heap::deallocate( self.data );
		}
	}
}

impl<T> Index<uint, T> for Vec<T>
{
	fn index<'a>(&'a self, index: &uint) -> &'a T
	{
		if *index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &*self.data.offset(*index as int) }
	}
}

impl<T> ::core::slice::AsSlice<T> for Vec<T>
{
	fn as_slice<'a>(&'a self) -> &'a [T]
	{
		let rawslice = ::core::raw::Slice { data: self.data as *const T, len: self.size };
		unsafe { ::core::mem::transmute( rawslice ) }
	}
}

impl<T: ::core::fmt::Show> ::core::fmt::Show for Vec<T>
{
	fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::result::Result<(),::core::fmt::FormatError>
	{
		write!(f, "{}", self.as_slice())
	}
}

impl<T> MutableSeq<T> for Vec<T>
{
	fn push(&mut self, t: T)
	{
		let pos = self.size;
		self.reserve(pos + 1);
		self.size += 1;
		let ptr = self.get_mut(pos);
		unsafe { ::core::ptr::write(ptr, t); }
	}
	fn pop(&mut self) -> Option<T>
	{
		if self.size == 0
		{
			None
		}
		else
		{
			self.size -= 1;
			let pos = self.size;
			Some( unsafe { self.move_ent(pos) } )
		}
	}
}

impl<T> FromIterator<T> for Vec<T>
{
	fn from_iter<IT: Iterator<T>>(mut iterator: IT) -> Vec<T>
	{
		let mut ret = Vec::new();
		for val in iterator
		{
			ret.push(val);
		}
		ret
	}
}

impl<T> MoveItems<T>
{
	fn pop_item(&mut self) -> T
	{
		assert!(self.ofs < self.count);
		let v = unsafe { ::core::ptr::replace(self.data.offset(self.ofs as int), ::core::mem::uninitialized()) };
		self.ofs += 1;
		v
	}
}

impl<T> Iterator<T> for MoveItems<T>
{
	fn next(&mut self) -> Option<T>
	{
		if self.ofs == self.count
		{
			None
		}
		else
		{
			Some( self.pop_item() )
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for MoveItems<T>
{
	fn drop(&mut self)
	{
		for i in range(self.ofs, self.count) {
			self.pop_item();
		}
		unsafe {
			::memory::heap::deallocate( self.data );
		}
	}
}

// vim: ft=rust
<|endoftext|>


<commit_before>// #![feature(scoped)]
// #![feature(collections)]

extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::thread;

use dataflow_join::graph::{GraphTrait, GraphMMap};

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_static::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    // let workers = if let Ok(threads) = args.get_str("<workers>").parse() { threads }
    //               else { panic!("invalid setting for workers: {}", args.get_str("<workers>")) };
    // println!("starting pagerank dataflow with {:?} worker{}", workers, if workers == 1 { "" } else { "s" });
    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_multi(communicators, source);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        pagerank_multi(ProcessCommunicator::new_vector(workers), source);
    }
    else {
        println!("Initializing ThreadCommunicator");
        pagerank_multi(vec![ThreadCommunicator], source);
    };
}

fn pagerank_multi<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn pagerank<C>(communicator: C, filename: String, workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    {   // new scope avoids long borrow on root
        let mut builder = root.new_subgraph();

        // establish the beginnings of a loop,
        // 20 iterations, each time around += 1.
        let (helper, stream) = builder.loop_variable::<(u32, f32)>(RootTimestamp::new(20), Local(1));

        let graph = GraphMMap::<u32>::new(&filename);

        let nodes = graph.nodes();

        let mut src = vec![1.0; nodes / peers as usize];    // local rank accumulation
        let mut dst = vec![0.0; nodes];                     // local rank accumulation

        let mut start = time::precise_time_s();

        // from feedback, place an operator that
        // aggregates and broadcasts ranks along edges.
        let ranks = stream.enable(builder).unary_notify(

            Exchange::new(|x: &(u32, f32)| x.0 as u64),     // 1. how data should be exchanged
            format!("PageRank"),                            // 2. a tasteful, descriptive name
            vec![RootTimestamp::new(0)],                    // 3. indicate an initial capability
            move |input, output, iterator| {                // 4. provide the operator logic

                while let Some((iter, _)) = iterator.next() {

                    // /---- should look familiar! ----\
                    for node in 0..src.len() {
                        src[node] = 0.15 + 0.85 * src[node];
                    }

                    let mut counter = 0u64;
                    for node in 0..src.len() {
                        let edges = graph.edges(index + peers * node);
                        let value = src[node] / edges.len() as f32;
                        for &b in edges {
                            dst[b as usize] += value;
                            counter += 1;
                        }
                    }
                    // \------ end familiar part ------/
                    output.give_at(&iter, dst.drain_temp()
                                             .enumerate()
                                             .filter(|&(_,f)| f != 0.0)
                                             .map(|(u,f)| (u as u32, f)));

                    for _ in 0..graph.nodes() { dst.push(0.0); }

                    println!("iteration {:?}: {}s; processed {} edges", iter, time::precise_time_s() - start, counter);
                    start = time::precise_time_s();
                }

                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        src[node as usize / peers] += rank;
                    }
                }
            }
        );

        let local_index = index as usize % workers;

        let mut acc = vec![0.0; nodes / workers];

        ranks
        // .unary_notify(
        //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
        //     format!("Aggregation"),
        //     vec![],
        //     move |input, output, iterator| {
        //         while let Some((iter, data)) = input.pull() {
        //             iterator.notify_at(&iter);
        //             for (node, rank) in data.drain_temp() {
        //                 acc[node as usize / workers] += rank;
        //             }
        //         }
        //
        //         while let Some((item, _)) = iterator.next() {
        //
        //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
        //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
        //
        //             for _ in 0..(nodes/workers) { acc.push(0.0); }
        //             assert!(acc.len() == nodes/workers);
        //         }
        //     }
        // )
        .connect_loop(helper);
    }

    while root.step() { }
}
<commit_msg>more reporting<commit_after>// #![feature(scoped)]
// #![feature(collections)]

extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::thread;

use dataflow_join::graph::{GraphTrait, GraphMMap};

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_static::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    // let workers = if let Ok(threads) = args.get_str("<workers>").parse() { threads }
    //               else { panic!("invalid setting for workers: {}", args.get_str("<workers>")) };
    // println!("starting pagerank dataflow with {:?} worker{}", workers, if workers == 1 { "" } else { "s" });
    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_multi(communicators, source);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        pagerank_multi(ProcessCommunicator::new_vector(workers), source);
    }
    else {
        println!("Initializing ThreadCommunicator");
        pagerank_multi(vec![ThreadCommunicator], source);
    };
}

fn pagerank_multi<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn pagerank<C>(communicator: C, filename: String, workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    {   // new scope avoids long borrow on root
        let mut builder = root.new_subgraph();

        // establish the beginnings of a loop,
        // 20 iterations, each time around += 1.
        let (helper, stream) = builder.loop_variable::<(u32, f32)>(RootTimestamp::new(20), Local(1));

        let graph = GraphMMap::<u32>::new(&filename);

        let nodes = graph.nodes();

        let mut src = vec![1.0; nodes / peers as usize];    // local rank accumulation
        let mut dst = vec![0.0; nodes];                     // local rank accumulation

        let mut start = time::precise_time_s();

        // from feedback, place an operator that
        // aggregates and broadcasts ranks along edges.
        let ranks = stream.enable(builder).unary_notify(

            Exchange::new(|x: &(u32, f32)| x.0 as u64),     // 1. how data should be exchanged
            format!("PageRank"),                            // 2. a tasteful, descriptive name
            vec![RootTimestamp::new(0)],                    // 3. indicate an initial capability
            move |input, output, iterator| {                // 4. provide the operator logic

                while let Some((iter, _)) = iterator.next() {

                    // /---- should look familiar! ----\
                    for node in 0..src.len() {
                        src[node] = 0.15 + 0.85 * src[node];
                    }

                    let mut counter = 0u64;
                    for node in 0..src.len() {
                        let edges = graph.edges(index + peers * node);
                        let value = src[node] / edges.len() as f32;
                        for &b in edges {
                            dst[b as usize] += value;
                            counter += 1;
                        }
                    }
                    // \------ end familiar part ------/

                    let mut updates = 0u64;
                    for d in dst.iter() { if *d != 0.0 { updates += 1; } }

                    output.give_at(&iter, dst.drain_temp()
                                             .enumerate()
                                             .filter(|&(_,f)| f != 0.0)
                                             .map(|(u,f)| (u as u32, f)));

                    for _ in 0..graph.nodes() { dst.push(0.0); }

                    println!("iteration {:?}: {}s; {} edges; {} updates", iter, time::precise_time_s() - start, counter, updates);
                    start = time::precise_time_s();
                }

                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        src[node as usize / peers] += rank;
                    }
                }
            }
        );

        let local_index = index as usize % workers;

        let mut acc = vec![0.0; nodes / workers];

        ranks
        // .unary_notify(
        //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
        //     format!("Aggregation"),
        //     vec![],
        //     move |input, output, iterator| {
        //         while let Some((iter, data)) = input.pull() {
        //             iterator.notify_at(&iter);
        //             for (node, rank) in data.drain_temp() {
        //                 acc[node as usize / workers] += rank;
        //             }
        //         }
        //
        //         while let Some((item, _)) = iterator.next() {
        //
        //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
        //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
        //
        //             for _ in 0..(nodes/workers) { acc.push(0.0); }
        //             assert!(acc.len() == nodes/workers);
        //         }
        //     }
        // )
        .connect_loop(helper);
    }

    while root.step() { }
}
<|endoftext|>


<commit_before>//! Sources of randomness.

use std::cell::RefCell;
use std::rc::Rc;

/// A source of randomness.
pub trait Generator {
    /// Read the next chunk.
    fn read(&mut self) -> u64;

    /// Read the next quantity.
    #[inline(always)]
    fn next<T: Quantity>(&mut self) -> T {
        Quantity::make(self.read())
    }
}

/// A random quantity.
pub trait Quantity {
    /// Make up a random quantity.
    fn make(u64) -> Self;
}

impl Quantity for f64 {
    #[inline(always)]
    fn make(chunk: u64) -> f64 {
        chunk as f64 / (::std::u64::MAX as f64 + 1.0)
    }
}

impl Quantity for u64 {
    #[inline(always)]
    fn make(chunk: u64) -> u64 {
        chunk
    }
}

/// The default generator, which is the Xorshift+ algorithm.
pub struct Default(Rc<RefCell<XorshiftPlus>>);

impl Default {
    /// Seed the generator.
    #[inline(always)]
    pub fn seed(&mut self, seed: [u64; 2]) -> &mut Default {
        *self.0.borrow_mut() = XorshiftPlus::new(seed);
        self
    }
}

impl Generator for Default {
    #[inline(always)]
    fn read(&mut self) -> u64 {
        self.0.borrow_mut().read()
    }

    #[inline(always)]
    fn next<T: Quantity>(&mut self) -> T {
        self.0.borrow_mut().next()
    }
}

/// Return the default generator.
#[inline(always)]
pub fn default() -> Default {
    thread_local!(static DEFAULT: Rc<RefCell<XorshiftPlus>> = {
        Rc::new(RefCell::new(XorshiftPlus::new([42, 69])))
    });
    Default(DEFAULT.with(|generator| generator.clone()))
}

mod xorshift;

pub use self::xorshift::XorshiftPlus;
<commit_msg>generator: improve the description of default<commit_after>//! Sources of randomness.

use std::cell::RefCell;
use std::rc::Rc;

/// A source of randomness.
pub trait Generator {
    /// Read the next chunk.
    fn read(&mut self) -> u64;

    /// Read the next quantity.
    #[inline(always)]
    fn next<T: Quantity>(&mut self) -> T {
        Quantity::make(self.read())
    }
}

/// A random quantity.
pub trait Quantity {
    /// Make up a random quantity.
    fn make(u64) -> Self;
}

impl Quantity for f64 {
    #[inline(always)]
    fn make(chunk: u64) -> f64 {
        chunk as f64 / (::std::u64::MAX as f64 + 1.0)
    }
}

impl Quantity for u64 {
    #[inline(always)]
    fn make(chunk: u64) -> u64 {
        chunk
    }
}

/// The default generator, which is the Xorshift+ algorithm.
pub struct Default(Rc<RefCell<XorshiftPlus>>);

impl Default {
    /// Seed the generator.
    #[inline(always)]
    pub fn seed(&mut self, seed: [u64; 2]) -> &mut Default {
        *self.0.borrow_mut() = XorshiftPlus::new(seed);
        self
    }
}

impl Generator for Default {
    #[inline(always)]
    fn read(&mut self) -> u64 {
        self.0.borrow_mut().read()
    }

    #[inline(always)]
    fn next<T: Quantity>(&mut self) -> T {
        self.0.borrow_mut().next()
    }
}

/// Return the default generator.
///
/// Each thread has its own copy of the generator, and each copy is initialized
/// with the same default seed. Consequently, the usage is thread safe; however,
/// each thread is responsible for reseeding its default generator.
#[inline(always)]
pub fn default() -> Default {
    thread_local!(static DEFAULT: Rc<RefCell<XorshiftPlus>> = {
        Rc::new(RefCell::new(XorshiftPlus::new([42, 69])))
    });
    Default(DEFAULT.with(|generator| generator.clone()))
}

mod xorshift;

pub use self::xorshift::XorshiftPlus;
<|endoftext|>


<commit_before>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use cpu::common_defs::opcode_class::OpcodeClass;
use memory::Memory;
use std::collections::HashMap;

macro_rules! set_zs {
    ($cpu_state:expr,$val:expr) => ($cpu_state.Z = $val == 0;$cpu_state.S = $val >= 0x80 );
}

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {

	/// Construct a new CpuExecutor.
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

	/// Reset the given cpu_state.
    pub fn power_on(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        self.reset(cpu_state,mem);
    }
	/// Reset the given cpu_state.
    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    /// Execute a single instruction in the given memory and cpu_state context.
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        self.execute(cpu_state,mem);
    }

	/// Fetch the next instruction and perform address resolution.
    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.decode_register = self.decode(cpu_state,mem);
        cpu_state.pc = cpu_state.pc+1;
    }

    /// Perform address resolution, returning the info in a DecodeRegister.
    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let mut dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            // no explicit addresses for the following modes
            AddressMode::Accumulator  => { },
            AddressMode::Implied      => { },

            // explicit addresses from here on out
            AddressMode::Absolute => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteX       => {
                dr.addr_final  = Some( ((mem.read16(cpu_state.pc+1).unwrap() as u32 + cpu_state.x as u32) % 65536) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteY       => {
                dr.addr_final  = Some( ((mem.read16(cpu_state.pc+1).unwrap() as u32 + cpu_state.y as u32) % 65536) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Immediate       => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Indirect        => {
                dr.addr_intermediate = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap());
            },
            AddressMode::IndexedIndirect => {
                dr.addr_intermediate = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap());
                dr.value_final       = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::IndirectIndexed => {
                dr.addr_init         = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.addr_intermediate = Some(mem.read16(dr.addr_init.unwrap()).unwrap());
                dr.addr_final        = Some( ((dr.addr_intermediate.unwrap() as u32 + cpu_state.y as u32) % 65536) as u16);
                dr.value_final       = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Relative        => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPage        => {
                dr.addr_final  = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageX       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() as u16 + cpu_state.x as u16) % 256);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageY       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() as u16 + cpu_state.y as u16) % 256);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }

    /// Perform the current instruction, returning the CpuState after execution.
    pub fn execute(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
    	// Figure out which opcode is being executed.
    	match cpu_state.decode_register.info.opcode_class {
    		OpcodeClass::ASL => {
				cpu_state.a = cpu_state.a << 1;
				cpu_state.C = (128 & cpu_state.a) > 0;
    			if cpu_state.a == 0 { cpu_state.Z = true; }

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LDA => {
    			cpu_state.a = cpu_state.decode_register.value_final.unwrap();
                set_zs!(cpu_state,cpu_state.a);

                //let tup = self.get_zs(cpu_state.a); cpu_state.Z = tup.0; cpu_state.S = tup.1;
                 //match self.get_zs(cpu_state.a) {
                     //(z,s) => { cpu_state.Z = z; cpu_state.S = s;}
                 //}

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LDX => {
    			cpu_state.x = cpu_state.decode_register.value_final.unwrap();
                set_zs!(cpu_state,cpu_state.x);

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LDY => {
    			cpu_state.y = cpu_state.decode_register.value_final.unwrap();
                set_zs!(cpu_state,cpu_state.y);

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LSR => {
    			cpu_state.a = cpu_state.a >> 1;
    			cpu_state.C = 1 & cpu_state.a > 0;
    			if cpu_state.a == 0 { cpu_state.Z = true; }

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::JMP => {
    			cpu_state.pc = cpu_state.decode_register.addr_final.unwrap();
    		},
    		OpcodeClass::NOP => {},
    		OpcodeClass::STX => {
                mem.write8(cpu_state.decode_register.addr_final.unwrap(),cpu_state.decode_register.value_final.unwrap());
                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},

    		// Default: not sure what this opcode is.
			_ => panic!("Unrecognised opcode class: {:?}", cpu_state.decode_register.info.opcode_class)

    	}
    }
}

<commit_msg>removed erroneous comment<commit_after>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use cpu::common_defs::opcode_class::OpcodeClass;
use memory::Memory;
use std::collections::HashMap;

macro_rules! set_zs {
    ($cpu_state:expr,$val:expr) => ($cpu_state.Z = $val == 0;$cpu_state.S = $val >= 0x80 );
}

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {

	/// Construct a new CpuExecutor.
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

	/// Reset the given cpu_state.
    pub fn power_on(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        self.reset(cpu_state,mem);
    }
	/// Reset the given cpu_state.
    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    /// Execute a single instruction in the given memory and cpu_state context.
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        self.execute(cpu_state,mem);
    }

	/// Fetch the next instruction and perform address resolution.
    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.decode_register = self.decode(cpu_state,mem);
        cpu_state.pc = cpu_state.pc+1;
    }

    /// Perform address resolution, returning the info in a DecodeRegister.
    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let mut dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            // no explicit addresses for the following modes
            AddressMode::Accumulator  => { },
            AddressMode::Implied      => { },

            // explicit addresses from here on out
            AddressMode::Absolute => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteX       => {
                dr.addr_final  = Some( ((mem.read16(cpu_state.pc+1).unwrap() as u32 + cpu_state.x as u32) % 65536) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteY       => {
                dr.addr_final  = Some( ((mem.read16(cpu_state.pc+1).unwrap() as u32 + cpu_state.y as u32) % 65536) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Immediate       => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Indirect        => {
                dr.addr_intermediate = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap());
            },
            AddressMode::IndexedIndirect => {
                dr.addr_intermediate = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap());
                dr.value_final       = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::IndirectIndexed => {
                dr.addr_init         = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.addr_intermediate = Some(mem.read16(dr.addr_init.unwrap()).unwrap());
                dr.addr_final        = Some( ((dr.addr_intermediate.unwrap() as u32 + cpu_state.y as u32) % 65536) as u16);
                dr.value_final       = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Relative        => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPage        => {
                dr.addr_final  = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageX       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() as u16 + cpu_state.x as u16) % 256);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageY       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() as u16 + cpu_state.y as u16) % 256);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }

    /// Perform the current instruction, returning the CpuState after execution.
    pub fn execute(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
    	// Figure out which opcode is being executed.
    	match cpu_state.decode_register.info.opcode_class {
    		OpcodeClass::ASL => {
				cpu_state.a = cpu_state.a << 1;
				cpu_state.C = (128 & cpu_state.a) > 0;
    			if cpu_state.a == 0 { cpu_state.Z = true; }

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LDA => {
    			cpu_state.a = cpu_state.decode_register.value_final.unwrap();
                set_zs!(cpu_state,cpu_state.a);

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LDX => {
    			cpu_state.x = cpu_state.decode_register.value_final.unwrap();
                set_zs!(cpu_state,cpu_state.x);

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LDY => {
    			cpu_state.y = cpu_state.decode_register.value_final.unwrap();
                set_zs!(cpu_state,cpu_state.y);

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::LSR => {
    			cpu_state.a = cpu_state.a >> 1;
    			cpu_state.C = 1 & cpu_state.a > 0;
    			if cpu_state.a == 0 { cpu_state.Z = true; }

                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},
    		OpcodeClass::JMP => {
    			cpu_state.pc = cpu_state.decode_register.addr_final.unwrap();
    		},
    		OpcodeClass::NOP => {},
    		OpcodeClass::STX => {
                mem.write8(cpu_state.decode_register.addr_final.unwrap(),cpu_state.decode_register.value_final.unwrap());
                cpu_state.pc = cpu_state.pc + (cpu_state.decode_register.info.len as u16 -1);
    		},

    		// Default: not sure what this opcode is.
			_ => panic!("Unrecognised opcode class: {:?}", cpu_state.decode_register.info.opcode_class)

    	}
    }
}

<|endoftext|>


<commit_before>use linalg::vector::Vector;
use linalg::matrix::Matrix;

use learning::UnSupModel;

pub const SQRT_2_PI: f64 = 2.50662827463100050241576528481104525_f64;

/// A gaussian mixture model
///
/// Currently contains it's own parameters.
/// In future we should construct a finite
/// mixture model and have the GaussianMixtureModel
/// own this.
pub struct GaussianMixtureModel {
    comp_count: usize,
    mix_weights: Vector<f64>,
    model_means: Matrix<f64>,
    model_covars: Vec<Matrix<f64>>,
}

impl UnSupModel<Matrix<f64>, Matrix<f64>> for GaussianMixtureModel {
    /// Train the model using inputs.
    fn train(&mut self, inputs: &Matrix<f64>) {
    	// Need to do initialization

    	for _ in 0..10 {
    		let weights = self.membership_weights(inputs);
    		self.update_params(inputs, weights);
    	}
    }

    /// Predict output from inputs.
    fn predict(&self, inputs: &Matrix<f64>) -> Matrix<f64> {
        self.membership_weights(inputs)
    }
}

impl GaussianMixtureModel {
    fn membership_weights(&self, inputs: &Matrix<f64>) -> Matrix<f64> {
        let d = self.model_means.cols();
        let n = inputs.rows();

        let pi_d = SQRT_2_PI.powi(d as i32);

        let mut member_weights_data = Vec::with_capacity(n * self.comp_count);

        // We compute the determinants and inverses now
        let mut cov_sqrt_dets = Vec::with_capacity(self.comp_count);
        let mut cov_invs = Vec::with_capacity(self.comp_count);

        for k in 0..self.comp_count {
            // TODO: combine these. We compute det to get the inverse.
            let covar_det = self.model_covars[k].det();
            let covar_inv = self.model_covars[k].inverse();

            cov_sqrt_dets.push(covar_det.sqrt());
            cov_invs.push(covar_inv);
        }

        // Now we compute the membership weights
        for i in 0..n {
            for k in 0..self.comp_count {

                let mut pdf_inv_sum = 0f64;
                let x_i = inputs.select_rows(&[i]);

                for j in 0..self.comp_count {
                    if j == k {
                        continue;
                    }

                    let mu_j = self.model_means.select_rows(&[j]);
                    let diff = &x_i - mu_j;

                    // diff is 1xd
                    let exponent = (&diff * &cov_invs[j] * diff.transpose() * 0.5).into_vec()[0];

                    pdf_inv_sum += exponent.exp() * cov_sqrt_dets[j] / self.mix_weights[j];
                }

                member_weights_data.push(self.mix_weights[k] * pi_d * pdf_inv_sum);
            }
        }

        Matrix::new(n, self.comp_count, member_weights_data)
    }

    fn update_params(&mut self, inputs: &Matrix<f64>, membership_weights: Matrix<f64>) {
        let n = membership_weights.rows();
        let d = membership_weights.cols();

        let sum_weights = membership_weights.sum_rows();

        self.mix_weights = &sum_weights / (n as f64);

        let mut new_means = membership_weights.transpose() * inputs;

        for (idx, mean) in new_means.mut_data().chunks_mut(d).enumerate() {
            for i in 0..d {
                mean[i] = mean[i] / sum_weights[idx];
            }
        }

        self.model_means = new_means;

        for k in 0..self.comp_count {
            let mut cov_mat = Matrix::zeros(d, d);

            for i in 0..n {
                let diff = inputs.select_rows(&[i]) - self.model_means.select_rows(&[k]);
                cov_mat = cov_mat + (diff.transpose() * diff) * membership_weights[[i, k]];
            }

            self.model_covars[k] = cov_mat / sum_weights[k];
        }

    }
}
<commit_msg>Fixing to use options for model parameters<commit_after>use linalg::vector::Vector;
use linalg::matrix::Matrix;

use learning::UnSupModel;

pub const SQRT_2_PI: f64 = 2.50662827463100050241576528481104525_f64;

/// A gaussian mixture model
///
/// Currently contains it's own parameters.
/// In future we should construct a finite
/// mixture model and have the GaussianMixtureModel
/// own this.
pub struct GaussianMixtureModel {
    comp_count: usize,
    mix_weights: Vector<f64>,
    model_means: Option<Matrix<f64>>,
    model_covars: Option<Vec<Matrix<f64>>>,
}

impl UnSupModel<Matrix<f64>, Matrix<f64>> for GaussianMixtureModel {
    /// Train the model using inputs.
    fn train(&mut self, inputs: &Matrix<f64>) {
        // Initialization:
        let k = self.comp_count;

        // TODO: Compute sample covariance of the data.
        // https://en.wikipedia.org/wiki/Sample_mean_and_covariance#Sample_covariance
        let mut cov_vec = Vec::with_capacity(k);
        for _ in 0..k {
            cov_vec.push(Matrix::identity(inputs.cols()));
        }

        self.model_covars = Some(cov_vec);

        // TODO: Use randomization, or k-means.
        self.model_means = Some(inputs.select_rows(&(0..k).collect::<Vec<usize>>()[..]));

        for _ in 0..10 {
            let weights = self.membership_weights(inputs);
            self.update_params(inputs, weights);
        }
    }

    /// Predict output from inputs.
    fn predict(&self, inputs: &Matrix<f64>) -> Matrix<f64> {
        if let (&Some(_), &Some(_)) = (&self.model_means, &self.model_covars) {
            self.membership_weights(inputs)
        } else {
            panic!("Model has not been trained.");
        }

    }
}

impl GaussianMixtureModel {
    pub fn new(k: usize) -> GaussianMixtureModel {
        GaussianMixtureModel {
            comp_count: k,
            mix_weights: Vector::ones(k) / (k as f64),
            model_means: None,
            model_covars: None,
        }
    }

    fn membership_weights(&self, inputs: &Matrix<f64>) -> Matrix<f64> {
        let d = inputs.cols();
        let n = inputs.rows();

        let pi_d = SQRT_2_PI.powi(d as i32);

        let mut member_weights_data = Vec::with_capacity(n * self.comp_count);

        // We compute the determinants and inverses now
        let mut cov_sqrt_dets = Vec::with_capacity(self.comp_count);
        let mut cov_invs = Vec::with_capacity(self.comp_count);

        if let Some(ref covars) = self.model_covars {
	        for k in 0..self.comp_count {
	            // TODO: combine these. We compute det to get the inverse.
	            let covar_det = covars[k].det();
	            let covar_inv = covars[k].inverse();

	            cov_sqrt_dets.push(covar_det.sqrt());
	            cov_invs.push(covar_inv);
	        }
	    }

        // Now we compute the membership weights
        if let Some(ref means) = self.model_means {
	        for i in 0..n {
	            for k in 0..self.comp_count {

	                let mut pdf_inv_sum = 0f64;
	                let x_i = inputs.select_rows(&[i]);

	                for j in 0..self.comp_count {
	                    if j == k {
	                        continue;
	                    }

	                    let mu_j = means.select_rows(&[j]);
	                    let diff = &x_i - mu_j;

	                    // diff is 1 x d
	                    let exponent = (&diff * &cov_invs[j] * diff.transpose() * 0.5).into_vec()[0];

	                    pdf_inv_sum += exponent.exp() * cov_sqrt_dets[j] / self.mix_weights[j];
	                }

	                member_weights_data.push(self.mix_weights[k] * pi_d * pdf_inv_sum);
	            }
	        }
	    }

        Matrix::new(n, self.comp_count, member_weights_data)
    }

    fn update_params(&mut self, inputs: &Matrix<f64>, membership_weights: Matrix<f64>) {
        let n = membership_weights.rows();
        let d = membership_weights.cols();

        let sum_weights = membership_weights.sum_rows();

        self.mix_weights = &sum_weights / (n as f64);

        let mut new_means = membership_weights.transpose() * inputs;

        // TODO: Optimize
        for (idx, mean) in new_means.mut_data().chunks_mut(d).enumerate() {
            for i in 0..d {
                mean[i] = mean[i] / sum_weights[idx];
            }
        }

        let mut new_covs = Vec::with_capacity(self.comp_count);

        // TODO: Optimize
        for k in 0..self.comp_count {
            let mut cov_mat = Matrix::zeros(d, d);

            for i in 0..n {
                let diff = inputs.select_rows(&[i]) - new_means.select_rows(&[k]);
                cov_mat = cov_mat + (diff.transpose() * diff) * membership_weights[[i, k]];
            }

            new_covs.push(cov_mat / sum_weights[k]);
        }

        self.model_means = Some(new_means);
        self.model_covars = Some(new_covs);
    }
}
<|endoftext|>