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

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */

use core::container::{Container, Mutable, Map, Set};
use core::old_iter::{BaseIter};
use core::option::{Some, None};
use core::util::replace;

pub struct SmallIntMap<T> {
    priv v: ~[Option<T>],
}

impl<V> Container for SmallIntMap<V> {
    /// Return the number of elements in the map
    fn len(&const self) -> uint {
        let mut sz = 0;
        for uint::range(0, vec::uniq_len(&const self.v)) |i| {
            match self.v[i] {
                Some(_) => sz += 1,
                None => {}
            }
        }
        sz
    }

    /// Return true if the map contains no elements
    fn is_empty(&const self) -> bool { self.len() == 0 }
}

impl<V> Mutable for SmallIntMap<V> {
    /// Clear the map, removing all key-value pairs.
    fn clear(&mut self) { self.v.clear() }
}

impl<V> Map<uint, V> for SmallIntMap<V> {
    /// Return true if the map contains a value for the specified key
    fn contains_key(&self, key: &uint) -> bool {
        self.find(key).is_some()
    }

    /// Visit all key-value pairs in order
    fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool {
        for uint::range(0, self.v.len()) |i| {
            match self.v[i] {
              Some(ref elt) => if !it(&i, elt) { return false; },
              None => ()
            }
        }
        return true;
    }

    /// Visit all keys in order
    fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool {
        self.each(|k, _| blk(k))
    }

    /// Visit all values in order
    fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool {
        self.each(|_, v| blk(v))
    }

    /// Iterate over the map and mutate the contained values
    fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool {
        for uint::range(0, self.v.len()) |i| {
            match self.v[i] {
              Some(ref mut elt) => if !it(&i, elt) { return false; },
              None => ()
            }
        }
        return true;
    }

    /// Return a reference to the value corresponding to the key
    fn find<'a>(&'a self, key: &uint) -> Option<&'a V> {
        if *key < self.v.len() {
            match self.v[*key] {
              Some(ref value) => Some(value),
              None => None
            }
        } else {
            None
        }
    }

    /// Return a mutable reference to the value corresponding to the key
    fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> {
        if *key < self.v.len() {
            match self.v[*key] {
              Some(ref mut value) => Some(value),
              None => None
            }
        } else {
            None
        }
    }

    /// Insert a key-value pair into the map. An existing value for a
    /// key is replaced by the new value. Return true if the key did
    /// not already exist in the map.
    fn insert(&mut self, key: uint, value: V) -> bool {
        let exists = self.contains_key(&key);
        let len = self.v.len();
        if len <= key {
            vec::grow_fn(&mut self.v, key - len + 1, |_| None);
        }
        self.v[key] = Some(value);
        !exists
    }

    /// Remove a key-value pair from the map. Return true if the key
    /// was present in the map, otherwise false.
    fn remove(&mut self, key: &uint) -> bool {
        self.pop(key).is_some()
    }

    /// Insert a key-value pair from the map. If the key already had a value
    /// present in the map, that value is returned. Otherwise None is returned.
    fn swap(&mut self, key: uint, value: V) -> Option<V> {
        match self.find_mut(&key) {
            Some(loc) => { return Some(replace(loc, value)); }
            None => ()
        }
        self.insert(key, value);
        return None;
    }

    /// Removes a key from the map, returning the value at the key if the key
    /// was previously in the map.
    fn pop(&mut self, key: &uint) -> Option<V> {
        if *key >= self.v.len() {
            return None;
        }
        replace(&mut self.v[*key], None)
    }
}

pub impl<V> SmallIntMap<V> {
    /// Create an empty SmallIntMap
    fn new() -> SmallIntMap<V> { SmallIntMap{v: ~[]} }

    /// Visit all key-value pairs in reverse order
    fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool {
        for uint::range_rev(self.v.len(), 0) |i| {
            match self.v[i - 1] {
              Some(ref elt) => if !it(i - 1, elt) { return false; },
              None => ()
            }
        }
        return true;
    }

    fn get<'a>(&'a self, key: &uint) -> &'a V {
        self.find(key).expect("key not present")
    }
}

pub impl<V:Copy> SmallIntMap<V> {
    fn update_with_key(&mut self, key: uint, val: V,
                       ff: &fn(uint, V, V) -> V) -> bool {
        let new_val = match self.find(&key) {
            None => val,
            Some(orig) => ff(key, *orig, val)
        };
        self.insert(key, new_val)
    }

    fn update(&mut self, key: uint, newval: V, ff: &fn(V, V) -> V) -> bool {
        self.update_with_key(key, newval, |_k, v, v1| ff(v,v1))
    }
}

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

    #[test]
    fn test_find_mut() {
        let mut m = SmallIntMap::new();
        assert!(m.insert(1, 12));
        assert!(m.insert(2, 8));
        assert!(m.insert(5, 14));
        let new = 100;
        match m.find_mut(&5) {
            None => fail!(), Some(x) => *x = new
        }
        assert_eq!(m.find(&5), Some(&new));
    }

    #[test]
    fn test_len() {
        let mut map = SmallIntMap::new();
        assert_eq!(map.len(), 0);
        assert!(map.is_empty());
        assert!(map.insert(5, 20));
        assert_eq!(map.len(), 1);
        assert!(!map.is_empty());
        assert!(map.insert(11, 12));
        assert_eq!(map.len(), 2);
        assert!(!map.is_empty());
        assert!(map.insert(14, 22));
        assert_eq!(map.len(), 3);
        assert!(!map.is_empty());
    }

    #[test]
    fn test_clear() {
        let mut map = SmallIntMap::new();
        assert!(map.insert(5, 20));
        assert!(map.insert(11, 12));
        assert!(map.insert(14, 22));
        map.clear();
        assert!(map.is_empty());
        assert!(map.find(&5).is_none());
        assert!(map.find(&11).is_none());
        assert!(map.find(&14).is_none());
    }

    #[test]
    fn test_insert_with_key() {
        let mut map = SmallIntMap::new();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert_eq!(map.find(&3).get(), &10);
        assert_eq!(map.find(&5).get(), &3);
        assert_eq!(map.find(&9).get(), &1);

        // sadly, no sevens were counted
        assert!(map.find(&7).is_none());
    }

    #[test]
    fn test_swap() {
        let mut m = SmallIntMap::new();
        assert_eq!(m.swap(1, 2), None);
        assert_eq!(m.swap(1, 3), Some(2));
        assert_eq!(m.swap(1, 4), Some(3));
    }

    #[test]
    fn test_pop() {
        let mut m = SmallIntMap::new();
        m.insert(1, 2);
        assert_eq!(m.pop(&1), Some(2));
        assert_eq!(m.pop(&1), None);
    }
}
<commit_msg>auto merge of #6677 : yjh0502/rust/smallintset, r=graydon<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */

use core::container::{Container, Mutable, Map, Set};
use core::old_iter::BaseIter;
use core::old_iter;
use core::option::{Some, None};
use core::util::replace;

pub struct SmallIntMap<T> {
    priv v: ~[Option<T>],
}

impl<V> Container for SmallIntMap<V> {
    /// Return the number of elements in the map
    fn len(&const self) -> uint {
        let mut sz = 0;
        for uint::range(0, vec::uniq_len(&const self.v)) |i| {
            match self.v[i] {
                Some(_) => sz += 1,
                None => {}
            }
        }
        sz
    }

    /// Return true if the map contains no elements
    fn is_empty(&const self) -> bool { self.len() == 0 }
}

impl<V> Mutable for SmallIntMap<V> {
    /// Clear the map, removing all key-value pairs.
    fn clear(&mut self) { self.v.clear() }
}

impl<V> Map<uint, V> for SmallIntMap<V> {
    /// Return true if the map contains a value for the specified key
    fn contains_key(&self, key: &uint) -> bool {
        self.find(key).is_some()
    }

    /// Visit all key-value pairs in order
    fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool {
        for uint::range(0, self.v.len()) |i| {
            match self.v[i] {
              Some(ref elt) => if !it(&i, elt) { return false; },
              None => ()
            }
        }
        return true;
    }

    /// Visit all keys in order
    fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool {
        self.each(|k, _| blk(k))
    }

    /// Visit all values in order
    fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool {
        self.each(|_, v| blk(v))
    }

    /// Iterate over the map and mutate the contained values
    fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool {
        for uint::range(0, self.v.len()) |i| {
            match self.v[i] {
              Some(ref mut elt) => if !it(&i, elt) { return false; },
              None => ()
            }
        }
        return true;
    }

