<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use ::arch::vga;
use core::ptr::Unique;
use core::mem;
use core::fmt::{Write, Result};
use core::str::MatchIndices;
use spin::Mutex;

const ANSI_ESCAPE: &'static str = "\x1b";

pub struct Terminal { buffer: Unique<vga::Buffer>
                    , x: usize
                    , y: usize
                    , colors: vga::Palette
                    }

macro_rules! next_ansi_byte {
    ($b:expr) => { $b.next().expect("Unterminated ANSI escape sequence!") }
}

impl Terminal {

    #[inline]
    fn buffer(&mut self) -> &mut vga::Buffer {
        unsafe { self.buffer.get_mut() }
    }

    pub fn set_colors(&mut self, bg: vga::Color, fg: vga::Color)
                     -> &mut Self
    {
        self.colors = vga::Palette::new(bg,fg);
        self
    }
    fn scroll(&mut self) {
        let mut rows = self.buffer()
                           .iter_mut();

        let mut next = rows.next()
                           .unwrap();

        while let Some(thing) = rows.next() {
            mem::swap(next, thing);
            next = thing;
        }

        // empty last line
        unsafe { *next = mem::zeroed() }
    }

    pub fn clear(&mut self) -> &mut Self {
        unsafe { *(self.buffer()) = mem::zeroed(); }
        self
    }

    pub fn write_byte(&mut self, byte: u8) -> &mut Self {
        if byte == b'\n' {
            self.x = 0;
            self.y += 1;
        } else {
            // set character at position
            self.buffer()[self.y][self.x]
                = vga::Char { ascii: byte
                            , colors: self.colors };
            self.x += 1;

            // check for line wrapping
            if self.x >= vga::X_MAX {
                self.x = 0;
                self.y += 1;
            }
        }
        // check for scrolling
        if self.y >= vga::Y_MAX {
            self.scroll();
            self.y = vga::Y_MAX- 1;
        }
        self
    }

    fn handle_ansi_escape(&self, escape_code: &str) -> Result {
        match escape_code[4..].as_bytes() {
            [b'3', n @ u8, b'm'] => {
                unsafe { self.colors
                             .set_foreground(mem::transmute(n - 48)); }
                Ok(())
            }
          , [b'4', n @ u8, b'm'] => {
                unsafe { self.colors
                             .set_background(mem::transmute(n - 48)); }
                Ok(())
            }
          , _ => unimplemented!()
        }
        // let escape_seq: &str = bytes.take_while(|b| b != b'm')
        //                       .collect::<&str>();
        // match escape_seq {
        //     [b'3', n] => unsafe {
        //         self.colors.set_foreground(mem::transmute(n - 48))
        //     }
        // }
        // while let Some(byte) = bytes.next() {
        //     match *byte {
        //         // we've recieved an ANSI escape sequence.
        //         // this basically enters a mediocre FSM for matching ANSI
        //         // control codes.
        //         0x1b => match *next_ansi_byte!(bytes) {
        //             // handle multi-char ANSI escapes
        //             b'[' => match *next_ansi_byte!(bytes) {
        //                 // foreground color code
        //                 fg @ 30 ... 37 => {
        //                     if !(*next_ansi_byte!(bytes) == b'm') {
        //                         unsafe {
        //                             let color: vga::Color
        //                                 = mem::transmute(fg - 30);
        //                             self.colors
        //                                 .set_foreground(color);
        //                         }
        //
        //                     }
        //                 }
        //                 // background color code
        //               , 40 ... 47 => {
        //
        //                 }
        //               , _ => unimplemented!()
        //             }
        //           , _    => unimplemented!()
        //         }
        //         // otherwise, treat the byte as a normal ASCII char
        //       , b => { self.write_byte(b); }
        //     }
        // }

    }

}

struct AnsiEscapeIter<'a> { string: &'a str
                          , curr_slice: &'a str
                          , in_escape: bool
                          }

impl<'a> AnsiEscapeIter<'a> {

    pub fn new(s: &'a str) -> Self {
        AnsiEscapeIter { string: s
                       , curr_slice: s
                       , in_escape: false
                       }
    }
}

impl<'a> Iterator for AnsiEscapeIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.curr_slice.len() == 0 {
            // if the remaining string is empty, we just return `None`
            None
        } else {
            // otherwise, find the next index to chunk on.
            let maybe_idx
                = if self.in_escape {
                     // if we're in an escape code, we split the chunk at the
                     // index of the next 'm' character, adding 1 so that the
                     // 'm' is in the escape code chunk.
                    self.curr_slice.find('m')
                        .map(|idx| idx + 1)
                } else {
                    // otherwise, split at the next ANSI escape sequence
                    self.curr_slice.find(ANSI_ESCAPE)
                };

            // if we found another index to chunk on, map over that index;
            // otherwise, we just yield the rest of the string
            maybe_idx.map_or(
                Some(self.curr_slice) // remainder (if no index to chunk on)
              , |idx| { // otherwise, chunk along that index...
                    let (chunk, next_slice) = self.curr_slice
                                                  .split_at(idx);
                    self.curr_slice = next_slice; // update current chunk
                    Some(chunk)                   // return the chunk
                })
        }

    }
}

impl Write for Terminal {

    fn write_str(&mut self, s: &str) -> Result {

        if s.contains(ANSI_ESCAPE) {
            // if the segment contains an ANSI escape, construct an iterator
            // over each chunk containing either an escape sequence or text
            for segment in AnsiEscapeIter::new(s) {
                if segment.starts_with(ANSI_ESCAPE) {
                    // if the current segment is an ANSI escape code,
                    // try to handle the escape and fail if it is malformed
                    try!(self.handle_ansi_escape(segment))
                } else {
                    // otherwise, just write each chunk in the string.
                    for byte in segment.as_bytes() {
                        self.write_byte(*byte);
                    }
                }
            }
        } else {
            // otherwise, if there are no ANSI escape codes,
            // we can just write each byte in the string.
            for byte in s.as_bytes() {
                self.write_byte(*byte);
            }
        }
        Ok(())
    }

}

/// The system's VGA terminal
pub static CONSOLE: Mutex<Terminal>
    = Mutex::new(Terminal {
        colors: vga::Palette::new( vga::Color::LightGreen
                                 , vga::Color::Black
                                 )
      , x: 0
      , y: 0
      , buffer: unsafe { Unique::new(0xB8000 as *mut _) },
    });
<commit_msg>[term.rs] Additional documentation<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use ::arch::vga;
use core::ptr::Unique;
use core::mem;
use core::fmt::{Write, Result};
use core::str::MatchIndices;
use spin::Mutex;

const ANSI_ESCAPE: &'static str = "\x1b";

pub struct Terminal { buffer: Unique<vga::Buffer>
                    , x: usize
                    , y: usize
                    , colors: vga::Palette
                    }

macro_rules! next_ansi_byte {
    ($b:expr) => { $b.next().expect("Unterminated ANSI escape sequence!") }
}

impl Terminal {

    #[inline]
    fn buffer(&mut self) -> &mut vga::Buffer {
        unsafe { self.buffer.get_mut() }
    }

    /// Set the color palette used for writing subsequent characters.
    pub fn set_colors(&mut self, bg: vga::Color, fg: vga::Color)
                     -> &mut Self
    {
        self.colors = vga::Palette::new(bg,fg);
        self
    }

    /// Scrolls the terminal one row.
    fn scroll(&mut self) {
        // construct an iterator over the whole buffer
        let mut rows = self.buffer()
                           .iter_mut();

        // the current row in the buffer
        let mut current = rows.next()
                           .unwrap();

        while let Some(next) = rows.next() {
            // while there are rows remaining in the iterator, swap the
            // next row with the current one (moving it back by one)
            mem::swap(current, next);
            // and advance our pointer to the current row.
            current = next;
        }

        // empty the last line in the buffer
        unsafe { *current = mem::zeroed() }
    }

    /// Clear the terminal
    pub fn clear(&mut self) -> &mut Self {
        // to clear the terminal, we just zero out the whole buffer.
        unsafe { *(self.buffer()) = mem::zeroed(); }
        self
    }

