<commit_before>//! Simple script to verify the coding style of this library
//!
//! ## How to run
//!
//! The first argument to this script is the directory to run on, so running
//! this script should be as simple as:
//!
//! ```notrust
//! rustc ci/style.rs
//! ./style src
//! ```
//!
//! ## Guidelines
//!
//! The current style is:
//!
//! * Specific module layout:
//!     1. use directives
//!     2. typedefs
//!     3. structs
//!     4. constants
//!     5. f! { ... } functions
//!     6. extern functions
//!     7. modules + pub use
//!
//! Things not verified:
//!
//! * alignment
//! * leading colons on paths

use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let arg = env::args().skip(1).next().unwrap_or(".".to_string());

    let mut errors = Errors { errs: false };
    walk(Path::new(&arg), &mut errors);

    if errors.errs {
        panic!("found some lint errors");
    } else {
        println!("good style!");
    }
}

fn walk(path: &Path, err: &mut Errors) {
    for entry in t!(path.read_dir()).map(|e| t!(e)) {
        let path = entry.path();
        if t!(entry.file_type()).is_dir() {
            walk(&path, err);
            continue
        }

        let name = entry.file_name().into_string().unwrap();
        match &name[..] {
            n if !n.ends_with(".rs") => continue,

            "lib.rs" |
            "macros.rs" => continue,

            _ => {}
        }

        let mut contents = String::new();
        t!(t!(fs::File::open(&path)).read_to_string(&mut contents));

        check_style(&contents, &path, err);
    }
}

struct Errors {
    errs: bool,
}

#[derive(Clone, Copy, PartialEq)]
enum State {
    Start,
    Imports,
    Typedefs,
    Structs,
    Constants,
    FunctionDefinitions,
    Functions,
    Modules,
}

fn check_style(file: &str, path: &Path, err: &mut Errors) {
    let mut state = State::Start;
    let mut s_macros = 0;
    let mut f_macros = 0;
    let mut in_impl = false;

    for (i, line) in file.lines().enumerate() {
        if line.contains("#[cfg(") && line.contains(']') && !line.contains(" if ")
            && !(line.contains("target_endian") ||
                 line.contains("target_arch"))
        {
            if state != State::Structs {
                err.error(path, i, "use cfg_if! and submodules \
                                    instead of #[cfg]");
            }
        }
        if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) {
            err.error(path, i, "impl ::Copy and ::Clone manually");
        }
        if line.contains("impl") {
            in_impl = true;
        }
        if in_impl && line.starts_with('}') {
            in_impl = false;
        }

        let orig_line = line;
        let line = line.trim_start();
        let is_pub = line.starts_with("pub ");
        let line = if is_pub {&line[4..]} else {line};

        let line_state = if line.starts_with("use ") {
            if line.contains("c_void") {
                continue;
            }
            if is_pub {
                State::Modules
            } else {
                State::Imports
            }
        } else if line.starts_with("const ") {
            State::Constants
        } else if line.starts_with("type ") && !in_impl {
            State::Typedefs
        } else if line.starts_with("s! {") {
            s_macros += 1;
            State::Structs
        } else if line.starts_with("f! {") {
            f_macros += 1;
            State::FunctionDefinitions
        } else if line.starts_with("extern ") && !orig_line.starts_with(" ") {
            State::Functions
        } else if line.starts_with("mod ") {
            State::Modules
        } else {
            continue
        };

        if state as usize > line_state as usize {
            err.error(path, i, &format!("{} found after {} when \
                                         it belongs before",
                                        line_state.desc(), state.desc()));
        }

        if f_macros == 2 {
            f_macros += 1;
            err.error(path, i, "multiple f! macros in one module");
        }
        if s_macros == 2 {
            s_macros += 1;
            err.error(path, i, "multiple s! macros in one module");
        }

        state = line_state;
    }
}

impl State {
    fn desc(&self) -> &str {
        match *self {
            State::Start => "start",
            State::Imports => "import",
            State::Typedefs => "typedef",
            State::Structs => "struct",
            State::Constants => "constant",
            State::FunctionDefinitions => "function definition",
            State::Functions => "extern function",
            State::Modules => "module",
        }
    }
}

impl Errors {
    fn error(&mut self, path: &Path, line: usize, msg: &str) {
        self.errs = true;
        println!("{}:{} - {}", path.display(), line + 1, msg);
    }
}
<commit_msg>Format style checker<commit_after>//! Simple script to verify the coding style of this library
//!
//! ## How to run
//!
//! The first argument to this script is the directory to run on, so running
//! this script should be as simple as:
//!
//! ```notrust
//! rustc ci/style.rs
//! ./style src
//! ```
//!
//! ## Guidelines
//!
//! The current style is:
//!
//! * Specific module layout:
//!     1. use directives
//!     2. typedefs
//!     3. structs
//!     4. constants
//!     5. f! { ... } functions
//!     6. extern functions
//!     7. modules + pub use
//!
//! Things not verified:
//!
//! * alignment
//! * leading colons on paths

use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

fn main() {
    let arg = env::args().skip(1).next().unwrap_or(".".to_string());

    let mut errors = Errors { errs: false };
    walk(Path::new(&arg), &mut errors);

    if errors.errs {
        panic!("found some lint errors");
    } else {
        println!("good style!");
    }
}

fn walk(path: &Path, err: &mut Errors) {
    for entry in t!(path.read_dir()).map(|e| t!(e)) {
        let path = entry.path();
        if t!(entry.file_type()).is_dir() {
            walk(&path, err);
            continue;
        }

        let name = entry.file_name().into_string().unwrap();
        match &name[..] {
            n if !n.ends_with(".rs") => continue,

            "lib.rs" | "macros.rs" => continue,

            _ => {}
        }

        let mut contents = String::new();
        t!(t!(fs::File::open(&path)).read_to_string(&mut contents));

        check_style(&contents, &path, err);
    }
}

struct Errors {
    errs: bool,
}

#[derive(Clone, Copy, PartialEq)]
enum State {
    Start,
    Imports,
    Typedefs,
    Structs,
    Constants,
    FunctionDefinitions,
    Functions,
    Modules,
}

fn check_style(file: &str, path: &Path, err: &mut Errors) {
    let mut state = State::Start;
    let mut s_macros = 0;
    let mut f_macros = 0;
    let mut in_impl = false;

    for (i, line) in file.lines().enumerate() {
        if line.contains("#[cfg(")
            && line.contains(']')
            && !line.contains(" if ")
            && !(line.contains("target_endian") || line.contains("target_arch"))
        {
            if state != State::Structs {
                err.error(path, i, "use cfg_if! and submodules instead of #[cfg]");
            }
        }
        if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) {
            err.error(path, i, "impl ::Copy and ::Clone manually");
        }
        if line.contains("impl") {
            in_impl = true;
        }
        if in_impl && line.starts_with('}') {
            in_impl = false;
        }

        let orig_line = line;
        let line = line.trim_start();
        let is_pub = line.starts_with("pub ");
        let line = if is_pub { &line[4..] } else { line };

        let line_state = if line.starts_with("use ") {
            if line.contains("c_void") {
                continue;
            }
            if is_pub {
                State::Modules
            } else {
                State::Imports
            }
        } else if line.starts_with("const ") {
            State::Constants
        } else if line.starts_with("type ") && !in_impl {
            State::Typedefs
        } else if line.starts_with("s! {") {
            s_macros += 1;
            State::Structs
        } else if line.starts_with("f! {") {
            f_macros += 1;
            State::FunctionDefinitions
        } else if line.starts_with("extern ") && !orig_line.starts_with(" ") {
            State::Functions
        } else if line.starts_with("mod ") {
            State::Modules
        } else {
            continue;
        };

        if state as usize > line_state as usize {
            err.error(
                path,
                i,
                &format!(
                    "{} found after {} when it belongs before",
                    line_state.desc(),
                    state.desc()
                ),
            );
        }

        if f_macros == 2 {
            f_macros += 1;
            err.error(path, i, "multiple f! macros in one module");
        }
        if s_macros == 2 {
            s_macros += 1;
            err.error(path, i, "multiple s! macros in one module");
        }

        state = line_state;
    }
}

impl State {
    fn desc(&self) -> &str {
        match *self {
            State::Start => "start",
            State::Imports => "import",
            State::Typedefs => "typedef",
            State::Structs => "struct",
            State::Constants => "constant",
            State::FunctionDefinitions => "function definition",
            State::Functions => "extern function",
            State::Modules => "module",
        }
    }
}

impl Errors {
    fn error(&mut self, path: &Path, line: usize, msg: &str) {
        self.errs = true;
        println!("{}:{} - {}", path.display(), line + 1, msg);
    }
}
<|endoftext|>


<commit_before>use super::allocators::{Allocator, DefaultHeap};
use super::compact::Compact;
use super::compact_vec::CompactVec;
use super::compact_dict::CompactDict;
use super::compact_array::CompactArray;
use std::iter::Iterator;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::hash::Hash;
use std::marker::PhantomData;

#[derive(Clone)]
struct Entry<K: Copy + Hash + Eq, V: Compact + Clone> {
    key: K,
    hash: u64,
    value: V,
    used: bool,
}

impl<K: Copy + Hash + Eq, V: Compact + Clone> Compact for Entry<K, V> {
    fn is_still_compact(&self) -> bool {
        self.value.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.value.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.value.compact_from(&source.value, new_dynamic_part);
    }

    unsafe fn decompact(&self) -> Entry<K, V> {
        Entry {
            key: self.key.clone(),
            value: self.value.decompact(),
            hash: self.hash,
            used: self.used
        }
    }
}

