<commit_before>//! The enum `Either`.

use std::error::Error;
use std::fmt;
use std::io::{self, Write, Read, BufRead};
use std::convert::{AsRef, AsMut};
use std::ops::Deref;
use std::ops::DerefMut;

pub use Either::{Left, Right};

/// `Either` represents an alternative holding one value out of
/// either of the two possible values.
///
/// `Either` is a general purpose sum type of two parts. For representing
/// success or error, use the regular `Result<T, E>` instead.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Either<L, R> {
    /// A value of type `L`.
    Left(L),
    /// A value of type `R`.
    Right(R),
}

macro_rules! either {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref $inner) => $result,
            Either::Right(ref $inner) => $result,
        }
    )
}

macro_rules! either_mut {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref mut $inner) => $result,
            Either::Right(ref mut $inner) => $result,
        }
    )
}

/// Macro for unwrapping the left side of an `Either`, which fails early
/// with the opposite side. Can only be used in functions that return
/// `Either` because of the early return of `Right` that it provides.
///
/// See also `try_right!` for its dual, which applies the same just to the
/// right side.
///
/// # Example
///
/// ```
/// #[macro_use] extern crate either;
/// use either::{Either, Left, Right};
///
/// fn twice(wrapper: Either<u32, &str>) -> Either<u32, &str> {
///     let value = try_left!(wrapper);
///     Left(value * 2)
/// }
///
/// fn main() {
///     assert_eq!(twice(Left(2)), Left(4));
///     assert_eq!(twice(Right("ups")), Right("ups"));
/// }
/// ```
#[macro_export]
macro_rules! try_left {
    ($expr:expr) => (
        match $expr {
            $crate::Left(val) => val,
            $crate::Right(err) => return $crate::Right(::std::convert::From::from(err))
        }
    )
}

/// Dual to `try_left!`, see its documentation for more information.
#[macro_export]
macro_rules! try_right {
    ($expr:expr) => (
        match $expr {
            $crate::Left(err) => return $crate::Left(::std::convert::From::from(err)),
            $crate::Right(val) => val
        }
    )
}

impl<L, R> Either<L, R> {
    pub fn is_left(&self) -> bool {
        match *self {
            Left(_) => true,
            Right(_) => false,
        }
    }

    pub fn is_right(&self) -> bool {
        !self.is_left()
    }

    pub fn left(self) -> Option<L> {
        match self {
            Left(l) => Some(l),
            Right(_) => None,
        }
    }

    pub fn right(self) -> Option<R> {
        match self {
            Left(_) => None,
            Right(r) => Some(r),
        }
    }

    pub fn as_ref(&self) -> Either<&L, &R> {
        match *self {
            Left(ref inner) => Left(inner),
            Right(ref inner) => Right(inner),
        }
    }

    pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
        match *self {
            Left(ref mut inner) => Left(inner),
            Right(ref mut inner) => Right(inner),
        }
    }

    pub fn flip(self) -> Either<R, L> {
        match self {
            Left(l) => Right(l),
            Right(r) => Left(r),
        }
    }
}

/// Convert from `Result` to `Either` with `Ok => Right` and `Err => Left`.
impl<L, R> From<Result<R, L>> for Either<L, R> {
    fn from(r: Result<R, L>) -> Self {
        match r {
            Err(e) => Left(e),
            Ok(o) => Right(o),
        }
    }
}

/// Convert from `Either` to `Result` with `Right => Ok` and `Left => Err`.
impl<L, R> Into<Result<R, L>> for Either<L, R> {
    fn into(self) -> Result<R, L> {
        match self {
            Left(l) => Err(l),
            Right(r) => Ok(r),
        }
    }
}

/// `Either<L, R>` is an iterator if both `L` and `R` are iterators.
impl<L, R> Iterator for Either<L, R>
    where L: Iterator, R: Iterator<Item=L::Item>
{
    type Item = L::Item;

    fn next(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        either!(*self, inner => inner.size_hint())
    }
}

impl<L, R> DoubleEndedIterator for Either<L, R>
    where L: DoubleEndedIterator, R: DoubleEndedIterator<Item=L::Item>
{
    fn next_back(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next_back())
    }
}

impl<L, R> ExactSizeIterator for Either<L, R>
    where L: ExactSizeIterator, R: ExactSizeIterator<Item=L::Item>
{
}

/// `Either<L, R>` implements `Read` if both `L` and `R` do.
impl<L, R> Read for Either<L, R>
    where L: Read, R: Read
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read(buf))
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read_to_end(buf))
    }
}

impl<L, R> BufRead for Either<L, R>
    where L: BufRead, R: BufRead
{
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        either_mut!(*self, inner => inner.fill_buf())
    }

    fn consume(&mut self, amt: usize) {
        either_mut!(*self, inner => inner.consume(amt))
    }
}

/// `Either<L, R>` implements `Write` if both `L` and `R` do.
impl<L, R> Write for Either<L, R>
    where L: Write, R: Write
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        either_mut!(*self, inner => inner.flush())
    }
}

impl<L, R, Target> AsRef<Target> for Either<L, R>
    where L: AsRef<Target>, R: AsRef<Target>
{
    fn as_ref(&self) -> &Target {
        either!(*self, inner => inner.as_ref())
    }
}

impl<L, R, Target> AsMut<Target> for Either<L, R>
    where L: AsMut<Target>, R: AsMut<Target>
{
    fn as_mut(&mut self) -> &mut Target {
        either_mut!(*self, inner => inner.as_mut())
    }
}

impl<L, R> Deref for Either<L, R>
    where L: Deref, R: Deref<Target=L::Target>
{
    type Target = L::Target;

    fn deref(&self) -> &Self::Target {
        either!(*self, inner => &*inner)
    }
}

impl<L, R> DerefMut for Either<L, R>
    where L: DerefMut, R: DerefMut<Target=L::Target>
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        either_mut!(*self, inner => &mut *inner)
    }
}

/// `Either` implements `Error` if *both* `L` and `R` implement it.
impl<L, R> Error for Either<L, R>
    where L: Error, R: Error
{
    fn description(&self) -> &str {
        either!(*self, inner => inner.description())
    }

    fn cause(&self) -> Option<&Error> {
        either!(*self, inner => inner.cause())
    }
}

impl<L, R> fmt::Display for Either<L, R>
    where L: fmt::Display, R: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        either!(*self, inner => inner.fmt(f))
    }
}

#[test]
fn basic() {
    let mut e = Left(2);
    let r = Right(2);
    assert_eq!(e, Left(2));
    e = r;
    assert_eq!(e, Right(2));
    assert_eq!(e.left(), None);
    assert_eq!(e.right(), Some(2));
    assert_eq!(e.as_ref().right(), Some(&2));
    assert_eq!(e.as_mut().right(), Some(&mut 2));
}

#[test]
fn macros() {
    fn a() -> Either<u32, u32> {
        let x: u32 = try_left!(Right(1337));
        Left(x * 2)
    }
    assert_eq!(a(), Right(1337));

    fn b() -> Either<String, &'static str> {
        Right(try_right!(Left("foo bar")))
    }
    assert_eq!(b(), Left(String::from("foo bar")));
}

#[test]
fn deref() {
    fn is_str(_: &str) {}
    let value: Either<String, &str> = Left(String::from("test"));
    is_str(&*value);
}

#[test]
fn iter() {
    let x = 3;
    let mut iter = match x {
        1...3 => Left(0..10),
        _ => Right(17..),
    };

    assert_eq!(iter.next(), Some(0));
    assert_eq!(iter.count(), 9);
}

#[test]
fn read_write() {
    use std::io;

    let use_stdio = false;
    let mockdata = [0xff; 256];

    let mut reader = if use_stdio {
        Left(io::stdin())
    } else {
        Right(&mockdata[..])
    };

    let mut buf = [0u8; 16];
    assert_eq!(reader.read(&mut buf).unwrap(), buf.len());
    assert_eq!(&buf, &mockdata[..buf.len()]);

    let mut mockbuf = [0u8; 256];
    let mut writer = if use_stdio {
        Left(io::stdout())
    } else {
        Right(&mut mockbuf[..])
    };

    let buf = [1u8; 16];
    assert_eq!(writer.write(&buf).unwrap(), buf.len());
}

#[test]
fn error() {
    let invalid_utf8 = b"\xff";
    let res = || -> Result<_, Either<_, _>> {
        try!(::std::str::from_utf8(invalid_utf8).map_err(Left));
        try!("x".parse::<i32>().map_err(Right));
        Ok(())
    }();
    assert!(res.is_err());
    res.unwrap_err().description(); // make sure this can be called
}
<commit_msg>Fix types in test<commit_after>//! The enum `Either`.

use std::error::Error;
use std::fmt;
use std::io::{self, Write, Read, BufRead};
use std::convert::{AsRef, AsMut};
use std::ops::Deref;
use std::ops::DerefMut;

pub use Either::{Left, Right};

/// `Either` represents an alternative holding one value out of
/// either of the two possible values.
///
/// `Either` is a general purpose sum type of two parts. For representing
/// success or error, use the regular `Result<T, E>` instead.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Either<L, R> {
    /// A value of type `L`.
    Left(L),
    /// A value of type `R`.
    Right(R),
}

macro_rules! either {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref $inner) => $result,
            Either::Right(ref $inner) => $result,
        }
    )
}

macro_rules! either_mut {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref mut $inner) => $result,
            Either::Right(ref mut $inner) => $result,
        }
    )
}

/// Macro for unwrapping the left side of an `Either`, which fails early
/// with the opposite side. Can only be used in functions that return
/// `Either` because of the early return of `Right` that it provides.
///
/// See also `try_right!` for its dual, which applies the same just to the
/// right side.
///
/// # Example
///
/// ```
/// #[macro_use] extern crate either;
/// use either::{Either, Left, Right};
///
/// fn twice(wrapper: Either<u32, &str>) -> Either<u32, &str> {
///     let value = try_left!(wrapper);
///     Left(value * 2)
/// }
///
/// fn main() {
///     assert_eq!(twice(Left(2)), Left(4));
///     assert_eq!(twice(Right("ups")), Right("ups"));
/// }
/// ```
#[macro_export]
macro_rules! try_left {
    ($expr:expr) => (
        match $expr {
            $crate::Left(val) => val,
            $crate::Right(err) => return $crate::Right(::std::convert::From::from(err))
        }
    )
}

/// Dual to `try_left!`, see its documentation for more information.
#[macro_export]
macro_rules! try_right {
    ($expr:expr) => (
        match $expr {
            $crate::Left(err) => return $crate::Left(::std::convert::From::from(err)),
            $crate::Right(val) => val
        }
    )
}

impl<L, R> Either<L, R> {
    pub fn is_left(&self) -> bool {
        match *self {
            Left(_) => true,
            Right(_) => false,
        }
    }