    /// Return a reference to the value corresponding to the key
    fn find<'a>(&'a self, key: &uint) -> Option<&'a V> {
        if *key < self.v.len() {
            match self.v[*key] {
              Some(ref value) => Some(value),
              None => None
            }
        } else {
            None
        }
    }

    /// Return a mutable reference to the value corresponding to the key
    fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> {
        if *key < self.v.len() {
            match self.v[*key] {
              Some(ref mut value) => Some(value),
              None => None
            }
        } else {
            None
        }
    }

    /// Insert a key-value pair into the map. An existing value for a
    /// key is replaced by the new value. Return true if the key did
    /// not already exist in the map.
    fn insert(&mut self, key: uint, value: V) -> bool {
        let exists = self.contains_key(&key);
        let len = self.v.len();
        if len <= key {
            vec::grow_fn(&mut self.v, key - len + 1, |_| None);
        }
        self.v[key] = Some(value);
        !exists
    }

    /// Remove a key-value pair from the map. Return true if the key
    /// was present in the map, otherwise false.
    fn remove(&mut self, key: &uint) -> bool {
        self.pop(key).is_some()
    }

    /// Insert a key-value pair from the map. If the key already had a value
    /// present in the map, that value is returned. Otherwise None is returned.
    fn swap(&mut self, key: uint, value: V) -> Option<V> {
        match self.find_mut(&key) {
            Some(loc) => { return Some(replace(loc, value)); }
            None => ()
        }
        self.insert(key, value);
        return None;
    }

    /// Removes a key from the map, returning the value at the key if the key
    /// was previously in the map.
    fn pop(&mut self, key: &uint) -> Option<V> {
        if *key >= self.v.len() {
            return None;
        }
        replace(&mut self.v[*key], None)
    }
}

pub impl<V> SmallIntMap<V> {
    /// Create an empty SmallIntMap
    fn new() -> SmallIntMap<V> { SmallIntMap{v: ~[]} }

    /// Visit all key-value pairs in reverse order
    fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool {
        for uint::range_rev(self.v.len(), 0) |i| {
            match self.v[i - 1] {
              Some(ref elt) => if !it(i - 1, elt) { return false; },
              None => ()
            }
        }
        return true;
    }

    fn get<'a>(&'a self, key: &uint) -> &'a V {
        self.find(key).expect("key not present")
    }
}

pub impl<V:Copy> SmallIntMap<V> {
    fn update_with_key(&mut self, key: uint, val: V,
                       ff: &fn(uint, V, V) -> V) -> bool {
        let new_val = match self.find(&key) {
            None => val,
            Some(orig) => ff(key, *orig, val)
        };
        self.insert(key, new_val)
    }

    fn update(&mut self, key: uint, newval: V, ff: &fn(V, V) -> V) -> bool {
        self.update_with_key(key, newval, |_k, v, v1| ff(v,v1))
    }
}

pub struct SmallIntSet {
    priv map: SmallIntMap<()>
}

impl Container for SmallIntSet {
    /// Return the number of elements in the map
    fn len(&const self) -> uint {
        self.map.len()
    }

    /// Return true if the map contains no elements
    fn is_empty(&const self) -> bool { self.len() == 0 }
}

impl Mutable for SmallIntSet {
    /// Clear the map, removing all key-value pairs.
    fn clear(&mut self) { self.map.clear() }
}

impl BaseIter<uint> for SmallIntSet {
    /// Visit all values in order
    fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) }
    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}

impl Set<uint> for SmallIntSet {
    /// Return true if the set contains a value
    fn contains(&self, value: &uint) -> bool { self.map.contains_key(value) }

    /// Add a value to the set. Return true if the value was not already
    /// present in the set.
    fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) }

    /// Remove a value from the set. Return true if the value was
    /// present in the set.
    fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) }

    /// Return true if the set has no elements in common with `other`.
    /// This is equivalent to checking for an empty uintersection.
    fn is_disjoint(&self, other: &SmallIntSet) -> bool {
        old_iter::all(self, |v| !other.contains(v))
    }

    /// Return true if the set is a subset of another
    fn is_subset(&self, other: &SmallIntSet) -> bool {
        old_iter::all(self, |v| other.contains(v))
    }

    /// Return true if the set is a superset of another
    fn is_superset(&self, other: &SmallIntSet) -> bool {
        other.is_subset(self)
    }

    /// Visit the values representing the difference
    fn difference(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
        self.each(|v| other.contains(v) || f(v))
    }

    /// Visit the values representing the symmetric difference
    fn symmetric_difference(&self,
                            other: &SmallIntSet,
                            f: &fn(&uint) -> bool) -> bool {
        self.difference(other, f) && other.difference(self, f)
    }

    /// Visit the values representing the uintersection
    fn intersection(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
        self.each(|v| !other.contains(v) || f(v))
    }

    /// Visit the values representing the union
    fn union(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
        self.each(f) && other.each(|v| self.contains(v) || f(v))
    }
}

pub impl SmallIntSet {
    /// Create an empty SmallIntSet
    fn new() -> SmallIntSet { SmallIntSet{map: SmallIntMap::new()} }
}

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

    #[test]
    fn test_find_mut() {
        let mut m = SmallIntMap::new();
        assert!(m.insert(1, 12));
        assert!(m.insert(2, 8));
        assert!(m.insert(5, 14));
        let new = 100;
        match m.find_mut(&5) {
            None => fail!(), Some(x) => *x = new
        }
        assert_eq!(m.find(&5), Some(&new));
    }

    #[test]
    fn test_len() {
        let mut map = SmallIntMap::new();
        assert_eq!(map.len(), 0);
        assert!(map.is_empty());
        assert!(map.insert(5, 20));
        assert_eq!(map.len(), 1);
        assert!(!map.is_empty());
        assert!(map.insert(11, 12));
        assert_eq!(map.len(), 2);
        assert!(!map.is_empty());
        assert!(map.insert(14, 22));
        assert_eq!(map.len(), 3);
        assert!(!map.is_empty());
    }

    #[test]
    fn test_clear() {
        let mut map = SmallIntMap::new();
        assert!(map.insert(5, 20));
        assert!(map.insert(11, 12));
        assert!(map.insert(14, 22));
        map.clear();
        assert!(map.is_empty());
        assert!(map.find(&5).is_none());
        assert!(map.find(&11).is_none());
        assert!(map.find(&14).is_none());
    }

    #[test]
    fn test_insert_with_key() {
        let mut map = SmallIntMap::new();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert_eq!(map.find(&3).get(), &10);
        assert_eq!(map.find(&5).get(), &3);
        assert_eq!(map.find(&9).get(), &1);

        // sadly, no sevens were counted
        assert!(map.find(&7).is_none());
    }

    #[test]
    fn test_swap() {
        let mut m = SmallIntMap::new();
        assert_eq!(m.swap(1, 2), None);
        assert_eq!(m.swap(1, 3), Some(2));
        assert_eq!(m.swap(1, 4), Some(3));
    }

    #[test]
    fn test_pop() {
        let mut m = SmallIntMap::new();
        m.insert(1, 2);
        assert_eq!(m.pop(&1), Some(2));
        assert_eq!(m.pop(&1), None);
    }
}

#[cfg(test)]
mod test_set {
    use super::SmallIntSet;

    #[test]
    fn test_disjoint() {
        let mut xs = SmallIntSet::new();
        let mut ys = SmallIntSet::new();
        assert!(xs.is_disjoint(&ys));
        assert!(ys.is_disjoint(&xs));
        assert!(xs.insert(5));
        assert!(ys.insert(11));
        assert!(xs.is_disjoint(&ys));
        assert!(ys.is_disjoint(&xs));
        assert!(xs.insert(7));
        assert!(xs.insert(19));
        assert!(xs.insert(4));
        assert!(ys.insert(2));
        assert!(xs.is_disjoint(&ys));
        assert!(ys.is_disjoint(&xs));
        assert!(ys.insert(7));
        assert!(!xs.is_disjoint(&ys));
        assert!(!ys.is_disjoint(&xs));
    }

    #[test]
    fn test_subset_and_superset() {
        let mut a = SmallIntSet::new();
        assert!(a.insert(0));
        assert!(a.insert(5));
        assert!(a.insert(11));
        assert!(a.insert(7));

        let mut b = SmallIntSet::new();
        assert!(b.insert(0));
        assert!(b.insert(7));
        assert!(b.insert(19));
        assert!(b.insert(250));
        assert!(b.insert(11));
        assert!(b.insert(200));

        assert!(!a.is_subset(&b));
        assert!(!a.is_superset(&b));
        assert!(!b.is_subset(&a));
        assert!(!b.is_superset(&a));

        assert!(b.insert(5));

        assert!(a.is_subset(&b));
        assert!(!a.is_superset(&b));
        assert!(!b.is_subset(&a));
        assert!(b.is_superset(&a));
    }

    #[test]
    fn test_intersection() {
        let mut a = SmallIntSet::new();
        let mut b = SmallIntSet::new();

        assert!(a.insert(11));
        assert!(a.insert(1));
        assert!(a.insert(3));
        assert!(a.insert(77));
        assert!(a.insert(103));
        assert!(a.insert(5));

        assert!(b.insert(2));
        assert!(b.insert(11));
        assert!(b.insert(77));
        assert!(b.insert(5));
        assert!(b.insert(3));

        let mut i = 0;
        let expected = [3, 5, 11, 77];
        for a.intersection(&b) |x| {
            assert!(vec::contains(expected, x));
            i += 1
        }
        assert_eq!(i, expected.len());
    }

