<commit_before>/// Memory buffers for the benefit of `std::rt::io::net` which has slow read/write.

use std::rt::io::{Reader, Writer};
use std::cast::transmute_mut;
use std::cmp::min;
use std::ptr;

// 64KB chunks (moderately arbitrary)
static READ_BUF_SIZE: uint = 0x10000;
static WRITE_BUF_SIZE: uint = 0x10000;
// TODO: consider removing constants and giving a buffer size in the constructor

struct BufferedReader<'self, T> {
    wrapped: &'self mut T,
    buffer: [u8, ..READ_BUF_SIZE],
    // The current position in the buffer
    pos: uint,
    // The last valid position in the reader
    max: uint,
}

impl<'self, T: Reader> BufferedReader<'self, T> {
    pub fn new<'a>(reader: &'a mut T/*, buffer_size: uint*/) -> BufferedReader<'a, T> {
        BufferedReader {
            wrapped: reader,
            buffer: [0u8, ..READ_BUF_SIZE], //[0u8, ..buffer_size],
            pos: 0u,
            max: 0u,
        }
    }

    /// Poke a single byte back so it will be read next. For this to make sense, you must have just
    /// read that byte. If `self.pos` is 0 and `self.max` is not 0 (i.e. if the buffer is just
    /// filled
    /// Very great caution must be used in calling this as it will fail if `self.pos` is 0.
    pub fn poke_byte(&mut self, byte: u8) {
        match (self.pos, self.max) {
            (0, 0) => self.max = 1,
            (0, _) => fail!("poke called when buffer is full"),
            (_, _) => self.pos -= 1,
        }
        self.buffer[self.pos] = byte;
    }
}

impl<'self, T: Reader> Reader for ~BufferedReader<'self, T> {
    /// Read at most N bytes into `buf`, where N is the minimum of `buf.len()` and the buffer size.
    ///
    /// At present, this makes no attempt to fill its buffer proactively, instead waiting until you
    /// ask.
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        if self.pos == self.max {
            // Run out of buffered content, read some more
            match self.wrapped.read(self.buffer) {
                None => {
                    self.pos = 0;
                    self.max = 0;
                    return None
                },
                Some(i) => {
                    self.pos = 0;
                    self.max = i;
                },
            }
        }
        let size = min(self.max - self.pos, buf.len());
        unsafe {
            do buf.as_mut_buf |p_dst, _len_dst| {
                do self.buffer.as_imm_buf |p_src, _len_src| {
                    // Note that copy_memory works on bytes; good, u8 is byte-sized
                    ptr::copy_memory(p_dst, ptr::offset(p_src, self.pos), size)
                }
            }
        }
        self.pos += size;
        Some(size)
    }

    /// Return whether the Reader has reached the end of the stream AND exhausted its buffer.
    fn eof(&mut self) -> bool {
        self.pos == self.max && self.wrapped.eof()
    }
}

struct BufferedWriter<'self, T> {
    wrapped: &'self mut T,
    buffer: [u8, ..WRITE_BUF_SIZE],
    buflen: uint,

    /// Some things being written may not like flush() being called yet (e.g. explicitly fail!())
    /// The BufferedReader may need to be flushed for good control, but let it provide for such
    /// cases by not calling the wrapped object's flush method in turn.
    call_wrapped_flush: bool,
}

impl<'self, T: Writer> BufferedWriter<'self, T> {
    pub fn new<'a>(writer: &'a mut T, call_wrapped_flush: bool/*, buffer_size: uint*/)
    -> BufferedWriter<'a, T> {
        BufferedWriter {
            wrapped: writer,
            buffer: [0u8, ..WRITE_BUF_SIZE], //[0u8, ..buffer_size],
            buflen: 0u,
            call_wrapped_flush: call_wrapped_flush,
        }
    }
}

#[unsafe_destructor]
impl<'self, T: Writer> Drop for BufferedWriter<'self, T> {
    fn drop(&self) {
        // Clearly wouldn't be a good idea to finish without flushing!
        unsafe { transmute_mut(self) }.flush();
    }
}

impl<'self, T: Writer> Writer for BufferedWriter<'self, T> {
    fn write(&mut self, buf: &[u8]) {
        if buf.len() + self.buflen > self.buffer.len() {
            // This is the lazy approach which may involve two writes where it's really not
            // warranted. Maybe deal with that later.
            if self.buflen > 0 {
                self.wrapped.write(self.buffer.slice_to(self.buflen));
                self.buflen = 0;
            }
            self.wrapped.write(buf);
            self.buflen = 0;
        } else {
            // Safely copy buf onto the "end" of self.buffer
            unsafe {
                do buf.as_imm_buf |p_src, len_src| {
                    do self.buffer.as_mut_buf |p_dst, _len_dst| {
                        // Note that copy_memory works on bytes; good, u8 is byte-sized
                        ptr::copy_memory(ptr::mut_offset(p_dst, self.buflen), p_src, len_src)
                    }
                }
            }
            self.buflen += buf.len();
            if self.buflen == self.buffer.len() {
                self.wrapped.write(self.buffer);
                self.buflen = 0;
            }
        }
    }

    fn flush(&mut self) {
        if self.buflen > 0 {
            self.wrapped.write(self.buffer.slice_to(self.buflen));
            self.buflen = 0;
        }
        if self.call_wrapped_flush {
            self.wrapped.flush();
        }
    }
}
<commit_msg>Don't flush a BufferedWriter on drop for now (ICE).<commit_after>/// Memory buffers for the benefit of `std::rt::io::net` which has slow read/write.

use std::rt::io::{Reader, Writer};
use std::cast::transmute_mut;
use std::cmp::min;
use std::ptr;

// 64KB chunks (moderately arbitrary)
static READ_BUF_SIZE: uint = 0x10000;
static WRITE_BUF_SIZE: uint = 0x10000;
// TODO: consider removing constants and giving a buffer size in the constructor

struct BufferedReader<'self, T> {
    wrapped: &'self mut T,
    buffer: [u8, ..READ_BUF_SIZE],
    // The current position in the buffer
    pos: uint,
    // The last valid position in the reader
    max: uint,
}

impl<'self, T: Reader> BufferedReader<'self, T> {
    pub fn new<'a>(reader: &'a mut T/*, buffer_size: uint*/) -> BufferedReader<'a, T> {
        BufferedReader {
            wrapped: reader,
            buffer: [0u8, ..READ_BUF_SIZE], //[0u8, ..buffer_size],
            pos: 0u,
            max: 0u,
        }
    }

    /// Poke a single byte back so it will be read next. For this to make sense, you must have just
    /// read that byte. If `self.pos` is 0 and `self.max` is not 0 (i.e. if the buffer is just
    /// filled
    /// Very great caution must be used in calling this as it will fail if `self.pos` is 0.
    pub fn poke_byte(&mut self, byte: u8) {
        match (self.pos, self.max) {
            (0, 0) => self.max = 1,
            (0, _) => fail!("poke called when buffer is full"),
            (_, _) => self.pos -= 1,
        }
        self.buffer[self.pos] = byte;
    }
}

impl<'self, T: Reader> Reader for ~BufferedReader<'self, T> {
    /// Read at most N bytes into `buf`, where N is the minimum of `buf.len()` and the buffer size.
    ///
    /// At present, this makes no attempt to fill its buffer proactively, instead waiting until you
    /// ask.
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        if self.pos == self.max {
            // Run out of buffered content, read some more
            match self.wrapped.read(self.buffer) {
                None => {
                    self.pos = 0;
                    self.max = 0;
                    return None
                },
                Some(i) => {
                    self.pos = 0;
                    self.max = i;
                },
            }
        }
        let size = min(self.max - self.pos, buf.len());
        unsafe {
            do buf.as_mut_buf |p_dst, _len_dst| {
                do self.buffer.as_imm_buf |p_src, _len_src| {
                    // Note that copy_memory works on bytes; good, u8 is byte-sized
                    ptr::copy_memory(p_dst, ptr::offset(p_src, self.pos), size)
                }
            }
        }
        self.pos += size;
        Some(size)
    }

    /// Return whether the Reader has reached the end of the stream AND exhausted its buffer.
    fn eof(&mut self) -> bool {
        self.pos == self.max && self.wrapped.eof()
    }
}

struct BufferedWriter<'self, T> {
    wrapped: &'self mut T,
    buffer: [u8, ..WRITE_BUF_SIZE],
    buflen: uint,

    /// Some things being written may not like flush() being called yet (e.g. explicitly fail!())
    /// The BufferedReader may need to be flushed for good control, but let it provide for such
    /// cases by not calling the wrapped object's flush method in turn.
    call_wrapped_flush: bool,
}

impl<'self, T: Writer> BufferedWriter<'self, T> {
    pub fn new<'a>(writer: &'a mut T, call_wrapped_flush: bool/*, buffer_size: uint*/)
    -> BufferedWriter<'a, T> {
        BufferedWriter {
            wrapped: writer,
            buffer: [0u8, ..WRITE_BUF_SIZE], //[0u8, ..buffer_size],
            buflen: 0u,
            call_wrapped_flush: call_wrapped_flush,
        }
    }
}

#[unsafe_destructor]
impl<'self, T: Writer> Drop for BufferedWriter<'self, T> {
    fn drop(&self) {
        // Clearly wouldn't be a good idea to finish without flushing!

        // TODO: blocked on https://github.com/mozilla/rust/issues/8059
        //unsafe { transmute_mut(self) }.flush();
    }
}