    pub fn is_right(&self) -> bool {
        !self.is_left()
    }

    pub fn left(self) -> Option<L> {
        match self {
            Left(l) => Some(l),
            Right(_) => None,
        }
    }

    pub fn right(self) -> Option<R> {
        match self {
            Left(_) => None,
            Right(r) => Some(r),
        }
    }

    pub fn as_ref(&self) -> Either<&L, &R> {
        match *self {
            Left(ref inner) => Left(inner),
            Right(ref inner) => Right(inner),
        }
    }

    pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
        match *self {
            Left(ref mut inner) => Left(inner),
            Right(ref mut inner) => Right(inner),
        }
    }

    pub fn flip(self) -> Either<R, L> {
        match self {
            Left(l) => Right(l),
            Right(r) => Left(r),
        }
    }
}

/// Convert from `Result` to `Either` with `Ok => Right` and `Err => Left`.
impl<L, R> From<Result<R, L>> for Either<L, R> {
    fn from(r: Result<R, L>) -> Self {
        match r {
            Err(e) => Left(e),
            Ok(o) => Right(o),
        }
    }
}

/// Convert from `Either` to `Result` with `Right => Ok` and `Left => Err`.
impl<L, R> Into<Result<R, L>> for Either<L, R> {
    fn into(self) -> Result<R, L> {
        match self {
            Left(l) => Err(l),
            Right(r) => Ok(r),
        }
    }
}

/// `Either<L, R>` is an iterator if both `L` and `R` are iterators.
impl<L, R> Iterator for Either<L, R>
    where L: Iterator, R: Iterator<Item=L::Item>
{
    type Item = L::Item;

    fn next(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        either!(*self, inner => inner.size_hint())
    }
}

impl<L, R> DoubleEndedIterator for Either<L, R>
    where L: DoubleEndedIterator, R: DoubleEndedIterator<Item=L::Item>
{
    fn next_back(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next_back())
    }
}

impl<L, R> ExactSizeIterator for Either<L, R>
    where L: ExactSizeIterator, R: ExactSizeIterator<Item=L::Item>
{
}

/// `Either<L, R>` implements `Read` if both `L` and `R` do.
impl<L, R> Read for Either<L, R>
    where L: Read, R: Read
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read(buf))
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read_to_end(buf))
    }
}

impl<L, R> BufRead for Either<L, R>
    where L: BufRead, R: BufRead
{
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        either_mut!(*self, inner => inner.fill_buf())
    }

    fn consume(&mut self, amt: usize) {
        either_mut!(*self, inner => inner.consume(amt))
    }
}

/// `Either<L, R>` implements `Write` if both `L` and `R` do.
impl<L, R> Write for Either<L, R>
    where L: Write, R: Write
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        either_mut!(*self, inner => inner.flush())
    }
}

impl<L, R, Target> AsRef<Target> for Either<L, R>
    where L: AsRef<Target>, R: AsRef<Target>
{
    fn as_ref(&self) -> &Target {
        either!(*self, inner => inner.as_ref())
    }
}

impl<L, R, Target> AsMut<Target> for Either<L, R>
    where L: AsMut<Target>, R: AsMut<Target>
{
    fn as_mut(&mut self) -> &mut Target {
        either_mut!(*self, inner => inner.as_mut())
    }
}

impl<L, R> Deref for Either<L, R>
    where L: Deref, R: Deref<Target=L::Target>
{
    type Target = L::Target;

    fn deref(&self) -> &Self::Target {
        either!(*self, inner => &*inner)
    }
}

impl<L, R> DerefMut for Either<L, R>
    where L: DerefMut, R: DerefMut<Target=L::Target>
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        either_mut!(*self, inner => &mut *inner)
    }
}

/// `Either` implements `Error` if *both* `L` and `R` implement it.
impl<L, R> Error for Either<L, R>
    where L: Error, R: Error
{
    fn description(&self) -> &str {
        either!(*self, inner => inner.description())
    }

    fn cause(&self) -> Option<&Error> {
        either!(*self, inner => inner.cause())
    }
}

impl<L, R> fmt::Display for Either<L, R>
    where L: fmt::Display, R: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        either!(*self, inner => inner.fmt(f))
    }
}

#[test]
fn basic() {
    let mut e = Left(2);
    let r = Right(2);
    assert_eq!(e, Left(2));
    e = r;
    assert_eq!(e, Right(2));
    assert_eq!(e.left(), None);
    assert_eq!(e.right(), Some(2));
    assert_eq!(e.as_ref().right(), Some(&2));
    assert_eq!(e.as_mut().right(), Some(&mut 2));
}

#[test]
fn macros() {
    fn a() -> Either<u32, u32> {
        let x: u32 = try_left!(Right(1337u32));
        Left(x * 2)
    }
    assert_eq!(a(), Right(1337));

    fn b() -> Either<String, &'static str> {
        Right(try_right!(Left("foo bar")))
    }
    assert_eq!(b(), Left(String::from("foo bar")));
}

#[test]
fn deref() {
    fn is_str(_: &str) {}
    let value: Either<String, &str> = Left(String::from("test"));
    is_str(&*value);
}

#[test]
fn iter() {
    let x = 3;
    let mut iter = match x {
        1...3 => Left(0..10),
        _ => Right(17..),
    };

    assert_eq!(iter.next(), Some(0));
    assert_eq!(iter.count(), 9);
}

#[test]
fn read_write() {
    use std::io;

    let use_stdio = false;
    let mockdata = [0xff; 256];

    let mut reader = if use_stdio {
        Left(io::stdin())
    } else {
        Right(&mockdata[..])
    };

    let mut buf = [0u8; 16];
    assert_eq!(reader.read(&mut buf).unwrap(), buf.len());
    assert_eq!(&buf, &mockdata[..buf.len()]);

    let mut mockbuf = [0u8; 256];
    let mut writer = if use_stdio {
        Left(io::stdout())
    } else {
        Right(&mut mockbuf[..])
    };

    let buf = [1u8; 16];
    assert_eq!(writer.write(&buf).unwrap(), buf.len());
}

#[test]
fn error() {
    let invalid_utf8 = b"\xff";
    let res = || -> Result<_, Either<_, _>> {
        try!(::std::str::from_utf8(invalid_utf8).map_err(Left));
        try!("x".parse::<i32>().map_err(Right));
        Ok(())
    }();
    assert!(res.is_err());
    res.unwrap_err().description(); // make sure this can be called
}
<|endoftext|>


<commit_before>use std::ops::Deref;

/// A `Vec` in sorted order without duplicates.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SortedUniqueVec<T: Ord + Clone> {
    vec: Vec<T>,
}

fn is_sorted_unique<T: Ord>(slice: &[T]) -> bool {
    if slice.len() < 2 {
        true
    } else {
        slice.windows(2).all(|win| win[0] < win[1])
    }
}

impl<T: Ord + Clone> SortedUniqueVec<T> {
    pub fn new() -> Self {
        SortedUniqueVec { vec: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.vec.len()
    }

    pub fn contains(&self, element: &T) -> bool {
        self.vec.binary_search(element).is_ok()
    }

    /// Insert `element` into the sorted list.
    ///
    /// Panics if an element with the same key (according to the Eq trait) already exists.
    pub fn insert(&mut self, element: T) {
        match self.vec.binary_search(&element) {
            Ok(_idx) => {
                panic!("Element already exists");
            }
            Err(idx) => {
                self.vec.insert(idx, element);
            }
        }
    }

    /// Merges `self` and `other` into a new SortedVec.
    pub fn merge(&self, other: &Self) -> Self {
        let mut vec = Vec::with_capacity(self.len() + other.len());

        let mut left_iter = self.vec.iter().peekable();
        let mut right_iter = other.vec.iter().peekable();

        enum Take {
            OneLeft,
            OneRight,
            Both,
            AllLeft,
            AllRight,
        };

        loop {
            let take;

            match (left_iter.peek(), right_iter.peek()) {
                (Some(l), Some(r)) => {
                    if l < r {
                        take = Take::OneLeft;
                    } else if r < l {
                        take = Take::OneRight;
                    } else {
                        take = Take::Both;
                    }
                }
                (Some(_), None) => {
                    take = Take::AllLeft;
                }
                (None, Some(_)) => {
                    take = Take::AllRight;
                }
                (None, None) => {
                    break;
                }
            }
            match take {
                Take::OneLeft => {
                    vec.push((*left_iter.next().unwrap()).clone());
                }
                Take::OneRight => {
                    vec.push((*right_iter.next().unwrap()).clone());
                }
                Take::Both => {
                    // two equal values
                    let left_value = left_iter.next().unwrap();
                    let _right_value = right_iter.next().unwrap();
                    // XXX: decide which one to copy
                    vec.push((*left_value).clone());
                }
                Take::AllLeft => {
                    for item in left_iter {
                        vec.push((*item).clone());
                    }
                    break;
                }
                Take::AllRight => {
                    for item in right_iter {
                        vec.push((*item).clone());
                    }
                    break;
                }

            }
        }

        debug_assert!(is_sorted_unique(&vec));
        SortedUniqueVec { vec: vec }
    }
}

impl<T: Ord + Clone> AsRef<[T]> for SortedUniqueVec<T> {
    fn as_ref(&self) -> &[T] {
        &self.vec
    }
}

impl<T: Ord + Clone> Deref for SortedUniqueVec<T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        &self.vec
    }
}

#[test]
fn test_insert() {
    let mut s = SortedUniqueVec::new();
    s.insert(5);
    s.insert(1);
    s.insert(8);
    s.insert(0);
    assert!(is_sorted_unique(&s));
    assert_eq!(&[0, 1, 5, 8][..], s.as_ref());
    assert_eq!(4, s.len());
}

#[test]
fn test_merge() {
    let mut s1 = SortedUniqueVec::new();
    s1.insert(5);
    s1.insert(1);
    s1.insert(8);
    s1.insert(0);
    assert!(is_sorted_unique(&s1));

    let mut s2 = SortedUniqueVec::new();
    s2.insert(55);
    s2.insert(1);
    s2.insert(5);
    s2.insert(7);
    s2.insert(9);
    assert!(is_sorted_unique(&s2));

    let r = s1.merge(&s2);
    assert!(is_sorted_unique(&r));
    assert_eq!(&[0, 1, 5, 7, 8, 9, 55][..], r.as_ref());
}
<commit_msg>Extend merge() to take a closure which decides which one of two equal values to take (left or right value).<commit_after>use std::ops::Deref;

/// A `Vec` in sorted order without duplicates.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SortedUniqueVec<T: Ord + Clone> {
    vec: Vec<T>,
}

fn is_sorted_unique<T: Ord>(slice: &[T]) -> bool {
    if slice.len() < 2 {
        true
    } else {
        slice.windows(2).all(|win| win[0] < win[1])
    }
}

pub enum LeftOrRight {
    Left,
    Right,
}