    #[test]
    fn test_difference() {
        let mut a = SmallIntSet::new();
        let mut b = SmallIntSet::new();

        assert!(a.insert(1));
        assert!(a.insert(3));
        assert!(a.insert(5));
        assert!(a.insert(9));
        assert!(a.insert(11));

        assert!(b.insert(3));
        assert!(b.insert(9));

        let mut i = 0;
        let expected = [1, 5, 11];
        for a.difference(&b) |x| {
            assert!(vec::contains(expected, x));
            i += 1
        }
        assert_eq!(i, expected.len());
    }

    #[test]
    fn test_symmetric_difference() {
        let mut a = SmallIntSet::new();
        let mut b = SmallIntSet::new();

        assert!(a.insert(1));
        assert!(a.insert(3));
        assert!(a.insert(5));
        assert!(a.insert(9));
        assert!(a.insert(11));

        assert!(b.insert(3));
        assert!(b.insert(9));
        assert!(b.insert(14));
        assert!(b.insert(22));

        let mut i = 0;
        let expected = [1, 5, 11, 14, 22];
        for a.symmetric_difference(&b) |x| {
            assert!(vec::contains(expected, x));
            i += 1
        }
        assert_eq!(i, expected.len());
    }

    #[test]
    fn test_union() {
        let mut a = SmallIntSet::new();
        let mut b = SmallIntSet::new();

        assert!(a.insert(1));
        assert!(a.insert(3));
        assert!(a.insert(5));
        assert!(a.insert(9));
        assert!(a.insert(11));
        assert!(a.insert(16));
        assert!(a.insert(19));
        assert!(a.insert(24));

        assert!(b.insert(1));
        assert!(b.insert(5));
        assert!(b.insert(9));
        assert!(b.insert(13));
        assert!(b.insert(19));

        let mut i = 0;
        let expected = [1, 3, 5, 9, 11, 13, 16, 19, 24];
        for a.union(&b) |x| {
            assert!(vec::contains(expected, x));
            i += 1
        }
        assert_eq!(i, expected.len());
    }
}
<|endoftext|>


<commit_before>//! Functions for affine transformations of images.

use image::{
    Pixel,
    GenericImage,
    ImageBuffer
};

use definitions::{
    Clamp,
    HasBlack,
    VecBuffer
};

use math::{
    cast
};

use conv::{
    ValueInto
};

/// How to handle pixels whose pre-image lies between input pixels.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Interpolation {
    /// Choose the nearest pixel to the pre-image of the
    /// output pixel.
    Nearest,
    /// Bilinearly interpolate between the four pixels
    /// closest to the pre-image of the output pixel.
    Bilinear
}

/// Rotate an image clockwise about provided center by theta radians.
/// The output image has the same dimensions as the input. Output pixels
/// whose pre-image lies outside the input image are black.
pub fn rotate<I>(image: &I, center: (f32, f32), theta: f32, interpolation: Interpolation)
        -> VecBuffer<I::Pixel>
        where I: GenericImage,
              I::Pixel: HasBlack + 'static,
              <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    rotate_with_default(image, center, theta, <I::Pixel as HasBlack>::black(), interpolation)
}

/// Rotate an image clockwise about its center by theta radians.
/// The output image has the same dimensions as the input. Output pixels
/// whose pre-image lies outside the input image are black.
pub fn rotate_about_center<I>(image: &I, theta: f32, interpolation: Interpolation)
        -> VecBuffer<I::Pixel>
    where I: GenericImage,
          I::Pixel: HasBlack + 'static,
          <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    let center =
        (image.width() as f32 / 2f32, image.height() as f32 / 2f32);

    rotate(image, center, theta, interpolation)
}

/// Rotate an image clockwise about provided center by theta radians.
/// The output image has the same dimensions as the input. Output pixels
/// whose pre-image lies outside the input image are set to default.
pub fn rotate_with_default<I>(
    image: &I,
    center: (f32, f32),
    theta: f32,
    default: I::Pixel,
    interpolation: Interpolation) -> VecBuffer<I::Pixel>
    where I: GenericImage,
          I::Pixel: HasBlack + 'static,
          <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    match interpolation {
        Interpolation::Nearest => rotate_nearest(image, center, theta, default),
        Interpolation::Bilinear => rotate_bilinear(image, center, theta, default)
    }
}

fn rotate_nearest<I>(
    image: &I,
    center: (f32, f32),
    theta: f32,
    default: I::Pixel) -> VecBuffer<I::Pixel>
    where I: GenericImage, I::Pixel: 'static {

    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let cos_theta = theta.cos();
    let sin_theta = theta.sin();
    let center_x  = center.0;
    let center_y  = center.1;

    for y in 0..height {
        let dy = y as f32 - center_y;
        let mut px = center_x + sin_theta * dy - cos_theta * center_x;
        let mut py = center_y + cos_theta * dy + sin_theta * center_x;

        for x in 0..width {

            let rx = px.round();
            let ry = py.round();

            let x_out_of_bounds = rx < 0f32 || rx >= width as f32;
            let y_out_of_bounds = ry < 0f32 || ry >= height as f32;

            if x_out_of_bounds || y_out_of_bounds {
                out.put_pixel(x, y, default);
            }
            else {
                let source = image.get_pixel(rx as u32, ry as u32);
                out.put_pixel(x, y, source);
            }

            px += cos_theta;
            py -= sin_theta;
        }
    }

    out
}

fn rotate_bilinear<I>(
    image: &I,
    center: (f32, f32),
    theta: f32,
    default: I::Pixel) -> VecBuffer<I::Pixel>
    where I: GenericImage,
          I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let cos_theta = theta.cos();
    let sin_theta = theta.sin();
    let center_x  = center.0;
    let center_y  = center.1;

    for y in 0..height {
        let dy = y as f32 - center_y;
        let mut px = center_x + sin_theta * dy - cos_theta * center_x;
        let mut py = center_y + cos_theta * dy + sin_theta * center_x;

        for x in 0..width {
            let left = px.floor();
            let right = left + 1f32;
            let top = py.floor();
            let bottom = top + 1f32;

            let right_weight = px - left;
            let bottom_weight = py - top;

            let x_out_of_bounds = left < 0f32 || right >= width as f32;
            let y_out_of_bounds = top < 0f32 || bottom >= height as f32;

            if x_out_of_bounds || y_out_of_bounds {
                out.put_pixel(x, y, default);
            }
            else {

                let mut top_left = image.get_pixel(left as u32, top as u32);
                let top_right = image.get_pixel(right as u32, top as u32);

                let mut bottom_left = image.get_pixel(left as u32, bottom as u32);
                let bottom_right = image.get_pixel(right as u32, bottom as u32);

                top_left.apply2(&top_right,
                    |u, v| <I::Pixel as Pixel>::Subpixel::clamp(
                        (1f32 - right_weight) * cast(u) +
                        right_weight * cast(v)));

                bottom_left.apply2(&bottom_right,
                    |u, v| <I::Pixel as Pixel>::Subpixel::clamp(
                        (1f32 - right_weight) * cast(u) +
                        right_weight * cast(v)));

                top_left.apply2(&bottom_left,
                    |u, v| <I::Pixel as Pixel>::Subpixel::clamp(
                        (1f32 - bottom_weight) * cast(u) +
                        bottom_weight * cast(v)));

                out.put_pixel(x, y, top_left);
            }

            px += cos_theta;
            py -= sin_theta;
        }
    }

    out
}

/// Translates the input image by t. Note that image coordinates increase from
/// top left to bottom right. Output pixels whose pre-image are not in the input
/// image are set to the boundary pixel in the input image nearest to their pre-image.
pub fn translate<I>(image: &I, t: (i32, i32)) -> VecBuffer<I::Pixel>
    where I: GenericImage, I::Pixel: 'static {

    use std::cmp;

    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let w = width as i32;
    let h = height as i32;

    for y in 0..out.height() {
        for x in 0..out.width() {
            let x_in = cmp::max(0, cmp::min(x as i32 - t.0, w - 1));
            let y_in = cmp::max(0, cmp::min(y as i32 - t.1, h - 1));
            let p = image.get_pixel(x_in as u32, y_in as u32);
            out.put_pixel(x, y, p);
        }
    }

    out
}

#[cfg(test)]
mod test {

    use super::{
        rotate_bilinear,
        rotate_nearest,
        translate
    };
    use utils::{
        gray_bench_image
    };
    use image::{
        GenericImage,
        GrayImage,
        ImageBuffer,
        Luma
    };
    use test;