struct OpenAddressingMap<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator = DefaultHeap> {
    size: usize,
    entries: CompactArray<Entry<K, V>, A>,
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> OpenAddressingMap<K, V, A> {
    pub fn new() -> Self {
        Self::with_capacity(100)
    }
    pub fn with_capacity(l: usize) -> Self {
        OpenAddressingMap {
            entries: CompactArray::with_capacity(l),
            size: l,
        }
    }

    /// Amount of entries in the dictionary
    pub fn len(&self) -> usize {
        self.size
    }

    /// Is the dictionary empty?
    pub fn is_empty(&self) -> bool {
        self.size == 0
    }

    /// Look up the value for key `query`, if it exists
    pub fn get(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mru(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mfu(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mut(&mut self, query: K) -> Option<&mut V> {
        self.get_inner_mut(query).map(|e|{& mut e.value})
    }

    /// Does the dictionary contain a value for `query`?
    pub fn contains_key(&self, query: K) -> bool {
        self.get(query).map_or(false, |i|{true})
    }

    /// Insert new value at key `query` and return the previous value at that key, if any existed
    pub fn insert(&mut self, query: K, value: V) -> Option<V> {
        self.ensure_capacity();
        let len = self.entries.capacity();
        let hash = self.hash(query);
        let h = hash as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            let entry = &mut self.entries[index];
            if !entry.used {
                entry.key = query;
                entry.value = value;
                entry.used = true;
                entry.hash = hash;
                return None
            } else if entry.key == query {
                let old_val: V = entry.value.clone();
                entry.value = value;
                entry.hash = hash;
                return Some(old_val)
            }
        }
        panic!("should always have place");
    }

    /// Remove value at key `query` and return it, if it existed
    pub fn remove(&mut self, query: K) -> Option<V> {
         self.remove_inner(query)
    }

    /// Iterator over all keys in the dictionary
    pub fn keys(&self) -> ::std::slice::Iter<K> {
         unimplemented!();
    }

    /// Iterator over all values in the dictionary
    pub fn values(&self) -> ::std::slice::Iter<V> {
         unimplemented!();
    }

    /// Iterator over mutable references to all values in the dictionary
    pub fn values_mut(&mut self) -> ::std::slice::IterMut<V> {
         unimplemented!();
    }

    /// Iterator over all key-value pairs in the dictionary
    pub fn pairs<'a>(&'a self) -> impl Iterator<Item = (&'a K, &'a V)> + Clone + 'a {
        self.into_iter()
    }

    fn hash(&self, key: K) -> u64 {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        hasher.finish()
    }

    fn get_inner(&self, query: K) -> Option<&Entry<K,V>> {
        self.find_pos(query).map(move |i| {&self.entries[i]})
    }

    fn get_inner_mut(&mut self, query: K) -> Option<&mut Entry<K,V>> {
        self.find_pos(query).map(move |i| {&mut self.entries[i]})
    }

    fn remove_inner(&mut self, query: K) -> Option<V> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                self.entries[index].used = false;
                return Some(self.entries[index].value.clone());
            }
        }
        None
    }

    fn ensure_capacity(&mut self) {
        if 10 * self.size > 7 * self.entries.capacity() {
            let old_entries = self.entries.clone();
            self.entries = CompactArray::with_capacity(old_entries.capacity() * 2);
            for entry in old_entries {
                self.insert(entry.key, entry.value);
            }
        }
    }

    fn find_pos(&self, query: K) -> Option<usize> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                return Some(i);
            } else if !self.entries[index].used {
                return Some(i);
            }
        }
        None
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Compact for OpenAddressingMap<K, V, A> {
    fn is_still_compact(&self) -> bool {
        self.entries.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.entries.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.entries.compact_from(
            &source.entries,
            new_dynamic_part,
        );
        self.size.compact_from(
            &source.size,
            new_dynamic_part.offset(
                (self.entries.dynamic_size_bytes()) as isize,
            ),
        )
    }

    unsafe fn decompact(&self) -> OpenAddressingMap<K, V, A> {
        OpenAddressingMap {
            entries: self.entries.decompact(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Clone for OpenAddressingMap<K, V, A> {
    fn clone(&self) -> Self {
        OpenAddressingMap {
            entries: self.entries.clone(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Default for OpenAddressingMap<K, V, A> {
    fn default() -> Self {
        OpenAddressingMap::with_capacity(100)
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> ::std::iter::FromIterator<(K, V)>
    for OpenAddressingMap<K, V, A> {
    /// Construct a compact dictionary from an interator over key-value pairs
    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
        let mut map = Self::with_capacity(100);
        for (key, value) in iter {
            map.insert(key, value);
        }
        map
    }
}

struct OpenAddressingMapIter<'a, K: 'a + Copy + Compact + Eq + Hash, V: 'a + Clone + Compact> {
    idx: usize,
    left: usize,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    arr_iter: Iterator<Item=(&'a(Entry<K,V>))>,
}

impl <'a, K: Copy + Eq + Hash,V: Clone + Compact> Iterator for OpenAddressingMapIter<'a, K, V> {
    type Item = &'a(Entry<K, V>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.left == 0 {
            return None;
        }
        loop {
            let res = self.arr_iter
                .next().unwrap();
            self.idx += 1;
            if res.used {
                self.left -= 1;
                return Some(res);
            }
        }
    }
}

impl<K: Hash + Eq + Copy, I: Compact, A1: Allocator, A2: Allocator> OpenAddressingMap<K, CompactVec<I, A1>, A2> {
    /// Push a value onto the `CompactVec` at the key `query`
    pub fn push_at(&mut self, query: K, item: I) {
        let index = self.find_pos(query);
        match index {
            Some(i) => {
                if self.entries[i].used {
                    self.entries[i].value.push(item);
                } else {
                    let mut vec = CompactVec::new();
                    vec.push(item);
                    self.entries[i].used = true;
                    self.entries[i].value = vec;
                }
            },
            None => {
                panic!("should always have place");
            }
        }
    }

    /// Iterator over the `CompactVec` at the key `query`
    #[allow(needless_lifetimes)]
    pub fn get_iter<'a>(&'a self, query: K) -> impl Iterator<Item = &'a I> + 'a {
        self.get(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.iter()
        })
    }

    /// Remove the `CompactVec` at the key `query` and iterate over its elements (if it existed)
    #[allow(needless_lifetimes)]
    pub fn remove_iter<'a>(&'a mut self, query: K) -> impl Iterator<Item = I> + 'a {
        self.remove(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.into_iter()
        })
    }
}

impl<'a, K: Copy + Eq + Hash,V: Clone + Compact> IntoIterator for &'a OpenAddressingMap<K, V> {
    type Item = (& 'a K, & 'a V);
    type IntoIter = ::std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.entries.into_iter()
    }
}

impl <T: Hash> Hash for CompactVec<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        for elem in self {
            elem.hash(state);
        }
    }
}

fn elem(n: u32) -> u32 {
    (n * n) as u32
}

#[test]
fn basic() {
    let n: u32 = 3000;
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for i in 0..n {
        map.insert(i, elem(i));
    }
    assert!(map.is_empty() == false);
    for i in 0..n {
        assert!(*map.get(i).unwrap() == i * i);
    }
    assert!(map.len() == n as usize);
    assert!(*map.get_mru(n - 1).unwrap() == elem(n - 1));
    assert!(*map.get_mfu(n - 100).unwrap() == elem(n - 100));
    assert!(map.contains_key(n - 300) == true);
    assert!(map.contains_key(n + 1) == false);
    assert!(map.remove(500) == Some(elem(500)));
    assert!(map.get_mru(500).is_none());
}

#[test]
fn iter() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    let mut sum = 0;
    let mut keys = map.keys();
    for n in 0..100 {
        assert!(keys.find(|i| **i == n).is_some());
    }
    let mut values = map.values();
    for n in 0..100 {
        assert!(values.find(|i| **i == elem(n)).is_some());
    }

}
#[test]
fn values_mut() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    {
        let mut values_mut = map.values_mut();
        for i in &mut values_mut {
            *i = *i + 1;
        }
    }
    for i in 0..100 {
        assert!(*map.get(i).unwrap() == i * i + 1);
    }
}

#[test]
fn pairs() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    for (key, value) in map.pairs() {
        assert!( elem(*key) == *value);
    }
}

#[test]
fn push_at() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }

    for n in 0..100 {
        let mut iter = map.get_iter(n);
        assert!(iter.find(|i|{ **i == elem(n)}).is_some());
        assert!(iter.find(|i|{ **i == elem(n) + 1}).is_some());
    }
}

#[test]
fn remove_iter() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }
    let mut iter = map.remove_iter(50);
    assert!(iter.find(|i|{ *i == elem(50)}).is_some());
    assert!(iter.find(|i|{ *i == elem(50) + 1}).is_some());
}<commit_msg>compiles<commit_after>use super::allocators::{Allocator, DefaultHeap};
use super::compact::Compact;
use super::compact_vec::CompactVec;
use super::compact_dict::CompactDict;
use super::compact_array::{CompactArray, IntoIter as ArrayIntoIter};
use std::iter::{Iterator, Map};
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::hash::Hash;
use std::marker::PhantomData;

#[derive(Clone)]
struct Entry<K: Copy + Hash + Eq, V: Compact + Clone> {
    key: K,
    hash: u64,
    value: V,
    used: bool,
}

impl<K: Copy + Hash + Eq, V: Compact + Clone> Compact for Entry<K, V> {
    fn is_still_compact(&self) -> bool {
        self.value.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.value.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.value.compact_from(&source.value, new_dynamic_part);
    }

    unsafe fn decompact(&self) -> Entry<K, V> {
        Entry {
            key: self.key.clone(),
            value: self.value.decompact(),
            hash: self.hash,
            used: self.used
        }
    }
}