    /// Write the given byte to the terminal, and advance the cursor position.
    pub fn write_byte(&mut self, byte: u8) -> &mut Self {
        if byte == b'\n' {
            // if the byte is a newline, we just advance to the next line
            // and reset the column position.
            self.x = 0;
            self.y += 1;
        } else {
            // otherwise, it's a regular character, so we just set the
            // byte at the current position in the buffer to that
            // character (with the current color palette)
            self.buffer()[self.y][self.x]
                = vga::Char { ascii: byte
                            , colors: self.colors };
            // and advance our column position by one
            self.x += 1;

            if self.x >= vga::X_MAX {
                // if we've reached the end of the line, advance to the next
                self.x = 0;
                self.y += 1;
            }
        }
        if self.y >= vga::Y_MAX {
            // if we've reached the bottom of the terminal, scroll.
            self.scroll();
            self.y = vga::Y_MAX- 1;
        }
        self
    }

    fn handle_ansi_escape(&self, escape_code: &str) -> Result {
        match escape_code.as_bytes() {
            // `\x1b[3Nm` sets the foreground color to N.
            [0x1b, b'[', b'3', n, b'm'] => {
                unsafe { self.colors
                             .set_foreground(mem::transmute(n - 48)); }
                Ok(())
            }
            // `\x1b[4Nm` sets the background color to N
          , [0x1b, b'[', b'4', n, b'm'] => {
                unsafe { self.colors
                             .set_background(mem::transmute(n - 48)); }
                Ok(())
            }
          , _ => unimplemented!()
        }
        // let escape_seq: &str = bytes.take_while(|b| b != b'm')
        //                       .collect::<&str>();
        // match escape_seq {
        //     [b'3', n] => unsafe {
        //         self.colors.set_foreground(mem::transmute(n - 48))
        //     }
        // }
        // while let Some(byte) = bytes.next() {
        //     match *byte {
        //         // we've recieved an ANSI escape sequence.
        //         // this basically enters a mediocre FSM for matching ANSI
        //         // control codes.
        //         0x1b => match *next_ansi_byte!(bytes) {
        //             // handle multi-char ANSI escapes
        //             b'[' => match *next_ansi_byte!(bytes) {
        //                 // foreground color code
        //                 fg @ 30 ... 37 => {
        //                     if !(*next_ansi_byte!(bytes) == b'm') {
        //                         unsafe {
        //                             let color: vga::Color
        //                                 = mem::transmute(fg - 30);
        //                             self.colors
        //                                 .set_foreground(color);
        //                         }
        //
        //                     }
        //                 }
        //                 // background color code
        //               , 40 ... 47 => {
        //
        //                 }
        //               , _ => unimplemented!()
        //             }
        //           , _    => unimplemented!()
        //         }
        //         // otherwise, treat the byte as a normal ASCII char
        //       , b => { self.write_byte(b); }
        //     }
        // }

    }

}

struct AnsiEscapeIter<'a> { string: &'a str
                          , curr_slice: &'a str
                          , in_escape: bool
                          }

impl<'a> AnsiEscapeIter<'a> {

    pub fn new(s: &'a str) -> Self {
        AnsiEscapeIter { string: s
                       , curr_slice: s
                       , in_escape: false
                       }
    }
}

impl<'a> Iterator for AnsiEscapeIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.curr_slice.len() == 0 {
            // if the remaining string is empty, we just return `None`
            None
        } else {
            // otherwise, find the next index to chunk on.
            let maybe_idx
                = if self.in_escape {
                     // if we're in an escape code, we split the chunk at the
                     // index of the next 'm' character, adding 1 so that the
                     // 'm' is in the escape code chunk.
                    self.curr_slice.find('m')
                        .map(|idx| idx + 1)
                } else {
                    // otherwise, split at the next ANSI escape sequence
                    self.curr_slice.find(ANSI_ESCAPE)
                };

            // if we found another index to chunk on, map over that index;
            // otherwise, we just yield the rest of the string
            maybe_idx.map_or(
                Some(self.curr_slice) // remainder (if no index to chunk on)
              , |idx| { // otherwise, chunk along that index...
                    let (chunk, next_slice) = self.curr_slice
                                                  .split_at(idx);
                    self.curr_slice = next_slice; // update current chunk
                    Some(chunk)                   // return the chunk
                })
        }

    }
}

impl Write for Terminal {

    fn write_str(&mut self, s: &str) -> Result {

        if s.contains(ANSI_ESCAPE) {
            // if the segment contains an ANSI escape, construct an iterator
            // over each chunk containing either an escape sequence or text
            for segment in AnsiEscapeIter::new(s) {
                if segment.starts_with(ANSI_ESCAPE) {
                    // if the current segment is an ANSI escape code,
                    // try to handle the escape and fail if it is malformed
                    try!(self.handle_ansi_escape(segment))
                } else {
                    // otherwise, just write each chunk in the string.
                    for byte in segment.as_bytes() {
                        self.write_byte(*byte);
                    }
                }
            }
        } else {
            // otherwise, if there are no ANSI escape codes,
            // we can just write each byte in the string.
            for byte in s.as_bytes() {
                self.write_byte(*byte);
            }
        }
        Ok(())
    }

}

/// The system's global VGA terminal
pub static CONSOLE: Mutex<Terminal>
    = Mutex::new(Terminal {
        colors: vga::Palette::new( vga::Color::LightGreen
                                 , vga::Color::Black
                                 )
      , x: 0
      , y: 0
      , buffer: unsafe { Unique::new(0xB8000 as *mut _) },
    });
<|endoftext|>


<commit_before>pub struct KissRng {
    x: usize,
    y: usize,
    z: usize,
    c: usize,
}

impl KissRng {
    pub fn new() -> KissRng {
        return KissRng {
            x: 123456789,
            y: 987654321,
            z: 43219876,
            c: 6543217,
        };
    }

    pub fn next(&mut self) -> usize {
        self.x = 314527869usize.wrapping_mul(self.x).wrapping_add(1234567);
        self.y ^= self.y.rotate_left(5);
        self.y ^= self.y.rotate_right(7);
        self.y ^= self.y.rotate_left(22);
        self.z = 4294584393usize.wrapping_mul(self.z).wrapping_add(self.c);
        self.c = self.z.rotate_right(32);
        return self.x.wrapping_add(self.y).wrapping_add(self.z);
    }
}

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

    #[test]
    fn kissrng_test_for_overflow() {
        let mut rng = KissRng::new();
        for _ in 0..1000000 {
            rng.next();
        }
    }
}
<commit_msg>Added time to modify seed<commit_after>extern crate time;

pub struct KissRng {
    x: usize,
    y: usize,
    z: usize,
    c: usize,
}

impl KissRng {
    pub fn new() -> KissRng {
        let now = time::precise_time_ns() as usize;
        return KissRng {
            x: 123456789usize.wrapping_add(now),
            y: 987654321usize.wrapping_add(now),
            z: 43219876usize.wrapping_add(now),
            c: 6543217usize.wrapping_add(now)
        };
    }