    #[test]
    fn test_rotate_nearest_zero_radians() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00, 01, 02,
            10, 11, 12]).unwrap();

        let rotated = rotate_nearest(&image, (1f32, 0f32), 0f32, Luma([99u8]));

        assert_pixels_eq!(rotated, image);
    }

    #[test]
    fn text_rotate_nearest_quarter_turn_clockwise() {
        use std::f32;

        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00, 01, 02,
            10, 11, 12]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            11, 01, 99,
            12, 02, 99]).unwrap();

        let rotated
            = rotate_nearest(&image, (1f32, 0f32), f32::consts::PI / 2f32, Luma([99u8]));

        assert_pixels_eq!(rotated, expected);
    }

    #[test]
    fn text_rotate_nearest_half_turn_anticlockwise() {
        use std::f32;

        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00, 01, 02,
            10, 11, 12]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            12, 11, 10,
            02, 01, 00]).unwrap();

        let rotated
            = rotate_nearest(&image, (1f32, 0.5f32), -f32::consts::PI, Luma([99u8]));

        assert_pixels_eq!(rotated, expected);
    }

    #[bench]
    fn bench_rotate_nearest(b: &mut test::Bencher) {
        let mut image: GrayImage = ImageBuffer::new(200, 200);
        for pix in image.pixels_mut() {
            *pix = Luma([15u8]);
        }

        b.iter(|| {
            let rotated = rotate_nearest(&image, (3f32, 3f32), 1f32, Luma([0u8]));
            test::black_box(rotated);
            });
    }

    #[bench]
    fn bench_rotate_bilinear(b: &mut test::Bencher) {
        let mut image: GrayImage = ImageBuffer::new(200, 200);
        for pix in image.pixels_mut() {
            *pix = Luma([15u8]);
        }

        b.iter(|| {
            let rotated = rotate_bilinear(&image, (3f32, 3f32), 1f32, Luma([0u8]));
            test::black_box(rotated);
            });
    }

    #[test]
    fn test_translate_positive_x_positive_y() {
        let image: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 01, 02,
            10, 11, 12,
            20, 21, 22,]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 00, 01,
            00, 00, 01,
            10, 10, 11,]).unwrap();

        let translated = translate(&image, (1, 1));
        assert_pixels_eq!(translated, expected);
    }

    #[test]
    fn test_translate_positive_x_negative_y() {
        let image: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 01, 02,
            10, 11, 12,
            20, 21, 22,]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            10, 10, 11,
            20, 20, 21,
            20, 20, 21,]).unwrap();

        let translated = translate(&image, (1, -1));
        assert_pixels_eq!(translated, expected);
    }

    #[test]
    fn test_translate_large_x_large_y() {
        let image: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 01, 02,
            10, 11, 12,
            20, 21, 22,]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 00, 00,
            00, 00, 00,
            00, 00, 00,]).unwrap();

        // Translating by more than the image width and height
        let translated = translate(&image, (5, 5));
        assert_pixels_eq!(translated, expected);
    }

    #[bench]
    fn bench_translate(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let translated = translate(&image, (30, 30));
            test::black_box(translated);
            });
    }
}
<commit_msg>Extract interpolate method from rotate_bilinear<commit_after>//! Functions for affine transformations of images.

use image::{
    Pixel,
    GenericImage,
    ImageBuffer
};

use definitions::{
    Clamp,
    HasBlack,
    VecBuffer
};

use math::{
    cast
};

use conv::{
    ValueInto
};

/// How to handle pixels whose pre-image lies between input pixels.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Interpolation {
    /// Choose the nearest pixel to the pre-image of the
    /// output pixel.
    Nearest,
    /// Bilinearly interpolate between the four pixels
    /// closest to the pre-image of the output pixel.
    Bilinear
}

/// Rotate an image clockwise about provided center by theta radians.
/// The output image has the same dimensions as the input. Output pixels
/// whose pre-image lies outside the input image are black.
pub fn rotate<I>(image: &I, center: (f32, f32), theta: f32, interpolation: Interpolation)
        -> VecBuffer<I::Pixel>
        where I: GenericImage,
              I::Pixel: HasBlack + 'static,
              <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    rotate_with_default(image, center, theta, <I::Pixel as HasBlack>::black(), interpolation)
}

/// Rotate an image clockwise about its center by theta radians.
/// The output image has the same dimensions as the input. Output pixels
/// whose pre-image lies outside the input image are black.
pub fn rotate_about_center<I>(image: &I, theta: f32, interpolation: Interpolation)
        -> VecBuffer<I::Pixel>
    where I: GenericImage,
          I::Pixel: HasBlack + 'static,
          <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    let center =
        (image.width() as f32 / 2f32, image.height() as f32 / 2f32);

    rotate(image, center, theta, interpolation)
}

/// Rotate an image clockwise about provided center by theta radians.
/// The output image has the same dimensions as the input. Output pixels
/// whose pre-image lies outside the input image are set to default.
pub fn rotate_with_default<I>(
    image: &I,
    center: (f32, f32),
    theta: f32,
    default: I::Pixel,
    interpolation: Interpolation) -> VecBuffer<I::Pixel>
    where I: GenericImage,
          I::Pixel: HasBlack + 'static,
          <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    match interpolation {
        Interpolation::Nearest => rotate_nearest(image, center, theta, default),
        Interpolation::Bilinear => rotate_bilinear(image, center, theta, default)
    }
}

fn rotate_nearest<I>(
    image: &I,
    center: (f32, f32),
    theta: f32,
    default: I::Pixel) -> VecBuffer<I::Pixel>
    where I: GenericImage, I::Pixel: 'static {

    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let cos_theta = theta.cos();
    let sin_theta = theta.sin();
    let center_x  = center.0;
    let center_y  = center.1;

    for y in 0..height {
        let dy = y as f32 - center_y;
        let mut px = center_x + sin_theta * dy - cos_theta * center_x;
        let mut py = center_y + cos_theta * dy + sin_theta * center_x;

        for x in 0..width {

            let rx = px.round();
            let ry = py.round();

            let x_out_of_bounds = rx < 0f32 || rx >= width as f32;
            let y_out_of_bounds = ry < 0f32 || ry >= height as f32;

            if x_out_of_bounds || y_out_of_bounds {
                out.put_pixel(x, y, default);
            }
            else {
                let source = image.get_pixel(rx as u32, ry as u32);
                out.put_pixel(x, y, source);
            }

            px += cos_theta;
            py -= sin_theta;
        }
    }

    out
}

fn rotate_bilinear<I>(
    image: &I,
    center: (f32, f32),
    theta: f32,
    default: I::Pixel) -> VecBuffer<I::Pixel>
    where I: GenericImage,
          I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32> {

    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let cos_theta = theta.cos();
    let sin_theta = theta.sin();
    let center_x  = center.0;
    let center_y  = center.1;

    for y in 0..height {
        let dy = y as f32 - center_y;
        let mut px = center_x + sin_theta * dy - cos_theta * center_x;
        let mut py = center_y + cos_theta * dy + sin_theta * center_x;

        for x in 0..width {
            let left = px.floor();
            let right = left + 1f32;
            let top = py.floor();
            let bottom = top + 1f32;

            let right_weight = px - left;
            let bottom_weight = py - top;

            let x_out_of_bounds = left < 0f32 || right >= width as f32;
            let y_out_of_bounds = top < 0f32 || bottom >= height as f32;

            if x_out_of_bounds || y_out_of_bounds {
                out.put_pixel(x, y, default);
            }
            else {
                let sum = interpolate(
                    image.get_pixel(left as u32, top as u32),
                    image.get_pixel(right as u32, top as u32),
                    image.get_pixel(left as u32, bottom as u32),
                    image.get_pixel(right as u32, bottom as u32),
                    right_weight, bottom_weight);

                out.put_pixel(x, y, sum);
            }

            px += cos_theta;
            py -= sin_theta;
        }
    }

    out
}

fn interpolate<P>(
    top_left: P,
    top_right: P,
    bottom_left: P,
    bottom_right: P,
    right_weight: f32,
    bottom_weight: f32) -> P
    where P: Pixel,
          P::Subpixel: ValueInto<f32> + Clamp<f32> {

    let top = top_left.map2(&top_right,
       |u, v| P::Subpixel::clamp(
           (1f32 - right_weight) * cast(u) + right_weight * cast(v)));

    let bottom = bottom_left.map2(&bottom_right,
        |u, v| P::Subpixel::clamp(
            (1f32 - right_weight) * cast(u) + right_weight * cast(v)));

    top.map2(&bottom,
        |u, v| P::Subpixel::clamp(
             (1f32 - bottom_weight) * cast(u) + bottom_weight * cast(v)))
}

/// Translates the input image by t. Note that image coordinates increase from
/// top left to bottom right. Output pixels whose pre-image are not in the input
/// image are set to the boundary pixel in the input image nearest to their pre-image.
pub fn translate<I>(image: &I, t: (i32, i32)) -> VecBuffer<I::Pixel>
    where I: GenericImage, I::Pixel: 'static {

    use std::cmp;

    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let w = width as i32;
    let h = height as i32;

    for y in 0..out.height() {
        for x in 0..out.width() {
            let x_in = cmp::max(0, cmp::min(x as i32 - t.0, w - 1));
            let y_in = cmp::max(0, cmp::min(y as i32 - t.1, h - 1));
            let p = image.get_pixel(x_in as u32, y_in as u32);
            out.put_pixel(x, y, p);
        }
    }

    out
}

#[cfg(test)]
mod test {

    use super::{
        rotate_bilinear,
        rotate_nearest,
        translate
    };
    use utils::{
        gray_bench_image
    };
    use image::{
        GenericImage,
        GrayImage,
        ImageBuffer,
        Luma
    };
    use test;