struct OpenAddressingMap<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator = DefaultHeap> {
    size: usize,
    entries: CompactArray<Entry<K, V>, A>,
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> OpenAddressingMap<K, V, A> {

    pub fn new() -> Self {
        Self::with_capacity(100)
    }
    pub fn with_capacity(l: usize) -> Self {
        OpenAddressingMap {
            entries: CompactArray::with_capacity(l),
            size: l,
        }
    }

    /// Amount of entries in the dictionary
    pub fn len(&self) -> usize {
        self.size
    }

    /// Is the dictionary empty?
    pub fn is_empty(&self) -> bool {
        self.size == 0
    }

    /// Look up the value for key `query`, if it exists
    pub fn get(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mru(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mfu(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mut(&mut self, query: K) -> Option<&mut V> {
        self.get_inner_mut(query).map(|e|{& mut e.value})
    }

    /// Does the dictionary contain a value for `query`?
    pub fn contains_key(&self, query: K) -> bool {
        self.get(query).map_or(false, |i|{true})
    }

    /// Insert new value at key `query` and return the previous value at that key, if any existed
    pub fn insert(&mut self, query: K, value: V) -> Option<V> {
        self.ensure_capacity();
        let len = self.entries.capacity();
        let hash = self.hash(query);
        let h = hash as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            let entry = &mut self.entries[index];
            if !entry.used {
                entry.key = query;
                entry.value = value;
                entry.used = true;
                entry.hash = hash;
                return None
            } else if entry.key == query {
                let old_val: V = entry.value.clone();
                entry.value = value;
                entry.hash = hash;
                return Some(old_val)
            }
        }
        panic!("should always have place");
    }

    /// Remove value at key `query` and return it, if it existed
    pub fn remove(&mut self, query: K) -> Option<V> {
         self.remove_inner(query)
    }

    /// Iterator over all keys in the dictionary
    pub fn keys(&self) -> ::std::slice::Iter<K> {
         unimplemented!();
    }

    /// Iterator over all values in the dictionary
    pub fn values(&self) -> ::std::slice::Iter<V> {
         unimplemented!();
    }

    /// Iterator over mutable references to all values in the dictionary
    pub fn values_mut(&mut self) -> ::std::slice::IterMut<V> {
         unimplemented!();
    }

    /// Iterator over all key-value pairs in the dictionary
    pub fn pairs<'a>(&'a self) -> impl Iterator<Item = (&'a K, &'a V)>  + 'a {
        self.entries.iter().filter(|e| {e.used}).map(|e|{(&e.key, &e.value)})
    }

    fn hash(&self, key: K) -> u64 {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        hasher.finish()
    }

    fn get_inner(&self, query: K) -> Option<&Entry<K,V>> {
        self.find_pos(query).map(move |i| {&self.entries[i]})
    }

    fn get_inner_mut(&mut self, query: K) -> Option<&mut Entry<K,V>> {
        self.find_pos(query).map(move |i| {&mut self.entries[i]})
    }

    fn remove_inner(&mut self, query: K) -> Option<V> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                self.entries[index].used = false;
                return Some(self.entries[index].value.clone());
            }
        }
        None
    }

    fn ensure_capacity(&mut self) {
        if 10 * self.size > 7 * self.entries.capacity() {
            let old_entries = self.entries.clone();
            self.entries = CompactArray::with_capacity(old_entries.capacity() * 2);
            for entry in old_entries {
                self.insert(entry.key, entry.value);
            }
        }
    }

    fn find_pos(&self, query: K) -> Option<usize> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                return Some(i);
            } else if !self.entries[index].used {
                return Some(i);
            }
        }
        None
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Compact for OpenAddressingMap<K, V, A> {
    fn is_still_compact(&self) -> bool {
        self.entries.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.entries.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.entries.compact_from(
            &source.entries,
            new_dynamic_part,
        );
        self.size.compact_from(
            &source.size,
            new_dynamic_part.offset(
                (self.entries.dynamic_size_bytes()) as isize,
            ),
        )
    }

    unsafe fn decompact(&self) -> OpenAddressingMap<K, V, A> {
        OpenAddressingMap {
            entries: self.entries.decompact(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Clone for OpenAddressingMap<K, V, A> {
    fn clone(&self) -> Self {
        OpenAddressingMap {
            entries: self.entries.clone(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Default for OpenAddressingMap<K, V, A> {
    fn default() -> Self {
        OpenAddressingMap::with_capacity(100)
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> ::std::iter::FromIterator<(K, V)>
    for OpenAddressingMap<K, V, A> {
    /// Construct a compact dictionary from an interator over key-value pairs
    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
        let mut map = Self::with_capacity(100);
        for (key, value) in iter {
            map.insert(key, value);
        }
        map
    }
}

struct OpenAddressingMapIter<'a, K: 'a + Copy + Compact + Eq + Hash, V: 'a + Clone + Compact> {
    idx: usize,
    left: usize,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    arr_iter: Iterator<Item=(&'a(Entry<K,V>))>,
}

impl <'a, K: Copy + Eq + Hash,V: Clone + Compact> Iterator for OpenAddressingMapIter<'a, K, V> {
    type Item = &'a(Entry<K, V>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.left == 0 {
            return None;
        }
        loop {
            let res = self.arr_iter
                .next().unwrap();
            self.idx += 1;
            if res.used {
                self.left -= 1;
                return Some(res);
            }
        }
    }
}

impl<K: Hash + Eq + Copy, I: Compact, A1: Allocator, A2: Allocator> OpenAddressingMap<K, CompactVec<I, A1>, A2> {
    /// Push a value onto the `CompactVec` at the key `query`
    pub fn push_at(&mut self, query: K, item: I) {
        let index = self.find_pos(query);
        match index {
            Some(i) => {
                if self.entries[i].used {
                    self.entries[i].value.push(item);
                } else {
                    let mut vec = CompactVec::new();
                    vec.push(item);
                    self.entries[i].used = true;
                    self.entries[i].value = vec;
                }
            },
            None => {
                panic!("should always have place");
            }
        }
    }

    /// Iterator over the `CompactVec` at the key `query`
    #[allow(needless_lifetimes)]
    pub fn get_iter<'a>(&'a self, query: K) -> impl Iterator<Item = &'a I> + 'a {
        self.get(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.iter()
        })
    }

    /// Remove the `CompactVec` at the key `query` and iterate over its elements (if it existed)
    #[allow(needless_lifetimes)]
    pub fn remove_iter<'a>(&'a mut self, query: K) -> impl Iterator<Item = I> + 'a {
        self.remove(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.into_iter()
        })
    }
}

type EntryIter<K,V,A> = ArrayIntoIter<Entry<K,V>,A>;

impl <T: Hash> Hash for CompactVec<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        for elem in self {
            elem.hash(state);
        }
    }
}

fn elem(n: u32) -> u32 {
    (n * n) as u32
}

#[test]
fn basic() {
    let n: u32 = 3000;
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for i in 0..n {
        map.insert(i, elem(i));
    }
    assert!(map.is_empty() == false);
    for i in 0..n {
        assert!(*map.get(i).unwrap() == i * i);
    }
    assert!(map.len() == n as usize);
    assert!(*map.get_mru(n - 1).unwrap() == elem(n - 1));
    assert!(*map.get_mfu(n - 100).unwrap() == elem(n - 100));
    assert!(map.contains_key(n - 300) == true);
    assert!(map.contains_key(n + 1) == false);
    assert!(map.remove(500) == Some(elem(500)));
    assert!(map.get_mru(500).is_none());
}

#[test]
fn iter() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    let mut sum = 0;
    let mut keys = map.keys();
    for n in 0..100 {
        assert!(keys.find(|i| **i == n).is_some());
    }
    let mut values = map.values();
    for n in 0..100 {
        assert!(values.find(|i| **i == elem(n)).is_some());
    }

}
#[test]
fn values_mut() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    {
        let mut values_mut = map.values_mut();
        for i in &mut values_mut {
            *i = *i + 1;
        }
    }
    for i in 0..100 {
        assert!(*map.get(i).unwrap() == i * i + 1);
    }
}

#[test]
fn pairs() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    for (key, value) in map.pairs() {
        assert!( elem(*key) == *value);
    }
}

#[test]
fn push_at() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }

    for n in 0..100 {
        let mut iter = map.get_iter(n);
        assert!(iter.find(|i|{ **i == elem(n)}).is_some());
        assert!(iter.find(|i|{ **i == elem(n) + 1}).is_some());
    }
}

#[test]
fn remove_iter() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }
    let mut iter = map.remove_iter(50);
    assert!(iter.find(|i|{ *i == elem(50)}).is_some());
    assert!(iter.find(|i|{ *i == elem(50) + 1}).is_some());
}<|endoftext|>


<commit_before>use cgmath::{self, Angle, Vector3, Matrix4, Point, Point3, Rad};
use glium::{DisplayBuild, Program, Surface};
use glium::{IndexBuffer, VertexBuffer};
use glium::{DrawParameters, Depth, DepthTest};
use glium::glutin::{ElementState, Event, WindowBuilder};
use glium::glutin::VirtualKeyCode as Key;
use glium::index::PrimitiveType;
use rand::{self, Rng, SeedableRng, XorShiftRng};

use nbody::NBodyBenchmark;
use ExecutionMode;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 3],
}

implement_vertex!(Vertex, position);

fn icosahedron() -> ([Vertex; 12], Vec<u8>) {
    let phi = (1.0 + f32::sqrt(5.0)) / 2.0;

    let vertices = [
        Vertex { position: [ phi,  1.0,  0.0] },
        Vertex { position: [ phi, -1.0,  0.0] },
        Vertex { position: [-phi,  1.0,  0.0] },
        Vertex { position: [-phi, -1.0,  0.0] },
        Vertex { position: [ 0.0,  phi,  1.0] },
        Vertex { position: [ 0.0,  phi, -1.0] },
        Vertex { position: [ 0.0, -phi,  1.0] },
        Vertex { position: [ 0.0, -phi, -1.0] },
        Vertex { position: [ 1.0,  0.0,  phi] },
        Vertex { position: [-1.0,  0.0,  phi] },
        Vertex { position: [ 1.0,  0.0, -phi] },
        Vertex { position: [-1.0,  0.0, -phi] },
    ];

    let indices = vec![
        0,  1,  8,
        0,  4,  5,
        0,  5, 10,
        0,  8,  4,
        0, 10,  1,
        1,  6,  8,
        1,  7,  6,
        1, 10,  7,
        2,  3, 11,
        2,  4,  9,
        2,  5,  4,
        2,  9,  3,
        2, 11,  5,
        3,  6,  7,
        3,  7, 11,
        3,  9,  6,
        4,  8,  9,
        5, 11, 10,
        6,  9,  8,
        7, 10, 11,
    ];

    (vertices, indices)
}

#[derive(Copy, Clone)]
struct Instance {
    color: [f32; 3],
    world_position: [f32; 3],
}

implement_vertex!(Instance, color, world_position);