impl<'self, T: Writer> Writer for BufferedWriter<'self, T> {
    fn write(&mut self, buf: &[u8]) {
        if buf.len() + self.buflen > self.buffer.len() {
            // This is the lazy approach which may involve two writes where it's really not
            // warranted. Maybe deal with that later.
            if self.buflen > 0 {
                self.wrapped.write(self.buffer.slice_to(self.buflen));
                self.buflen = 0;
            }
            self.wrapped.write(buf);
            self.buflen = 0;
        } else {
            // Safely copy buf onto the "end" of self.buffer
            unsafe {
                do buf.as_imm_buf |p_src, len_src| {
                    do self.buffer.as_mut_buf |p_dst, _len_dst| {
                        // Note that copy_memory works on bytes; good, u8 is byte-sized
                        ptr::copy_memory(ptr::mut_offset(p_dst, self.buflen), p_src, len_src)
                    }
                }
            }
            self.buflen += buf.len();
            if self.buflen == self.buffer.len() {
                self.wrapped.write(self.buffer);
                self.buflen = 0;
            }
        }
    }

    fn flush(&mut self) {
        if self.buflen > 0 {
            self.wrapped.write(self.buffer.slice_to(self.buflen));
            self.buflen = 0;
        }
        if self.call_wrapped_flush {
            self.wrapped.flush();
        }
    }
}
<|endoftext|>


<commit_before>#![feature(hash)]

#[macro_use]
extern crate objc;
#[macro_use]
extern crate objc_foundation;

use objc::{ClassDecl, Id};
use objc::runtime::Object;
use objc_foundation::{INSObject, NSObject};

object_struct!(MYObject);

impl MYObject {
    fn number(&self) -> u32 {
        let obj = unsafe {
            &*(self as *const _ as *const Object)
        };
        unsafe {
            *obj.get_ivar::<u32>("_number")
        }
    }

    fn set_number(&mut self, number: u32) {
        let obj = unsafe {
            &mut *(self as *mut _ as *mut Object)
        };
        unsafe {
            obj.set_ivar("_number", number);
        }
    }

    fn register() {
        let superclass = <NSObject as INSObject>::class();
        let mut decl = ClassDecl::new(superclass, "MYObject").unwrap();

        decl.add_ivar::<u32>("_number");
        decl.add_method(method!(
            (&mut MYObject)this, setNumber:(u32)number; {
                this.set_number(number);
            }
        ));
        decl.add_method(method!(
            (&MYObject)this, number -> u32, {
                this.number()
            }
        ));

        decl.register();
    }
}

fn main() {
    MYObject::register();
    let mut obj: Id<MYObject> = INSObject::new();
    println!("{:?}", obj);

    obj.set_number(7);
    println!("Number: {}", obj.number());

    unsafe {
        let _: () = msg_send![obj, setNumber:12u32];
    }
    println!("Number: {}", obj.number());
}
<commit_msg>Updated custom_class example.<commit_after>#[macro_use]
extern crate objc;
extern crate objc_foundation;

use std::sync::{Once, ONCE_INIT};

use objc::{ClassDecl, EncodePtr, Id, Message, MethodDecl};
use objc::runtime::{Class, Object, Sel};
use objc_foundation::{INSObject, NSObject};

pub enum MYObject { }

impl MYObject {
    fn number(&self) -> u32 {
        let obj = unsafe {
            &*(self as *const _ as *const Object)
        };
        unsafe {
            *obj.get_ivar::<u32>("_number")
        }
    }

    fn set_number(&mut self, number: u32) {
        let obj = unsafe {
            &mut *(self as *mut _ as *mut Object)
        };
        unsafe {
            obj.set_ivar("_number", number);
        }
    }
}

unsafe impl Message for MYObject { }

impl EncodePtr for MYObject {
    fn ptr_code() -> &'static str { "@" }
}

static MYOBJECT_REGISTER_CLASS: Once = ONCE_INIT;

impl INSObject for MYObject {
    fn class() -> &'static Class {
        MYOBJECT_REGISTER_CLASS.call_once(|| {
            let superclass = <NSObject as INSObject>::class();
            let mut decl = ClassDecl::new(superclass, "MYObject").unwrap();
            assert!(decl.add_ivar::<u32>("_number"));

            // Add ObjC methods for getting and setting the number
            extern fn my_object_set_number(this: &mut MYObject, _cmd: Sel, number: u32) {
                this.set_number(number);
            }
            let method = MethodDecl::new(sel!(setNumber:),
                my_object_set_number as extern fn(&mut MYObject, Sel, u32));
            assert!(decl.add_method(method.unwrap()));

            extern fn my_object_get_number(this: &MYObject, _cmd: Sel) -> u32 {
                this.number()
            }
            let method = MethodDecl::new(sel!(number),
                my_object_get_number as extern fn(&MYObject, Sel) -> u32);
            assert!(decl.add_method(method.unwrap()));

            decl.register();
        });

        Class::get("MYObject").unwrap()
    }
}

fn main() {
    let mut obj: Id<MYObject> = INSObject::new();

    obj.set_number(7);
    println!("Number: {}", unsafe {
        let number: u32 = msg_send![obj, number];
        number
    });

    unsafe {
        let _: () = msg_send![obj, setNumber:12u32];
    }
    println!("Number: {}", obj.number());
}
<|endoftext|>


<commit_before>use field::{Field, FieldHeight};

pub struct FieldWithHeight<F: Field> {
    field: F,
    height: [u16; 8],
}

impl<F: Field> FieldWithHeight<F> {
    pub fn new() -> FieldWithHeight<F> {
        FieldWithHeight::<F> {
            field: F::new(),
            height: [0; 8],
        }
    }
}

impl<F: Field> FieldHeight for FieldWithHeight<F> {
    #[inline]
    fn height(&self, x: usize) -> usize {
        self.height[x] as usize
    }
}
<commit_msg>Add field() and field_mut() to FieldWithHeight<commit_after>use field::{Field, FieldHeight};

pub struct FieldWithHeight<F: Field> {
    field: F,
    height: [u16; 8],
}

impl<F: Field> FieldWithHeight<F> {
    pub fn new() -> FieldWithHeight<F> {
        FieldWithHeight::<F> {
            field: F::new(),
            height: [0; 8],
        }
    }

    pub fn field(&self) -> &F {
        &self.field
    }

    pub fn field_mut(&mut self) -> &mut F {
        &mut self.field
    }
}

impl<F: Field> FieldHeight for FieldWithHeight<F> {
    #[inline]
    fn height(&self, x: usize) -> usize {
        self.height[x] as usize
    }
}
<|endoftext|>


<commit_before>use nom::{IResult};
use nom::{le_u32};

/// Public representation of a parsed block
struct Block<'a> {
    //  0                   1                   2                   3
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                          Block Type                           |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  /                          Block Body                           /
    //  /          /* variable length, aligned to 32 bits */            /
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    ty: u32,
    block_length: u32,
    body: &'a [u8],
    check_length: u32,
}

named!(block<&[u8],Block>,
       chain!(
           ty: le_u32 ~
           block_length: le_u32 ~
           body: take!((block_length - 12) as usize) ~
           check_length: le_u32 ,

           ||{ Block {
               ty: ty,
               block_length: block_length,
               body: body,
               check_length: check_length
           } }
           )
      );

#[test]
fn test_parse_block() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match block(input) {
        IResult::Done(left, Block { ty, block_length, body, check_length }) => {
            // Ignored because we do not currently parse the whole block
            assert_eq!(left, b"");
            assert_eq!(ty, 0x0A0D0D0A);
            assert_eq!(block_length, 28);
            assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
            assert_eq!(check_length, 28);
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}
<commit_msg>Parse several blocks<commit_after>use nom::{IResult};
use nom::{le_u32};

/// Public representation of a parsed block
struct Block<'a> {
    //  0                   1                   2                   3
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                          Block Type                           |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  /                          Block Body                           /
    //  /          /* variable length, aligned to 32 bits */            /
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    ty: u32,
    block_length: u32,
    body: &'a [u8],
    check_length: u32,
}

named!(block<&[u8],Block>,
       chain!(
           ty: le_u32 ~
           block_length: le_u32 ~
           body: take!((block_length - 12) as usize) ~
           check_length: le_u32 ,

           ||{ Block {
               ty: ty,
               block_length: block_length,
               body: body,
               check_length: check_length
           } }
           )
      );

named!(blocks< &[u8],Vec<Block> >,
       many1!(block)
       );