    #[test]
    fn test_rotate_nearest_zero_radians() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00, 01, 02,
            10, 11, 12]).unwrap();

        let rotated = rotate_nearest(&image, (1f32, 0f32), 0f32, Luma([99u8]));

        assert_pixels_eq!(rotated, image);
    }

    #[test]
    fn text_rotate_nearest_quarter_turn_clockwise() {
        use std::f32;

        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00, 01, 02,
            10, 11, 12]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            11, 01, 99,
            12, 02, 99]).unwrap();

        let rotated
            = rotate_nearest(&image, (1f32, 0f32), f32::consts::PI / 2f32, Luma([99u8]));

        assert_pixels_eq!(rotated, expected);
    }

    #[test]
    fn text_rotate_nearest_half_turn_anticlockwise() {
        use std::f32;

        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00, 01, 02,
            10, 11, 12]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            12, 11, 10,
            02, 01, 00]).unwrap();

        let rotated
            = rotate_nearest(&image, (1f32, 0.5f32), -f32::consts::PI, Luma([99u8]));

        assert_pixels_eq!(rotated, expected);
    }

    #[bench]
    fn bench_rotate_nearest(b: &mut test::Bencher) {
        let mut image: GrayImage = ImageBuffer::new(200, 200);
        for pix in image.pixels_mut() {
            *pix = Luma([15u8]);
        }

        b.iter(|| {
            let rotated = rotate_nearest(&image, (3f32, 3f32), 1f32, Luma([0u8]));
            test::black_box(rotated);
            });
    }

    #[bench]
    fn bench_rotate_bilinear(b: &mut test::Bencher) {
        let mut image: GrayImage = ImageBuffer::new(200, 200);
        for pix in image.pixels_mut() {
            *pix = Luma([15u8]);
        }

        b.iter(|| {
            let rotated = rotate_bilinear(&image, (3f32, 3f32), 1f32, Luma([0u8]));
            test::black_box(rotated);
            });
    }

    #[test]
    fn test_translate_positive_x_positive_y() {
        let image: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 01, 02,
            10, 11, 12,
            20, 21, 22,]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 00, 01,
            00, 00, 01,
            10, 10, 11,]).unwrap();

        let translated = translate(&image, (1, 1));
        assert_pixels_eq!(translated, expected);
    }

    #[test]
    fn test_translate_positive_x_negative_y() {
        let image: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 01, 02,
            10, 11, 12,
            20, 21, 22,]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            10, 10, 11,
            20, 20, 21,
            20, 20, 21,]).unwrap();

        let translated = translate(&image, (1, -1));
        assert_pixels_eq!(translated, expected);
    }

    #[test]
    fn test_translate_large_x_large_y() {
        let image: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 01, 02,
            10, 11, 12,
            20, 21, 22,]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 3, vec![
            00, 00, 00,
            00, 00, 00,
            00, 00, 00,]).unwrap();

        // Translating by more than the image width and height
        let translated = translate(&image, (5, 5));
        assert_pixels_eq!(translated, expected);
    }

    #[bench]
    fn bench_translate(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let translated = translate(&image, (30, 30));
            test::black_box(translated);
            });
    }
}
<|endoftext|>


<commit_before>use acpi;
use device;
use interrupts;
use memory;
use memory::MemoryController;
use multiboot2;
use vga_buffer;
use kernel_messaging;
use spin::Mutex;

/// Enable the NXE bit to allow NO_EXECUTE pages.
fn enable_nxe_bit() {
    use x86_64::registers::msr::{IA32_EFER, rdmsr, wrmsr};

    let nxe_bit = 1 << 11;
    unsafe {
        let efer = rdmsr(IA32_EFER);
        wrmsr(IA32_EFER, efer | nxe_bit);
    }
}

/// This enables the write protect bit in order to enable write protection on kernel mode.
fn enable_write_protect_bit() {
    use x86_64::registers::control_regs::{cr0, cr0_write, Cr0};

    unsafe { cr0_write(cr0() | Cr0::WRITE_PROTECT) };
}

extern {
    /// Kernel main function
    fn kmain(memory_controller: &mut MemoryController) -> !;
}

/// Entry point for the Rust code.
#[no_mangle]
pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! {
    // Initialize all the arch components in a different scope than the kernel's main function call.

    // clear the console screen
    vga_buffer::clear_screen();

    // print out a welcome message
    println!("kernel: botting");

    let boot_info = unsafe { multiboot2::load(multiboot_information_address) };

    // enable NXE bit, to allow define none executable pages.
    enable_nxe_bit();

    // set write protect bit in order to enable write protection on kernel mode.
    enable_write_protect_bit();

    // set up guard page and map the heap pages
    let mut memory_controller = memory::init(boot_info);

    // Initialize IDT
    interrupts::init(&mut memory_controller);

    // Initialize devices
    device::init(&mut memory_controller);

    // Read ACPI tables, starts APs
    acpi::init(&mut memory_controller);

    // Initialize all the non-core devices
    device::init_non_core();

    //  //TODO test porposals only, remove later
    vga_buffer::WRITER.lock().set_colors(vga_buffer::Color::Blue, vga_buffer::Color::Black);
    println!("Set color test");
    kernel_messaging::kprint(kernel_messaging::MessageType::DEFAULT,"Default message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::SUCCESS,"Success message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::ERROR,"Error message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::WARNING,"Warning message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::INFO,"Info message!");
    println!("Back to default");

    // Call the kernel main function
    unsafe { kmain(&mut memory_controller); }
}
<commit_msg>Store the number of CPUs<commit_after>use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use acpi;
use device;
use interrupts;
use memory;
use memory::MemoryController;
use multiboot2;
use vga_buffer;
use kernel_messaging;
use spin::Mutex;

/// This is used to count the number of CPUs on the system
pub static CPU_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

///  Get the number of CPUs currently active
pub fn cpu_count() -> usize {
    CPU_COUNT.load(Ordering::Relaxed)
}

/// Enable the NXE bit to allow NO_EXECUTE pages.
fn enable_nxe_bit() {
    use x86_64::registers::msr::{IA32_EFER, rdmsr, wrmsr};

    let nxe_bit = 1 << 11;
    unsafe {
        let efer = rdmsr(IA32_EFER);
        wrmsr(IA32_EFER, efer | nxe_bit);
    }
}

/// This enables the write protect bit in order to enable write protection on kernel mode.
fn enable_write_protect_bit() {
    use x86_64::registers::control_regs::{cr0, cr0_write, Cr0};

    unsafe { cr0_write(cr0() | Cr0::WRITE_PROTECT) };
}

extern {
    /// Kernel main function
    fn kmain(memory_controller: &mut MemoryController) -> !;
}