pub fn visualize_benchmarks(num_bodies: usize, mode: ExecutionMode) {
    let display = WindowBuilder::new()
        .with_dimensions(800, 600)
        .with_title("nbody demo".to_string())
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    let mut benchmark = NBodyBenchmark::new(num_bodies, &mut rand::thread_rng());

    let vertex_shader_src = r#"
        #version 100

        uniform mat4 matrix;

        attribute vec3 position;
        attribute vec3 world_position;
        attribute vec3 color;

        varying lowp vec3 v_color;

        void main() {
            v_color = color;
            gl_Position = matrix * vec4(position * 0.1 + world_position * 0.0005, 1.0);
        }
    "#;

    let fragment_shader_src = r#"
        #version 100

        varying lowp vec3 v_color;

        void main() {
            gl_FragColor = vec4(v_color, 1.0);
        }
    "#;

    let program = Program::from_source(&display, vertex_shader_src,
                                       fragment_shader_src, None).unwrap();

    let (vertices, indices) = icosahedron();
    let vertex_buffer = VertexBuffer::new(&display, &vertices).unwrap();
    let index_buffer = IndexBuffer::new(&display, PrimitiveType::TrianglesList, &indices).unwrap();

    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    let instances: Vec<_> =
        (0..num_bodies)
            .map(|_| {
                Instance {
                    color: [
                        rng.gen_range(0.5, 1.0),
                        rng.gen_range(0.5, 1.0),
                        rng.gen_range(0.5, 1.0),
                    ],
                    world_position: [0.0, 0.0, 0.0],
                }
            })
            .collect();

    let mut instance_buffer = VertexBuffer::dynamic(&display, &instances).unwrap();

    'main: loop {
        {
            let bodies = match mode {
                ExecutionMode::Par => benchmark.tick_par(),
                ExecutionMode::ParReduce => benchmark.tick_par_reduce(),
                ExecutionMode::Seq => benchmark.tick_seq(),
            };

            let mut mapping = instance_buffer.map();
            for (body, instance) in bodies.iter().zip(mapping.iter_mut()) {
                instance.world_position = [
                    body.position.x as f32,
                    body.position.y as f32,
                    body.position.z as f32,
                ];
            }
        }

        let params = DrawParameters {
            depth: Depth {
                test: DepthTest::IfLess,
                write: true,
                .. Default::default()
            },
            .. Default::default()
        };

        let mut target = display.draw();

        let (width, height) = target.get_dimensions();
        let aspect = width as f32 / height as f32;

        let proj = cgmath::perspective(Rad::full_turn() / 6.0, aspect, 0.1, 3000.0);
        let view = Matrix4::look_at(Point3::new(10.0, 10.0, 10.0), Point3::origin(), Vector3::unit_z());
        let view_proj: [[f32; 4]; 4] = (proj * view).into();

        target.clear_color_and_depth((0.1, 0.1, 0.1, 1.0), 1.0);
        target.draw((&vertex_buffer, instance_buffer.per_instance().unwrap()),
                    &index_buffer,
                    &program,
                    &uniform! { matrix: view_proj },
                    &params).unwrap();
        target.finish().unwrap();

        for event in display.poll_events() {
            match event {
                Event::Closed => break 'main,
                Event::KeyboardInput(ElementState::Pressed, _, Some(Key::Escape)) => break 'main,
                _ => ()
            }
        }
    }
}
<commit_msg>Update visualizer to change modes with keypress<commit_after>use cgmath::{self, Angle, Vector3, Matrix4, Point, Point3, Rad};
use glium::{DisplayBuild, Program, Surface};
use glium::{IndexBuffer, VertexBuffer};
use glium::{DrawParameters, Depth, DepthTest};
use glium::glutin::{ElementState, Event, WindowBuilder};
use glium::glutin::VirtualKeyCode as Key;
use glium::index::PrimitiveType;
use rand::{self, Rng, SeedableRng, XorShiftRng};

use nbody::NBodyBenchmark;
use ExecutionMode;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 3],
}

implement_vertex!(Vertex, position);

fn icosahedron() -> ([Vertex; 12], Vec<u8>) {
    let phi = (1.0 + f32::sqrt(5.0)) / 2.0;

    let vertices = [
        Vertex { position: [ phi,  1.0,  0.0] },
        Vertex { position: [ phi, -1.0,  0.0] },
        Vertex { position: [-phi,  1.0,  0.0] },
        Vertex { position: [-phi, -1.0,  0.0] },
        Vertex { position: [ 0.0,  phi,  1.0] },
        Vertex { position: [ 0.0,  phi, -1.0] },
        Vertex { position: [ 0.0, -phi,  1.0] },
        Vertex { position: [ 0.0, -phi, -1.0] },
        Vertex { position: [ 1.0,  0.0,  phi] },
        Vertex { position: [-1.0,  0.0,  phi] },
        Vertex { position: [ 1.0,  0.0, -phi] },
        Vertex { position: [-1.0,  0.0, -phi] },
    ];

    let indices = vec![
        0,  1,  8,
        0,  4,  5,
        0,  5, 10,
        0,  8,  4,
        0, 10,  1,
        1,  6,  8,
        1,  7,  6,
        1, 10,  7,
        2,  3, 11,
        2,  4,  9,
        2,  5,  4,
        2,  9,  3,
        2, 11,  5,
        3,  6,  7,
        3,  7, 11,
        3,  9,  6,
        4,  8,  9,
        5, 11, 10,
        6,  9,  8,
        7, 10, 11,
    ];

    (vertices, indices)
}

#[derive(Copy, Clone)]
struct Instance {
    color: [f32; 3],
    world_position: [f32; 3],
}

implement_vertex!(Instance, color, world_position);

pub fn visualize_benchmarks(num_bodies: usize, mut mode: ExecutionMode) {
    let display = WindowBuilder::new()
        .with_dimensions(800, 600)
        .with_title("nbody demo".to_string())
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    let mut benchmark = NBodyBenchmark::new(num_bodies, &mut rand::thread_rng());

    let vertex_shader_src = r#"
        #version 100

        uniform mat4 matrix;

        attribute vec3 position;
        attribute vec3 world_position;
        attribute vec3 color;

        varying lowp vec3 v_color;

        void main() {
            v_color = color;
            gl_Position = matrix * vec4(position * 0.1 + world_position * 0.0005, 1.0);
        }
    "#;

    let fragment_shader_src = r#"
        #version 100

        varying lowp vec3 v_color;

        void main() {
            gl_FragColor = vec4(v_color, 1.0);
        }
    "#;

    let program = Program::from_source(&display, vertex_shader_src,
                                       fragment_shader_src, None).unwrap();

    let (vertices, indices) = icosahedron();
    let vertex_buffer = VertexBuffer::new(&display, &vertices).unwrap();
    let index_buffer = IndexBuffer::new(&display, PrimitiveType::TrianglesList, &indices).unwrap();

    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    let instances: Vec<_> =
        (0..num_bodies)
            .map(|_| {
                Instance {
                    color: [
                        rng.gen_range(0.5, 1.0),
                        rng.gen_range(0.5, 1.0),
                        rng.gen_range(0.5, 1.0),
                    ],
                    world_position: [0.0, 0.0, 0.0],
                }
            })
            .collect();

    let mut instance_buffer = VertexBuffer::dynamic(&display, &instances).unwrap();

    'main: loop {
        {
            let bodies = match mode {
                ExecutionMode::Par => benchmark.tick_par(),
                ExecutionMode::ParReduce => benchmark.tick_par_reduce(),
                ExecutionMode::Seq => benchmark.tick_seq(),
            };

            let mut mapping = instance_buffer.map();
            for (body, instance) in bodies.iter().zip(mapping.iter_mut()) {
                instance.world_position = [
                    body.position.x as f32,
                    body.position.y as f32,
                    body.position.z as f32,
                ];
            }
        }

        let params = DrawParameters {
            depth: Depth {
                test: DepthTest::IfLess,
                write: true,
                .. Default::default()
            },
            .. Default::default()
        };

        let mut target = display.draw();

        let (width, height) = target.get_dimensions();
        let aspect = width as f32 / height as f32;

        let proj = cgmath::perspective(Rad::full_turn() / 6.0, aspect, 0.1, 3000.0);
        let view = Matrix4::look_at(Point3::new(10.0, 10.0, 10.0), Point3::origin(), Vector3::unit_z());
        let view_proj: [[f32; 4]; 4] = (proj * view).into();

        target.clear_color_and_depth((0.1, 0.1, 0.1, 1.0), 1.0);
        target.draw((&vertex_buffer, instance_buffer.per_instance().unwrap()),
                    &index_buffer,
                    &program,
                    &uniform! { matrix: view_proj },
                    &params).unwrap();
        target.finish().unwrap();

        for event in display.poll_events() {
            match event {
                Event::Closed => break 'main,
                Event::KeyboardInput(ElementState::Pressed, _, Some(Key::Escape)) => break 'main,
                Event::KeyboardInput(ElementState::Pressed, _, Some(Key::P)) => {
                    mode = ExecutionMode::Par;
                }
                Event::KeyboardInput(ElementState::Pressed, _, Some(Key::S)) => {
                    mode = ExecutionMode::Seq;
                }
                Event::KeyboardInput(ElementState::Pressed, _, Some(Key::R)) => {
                    mode = ExecutionMode::ParReduce;
                }
                _ => ()
            }
        }
    }
}
<|endoftext|>


<commit_before>//! ELF executables

use collections::String;

use core::str;

#[cfg(target_arch = "x86")]
use goblin::elf32::{header, program_header};

#[cfg(target_arch = "x86_64")]
use goblin::elf64::{header, program_header};

use arch::externs::memcpy;
use arch::paging::{entry, VirtualAddress};
use arch::start::usermode;
use context;
use syscall::{Error, Result as SysResult};

/// An ELF executable
pub struct Elf<'a> {
    pub data: &'a [u8],
    header: &'a header::Header
}