#[test]
fn test_parse_block() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match block(input) {
        IResult::Done(left, Block { ty, block_length, body, check_length }) => {
            // Ignored because we do not currently parse the whole block
            assert_eq!(left, b"");
            assert_eq!(ty, 0x0A0D0D0A);
            assert_eq!(block_length, 28);
            assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
            assert_eq!(check_length, 28);
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}

#[test]
fn test_parse_blocks() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00\
    \n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match blocks(input) {
        IResult::Done(left, blocks) => {
            assert_eq!(blocks.len(), 2);
            for i in blocks {
                let Block { ty, block_length, body, check_length } = i;
                // Ignored because we do not currently parse the whole block
                assert_eq!(left, b"");
                assert_eq!(ty, 0x0A0D0D0A);
                assert_eq!(block_length, 28);
                assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
                assert_eq!(check_length, 28);
            }
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}
<|endoftext|>


<commit_before>use schemars::JsonSchema;
use serde::Serialize;
use serde_with::skip_serializing_none;
use std::{
    collections::BTreeMap,
    path::{Path, PathBuf},
    time::UNIX_EPOCH,
};

/// # A file or directory within a `Project`
#[skip_serializing_none]
#[derive(Debug, Default, Clone, JsonSchema, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct File {
    /// The relative path of the file within the project folder
    pub path: String,

    /// Time that the file was last modified (seconds since Unix Epoch)
    pub modified: Option<u64>,

    /// Size of the file in bytes
    pub size: Option<u64>,

    /// The media type (aka MIME type) of the file
    pub media_type: Option<String>,

    /// The SHA1 hash of the contents of the file
    pub sha1: Option<String>,

    /// The parent `File`, if any
    pub parent: Option<PathBuf>,

    /// If a directory, a list of the canonical paths of the files within it.
    /// Otherwise, `None`.
    pub children: Option<Vec<PathBuf>>,
}

impl File {
    pub fn from_path(folder: &Path, path: &Path) -> (PathBuf, File) {
        let canonical_path = path.canonicalize().expect("Unable to canonicalize path");
        let relative_path = path
            .strip_prefix(folder)
            .expect("Unable to strip prefix")
            .display()
            .to_string();

        let (modified, size) = match path.metadata() {
            Ok(metadata) => {
                let modified = metadata
                    .modified()
                    .ok()
                    .and_then(|time| time.duration_since(UNIX_EPOCH).ok())
                    .and_then(|duration| Some(duration.as_secs()));
                let size = Some(metadata.len());
                (modified, size)
            }
            Err(_) => (None, None),
        };

        let (media_type, children) = if path.is_file() {
            let media_type = mime_guess::from_path(path)
                .first()
                .map(|mime| mime.essence_str().to_string());

            (media_type, None)
        } else {
            (None, Some(Vec::new()))
        };

        let file = File {
            path: relative_path,
            modified,
            size,
            media_type,
            children,
            ..Default::default()
        };

        (canonical_path, file)
    }
}

/// # The set of `File`s within a `Project`
#[derive(Debug, Default, Clone, JsonSchema, Serialize)]
#[serde(transparent)]
pub struct Files {
    pub files: BTreeMap<PathBuf, File>,
}

impl Files {
    pub fn from_path(path: &Path) -> Files {
        // Collect all the files
        let mut files = walkdir::WalkDir::new(path)
            .into_iter()
            .filter_map(|entry| {
                let entry = match entry.ok() {
                    Some(entry) => entry,
                    None => return None,
                };
                Some(File::from_path(path, entry.path()))
            })
            .into_iter()
            .collect::<BTreeMap<PathBuf, File>>();

        // Resolve `parent` and `children` properties
        // This needs to clone the files to avoid mutable borrow twice,
        // there may be a more efficient alternative
        let mut children: BTreeMap<PathBuf, Vec<PathBuf>> = BTreeMap::new();
        for (path, file) in &mut files {
            if let Some(parent_path) = path.parent() {
                let parent_path = parent_path.to_path_buf();
                file.parent = Some(parent_path.clone());
                children
                    .entry(parent_path)
                    .or_insert_with(Vec::new)
                    .push(path.clone());
            }
        }
        for (path, vec) in children {
            if let Some(parent) = files.get_mut(&path) {
                parent.children = Some(vec)
            }
        }

        Files { files }
    }
}
<commit_msg>feat(Files): Add format property and media type fallbacks<commit_after>use schemars::JsonSchema;
use serde::Serialize;
use serde_with::skip_serializing_none;
use std::{
    collections::BTreeMap,
    path::{Path, PathBuf},
    time::UNIX_EPOCH,
};

/// # A file or directory within a `Project`
#[skip_serializing_none]
#[derive(Debug, Default, Clone, JsonSchema, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct File {
    /// The relative path of the file within the project folder
    pub path: String,

    /// Time that the file was last modified (seconds since Unix Epoch)
    pub modified: Option<u64>,

    /// Size of the file in bytes
    pub size: Option<u64>,

    /// Format of the file
    ///
    /// Usually this is the lower cased filename extension (if any)
    /// but may also be normalized. May be more convenient,
    /// and usually more available, than the `media_type` property.
    pub format: Option<String>,

    /// The media type (aka MIME type) of the file
    pub media_type: Option<String>,

    /// The SHA1 hash of the contents of the file
    pub sha1: Option<String>,

    /// The parent `File`, if any
    pub parent: Option<PathBuf>,

    /// If a directory, a list of the canonical paths of the files within it.
    /// Otherwise, `None`.
    pub children: Option<Vec<PathBuf>>,
}

impl File {
    pub fn from_path(folder: &Path, path: &Path) -> (PathBuf, File) {
        let canonical_path = path.canonicalize().expect("Unable to canonicalize path");
        let relative_path = path
            .strip_prefix(folder)
            .expect("Unable to strip prefix")
            .display()
            .to_string();

        let (modified, size) = match path.metadata() {
            Ok(metadata) => {
                let modified = metadata
                    .modified()
                    .ok()
                    .and_then(|time| time.duration_since(UNIX_EPOCH).ok())
                    .and_then(|duration| Some(duration.as_secs()));
                let size = Some(metadata.len());
                (modified, size)
            }
            Err(_) => (None, None),
        };

        let format = path
            .extension()
            .map(|ext| ext.to_string_lossy().to_lowercase());

        let (media_type, children) = if path.is_file() {
            let media_type = if let Some(ext) = &format {
                mime_guess::from_ext(&ext)
                    .first()
                    .map(|mime| mime.essence_str().to_string())
                    .or_else(|| match ext.as_str() {
                        // Add MIME types that are not registered
                        // See https://github.com/jupyter/jupyter/issues/68
                        "ipynb" => Some("application/ipynb+json".to_string()),
                        _ => None,
                    })
            } else {
                None
            };

            (media_type, None)
        } else {
            (None, Some(Vec::new()))
        };

        let file = File {
            path: relative_path,
            modified,
            size,
            format,
            media_type,
            children,
            ..Default::default()
        };

        (canonical_path, file)
    }
}

/// # The set of `File`s within a `Project`
#[derive(Debug, Default, Clone, JsonSchema, Serialize)]
#[serde(transparent)]
pub struct Files {
    pub files: BTreeMap<PathBuf, File>,
}

impl Files {
    pub fn from_path(path: &Path) -> Files {
        // Collect all the files
        let mut files = walkdir::WalkDir::new(path)
            .into_iter()
            .filter_map(|entry| {
                let entry = match entry.ok() {
                    Some(entry) => entry,
                    None => return None,
                };
                Some(File::from_path(path, entry.path()))
            })
            .into_iter()
            .collect::<BTreeMap<PathBuf, File>>();

        // Resolve `parent` and `children` properties
        // This needs to clone the files to avoid mutable borrow twice,
        // there may be a more efficient alternative
        let mut children: BTreeMap<PathBuf, Vec<PathBuf>> = BTreeMap::new();
        for (path, file) in &mut files {
            if let Some(parent_path) = path.parent() {
                let parent_path = parent_path.to_path_buf();
                file.parent = Some(parent_path.clone());
                children
                    .entry(parent_path)
                    .or_insert_with(Vec::new)
                    .push(path.clone());
            }
        }
        for (path, vec) in children {
            if let Some(parent) = files.get_mut(&path) {
                parent.children = Some(vec)
            }
        }

        Files { files }
    }
}
<|endoftext|>


<commit_before>use crate::{Command, Merge};
#[cfg(feature = "display")]
use std::fmt;
use std::{
    iter::{FromIterator, IntoIterator},
    vec::IntoIter,
};

/// A chain of merged commands.
///
/// Commands in a chain are all executed in the order they was merged in.
///
/// # Examples
///
/// ```
/// # use undo::*;
/// # struct Add(char);
/// # impl Command<String> for Add {
/// #     fn apply(&mut self, s: &mut String) -> undo::Result {
/// #         s.push(self.0);
/// #         Ok(())
/// #     }
/// #     fn undo(&mut self, s: &mut String) -> undo::Result {
/// #         self.0 = s.pop().ok_or("`s` is empty")?;
/// #         Ok(())
/// #     }
/// # }
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let chain = Chain::with_capacity(2)
///     .join(Add('a'))
///     .join(Add('b'));
/// record.apply(chain)?;
/// assert_eq!(record.as_receiver(), "ab");
/// record.undo().unwrap()?;
/// assert_eq!(record.as_receiver(), "");
/// record.redo().unwrap()?;
/// assert_eq!(record.as_receiver(), "ab");
/// # Ok(())
/// # }
/// ```
pub struct Chain<R> {
    commands: Vec<Box<dyn Command<R>>>,
    merge: Option<Merge>,
    #[cfg(feature = "display")]
    text: Option<String>,
}

impl<R> Chain<R> {
    /// Returns an empty command.
    #[inline]
    pub fn new() -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Creates a new command with the provided text.
    #[inline]
    #[cfg(feature = "display")]
    pub fn with_text(text: impl Into<String>) -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: Some(text.into()),
        }
    }

    /// Returns an empty command with the specified capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Chain<R> {
        Chain {
            commands: Vec::with_capacity(capacity),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Reserves capacity for at least `additional` more commands in the chain.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.commands.reserve(additional);
    }

    /// Returns the capacity of the chain.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.commands.capacity()
    }

    /// Returns the amount of commands in the chain.
    #[inline]
    pub fn len(&self) -> usize {
        self.commands.len()
    }

    /// Returns `true` if no commands have been merged.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.commands.is_empty()
    }

    /// Merges the command with the chain.
    #[inline]
    pub fn push(&mut self, command: impl Command<R> + 'static) {
        self.commands.push(Box::new(command));
    }

    /// Merges the command with the chain and returns the chain.
    #[inline]
    pub fn join(mut self, command: impl Command<R> + 'static) -> Chain<R> {
        self.push(command);
        self
    }

    /// Sets the merge behavior of the chain.
    ///
    /// By default the merge behavior of the first command in the chain is used,
    /// and it always merges if the chain is empty.
    #[inline]
    pub fn set_merge(&mut self, merge: Merge) {
        self.merge = Some(merge);
    }

    /// Returns the text for the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn text(&self) -> Option<&str> {
        self.text.as_ref().map(String::as_str)
    }

    /// Sets the text for the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn set_text(&mut self, text: impl Into<String>) {
        self.text = Some(text.into());
    }
}