/// Entry point for the Rust code.
#[no_mangle]
pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! {
    // Initialize all the arch components in a different scope than the kernel's main function call.

    // clear the console screen
    vga_buffer::clear_screen();

    // print out a welcome message
    println!("kernel: botting");

    let boot_info = unsafe { multiboot2::load(multiboot_information_address) };

    // enable NXE bit, to allow define none executable pages.
    enable_nxe_bit();

    // set write protect bit in order to enable write protection on kernel mode.
    enable_write_protect_bit();

    // set up guard page and map the heap pages
    let mut memory_controller = memory::init(boot_info);

    // Initialize IDT
    interrupts::init(&mut memory_controller);

    // Initialize devices
    device::init(&mut memory_controller);

    // Read ACPI tables, starts APs
    acpi::init(&mut memory_controller);

    // Initialize all the non-core devices
    device::init_non_core();

    // reset CPU count
    CPU_COUNT.store(1, Ordering::SeqCst);

    //  //TODO test porposals only, remove later
    vga_buffer::WRITER.lock().set_colors(vga_buffer::Color::Blue, vga_buffer::Color::Black);
    println!("Set color test");
    kernel_messaging::kprint(kernel_messaging::MessageType::DEFAULT,"Default message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::SUCCESS,"Success message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::ERROR,"Error message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::WARNING,"Warning message!");
    kernel_messaging::kprint(kernel_messaging::MessageType::INFO,"Info message!");
    println!("Back to default");

    // Call the kernel main function
    unsafe { kmain(&mut memory_controller); }
}
<|endoftext|>


<commit_before>use bls::{PublicKey, verify_proof_of_possession};
use types::{BeaconState, Deposit, ValidatorRecord, ValidatorStatus};
use spec::ChainSpec;

/// The size of a validators deposit in GWei.
pub const DEPOSIT_GWEI: u64 = 32_000_000_000;

#[derive(Debug, PartialEq, Clone)]
pub enum ValidatorInductionError {
    InvalidShard,
    InvaidProofOfPossession,
    InvalidWithdrawalCredentials
}

pub fn process_deposit(
    state: &mut BeaconState,
    deposit: &Deposit,
    spec: &ChainSpec)
-> Result<usize, ValidatorInductionError> {
    let deposit_input = &deposit.deposit_data.deposit_input;
    let deposit_data = &deposit.deposit_data;

    if !verify_proof_of_possession(&deposit_input.proof_of_possession, &deposit_input.pubkey) {
        return Err(ValidatorInductionError::InvaidProofOfPossession);
    }

    let validator_index = state.validator_registry.iter()
        .position(|validator| validator.pubkey == deposit_input.pubkey);

    match validator_index {
        Some(i) => {
            if state.validator_registry[i].withdrawal_credentials == deposit_input.withdrawal_credentials {
                state.validator_balances[i] += deposit_data.value;
                return Ok(i);
            }

            Err(ValidatorInductionError::InvalidWithdrawalCredentials)
        },
        None => {
            let validator = ValidatorRecord {
                pubkey: deposit_input.pubkey.clone(),
                withdrawal_credentials: deposit_input.withdrawal_credentials,
                randao_commitment: deposit_input.randao_commitment,
                randao_layers: 0,
                status: ValidatorStatus::PendingActivation,
                latest_status_change_slot: state.validator_registry_latest_change_slot.clone(),
                exit_count: 0
            };

            match min_empty_validator_index(state, spec) {
                Some(i) => {
                    state.validator_registry[i] = validator;
                    state.validator_balances[i] = deposit_data.value;
                    Ok(i)
                },
                None => {
                    state.validator_registry.push(validator);
                    state.validator_balances.push(deposit_data.value);
                    Ok(state.validator_registry.len() - 1)
                }
            }
        }
    }
}

fn min_empty_validator_index(
    state: &BeaconState,
    spec: &ChainSpec
) -> Option<usize> {
    for i in 0..state.validator_registry.len() {
        if state.validator_balances[i] == 0
            && state.validator_registry[i].latest_status_change_slot
                + spec.zero_balance_validator_ttl <= state.slot {
            return Some(i);
        }
    }
    None
}

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

    use bls::{Keypair, Signature};
    use hashing::proof_of_possession_hash;
    use types::{Hash256, DepositData, DepositInput};

    fn get_deposit() -> Deposit {
        let kp = Keypair::random();
        let deposit_input = DepositInput {
            pubkey: kp.pk.clone(),
            withdrawal_credentials: Hash256::zero(),
            randao_commitment: Hash256::zero(),
            proof_of_possession: get_proof_of_possession(&kp)
        };
        let deposit_data = DepositData {
            deposit_input: deposit_input,
            value: DEPOSIT_GWEI,
            timestamp: 0
        };
        Deposit {
            merkle_branch: Vec::new(),
            merkle_tree_index: 0,
            deposit_data: deposit_data
        }
    }

    fn deposit_equals_record(dep: &Deposit, rec: &ValidatorRecord) -> bool {
        (dep.deposit_data.deposit_input.pubkey == rec.pubkey)
            & (dep.deposit_data.deposit_input.withdrawal_credentials == rec.withdrawal_credentials)
            & (dep.deposit_data.deposit_input.randao_commitment == rec.randao_commitment)
            //& (verify_proof_of_possession(&reg.proof_of_possession, &rec.pubkey))
    }

    /// Generate a proof of possession for some keypair.
    fn get_proof_of_possession(kp: &Keypair) -> Signature {
        let pop_message = proof_of_possession_hash(&kp.pk.as_bytes());
        Signature::new_hashed(&pop_message, &kp.sk)
    }

    #[test]
    fn test_process_deposit_valid_empty_validators() {
        let mut state = BeaconState::default();
        let deposit = get_deposit();
        let spec = ChainSpec::foundation();

        let result = process_deposit(&mut state, &deposit, &spec);

        assert_eq!(result.unwrap(), 0);
        assert!(deposit_equals_record(&deposit, &state.validator_registry[0]));
        assert_eq!(state.validator_registry.len(), 1);
        assert_eq!(state.validator_balances.len(), 1);
    }

    #[test]
    fn test_process_deposits_empty_validators() {
        let mut state = BeaconState::default();
        let spec = ChainSpec::foundation();

        for i in 0..5 {
            let deposit = get_deposit();
            let result = process_deposit(&mut state, &deposit, &spec);
            assert_eq!(result.unwrap(), i);
            assert!(deposit_equals_record(&deposit, &state.validator_registry[i]));
            assert_eq!(state.validator_registry.len(), i + 1);
            assert_eq!(state.validator_balances.len(), i + 1);
        }
    }

    #[test]
    fn test_process_deposit_top_out() {
        let mut state = BeaconState::default();
        let spec = ChainSpec::foundation();

        let deposit = get_deposit();
        let (mut validator, _) = ValidatorRecord::zero_with_thread_rand_keypair();
        validator.pubkey = deposit.deposit_data.deposit_input.pubkey.clone();
        validator.withdrawal_credentials = deposit.deposit_data.deposit_input.withdrawal_credentials;
        validator.randao_commitment = deposit.deposit_data.deposit_input.randao_commitment;

        state.validator_registry.push(validator);
        state.validator_balances.push(DEPOSIT_GWEI);

        let result = process_deposit(&mut state, &deposit, &spec);

        assert_eq!(result.unwrap(), 0);
        assert!(deposit_equals_record(&deposit, &state.validator_registry[0]));
        assert_eq!(state.validator_balances[0], DEPOSIT_GWEI * 2);
        assert_eq!(state.validator_registry.len(), 1);
        assert_eq!(state.validator_balances.len(), 1);
    }

    #[test]
    fn test_process_deposit_replace_validator() {
        let mut state = BeaconState::default();
        let spec = ChainSpec::foundation();

        let (mut validator, _) = ValidatorRecord::zero_with_thread_rand_keypair();
        state.validator_registry.push(validator);
        state.validator_balances.push(0);

        let deposit = get_deposit();
        state.slot = spec.zero_balance_validator_ttl;

        let result = process_deposit(&mut state, &deposit, &spec);

        assert_eq!(result.unwrap(), 0);
        assert!(deposit_equals_record(&deposit, &state.validator_registry[0]));
        assert_eq!(state.validator_balances[0], DEPOSIT_GWEI);
        assert_eq!(state.validator_registry.len(), 1);
        assert_eq!(state.validator_balances.len(), 1);
    }
}
<commit_msg>tests passing again<commit_after>use bls::{PublicKey, verify_proof_of_possession};
use types::{BeaconState, Deposit, ValidatorRecord, ValidatorStatus};
use spec::ChainSpec;

/// The size of a validators deposit in GWei.
pub const DEPOSIT_GWEI: u64 = 32_000_000_000;

#[derive(Debug, PartialEq, Clone)]
pub enum ValidatorInductionError {
    InvalidShard,
    InvaidProofOfPossession,
    InvalidWithdrawalCredentials
}

pub fn process_deposit(
    state: &mut BeaconState,
    deposit: &Deposit,
    spec: &ChainSpec)
-> Result<usize, ValidatorInductionError> {
    let deposit_input = &deposit.deposit_data.deposit_input;
    let deposit_data = &deposit.deposit_data;

    if !verify_proof_of_possession(&deposit_input.proof_of_possession, &deposit_input.pubkey) {
        return Err(ValidatorInductionError::InvaidProofOfPossession);
    }

    let validator_index = state.validator_registry.iter()
        .position(|validator| validator.pubkey == deposit_input.pubkey);

    match validator_index {
        Some(i) => {
            if state.validator_registry[i].withdrawal_credentials == deposit_input.withdrawal_credentials {
                state.validator_balances[i] += deposit_data.value;
                return Ok(i);
            }

            Err(ValidatorInductionError::InvalidWithdrawalCredentials)
        },
        None => {
            let validator = ValidatorRecord {
                pubkey: deposit_input.pubkey.clone(),
                withdrawal_credentials: deposit_input.withdrawal_credentials,
                randao_commitment: deposit_input.randao_commitment,
                randao_layers: 0,
                status: ValidatorStatus::PendingActivation,
                latest_status_change_slot: state.validator_registry_latest_change_slot,
                exit_count: 0
            };

            match min_empty_validator_index(state, spec) {
                Some(i) => {
                    state.validator_registry[i] = validator;
                    state.validator_balances[i] = deposit_data.value;
                    Ok(i)
                },
                None => {
                    state.validator_registry.push(validator);
                    state.validator_balances.push(deposit_data.value);
                    Ok(state.validator_registry.len() - 1)
                }
            }
        }
    }
}