impl<'a> Elf<'a> {
    /// Create a ELF executable from data
    pub fn from(data: &'a [u8]) -> Result<Elf<'a>, String> {
        if data.len() < header::SIZEOF_EHDR {
            Err(format!("Elf: Not enough data: {} < {}", data.len(), header::SIZEOF_EHDR))
        } else if &data[..header::SELFMAG] != header::ELFMAG {
            Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], header::ELFMAG))
        } else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) {
            Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(header::EI_CLASS), header::ELFCLASS))
        } else {
            Ok(Elf {
                data: data,
                header: unsafe { &*(data.as_ptr() as usize as *const header::Header) }
            })
        }
    }

    pub fn segments(&'a self) -> ElfSegments<'a> {
        ElfSegments {
            data: self.data,
            header: self.header,
            i: 0
        }
    }

    /// Get the entry field of the header
    pub fn entry(&self) -> usize {
        self.header.e_entry as usize
    }

    /// Test function to run. Remove and replace with proper syscall
    pub fn run(self) -> SysResult<!> {
        let stack_addr = 0x80000000;
        let stack_size = 64 * 1024;
        {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::NoProcess)?;
            let mut context = context_lock.write();

            // Unmap previous image and stack
            context.image.clear();
            drop(context.heap.take());
            drop(context.stack.take());

            for segment in self.segments() {
                if segment.p_type == program_header::PT_LOAD {
                    let mut memory = context::memory::Memory::new(
                        VirtualAddress::new(segment.p_vaddr as usize),
                        segment.p_memsz as usize,
                        entry::NO_EXECUTE | entry::WRITABLE,
                        true,
                        true
                    );

                    unsafe {
                        // Copy file data
                        memcpy(segment.p_vaddr as *mut u8,
                                (self.data.as_ptr() as usize + segment.p_offset as usize) as *const u8,
                                segment.p_filesz as usize);
                    }

                    let mut flags = entry::NO_EXECUTE | entry::USER_ACCESSIBLE;

                    if segment.p_flags & program_header::PF_R == program_header::PF_R {
                        flags.insert(entry::PRESENT);
                    }

                    // W ^ X. If it is executable, do not allow it to be writable, even if requested
                    if segment.p_flags & program_header::PF_X == program_header::PF_X {
                        flags.remove(entry::NO_EXECUTE);
                    } else if segment.p_flags & program_header::PF_W == program_header::PF_W {
                        flags.insert(entry::WRITABLE);
                    }

                    memory.remap(flags, true);

                    context.image.push(memory);
                }
            }

            // Map stack
            context.stack = Some(context::memory::Memory::new(
                VirtualAddress::new(stack_addr),
                stack_size,
                entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
                true,
                true
            ));
        }

        // Go to usermode
        unsafe { usermode(self.entry(), stack_addr + stack_size - 256); }
    }
}

pub struct ElfSegments<'a> {
    data: &'a [u8],
    header: &'a header::Header,
    i: usize
}

impl<'a> Iterator for ElfSegments<'a> {
    type Item = &'a program_header::ProgramHeader;
    fn next(&mut self) -> Option<Self::Item> {
        if self.i < self.header.e_phnum as usize {
            let item = unsafe {
                &* ((
                        self.data.as_ptr() as usize
                        + self.header.e_phoff as usize
                        + self.i * self.header.e_phentsize as usize
                    ) as *const program_header::ProgramHeader)
            };
            self.i += 1;
            Some(item)
        } else {
            None
        }
    }
}
<commit_msg>Map kernel TLS to general area<commit_after>//! ELF executables

use collections::String;

use core::str;

#[cfg(target_arch = "x86")]
use goblin::elf32::{header, program_header};

#[cfg(target_arch = "x86_64")]
use goblin::elf64::{header, program_header};

use arch;
use arch::externs::memcpy;
use arch::paging::{entry, VirtualAddress};
use arch::start::usermode;
use context;
use syscall::{Error, Result as SysResult};

/// An ELF executable
pub struct Elf<'a> {
    pub data: &'a [u8],
    header: &'a header::Header
}

impl<'a> Elf<'a> {
    /// Create a ELF executable from data
    pub fn from(data: &'a [u8]) -> Result<Elf<'a>, String> {
        if data.len() < header::SIZEOF_EHDR {
            Err(format!("Elf: Not enough data: {} < {}", data.len(), header::SIZEOF_EHDR))
        } else if &data[..header::SELFMAG] != header::ELFMAG {
            Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], header::ELFMAG))
        } else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) {
            Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(header::EI_CLASS), header::ELFCLASS))
        } else {
            Ok(Elf {
                data: data,
                header: unsafe { &*(data.as_ptr() as usize as *const header::Header) }
            })
        }
    }

    pub fn segments(&'a self) -> ElfSegments<'a> {
        ElfSegments {
            data: self.data,
            header: self.header,
            i: 0
        }
    }

    /// Get the entry field of the header
    pub fn entry(&self) -> usize {
        self.header.e_entry as usize
    }

    /// Test function to run. Remove and replace with proper syscall
    pub fn run(self) -> SysResult<!> {
        let stack_addr = arch::USER_STACK_OFFSET;
        let stack_size = arch::USER_STACK_SIZE;
        {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::NoProcess)?;
            let mut context = context_lock.write();

            // Unmap previous image and stack
            context.image.clear();
            drop(context.heap.take());
            drop(context.stack.take());

            for segment in self.segments() {
                if segment.p_type == program_header::PT_LOAD {
                    let mut memory = context::memory::Memory::new(
                        VirtualAddress::new(segment.p_vaddr as usize),
                        segment.p_memsz as usize,
                        entry::NO_EXECUTE | entry::WRITABLE,
                        true,
                        true
                    );

                    unsafe {
                        // Copy file data
                        memcpy(segment.p_vaddr as *mut u8,
                                (self.data.as_ptr() as usize + segment.p_offset as usize) as *const u8,
                                segment.p_filesz as usize);
                    }

                    let mut flags = entry::NO_EXECUTE | entry::USER_ACCESSIBLE;

                    if segment.p_flags & program_header::PF_R == program_header::PF_R {
                        flags.insert(entry::PRESENT);
                    }

                    // W ^ X. If it is executable, do not allow it to be writable, even if requested
                    if segment.p_flags & program_header::PF_X == program_header::PF_X {
                        flags.remove(entry::NO_EXECUTE);
                    } else if segment.p_flags & program_header::PF_W == program_header::PF_W {
                        flags.insert(entry::WRITABLE);
                    }

                    memory.remap(flags, true);

                    context.image.push(memory);
                }
            }

            // Map stack
            context.stack = Some(context::memory::Memory::new(
                VirtualAddress::new(stack_addr),
                stack_size,
                entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
                true,
                true
            ));
        }

        // Go to usermode
        unsafe { usermode(self.entry(), stack_addr + stack_size - 256); }
    }
}

pub struct ElfSegments<'a> {
    data: &'a [u8],
    header: &'a header::Header,
    i: usize
}

impl<'a> Iterator for ElfSegments<'a> {
    type Item = &'a program_header::ProgramHeader;
    fn next(&mut self) -> Option<Self::Item> {
        if self.i < self.header.e_phnum as usize {
            let item = unsafe {
                &* ((
                        self.data.as_ptr() as usize
                        + self.header.e_phoff as usize
                        + self.i * self.header.e_phentsize as usize
                    ) as *const program_header::ProgramHeader)
            };
            self.i += 1;
            Some(item)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    counters::{
        PROCESSED_STRUCT_LOG_COUNT, SENT_STRUCT_LOG_COUNT, STRUCT_LOG_PARSE_ERROR_COUNT,
        STRUCT_LOG_QUEUE_ERROR_COUNT, STRUCT_LOG_SEND_ERROR_COUNT,
    },
    logger::Logger,
    struct_log::TcpWriter,
    Event, Level, Metadata,
};
use chrono::{SecondsFormat, Utc};
use serde::Serialize;
use std::{
    collections::HashMap,
    env, fmt,
    io::Write,
    sync::{
        mpsc::{self, Receiver, SyncSender},
        Arc,
    },
    thread,
};

pub const CHANNEL_SIZE: usize = 10000;
const NUM_SEND_RETRIES: u8 = 1;

#[derive(Debug, Serialize)]
pub struct LogEntry {
    #[serde(flatten)]
    metadata: Metadata,
    timestamp: String,
    #[serde(skip_serializing_if = "HashMap::is_empty")]
    data: HashMap<&'static str, serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    message: Option<String>,
}

impl LogEntry {
    fn new(event: &Event) -> Self {
        use crate::{Key, Value, Visitor};

        struct JsonVisitor<'a>(&'a mut HashMap<&'static str, serde_json::Value>);

        impl<'a> Visitor for JsonVisitor<'a> {
            fn visit_pair(&mut self, key: Key, value: Value<'_>) {
                let v = match value {
                    Value::Debug(d) => serde_json::Value::String(format!("{:?}", d)),
                    Value::Display(d) => serde_json::Value::String(d.to_string()),
                    Value::Serde(s) => serde_json::to_value(s).unwrap(),
                };

                self.0.insert(key.as_str(), v);
            }
        }

        let metadata = *event.metadata();
        let message = event.message().map(fmt::format);

        let mut data = HashMap::new();
        for schema in event.keys_and_values() {
            schema.visit(&mut JsonVisitor(&mut data));
        }

        Self {
            metadata,
            timestamp: Utc::now().to_rfc3339_opts(SecondsFormat::Micros, true),
            data,
            message,
        }
    }
}

pub struct LibraLoggerBuilder {
    channel_size: usize,
    level: Level,
    address: Option<String>,
    printer: Option<Box<dyn Writer>>,
    is_async: bool,
}

impl LibraLoggerBuilder {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self {
            channel_size: CHANNEL_SIZE,
            level: Level::Debug,
            address: None,
            printer: Some(Box::new(StderrWriter)),
            is_async: false,
        }
    }

    pub fn address(&mut self, address: String) -> &mut Self {
        self.address = Some(address);
        self
    }

    pub fn read_env(&mut self) -> &mut Self {
        if let Ok(address) = env::var("STRUCT_LOG_TCP_ADDR") {
            self.address(address);
        }
        self
    }

    pub fn level(&mut self, level: Level) -> &mut Self {
        self.level = level;
        self
    }

    pub fn channel_size(&mut self, channel_size: usize) -> &mut Self {
        self.channel_size = channel_size;
        self
    }

    pub fn printer(&mut self, printer: Box<dyn Writer + Send + Sync + 'static>) -> &mut Self {
        self.printer = Some(printer);
        self
    }

    pub fn is_async(&mut self, is_async: bool) -> &mut Self {
        self.is_async = is_async;
        self
    }

    pub fn init(&mut self) {
        self.build()
    }

    pub fn build(&mut self) {
        let logger = if self.is_async {
            let (sender, receiver) = mpsc::sync_channel(self.channel_size);
            let service = LoggerService {
                receiver,
                address: self.address.clone(),
                printer: self.printer.take(),
            };
            let logger = Arc::new(LibraLogger {
                sender: Some(sender),
                printer: None,
                level: self.level,
            });

            thread::spawn(move || service.run());
            logger
        } else {
            Arc::new(LibraLogger {
                sender: None,
                printer: self.printer.take(),
                level: self.level,
            })
        };

        crate::logger::set_global_logger(logger);
    }
}

pub struct LibraLogger {
    sender: Option<SyncSender<LogEntry>>,
    printer: Option<Box<dyn Writer>>,
    level: Level,
}

impl LibraLogger {
    pub fn builder() -> LibraLoggerBuilder {
        LibraLoggerBuilder::new()
    }