impl<R> Command<R> for Chain<R> {
    #[inline]
    fn apply(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.apply(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> crate::Result {
        for command in self.commands.iter_mut().rev() {
            command.undo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn redo(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.redo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn merge(&self) -> Merge {
        self.merge
            .or_else(|| self.commands.first().map(Command::merge))
            .unwrap_or(Merge::Yes)
    }

    #[inline]
    fn is_dead(&self) -> bool {
        self.commands.iter().any(Command::is_dead)
    }
}

impl<R> Default for Chain<R> {
    #[inline]
    fn default() -> Self {
        Chain::new()
    }
}

impl<R, C: Command<R> + 'static> FromIterator<C> for Chain<R> {
    #[inline]
    fn from_iter<T: IntoIterator<Item = C>>(commands: T) -> Self {
        Chain {
            commands: commands.into_iter().map(|c| Box::new(c) as _).collect(),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }
}

impl<R> IntoIterator for Chain<R> {
    type Item = Box<dyn Command<R>>;
    type IntoIter = IntoIter<Self::Item>;

    #[inline]
    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.commands.into_iter()
    }
}

impl<R, C: Command<R> + 'static> Extend<C> for Chain<R> {
    #[inline]
    fn extend<T: IntoIterator<Item = C>>(&mut self, iter: T) {
        self.commands
            .extend(iter.into_iter().map(|c| Box::new(c) as _));
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Debug for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Chain")
            .field("commands", &self.commands)
            .field("merge", &self.merge)
            .field("text", &self.text)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.text {
            Some(text) => f.write_str(text),
            None => {
                for command in &self.commands {
                    writeln!(f, "- {}", command)?;
                }
                Ok(())
            }
        }
    }
}
<commit_msg>Update documentation<commit_after>use crate::{Command, Merge};
#[cfg(feature = "display")]
use std::fmt;
use std::{
    iter::{FromIterator, IntoIterator},
    vec::IntoIter,
};

/// A chain of merged commands.
///
/// Commands in a chain are all executed in the order they was merged in.
///
/// # Examples
///
/// ```
/// # use undo::*;
/// # struct Add(char);
/// # impl Command<String> for Add {
/// #     fn apply(&mut self, s: &mut String) -> undo::Result {
/// #         s.push(self.0);
/// #         Ok(())
/// #     }
/// #     fn undo(&mut self, s: &mut String) -> undo::Result {
/// #         self.0 = s.pop().ok_or("`s` is empty")?;
/// #         Ok(())
/// #     }
/// # }
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let chain = Chain::with_capacity(2)
///     .join(Add('a'))
///     .join(Add('b'));
/// record.apply(chain)?;
/// assert_eq!(record.as_receiver(), "ab");
/// record.undo().unwrap()?;
/// assert_eq!(record.as_receiver(), "");
/// record.redo().unwrap()?;
/// assert_eq!(record.as_receiver(), "ab");
/// # Ok(())
/// # }
/// ```
pub struct Chain<R> {
    commands: Vec<Box<dyn Command<R>>>,
    merge: Option<Merge>,
    #[cfg(feature = "display")]
    text: Option<String>,
}

impl<R> Chain<R> {
    /// Returns an empty command.
    #[inline]
    pub fn new() -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Returns an empty command with the specified display text.
    #[inline]
    #[cfg(feature = "display")]
    pub fn with_text(text: impl Into<String>) -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: Some(text.into()),
        }
    }

    /// Returns an empty command with the specified capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Chain<R> {
        Chain {
            commands: Vec::with_capacity(capacity),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Reserves capacity for at least `additional` more commands in the chain.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.commands.reserve(additional);
    }

    /// Returns the capacity of the chain.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.commands.capacity()
    }

    /// Returns the amount of commands in the chain.
    #[inline]
    pub fn len(&self) -> usize {
        self.commands.len()
    }

    /// Returns `true` if no commands have been merged.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.commands.is_empty()
    }

    /// Merges the command with the chain.
    #[inline]
    pub fn push(&mut self, command: impl Command<R> + 'static) {
        self.commands.push(Box::new(command));
    }

    /// Merges the command with the chain and returns the chain.
    #[inline]
    pub fn join(mut self, command: impl Command<R> + 'static) -> Chain<R> {
        self.push(command);
        self
    }

    /// Sets the merge behavior of the chain.
    ///
    /// By default the merge behavior of the first command in the chain is used,
    /// and it merges if the chain is empty.
    #[inline]
    pub fn set_merge(&mut self, merge: Merge) {
        self.merge = Some(merge);
    }

    /// Sets the display text for the chain.
    ///
    /// By default the display text will be the display text for every command in the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn set_text(&mut self, text: impl Into<String>) {
        self.text = Some(text.into());
    }
}

impl<R> Command<R> for Chain<R> {
    #[inline]
    fn apply(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.apply(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> crate::Result {
        for command in self.commands.iter_mut().rev() {
            command.undo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn redo(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.redo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn merge(&self) -> Merge {
        self.merge
            .or_else(|| self.commands.first().map(Command::merge))
            .unwrap_or(Merge::Yes)
    }

    #[inline]
    fn is_dead(&self) -> bool {
        self.commands.iter().any(Command::is_dead)
    }
}

impl<R> Default for Chain<R> {
    #[inline]
    fn default() -> Self {
        Chain::new()
    }
}

impl<R, C: Command<R> + 'static> FromIterator<C> for Chain<R> {
    #[inline]
    fn from_iter<T: IntoIterator<Item = C>>(commands: T) -> Self {
        Chain {
            commands: commands.into_iter().map(|c| Box::new(c) as _).collect(),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }
}

impl<R> IntoIterator for Chain<R> {
    type Item = Box<dyn Command<R>>;
    type IntoIter = IntoIter<Self::Item>;

    #[inline]
    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.commands.into_iter()
    }
}

impl<R, C: Command<R> + 'static> Extend<C> for Chain<R> {
    #[inline]
    fn extend<T: IntoIterator<Item = C>>(&mut self, iter: T) {
        self.commands
            .extend(iter.into_iter().map(|c| Box::new(c) as _));
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Debug for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Chain")
            .field("commands", &self.commands)
            .field("merge", &self.merge)
            .field("text", &self.text)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.text {
            Some(text) => f.write_str(text),
            None => {
                for command in &self.commands {
                    writeln!(f, "- {}", command)?;
                }
                Ok(())
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::path::Path;
use std::fs::File;
use std::io::Read;
use std::fmt::{Debug, Formatter, Result as FmtResult};

use rand::{thread_rng, Rng};
use sdl2::Sdl;
use sdl2::rect::Rect;
use ep::FromPrimitive;

use screen::Screen;
use instruction::{Opcodes, Instruction};

const FONT_SET: [u8; 80] = [
    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, 0x80, // C
    0xe0, 0x90, 0x90, 0x90, 0xe0, // D
    0xf0, 0x80, 0xf0, 0x80, 0xf0, // E
    0xf0, 0x80, 0xf0, 0x80, 0x80, // F
];

pub struct Chip8<'a> {
    regs:   [u8; 16],
    i:      u16,
    dt:     u8,
    st:     u8,
    pc:     usize,

    inst:   Instruction,
    jmp:    bool,

    keys:   [u8; 16],
    mem:    [u8; 4096],
    stack:  Vec<usize>,
    screen: Screen<'a>,
}

impl<'a> Debug for Chip8<'a> {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        self.regs[..].fmt(f)
    }
}

impl<'a> Chip8<'a> {
    pub fn new(sdl: &Sdl) -> Chip8<'a> {
        Chip8 {
            regs:   [0; 16],
            i:      0,
            dt:     0,
            st:     0,
            pc:     0x200,
            inst:   Instruction::new(),
            jmp:    false,
            keys:   [0; 16],
            mem:    [0; 4096],
            stack:  vec![],
            screen: Screen::new(sdl),
        }
    }

    pub fn load_rom(&mut self, path: &str) {
        let mut rom: Vec<u8> = Vec::new();
        let mut file = File::open(Path::new(path)).unwrap();
        file.read_to_end(&mut rom).unwrap();
        for i in 0usize..rom.len() {
            self.mem[0x200 + i] = rom[i];
        }
        // TODO: move this
        for i in 0usize..FONT_SET.len() {
            self.mem[0x00 + i] = FONT_SET[i];
        }
    }

    pub fn run(&mut self) {
        let raw_data = (self.mem[self.pc], self.mem[self.pc +1]);
        self.inst.decode(raw_data);

        self.jmp  = false;

        println!("{:#x}: {:#x}", self.pc, self.inst.opcode);

        match Opcodes::from_u16(self.inst.opcode).unwrap() {
            Opcodes::CLS    => self.cls(),
            Opcodes::RET    => self.ret(),
            Opcodes::JMP    => self.jmp(),
            Opcodes::JMP_VA => self.jmp_va(),
            Opcodes::CALL   => self.call(),
            Opcodes::SE_VB  => self.se_vb(),
            Opcodes::SE_VV  => self.se_vv(),
            Opcodes::SNE_VB => self.sne_vb(),
            Opcodes::SNE_VV => self.sne_vv(),
            Opcodes::OR     => self.or(),
            Opcodes::ADD_VB => self.add_vb(),
            Opcodes::ADD_VV => self.add_vv(),
            Opcodes::ADD_IV => self.add_iv(),
            Opcodes::SUB    => self.sub(),
            Opcodes::XOR    => self.xor(),
            Opcodes::AND    => self.and(),
            Opcodes::LD_VB  => self.ld_vb(),
            Opcodes::LD_BV  => self.ld_bv(),
            Opcodes::LD_VV  => self.ld_vv(),
            Opcodes::LD_VI  => self.ld_vi(),
            Opcodes::LD_VK  => self.ld_vk(),
            Opcodes::LD_IV  => self.ld_iv(),
            Opcodes::LD_FV  => self.ld_fv(),
            Opcodes::LD_IA  => self.ld_ia(),
            Opcodes::LD_VDT => self.ld_vdt(),
            Opcodes::LD_DTV => self.ld_dtv(),
            Opcodes::LD_STV => self.ld_stv(),
            Opcodes::SKP    => self.skp(),
            Opcodes::SKNP   => self.sknp(),
            Opcodes::RND    => self.rnd(),
            Opcodes::SHR    => self.shr(),
            Opcodes::DRW    => self.drw(),
            _               => panic!("Unrecognized opcode: {:?}", self.inst.opcode),
        }

        if !self.jmp { self.inc_pc(); }

        if self.dt > 0 { self.dt -= 1; }
        if self.st > 0 { self.st -= 1; }
    }

    fn set_pc(&mut self, addr: u16) {
        self.pc = addr as usize;
    }

    fn inc_pc(&mut self) {
        self.pc += 2;
    }

    fn cls(&mut self) {
        self.screen.clear();
    }

    fn ret(&mut self) {
        let addr = self.stack.pop().unwrap();
        self.set_pc(addr as u16);
    }

    fn jmp(&mut self) {
        let addr = self.inst.nnn;
        self.set_pc(addr);
        self.jmp = true;
    }

    fn jmp_va(&mut self) {
        let offset = self.regs[0] as u16;
        let addr = self.inst.nnn + offset;
        self.set_pc(addr);
        self.jmp = true;
    }

    fn call(&mut self) {
        let old_addr = self.pc;
        let cur_addr = self.inst.nnn;
        self.stack.push(old_addr);
        self.set_pc(cur_addr);
        self.jmp = true;
    }

    fn se_vb(&mut self) {
        let idx = self.inst.x;
        if self.regs[idx] == self.inst.kk {
            self.inc_pc();
        }
    }

    fn se_vv(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        if self.regs[idx_x] == self.regs[idx_y] {
            self.inc_pc();
        }
    }

    fn sne_vb(&mut self) {
        let idx = self.inst.x;
        if self.regs[idx] != self.inst.kk {
            self.inc_pc();
        }
    }

    fn sne_vv(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        if self.regs[idx_x] != self.regs[idx_y] {
            self.inc_pc();
        }
    }

    fn or(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] |= self.regs[idx_y]
    }

    fn and(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] &= self.regs[idx_y];
    }

    fn add_vb(&mut self) {
        let idx_x = self.inst.x;

        // TODO: I guess this shouldn't be this way
        let res = self.regs[idx_x]  as u16 + self.inst.kk as u16;

        if res > 0xFF {
            self.regs[idx_x] = (res & 0xFF) as u8;
        } else {
            self.regs[idx_x] += self.inst.kk;
        }
    }

    fn add_vv(&mut self) {
        let idx_x = self.inst.x;
        let x = self.regs[idx_x] as u16;
        let y = self.regs[self.inst.y] as u16;

        let res = x + y;
        if res > 0xFF {
            self.regs[15] = 1;
        } else {
            self.regs[15] = 0;
        }

        self.regs[idx_x] = res as u8;
    }

    fn add_iv(&mut self) {
        let idx = self.inst.x;
        let x   = self.regs[idx] as u16;
        self.regs[15] = if (self.i + x) > 0xFFF { 1 } else { 0 };
        self.i += x;
    }

    fn sub(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        let x = self.regs[idx_x];
        let y = self.regs[idx_y];

        self.regs[15] = if x > y { 1 } else { 0 };
        self.regs[idx_x] -= y;
    }

    fn xor(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] ^= self.regs[idx_y];
    }

    fn shr(&mut self) {
        let idx_x = self.inst.x;
        let vx    = self.regs[idx_x];
        if vx & 0x01 == 0 {
            self.regs[15] = 1;
        }
        self.regs[idx_x] = vx >> 1;
    }

    fn ld_vv(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] = self.regs[idx_y];
    }