    pub fn next(&mut self) -> usize {
        self.x = 314527869usize.wrapping_mul(self.x).wrapping_add(1234567);
        self.y ^= self.y.rotate_left(5);
        self.y ^= self.y.rotate_right(7);
        self.y ^= self.y.rotate_left(22);
        self.z = 4294584393usize.wrapping_mul(self.z).wrapping_add(self.c);
        self.c = self.z.rotate_right(32);
        return self.x.wrapping_add(self.y).wrapping_add(self.z);
    }
}

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

    #[test]
    fn kissrng_test_for_overflow() {
        let mut rng = KissRng::new();
        for _ in 0..1000000 {
            rng.next();
        }
    }
}
<|endoftext|>


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

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrow from an owned value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrow from an owned value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of Clone to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Create owned data from borrowed data, usually by copying.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements both `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable references to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquire a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extract the owned data.
    ///
    /// Copies the data if it is not already owned.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }

    /// Returns true if this `Cow` wraps a borrowed value
    #[deprecated(since = "1.0.0", reason = "match on the enum instead")]
    #[unstable(feature = "std_misc")]
    pub fn is_borrowed(&self) -> bool {
        match *self {
            Borrowed(_) => true,
            _ => false,
        }
    }

    /// Returns true if this `Cow` wraps an owned value
    #[deprecated(since = "1.0.0", reason = "match on the enum instead")]
    #[unstable(feature = "std_misc")]
    pub fn is_owned(&self) -> bool {
        match *self {
            Owned(_) => true,
            _ => false,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: Clone> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<commit_msg>Document std::borrow with examples<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrow from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrow from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of Clone to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Create owned data from borrowed data, usually by copying.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements both `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable references to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquire a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(&[1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extract the owned data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }

    /// Returns true if this `Cow` wraps a borrowed value
    #[deprecated(since = "1.0.0", reason = "match on the enum instead")]
    #[unstable(feature = "std_misc")]
    pub fn is_borrowed(&self) -> bool {
        match *self {
            Borrowed(_) => true,
            _ => false,
        }
    }

    /// Returns true if this `Cow` wraps an owned value
    #[deprecated(since = "1.0.0", reason = "match on the enum instead")]
    #[unstable(feature = "std_misc")]
    pub fn is_owned(&self) -> bool {
        match *self {
            Owned(_) => true,
            _ => false,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: Clone> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Logging for alacritty.
//!
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
use log;
use std::sync;
use std::io;
use cli;

pub struct Logger<T:Send+io::Write> {
    level: log::LogLevelFilter,
    output: sync::Mutex<T>
}

impl<T> Logger<T> where T:Send+io::Write {
    pub fn new(output: T, level: log::LogLevelFilter) -> Logger<io::LineWriter<T>> {
        Logger { level: level,
                 output: sync::Mutex::new(io::LineWriter::new(output)) }
    }
}

impl<T> log::Log for Logger<T> where T:Send+io::Write {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            if record.target().starts_with("alacritty") {
                if let Ok(ref mut writer) = self.output.lock() {
                    let _ = writer.write(format!("{}\n", record.args()).as_ref());
                }
            }
        }
    }
}

pub fn initialize(options: &cli::Options) {
    log::set_logger(|max_log_level| {
        max_log_level.set(options.log_level);
        Box::new(Logger::new(io::stdout(), options.log_level))
    }).unwrap_or_else(|e| die!("{}", e));
}
<commit_msg>Minor formatting fixes<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Logging for alacritty.
//!
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
use log;
use std::sync;
use std::io;
use cli;

pub struct Logger<T> {
    level: log::LogLevelFilter,
    output: sync::Mutex<T>
}

impl<T: Send + io::Write> Logger<T> {
    pub fn new(output: T, level: log::LogLevelFilter) -> Logger<io::LineWriter<T>> {
        Logger {
            level: level,
            output: sync::Mutex::new(io::LineWriter::new(output))
        }
    }
}

impl<T: Send + io::Write> log::Log for Logger<T> {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            if record.target().starts_with("alacritty") {
                if let Ok(ref mut writer) = self.output.lock() {
                    let _ = writer.write(format!("{}\n", record.args()).as_ref());
                }
            }
        }
    }
}

pub fn initialize(options: &cli::Options) {
    log::set_logger(|max_log_level| {
        max_log_level.set(options.log_level);
        Box::new(Logger::new(io::stdout(), options.log_level))
    }).unwrap_or_else(|e| die!("{}", e));
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

#[derive(Clone, Debug)]
pub struct Message {
    uuid: String,
    name: Option<String>,
    data: BTreeMap<String, String>
}

impl Message {
    pub fn new(uuid: String) -> Message {
        Message {
            uuid: uuid,
            name: None,
            data: BTreeMap::new()
        }
    }

    pub fn uuid(&self) -> &String {
        &self.uuid
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.data.get(key)
    }
}

pub struct Builder {
    uuid: String,
    name: Option<String>,
    data: BTreeMap<String, String>
}

impl Builder {
    pub fn new(uuid: String) -> Builder {
        Builder {
            uuid: uuid,
            name: None,
            data: BTreeMap::new()
        }
    }

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

    pub fn pair(&mut self, key: String, value: String) -> &mut Builder {
        self.data.insert(key, value);
        self
    }

    pub fn build(&self) -> Message {
        Message {
            uuid: self.uuid.clone(),
            name: self.name.clone(),
            data: self.data.clone()
        }
    }
}
<commit_msg>Message: add name() method<commit_after>use std::collections::BTreeMap;

#[derive(Clone, Debug)]
pub struct Message {
    uuid: String,
    name: Option<String>,
    data: BTreeMap<String, String>
}

impl Message {
    pub fn new(uuid: String) -> Message {
        Message {
            uuid: uuid,
            name: None,
            data: BTreeMap::new()
        }
    }

    pub fn uuid(&self) -> &String {
        &self.uuid
    }

    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.data.get(key)
    }
}

pub struct Builder {
    uuid: String,
    name: Option<String>,
    data: BTreeMap<String, String>
}

impl Builder {
    pub fn new(uuid: String) -> Builder {
        Builder {
            uuid: uuid,
            name: None,
            data: BTreeMap::new()
        }
    }

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

    pub fn pair(&mut self, key: String, value: String) -> &mut Builder {
        self.data.insert(key, value);
        self
    }

    pub fn build(&self) -> Message {
        Message {
            uuid: self.uuid.clone(),
            name: self.name.clone(),
            data: self.data.clone()
        }
    }
}
<|endoftext|>


<commit_before>extern crate git2;

use git2::*;
use std::process::Command;
use std::path::Path;
use std::path::PathBuf;

const TMP_NAME: &'static str = "tmp_fd2db5f8_bac2_4a1e_9487_4ac3414788aa";

pub trait RepoHost
{
    fn central(&self) -> &str;
    fn projects(&self) -> Vec<String>;

    fn remote_url(&self, &str) -> String;
    fn fetch_url(&self, module: &str) -> String
    {
        self.remote_url(module)
    }
}

pub struct Scratch<'a>
{
    repo: Repository,
    host: &'a RepoHost,
}

impl<'a> Scratch<'a>
{
    pub fn new(path: &Path, host: &'a RepoHost) -> Scratch<'a>
    {
        Scratch {
            repo: Repository::init_bare(&path).expect("could not init scratch"),
            host: host,
        }
    }

    fn tracking(&self, module: &str, branch: &str) -> Option<Object>
    {
        let remote_name = format!("{}", module);
        let fetch_url = self.host.fetch_url(&module);
        let mut remote = if let Ok(remote) = self.repo.find_remote(&remote_name) {
            remote
        }
        else {
            debug!("==== create remote (remote_name:{}, remote_url:{})",
                   &remote_name,
                   &fetch_url);
            self.repo.remote(&remote_name, &fetch_url).expect("can't create remote")
        };

        let rs = remote.get_refspec(0).unwrap().str().unwrap().to_string();
        remote.fetch(&[&rs], None, None).expect("fetch failed");
        return self.repo
            .revparse_single(&format!("remotes/{}/{}", module, branch))
            .ok();
    }

    fn call_git(self: &Scratch<'a>, cmd: &str) -> Result<String, Error>
    {
        let args: Vec<&str> = cmd.split(" ").collect();
        let repo_path = &self.repo.path();
        let mut c = Command::new("git");
        c.current_dir(&repo_path);
        c.env("GIT_DIR", repo_path.as_os_str());
        c.args(&args);

        let output = c.output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));
        Ok(String::from_utf8(output.stderr).expect("cannot decode utf8"))
    }

    // force push of the new revision-object to temp repo
    pub fn transfer(&self, rev: &str, source: &Path) -> Object
    {
        // TODO: implement using libgit
        let target = &self.repo.path();
        let shell = Shell { cwd: source.to_path_buf() };
        // create tmp branch
        shell.command(&format!("git branch -f {} {}", TMP_NAME, rev));
        // force push
        shell.command(&format!("git push --force {} {}",
                               &target.to_string_lossy(),
                               TMP_NAME));
        // delete tmp branch
        shell.command(&format!("git branch -D {}", TMP_NAME));

        let obj = self.repo.revparse_single(rev).expect("can't find transfered ref");
        return obj;
    }