impl<T: Ord + Clone> SortedUniqueVec<T> {
    pub fn new() -> Self {
        SortedUniqueVec { vec: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.vec.len()
    }

    pub fn contains(&self, element: &T) -> bool {
        self.vec.binary_search(element).is_ok()
    }

    /// Insert `element` into the sorted list.
    ///
    /// Panics if an element with the same key (according to the Eq trait) already exists.
    pub fn insert(&mut self, element: T) {
        match self.vec.binary_search(&element) {
            Ok(_idx) => {
                panic!("Element already exists");
            }
            Err(idx) => {
                self.vec.insert(idx, element);
            }
        }
    }

    /// Merges `self` and `other` into a new SortedVec.
    /// `choose_equal` decides which one of two equal values to take.
    pub fn merge<F>(&self, other: &Self, choose_equal: &F) -> Self
        where F: Fn(&T, &T) -> LeftOrRight
    {
        let mut vec = Vec::with_capacity(self.len() + other.len());

        let mut left_iter = self.vec.iter().peekable();
        let mut right_iter = other.vec.iter().peekable();

        enum Take {
            OneLeft,
            OneRight,
            Both,
            AllLeft,
            AllRight,
        };

        loop {
            let take;

            match (left_iter.peek(), right_iter.peek()) {
                (Some(l), Some(r)) => {
                    if l < r {
                        take = Take::OneLeft;
                    } else if r < l {
                        take = Take::OneRight;
                    } else {
                        take = Take::Both;
                    }
                }
                (Some(_), None) => {
                    take = Take::AllLeft;
                }
                (None, Some(_)) => {
                    take = Take::AllRight;
                }
                (None, None) => {
                    break;
                }
            }
            match take {
                Take::OneLeft => {
                    vec.push((*left_iter.next().unwrap()).clone());
                }
                Take::OneRight => {
                    vec.push((*right_iter.next().unwrap()).clone());
                }
                Take::Both => {
                    // two equal values
                    let left_value = left_iter.next().unwrap();
                    let right_value = right_iter.next().unwrap();
                    match choose_equal(left_value, right_value) {
                        LeftOrRight::Left => {
                            vec.push((*left_value).clone());
                        }
                        LeftOrRight::Right => {
                            vec.push((*right_value).clone());
                        }
                    }
                }
                Take::AllLeft => {
                    for item in left_iter {
                        vec.push((*item).clone());
                    }
                    break;
                }
                Take::AllRight => {
                    for item in right_iter {
                        vec.push((*item).clone());
                    }
                    break;
                }

            }
        }

        debug_assert!(is_sorted_unique(&vec));
        SortedUniqueVec { vec: vec }
    }
}

impl<T: Ord + Clone> AsRef<[T]> for SortedUniqueVec<T> {
    fn as_ref(&self) -> &[T] {
        &self.vec
    }
}

impl<T: Ord + Clone> Deref for SortedUniqueVec<T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        &self.vec
    }
}

#[test]
fn test_insert() {
    let mut s = SortedUniqueVec::new();
    s.insert(5);
    s.insert(1);
    s.insert(8);
    s.insert(0);
    assert!(is_sorted_unique(&s));
    assert_eq!(&[0, 1, 5, 8][..], s.as_ref());
    assert_eq!(4, s.len());
}

#[test]
fn test_merge() {
    let mut s1 = SortedUniqueVec::new();
    s1.insert(5);
    s1.insert(1);
    s1.insert(8);
    s1.insert(0);
    assert!(is_sorted_unique(&s1));

    let mut s2 = SortedUniqueVec::new();
    s2.insert(55);
    s2.insert(1);
    s2.insert(5);
    s2.insert(7);
    s2.insert(9);
    assert!(is_sorted_unique(&s2));

    let r = s1.merge(&s2, &|_, _| LeftOrRight::Left);
    assert!(is_sorted_unique(&r));
    assert_eq!(&[0, 1, 5, 7, 8, 9, 55][..], r.as_ref());
}
<|endoftext|>


<commit_before>// Needed by pest
#![recursion_limit = "300"]

#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(feature = "dev", allow(block_in_if_condition_stmt, linkedlist))]

extern crate serde;
extern crate serde_json;
extern crate glob;
#[macro_use] extern crate pest;
#[macro_use] extern crate error_chain;
extern crate slug;
extern crate regex;
#[macro_use] extern crate lazy_static;
extern crate url;
extern crate humansize;

mod errors;
#[macro_use] mod macros;
mod parser;
mod context;
mod render;
mod template;
mod tera;
mod filters;
mod testers;
mod utils;

// Library exports.

// Template is meant to be used internally only but is exported for test/bench.
#[doc(hidden)] pub use template::Template;
pub use context::Context;
pub use tera::Tera;
pub use errors::{Result, Error, ErrorKind};
pub use utils::{escape_html};
// Re-export Value so apps/tools can encode data in Tera types
// for now it's serde_json
pub use serde_json::value::{Value, to_value};
<commit_msg>Add module level comment<commit_after>//! # Tera
//! Tera is a template engine based on [Jinja2](http://jinja.pocoo.org/)
//! and the [Django template language](https://docs.djangoproject.com/en/1.9/topics/templates/).
//!
//! See the [README](https://github.com/Keats/tera/blob/master/README.md) for features and
//! to get started.

// Needed by pest
#![recursion_limit = "300"]

#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(feature = "dev", allow(block_in_if_condition_stmt, linkedlist))]

extern crate serde;
extern crate serde_json;
extern crate glob;
#[macro_use] extern crate pest;
#[macro_use] extern crate error_chain;
extern crate slug;
extern crate regex;
#[macro_use] extern crate lazy_static;
extern crate url;
extern crate humansize;

mod errors;
#[macro_use] mod macros;
mod parser;
mod context;
mod render;
mod template;
mod tera;
mod filters;
mod testers;
mod utils;

// Library exports.

// Template is meant to be used internally only but is exported for test/bench.
#[doc(hidden)] pub use template::Template;
pub use context::Context;
pub use tera::Tera;
pub use errors::{Result, Error, ErrorKind};
pub use utils::{escape_html};
// Re-export Value so apps/tools can encode data in Tera types
// for now it's serde_json
pub use serde_json::value::{Value, to_value};
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](https://capnproto.org) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![allow(raw_pointer_derive)]

extern crate byteorder;

#[cfg(any(feature="quickcheck", test))]
extern crate quickcheck;

#[cfg(feature = "rpc")]
extern crate gj;

pub mod any_pointer;
pub mod capability;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod private;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;

mod util;

/// Eight bytes of memory with opaque interior.
///
/// This type is used to ensure that the data of a message is properly aligned.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Word(u64);

impl Word {
    /// Does this, but faster:
    /// `::std::iter::repeat(Word(0)).take(length).collect()`
    pub fn allocate_zeroed_vec(length: usize) -> Vec<Word> {
        let mut result : Vec<Word> = Vec::with_capacity(length);
        unsafe {
            result.set_len(length);
            let p : *mut u8 = result.as_mut_ptr() as *mut u8;
            ::std::ptr::write_bytes(p, 0u8, length * ::std::mem::size_of::<Word>());
        }
        result
    }

    pub fn bytes_to_words<'a>(bytes: &'a [u8]) -> &'a [Word] {
        unsafe {
            ::std::slice::from_raw_parts(bytes.as_ptr() as *const Word, bytes.len() / 8)
        }
    }

    pub fn bytes_to_words_mut<'a>(bytes: &'a mut [u8]) -> &'a mut [Word] {
        unsafe {
            ::std::slice::from_raw_parts_mut(bytes.as_ptr() as *mut Word, bytes.len() / 8)
        }
    }

    pub fn words_to_bytes<'a>(words: &'a [Word]) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8)
        }
    }

    pub fn words_to_bytes_mut<'a>(words: &'a mut [Word]) -> &'a mut [u8] {
        unsafe {
            ::std::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8)
        }
    }

    #[cfg(test)]
    pub fn from(n: u64) -> Word {
        Word(n)
    }
}

#[cfg(any(feature="quickcheck", test))]
impl quickcheck::Arbitrary for Word {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Word {
        Word(quickcheck::Arbitrary::arbitrary(g))
    }
}

/// Size of a message. Every generated struct has a method `.total_size()` that returns this.
#[derive(Clone, Copy, PartialEq)]
pub struct MessageSize {
    pub word_count: u64,

    /// Size of the capability table.
    pub cap_count: u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

/// An enum value or union discriminant that was not found among those defined in a schema.
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct NotInSchema(pub u16);

impl ::std::fmt::Display for NotInSchema {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "Enum value or union discriminant {} was not present in the schema.", self.0)
    }
}

impl ::std::error::Error for NotInSchema {
    fn description<'a>(&'a self) -> &'a str {
        "Enum value or union disriminant was not present in schema."
    }
}

/// Because messages are lazily validated, the return type of any method that reads a pointer field
/// must be wrapped in a Result.
pub type Result<T> = ::std::result::Result<T, Error>;

/// Describes an arbitrary error that prevented an operation from completing.
#[derive(Debug, Clone)]
pub struct Error {
    /// The type of the error. The purpose of this enum is not to describe the error itself, but
    /// rather to describe how the client might want to respond to the error.
    pub kind: ErrorKind,

    /// Human-readable failure description.
    pub description: String,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorKind {
    /// Something went wrong. This is the usual error kind. It includes decoding errors.
    Failed,

    /// The call failed because of a temporary lack of resources. This could be space resources
    /// (out of memory, out of disk space) or time resources (request queue overflow, operation
    /// timed out).
    //
    /// The operation might work if tried again, but it should NOT be repeated immediately as this
    /// may simply exacerbate the problem.
    Overloaded,

    /// The call required communication over a connection that has been lost. The callee will need
    /// to re-establish connections and try again.
    Disconnected,

    /// The requested method is not implemented. The caller may wish to revert to a fallback
    /// approach based on other methods.
    Unimplemented,
}

impl Error {
    pub fn failed(description: String) -> Error {
        Error { description: description, kind: ErrorKind::Failed }
    }
    pub fn unimplemented(description: String) -> Error {
        Error { description: description, kind: ErrorKind::Unimplemented }
    }
}

impl ::std::convert::From<::std::io::Error> for Error {
    fn from(err: ::std::io::Error) -> Error {
        use std::io;
        let kind = match err.kind() {
            io::ErrorKind::TimedOut => ErrorKind::Overloaded,
            io::ErrorKind::BrokenPipe |
            io::ErrorKind::ConnectionRefused |
            io::ErrorKind::ConnectionReset |
            io::ErrorKind::ConnectionAborted |
            io::ErrorKind::NotConnected  => ErrorKind::Disconnected,
            _ => ErrorKind::Failed,
        };
        Error { description: format!("{}", err), kind: kind }
    }
}

impl ::std::convert::From<NotInSchema> for Error {
    fn from(e: NotInSchema) -> Error {
        Error::failed(format!("Enum value or union discriminant {} was not present in schema.", e.0))
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "{:?}: {}", self.kind, self.description)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        &self.description
    }
    fn cause(&self) -> Option<&::std::error::Error> {
        None
    }
}