    fn ld_vb(&mut self) {
        let idx = self.inst.x;
        self.regs[idx] = self.inst.kk;
    }

    fn ld_bv(&mut self) {
        let idx = self.inst.x;
        let mut vx  = self.regs[idx];
        let mut hundred = 100;

        for i in 0usize..3 {
            let bcd = vx / hundred;
            self.mem[self.i as usize + i] = bcd;
            vx -= bcd * hundred;
            hundred /= 10;
        }
    }

    fn ld_fv(&mut self) {
        let x = self.regs[self.inst.x];
        self.i = (x * 5) as u16;
    }

    fn ld_vi(&mut self) {
        let x = self.inst.x as usize;

        for i in 0usize..x {
            self.regs[i] = self.mem[self.i as usize + i];
        }
    }

    fn ld_iv(&mut self) {
        let x = self.inst.x as usize;

        for i in 0usize..x {
            self.mem[self.i as usize + i] = self.regs[i];
        }
    }

    fn ld_ia(&mut self) {
        self.i = self.inst.nnn;
    }

    fn ld_vk(&mut self) {
        let mut key_pressed = false;

        for i in 0..self.keys.len() {
            if self.keys[i] == 1 {
                self.regs[self.inst.x] = i as u8;
                key_pressed = true;
            }
        }

        if !key_pressed {
            self.dec_pc();
        }
    }

    fn ld_vdt(&mut self) {
        let idx = self.inst.x;
        self.regs[idx] = self.dt;
    }

    fn ld_dtv(&mut self) {
        let idx: usize = self.inst.x;
        self.dt = self.regs[idx];
    }

    fn ld_stv(&mut self) {
        let idx = self.inst.x;
        self.st = self.regs[idx];
    }

    fn rnd(&mut self) {
        let idx = self.inst.x;
        let byte = self.inst.kk;
        let n: u8 = thread_rng().gen_range(0,255);
        self.regs[idx] = n & byte;
    }

    fn drw(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        let (x, y) = (self.regs[idx_x] as usize, self.regs[idx_y] as usize);
        let n = self.inst.n as usize;

        self.screen.renderer.clear();
        self.regs[15] = 0;

        for i in 0..n {
            let px = self.mem[(self.i + i as u16) as usize];
            for j in 0..8 {
                if px & (0x80 >> j) != 0 {
                    if self.screen.buffer[(x+j + (y+i) * 64) as usize] == 1 {
                        self.regs[15] = 1;
                    }
                    self.screen.buffer[(x+j + (y+i) * 64) as usize] ^= 1;
                }
            }
        }

        for i in 0usize..320 {
            for j in 0usize..640 {
                if self.screen.buffer[(j/10)+(i/10)*64] == 1 {
                    self.screen.renderer.fill_rect(
                        Rect::new(j as i32, i as i32, 1, 1)
                        );
                }
            }
        }

        self.screen.draw();
    }

    fn skp(&mut self) {
        let x = self.regs[self.inst.x];
        if self.keys[x as usize] == 1{
            self.inc_pc();
        }
    }

    fn sknp(&mut self) {
        let x = self.regs[self.inst.x];
        if self.keys[x as usize] == 0 {
            self.inc_pc();
        }
    }
    pub fn reset_keys(&mut self) {
        self.keys = [0;16];
    }

    pub fn press(&mut self, key: u8) {
        self.keys[key as usize] = 1;
    }
}
<commit_msg>added dec_pc function<commit_after>#![allow(dead_code)]

use std::path::Path;
use std::fs::File;
use std::io::Read;
use std::fmt::{Debug, Formatter, Result as FmtResult};

use rand::{thread_rng, Rng};
use sdl2::Sdl;
use sdl2::rect::Rect;
use ep::FromPrimitive;

use screen::Screen;
use instruction::{Opcodes, Instruction};

const FONT_SET: [u8; 80] = [
    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, 0x80, // C
    0xe0, 0x90, 0x90, 0x90, 0xe0, // D
    0xf0, 0x80, 0xf0, 0x80, 0xf0, // E
    0xf0, 0x80, 0xf0, 0x80, 0x80, // F
];

pub struct Chip8<'a> {
    regs:   [u8; 16],
    i:      u16,
    dt:     u8,
    st:     u8,
    pc:     usize,

    inst:   Instruction,
    jmp:    bool,

    keys:   [u8; 16],
    mem:    [u8; 4096],
    stack:  Vec<usize>,
    screen: Screen<'a>,
}

impl<'a> Debug for Chip8<'a> {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        self.regs[..].fmt(f)
    }
}