    // takes everything from base except it's tree and replaces it with the tree
    // given
    fn rewrite(&self, base: &Commit, parents: &[&Commit], tree: &Tree) -> Oid
    {
        if parents.len() != 0 {
            self.repo.set_head_detached(parents[0].id()).expect("rewrite: can't detach head");
        }
        self.repo
            .commit(Some("HEAD"),
                    &base.author(),
                    &base.committer(),
                    &base.message().unwrap_or("no message"),
                    tree,
                    parents)
            .expect("rewrite: can't commit")
    }

    pub fn push(&self, oid: Oid, module: &str, target: &str) -> String
    {
        let commit = &self.repo.find_commit(oid).expect("can't find commit");
        self.repo.set_head_detached(commit.id()).expect("can't detach HEAD");
        let output =
            self.call_git(&format!("push {} HEAD:{}", self.host.remote_url(module), target))
                .expect("can't push");
        format!("{}", output)
    }

    fn subtree(&self, tree: &Tree, path: &Path) -> Option<Tree>
    {
        if let Some(oid) = tree.get_path(path).map(|x| x.id()).ok() {
            return self.repo.find_tree(oid).ok();
        }
        else {
            return None;
        }
    }

    fn replace_child(&self, child: &Path, subtree: Oid, full_tree: Tree) -> Tree
    {
        let full_tree_id = {
            let mut builder = self.repo
                .treebuilder(Some(&full_tree))
                .expect("replace_child: can't create treebuilder");
            builder.insert(child, subtree, 0o0040000) // GIT_FILEMODE_TREE
                .expect("replace_child: can't insert tree");
            builder.write().expect("replace_child: can't write tree")
        };
        return self.repo.find_tree(full_tree_id).expect("replace_child: can't find new tree");
    }

    fn replace_subtree(&self, path: &Path, subtree: Oid, full_tree: Tree) -> Tree
    {
        if path.components().count() == 1 {
            return self.replace_child(path, subtree, full_tree);
        }
        else {
            let name = Path::new(path.file_name().expect("no module name"));
            let path = path.parent().expect("module not in subdir");

            let st = self.subtree(&full_tree, path).unwrap();
            let tree = self.replace_child(name, subtree, st);

            return self.replace_subtree(path, tree.id(), full_tree);
        }
    }

    fn split_subdir(&self, module: &str, newrev: Oid) -> Object
    {
        // TODO: implement using libgit
        let shell = Shell { cwd: self.repo.path().to_path_buf() };
        shell.command("rm -Rf refs/original");
        shell.command("rm -Rf .git-rewrite");

        self.repo.set_head_detached(newrev).expect("can't detatch head");;

        self.call_git(&format!("filter-branch --subdirectory-filter {}/ -- HEAD", module))
            .expect("error in filter-branch");

        return self.repo
            .revparse_single("HEAD")
            .expect("can't find rewritten branch");
    }
}

pub enum ReviewUploadResult
{
    Uploaded(Oid),
    RejectNoFF,
    RejectMerge,
    NoChanges,
    Central,
}

pub fn review_upload(scratch: &Scratch, newrev: Object, module: &str) -> ReviewUploadResult
{
    debug!(".\n\n==== Doing review upload for module {}", &module);

    let new = newrev.id();
    let old = scratch.tracking(&module, "master").expect("no tracking branch 1").id();

    if old == new {
        return ReviewUploadResult::NoChanges;
    }

    match scratch.repo.graph_descendant_of(new, old) {
        Err(_) => return ReviewUploadResult::RejectNoFF,
        Ok(false) => return ReviewUploadResult::RejectNoFF,
        Ok(true) => (),
    }

    debug!("==== walking commits from {} to {}", old, new);

    let walk = {
        let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
        walk.set_sorting(SORT_REVERSE | SORT_TIME);
        let range = format!("{}..{}", old, new);
        walk.push_range(&range).expect(&format!("walk: invalid range: {}", range));;
        walk
    };

    let mut current =
        scratch.tracking(scratch.host.central(), "master").expect("no central tracking").id();

    for rev in walk {
        let rev = rev.expect("walk: invalid rev");
        if old == rev {
            continue;
        }

        debug!("==== walking commit {}", rev);

        let module_commit = scratch.repo
            .find_commit(rev)
            .expect("walk: object is not actually a commit");

        if module_commit.parents().count() > 1 {
            // TODO: also do this check on pushes to cenral refs/for/master
            // TODO: invectigate the possibility of allowing merge commits
            return ReviewUploadResult::RejectMerge;
        }

        if module != scratch.host.central() {
            debug!("==== Rewriting commit {}", rev);

            let tree = module_commit.tree().expect("walk: commit has no tree");
            let parent =
                scratch.repo.find_commit(current).expect("walk: current object is no commit");

            let new_tree = scratch.replace_subtree(Path::new(module),
                                                   tree.id(),
                                                   parent.tree()
                                                       .expect("walk: parent has no tree"));

            current = scratch.rewrite(&module_commit, &vec![&parent], &new_tree);
        }
    }

    if module != scratch.host.central() {
        return ReviewUploadResult::Uploaded(current);
    }
    else {
        return ReviewUploadResult::Central;
    }
}

pub fn project_created(scratch: &Scratch)
{
    if let Some(rev) = scratch.tracking(scratch.host.central(), "master") {
        central_submit(scratch, rev);
    }
}

pub fn central_submit(scratch: &Scratch, newrev: Object)
{
    debug!(" ---> central_submit (sha1 of commit: {})", &newrev.id());

    let central_commit = newrev.as_commit().expect("could not get commit from obj");
    let central_tree = central_commit.tree().expect("commit has no tree");

    for module in scratch.host.projects() {
        if module == scratch.host.central() {
            continue;
        }
        debug!("");
        debug!("==== fetching tracking branch for module: {}", &module);
        let module_master_commit_obj = match scratch.tracking(&module, "master") {
            Some(obj) => obj,
            None => {
                debug!("====    no tracking branch for module {} => project does not exist or is \
                        empty",
                       &module);
                debug!("====    initializing with subdir history");
                let commit = scratch.split_subdir(&module, newrev.id());
                scratch.push(commit.id(), &module, "refs/heads/master");
                scratch.tracking(&module, "master").expect("no tracking branch 3")
            }
        };

        let parents = vec![module_master_commit_obj.as_commit()
                               .expect("could not get commit from obj")];

        debug!("==== checking for changes in module: {:?}", module);

        // new tree is sub-tree of complete central tree
        let old_tree_id = if let Ok(tree) = parents[0].tree() {
            tree.id()
        }
        else {
            Oid::from_str("0000000000000000000000000000000000000000").unwrap()
        };

        let new_tree_id = if let Ok(tree_entry) = central_tree.get_path(&Path::new(&module)) {
            tree_entry.id()
        }
        else {
            Oid::from_str("0000000000000000000000000000000000000000").unwrap()
        };

        // if sha1's are equal the content is equal
        if new_tree_id != old_tree_id && !new_tree_id.is_zero() {
            let new_tree = scratch.repo.find_tree(new_tree_id).expect("central_submit: can't find tree");
            debug!("====    commit changes module => make commit on module");
            let module_commit = scratch.rewrite(central_commit, &parents, &new_tree);
            let output = scratch.push(module_commit, &module, "master");
            debug!("{}",output);
        }
        else {
            debug!("====    commit does not change module => skipping");
        }
    }
}

pub fn find_repos(root: &Path, path: &Path, mut repos: Vec<String>) -> Vec<String>
{
    if let Ok(children) = path.read_dir() {
        for child in children {
            let path = child.unwrap().path();

            let name = format!("{}", &path.to_str().unwrap());
            if let Some(last) = path.extension() {
                if last == "git" {
                    repos.push(name.trim_right_matches(".git")
                        .trim_left_matches(root.to_str().unwrap())
                        .trim_left_matches("/")
                        .to_string());
                    continue;
                }
            }
            repos = find_repos(root, &path, repos);
        }
    }
    return repos;
}