fn min_empty_validator_index(
    state: &BeaconState,
    spec: &ChainSpec
) -> Option<usize> {
    for i in 0..state.validator_registry.len() {
        if state.validator_balances[i] == 0
            && state.validator_registry[i].latest_status_change_slot
                + spec.zero_balance_validator_ttl <= state.slot {
            return Some(i);
        }
    }
    None
}

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

    use bls::{Keypair, Signature, create_proof_of_possession};
    use hashing::canonical_hash;
    use types::{Hash256, DepositData, DepositInput};

    fn get_deposit() -> Deposit {
        let kp = Keypair::random();
        let deposit_input = DepositInput {
            pubkey: kp.pk.clone(),
            withdrawal_credentials: Hash256::zero(),
            randao_commitment: Hash256::zero(),
            proof_of_possession: create_proof_of_possession(&kp)
        };
        let deposit_data = DepositData {
            deposit_input: deposit_input,
            value: DEPOSIT_GWEI,
            timestamp: 0
        };
        Deposit {
            merkle_branch: Vec::new(),
            merkle_tree_index: 0,
            deposit_data: deposit_data
        }
    }

    fn deposit_equals_record(dep: &Deposit, rec: &ValidatorRecord) -> bool {
        (dep.deposit_data.deposit_input.pubkey == rec.pubkey)
            & (dep.deposit_data.deposit_input.withdrawal_credentials == rec.withdrawal_credentials)
            & (dep.deposit_data.deposit_input.randao_commitment == rec.randao_commitment)
            //& (verify_proof_of_possession(&reg.proof_of_possession, &rec.pubkey))
    }

    #[test]
    fn test_process_deposit_valid_empty_validators() {
        let mut state = BeaconState::default();
        let deposit = get_deposit();
        let spec = ChainSpec::foundation();

        let result = process_deposit(&mut state, &deposit, &spec);

        assert_eq!(result.unwrap(), 0);
        assert!(deposit_equals_record(&deposit, &state.validator_registry[0]));
        assert_eq!(state.validator_registry.len(), 1);
        assert_eq!(state.validator_balances.len(), 1);
    }

    #[test]
    fn test_process_deposits_empty_validators() {
        let mut state = BeaconState::default();
        let spec = ChainSpec::foundation();

        for i in 0..5 {
            let deposit = get_deposit();
            let result = process_deposit(&mut state, &deposit, &spec);
            assert_eq!(result.unwrap(), i);
            assert!(deposit_equals_record(&deposit, &state.validator_registry[i]));
            assert_eq!(state.validator_registry.len(), i + 1);
            assert_eq!(state.validator_balances.len(), i + 1);
        }
    }

    #[test]
    fn test_process_deposit_top_out() {
        let mut state = BeaconState::default();
        let spec = ChainSpec::foundation();

        let deposit = get_deposit();
        let (mut validator, _) = ValidatorRecord::zero_with_thread_rand_keypair();
        validator.pubkey = deposit.deposit_data.deposit_input.pubkey.clone();
        validator.withdrawal_credentials = deposit.deposit_data.deposit_input.withdrawal_credentials;
        validator.randao_commitment = deposit.deposit_data.deposit_input.randao_commitment;

        state.validator_registry.push(validator);
        state.validator_balances.push(DEPOSIT_GWEI);

        let result = process_deposit(&mut state, &deposit, &spec);

        assert_eq!(result.unwrap(), 0);
        assert!(deposit_equals_record(&deposit, &state.validator_registry[0]));
        assert_eq!(state.validator_balances[0], DEPOSIT_GWEI * 2);
        assert_eq!(state.validator_registry.len(), 1);
        assert_eq!(state.validator_balances.len(), 1);
    }

    #[test]
    fn test_process_deposit_replace_validator() {
        let mut state = BeaconState::default();
        let spec = ChainSpec::foundation();

        let (mut validator, _) = ValidatorRecord::zero_with_thread_rand_keypair();
        state.validator_registry.push(validator);
        state.validator_balances.push(0);

        let deposit = get_deposit();
        state.slot = spec.zero_balance_validator_ttl;

        let result = process_deposit(&mut state, &deposit, &spec);

        assert_eq!(result.unwrap(), 0);
        assert!(deposit_equals_record(&deposit, &state.validator_registry[0]));
        assert_eq!(state.validator_balances[0], DEPOSIT_GWEI);
        assert_eq!(state.validator_registry.len(), 1);
        assert_eq!(state.validator_balances.len(), 1);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature = "heapsize")] use heapsize::HeapSizeOf;
use host::Host;
use idna::domain_to_unicode;
use parser::default_port;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use Url;

pub fn url_origin(url: &Url) -> Origin {
    let scheme = url.scheme();
    match scheme {
        "blob" => {
            let result = Url::parse(url.path());
            match result {
                Ok(ref url) => url_origin(url),
                Err(_)  => Origin::new_opaque()
            }
        },
        "ftp" | "gopher" | "http" | "https" | "ws" | "wss" => {
            Origin::Tuple(scheme.to_owned(), url.host().unwrap().to_owned(),
                url.port_or_known_default().unwrap())
        },
        // TODO: Figure out what to do if the scheme is a file
        "file" => Origin::new_opaque(),
        _ => Origin::new_opaque()
    }
}

/// The origin of an URL
///
/// Two URLs with the same origin are considered
/// to originate from the same entity and can therefore trust
/// each other.
///
/// The origin is determined based on the scheme as follows:
///
/// - If the scheme is "blob" the origin is the origin of the
///   URL contained in the path component. If parsing fails,
///   it is an opaque origin.
/// - If the scheme is "ftp", "gopher", "http", "https", "ws", or "wss",
///   then the origin is a tuple of the scheme, host, and port.
/// - If the scheme is anything else, the origin is opaque, meaning
///   the URL does not have the same origin as any other URL.
///
/// For more information see <https://url.spec.whatwg.org/#origin>
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Origin {
    /// A globally unique identifier
    Opaque(OpaqueOrigin),

    /// Consists of the URL's scheme, host and port
    Tuple(String, Host<String>, u16)
}

#[cfg(feature = "heapsize")]
impl HeapSizeOf for Origin {
    fn heap_size_of_children(&self) -> usize {
        match *self {
            Origin::Tuple(ref scheme, ref host, _) => {
                scheme.heap_size_of_children() +
                host.heap_size_of_children()
            },
            _ => 0,
        }
    }
}

impl Origin {
    /// Creates a new opaque origin that is only equal to itself.
    pub fn new_opaque() -> Origin {
        static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
        Origin::Opaque(OpaqueOrigin(COUNTER.fetch_add(1, Ordering::SeqCst)))
    }

    /// Return whether this origin is a (scheme, host, port) tuple
    /// (as opposed to an opaque origin).
    pub fn is_tuple(&self) -> bool {
        matches!(*self, Origin::Tuple(..))
    }

    /// <https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin>
    pub fn ascii_serialization(&self) -> String {
        match *self {
            Origin::Opaque(_) => "null".to_owned(),
            Origin::Tuple(ref scheme, ref host, port) => {
                if default_port(scheme) == Some(port) {
                    format!("{}://{}", scheme, host)
                } else {
                    format!("{}://{}:{}", scheme, host, port)
                }
            }
        }
    }

    /// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
    pub fn unicode_serialization(&self) -> String {
        match *self {
            Origin::Opaque(_) => "null".to_owned(),
            Origin::Tuple(ref scheme, ref host, port) => {
                let host = match *host {
                    Host::Domain(ref domain) => {
                        let (domain, _errors) = domain_to_unicode(domain);
                        Host::Domain(domain)
                    }
                    _ => host.clone()
                };
                if default_port(scheme) == Some(port) {
                    format!("{}://{}", scheme, host)
                } else {
                    format!("{}://{}:{}", scheme, host, port)
                }
            }
        }
    }
}

/// Opaque identifier for URLs that have file or other schemes
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub struct OpaqueOrigin(usize);

#[cfg(feature = "heapsize")]
known_heap_size!(0, OpaqueOrigin);
<commit_msg>Replace deprecated ATOMIC_USIZE_INIT by AtomicUsize::new<commit_after>// Copyright 2016 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature = "heapsize")] use heapsize::HeapSizeOf;
use host::Host;
use idna::domain_to_unicode;
use parser::default_port;
use std::sync::atomic::{AtomicUsize, Ordering};
use Url;

pub fn url_origin(url: &Url) -> Origin {
    let scheme = url.scheme();
    match scheme {
        "blob" => {
            let result = Url::parse(url.path());
            match result {
                Ok(ref url) => url_origin(url),
                Err(_)  => Origin::new_opaque()
            }
        },
        "ftp" | "gopher" | "http" | "https" | "ws" | "wss" => {
            Origin::Tuple(scheme.to_owned(), url.host().unwrap().to_owned(),
                url.port_or_known_default().unwrap())
        },
        // TODO: Figure out what to do if the scheme is a file
        "file" => Origin::new_opaque(),
        _ => Origin::new_opaque()
    }
}

/// The origin of an URL
///
/// Two URLs with the same origin are considered
/// to originate from the same entity and can therefore trust
/// each other.
///
/// The origin is determined based on the scheme as follows:
///
/// - If the scheme is "blob" the origin is the origin of the
///   URL contained in the path component. If parsing fails,
///   it is an opaque origin.
/// - If the scheme is "ftp", "gopher", "http", "https", "ws", or "wss",
///   then the origin is a tuple of the scheme, host, and port.
/// - If the scheme is anything else, the origin is opaque, meaning
///   the URL does not have the same origin as any other URL.
///
/// For more information see <https://url.spec.whatwg.org/#origin>
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Origin {
    /// A globally unique identifier
    Opaque(OpaqueOrigin),

    /// Consists of the URL's scheme, host and port
    Tuple(String, Host<String>, u16)
}

#[cfg(feature = "heapsize")]
impl HeapSizeOf for Origin {
    fn heap_size_of_children(&self) -> usize {
        match *self {
            Origin::Tuple(ref scheme, ref host, _) => {
                scheme.heap_size_of_children() +
                host.heap_size_of_children()
            },
            _ => 0,
        }
    }
}

impl Origin {
    /// Creates a new opaque origin that is only equal to itself.
    pub fn new_opaque() -> Origin {
        static COUNTER: AtomicUsize = AtomicUsize::new(0);
        Origin::Opaque(OpaqueOrigin(COUNTER.fetch_add(1, Ordering::SeqCst)))
    }

    /// Return whether this origin is a (scheme, host, port) tuple
    /// (as opposed to an opaque origin).
    pub fn is_tuple(&self) -> bool {
        matches!(*self, Origin::Tuple(..))
    }