impl<'a> Chip8<'a> {
    pub fn new(sdl: &Sdl) -> Chip8<'a> {
        Chip8 {
            regs:   [0; 16],
            i:      0,
            dt:     0,
            st:     0,
            pc:     0x200,
            inst:   Instruction::new(),
            jmp:    false,
            keys:   [0; 16],
            mem:    [0; 4096],
            stack:  vec![],
            screen: Screen::new(sdl),
        }
    }

    pub fn load_rom(&mut self, path: &str) {
        let mut rom: Vec<u8> = Vec::new();
        let mut file = File::open(Path::new(path)).unwrap();
        file.read_to_end(&mut rom).unwrap();
        for i in 0usize..rom.len() {
            self.mem[0x200 + i] = rom[i];
        }
        // TODO: move this
        for i in 0usize..FONT_SET.len() {
            self.mem[0x00 + i] = FONT_SET[i];
        }
    }

    pub fn run(&mut self) {
        let raw_data = (self.mem[self.pc], self.mem[self.pc +1]);
        self.inst.decode(raw_data);

        self.jmp  = false;

        println!("{:#x}: {:#x}", self.pc, self.inst.opcode);

        match Opcodes::from_u16(self.inst.opcode).unwrap() {
            Opcodes::CLS    => self.cls(),
            Opcodes::RET    => self.ret(),
            Opcodes::JMP    => self.jmp(),
            Opcodes::JMP_VA => self.jmp_va(),
            Opcodes::CALL   => self.call(),
            Opcodes::SE_VB  => self.se_vb(),
            Opcodes::SE_VV  => self.se_vv(),
            Opcodes::SNE_VB => self.sne_vb(),
            Opcodes::SNE_VV => self.sne_vv(),
            Opcodes::OR     => self.or(),
            Opcodes::ADD_VB => self.add_vb(),
            Opcodes::ADD_VV => self.add_vv(),
            Opcodes::ADD_IV => self.add_iv(),
            Opcodes::SUB    => self.sub(),
            Opcodes::XOR    => self.xor(),
            Opcodes::AND    => self.and(),
            Opcodes::LD_VB  => self.ld_vb(),
            Opcodes::LD_BV  => self.ld_bv(),
            Opcodes::LD_VV  => self.ld_vv(),
            Opcodes::LD_VI  => self.ld_vi(),
            Opcodes::LD_VK  => self.ld_vk(),
            Opcodes::LD_IV  => self.ld_iv(),
            Opcodes::LD_FV  => self.ld_fv(),
            Opcodes::LD_IA  => self.ld_ia(),
            Opcodes::LD_VDT => self.ld_vdt(),
            Opcodes::LD_DTV => self.ld_dtv(),
            Opcodes::LD_STV => self.ld_stv(),
            Opcodes::SKP    => self.skp(),
            Opcodes::SKNP   => self.sknp(),
            Opcodes::RND    => self.rnd(),
            Opcodes::SHR    => self.shr(),
            Opcodes::DRW    => self.drw(),
            _               => panic!("Unrecognized opcode: {:?}", self.inst.opcode),
        }

        if !self.jmp { self.inc_pc(); }

        if self.dt > 0 { self.dt -= 1; }
        if self.st > 0 { self.st -= 1; }
    }

    fn set_pc(&mut self, addr: u16) {
        self.pc = addr as usize;
    }

    fn inc_pc(&mut self) {
        self.pc += 2;
    }

    fn dec_pc(&mut self) {
        self.pc -= 2;
    }

    fn cls(&mut self) {
        self.screen.clear();
    }

    fn ret(&mut self) {
        let addr = self.stack.pop().unwrap();
        self.set_pc(addr as u16);
    }

    fn jmp(&mut self) {
        let addr = self.inst.nnn;
        self.set_pc(addr);
        self.jmp = true;
    }

    fn jmp_va(&mut self) {
        let offset = self.regs[0] as u16;
        let addr = self.inst.nnn + offset;
        self.set_pc(addr);
        self.jmp = true;
    }

    fn call(&mut self) {
        let old_addr = self.pc;
        let cur_addr = self.inst.nnn;
        self.stack.push(old_addr);
        self.set_pc(cur_addr);
        self.jmp = true;
    }

    fn se_vb(&mut self) {
        let idx = self.inst.x;
        if self.regs[idx] == self.inst.kk {
            self.inc_pc();
        }
    }

    fn se_vv(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        if self.regs[idx_x] == self.regs[idx_y] {
            self.inc_pc();
        }
    }

    fn sne_vb(&mut self) {
        let idx = self.inst.x;
        if self.regs[idx] != self.inst.kk {
            self.inc_pc();
        }
    }

    fn sne_vv(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        if self.regs[idx_x] != self.regs[idx_y] {
            self.inc_pc();
        }
    }

    fn or(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] |= self.regs[idx_y]
    }

    fn and(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] &= self.regs[idx_y];
    }

    fn add_vb(&mut self) {
        let idx_x = self.inst.x;

        // TODO: I guess this shouldn't be this way
        let res = self.regs[idx_x]  as u16 + self.inst.kk as u16;

        if res > 0xFF {
            self.regs[idx_x] = (res & 0xFF) as u8;
        } else {
            self.regs[idx_x] += self.inst.kk;
        }
    }

    fn add_vv(&mut self) {
        let idx_x = self.inst.x;
        let x = self.regs[idx_x] as u16;
        let y = self.regs[self.inst.y] as u16;

        let res = x + y;
        if res > 0xFF {
            self.regs[15] = 1;
        } else {
            self.regs[15] = 0;
        }

        self.regs[idx_x] = res as u8;
    }

    fn add_iv(&mut self) {
        let idx = self.inst.x;
        let x   = self.regs[idx] as u16;
        self.regs[15] = if (self.i + x) > 0xFFF { 1 } else { 0 };
        self.i += x;
    }

    fn sub(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        let x = self.regs[idx_x];
        let y = self.regs[idx_y];

        self.regs[15] = if x > y { 1 } else { 0 };
        self.regs[idx_x] -= y;
    }

    fn xor(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] ^= self.regs[idx_y];
    }

    fn shr(&mut self) {
        let idx_x = self.inst.x;
        let vx    = self.regs[idx_x];
        if vx & 0x01 == 0 {
            self.regs[15] = 1;
        }
        self.regs[idx_x] = vx >> 1;
    }

    fn ld_vv(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        self.regs[idx_x] = self.regs[idx_y];
    }

    fn ld_vb(&mut self) {
        let idx = self.inst.x;
        self.regs[idx] = self.inst.kk;
    }

    fn ld_bv(&mut self) {
        let idx = self.inst.x;
        let mut vx  = self.regs[idx];
        let mut hundred = 100;

        for i in 0usize..3 {
            let bcd = vx / hundred;
            self.mem[self.i as usize + i] = bcd;
            vx -= bcd * hundred;
            hundred /= 10;
        }
    }

    fn ld_fv(&mut self) {
        let x = self.regs[self.inst.x];
        self.i = (x * 5) as u16;
    }

    fn ld_vi(&mut self) {
        let x = self.inst.x as usize;

        for i in 0usize..x {
            self.regs[i] = self.mem[self.i as usize + i];
        }
    }

    fn ld_iv(&mut self) {
        let x = self.inst.x as usize;

        for i in 0usize..x {
            self.mem[self.i as usize + i] = self.regs[i];
        }
    }

    fn ld_ia(&mut self) {
        self.i = self.inst.nnn;
    }

    fn ld_vk(&mut self) {
        let mut key_pressed = false;

        for i in 0..self.keys.len() {
            if self.keys[i] == 1 {
                self.regs[self.inst.x] = i as u8;
                key_pressed = true;
            }
        }

        if !key_pressed {
            self.dec_pc();
        }
    }

    fn ld_vdt(&mut self) {
        let idx = self.inst.x;
        self.regs[idx] = self.dt;
    }

    fn ld_dtv(&mut self) {
        let idx: usize = self.inst.x;
        self.dt = self.regs[idx];
    }

    fn ld_stv(&mut self) {
        let idx = self.inst.x;
        self.st = self.regs[idx];
    }

    fn rnd(&mut self) {
        let idx = self.inst.x;
        let byte = self.inst.kk;
        let n: u8 = thread_rng().gen_range(0,255);
        self.regs[idx] = n & byte;
    }

    fn drw(&mut self) {
        let idx_x = self.inst.x;
        let idx_y = self.inst.y;
        let (x, y) = (self.regs[idx_x] as usize, self.regs[idx_y] as usize);
        let n = self.inst.n as usize;

        self.screen.renderer.clear();
        self.regs[15] = 0;

        for i in 0..n {
            let px = self.mem[(self.i + i as u16) as usize];
            for j in 0..8 {
                if px & (0x80 >> j) != 0 {
                    if self.screen.buffer[(x+j + (y+i) * 64) as usize] == 1 {
                        self.regs[15] = 1;
                    }
                    self.screen.buffer[(x+j + (y+i) * 64) as usize] ^= 1;
                }
            }
        }

        for i in 0usize..320 {
            for j in 0usize..640 {
                if self.screen.buffer[(j/10)+(i/10)*64] == 1 {
                    self.screen.renderer.fill_rect(
                        Rect::new(j as i32, i as i32, 1, 1)
                        );
                }
            }
        }

        self.screen.draw();
    }

    fn skp(&mut self) {
        let x = self.regs[self.inst.x];
        if self.keys[x as usize] == 1{
            self.inc_pc();
        }
    }

    fn sknp(&mut self) {
        let x = self.regs[self.inst.x];
        if self.keys[x as usize] == 0 {
            self.inc_pc();
        }
    }
    pub fn reset_keys(&mut self) {
        self.keys = [0;16];
    }

    pub fn press(&mut self, key: u8) {
        self.keys[key as usize] = 1;
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(herbie_lint)]

#![allow(dead_code)]
#![deny(herbie)]

struct Foo { a: f64, b: f64 }

impl Foo {
    fn foo(self) {
        (self.a/self.a + self.a) * self.a;
        //~^ ERROR
        //~| HELP Try this
        //~| SUGGESTION (self.a * self.a) + self.a
    }

    #[herbie_ignore]
    fn bar(self) {
        (self.a/self.a + self.a) * self.a;
    }
}

fn get_f64() -> f64 {
    4.2
}

fn get_tup() -> (f64, f64) {
    (0., 0.)
}

fn get_struct() -> Foo {
    Foo { a: 0., b: 0. }
}

fn integers() {
    1;
    (1/2 + 3) * 2;
}

#[herbie_ignore]
fn attr_on_fn() {
    (0./0. + 0.) * 0.;

    fn foo() {
        (0./0. + 0.) * 0.;
        //~^ ERROR
        //~| HELP Try this
        //~| SUGGESTION (0. * 0.) + 0.
    }

    #[herbie_ignore]
    fn bar() {
        (0./0. + 0.) * 0.;
    }
}