pub struct Shell
{
    pub cwd: PathBuf,
}

impl Shell
{
    pub fn command(&self, cmd: &str) -> String
    {
        debug!("Shell::command: {}", cmd);
        let output = Command::new("sh")
            .current_dir(&self.cwd)
            .arg("-c")
            .arg(&cmd)
            .output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

        return String::from_utf8(output.stdout).expect("failed to decode utf8").trim().to_string();
    }
}
<commit_msg>better debug output<commit_after>extern crate git2;

use git2::*;
use std::process::Command;
use std::path::Path;
use std::path::PathBuf;

const TMP_NAME: &'static str = "tmp_fd2db5f8_bac2_4a1e_9487_4ac3414788aa";

pub trait RepoHost
{
    fn central(&self) -> &str;
    fn projects(&self) -> Vec<String>;

    fn remote_url(&self, &str) -> String;
    fn fetch_url(&self, module: &str) -> String
    {
        self.remote_url(module)
    }
}

pub struct Scratch<'a>
{
    repo: Repository,
    host: &'a RepoHost,
}

impl<'a> Scratch<'a>
{
    pub fn new(path: &Path, host: &'a RepoHost) -> Scratch<'a>
    {
        Scratch {
            repo: Repository::init_bare(&path).expect("could not init scratch"),
            host: host,
        }
    }

    fn tracking(&self, module: &str, branch: &str) -> Option<Object>
    {
        let remote_name = format!("{}", module);
        let fetch_url = self.host.fetch_url(&module);
        let mut remote = if let Ok(remote) = self.repo.find_remote(&remote_name) {
            remote
        }
        else {
            debug!("==== create remote (remote_name:{}, remote_url:{})",
                   &remote_name,
                   &fetch_url);
            self.repo.remote(&remote_name, &fetch_url).expect("can't create remote")
        };

        let rs = remote.get_refspec(0).unwrap().str().unwrap().to_string();
        remote.fetch(&[&rs], None, None).expect("fetch failed");
        return self.repo
            .revparse_single(&format!("remotes/{}/{}", module, branch))
            .ok();
    }

    fn call_git(self: &Scratch<'a>, cmd: &str) -> Result<String, Error>
    {
        let args: Vec<&str> = cmd.split(" ").collect();
        let repo_path = &self.repo.path();
        let mut c = Command::new("git");
        c.current_dir(&repo_path);
        c.env("GIT_DIR", repo_path.as_os_str());
        c.args(&args);

        let output = c.output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));
        Ok(String::from_utf8(output.stderr).expect("cannot decode utf8"))
    }

    // force push of the new revision-object to temp repo
    pub fn transfer(&self, rev: &str, source: &Path) -> Object
    {
        // TODO: implement using libgit
        let target = &self.repo.path();
        let shell = Shell { cwd: source.to_path_buf() };
        // create tmp branch
        shell.command(&format!("git branch -f {} {}", TMP_NAME, rev));
        // force push
        shell.command(&format!("git push --force {} {}",
                               &target.to_string_lossy(),
                               TMP_NAME));
        // delete tmp branch
        shell.command(&format!("git branch -D {}", TMP_NAME));

        let obj = self.repo.revparse_single(rev).expect("can't find transfered ref");
        return obj;
    }

    // takes everything from base except it's tree and replaces it with the tree
    // given
    fn rewrite(&self, base: &Commit, parents: &[&Commit], tree: &Tree) -> Oid
    {
        if parents.len() != 0 {
            self.repo.set_head_detached(parents[0].id()).expect("rewrite: can't detach head");
        }
        self.repo
            .commit(Some("HEAD"),
                    &base.author(),
                    &base.committer(),
                    &base.message().unwrap_or("no message"),
                    tree,
                    parents)
            .expect("rewrite: can't commit")
    }

    pub fn push(&self, oid: Oid, module: &str, target: &str) -> String
    {
        let commit = &self.repo.find_commit(oid).expect("can't find commit");
        self.repo.set_head_detached(commit.id()).expect("can't detach HEAD");
        let cmd = format!("push {} HEAD:{}", self.host.remote_url(module), target);
        let output =
            self.call_git(&cmd) .expect("can't push");
        debug!("push: {}\n{}", cmd, output);
        format!("{}", output)
    }

    fn subtree(&self, tree: &Tree, path: &Path) -> Option<Tree>
    {
        if let Some(oid) = tree.get_path(path).map(|x| x.id()).ok() {
            return self.repo.find_tree(oid).ok();
        }
        else {
            return None;
        }
    }

    fn replace_child(&self, child: &Path, subtree: Oid, full_tree: Tree) -> Tree
    {
        let full_tree_id = {
            let mut builder = self.repo
                .treebuilder(Some(&full_tree))
                .expect("replace_child: can't create treebuilder");
            builder.insert(child, subtree, 0o0040000) // GIT_FILEMODE_TREE
                .expect("replace_child: can't insert tree");
            builder.write().expect("replace_child: can't write tree")
        };
        return self.repo.find_tree(full_tree_id).expect("replace_child: can't find new tree");
    }

    fn replace_subtree(&self, path: &Path, subtree: Oid, full_tree: Tree) -> Tree
    {
        if path.components().count() == 1 {
            return self.replace_child(path, subtree, full_tree);
        }
        else {
            let name = Path::new(path.file_name().expect("no module name"));
            let path = path.parent().expect("module not in subdir");

            let st = self.subtree(&full_tree, path).unwrap();
            let tree = self.replace_child(name, subtree, st);

            return self.replace_subtree(path, tree.id(), full_tree);
        }
    }

    fn split_subdir(&self, module: &str, newrev: Oid) -> Object
    {
        // TODO: implement using libgit
        let shell = Shell { cwd: self.repo.path().to_path_buf() };
        shell.command("rm -Rf refs/original");
        shell.command("rm -Rf .git-rewrite");

        self.repo.set_head_detached(newrev).expect("can't detatch head");;

        self.call_git(&format!("filter-branch --subdirectory-filter {}/ -- HEAD", module))
            .expect("error in filter-branch");

        return self.repo
            .revparse_single("HEAD")
            .expect("can't find rewritten branch");
    }
}

pub enum ReviewUploadResult
{
    Uploaded(Oid),
    RejectNoFF,
    RejectMerge,
    NoChanges,
    Central,
}

pub fn review_upload(scratch: &Scratch, newrev: Object, module: &str) -> ReviewUploadResult
{
    debug!(".\n\n==== Doing review upload for module {}", &module);

    let new = newrev.id();
    let old = scratch.tracking(&module, "master").expect("no tracking branch 1").id();

    if old == new {
        return ReviewUploadResult::NoChanges;
    }

    match scratch.repo.graph_descendant_of(new, old) {
        Err(_) => return ReviewUploadResult::RejectNoFF,
        Ok(false) => return ReviewUploadResult::RejectNoFF,
        Ok(true) => (),
    }

    debug!("==== walking commits from {} to {}", old, new);

    let walk = {
        let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
        walk.set_sorting(SORT_REVERSE | SORT_TIME);
        let range = format!("{}..{}", old, new);
        walk.push_range(&range).expect(&format!("walk: invalid range: {}", range));;
        walk
    };

    let mut current =
        scratch.tracking(scratch.host.central(), "master").expect("no central tracking").id();

    for rev in walk {
        let rev = rev.expect("walk: invalid rev");
        if old == rev {
            continue;
        }

        debug!("==== walking commit {}", rev);

        let module_commit = scratch.repo
            .find_commit(rev)
            .expect("walk: object is not actually a commit");

        if module_commit.parents().count() > 1 {
            // TODO: also do this check on pushes to cenral refs/for/master
            // TODO: invectigate the possibility of allowing merge commits
            return ReviewUploadResult::RejectMerge;
        }

        if module != scratch.host.central() {
            debug!("==== Rewriting commit {}", rev);

            let tree = module_commit.tree().expect("walk: commit has no tree");
            let parent =
                scratch.repo.find_commit(current).expect("walk: current object is no commit");

            let new_tree = scratch.replace_subtree(Path::new(module),
                                                   tree.id(),
                                                   parent.tree()
                                                       .expect("walk: parent has no tree"));

            current = scratch.rewrite(&module_commit, &vec![&parent], &new_tree);
        }
    }

    if module != scratch.host.central() {
        return ReviewUploadResult::Uploaded(current);
    }
    else {
        return ReviewUploadResult::Central;
    }
}