    #[allow(clippy::new_ret_no_self)]
    pub fn new() -> LibraLoggerBuilder {
        Self::builder()
    }

    pub fn init_for_testing() {
        if env::var("RUST_LOG").is_err() {
            return;
        }

        Self::builder()
            .is_async(false)
            .printer(Box::new(StderrWriter))
            .build()
    }

    fn send_entry(&self, entry: LogEntry) {
        if let Some(printer) = &self.printer {
            let s = format(&entry).expect("Unable to format");
            printer.write(s);
        }

        if let Some(sender) = &self.sender {
            if let Err(e) = sender.try_send(entry) {
                STRUCT_LOG_QUEUE_ERROR_COUNT.inc();
                eprintln!("Failed to send structured log: {}", e);
            }
        }
    }
}

impl Logger for LibraLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= self.level
    }

    fn record(&self, event: &Event) {
        let entry = LogEntry::new(event);

        self.send_entry(entry)
    }
}

struct LoggerService {
    receiver: Receiver<LogEntry>,
    address: Option<String>,
    printer: Option<Box<dyn Writer>>,
}

impl LoggerService {
    pub fn run(mut self) {
        let mut writer = self.address.take().map(TcpWriter::new);

        for entry in self.receiver {
            PROCESSED_STRUCT_LOG_COUNT.inc();

            if let Some(writer) = &mut writer {
                Self::write_to_logstash(writer, &entry);
            }

            if let Some(printer) = &self.printer {
                let s = format(&entry).expect("Unable to format");
                printer.write(s)
            }
        }
    }

    /// Writes a log line into json_lines logstash format, which has a newline at the end
    fn write_to_logstash(stream: &mut TcpWriter, entry: &LogEntry) {
        let message = if let Ok(json) = serde_json::to_string(entry) {
            json
        } else {
            STRUCT_LOG_PARSE_ERROR_COUNT.inc();
            return;
        };

        let message = message + "\n";
        let bytes = message.as_bytes();

        // Attempt to write the log up to NUM_SEND_RETRIES + 1, and then drop it
        // Each `write_all` call will attempt to open a connection if one isn't open
        let mut result = stream.write_all(bytes);
        for _ in 0..NUM_SEND_RETRIES {
            if result.is_ok() {
                break;
            } else {
                result = stream.write_all(bytes);
            }
        }

        if let Err(e) = result {
            STRUCT_LOG_SEND_ERROR_COUNT.inc();
            eprintln!(
                "[Logging] Error while sending data to logstash({}): {}",
                stream.endpoint(),
                e
            );
        } else {
            SENT_STRUCT_LOG_COUNT.inc()
        }
    }
}

/// An trait encapsulating the operations required for writing logs.
pub trait Writer: Send + Sync {
    /// Write the log.
    fn write(&self, log: String);
}

/// A struct for writing logs to stderr
struct StderrWriter;

impl Writer for StderrWriter {
    /// Write log to stderr
    fn write(&self, log: String) {
        eprintln!("{}", log);
    }
}

/// Converts a record into a string representation:
/// UNIX_TIMESTAMP LOG_LEVEL FILE:LINE MESSAGE
/// Example:
/// 2020-03-07 05:03:03 INFO common/libra-logger/src/lib.rs:261 Hello
fn format(entry: &LogEntry) -> Result<String, fmt::Error> {
    use std::fmt::Write;

    let mut w = String::new();
    write!(
        w,
        "{} {} {}",
        entry.metadata.level(),
        entry.timestamp,
        entry.metadata.location()
    )?;

    if let Some(message) = &entry.message {
        write!(w, " {}", message)?;
    }

    Ok(w)
}
<commit_msg>logger: rework old struct_log tests for the new backend<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    counters::{
        PROCESSED_STRUCT_LOG_COUNT, SENT_STRUCT_LOG_COUNT, STRUCT_LOG_PARSE_ERROR_COUNT,
        STRUCT_LOG_QUEUE_ERROR_COUNT, STRUCT_LOG_SEND_ERROR_COUNT,
    },
    logger::Logger,
    struct_log::TcpWriter,
    Event, Level, Metadata,
};
use chrono::{SecondsFormat, Utc};
use serde::Serialize;
use std::{
    collections::HashMap,
    env, fmt,
    io::Write,
    sync::{
        mpsc::{self, Receiver, SyncSender},
        Arc,
    },
    thread,
};

pub const CHANNEL_SIZE: usize = 10000;
const NUM_SEND_RETRIES: u8 = 1;

#[derive(Debug, Serialize)]
pub struct LogEntry {
    #[serde(flatten)]
    metadata: Metadata,
    timestamp: String,
    #[serde(skip_serializing_if = "HashMap::is_empty")]
    data: HashMap<&'static str, serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    message: Option<String>,
}

impl LogEntry {
    fn new(event: &Event) -> Self {
        use crate::{Key, Value, Visitor};

        struct JsonVisitor<'a>(&'a mut HashMap<&'static str, serde_json::Value>);

        impl<'a> Visitor for JsonVisitor<'a> {
            fn visit_pair(&mut self, key: Key, value: Value<'_>) {
                let v = match value {
                    Value::Debug(d) => serde_json::Value::String(format!("{:?}", d)),
                    Value::Display(d) => serde_json::Value::String(d.to_string()),
                    Value::Serde(s) => serde_json::to_value(s).unwrap(),
                };

                self.0.insert(key.as_str(), v);
            }
        }

        let metadata = *event.metadata();
        let message = event.message().map(fmt::format);

        let mut data = HashMap::new();
        for schema in event.keys_and_values() {
            schema.visit(&mut JsonVisitor(&mut data));
        }

        Self {
            metadata,
            timestamp: Utc::now().to_rfc3339_opts(SecondsFormat::Micros, true),
            data,
            message,
        }
    }
}

pub struct LibraLoggerBuilder {
    channel_size: usize,
    level: Level,
    address: Option<String>,
    printer: Option<Box<dyn Writer>>,
    is_async: bool,
}

impl LibraLoggerBuilder {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self {
            channel_size: CHANNEL_SIZE,
            level: Level::Debug,
            address: None,
            printer: Some(Box::new(StderrWriter)),
            is_async: false,
        }
    }

    pub fn address(&mut self, address: String) -> &mut Self {
        self.address = Some(address);
        self
    }

    pub fn read_env(&mut self) -> &mut Self {
        if let Ok(address) = env::var("STRUCT_LOG_TCP_ADDR") {
            self.address(address);
        }
        self
    }

    pub fn level(&mut self, level: Level) -> &mut Self {
        self.level = level;
        self
    }

    pub fn channel_size(&mut self, channel_size: usize) -> &mut Self {
        self.channel_size = channel_size;
        self
    }

    pub fn printer(&mut self, printer: Box<dyn Writer + Send + Sync + 'static>) -> &mut Self {
        self.printer = Some(printer);
        self
    }

    pub fn is_async(&mut self, is_async: bool) -> &mut Self {
        self.is_async = is_async;
        self
    }

    pub fn init(&mut self) {
        self.build()
    }

    pub fn build(&mut self) {
        let logger = if self.is_async {
            let (sender, receiver) = mpsc::sync_channel(self.channel_size);
            let service = LoggerService {
                receiver,
                address: self.address.clone(),
                printer: self.printer.take(),
            };
            let logger = Arc::new(LibraLogger {
                sender: Some(sender),
                printer: None,
                level: self.level,
            });

            thread::spawn(move || service.run());
            logger
        } else {
            Arc::new(LibraLogger {
                sender: None,
                printer: self.printer.take(),
                level: self.level,
            })
        };

        crate::logger::set_global_logger(logger);
    }
}

pub struct LibraLogger {
    sender: Option<SyncSender<LogEntry>>,
    printer: Option<Box<dyn Writer>>,
    level: Level,
}

impl LibraLogger {
    pub fn builder() -> LibraLoggerBuilder {
        LibraLoggerBuilder::new()
    }

    #[allow(clippy::new_ret_no_self)]
    pub fn new() -> LibraLoggerBuilder {
        Self::builder()
    }

    pub fn init_for_testing() {
        if env::var("RUST_LOG").is_err() {
            return;
        }

        Self::builder()
            .is_async(false)
            .printer(Box::new(StderrWriter))
            .build()
    }

    fn send_entry(&self, entry: LogEntry) {
        if let Some(printer) = &self.printer {
            let s = format(&entry).expect("Unable to format");
            printer.write(s);
        }

        if let Some(sender) = &self.sender {
            if let Err(e) = sender.try_send(entry) {
                STRUCT_LOG_QUEUE_ERROR_COUNT.inc();
                eprintln!("Failed to send structured log: {}", e);
            }
        }
    }
}

impl Logger for LibraLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= self.level
    }

    fn record(&self, event: &Event) {
        let entry = LogEntry::new(event);

        self.send_entry(entry)
    }
}

struct LoggerService {
    receiver: Receiver<LogEntry>,
    address: Option<String>,
    printer: Option<Box<dyn Writer>>,
}

impl LoggerService {
    pub fn run(mut self) {
        let mut writer = self.address.take().map(TcpWriter::new);

        for entry in self.receiver {
            PROCESSED_STRUCT_LOG_COUNT.inc();

            if let Some(writer) = &mut writer {
                Self::write_to_logstash(writer, &entry);
            }

            if let Some(printer) = &self.printer {
                let s = format(&entry).expect("Unable to format");
                printer.write(s)
            }
        }
    }

    /// Writes a log line into json_lines logstash format, which has a newline at the end
    fn write_to_logstash(stream: &mut TcpWriter, entry: &LogEntry) {
        let message = if let Ok(json) = serde_json::to_string(entry) {
            json
        } else {
            STRUCT_LOG_PARSE_ERROR_COUNT.inc();
            return;
        };

        let message = message + "\n";
        let bytes = message.as_bytes();

        // Attempt to write the log up to NUM_SEND_RETRIES + 1, and then drop it
        // Each `write_all` call will attempt to open a connection if one isn't open
        let mut result = stream.write_all(bytes);
        for _ in 0..NUM_SEND_RETRIES {
            if result.is_ok() {
                break;
            } else {
                result = stream.write_all(bytes);
            }
        }

        if let Err(e) = result {
            STRUCT_LOG_SEND_ERROR_COUNT.inc();
            eprintln!(
                "[Logging] Error while sending data to logstash({}): {}",
                stream.endpoint(),
                e
            );
        } else {
            SENT_STRUCT_LOG_COUNT.inc()
        }
    }
}