fn main() {
    integers();

    let (a, b, c) = (0., 0., 0.);

    a*a + b*b;

    (a/a + a) * a;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a * a) + a
    (a/b + a) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a * b) + a
    (a/b + c) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (c * b) + a

    (a/b + c) * a;

    (0./1. + 2.) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (2. * 1.) + 0.
    (1./1. + 2.) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (2. * 1.) + 1.
    (1./1. + 1.) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (1. * 1.) + 1.

    (0./1. + a) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a * 1.) + 0.
    (0./a + 2.) * a;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (2. * a) + 0.

    (a/b + get_f64()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((get_f64()) * b) + a
    (a/b + (4.5f64).sqrt()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (((4.5f64).sqrt()) * b) + a
    (a/b + (42 as f64)) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((42 as f64) * b) + a
    (a/b + { 42. }) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (({ 42. }) * b) + a

    (a/get_f64() + c) * get_f64();
    (a/{ 42. } + c) * { 42. };

    (4.5f64).abs();

    (a*a + b*b).sqrt();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION a.hypot(b)

    a.floor();

    (a/b + c.floor()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((c.floor()) * b) + a

    (a/b + (0.5 + c).floor()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (((0.5 + c).floor()) * b) + a

    let d = (0., 0.);
    let d2 = (0., 0.);

    (a/b + d.0) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (d.0 * b) + a

    (a/b + get_tup().0) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((get_tup().0) * b) + a

    (a/d.0 + c) * d.0;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (c * d.0) + a

    (a/d.0 + c) * d2.0;
    (a/d.0 + c) * a;
    (a/0. + c) * a;

    (a/d.0 + c) * d.1;
    (a/get_tup().0 + c) * get_tup().0;

    let e = get_struct();
    let e2 = get_struct();

    (a/b + e.a) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (e.a * b) + a

    (a/b + get_struct().a) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((get_struct().a) * b) + a

    (a/e.a + c) * e.a;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (c * e.a) + a

    (a/e.a + c) * e2.a;

    (a/get_struct().a + c) * get_struct().a;
    (a/e.a + c) * e.b;

    1. - a.cos();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a.sin() * a.sin()) / a.cos().ln_1p().exp()

    (a+b).sin() - (a+b).cos();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (b.sin() * (a.sin() + a.cos())) - ((a.cos() - a.sin()) * b.cos())

    (a+1.).ln();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION a.ln_1p()
}
<commit_msg>Fix tests<commit_after>#![feature(plugin)]
#![plugin(herbie_lint)]

#![allow(dead_code)]
#![deny(herbie)]

struct Foo { a: f64, b: f64 }

impl Foo {
    fn foo(self) {
        (self.a/self.a + self.a) * self.a;
        //~^ ERROR
        //~| HELP Try this
        //~| SUGGESTION (self.a * self.a) + self.a
    }

    #[herbie_ignore]
    fn bar(self) {
        (self.a/self.a + self.a) * self.a;
    }
}

fn get_f64() -> f64 {
    4.2
}

fn get_tup() -> (f64, f64) {
    (0., 0.)
}

fn get_struct() -> Foo {
    Foo { a: 0., b: 0. }
}

fn integers() {
    1;
    (1/2 + 3) * 2;
}

#[herbie_ignore]
fn attr_on_fn() {
    (0./0. + 0.) * 0.;

    fn foo() {
        (0./0. + 0.) * 0.;
        //~^ ERROR
        //~| HELP Try this
        //~| SUGGESTION (0. * 0.) + 0.
    }

    #[herbie_ignore]
    fn bar() {
        (0./0. + 0.) * 0.;
    }
}

fn main() {
    integers();

    let (a, b, c) = (0., 0., 0.);

    a*a + b*b;

    (a/a + a) * a;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a * a) + a
    (a/b + a) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a * b) + a
    (a/b + c) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (c * b) + a

    (a/b + c) * a;

    (0./1. + 2.) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (2. * 1.) + 0.
    (1./1. + 2.) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (2. * 1.) + 1.
    (1./1. + 1.) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (1. * 1.) + 1.

    (0./1. + a) * 1.;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a * 1.) + 0.
    (0./a + 2.) * a;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (2. * a) + 0.

    (a/b + get_f64()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((get_f64()) * b) + a
    (a/b + (4.5f64).sqrt()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (((4.5f64).sqrt()) * b) + a
    (a/b + (42 as f64)) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (((42 as f64)) * b) + a
    (a/b + { 42. }) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (({ 42. }) * b) + a

    (a/get_f64() + c) * get_f64();
    (a/{ 42. } + c) * { 42. };

    (4.5f64).abs();

    (a*a + b*b).sqrt();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION a.hypot(b)

    a.floor();

    (a/b + c.floor()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((c.floor()) * b) + a

    (a/b + (0.5 + c).floor()) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (((0.5 + c).floor()) * b) + a

    let d = (0., 0.);
    let d2 = (0., 0.);

    (a/b + d.0) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (d.0 * b) + a

    (a/b + get_tup().0) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((get_tup().0) * b) + a

    (a/d.0 + c) * d.0;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (c * d.0) + a

    (a/d.0 + c) * d2.0;
    (a/d.0 + c) * a;
    (a/0. + c) * a;

    (a/d.0 + c) * d.1;
    (a/get_tup().0 + c) * get_tup().0;

    let e = get_struct();
    let e2 = get_struct();

    (a/b + e.a) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (e.a * b) + a

    (a/b + get_struct().a) * b;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION ((get_struct().a) * b) + a

    (a/e.a + c) * e.a;
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (c * e.a) + a

    (a/e.a + c) * e2.a;

    (a/get_struct().a + c) * get_struct().a;
    (a/e.a + c) * e.b;

    1. - a.cos();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (a.sin() * a.sin()) / a.cos().ln_1p().exp()

    (a+b).sin() - (a+b).cos();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION (b.sin() * (a.sin() + a.cos())) - ((a.cos() - a.sin()) * b.cos())

    (a+1.).ln();
    //~^ ERROR
    //~| HELP Try this
    //~| SUGGESTION a.ln_1p()
}
<|endoftext|>


<commit_before>use std;
use std::any::Any;
use std::panic;
use std::panic::AssertUnwindSafe;

use chashmap::CHashMap;

use two_lock_queue::{unbounded, Sender, Receiver, TryRecvError};

use futures;
use futures::future::*;

use futures::{Future, future};
use fibers::{Executor, ThreadPoolExecutor, Spawn};

use uuid::Uuid;

pub trait Actor: Send {
    fn on_message(&mut self, msg: Box<Any + Send>);
}

pub trait ActorRef: Clone {
    fn send(&mut self, msg: Box<Any + Send>);
}

pub struct Supervisor<H, F>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> Box<Actor>
{
    map: std::collections::HashMap<String, (WorkerRef, ChildSpec<H, F>)>,
    handle: H,
}

impl<H, F> Supervisor<H, F>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> Box<Actor>
{
    pub fn new(handle: H, child_specs: Vec<ChildSpec<H, F>>) -> Supervisor<H, F> {
        let mut map = std::collections::HashMap::new();

        for spec in child_specs {
            let child = (spec.start)(handle.clone());
            let actor = actor_of(handle.clone(), child);
            map.insert(spec.key.clone(), (actor, spec));
        }

        Supervisor {
            map: map,
            handle: handle,
        }
    }
}

impl<H, F> Actor for Supervisor<H, F>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> Box<Actor>
{
    fn on_message(&mut self, msg: Box<Any + Send>) {
        if let Ok(msg) = msg.downcast::<SupervisorMessage>() {
            let id = msg.id.clone();
            println!("got id {}", id);
            if let Some(val) = self.map.get_mut(&id) {
                let &mut (ref mut actor, ref childspec) = val;

                let msg = msg.msg;
                actor.send(msg)

//                match result {
//                    Err(_) => {
//                        *actor = actor_of(self.handle.clone(),
//                                          (childspec.start)(self.handle.clone()))
//                    }
//                    _ => (),
//                }
            }
        } else {
            panic!("downcast error");
        }
    }
}

#[derive(Clone)]
pub struct WorkerRef {
    sender: Sender<Box<Any + Send>>,
    receiver: Receiver<Box<Any + Send>>,
    id: String,
}

#[derive(Clone)]
pub enum Restart {
    Transient,
    Persistent,
    Temporary,
}

#[derive(Clone)]
pub enum Shutdown {
    Eventually,
    Immediately,
    Brute,
}

#[derive(Clone)]
pub enum ActorKind {
    System,
    Worker,
    Supervisor,
}

#[derive(Clone)]
pub struct ChildSpec<H, F>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> Box<Actor>
{
    key: String,
    start: F,
    restart: Restart,
    shutdown: Shutdown,
    kind: ActorKind,
    _ph: std::marker::PhantomData<H>,
}

impl<H, F> ChildSpec<H, F>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> Box<Actor>
{
    pub fn new(key: String,
               start: F,
               restart: Restart,
               shutdown: Shutdown,
               kind: ActorKind)
               -> ChildSpec<H, F> {
        ChildSpec {
            key: key,
            start: start,
            restart: restart,
            shutdown: shutdown,
            kind: kind,
            _ph: std::marker::PhantomData,
        }
    }
}

struct SupervisorMessage {
    id: String,
    msg: Box<Any + Send>,
}

impl ActorRef for WorkerRef {
    fn send(&mut self, msg: Box<Any + Send>) {
        self.sender.send(msg).unwrap();
    }
}

pub fn supervised_actor_of<H, F>(exec: H,
                                 mut actor: Box<Actor>,
                                 policy: ChildSpec<H, F>)
                                 -> WorkerRef
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> Box<Actor>
{
    let (sender, receiver) = unbounded();
    let recvr = receiver.clone();
    exec.spawn(futures::lazy(move || {
        loop_fn(0, move |_| match recvr.try_recv() {
            Ok(msg) => {
                actor.on_message(msg);

                Ok::<_, _>(Loop::Continue(0))
            }
            Err(TryRecvError::Disconnected) => Ok::<_, _>(Loop::Break(())),
            Err(TryRecvError::Empty) => Ok::<_, _>(Loop::Continue(0)),
        })
    }));

    WorkerRef {
        sender: sender,
        receiver: receiver,
        id: Uuid::new_v4().to_string(),
    }
}

pub fn actor_of<H>(exec: H, mut actor: Box<Actor>) -> WorkerRef
    where H: Send + Spawn + Clone + 'static
{
    let (sender, receiver) = unbounded();
    let recvr = receiver.clone();
    exec.spawn(futures::lazy(move || {
        loop_fn(0, move |_| match recvr.try_recv() {
            Ok(msg) => {
                actor.on_message(msg);

                Ok::<_, _>(Loop::Continue(0))
            }
            Err(TryRecvError::Disconnected) => Ok::<_, _>(Loop::Break(())),
            Err(TryRecvError::Empty) => Ok::<_, _>(Loop::Continue(0)),
        })
    }));

    WorkerRef {
        sender: sender,
        receiver: receiver,
        id: Uuid::new_v4().to_string(),
    }
}

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

    struct MyActor<H>
        where H: Send + Spawn + Clone + 'static
    {
        handle: H,
        id: String,
    }

    impl<H> MyActor<H>
        where H: Send + Spawn + Clone + 'static
    {
        pub fn new(h: H) -> MyActor<H> {
            MyActor {
                handle: h,
                id: Uuid::new_v4().to_string(),
            }
        }
    }

    impl<H> Actor for MyActor<H>
        where H: Send + Spawn + Clone + 'static
    {
        fn on_message(&mut self, msg: Box<Any + Send>) {
            if let Some(number) = msg.downcast_ref::<u64>() {
                if number % 1000 == 0 {
                    println!("{} got {}", self.id, number);
                }

                //                if *number == 0 {panic!("zero!")};
                let new_actor = Box::new(MyActor::new(self.handle.clone())) as Box<Actor>;
                let actor_ref = actor_of(self.handle.clone(), new_actor);
                actor_ref.sender.send(Box::new(number + 1));
                drop(actor_ref);
            } else {
                panic!("downcast error");
            }
        }
    }

    #[test]
    fn supervisors() {
        let system = ThreadPoolExecutor::with_thread_count(2).unwrap();
        let handle = system.handle();

        let child_spec = ChildSpec::new("worker child".to_owned(),
                                        move |handle| Box::new(MyActor::new(handle)) as Box<Actor>,
                                        Restart::Temporary,
                                        Shutdown::Eventually,
                                        ActorKind::Worker);

        let mut supervisor_ref =
            actor_of(handle.clone(),
                     Box::new(Supervisor::new(handle.clone(), vec![child_spec])) as Box<Actor>);

        supervisor_ref.send(Box::new(SupervisorMessage {
            id: "worker child".to_owned(),
            msg: Box::new(1000000 as u64),
        }));

        drop(supervisor_ref);

        let _ = system.run();
    }

        #[test]
        fn test_name() {
            let system = ThreadPoolExecutor::with_thread_count(2).unwrap();

            let actor = MyActor::new(system.handle());
            let mut actor_ref = actor_of(system.handle(), Box::new(actor));
            actor_ref.send(Box::new(0 as u64));
            drop(actor_ref);

            let _ = system.run();
        }
}
<commit_msg>Static-ify the actor/supervisor interface<commit_after>use std;

use two_lock_queue::{unbounded, Sender, Receiver, TryRecvError};

use futures;
use futures::future::*;

use fibers::Spawn;

use uuid::Uuid;

pub trait Actor<M: Send>: Send {
    fn on_message(&mut self, msg: M);
}

pub trait ActorRef<M: Send>: Clone {
    fn send(&mut self, msg: M);
}

pub struct Supervisor<A, H, F, M>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> A,
          A: Actor<M>,
          M: Send
{
    map: std::collections::HashMap<String, (WorkerRef<M>, ChildSpec<A, H, F, M>)>,
}

impl<A, H, F, M> Supervisor<A, H, F, M>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> A,
          A: Actor<M> + 'static,
          M: Send + 'static
{
    pub fn new(handle: H, child_specs: Vec<ChildSpec<A, H, F, M>>) -> Supervisor<A, H, F, M> {
        let mut map = std::collections::HashMap::new();

        for spec in child_specs {
            let child = (spec.start)(handle.clone());
            let actor = actor_of(handle.clone(), child);
            map.insert(spec.key.clone(), (actor, spec));
        }

        Supervisor { map: map }
    }
}

impl<A, H, F, M> Actor<SupervisorMessage<M>> for Supervisor<A, H, F, M>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> A,
          A: Actor<M>,
          M: Send
{
    fn on_message(&mut self, msg: SupervisorMessage<M>) {
        let id = msg.id.clone();
        println!("got id {}", id);
        if let Some(val) = self.map.get_mut(&id) {
            let &mut (ref mut actor, _) = val;

            let msg = msg.msg;
            actor.send(msg)

            //                match result {
            //                    Err(_) => {
            //                        *actor = actor_of(self.handle.clone(),
            //                                          (childspec.start)(self.handle.clone()))
            //                    }
            //                    _ => (),
            //                }
        }
    }
}

pub struct WorkerRef<M>
    where M: Send
{
    sender: Sender<M>,
    receiver: Receiver<M>,
    id: String,
}

// wtf, why does this work and #[derive(Clone)] not?
impl<M> Clone for WorkerRef<M>
    where M: Send
{
    fn clone(&self) -> Self {
        WorkerRef {
            sender: self.sender.clone(),
            receiver: self.receiver.clone(),
            id: self.id.clone(),
        }
    }
}

#[derive(Clone)]
pub enum Restart {
    Transient,
    Persistent,
    Temporary,
}

#[derive(Clone)]
pub enum Shutdown {
    Eventually,
    Immediately,
    Brute,
}

#[derive(Clone)]
pub enum ActorKind {
    System,
    Worker,
    Supervisor,
}

#[derive(Clone)]
pub struct ChildSpec<A, H, F, M>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> A,
          A: Actor<M>,
          M: Send
{
    key: String,
    start: F,
    restart: Restart,
    shutdown: Shutdown,
    kind: ActorKind,
    _ph: std::marker::PhantomData<(H, M)>,
}

impl<A, H, F, M> ChildSpec<A, H, F, M>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> A,
          A: Actor<M>,
          M: Send
{
    pub fn new(key: String,
               start: F,
               restart: Restart,
               shutdown: Shutdown,
               kind: ActorKind)
               -> ChildSpec<A, H, F, M> {
        ChildSpec {
            key: key,
            start: start,
            restart: restart,
            shutdown: shutdown,
            kind: kind,
            _ph: std::marker::PhantomData,
        }
    }
}

pub struct SupervisorMessage<M> {
    id: String,
    msg: M,
}

impl<M> ActorRef<M> for WorkerRef<M>
    where M: Send
{
    fn send(&mut self, msg: M) {
        self.sender.send(msg).unwrap();
    }
}

pub fn supervised_actor_of<A, H, F, M>(exec: H,
                                       mut actor: A,
                                       _: ChildSpec<A, H, F, M>)
                                       -> WorkerRef<M>
    where H: Send + Spawn + Clone + 'static,
          F: Send + 'static + Fn(H) -> A,
          A: Actor<M> + 'static,
          M: Send + 'static
{
    let (sender, receiver) = unbounded();
    let recvr = receiver.clone();
    exec.spawn(futures::lazy(move || {
        loop_fn(0, move |_| match recvr.try_recv() {
            Ok(msg) => {
                actor.on_message(msg);

                Ok::<_, _>(Loop::Continue(0))
            }
            Err(TryRecvError::Disconnected) => Ok::<_, _>(Loop::Break(())),
            Err(TryRecvError::Empty) => Ok::<_, _>(Loop::Continue(0)),
        })
    }));

    WorkerRef {
        sender: sender,
        receiver: receiver,
        id: Uuid::new_v4().to_string(),
    }
}

pub fn actor_of<A, H, M>(exec: H, mut actor: A) -> WorkerRef<M>
    where H: Send + Spawn + Clone + 'static,
          M: Send + 'static,
          A: Actor<M> + 'static
{
    let (sender, receiver) = unbounded();
    let recvr = receiver.clone();
    exec.spawn(futures::lazy(move || {
        loop_fn(0, move |_| match recvr.try_recv() {
            Ok(msg) => {
                actor.on_message(msg);

                Ok::<_, _>(Loop::Continue(0))
            }
            Err(TryRecvError::Disconnected) => Ok::<_, _>(Loop::Break(())),
            Err(TryRecvError::Empty) => Ok::<_, _>(Loop::Continue(0)),
        })
    }));

    WorkerRef {
        sender: sender,
        receiver: receiver,
        id: Uuid::new_v4().to_string(),
    }
}

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

    use std::any::Any;

    use fibers::{Executor, ThreadPoolExecutor};

    struct MyActor<H>
        where H: Send + Spawn + Clone + 'static
    {
        handle: H,
        id: String,
    }

    impl<H> MyActor<H>
        where H: Send + Spawn + Clone + 'static
    {
        pub fn new(h: H) -> MyActor<H> {
            MyActor {
                handle: h,
                id: Uuid::new_v4().to_string(),
            }
        }
    }

    impl<H> Actor<Box<Any + Send>> for MyActor<H>
        where H: Send + Spawn + Clone + 'static
    {
        fn on_message(&mut self, msg: Box<Any + Send>) {
            if let Some(number) = msg.downcast_ref::<u64>() {
                if number % 1000 == 0 {
                    println!("{} got {}", self.id, number);
                }

                //                if *number == 0 {panic!("zero!")};
                let new_actor = MyActor::new(self.handle.clone());
                let actor_ref = actor_of(self.handle.clone(), new_actor);
                actor_ref.sender.send(Box::new(number + 1));
                drop(actor_ref);
            } else {
                panic!("downcast error");
            }
        }
    }

    #[test]
    fn supervisors() {
        let system = ThreadPoolExecutor::with_thread_count(2).unwrap();
        let handle = system.handle();

        let child_spec = ChildSpec::new("worker child".to_owned(),
                                        move |handle| MyActor::new(handle),
                                        Restart::Temporary,
                                        Shutdown::Eventually,
                                        ActorKind::Worker);

        let mut supervisor_ref = actor_of(handle.clone(),
                                          Supervisor::new(handle.clone(), vec![child_spec]));

        supervisor_ref.send(SupervisorMessage {
                                id: "worker child".to_owned(),
                                msg: Box::new(1000000 as u64) as Box<Any + Send>,
                            });

        drop(supervisor_ref);

        let _ = system.run();
    }

    #[test]
    fn test_name() {
        let system = ThreadPoolExecutor::with_thread_count(2).unwrap();

        let actor = MyActor::new(system.handle());
        let mut actor_ref = actor_of(system.handle(), actor);
        actor_ref.send(Box::new(0 as u64));
        drop(actor_ref);

        let _ = system.run();
    }
}

<|endoftext|>