pub fn project_created(scratch: &Scratch)
{
    if let Some(rev) = scratch.tracking(scratch.host.central(), "master") {
        central_submit(scratch, rev);
    }
}

pub fn central_submit(scratch: &Scratch, newrev: Object)
{
    debug!(" ---> central_submit (sha1 of commit: {})", &newrev.id());

    let central_commit = newrev.as_commit().expect("could not get commit from obj");
    let central_tree = central_commit.tree().expect("commit has no tree");

    for module in scratch.host.projects() {
        if module == scratch.host.central() {
            continue;
        }
        debug!("");
        debug!("==== fetching tracking branch for module: {}", &module);
        let module_master_commit_obj = match scratch.tracking(&module, "master") {
            Some(obj) => obj,
            None => {
                debug!("====    no tracking branch for module {} => project does not exist or is \
                        empty",
                       &module);
                debug!("====    initializing with subdir history");
                let commit = scratch.split_subdir(&module, newrev.id());
                scratch.push(commit.id(), &module, "refs/heads/master");
                scratch.tracking(&module, "master")
                    .expect(&format!("no tracking branch for module: {}",module))
            }
        };

        let parents = vec![module_master_commit_obj.as_commit()
                               .expect("could not get commit from obj")];

        debug!("==== checking for changes in module: {:?}", module);

        // new tree is sub-tree of complete central tree
        let old_tree_id = if let Ok(tree) = parents[0].tree() {
            tree.id()
        }
        else {
            Oid::from_str("0000000000000000000000000000000000000000").unwrap()
        };

        let new_tree_id = if let Ok(tree_entry) = central_tree.get_path(&Path::new(&module)) {
            tree_entry.id()
        }
        else {
            Oid::from_str("0000000000000000000000000000000000000000").unwrap()
        };

        // if sha1's are equal the content is equal
        if new_tree_id != old_tree_id && !new_tree_id.is_zero() {
            let new_tree = scratch.repo.find_tree(new_tree_id).expect("central_submit: can't find tree");
            debug!("====    commit changes module => make commit on module");
            let module_commit = scratch.rewrite(central_commit, &parents, &new_tree);
            let output = scratch.push(module_commit, &module, "master");
            debug!("{}",output);
        }
        else {
            debug!("====    commit does not change module => skipping");
        }
    }
}

pub fn find_repos(root: &Path, path: &Path, mut repos: Vec<String>) -> Vec<String>
{
    if let Ok(children) = path.read_dir() {
        for child in children {
            let path = child.unwrap().path();

            let name = format!("{}", &path.to_str().unwrap());
            if let Some(last) = path.extension() {
                if last == "git" {
                    repos.push(name.trim_right_matches(".git")
                        .trim_left_matches(root.to_str().unwrap())
                        .trim_left_matches("/")
                        .to_string());
                    continue;
                }
            }
            repos = find_repos(root, &path, repos);
        }
    }
    return repos;
}

pub struct Shell
{
    pub cwd: PathBuf,
}

impl Shell
{
    pub fn command(&self, cmd: &str) -> String
    {
        debug!("Shell::command: {}", cmd);
        let output = Command::new("sh")
            .current_dir(&self.cwd)
            .arg("-c")
            .arg(&cmd)
            .output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

        return String::from_utf8(output.stdout).expect("failed to decode utf8").trim().to_string();
    }
}
<|endoftext|>


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

use nes::instruction::Instruction;
use nes::memory::Memory;
use std::fmt;

// Flag constants that allow easy bitwise getting and setting of flag values.
pub const CARRY_FLAG       : u8 = 0x1;
pub const ZERO_FLAG        : u8 = 0x2;
pub const INTERRUPT_DISABLE: u8 = 0x4;
pub const DECIMAL_MODE     : u8 = 0x8;
pub const BREAK_COMMAND    : u8 = 0x10;
pub const OVERFLOW_FLAG    : u8 = 0x40;
pub const NEGATIVE_FLAG    : u8 = 0x80;

/// This is an implementation of 2A03 processor used in the NES. The 2A03 is
/// based off the 6502 processor with some minor changes such as having no
/// binary-coded decimal mode. Currently only the NTSC variant of the chip is
/// planned to be implemented.
///
/// Much of the information and comments are due credit to www.obelisk.me.uk,
/// which has really good information about the 6502 processor. If you're
/// interested in diving further, I recommend you give that site a visit.
#[derive(Debug)]
pub struct CPU {
    // The program counter is a 16-bit register which points to the next
    // instruction to be executed. The value of program counter is modified
    // automatically as instructions are executed.
    //
    // The value of the program counter can be modified by executing a jump, a
    // relative branch, a subroutine call to another memory address, by
    // returning from a subroutine, or by an interrupt.
    pub pc: u16,

    // The processor supports a 256 byte stack located between $0100 and $01FF.
    // The stack pointer is an 8-bit register and holds the next free location
    // on the stack. The location of the stack is fixed and cannot be moved and
    // grows downwards.
    pub sp: u8,

    // The 8-bit accumulator is used all arithmetic and logical operations (with
    // the exception of increments and decrements). The contents of the
    // accumulator can be stored and retrieved either from memory or the stack.
    pub a: u8,

    // The 8-bit X register can be used to control information, compare values
    // in memory, and be incremented or decremented. The X register is special
    // as it can be used to get a copy of the stack pointer or change its value.
    pub x: u8,

    // The 8-bit Y register like X, can be used to manage information and be
    // incremented or decremented; however it doesn't have any special functions
    // like the X register does.
    pub y: u8,

    // The Processor Status register contains a list of flags that are set and
    // cleared by instructions to record the results of operations. Each flag
    // has a special bit within the register (8 bits).  Instructions exist to
    // set, clear, and read the various flags. One even allows pushing or
    // pulling the flags to the stack.
    //
    // Carry Flag:
    //
    // The carry flag is set if the last operation caused an overflow from bit 7
    // of the result or an underflow from bit 0. This condition is set during
    // arithmetic, comparison and during logical shifts. It can be explicitly
    // set using the 'Set Carry Flag' (SEC) instruction and cleared with 'Clear
    // Carry Flag' (CLC).
    //
    // Zero Flag:
    //
    // The zero flag is set if the result of the last operation as was zero.
    //
    // Interrupt Disable:
    //
    // The interrupt disable flag is set if the program has executed a 'Set
    // Interrupt Disable' (SEI) instruction. While this flag is set the
    // processor will not respond to interrupts from devices until it is cleared
    // by a 'Clear Interrupt Disable' (CLI) instruction.
    //
    // Decimal Mode: (UNUSED in 2A03)
    //
    // While the decimal mode flag is set the processor will obey the rules of
    // Binary Coded Decimal (BCD) arithmetic during addition and subtraction.
    // The flag can be explicitly set using 'Set Decimal Flag' (SED) and cleared
    // with 'Clear Decimal Flag' (CLD).
    //
    // Break Command:
    //
    // The break command bit is set when a BRK instruction has been executed and
    // an interrupt has been generated to process it.
    //
    // Overflow Flag:
    //
    // The overflow flag is set during arithmetic operations if the result has
    // yielded an invalid 2's complement result (e.g. adding to positive numbers
    // and ending up with a negative result: 64 + 64 => -128). It is determined
    // by looking at the carry between bits 6 and 7 and between bit 7 and the
    // carry flag.
    //
    // Negative Flag:
    //
    // The negative flag is set if the result of the last operation had bit 7
    // set to a one.
    pub p: u8,