#[cfg(feature = "rpc")]
impl ::gj::FulfillerDropped for Error {
    fn fulfiller_dropped() -> Error {
        Error::failed("Promise fulfiller was dropped.".to_string())
    }
}

/// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations
/// in the single-segment case.
pub enum OutputSegments<'a> {
    #[doc(hidden)]
    SingleSegment([&'a [Word]; 1]),

    #[doc(hidden)]
    MultiSegment(Vec<&'a [Word]>),
}

impl <'a> ::std::ops::Deref for OutputSegments<'a> {
    type Target = [&'a [Word]];
    fn deref<'b>(&'b self) -> &'b [&'a [Word]] {
        match self {
            &OutputSegments::SingleSegment(ref s) => {
                s
            }
            &OutputSegments::MultiSegment(ref v) => {
                &*v
            }
        }
    }
}
<commit_msg>lint raw_pointer_derive has been removed<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](https://capnproto.org) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

extern crate byteorder;

#[cfg(any(feature="quickcheck", test))]
extern crate quickcheck;

#[cfg(feature = "rpc")]
extern crate gj;

pub mod any_pointer;
pub mod capability;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod private;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;

mod util;

/// Eight bytes of memory with opaque interior.
///
/// This type is used to ensure that the data of a message is properly aligned.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Word(u64);

impl Word {
    /// Does this, but faster:
    /// `::std::iter::repeat(Word(0)).take(length).collect()`
    pub fn allocate_zeroed_vec(length: usize) -> Vec<Word> {
        let mut result : Vec<Word> = Vec::with_capacity(length);
        unsafe {
            result.set_len(length);
            let p : *mut u8 = result.as_mut_ptr() as *mut u8;
            ::std::ptr::write_bytes(p, 0u8, length * ::std::mem::size_of::<Word>());
        }
        result
    }

    pub fn bytes_to_words<'a>(bytes: &'a [u8]) -> &'a [Word] {
        unsafe {
            ::std::slice::from_raw_parts(bytes.as_ptr() as *const Word, bytes.len() / 8)
        }
    }

    pub fn bytes_to_words_mut<'a>(bytes: &'a mut [u8]) -> &'a mut [Word] {
        unsafe {
            ::std::slice::from_raw_parts_mut(bytes.as_ptr() as *mut Word, bytes.len() / 8)
        }
    }

    pub fn words_to_bytes<'a>(words: &'a [Word]) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8)
        }
    }

    pub fn words_to_bytes_mut<'a>(words: &'a mut [Word]) -> &'a mut [u8] {
        unsafe {
            ::std::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8)
        }
    }

    #[cfg(test)]
    pub fn from(n: u64) -> Word {
        Word(n)
    }
}

#[cfg(any(feature="quickcheck", test))]
impl quickcheck::Arbitrary for Word {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Word {
        Word(quickcheck::Arbitrary::arbitrary(g))
    }
}

/// Size of a message. Every generated struct has a method `.total_size()` that returns this.
#[derive(Clone, Copy, PartialEq)]
pub struct MessageSize {
    pub word_count: u64,

    /// Size of the capability table.
    pub cap_count: u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

/// An enum value or union discriminant that was not found among those defined in a schema.
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct NotInSchema(pub u16);

impl ::std::fmt::Display for NotInSchema {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "Enum value or union discriminant {} was not present in the schema.", self.0)
    }
}

impl ::std::error::Error for NotInSchema {
    fn description<'a>(&'a self) -> &'a str {
        "Enum value or union disriminant was not present in schema."
    }
}

/// Because messages are lazily validated, the return type of any method that reads a pointer field
/// must be wrapped in a Result.
pub type Result<T> = ::std::result::Result<T, Error>;

/// Describes an arbitrary error that prevented an operation from completing.
#[derive(Debug, Clone)]
pub struct Error {
    /// The type of the error. The purpose of this enum is not to describe the error itself, but
    /// rather to describe how the client might want to respond to the error.
    pub kind: ErrorKind,

    /// Human-readable failure description.
    pub description: String,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorKind {
    /// Something went wrong. This is the usual error kind. It includes decoding errors.
    Failed,

    /// The call failed because of a temporary lack of resources. This could be space resources
    /// (out of memory, out of disk space) or time resources (request queue overflow, operation
    /// timed out).
    //
    /// The operation might work if tried again, but it should NOT be repeated immediately as this
    /// may simply exacerbate the problem.
    Overloaded,

    /// The call required communication over a connection that has been lost. The callee will need
    /// to re-establish connections and try again.
    Disconnected,

    /// The requested method is not implemented. The caller may wish to revert to a fallback
    /// approach based on other methods.
    Unimplemented,
}

impl Error {
    pub fn failed(description: String) -> Error {
        Error { description: description, kind: ErrorKind::Failed }
    }
    pub fn unimplemented(description: String) -> Error {
        Error { description: description, kind: ErrorKind::Unimplemented }
    }
}

impl ::std::convert::From<::std::io::Error> for Error {
    fn from(err: ::std::io::Error) -> Error {
        use std::io;
        let kind = match err.kind() {
            io::ErrorKind::TimedOut => ErrorKind::Overloaded,
            io::ErrorKind::BrokenPipe |
            io::ErrorKind::ConnectionRefused |
            io::ErrorKind::ConnectionReset |
            io::ErrorKind::ConnectionAborted |
            io::ErrorKind::NotConnected  => ErrorKind::Disconnected,
            _ => ErrorKind::Failed,
        };
        Error { description: format!("{}", err), kind: kind }
    }
}

impl ::std::convert::From<NotInSchema> for Error {
    fn from(e: NotInSchema) -> Error {
        Error::failed(format!("Enum value or union discriminant {} was not present in schema.", e.0))
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "{:?}: {}", self.kind, self.description)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        &self.description
    }
    fn cause(&self) -> Option<&::std::error::Error> {
        None
    }
}

#[cfg(feature = "rpc")]
impl ::gj::FulfillerDropped for Error {
    fn fulfiller_dropped() -> Error {
        Error::failed("Promise fulfiller was dropped.".to_string())
    }
}

/// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations
/// in the single-segment case.
pub enum OutputSegments<'a> {
    #[doc(hidden)]
    SingleSegment([&'a [Word]; 1]),

    #[doc(hidden)]
    MultiSegment(Vec<&'a [Word]>),
}

impl <'a> ::std::ops::Deref for OutputSegments<'a> {
    type Target = [&'a [Word]];
    fn deref<'b>(&'b self) -> &'b [&'a [Word]] {
        match self {
            &OutputSegments::SingleSegment(ref s) => {
                s
            }
            &OutputSegments::MultiSegment(ref v) => {
                &*v
            }
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "XBTVEd"]
#![crate_type = "dylib"]
#![feature(libc, convert, collections, unboxed_closures)]

extern crate libc;

use std::ffi::{CStr, CString};
use std::mem;

pub mod action;
pub mod parse;
pub mod schedule;
pub mod program;
pub mod tags;
pub mod blocks;
pub mod gui;

pub use gui::XBTVEd;
use action::*;

#[no_mangle]
pub extern fn create_app() -> *const XBTVEd {
    let app = Box::new(XBTVEd::new());
    unsafe {
        mem::transmute(app)
    }
}

#[no_mangle]
pub extern fn undo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().undo()
    }
}

#[no_mangle]
pub extern fn redo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().redo()
    }
}

#[no_mangle]
pub extern fn buffers_len(xbtved: *const XBTVEd) -> u32 {
    unsafe {
        let res = (*xbtved).buffers_len();
        res as u32
    }
}

#[no_mangle]
pub extern fn new_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).add_buffer();
    }
}

#[no_mangle]
pub extern fn prev_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).prev_buffer();
    }
}

#[no_mangle]
pub extern fn next_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).next_buffer();
    }
}

#[no_mangle]
pub extern fn get_buffer_name(xbtved: *const XBTVEd) -> *const i8 {
    unsafe {
        match CString::new((*xbtved).current_buffer().get_name()) {
            Ok(x) => x.as_ptr(),
            Err(_) => CString::new("SCREWED UP!").unwrap().as_ptr()
        }
    }
}

fn ptr_to_string(bullshit: *const libc::c_char) -> String {
    unsafe {
        match String::from_utf8(CStr::from_ptr(bullshit).to_bytes().to_vec()) {
            Ok(x) => x,
            Err(f) => panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn set_buffer_name(xbtved: *mut XBTVEd, name: *const libc::c_char) {
    unsafe {
        let new_name = ptr_to_string(name);
        let name_change = SetName::new((*xbtved).current_buffer(), &new_name);
        if let Err(f) = (*xbtved).current_buffer_mut().apply(name_change) {
            panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn add_program(xbtved: *mut XBTVEd,
                          source: *const libc::c_char,
                          loc: *const libc::c_char) -> *const i8 {
    unsafe {
        let location = ptr_to_string(loc);
        let source = match ptr_to_string(source).as_str() {
            "local" => program::Source::Pathname(location),
            "network" => program::Source::URL(location),
            x => return CString::new(format!("{} is invalid source", x)).unwrap().as_ptr()
        };

        let prog = program::Program::new(source, tags::Tags::new(),
                                         vec!(program::Instruction::Play(0, 0)));
        let add_prog = AddProgram::new(&prog);

        match (*xbtved).current_buffer_mut().apply(add_prog) {
            Err(f) => CString::new(f).unwrap().as_ptr(),
            Ok(_) => CString::new("Ok").unwrap().as_ptr()
        }
    }
}
<commit_msg>fixed a name<commit_after>#![crate_name = "XBTVEd"]
#![crate_type = "dylib"]
#![feature(libc, convert, collections, unboxed_closures)]

extern crate libc;

use std::ffi::{CStr, CString};
use std::mem;

pub mod action;
pub mod parse;
pub mod schedule;
pub mod program;
pub mod tags;
pub mod blocks;
pub mod gui;

pub use gui::XBTVEd;
use action::*;

#[no_mangle]
pub extern fn create_app() -> *const XBTVEd {
    let app = Box::new(XBTVEd::new());
    unsafe {
        mem::transmute(app)
    }
}

#[no_mangle]
pub extern fn undo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().undo()
    }
}

#[no_mangle]
pub extern fn redo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().redo()
    }
}

#[no_mangle]
pub extern fn buffers_len(xbtved: *const XBTVEd) -> u32 {
    unsafe {
        let res = (*xbtved).buffers_len();
        res as u32
    }
}

#[no_mangle]
pub extern fn new_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).add_buffer();
    }
}