    /// <https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin>
    pub fn ascii_serialization(&self) -> String {
        match *self {
            Origin::Opaque(_) => "null".to_owned(),
            Origin::Tuple(ref scheme, ref host, port) => {
                if default_port(scheme) == Some(port) {
                    format!("{}://{}", scheme, host)
                } else {
                    format!("{}://{}:{}", scheme, host, port)
                }
            }
        }
    }

    /// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
    pub fn unicode_serialization(&self) -> String {
        match *self {
            Origin::Opaque(_) => "null".to_owned(),
            Origin::Tuple(ref scheme, ref host, port) => {
                let host = match *host {
                    Host::Domain(ref domain) => {
                        let (domain, _errors) = domain_to_unicode(domain);
                        Host::Domain(domain)
                    }
                    _ => host.clone()
                };
                if default_port(scheme) == Some(port) {
                    format!("{}://{}", scheme, host)
                } else {
                    format!("{}://{}:{}", scheme, host, port)
                }
            }
        }
    }
}

/// Opaque identifier for URLs that have file or other schemes
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub struct OpaqueOrigin(usize);

#[cfg(feature = "heapsize")]
known_heap_size!(0, OpaqueOrigin);
<|endoftext|>


<commit_before>use oak_runtime::stream::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::PNode;

grammar! bailey {
    use ast::PNode;
    use ast::Node::*;
    use ast::BinOp;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = ((decl / stmt) terminator?)* > program

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = def_kw ident lparen param_list rparen block > method_decl

    block
        = lbracket ((stmt / expr) terminator?)* rbracket > block

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = ident bind_op expr > assign_stmt

    expr
        = cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal
        / constant
        / ident
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit
        / array_lit
        / map_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit
    array_lit = lsqbracket expr (comma expr)* rsqbracket > array_lit

    map_entry =  (expr colon expr)
    map_lit = lbracket map_entry (comma map_entry)* rbracket > map_lit

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    lsqbracket = "[" spacing
    rsqbracket = "]" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn int_lit(raw_text: Vec<char>) -> PNode {
        PNode(IntLit(to_number(raw_text)))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> PNode {
        integer.push('.');
        PNode(FltLit(to_float(combine(integer, fractional))))
    }

    fn string_lit(raw_text: Vec<char>) -> PNode {
        PNode(StrLit(to_string(raw_text)))
    }

    fn array_lit(first: PNode, rest: Vec<PNode>) -> PNode {
        PNode(ArrLit(combine_one_with_many(first, rest)))
    }

    fn map_lit(first: (PNode, PNode), rest: Vec<(PNode, PNode)>) -> PNode {
        PNode(MapLit(combine_one_with_many(first, rest)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PNode {
        PNode(Const(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> PNode {
        PNode(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: PNode, args: Vec<PNode>) -> PNode {
        PNode(Message { recv: None, meth: func, args: args })
    }

    fn method_call(recv: PNode, call: Vec<(PNode, Vec<PNode>)>) -> PNode {
        call.into_iter().fold(recv, { |accu, (method, args)|
            PNode(Message { recv: Some(accu), meth: method, args: args })
        })
    }

    fn assign_stmt(var: PNode, expr: PNode) -> PNode {
        PNode(AssignStmt { var: var, expr: expr })
    }

    fn class_decl(class: PNode, methods: Vec<PNode>) -> PNode {
        PNode(ClassDecl { class: class, meths: methods })
    }

    fn method_decl(meth: PNode, params: Vec<PNode>, block: PNode) -> PNode {
        PNode(MethodDecl { meth: meth, params: params, blk: block })
    }

    fn block(stmts: Vec<(PNode, Option<()>)>) -> PNode {
        let stmts = stmts.into_iter().map(|stmt| {
            match stmt { (s, _) => s }
        }).collect();

        PNode(Block(stmts))
    }

    fn program(stmts: Vec<(PNode, Option<()>)>) -> Vec<PNode> {
        stmts.into_iter().map(|stmt| {
            match stmt { (s, _) => s }
        }).collect()
    }

    fn if_stmt(cond: PNode, true_blk: PNode, false_blk: Option<PNode>) -> PNode {
        PNode(IfStmt { cond: cond, true_blk: true_blk, false_blk: false_blk })
    }

    fn while_stmt(cond: PNode, blk: PNode) -> PNode {
        PNode(WhileStmt { cond: cond, blk: blk })
    }

    fn arg_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<PNode> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u64 {
        u64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PNode, rest: Vec<(BinOp, PNode)>) -> PNode {
        rest.into_iter().fold(head,
          |accu, (op, expr)| PNode(BinExpr { op: op, left: accu, right: expr }))
    }

    fn fold_right(front: Vec<(PNode, BinOp)>, last: PNode) -> PNode {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| PNode(BinExpr { op: op, left: expr, right: accu }))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<PNode>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<PNode>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<PNode>, String> {
        let state = bailey::parse_program(code.stream());

        match state.into_result() {
            Ok((success, error)) => {
                if success.partial_read() {
                    Err(format!("Partial match: {:?} because: {}", success.data, error))
                } else {
                    self.ast = Some(success.data.clone());
                    Ok(success.data)
                }
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }
}
<commit_msg>Simplified block rule.<commit_after>use oak_runtime::stream::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::PNode;

grammar! bailey {
    use ast::PNode;
    use ast::Node::*;
    use ast::BinOp;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = ((decl / stmt) terminator?)* > program

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = def_kw ident lparen param_list rparen block > method_decl

    block
        = lbracket (stmt terminator?)* rbracket > block

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = ident bind_op expr > assign_stmt

    expr
        = cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal
        / constant
        / ident
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit
        / array_lit
        / map_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit
    array_lit = lsqbracket expr (comma expr)* rsqbracket > array_lit

    map_entry =  (expr colon expr)
    map_lit = lbracket map_entry (comma map_entry)* rbracket > map_lit

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    lsqbracket = "[" spacing
    rsqbracket = "]" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn int_lit(raw_text: Vec<char>) -> PNode {
        PNode(IntLit(to_number(raw_text)))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> PNode {
        integer.push('.');
        PNode(FltLit(to_float(combine(integer, fractional))))
    }

    fn string_lit(raw_text: Vec<char>) -> PNode {
        PNode(StrLit(to_string(raw_text)))
    }

    fn array_lit(first: PNode, rest: Vec<PNode>) -> PNode {
        PNode(ArrLit(combine_one_with_many(first, rest)))
    }

    fn map_lit(first: (PNode, PNode), rest: Vec<(PNode, PNode)>) -> PNode {
        PNode(MapLit(combine_one_with_many(first, rest)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PNode {
        PNode(Const(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> PNode {
        PNode(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: PNode, args: Vec<PNode>) -> PNode {
        PNode(Message { recv: None, meth: func, args: args })
    }

    fn method_call(recv: PNode, call: Vec<(PNode, Vec<PNode>)>) -> PNode {
        call.into_iter().fold(recv, { |accu, (method, args)|
            PNode(Message { recv: Some(accu), meth: method, args: args })
        })
    }

    fn assign_stmt(var: PNode, expr: PNode) -> PNode {
        PNode(AssignStmt { var: var, expr: expr })
    }

    fn class_decl(class: PNode, methods: Vec<PNode>) -> PNode {
        PNode(ClassDecl { class: class, meths: methods })
    }

    fn method_decl(meth: PNode, params: Vec<PNode>, block: PNode) -> PNode {
        PNode(MethodDecl { meth: meth, params: params, blk: block })
    }

    fn block(stmts: Vec<(PNode, Option<()>)>) -> PNode {
        let stmts = stmts.into_iter().map(|stmt| {
            match stmt { (s, _) => s }
        }).collect();

        PNode(Block(stmts))
    }

    fn program(stmts: Vec<(PNode, Option<()>)>) -> Vec<PNode> {
        stmts.into_iter().map(|stmt| {
            match stmt { (s, _) => s }
        }).collect()
    }

    fn if_stmt(cond: PNode, true_blk: PNode, false_blk: Option<PNode>) -> PNode {
        PNode(IfStmt { cond: cond, true_blk: true_blk, false_blk: false_blk })
    }

    fn while_stmt(cond: PNode, blk: PNode) -> PNode {
        PNode(WhileStmt { cond: cond, blk: blk })
    }

    fn arg_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<PNode> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u64 {
        u64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PNode, rest: Vec<(BinOp, PNode)>) -> PNode {
        rest.into_iter().fold(head,
          |accu, (op, expr)| PNode(BinExpr { op: op, left: accu, right: expr }))
    }

    fn fold_right(front: Vec<(PNode, BinOp)>, last: PNode) -> PNode {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| PNode(BinExpr { op: op, left: expr, right: accu }))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<PNode>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<PNode>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<PNode>, String> {
        let state = bailey::parse_program(code.stream());

        match state.into_result() {
            Ok((success, error)) => {
                if success.partial_read() {
                    Err(format!("Partial match: {:?} because: {}", success.data, error))
                } else {
                    self.ast = Some(success.data.clone());
                    Ok(success.data)
                }
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }
}
<|endoftext|>