    // The amount of cycles currently accumulated. A cycle represents a unit of
    // time (the time it takes for the CPU clock to fire). Different
    // instructions take a different amount of cycles to complete depending on
    // their complexity.
    pub cycles: u16
}

impl CPU {
    pub fn new() -> CPU {
        CPU {
            pc: 0xC000,
            sp: 0xFD,
            a: 0,
            x: 0,
            y: 0,
            p: 0x24,
            cycles: 0
        }
    }

    /// Sets the carry flag in the status register.
    #[inline(always)]
    pub fn set_carry_flag(&mut self) {
        self.p |= CARRY_FLAG;
    }

    /// Sets the zero flag in the status register.
    #[inline(always)]
    pub fn set_zero_flag(&mut self) {
        self.p |= ZERO_FLAG;
    }

    /// Sets the interrupt disable flag in the status register.
    #[inline(always)]
    pub fn set_interrupt_disable(&mut self) {
        self.p |= INTERRUPT_DISABLE;
    }

    /// Sets the decimal mode flag in the status register.
    /// NOTE: This flag is disabled in the 2A03 variation of the 6502.
    #[inline(always)]
    pub fn set_decimal_mode(&mut self) {
        self.p |= DECIMAL_MODE;
    }

    /// Sets the break command flag in the status register.
    #[inline(always)]
    pub fn set_break_command(&mut self) {
        self.p |= BREAK_COMMAND;
    }

    /// Sets the overflow flag in the status register.
    #[inline(always)]
    pub fn set_overflow_flag(&mut self) {
        self.p |= OVERFLOW_FLAG;
    }

    /// Sets the negative flag in the status register.
    #[inline(always)]
    pub fn set_negative_flag(&mut self) {
        self.p |= NEGATIVE_FLAG;
    }

    /// Sets the carry flag in the status register.
    #[inline(always)]
    pub fn carry_flag_set(&self) -> bool {
        self.p & CARRY_FLAG == CARRY_FLAG
    }

    /// Sets the zero flag in the status register.
    #[inline(always)]
    pub fn zero_flag_set(&self) -> bool {
        self.p & ZERO_FLAG == ZERO_FLAG
    }

    /// Sets the interrupt disable flag in the status register.
    #[inline(always)]
    pub fn interrupt_disable_set(&self) -> bool {
        self.p & INTERRUPT_DISABLE == INTERRUPT_DISABLE
    }

    /// Sets the decimal mode flag in the status register.
    /// NOTE: This flag is disabled in the 2A03 variation of the 6502.
    #[inline(always)]
    pub fn decimal_mode_set(&self) -> bool {
        self.p & DECIMAL_MODE == DECIMAL_MODE
    }

    /// Sets the break command flag in the status register.
    #[inline(always)]
    pub fn break_command_set(&self) -> bool {
        self.p & BREAK_COMMAND == BREAK_COMMAND
    }

    /// Sets the overflow flag in the status register.
    #[inline(always)]
    pub fn overflow_flag_set(&self) -> bool {
        self.p & OVERFLOW_FLAG == OVERFLOW_FLAG
    }

    /// Sets the negative flag in the status register.
    #[inline(always)]
    pub fn negative_flag_set(&self) -> bool {
        self.p & NEGATIVE_FLAG == NEGATIVE_FLAG
    }

    /// Parse an instruction from memory at the address the program counter
    /// currently points execute it. All instruction logic is in instruction.rs.
    pub fn execute(&mut self, memory: &mut Memory) {
        // NOTE: At this time, some parsing logic is done twice for the sake of
        // code simplicity. In the future I may rework the function arguments to
        // reuse as much data as possible since this is high-performance code.
        let instr = Instruction::parse(self.pc as usize, memory);
        instr.log(self);
        instr.execute(self, memory);
    }

    fn fmt_flag(&self, flag: bool) -> &'static str {
        if flag { "SET" } else { "UNSET" }
    }
}

impl fmt::Display for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "\nCPU Crash State:").unwrap();
        writeln!(f, "    Program Counter: {:#X}", self.pc).unwrap();
        writeln!(f, "    Stack Pointer:   {:#X}", self.sp).unwrap();
        writeln!(f, "    Accumulator:     {:#X}", self.a).unwrap();
        writeln!(f, "    X Register:      {:#X}", self.x).unwrap();
        writeln!(f, "    Y Register:      {:#X}", self.y).unwrap();
        writeln!(f, "").unwrap();
        writeln!(f, "Status Register: {:#X}", self.p).unwrap();
        writeln!(f, "    Carry Flag:        {}", self.fmt_flag(self.carry_flag_set())).unwrap();
        writeln!(f, "    Zero Flag:         {}", self.fmt_flag(self.zero_flag_set())).unwrap();
        writeln!(f, "    Interrupt Disable: {}", self.fmt_flag(self.interrupt_disable_set())).unwrap();
        writeln!(f, "    Decimal Mode:      {}", self.fmt_flag(self.decimal_mode_set())).unwrap();
        writeln!(f, "    Break Command:     {}", self.fmt_flag(self.break_command_set())).unwrap();
        writeln!(f, "    Overflow Flag:     {}", self.fmt_flag(self.overflow_flag_set())).unwrap();
        writeln!(f, "    Negative Flag:     {}", self.fmt_flag(self.negative_flag_set()))
    }
}
<commit_msg>Added flag unsetting methods<commit_after>// Copyright 2016 Walter Kuppens.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use nes::instruction::Instruction;
use nes::memory::Memory;
use std::fmt;

// Flag constants that allow easy bitwise getting and setting of flag values.
pub const CARRY_FLAG       : u8 = 0x1;
pub const ZERO_FLAG        : u8 = 0x2;
pub const INTERRUPT_DISABLE: u8 = 0x4;
pub const DECIMAL_MODE     : u8 = 0x8;
pub const BREAK_COMMAND    : u8 = 0x10;
pub const OVERFLOW_FLAG    : u8 = 0x40;
pub const NEGATIVE_FLAG    : u8 = 0x80;

/// This is an implementation of 2A03 processor used in the NES. The 2A03 is
/// based off the 6502 processor with some minor changes such as having no
/// binary-coded decimal mode. Currently only the NTSC variant of the chip is
/// planned to be implemented.
///
/// Much of the information and comments are due credit to www.obelisk.me.uk,
/// which has really good information about the 6502 processor. If you're
/// interested in diving further, I recommend you give that site a visit.
#[derive(Debug)]
pub struct CPU {
    // The program counter is a 16-bit register which points to the next
    // instruction to be executed. The value of program counter is modified
    // automatically as instructions are executed.
    //
    // The value of the program counter can be modified by executing a jump, a
    // relative branch, a subroutine call to another memory address, by
    // returning from a subroutine, or by an interrupt.
    pub pc: u16,

    // The processor supports a 256 byte stack located between $0100 and $01FF.
    // The stack pointer is an 8-bit register and holds the next free location
    // on the stack. The location of the stack is fixed and cannot be moved and
    // grows downwards.
    pub sp: u8,

    // The 8-bit accumulator is used all arithmetic and logical operations (with
    // the exception of increments and decrements). The contents of the
    // accumulator can be stored and retrieved either from memory or the stack.
    pub a: u8,

    // The 8-bit X register can be used to control information, compare values
    // in memory, and be incremented or decremented. The X register is special
    // as it can be used to get a copy of the stack pointer or change its value.
    pub x: u8,

    // The 8-bit Y register like X, can be used to manage information and be
    // incremented or decremented; however it doesn't have any special functions
    // like the X register does.
    pub y: u8,