/// An trait encapsulating the operations required for writing logs.
pub trait Writer: Send + Sync {
    /// Write the log.
    fn write(&self, log: String);
}

/// A struct for writing logs to stderr
struct StderrWriter;

impl Writer for StderrWriter {
    /// Write log to stderr
    fn write(&self, log: String) {
        eprintln!("{}", log);
    }
}

/// Converts a record into a string representation:
/// UNIX_TIMESTAMP LOG_LEVEL FILE:LINE MESSAGE
/// Example:
/// 2020-03-07 05:03:03 INFO common/libra-logger/src/lib.rs:261 Hello
fn format(entry: &LogEntry) -> Result<String, fmt::Error> {
    use std::fmt::Write;

    let mut w = String::new();
    write!(
        w,
        "{} {} {}",
        entry.metadata.level(),
        entry.timestamp,
        entry.metadata.location()
    )?;

    if let Some(message) = &entry.message {
        write!(w, " {}", message)?;
    }

    Ok(w)
}

#[cfg(test)]
mod tests {
    use super::LogEntry;
    use crate::{
        debug, error, info, logger::Logger, trace, warn, Event, Key, KeyValue, Level, Metadata,
        Schema, Value, Visitor,
    };
    use chrono::{DateTime, Utc};
    use serde_json::Value as JsonValue;
    use std::sync::{
        mpsc::{self, Receiver, SyncSender},
        Arc,
    };

    #[derive(serde::Serialize)]
    #[serde(rename_all = "snake_case")]
    enum Enum {
        FooBar,
    }

    struct TestSchema<'a> {
        foo: usize,
        bar: &'a Enum,
    }

    impl Schema for TestSchema<'_> {
        fn visit(&self, visitor: &mut dyn Visitor) {
            visitor.visit_pair(Key::new("foo"), Value::from_serde(&self.foo));
            visitor.visit_pair(Key::new("bar"), Value::from_serde(&self.bar));
        }
    }

    struct LogStream(SyncSender<LogEntry>);

    impl LogStream {
        fn new() -> (Self, Receiver<LogEntry>) {
            let (sender, receiver) = mpsc::sync_channel(1024);
            (Self(sender), receiver)
        }
    }

    impl Logger for LogStream {
        fn enabled(&self, metadata: &Metadata) -> bool {
            metadata.level() <= Level::Debug
        }

        fn record(&self, event: &Event) {
            self.0.send(LogEntry::new(event)).unwrap();
        }
    }

    fn set_test_logger() -> Receiver<LogEntry> {
        let (logger, receiver) = LogStream::new();
        let logger = Arc::new(logger);
        crate::logger::set_global_logger(logger);
        receiver
    }

    // TODO: Find a better mechanism for testing that allows setting the logger not globally
    #[test]
    fn basic() {
        let receiver = set_test_logger();
        let number = 12345;

        // Send an info log
        let before = Utc::now();
        info!(
            TestSchema {
                foo: 5,
                bar: &Enum::FooBar
            },
            test = true,
            category = "name",
            KeyValue::new("display", Value::from_display(&number)),
            "This is a log"
        );
        let after = Utc::now();

        let entry = receiver.recv().unwrap();

        // Ensure standard fields are filled
        assert_eq!(entry.metadata.level(), Level::Info);
        assert_eq!(
            entry.metadata.target(),
            module_path!().split("::").next().unwrap()
        );
        assert_eq!(entry.metadata.module_path(), module_path!());
        assert_eq!(entry.metadata.file(), file!());
        assert_eq!(entry.message.as_deref(), Some("This is a log"));

        // Log time should be the time the structured log entry was created
        let timestamp = DateTime::parse_from_rfc3339(&entry.timestamp).unwrap();
        let timestamp: DateTime<Utc> = DateTime::from(timestamp);
        assert!(before <= timestamp && timestamp <= after);

        // Ensure data stored is the right type
        assert_eq!(entry.data.get("foo").and_then(JsonValue::as_u64), Some(5));
        assert_eq!(
            entry.data.get("bar").and_then(JsonValue::as_str),
            Some("foo_bar")
        );
        assert_eq!(
            entry.data.get("display").and_then(JsonValue::as_str),
            Some(format!("{}", number)).as_deref(),
        );
        assert_eq!(
            entry.data.get("test").and_then(JsonValue::as_bool),
            Some(true),
        );
        assert_eq!(
            entry.data.get("category").and_then(JsonValue::as_str),
            Some("name"),
        );

        // Test all log levels work properly
        // Tracing should be skipped because the Logger was setup to skip Tracing events
        trace!("trace");
        debug!("debug");
        info!("info");
        warn!("warn");
        error!("error");

        let levels = &[Level::Debug, Level::Info, Level::Warn, Level::Error];

        for level in levels {
            let entry = receiver.recv().unwrap();
            assert_eq!(entry.metadata.level(), *level);
        }
    }
}
<|endoftext|>


<commit_before>#![crate_id = "vm#0.0"]
#![crate_type = "bin"]
#![feature(globs, phase, default_type_params, macro_rules)]
#[phase(syntax, link)]
extern crate log;
extern crate collections;
#[cfg(test)]
extern crate test;

#[cfg(not(test))]
use module::{Type, TypeApplication, TypeOperator};
#[cfg(not(test))]
use parser::Parser;
#[cfg(not(test))]
use compiler::{Compiler, Instruction, PushInt, Mkap};
#[cfg(not(test))]
use typecheck::{DataTypes, TypeEnvironment};
#[cfg(not(test))]
use vm::{VM, evaluate, execute_main_module, compile_file};
#[cfg(not(test))]
use core::{Module};
#[cfg(not(test))]
use core::translate::{translate_expr};
#[cfg(not(test))]
use lambda_lift::do_lambda_lift;
#[cfg(not(test))]
use renamer::{rename_expr, Name};
#[cfg(not(test))]
use interner::intern;
#[cfg(not(test))]
use std::vec::FromVec;

#[macro_escape]
macro_rules! write_core_expr(
    ($e:expr, $f:expr, $($p:pat),*) => ({
        match $e {
            Identifier(ref s) => write!($f, "{}", *s),
            Apply(ref func, ref arg) => write!($f, "({} {})", func, *arg),
            Literal(ref l) => write!($f, "{}", *l),
            Lambda(ref arg, ref body) => write!($f, "({} -> {})", *arg, *body),
            Let(ref bindings, ref body) => {
                try!(write!($f, "let \\{\n"));
                for bind in bindings.iter() {
                    try!(write!($f, "; {} = {}\n", bind.name, bind.expression));
                }
                write!($f, "\\} in {}\n", *body)
            }
            Case(ref expr, ref alts) => {
                try!(write!($f, "case {} of \\{\n", *expr));
                for alt in alts.iter() {
                    try!(write!($f, "; {} -> {}\n", alt.pattern, alt.expression));
                }
                write!($f, "\\}\n")
            }
            $($p => Ok(()))*
        }
    })
)

mod module;
mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod graph;
mod vm;
mod scoped_map;
mod core;
mod lambda_lift;
mod renamer;
mod primitive;
mod interner;

#[cfg(not(test))]
fn is_io(typ: &Type) -> bool {
    match *typ {
        TypeApplication(ref lhs, _) =>
            match **lhs {
                TypeOperator(ref op) => op.name.as_slice() == "IO",
                _ => false
            },
        _ => false
    }
}