#[no_mangle]
pub extern fn prev_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).prev_buffer();
    }
}

#[no_mangle]
pub extern fn next_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).next_buffer();
    }
}

#[no_mangle]
pub extern fn get_buffer_name(xbtved: *const XBTVEd) -> *const i8 {
    unsafe {
        match CString::new((*xbtved).current_buffer().get_name()) {
            Ok(x) => x.as_ptr(),
            Err(_) => CString::new("SCREWED UP!").unwrap().as_ptr()
        }
    }
}

fn ptr_to_string(name: *const libc::c_char) -> String {
    unsafe {
        match String::from_utf8(CStr::from_ptr(name).to_bytes().to_vec()) {
            Ok(x) => x,
            Err(f) => panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn set_buffer_name(xbtved: *mut XBTVEd, name: *const libc::c_char) {
    unsafe {
        let new_name = ptr_to_string(name);
        let name_change = SetName::new((*xbtved).current_buffer(), &new_name);
        if let Err(f) = (*xbtved).current_buffer_mut().apply(name_change) {
            panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn add_program(xbtved: *mut XBTVEd,
                          source: *const libc::c_char,
                          loc: *const libc::c_char) -> *const i8 {
    unsafe {
        let location = ptr_to_string(loc);
        let source = match ptr_to_string(source).as_str() {
            "local" => program::Source::Pathname(location),
            "network" => program::Source::URL(location),
            x => return CString::new(format!("{} is invalid source", x)).unwrap().as_ptr()
        };

        let prog = program::Program::new(source, tags::Tags::new(),
                                         vec!(program::Instruction::Play(0, 0)));
        let add_prog = AddProgram::new(&prog);

        match (*xbtved).current_buffer_mut().apply(add_prog) {
            Err(f) => CString::new(f).unwrap().as_ptr(),
            Ok(_) => CString::new("Ok").unwrap().as_ptr()
        }
    }
}
<|endoftext|>


<commit_before>// use variable names from paper, namely registers M
#![allow(non_snake_case)]

#![crate_name = "basichll"]
#![crate_type = "lib"]

extern crate byteorder;

/* -------------------- std libs ------------------- */
use std::cmp;
use std::fmt;
use std::hash::{ Hash, Hasher, SipHasher };
use std::io::Cursor;
use std::iter::{ repeat, Iterator };
/* ------------------------------------------------- */

use byteorder::{ BigEndian, WriteBytesExt, ReadBytesExt };

/* -------------------- helpers -------------------- */

fn alpha (m: usize) -> f64 {
    match m {
        16 => 0.673,
        32 => 0.697,
        64 => 0.709,
        _  => 0.7213/(1f64 + 1.079/(m as f64))
    }
}

fn leftmost_one_bit (v: u64) -> usize {
    let mut counter: usize = 0;
    let mut shiftable = v;

    while shiftable > 0 {
        shiftable >>= 1;
        counter += 1;
    }

    64 - counter
}

/* ------------------------------------------------- */

/* --------------- hyper log log ------------------- */

/// The `HLL` struct stores the underlying registers
/// of the HyperLogLog, with `m` many registers.
///
/// The value for `m` is derived from the desired error
/// of the estimation. The error is considered to be
/// 1.04 / sqrt(2 ^ bits). So, given a desired 1% error
/// rate, we result in around 12 bits per register,
/// producing an underlying M of 2^12 bits (i.e. 4kb).
#[derive(Clone, PartialEq)]
pub struct HLL {
    alpha: f64,
    b: u32,
    m: usize,
    M: Vec<u8>,
    // [!] this is pretty much a hack until I can think of something
    //     better to do for the monoid instance. Basically we need the
    //     zero value to always satisfy the left and right identity laws
    //     but because you need to have the number of registers be
    //     equivalent to do addition, it implies you need a distinct
    //     monoid instance per HLL configuration (i.e. an HLL of 4
    //     registers has a distinct zero from a HLL of 16).
    //
    //     Because I can't really do dependent types in rust, we instead
    //     have a distinguished zero element, that is allowed to bypass
    //     the assertions on the equivalent sizes...
    //
    //     For reference, Ed Kmett's haskell implementation actually does
    //     use higher kinded types and some tricky reflection to make the
    //     monoid instance be parameterised by a config type that is itself
    //     typed to a Peano natural encoded type. Twitter's algebird instance
    //     declares a separate class that encapsulates the notion of
    //     a "HyperLogLogMonoid" instance, and instances of that class are
    //     instantiated with the register size (i.e. the 'instance' for monoid
    //     is just an 'instance' of the class, for two interpretations of
    //     'instance').
    isZero: bool
}

impl std::cmp::Eq for HLL {}

impl HLL {
    /// Convenience function to produce a HLL with
    /// one hundred and twenty eight registers.
    pub fn one_hundred_twenty_eight () -> HLL {
        HLL::new(0.09192)
    }

    /// Create a new HLL with the desired standard error.
    /// Some examples might be:
    ///
    ///```ignore
    ///     bits    size    error
    ///     12      4096    0.0163
    ///     13      8192    0.0115
    ///     14      16384   0.0081
    ///```
    ///
    /// The error must be between 0.0 and 1.0. Beware using a stupidly
    /// small error size will grow beyond e.g. isize at less than 0.03
    /// (if you need something that isn't an estimate probably don't use
    /// a hyperloglog).
    pub fn new(error: f64) -> HLL {
        assert!(error > 0.0 && error < 1.0);
        // error = 1.04 / sqrt(m)
        let m = ((1.04/error) * (1.04/error)).floor() as usize;
        let b = (m as f64).log2() as u32;

        HLL {
            alpha: alpha(m),
            b: b,
            m: m,
            M: repeat(0u8).take(m).collect(),
            isZero: false
        }
    }

    /// Add an element into the hyperloglog estimate.
    /// We require the type of value to be able to be hashed.
    /// Returns whether the insertion altered the hyperloglog
    pub fn insert<T: Hash>(&mut self, val: &T) -> bool {
        let mut hasher = SipHasher::new();
        val.hash(&mut hasher);
        let hash = hasher.finish();

        // j is the first b many bits
        let j = (hash >> (64 - self.b)) as usize;
        // w is the remaining bits (i.e. b -> 64)
        let w = hash & (2u64.pow(64 - self.b) - 1) as u64;
        let rho = leftmost_one_bit(w) as u8;

        let prev = self.M[j];
        self.M[j] = cmp::max(self.M[j], rho);

        prev != self.M[j]
    }

    /// Return the estimated cardinality of the observed set
    /// of elements.
    pub fn count(&self) -> f64 {
        self.range_correction(self.raw_estimate())
    }

    fn raw_estimate(&self) -> f64 {
        let sum: f64 = self.M.iter().fold (0.0, |p, &r| p + 2.0f64.powi(-(r as i32)));

        self.alpha as f64 * ((self.m  * self.m) as f64) * (1.0 / sum)
    }

    fn empty_registers (&self) -> usize {
        self.M.iter().filter(|&r| *r == 0).count()
    }

    fn range_correction(&self, e: f64) -> f64 {
        let twoTo32: f64 = 2.0f64.powi(32) as f64;

        // small range correction
        if e <= (5.0*(self.m as f64))/2.0 {
            let v  = self.empty_registers() as f64;
            let fm = self.m as f64;

            return match v {
                0.0 => e,
                _   => fm * (fm / v).ln()
            }
        }

        // medium range (no) correction
        if e <= twoTo32/30.0 {
            return e;
        }

        -twoTo32 * (1.0 - e/twoTo32).ln()
    }

    /// Access a copy of the underlying registers (this is mainly
    /// here just for debugging/testing... its unlikely you'll need
    /// this access typically).
    pub fn registers(&self) -> Vec<u8> {
        self.M.clone()
    }

    /// A completely zeroed HLL. Not particularly useful
    /// except as an identity element in `Add`.
    pub fn empty () -> HLL {
        HLL {
            alpha: 0.0,
            m: 0,
            b: 0,
            M: Vec::new(),
            isZero: true
        }
    }

    pub fn into_vec(self) -> Vec<u8> {
        let mut data = self.M;
        data.reserve(21);
        data.write_f64::<BigEndian>(self.alpha).unwrap();
        data.write_u32::<BigEndian>(self.b).unwrap();
        data.write_u64::<BigEndian>(self.m as u64).unwrap();
        data.write_u8(if self.isZero { 0 } else { 1 }).unwrap();
        data
    }

    pub fn from_vec(data: Vec<u8>) -> HLL {
        assert!(data.len() >= 21);
        let mut M = data;
        // drain or split_off would be useful, but are not stable yet
        let mut metadata = [0u8; 21];
        for i in 0..21 {
            metadata[20 - i] = M.pop().unwrap();
        }
        let mut readable = Cursor::new(metadata.to_vec());
        let alpha = readable.read_f64::<BigEndian>().unwrap();
        let b = readable.read_u32::<BigEndian>().unwrap();
        let m = readable.read_u64::<BigEndian>().unwrap() as usize;
        let isZero = readable.read_u8().unwrap() == 0;
        HLL {
            M: M,
            alpha: alpha,
            b: b,
            m: m,
            isZero: isZero,
        }
    }
}

/* ------------------------------------------------- */

/* --------------- trait instances ----------------- */

impl std::fmt::Display for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::fmt::Debug for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

fn zipWith<R, U: Iterator, C: Fn(U::Item, U::Item) -> R> (combo: C, left: U, right: U)
   -> Vec<R> {
    left.zip(right).map(| (l, r) | combo(l, r)).collect()
}

fn mergeRegisters (first: &Vec<u8>, second: &Vec<u8>) -> Vec<u8> {
    zipWith(|&l, &r| std::cmp::max(l, r), first.iter(), second.iter())
}

/// Adding together two HLLs produces a new HLL where
/// the larger value of each register has been selected.
impl<'a> std::ops::Add<&'a HLL> for &'a HLL {
    type Output = HLL;

    fn add(self, other: &'a HLL) -> HLL {
        // [!] gross...
        if self.isZero { return other.clone(); }
        if other.isZero { return self.clone(); }

        assert!(self.alpha == other.alpha);
        assert!(self.b == other.b);
        assert!(self.m == other.m);

        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: mergeRegisters(&self.M, &other.M),
            isZero: false
        }
    }
}

/* ------------------------------------------------- */
<commit_msg>manual pop loop -> drain<commit_after>// use variable names from paper, namely registers M
#![allow(non_snake_case)]

#![crate_name = "basichll"]
#![crate_type = "lib"]

extern crate byteorder;

/* -------------------- std libs ------------------- */
use std::cmp;
use std::fmt;
use std::hash::{ Hash, Hasher, SipHasher };
use std::io::Cursor;
use std::iter::{ repeat, Iterator };
/* ------------------------------------------------- */

use byteorder::{ BigEndian, WriteBytesExt, ReadBytesExt };

/* -------------------- constants ------------------ */

const METADATA_LENGTH: usize = 21;

/* -------------------- helpers -------------------- */

fn alpha (m: usize) -> f64 {
    match m {
        16 => 0.673,
        32 => 0.697,
        64 => 0.709,
        _  => 0.7213/(1f64 + 1.079/(m as f64))
    }
}

fn leftmost_one_bit (v: u64) -> usize {
    let mut counter: usize = 0;
    let mut shiftable = v;

    while shiftable > 0 {
        shiftable >>= 1;
        counter += 1;
    }

    64 - counter
}

/* ------------------------------------------------- */

/* --------------- hyper log log ------------------- */

/// The `HLL` struct stores the underlying registers
/// of the HyperLogLog, with `m` many registers.
///
/// The value for `m` is derived from the desired error
/// of the estimation. The error is considered to be
/// 1.04 / sqrt(2 ^ bits). So, given a desired 1% error
/// rate, we result in around 12 bits per register,
/// producing an underlying M of 2^12 bits (i.e. 4kb).
#[derive(Clone, PartialEq)]
pub struct HLL {
    alpha: f64,
    b: u32,
    m: usize,
    M: Vec<u8>,
    // [!] this is pretty much a hack until I can think of something
    //     better to do for the monoid instance. Basically we need the
    //     zero value to always satisfy the left and right identity laws
    //     but because you need to have the number of registers be
    //     equivalent to do addition, it implies you need a distinct
    //     monoid instance per HLL configuration (i.e. an HLL of 4
    //     registers has a distinct zero from a HLL of 16).
    //
    //     Because I can't really do dependent types in rust, we instead
    //     have a distinguished zero element, that is allowed to bypass
    //     the assertions on the equivalent sizes...
    //
    //     For reference, Ed Kmett's haskell implementation actually does
    //     use higher kinded types and some tricky reflection to make the
    //     monoid instance be parameterised by a config type that is itself
    //     typed to a Peano natural encoded type. Twitter's algebird instance
    //     declares a separate class that encapsulates the notion of
    //     a "HyperLogLogMonoid" instance, and instances of that class are
    //     instantiated with the register size (i.e. the 'instance' for monoid
    //     is just an 'instance' of the class, for two interpretations of
    //     'instance').
    isZero: bool
}

impl std::cmp::Eq for HLL {}

impl HLL {
    /// Convenience function to produce a HLL with
    /// one hundred and twenty eight registers.
    pub fn one_hundred_twenty_eight () -> HLL {
        HLL::new(0.09192)
    }

    /// Create a new HLL with the desired standard error.
    /// Some examples might be:
    ///
    ///```ignore
    ///     bits    size    error
    ///     12      4096    0.0163
    ///     13      8192    0.0115
    ///     14      16384   0.0081
    ///```
    ///
    /// The error must be between 0.0 and 1.0. Beware using a stupidly
    /// small error size will grow beyond e.g. isize at less than 0.03
    /// (if you need something that isn't an estimate probably don't use
    /// a hyperloglog).
    pub fn new(error: f64) -> HLL {
        assert!(error > 0.0 && error < 1.0);
        // error = 1.04 / sqrt(m)
        let m = ((1.04/error) * (1.04/error)).floor() as usize;
        let b = (m as f64).log2() as u32;

        HLL {
            alpha: alpha(m),
            b: b,
            m: m,
            M: repeat(0u8).take(m).collect(),
            isZero: false
        }
    }

    /// Add an element into the hyperloglog estimate.
    /// We require the type of value to be able to be hashed.
    /// Returns whether the insertion altered the hyperloglog
    pub fn insert<T: Hash>(&mut self, val: &T) -> bool {
        let mut hasher = SipHasher::new();
        val.hash(&mut hasher);
        let hash = hasher.finish();

        // j is the first b many bits
        let j = (hash >> (64 - self.b)) as usize;
        // w is the remaining bits (i.e. b -> 64)
        let w = hash & (2u64.pow(64 - self.b) - 1) as u64;
        let rho = leftmost_one_bit(w) as u8;

        let prev = self.M[j];
        self.M[j] = cmp::max(self.M[j], rho);

        prev != self.M[j]
    }

    /// Return the estimated cardinality of the observed set
    /// of elements.
    pub fn count(&self) -> f64 {
        self.range_correction(self.raw_estimate())
    }

    fn raw_estimate(&self) -> f64 {
        let sum: f64 = self.M.iter().fold (0.0, |p, &r| p + 2.0f64.powi(-(r as i32)));

        self.alpha as f64 * ((self.m  * self.m) as f64) * (1.0 / sum)
    }

    fn empty_registers (&self) -> usize {
        self.M.iter().filter(|&r| *r == 0).count()
    }

    fn range_correction(&self, e: f64) -> f64 {
        let twoTo32: f64 = 2.0f64.powi(32) as f64;

        // small range correction
        if e <= (5.0*(self.m as f64))/2.0 {
            let v  = self.empty_registers() as f64;
            let fm = self.m as f64;

            return match v {
                0.0 => e,
                _   => fm * (fm / v).ln()
            }
        }

        // medium range (no) correction
        if e <= twoTo32/30.0 {
            return e;
        }

        -twoTo32 * (1.0 - e/twoTo32).ln()
    }

    /// Access a copy of the underlying registers (this is mainly
    /// here just for debugging/testing... its unlikely you'll need
    /// this access typically).
    pub fn registers(&self) -> Vec<u8> {
        self.M.clone()
    }

    /// A completely zeroed HLL. Not particularly useful
    /// except as an identity element in `Add`.
    pub fn empty () -> HLL {
        HLL {
            alpha: 0.0,
            m: 0,
            b: 0,
            M: Vec::new(),
            isZero: true
        }
    }

    pub fn into_vec(self) -> Vec<u8> {
        let mut data = self.M;
        data.reserve(METADATA_LENGTH);
        data.write_f64::<BigEndian>(self.alpha).unwrap();
        data.write_u32::<BigEndian>(self.b).unwrap();
        data.write_u64::<BigEndian>(self.m as u64).unwrap();
        data.write_u8(if self.isZero { 0 } else { 1 }).unwrap();
        data
    }

    pub fn from_vec(data: Vec<u8>) -> HLL {
        assert!(data.len() >= METADATA_LENGTH);
        let mut M = data;
        let metadata_offset = M.len() - METADATA_LENGTH;
        let metadata: Vec<u8> = M.drain(metadata_offset..).collect();

        let mut readable = Cursor::new(metadata);
        let alpha = readable.read_f64::<BigEndian>().unwrap();
        let b = readable.read_u32::<BigEndian>().unwrap();
        let m = readable.read_u64::<BigEndian>().unwrap() as usize;
        let isZero = readable.read_u8().unwrap() == 0;
        HLL {
            M: M,
            alpha: alpha,
            b: b,
            m: m,
            isZero: isZero,
        }
    }
}

/* ------------------------------------------------- */

/* --------------- trait instances ----------------- */

impl std::fmt::Display for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::fmt::Debug for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

fn zipWith<R, U: Iterator, C: Fn(U::Item, U::Item) -> R> (combo: C, left: U, right: U)
   -> Vec<R> {
    left.zip(right).map(| (l, r) | combo(l, r)).collect()
}

fn mergeRegisters (first: &Vec<u8>, second: &Vec<u8>) -> Vec<u8> {
    zipWith(|&l, &r| std::cmp::max(l, r), first.iter(), second.iter())
}

/// Adding together two HLLs produces a new HLL where
/// the larger value of each register has been selected.
impl<'a> std::ops::Add<&'a HLL> for &'a HLL {
    type Output = HLL;

    fn add(self, other: &'a HLL) -> HLL {
        // [!] gross...
        if self.isZero { return other.clone(); }
        if other.isZero { return self.clone(); }

        assert!(self.alpha == other.alpha);
        assert!(self.b == other.b);
        assert!(self.m == other.m);

        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: mergeRegisters(&self.M, &other.M),
            isZero: false
        }
    }
}

/* ------------------------------------------------- */
<|endoftext|>


<commit_before>extern crate num;
use std::ops::{Add,Mul,Shr};
use std::num::Int;

use self::num::bigint::BigUint;
use self::num::Zero;
use self::num::Integer;
use self::num::bigint::ToBigUint;

pub enum DynamicChangingU64 {
    Regular(u64),
    Struct(BigUint),
}

impl DynamicChangingU64 {
    pub fn new(val: u64) -> DynamicChangingU64 {
        DynamicChangingU64::Regular(val)
    }
    pub fn is_zero(&self) -> bool {
        match *self {
            DynamicChangingU64::Regular(ref v) => {
                *v == 0
            }
            DynamicChangingU64::Struct(ref v) => {
                v.is_zero()
            }
        }
    }
    pub fn is_odd(&self) -> bool {
        match *self {
            DynamicChangingU64::Regular(ref v) => {
                *v % 2 == 1
            }
            DynamicChangingU64::Struct(ref v) => {
                v.is_odd()
            }
        }
    }
    pub fn bits(&self) -> uint {
        match *self {
            DynamicChangingU64::Regular(ref v) => {
                v.to_biguint().unwrap().bits()
            }
            DynamicChangingU64::Struct(ref v) => {
                v.bits()
            }
        }
    }
}

impl Add<uint> for DynamicChangingU64 {
    type Output = DynamicChangingU64;
    fn add(self, other: uint) -> DynamicChangingU64 {
        match self {
            DynamicChangingU64::Regular(ref v) => {
                match v.checked_add(other as u64) {
                    Some(v2) => DynamicChangingU64::Regular(v2),
                    None => DynamicChangingU64::Struct(v.to_biguint().unwrap() +
                                                       other.to_biguint().unwrap())
                }
            }
            DynamicChangingU64::Struct(ref v) => {
                DynamicChangingU64::Struct(v + other.to_biguint().unwrap())
            }
        }
    }
}

impl Mul<uint> for DynamicChangingU64 {
    type Output = DynamicChangingU64;
    fn mul(self, other: uint) -> DynamicChangingU64 {
        match self {
            DynamicChangingU64::Regular(ref v) => {
                match v.checked_mul(other as u64) {
                    Some(v2) => DynamicChangingU64::Regular(v2),
                    None => {
                        println!("switch over!");
                        DynamicChangingU64::Struct(v.to_biguint().unwrap() *
                                                       other.to_biguint().unwrap())
                    }
                }
            }
            DynamicChangingU64::Struct(ref v) => {
                DynamicChangingU64::Struct(v * other.to_biguint().unwrap())
            }
        }
    }
}

impl Shr<uint> for DynamicChangingU64 {
    type Output = DynamicChangingU64;
    fn shr(self, other: uint) -> DynamicChangingU64 {
        match self {
            DynamicChangingU64::Regular(ref v) => {
                DynamicChangingU64::Regular(*v >> other)
            }
            DynamicChangingU64::Struct(ref v) => {
                DynamicChangingU64::Struct(v >> other)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    extern crate num;
    use DynamicChangingU64;

    use self::num::Integer;
    use self::test::Bencher;
    use self::num::bigint::ToBigUint;

    #[bench]
    fn bench_dynamic_mul(b: &mut Bencher) {
        b.iter(|| {
            let a = DynamicChangingU64::new(123);
            let b = 123;
            let c = a * b;
            assert_eq!(true, c.is_odd());
        });
    }

    #[bench]
    fn bench_normal_mul(b: &mut Bencher) {
        b.iter(|| {
            let a = 123u64;
            let b = 123u64;
            let c = a * b;
            assert_eq!(1, c % 2);
        });
    }

    #[bench]
    fn bench_bigint_mul(b: &mut Bencher) {
        b.iter(|| {
            let a = 123u64.to_biguint().unwrap();
            let b = 123u64.to_biguint().unwrap();
            let c = a * b;
            assert_eq!(true, c.is_odd());
        });
    }
}
<commit_msg>uint deprecated<commit_after>extern crate num;
use std::ops::{Add,Mul,Shr};
use std::num::Int;

use self::num::bigint::BigUint;
use self::num::Zero;
use self::num::Integer;
use self::num::bigint::ToBigUint;

pub enum DynamicChangingU64 {
    Regular(u64),
    Struct(BigUint),
}

impl DynamicChangingU64 {
    pub fn new(val: u64) -> DynamicChangingU64 {
        DynamicChangingU64::Regular(val)
    }
    pub fn is_zero(&self) -> bool {
        match *self {
            DynamicChangingU64::Regular(ref v) => {
                *v == 0
            }
            DynamicChangingU64::Struct(ref v) => {
                v.is_zero()
            }
        }
    }
    pub fn is_odd(&self) -> bool {
        match *self {
            DynamicChangingU64::Regular(ref v) => {
                *v % 2 == 1
            }
            DynamicChangingU64::Struct(ref v) => {
                v.is_odd()
            }
        }
    }
    pub fn bits(&self) -> usize {
        match *self {
            DynamicChangingU64::Regular(ref v) => {
                v.to_biguint().unwrap().bits()
            }
            DynamicChangingU64::Struct(ref v) => {
                v.bits()
            }
        }
    }
}

impl Add<u64> for DynamicChangingU64 {
    type Output = DynamicChangingU64;
    fn add(self, other: u64) -> DynamicChangingU64 {
        match self {
            DynamicChangingU64::Regular(ref v) => {
                match v.checked_add(other as u64) {
                    Some(v2) => DynamicChangingU64::Regular(v2),
                    None => DynamicChangingU64::Struct(v.to_biguint().unwrap() +
                                                       other.to_biguint().unwrap())
                }
            }
            DynamicChangingU64::Struct(ref v) => {
                DynamicChangingU64::Struct(v + other.to_biguint().unwrap())
            }
        }
    }
}

impl Mul<u64> for DynamicChangingU64 {
    type Output = DynamicChangingU64;
    fn mul(self, other: u64) -> DynamicChangingU64 {
        match self {
            DynamicChangingU64::Regular(ref v) => {
                match v.checked_mul(other as u64) {
                    Some(v2) => DynamicChangingU64::Regular(v2),
                    None => {
                        println!("switch over!");
                        DynamicChangingU64::Struct(v.to_biguint().unwrap() *
                                                       other.to_biguint().unwrap())
                    }
                }
            }
            DynamicChangingU64::Struct(ref v) => {
                DynamicChangingU64::Struct(v * other.to_biguint().unwrap())
            }
        }
    }
}

impl Shr<usize> for DynamicChangingU64 {
    type Output = DynamicChangingU64;
    fn shr(self, other: usize) -> DynamicChangingU64 {
        match self {
            DynamicChangingU64::Regular(ref v) => {
                DynamicChangingU64::Regular(*v >> other)
            }
            DynamicChangingU64::Struct(ref v) => {
                DynamicChangingU64::Struct(v >> other)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    extern crate num;
    use DynamicChangingU64;

    use self::num::Integer;
    use self::test::Bencher;
    use self::num::bigint::ToBigUint;

    #[bench]
    fn bench_dynamic_mul(b: &mut Bencher) {
        b.iter(|| {
            let a = DynamicChangingU64::new(123);
            let b = 123;
            let c = a * b;
            assert_eq!(true, c.is_odd());
        });
    }

    #[bench]
    fn bench_normal_mul(b: &mut Bencher) {
        b.iter(|| {
            let a = 123u64;
            let b = 123u64;
            let c = a * b;
            assert_eq!(1, c % 2);
        });
    }

    #[bench]
    fn bench_bigint_mul(b: &mut Bencher) {
        b.iter(|| {
            let a = 123u64.to_biguint().unwrap();
            let b = 123u64.to_biguint().unwrap();
            let c = a * b;
            assert_eq!(true, c.is_odd());
        });
    }
}
<|endoftext|>


<commit_before>//! CHIP-8 emulator backend.
//! You can develop your own frontends for it.
//!
//! The reference frontend is
//! [crusty-chip-sfml](https://github.com/crumblingstatue/crusty-chip-sfml).
//!
//! The CHIP-8 technical documentation in the comments is copied from
//! http://devernay.free.fr/hacks/chip8/C8TECH10.HTM,
//! Copyright (c) Thomas P. Greene.

#![feature(core)]
#![warn(missing_docs)]

use std::slice::bytes::copy_memory;
use std::num::Wrapping;
use std::ops::{Deref, DerefMut};

mod ops;

const START_ADDR: u16 = 0x200;
const MEM_SIZE: usize = 4096;
/// The width of the Chip8's display in pixels.
pub const DISPLAY_WIDTH: usize = 64;
/// The height of the Chip8's display in pixels.
pub const DISPLAY_HEIGHT: usize = 32;

static FONTSET: [u8; 5 * 0x10] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80, // F
];

#[derive(Clone, Copy)]
struct KeypressWait {
    wait: bool,
    vx: usize
}

macro_rules! array_wrap (
    ($name:ident, $typ:ty) => (
        #[derive(Copy)]
        struct $name($typ);
        impl Clone for $name {
            fn clone(&self) -> $name { *self }
        }
        impl Deref for $name {
            type Target = $typ;
            fn deref(&self) -> &$typ { &self.0 }
        }
        impl DerefMut for $name {
            fn deref_mut(&mut self) -> &mut $typ { &mut self.0 }
        }
    )
);

array_wrap!(DisplayArray, [u8; DISPLAY_WIDTH * DISPLAY_HEIGHT]);
array_wrap!(MemArray, [u8; MEM_SIZE]);

/// A CHIP-8 virtual machine.
#[derive(Clone, Copy)]
pub struct VirtualMachine {
    ram: MemArray,
    v: [Wrapping<u8>; 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
    display: DisplayArray,
    display_updated: bool,
    keys: [bool; 16],
    keypress_wait: KeypressWait
}

impl VirtualMachine {

    /// Constructs a new VirtualMachine.
    pub fn new() -> VirtualMachine {
        let mut ch8 = VirtualMachine {
            ram: MemArray([0; MEM_SIZE]),
            v: [Wrapping(0); 16],
            i: 0,
            delay_timer: 0,
            sound_timer: 0,
            pc: START_ADDR,
            sp: 0,
            stack: [0; 16],
            display: DisplayArray([0; DISPLAY_WIDTH * DISPLAY_HEIGHT]),
            display_updated: false,
            keys: [false; 16],
            keypress_wait: KeypressWait {
                wait: false,
                vx: 0
            }
        };
        copy_memory(&FONTSET, &mut ch8.ram[0usize..5 * 0x10]);
        ch8
    }

    /// Loads a ROM into the VirtualMachine.
    ///
    /// ## Arguments ##
    /// * rom - ROM to load
    pub fn load_rom(&mut self, rom: &[u8]) {
        let len = self.ram.len();
        copy_memory(rom, &mut self.ram[START_ADDR as usize .. len]);
    }

    /// Does an emulation cycle.
    pub fn do_cycle(&mut self) {
        self.display_updated = false;
        if self.keypress_wait.wait {
            return;
        }

        let ins = self.fetch_ins();
        self.dispatch(ins);
    }

    // Decode instruction and execute it
    fn dispatch(&mut self, ins: u16) {
        // A 12-bit value, the lowest 12 bits of the instruction
        let nnn = ins & 0x0FFF;
        // A 4-bit value, the lowest 4 bits of the instruction
        let n = ins & 0x000F;
        // A 4-bit value, the lower 4 bits of the high byte of the instruction
        let x = (ins & 0x0F00) >> 8;
        // A 4-bit value, the upper 4 bits of the low byte of the instruction
        let y = (ins & 0x00F0) >> 4;
        // kk or byte - An 8-bit value, the lowest 8 bits of the instruction
        let kk = (ins & 0x00FF) as u8;

        match (ins & 0xF000) >> 12 {
            0x0 => match nnn {
                0x0E0 => ops::clear_display(self, ),
                0x0EE => ops::ret_from_subroutine(self, ),
                _ => ops::jump_to_sys_routine(self, 0)
            },
            0x1 => ops::jump_addr(self, nnn),
            0x2 => ops::call_subroutine(self, nnn as usize),
            0x3 => ops::skip_next_vx_eq(self, x as usize, kk),
            0x4 => ops::skip_next_vx_ne(self, x as usize, kk),
            0x5 => match n {
                0x0 => ops::skip_next_vx_eq_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x5XXX instruction: {:x}", ins)
            },
            0x6 => ops::set_vx_byte(self, x as usize, kk),
            0x7 => ops::add_vx_byte(self, x as usize, kk),
            0x8 => {
                let (x, y) = (x as usize, y as usize);
                match n {
                    0x0 => ops::set_vx_to_vy(self, x, y),
                    0x1 => ops::set_vx_to_vx_or_vy(self, x, y),
                    0x2 => ops::set_vx_to_vx_and_vy(self, x, y),
                    0x3 => ops::set_vx_to_vx_xor_vy(self, x, y),
                    0x4 => ops::add_vx_vy(self, x, y),
                    0x5 => ops::sub_vx_vy(self, x, y),
                    0x6 => ops::set_vx_to_vx_shr_1(self, x),
                    0xE => ops::set_vx_to_vx_shl_1(self, x),
                    _ => panic!("Unknown 0x8XXX instruction: {:x}", ins)
                }
            },
            0x9 => match n {
                0x0 => ops::skip_next_vx_ne_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x9XXX instruction: {:x}", ins)
            },
            0xA => ops::set_i(self, nnn),
            0xC => ops::set_vx_rand_and(self, x as usize, kk),
            0xD => ops::display_sprite(self, x as usize, y as usize, n as usize),
            0xE => match kk {
                0xA1 => ops::skip_next_key_vx_not_pressed(self, x as usize),
                0x9E => ops::skip_next_key_vx_pressed(self, x as usize),
                _ => panic!("Unknown 0xEXXX instruction: {:x}", ins)
            },
            0xF => {
                match kk {
                    0x07 => ops::set_vx_to_delay_timer(self, x as usize),
                    0x0A => ops::wait_for_keypress_store_in_vx(self, x as usize),
                    0x15 => ops::set_delay_timer(self, x as usize),
                    0x18 => ops::set_sound_timer(self, x as usize),
                    0x1E => ops::add_vx_to_i(self, x as usize),
                    0x29 => ops::set_i_to_loc_of_digit_vx(self, x as usize),
                    0x33 => ops::store_bcd_of_vx_to_i(self, x as usize),
                    0x55 => ops::copy_v0_through_vx_to_mem(self, x as usize),
                    0x65 => ops::read_v0_through_vx_from_mem(self, x as usize),
                    _ => panic!("Unknown 0xFXXX instruction: {:x}", ins)
                }
            },
            _ => panic!("Unknown instruction: {:04x}", ins)
        }
    }

    fn fetch_ins(&mut self) -> u16 {
        let b1 = self.ram[self.pc as usize];
        let b2 = self.ram[(self.pc + 1) as usize];
        self.pc += 2;
        (b1 as u16) << 8 | b2 as u16
    }

    /// Presses a key on the hexadecimal keypad.
    ///
    /// `key` should be in the range `0..15`.
    pub fn press_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = true;
        if self.keypress_wait.wait {
            self.v[self.keypress_wait.vx].0 = key as u8;
            self.keypress_wait.wait = false;
        }
    }

    /// Releases a key on the hexadecimal keypad.
    ///
    /// `key` should be in the range `0..15`.
    pub fn release_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = false;
    }

    /// Decrements the sound and delay timers.
    ///
    /// They should be decremented at a rate of 60 Hz.
    pub fn decrement_timers(&mut self) {
        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            self.sound_timer -= 1;
        }
    }

    /// Returns whether the display has been updated.
    pub fn display_updated(&self) -> bool { self.display_updated }
    /// Returns the contents of the display.
    pub fn display(&self) -> &[u8; DISPLAY_WIDTH * DISPLAY_HEIGHT] { &*self.display }
}
<commit_msg>Convert to stable rust<commit_after>//! CHIP-8 emulator backend.
//! You can develop your own frontends for it.
//!
//! The reference frontend is
//! [crusty-chip-sfml](https://github.com/crumblingstatue/crusty-chip-sfml).
//!
//! The CHIP-8 technical documentation in the comments is copied from
//! http://devernay.free.fr/hacks/chip8/C8TECH10.HTM,
//! Copyright (c) Thomas P. Greene.

#![warn(missing_docs)]

use std::num::Wrapping;
use std::ops::{Deref, DerefMut};

mod ops;

fn copy_memory(src: &[u8], dst: &mut [u8]) {
        let len_src = src.len();
        assert!(dst.len() >= len_src);
        // `dst` is unaliasable, so we know statically it doesn't overlap
        // with `src`.
        unsafe {
            std::ptr::copy_nonoverlapping(src.as_ptr(),
                                          dst.as_mut_ptr(),
                                          len_src);
        }
    }

const START_ADDR: u16 = 0x200;
const MEM_SIZE: usize = 4096;
/// The width of the Chip8's display in pixels.
pub const DISPLAY_WIDTH: usize = 64;
/// The height of the Chip8's display in pixels.
pub const DISPLAY_HEIGHT: usize = 32;

static FONTSET: [u8; 5 * 0x10] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80, // F
];

#[derive(Clone, Copy)]
struct KeypressWait {
    wait: bool,
    vx: usize
}

macro_rules! array_wrap (
    ($name:ident, $typ:ty) => (
        #[derive(Copy)]
        struct $name($typ);
        impl Clone for $name {
            fn clone(&self) -> $name { *self }
        }
        impl Deref for $name {
            type Target = $typ;
            fn deref(&self) -> &$typ { &self.0 }
        }
        impl DerefMut for $name {
            fn deref_mut(&mut self) -> &mut $typ { &mut self.0 }
        }
    )
);

array_wrap!(DisplayArray, [u8; DISPLAY_WIDTH * DISPLAY_HEIGHT]);
array_wrap!(MemArray, [u8; MEM_SIZE]);

/// A CHIP-8 virtual machine.
#[derive(Clone, Copy)]
pub struct VirtualMachine {
    ram: MemArray,
    v: [Wrapping<u8>; 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
    display: DisplayArray,
    display_updated: bool,
    keys: [bool; 16],
    keypress_wait: KeypressWait
}

impl VirtualMachine {

    /// Constructs a new VirtualMachine.
    pub fn new() -> VirtualMachine {
        let mut ch8 = VirtualMachine {
            ram: MemArray([0; MEM_SIZE]),
            v: [Wrapping(0); 16],
            i: 0,
            delay_timer: 0,
            sound_timer: 0,
            pc: START_ADDR,
            sp: 0,
            stack: [0; 16],
            display: DisplayArray([0; DISPLAY_WIDTH * DISPLAY_HEIGHT]),
            display_updated: false,
            keys: [false; 16],
            keypress_wait: KeypressWait {
                wait: false,
                vx: 0
            }
        };
        copy_memory(&FONTSET, &mut ch8.ram[0usize..5 * 0x10]);
        ch8
    }

    /// Loads a ROM into the VirtualMachine.
    ///
    /// ## Arguments ##
    /// * rom - ROM to load
    pub fn load_rom(&mut self, rom: &[u8]) {
        let len = self.ram.len();
        copy_memory(rom, &mut self.ram[START_ADDR as usize .. len]);
    }

    /// Does an emulation cycle.
    pub fn do_cycle(&mut self) {
        self.display_updated = false;
        if self.keypress_wait.wait {
            return;
        }

        let ins = self.fetch_ins();
        self.dispatch(ins);
    }

    // Decode instruction and execute it
    fn dispatch(&mut self, ins: u16) {
        // A 12-bit value, the lowest 12 bits of the instruction
        let nnn = ins & 0x0FFF;
        // A 4-bit value, the lowest 4 bits of the instruction
        let n = ins & 0x000F;
        // A 4-bit value, the lower 4 bits of the high byte of the instruction
        let x = (ins & 0x0F00) >> 8;
        // A 4-bit value, the upper 4 bits of the low byte of the instruction
        let y = (ins & 0x00F0) >> 4;
        // kk or byte - An 8-bit value, the lowest 8 bits of the instruction
        let kk = (ins & 0x00FF) as u8;

        match (ins & 0xF000) >> 12 {
            0x0 => match nnn {
                0x0E0 => ops::clear_display(self, ),
                0x0EE => ops::ret_from_subroutine(self, ),
                _ => ops::jump_to_sys_routine(self, 0)
            },
            0x1 => ops::jump_addr(self, nnn),
            0x2 => ops::call_subroutine(self, nnn as usize),
            0x3 => ops::skip_next_vx_eq(self, x as usize, kk),
            0x4 => ops::skip_next_vx_ne(self, x as usize, kk),
            0x5 => match n {
                0x0 => ops::skip_next_vx_eq_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x5XXX instruction: {:x}", ins)
            },
            0x6 => ops::set_vx_byte(self, x as usize, kk),
            0x7 => ops::add_vx_byte(self, x as usize, kk),
            0x8 => {
                let (x, y) = (x as usize, y as usize);
                match n {
                    0x0 => ops::set_vx_to_vy(self, x, y),
                    0x1 => ops::set_vx_to_vx_or_vy(self, x, y),
                    0x2 => ops::set_vx_to_vx_and_vy(self, x, y),
                    0x3 => ops::set_vx_to_vx_xor_vy(self, x, y),
                    0x4 => ops::add_vx_vy(self, x, y),
                    0x5 => ops::sub_vx_vy(self, x, y),
                    0x6 => ops::set_vx_to_vx_shr_1(self, x),
                    0xE => ops::set_vx_to_vx_shl_1(self, x),
                    _ => panic!("Unknown 0x8XXX instruction: {:x}", ins)
                }
            },
            0x9 => match n {
                0x0 => ops::skip_next_vx_ne_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x9XXX instruction: {:x}", ins)
            },
            0xA => ops::set_i(self, nnn),
            0xC => ops::set_vx_rand_and(self, x as usize, kk),
            0xD => ops::display_sprite(self, x as usize, y as usize, n as usize),
            0xE => match kk {
                0xA1 => ops::skip_next_key_vx_not_pressed(self, x as usize),
                0x9E => ops::skip_next_key_vx_pressed(self, x as usize),
                _ => panic!("Unknown 0xEXXX instruction: {:x}", ins)
            },
            0xF => {
                match kk {
                    0x07 => ops::set_vx_to_delay_timer(self, x as usize),
                    0x0A => ops::wait_for_keypress_store_in_vx(self, x as usize),
                    0x15 => ops::set_delay_timer(self, x as usize),
                    0x18 => ops::set_sound_timer(self, x as usize),
                    0x1E => ops::add_vx_to_i(self, x as usize),
                    0x29 => ops::set_i_to_loc_of_digit_vx(self, x as usize),
                    0x33 => ops::store_bcd_of_vx_to_i(self, x as usize),
                    0x55 => ops::copy_v0_through_vx_to_mem(self, x as usize),
                    0x65 => ops::read_v0_through_vx_from_mem(self, x as usize),
                    _ => panic!("Unknown 0xFXXX instruction: {:x}", ins)
                }
            },
            _ => panic!("Unknown instruction: {:04x}", ins)
        }
    }

    fn fetch_ins(&mut self) -> u16 {
        let b1 = self.ram[self.pc as usize];
        let b2 = self.ram[(self.pc + 1) as usize];
        self.pc += 2;
        (b1 as u16) << 8 | b2 as u16
    }

    /// Presses a key on the hexadecimal keypad.
    ///
    /// `key` should be in the range `0..15`.
    pub fn press_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = true;
        if self.keypress_wait.wait {
            self.v[self.keypress_wait.vx].0 = key as u8;
            self.keypress_wait.wait = false;
        }
    }

    /// Releases a key on the hexadecimal keypad.
    ///
    /// `key` should be in the range `0..15`.
    pub fn release_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = false;
    }

    /// Decrements the sound and delay timers.
    ///
    /// They should be decremented at a rate of 60 Hz.
    pub fn decrement_timers(&mut self) {
        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            self.sound_timer -= 1;
        }
    }

    /// Returns whether the display has been updated.
    pub fn display_updated(&self) -> bool { self.display_updated }
    /// Returns the contents of the display.
    pub fn display(&self) -> &[u8; DISPLAY_WIDTH * DISPLAY_HEIGHT] { &*self.display }
}
<|endoftext|>