    // The Processor Status register contains a list of flags that are set and
    // cleared by instructions to record the results of operations. Each flag
    // has a special bit within the register (8 bits).  Instructions exist to
    // set, clear, and read the various flags. One even allows pushing or
    // pulling the flags to the stack.
    //
    // Carry Flag:
    //
    // The carry flag is set if the last operation caused an overflow from bit 7
    // of the result or an underflow from bit 0. This condition is set during
    // arithmetic, comparison and during logical shifts. It can be explicitly
    // set using the 'Set Carry Flag' (SEC) instruction and cleared with 'Clear
    // Carry Flag' (CLC).
    //
    // Zero Flag:
    //
    // The zero flag is set if the result of the last operation as was zero.
    //
    // Interrupt Disable:
    //
    // The interrupt disable flag is set if the program has executed a 'Set
    // Interrupt Disable' (SEI) instruction. While this flag is set the
    // processor will not respond to interrupts from devices until it is cleared
    // by a 'Clear Interrupt Disable' (CLI) instruction.
    //
    // Decimal Mode: (UNUSED in 2A03)
    //
    // While the decimal mode flag is set the processor will obey the rules of
    // Binary Coded Decimal (BCD) arithmetic during addition and subtraction.
    // The flag can be explicitly set using 'Set Decimal Flag' (SED) and cleared
    // with 'Clear Decimal Flag' (CLD).
    //
    // Break Command:
    //
    // The break command bit is set when a BRK instruction has been executed and
    // an interrupt has been generated to process it.
    //
    // Overflow Flag:
    //
    // The overflow flag is set during arithmetic operations if the result has
    // yielded an invalid 2's complement result (e.g. adding to positive numbers
    // and ending up with a negative result: 64 + 64 => -128). It is determined
    // by looking at the carry between bits 6 and 7 and between bit 7 and the
    // carry flag.
    //
    // Negative Flag:
    //
    // The negative flag is set if the result of the last operation had bit 7
    // set to a one.
    pub p: u8,

    // The amount of cycles currently accumulated. A cycle represents a unit of
    // time (the time it takes for the CPU clock to fire). Different
    // instructions take a different amount of cycles to complete depending on
    // their complexity.
    pub cycles: u16
}

impl CPU {
    pub fn new() -> CPU {
        CPU {
            pc: 0xC000,
            sp: 0xFD,
            a: 0,
            x: 0,
            y: 0,
            p: 0x24,
            cycles: 0
        }
    }

    /// Sets the carry flag in the status register.
    #[inline(always)]
    pub fn set_carry_flag(&mut self) {
        self.p |= CARRY_FLAG;
    }

    /// Sets the zero flag in the status register.
    #[inline(always)]
    pub fn set_zero_flag(&mut self) {
        self.p |= ZERO_FLAG;
    }

    /// Sets the interrupt disable flag in the status register.
    #[inline(always)]
    pub fn set_interrupt_disable(&mut self) {
        self.p |= INTERRUPT_DISABLE;
    }

    /// Sets the decimal mode flag in the status register.
    /// NOTE: This flag is disabled in the 2A03 variation of the 6502.
    #[inline(always)]
    pub fn set_decimal_mode(&mut self) {
        self.p |= DECIMAL_MODE;
    }

    /// Sets the break command flag in the status register.
    #[inline(always)]
    pub fn set_break_command(&mut self) {
        self.p |= BREAK_COMMAND;
    }

    /// Sets the overflow flag in the status register.
    #[inline(always)]
    pub fn set_overflow_flag(&mut self) {
        self.p |= OVERFLOW_FLAG;
    }

    /// Sets the negative flag in the status register.
    #[inline(always)]
    pub fn set_negative_flag(&mut self) {
        self.p |= NEGATIVE_FLAG;
    }

    /// Unsets the carry flag in the status register.
    #[inline(always)]
    pub fn unset_carry_flag(&mut self) {
        self.p &= ~CARRY_FLAG;
    }

    /// Unsets the zero flag in the status register.
    #[inline(always)]
    pub fn unset_zero_flag(&mut self) {
        self.p &= ~ZERO_FLAG;
    }

    /// Unsets the interrupt disable flag in the status register.
    #[inline(always)]
    pub fn unset_interrupt_disable(&mut self) {
        self.p &= ~INTERRUPT_DISABLE;
    }

    /// Unsets the decimal mode flag in the status register.
    /// NOTE: This flag is disabled in the 2A03 variation of the 6502.
    #[inline(always)]
    pub fn unset_decimal_mode(&mut self) {
        self.p &= ~DECIMAL_MODE;
    }

    /// Unsets the break command flag in the status register.
    #[inline(always)]
    pub fn unset_break_command(&mut self) {
        self.p &= ~BREAK_COMMAND;
    }

    /// Unsets the overflow flag in the status register.
    #[inline(always)]
    pub fn unset_overflow_flag(&mut self) {
        self.p &= ~OVERFLOW_FLAG;
    }

    /// Unsets the negative flag in the status register.
    #[inline(always)]
    pub fn unset_negative_flag(&mut self) {
        self.p &= ~NEGATIVE_FLAG;
    }

    /// Sets the carry flag in the status register.
    #[inline(always)]
    pub fn carry_flag_set(&self) -> bool {
        self.p & CARRY_FLAG == CARRY_FLAG
    }

    /// Sets the zero flag in the status register.
    #[inline(always)]
    pub fn zero_flag_set(&self) -> bool {
        self.p & ZERO_FLAG == ZERO_FLAG
    }

    /// Sets the interrupt disable flag in the status register.
    #[inline(always)]
    pub fn interrupt_disable_set(&self) -> bool {
        self.p & INTERRUPT_DISABLE == INTERRUPT_DISABLE
    }

    /// Sets the decimal mode flag in the status register.
    /// NOTE: This flag is disabled in the 2A03 variation of the 6502.
    #[inline(always)]
    pub fn decimal_mode_set(&self) -> bool {
        self.p & DECIMAL_MODE == DECIMAL_MODE
    }

    /// Sets the break command flag in the status register.
    #[inline(always)]
    pub fn break_command_set(&self) -> bool {
        self.p & BREAK_COMMAND == BREAK_COMMAND
    }

    /// Sets the overflow flag in the status register.
    #[inline(always)]
    pub fn overflow_flag_set(&self) -> bool {
        self.p & OVERFLOW_FLAG == OVERFLOW_FLAG
    }

    /// Sets the negative flag in the status register.
    #[inline(always)]
    pub fn negative_flag_set(&self) -> bool {
        self.p & NEGATIVE_FLAG == NEGATIVE_FLAG
    }

    /// Parse an instruction from memory at the address the program counter
    /// currently points execute it. All instruction logic is in instruction.rs.
    pub fn execute(&mut self, memory: &mut Memory) {
        // NOTE: At this time, some parsing logic is done twice for the sake of
        // code simplicity. In the future I may rework the function arguments to
        // reuse as much data as possible since this is high-performance code.
        let instr = Instruction::parse(self.pc as usize, memory);
        instr.log(self);
        instr.execute(self, memory);
    }

    fn fmt_flag(&self, flag: bool) -> &'static str {
        if flag { "SET" } else { "UNSET" }
    }
}

impl fmt::Display for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "\nCPU Crash State:").unwrap();
        writeln!(f, "    Program Counter: {:#X}", self.pc).unwrap();
        writeln!(f, "    Stack Pointer:   {:#X}", self.sp).unwrap();
        writeln!(f, "    Accumulator:     {:#X}", self.a).unwrap();
        writeln!(f, "    X Register:      {:#X}", self.x).unwrap();
        writeln!(f, "    Y Register:      {:#X}", self.y).unwrap();
        writeln!(f, "").unwrap();
        writeln!(f, "Status Register: {:#X}", self.p).unwrap();
        writeln!(f, "    Carry Flag:        {}", self.fmt_flag(self.carry_flag_set())).unwrap();
        writeln!(f, "    Zero Flag:         {}", self.fmt_flag(self.zero_flag_set())).unwrap();
        writeln!(f, "    Interrupt Disable: {}", self.fmt_flag(self.interrupt_disable_set())).unwrap();
        writeln!(f, "    Decimal Mode:      {}", self.fmt_flag(self.decimal_mode_set())).unwrap();
        writeln!(f, "    Break Command:     {}", self.fmt_flag(self.break_command_set())).unwrap();
        writeln!(f, "    Overflow Flag:     {}", self.fmt_flag(self.overflow_flag_set())).unwrap();
        writeln!(f, "    Negative Flag:     {}", self.fmt_flag(self.negative_flag_set()))
    }
}
<|endoftext|>