#[cfg(not(test))]
fn main() {
    let args = std::os::args();
    if args.len() == 2 {
        let expr_str = args.get(1).as_slice();
        let prelude = compile_file("Prelude.hs");
        let assembly = {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = rename_expr(parser.expression_());

            let mut type_env = TypeEnvironment::new();
            type_env.add_types(&prelude as &DataTypes);
            type_env.typecheck_expr(&mut expr);
            let temp_module = Module::from_expr(translate_expr(expr));
            let m = do_lambda_lift(temp_module);

            let mut compiler = Compiler::new(&type_env);
            compiler.assemblies.push(&prelude);
            compiler.compileModule(&m)
        };
        let mut vm = VM::new();
        vm.add_assembly(prelude);
        let (instructions, type_decl) = assembly.superCombinators.iter()
            .find(|sc| sc.name == Name { name: intern("main"), uid: 0 })
            .map(|sc| {
                if is_io(&sc.type_declaration.typ) {
                    //If the expression we compiled is IO we need to add an extra argument
                    //'RealWorld' which can be any dumb value (42 here), len - 3 is used because
                    //it is currently 3 instructions Eval, Update(0), Unwind at the end of each instruction list
                    //to finish the expression
                    let mut vec: Vec<Instruction> = sc.instructions.iter().map(|x| x.clone()).collect();
                    let len = vec.len();
                    vec.insert(len - 3, Mkap);
                    vec.insert(0, PushInt(42));//Realworld
                    (FromVec::from_vec(vec), sc.type_declaration.clone())
                }
                else {
                    (sc.instructions.clone(), sc.type_declaration.clone())
                }
            })
            .expect("Expected main function");
        let assembly_index = vm.add_assembly(assembly);
        let result = evaluate(&vm, instructions, assembly_index);//TODO 0 is not necessarily correct
        println!("{}  {}", result, type_decl);
    }
    else if args.len() == 3 && "-l" == args.get(1).as_slice() {
        let modulename = args.get(2).as_slice();
        let result = execute_main_module(modulename).unwrap();
        match result {
            Some(x) => println!("{:?}", x),
            None => println!("Error running module {:?}", modulename)
        }
    }
    else {
        println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

<commit_msg>Use the getopts library to parse the command line arguments<commit_after>#![crate_id = "vm#0.0"]
#![crate_type = "bin"]
#![feature(globs, phase, default_type_params, macro_rules)]
#[phase(syntax, link)]
extern crate log;
extern crate collections;
extern crate getopts;
#[cfg(test)]
extern crate test;

#[cfg(not(test))]
use module::{Type, TypeApplication, TypeOperator};
#[cfg(not(test))]
use parser::Parser;
#[cfg(not(test))]
use compiler::{Compiler, Instruction, PushInt, Mkap};
#[cfg(not(test))]
use typecheck::{DataTypes, TypeEnvironment};
#[cfg(not(test))]
use vm::{VM, evaluate, execute_main_module, compile_file};
#[cfg(not(test))]
use core::{Module};
#[cfg(not(test))]
use core::translate::{translate_expr};
#[cfg(not(test))]
use lambda_lift::do_lambda_lift;
#[cfg(not(test))]
use renamer::{rename_expr, Name};
#[cfg(not(test))]
use interner::intern;
#[cfg(not(test))]
use std::vec::FromVec;
#[cfg(not(test))]
use getopts::{optopt, optflag, getopts, usage};

#[macro_escape]
macro_rules! write_core_expr(
    ($e:expr, $f:expr, $($p:pat),*) => ({
        match $e {
            Identifier(ref s) => write!($f, "{}", *s),
            Apply(ref func, ref arg) => write!($f, "({} {})", func, *arg),
            Literal(ref l) => write!($f, "{}", *l),
            Lambda(ref arg, ref body) => write!($f, "({} -> {})", *arg, *body),
            Let(ref bindings, ref body) => {
                try!(write!($f, "let \\{\n"));
                for bind in bindings.iter() {
                    try!(write!($f, "; {} = {}\n", bind.name, bind.expression));
                }
                write!($f, "\\} in {}\n", *body)
            }
            Case(ref expr, ref alts) => {
                try!(write!($f, "case {} of \\{\n", *expr));
                for alt in alts.iter() {
                    try!(write!($f, "; {} -> {}\n", alt.pattern, alt.expression));
                }
                write!($f, "\\}\n")
            }
            $($p => Ok(()))*
        }
    })
)

mod module;
mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod graph;
mod vm;
mod scoped_map;
mod core;
mod lambda_lift;
mod renamer;
mod primitive;
mod interner;

#[cfg(not(test))]
fn is_io(typ: &Type) -> bool {
    match *typ {
        TypeApplication(ref lhs, _) =>
            match **lhs {
                TypeOperator(ref op) => op.name.as_slice() == "IO",
                _ => false
            },
        _ => false
    }
}

#[cfg(not(test))]
fn main() {
    let opts = [
        optopt("l", "", "Input file", "Module name"),
        optflag("h", "help", "Print help")
    ];
    let matches = {
        let args = std::os::args();
        getopts(args.tail(), opts)
            .unwrap_or_else(|err| fail!("{}", err))
    };

    if matches.opt_present("h") {
        println!("Usage: vm [OPTIONS|EXPRESSION] {}", usage("", opts));
        return;
    }
    match matches.opt_str("l") {
        Some(modulename) => {
            let result = execute_main_module(modulename.as_slice()).unwrap();
            match result {
                Some(x) => println!("{:?}", x),
                None => println!("Error running module {:?}", modulename)
            }
            return;
        }
        None => ()
    }
    let expr_str = matches.free.get(0).as_slice();
    let prelude = compile_file("Prelude.hs");
    let assembly = {
        let mut parser = Parser::new(expr_str.chars());
        let mut expr = rename_expr(parser.expression_());

        let mut type_env = TypeEnvironment::new();
        type_env.add_types(&prelude as &DataTypes);
        type_env.typecheck_expr(&mut expr);
        let temp_module = Module::from_expr(translate_expr(expr));
        let m = do_lambda_lift(temp_module);

        let mut compiler = Compiler::new(&type_env);
        compiler.assemblies.push(&prelude);
        compiler.compileModule(&m)
    };
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    let (instructions, type_decl) = assembly.superCombinators.iter()
        .find(|sc| sc.name == Name { name: intern("main"), uid: 0 })
        .map(|sc| {
            if is_io(&sc.type_declaration.typ) {
                //If the expression we compiled is IO we need to add an extra argument
                //'RealWorld' which can be any dumb value (42 here), len - 3 is used because
                //it is currently 3 instructions Eval, Update(0), Unwind at the end of each instruction list
                //to finish the expression
                let mut vec: Vec<Instruction> = sc.instructions.iter().map(|x| x.clone()).collect();
                let len = vec.len();
                vec.insert(len - 3, Mkap);
                vec.insert(0, PushInt(42));//Realworld
                (FromVec::from_vec(vec), sc.type_declaration.clone())
            }
            else {
                (sc.instructions.clone(), sc.type_declaration.clone())
            }
        })
        .expect("Expected main function");
    let assembly_index = vm.add_assembly(assembly);
    let result = evaluate(&vm, instructions, assembly_index);//TODO 0 is not necessarily correct
    println!("{}  {}", result, type_decl);
}

<|endoftext|>


<commit_before>struct Node {
    next: Option<Box<Node>>,
    data: String,
}

use std::fmt;

impl fmt::Pointer for Option<Box<Node>> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "there should be the address here :'(")
    }
}

fn main() {

    let newNode: Option<Box<Node>> = Some(Box::new(Node {next: None, data: "Hello".to_string()}));

    let secondNode: Node = Node {next: newNode, data: "some data".to_string()};

    println!("{:p}, {}", secondNode.next, secondNode.data);

}
<commit_msg>Progress: formatted output<commit_after>
fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

}
<|endoftext|>


<commit_before>use screen::*;
use context::Context;
use piston_window::{self, PistonWindow, Texture};
use gfx_device_gl;

pub struct Battle {
    a: Texture<gfx_device_gl::Resources>,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { a: context.resource_manager.load_texture(window) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|_context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<commit_msg>Texture drawing<commit_after>use screen::*;
use context::Context;
use piston_window::{self, PistonWindow, Texture};
use gfx_device_gl;

pub struct Battle {
    a: Texture<gfx_device_gl::Resources>,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { a: context.resource_manager.load_texture(window) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);
            piston_window::image(&self.a, context.transform, graphics);
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<|endoftext|>


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

#![feature(macro_rules,unsafe_destructor)]

#![deny(unused_imports, unused_variable)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

extern crate debug;
extern crate alloc;
extern crate azure;
extern crate collections;
extern crate geom;
extern crate getopts;
extern crate layers;
extern crate libc;
extern crate native;
extern crate rand;
extern crate rustrt;
extern crate serialize;
extern crate sync;
#[cfg(target_os="macos")]
extern crate task_info;
extern crate std_time = "time";
extern crate string_cache;

pub mod atom;
pub mod cache;
pub mod debug_utils;
pub mod geometry;
pub mod logical_geometry;
pub mod memory;
pub mod namespace;
pub mod opts;
pub mod range;
pub mod smallvec;
pub mod sort;
pub mod str;
pub mod task;
pub mod time;
pub mod vec;
pub mod workqueue;
<commit_msg>Add breakpoint utility function.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(macro_rules,unsafe_destructor)]

#![deny(unused_imports, unused_variable)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

extern crate debug;
extern crate alloc;
extern crate azure;
extern crate collections;
extern crate geom;
extern crate getopts;
extern crate layers;
extern crate libc;
extern crate native;
extern crate rand;
extern crate rustrt;
extern crate serialize;
extern crate sync;
#[cfg(target_os="macos")]
extern crate task_info;
extern crate std_time = "time";
extern crate string_cache;

pub mod atom;
pub mod cache;
pub mod debug_utils;
pub mod geometry;
pub mod logical_geometry;
pub mod memory;
pub mod namespace;
pub mod opts;
pub mod range;
pub mod smallvec;
pub mod sort;
pub mod str;
pub mod task;
pub mod time;
pub mod vec;
pub mod workqueue;

pub fn breakpoint() {
    unsafe { ::std::intrinsics::breakpoint() };
}
<|endoftext|>


<commit_before>extern crate wayland_server;
extern crate smithay;
extern crate glium;

use glium::Surface;
use smithay::backend::graphics::glium::IntoGlium;
use smithay::backend::input::InputBackend;
use smithay::backend::winit;
use smithay::shm::ShmGlobal;
use wayland_server::protocol::wl_shm;

fn main() {
    // Initialize a simple backend for testing
    let (renderer, mut input) = winit::init().unwrap();

    let (_display, mut event_loop) = wayland_server::create_display();

    // Insert the ShmGlobal as a handler to your event loop
    // Here, we specify tha the standard Argb8888 and Xrgb8888 is the only supported.
    let handler_id = event_loop.add_handler_with_init(ShmGlobal::new(vec![], None /* we don't provide a logger here */));

    // Register this handler to advertise a wl_shm global of version 1
    let shm_global = event_loop.register_global::<wl_shm::WlShm, ShmGlobal>(handler_id, 1);

    // Retrieve the shm token for later use to access the buffers
    let shm_token = {
        let state = event_loop.state();
        state.get_handler::<ShmGlobal>(handler_id).get_token()
    };

    // Init glium
    let context = renderer.into_glium();

    loop {
        input.dispatch_new_events().unwrap();

        let mut frame = context.draw();
        frame.clear(None, Some((0.0, 0.0, 0.0, 1.0)), false, None, None);
        frame.finish().unwrap();

        event_loop.dispatch(Some(16)).unwrap();
    }
}
<commit_msg>Fix example formatting<commit_after>extern crate wayland_server;
extern crate smithay;
extern crate glium;

use glium::Surface;
use smithay::backend::graphics::glium::IntoGlium;
use smithay::backend::input::InputBackend;
use smithay::backend::winit;
use smithay::shm::ShmGlobal;
use wayland_server::protocol::wl_shm;

fn main() {
    // Initialize a simple backend for testing
    let (renderer, mut input) = winit::init().unwrap();

    let (_display, mut event_loop) = wayland_server::create_display();

    // Insert the ShmGlobal as a handler to your event loop
    // Here, we specify tha the standard Argb8888 and Xrgb8888 is the only supported.
    let handler_id =
        event_loop.add_handler_with_init(ShmGlobal::new(vec![],
                                                        None /* we don't provide a logger here */));

    // Register this handler to advertise a wl_shm global of version 1
    let shm_global = event_loop.register_global::<wl_shm::WlShm, ShmGlobal>(handler_id, 1);

    // Retrieve the shm token for later use to access the buffers
    let shm_token = {
        let state = event_loop.state();
        state.get_handler::<ShmGlobal>(handler_id).get_token()
    };

    // Init glium
    let context = renderer.into_glium();

    loop {
        input.dispatch_new_events().unwrap();

        let mut frame = context.draw();
        frame.clear(None, Some((0.0, 0.0, 0.0, 1.0)), false, None, None);
        frame.finish().unwrap();

        event_loop.dispatch(Some(16)).unwrap();
    }
}
<|endoftext|>