<commit_before>use std::fmt;
use std::io::BufRead;
use std::io::Write;
use std::io;
use std::net;

use types::MemcacheError;

pub struct Connection {
    reader: io::BufReader<net::TcpStream>,
}

enum StoreCommand {
    Set,
    Add,
    Replace,
}

impl fmt::Display for StoreCommand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StoreCommand::Set => write!(f, "set"),
            StoreCommand::Add => write!(f, "add"),
            StoreCommand::Replace => write!(f, "replace"),
        }
    }
}

impl Connection {
    fn store(&mut self,
             command: StoreCommand,
             key: &str,
             value: &[u8],
             flags: u16,
             exptime: u32)
             -> Result<bool, MemcacheError> {
        try!(write!(self.reader.get_ref(),
                    "{} {} {} {} {}\r\n",
                    command,
                    key,
                    flags,
                    exptime,
                    value.len()));
        try!(self.reader.get_ref().write(value));
        try!(self.reader.get_ref().write(b"\r\n"));
        try!(self.reader.get_ref().flush());
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        if s == "ERROR\r\n" {
            return Err(MemcacheError::Error);
        } else if s.starts_with("CLIENT_ERROR") {
            return Err(MemcacheError::ClientError(s));
        } else if s.starts_with("SERVER_ERROR") {
            return Err(MemcacheError::ServerError(s));
        } else if s == "STORED\r\n" {
            return Ok(true);
        } else if s == "NOT_STORED\r\n" {
            return Ok(false);
        } else {
            return Err(MemcacheError::Error);
        }
    }

    pub fn flush(&mut self) -> Result<(), MemcacheError> {
        match self.reader.get_ref().write(b"flush_all\r\n") {
            Ok(_) => {}
            Err(err) => return Err(MemcacheError::from(err)),
        }
        try!(self.reader.get_ref().flush());
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        if s == "ERROR\r\n" {
            return Err(MemcacheError::Error);
        } else if s.starts_with("CLIENT_ERROR") {
            return Err(MemcacheError::ClientError(s));
        } else if s.starts_with("SERVER_ERROR") {
            return Err(MemcacheError::ServerError(s));
        } else if s != "OK\r\n" {
            return Err(MemcacheError::Error);
        }
        return Ok(());
    }

    pub fn set(&mut self,
               key: &str,
               value: &[u8],
               flags: u16,
               exptime: u32)
               -> Result<bool, MemcacheError> {
        return self.store(StoreCommand::Set, key, value, flags, exptime);
    }

    pub fn replace(&mut self,
                   key: &str,
                   value: &[u8],
                   flags: u16,
                   exptime: u32)
                   -> Result<bool, MemcacheError> {
        return self.store(StoreCommand::Replace, key, value, flags, exptime);
    }

    pub fn version(&mut self) -> Result<String, MemcacheError> {
        match self.reader.get_ref().write(b"version\r\n") {
            Ok(_) => {}
            Err(err) => return Err(MemcacheError::from(err)),
        }

        try!(self.reader.get_ref().flush());
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        if s == "ERROR\r\n" {
            return Err(MemcacheError::Error);
        } else if s.starts_with("CLIENT_ERROR") {
            return Err(MemcacheError::ClientError(s));
        } else if s.starts_with("SERVER_ERROR") {
            return Err(MemcacheError::ServerError(s));
        } else if !s.starts_with("VERSION") {
            return Err(MemcacheError::Error);
        }
        let s = s.trim_left_matches("VERSION ");
        let s = s.trim_right_matches("\r\n");

        return Ok(s.to_string());
    }
}

pub fn connect() -> Result<Connection, MemcacheError> {
    match net::TcpStream::connect("127.0.0.1:11211") {
        Ok(stream) => return Ok(Connection { reader: io::BufReader::new(stream) }),
        Err(err) => return Err(MemcacheError::from(err)),
    }
}
<commit_msg>refactor: using rust 1.13.0's ? operator<commit_after>use std::fmt;
use std::io::BufRead;
use std::io::Write;
use std::io;
use std::net;

use types::MemcacheError;

pub struct Connection {
    reader: io::BufReader<net::TcpStream>,
}

enum StoreCommand {
    Set,
    Add,
    Replace,
}

impl fmt::Display for StoreCommand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StoreCommand::Set => write!(f, "set"),
            StoreCommand::Add => write!(f, "add"),
            StoreCommand::Replace => write!(f, "replace"),
        }
    }
}

impl Connection {
    fn store(&mut self,
             command: StoreCommand,
             key: &str,
             value: &[u8],
             flags: u16,
             exptime: u32)
             -> Result<bool, MemcacheError> {
        write!(self.reader.get_ref(),
               "{} {} {} {} {}\r\n",
               command,
               key,
               flags,
               exptime,
               value.len())?;
        self.reader.get_ref().write(value)?;
        self.reader.get_ref().write(b"\r\n")?;
        self.reader.get_ref().flush()?;
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        if s == "ERROR\r\n" {
            return Err(MemcacheError::Error);
        } else if s.starts_with("CLIENT_ERROR") {
            return Err(MemcacheError::ClientError(s));
        } else if s.starts_with("SERVER_ERROR") {
            return Err(MemcacheError::ServerError(s));
        } else if s == "STORED\r\n" {
            return Ok(true);
        } else if s == "NOT_STORED\r\n" {
            return Ok(false);
        } else {
            return Err(MemcacheError::Error);
        }
    }

    pub fn flush(&mut self) -> Result<(), MemcacheError> {
        match self.reader.get_ref().write(b"flush_all\r\n") {
            Ok(_) => {}
            Err(err) => return Err(MemcacheError::from(err)),
        }
        self.reader.get_ref().flush()?;
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        if s == "ERROR\r\n" {
            return Err(MemcacheError::Error);
        } else if s.starts_with("CLIENT_ERROR") {
            return Err(MemcacheError::ClientError(s));
        } else if s.starts_with("SERVER_ERROR") {
            return Err(MemcacheError::ServerError(s));
        } else if s != "OK\r\n" {
            return Err(MemcacheError::Error);
        }
        return Ok(());
    }

    pub fn set(&mut self,
               key: &str,
               value: &[u8],
               flags: u16,
               exptime: u32)
               -> Result<bool, MemcacheError> {
        return self.store(StoreCommand::Set, key, value, flags, exptime);
    }

    pub fn replace(&mut self,
                   key: &str,
                   value: &[u8],
                   flags: u16,
                   exptime: u32)
                   -> Result<bool, MemcacheError> {
        return self.store(StoreCommand::Replace, key, value, flags, exptime);
    }

    pub fn version(&mut self) -> Result<String, MemcacheError> {
        self.reader.get_ref().write(b"version\r\n")?;

        self.reader.get_ref().flush()?;
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        if s == "ERROR\r\n" {
            return Err(MemcacheError::Error);
        } else if s.starts_with("CLIENT_ERROR") {
            return Err(MemcacheError::ClientError(s));
        } else if s.starts_with("SERVER_ERROR") {
            return Err(MemcacheError::ServerError(s));
        } else if !s.starts_with("VERSION") {
            return Err(MemcacheError::Error);
        }
        let s = s.trim_left_matches("VERSION ");
        let s = s.trim_right_matches("\r\n");

        return Ok(s.to_string());
    }
}

pub fn connect() -> Result<Connection, MemcacheError> {
    let stream = net::TcpStream::connect("127.0.0.1:11211")?;
    return Ok(Connection { reader: io::BufReader::new(stream) });
}
<|endoftext|>


<commit_before>use async_std::path::PathBuf as AsyncPathBuf;
use std::path::{Path, PathBuf};
use std::{ffi::OsStr, io};
use tide::{Body, Endpoint, Request, Response, Result, StatusCode};

pub struct ServeStaticFiles {
    prefix: String,
    dir: PathBuf,
}

impl ServeStaticFiles {
    pub fn new(prefix: String, dir: PathBuf) -> Self {
        Self { prefix, dir }
    }
}

#[async_trait::async_trait]
impl<State> Endpoint<State> for ServeStaticFiles
where
    State: Clone + Send + Sync + 'static,
{
    async fn call(&self, req: Request<State>) -> Result {
        let path = req.url().path();
        let path = path
            .strip_prefix(&self.prefix.trim_end_matches('*'))
            .unwrap();
        let path = path.trim_start_matches('/');
        let mut file_path = self.dir.clone();
        for p in Path::new(path) {
            if p == OsStr::new(".") {
                continue;
            } else if p == OsStr::new("..") {
                file_path.pop();
            } else {
                file_path.push(&p);
            }
        }
        let file_path = AsyncPathBuf::from(file_path);

        // Search for .html suffix and/or directory with index.html
        let mut file_path_to_search = file_path.clone();
        let mut file_path_with_extension = file_path.clone();
        file_path_with_extension.set_extension("html");
        if file_path.is_dir().await {
            if file_path_with_extension.exists().await {
                file_path_to_search = file_path_with_extension;
            } else {
                file_path_to_search.push("index.html");
            }
        } else if !file_path.exists().await {
            file_path_to_search = file_path_with_extension;
        }

        if !file_path_to_search.starts_with(&self.dir) {
            log::warn!("Unauthorized attempt to read: {:?}", file_path_to_search);
            Ok(Response::new(StatusCode::Forbidden))
        } else {
            match Body::from_file(&file_path_to_search).await {
                Ok(body) => Ok(Response::builder(StatusCode::Ok).body(body).build()),
                Err(e) if e.kind() == io::ErrorKind::NotFound => {
                    log::warn!("File not found: {:?}", &file_path_to_search);
                    Ok(Response::new(StatusCode::NotFound))
                }
                Err(e) => Err(e.into()),
            }
        }
    }
}
<commit_msg>Slightly more efficient file lookup<commit_after>use async_std::path::PathBuf as AsyncPathBuf;
use std::path::{Path, PathBuf};
use std::{ffi::OsStr, io};
use tide::{Body, Endpoint, Request, Response, Result, StatusCode};

pub struct ServeStaticFiles {
    prefix: String,
    dir: PathBuf,
}

impl ServeStaticFiles {
    pub fn new(prefix: String, dir: PathBuf) -> Self {
        Self { prefix, dir }
    }

    pub fn get_path_with_extension(path: &AsyncPathBuf, extension: &str) -> AsyncPathBuf {
        let mut path_with_extension = path.clone();
        path_with_extension.set_extension(extension);
        return path_with_extension;
    }
}

#[async_trait::async_trait]
impl<State> Endpoint<State> for ServeStaticFiles
where
    State: Clone + Send + Sync + 'static,
{
    async fn call(&self, req: Request<State>) -> Result {
        let path = req.url().path();
        let path = path
            .strip_prefix(&self.prefix.trim_end_matches('*'))
            .unwrap();
        let path = path.trim_start_matches('/');
        let mut file_path = self.dir.clone();
        for p in Path::new(path) {
            if p == OsStr::new(".") {
                continue;
            } else if p == OsStr::new("..") {
                file_path.pop();
            } else {
                file_path.push(&p);
            }
        }
        let file_path = AsyncPathBuf::from(file_path);

        // Search for .html suffix and/or directory with index.html
        let mut file_path_to_search = file_path;
        if file_path_to_search.is_dir().await {
            let file_path_with_extension =
                ServeStaticFiles::get_path_with_extension(&file_path_to_search, "html");
            if file_path_with_extension.exists().await {
                file_path_to_search = file_path_with_extension;
            } else {
                file_path_to_search.push("index.html");
            }
        } else if !file_path_to_search.exists().await {
            let file_path_with_extension =
                ServeStaticFiles::get_path_with_extension(&file_path_to_search, "html");
            file_path_to_search = file_path_with_extension;
        }

        if !file_path_to_search.starts_with(&self.dir) {
            log::warn!("Unauthorized attempt to read: {:?}", file_path_to_search);
            Ok(Response::new(StatusCode::Forbidden))
        } else {
            match Body::from_file(&file_path_to_search).await {
                Ok(body) => Ok(Response::builder(StatusCode::Ok).body(body).build()),
                Err(e) if e.kind() == io::ErrorKind::NotFound => {
                    log::warn!("File not found: {:?}", &file_path_to_search);
                    Ok(Response::new(StatusCode::NotFound))
                }
                Err(e) => Err(e.into()),
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Jauhien Piatlicki.
//
// 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.

// Core LLVM: Value hierarchy
// LLVM-C header Core.h

use std;
use std::ffi::CString;

use libc::{c_char, c_uint, c_ulonglong};

use llvm_sys::*;
use llvm_sys::prelude::*;
use llvm_sys::core::*;

use ::{LLVMRef, LLVMRefCtor};
use core::basic_block::{BasicBlock, BasicBlocksIter};
use core::context::Context;
use core::module;
use core::types::{Type, IntType, FunctionType, RealType};

pub trait ValueCtor : LLVMRefCtor<LLVMValueRef> {}

pub trait Value : LLVMRef<LLVMValueRef> {
    fn get_type(&self) -> LLVMTypeRef {
        unsafe {
            LLVMTypeOf(self.to_ref())
        }
    }

    fn get_name(&self) -> String {
        let buf = unsafe {
            std::ffi::CStr::from_ptr(LLVMGetValueName(self.to_ref()))
        };
        let result = String::from_utf8_lossy(buf.to_bytes()).into_owned();
        result
    }

    fn set_name(&self, name: &str) {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMSetValueName(self.to_ref(), name.as_ptr() as *const i8)
        }
    }

    fn dump(&self) {
        unsafe {
            LLVMDumpValue(self.to_ref())
        }
    }

    fn print_to_string(&self) -> String {
        unsafe {
            let buf = LLVMPrintValueToString(self.to_ref());
            let cstr_buf = std::ffi::CStr::from_ptr(buf);
            let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
            LLVMDisposeMessage(buf);
            result
        }
    }

    fn replace_all_uses_with(&self, new_val: &Value) {
        unsafe {
            LLVMReplaceAllUsesWith(self.to_ref(), new_val.to_ref())
        }
    }

    fn is_constant(&self) -> bool {
        unsafe {
            LLVMIsConstant(self.to_ref()) > 0
        }
    }

    fn is_undef(&self) -> bool {
        unsafe {
            LLVMIsUndef(self.to_ref()) > 0
        }
    }

    fn use_iter(&self) -> UseIter {
        let first = unsafe {
            LLVMGetFirstUse(self.to_ref())
        };

        let current = if first.is_null() {
            None
        } else {
            Some(first)
        };

        UseIter{current: current}
    }
}

impl LLVMRef<LLVMValueRef> for LLVMValueRef {
    fn to_ref(&self) -> LLVMValueRef {
        *self
    }
}

impl LLVMRefCtor<LLVMValueRef> for LLVMValueRef {
    unsafe fn from_ref(rf: LLVMValueRef) -> LLVMValueRef {
        rf
    }
}

impl Value for LLVMValueRef {}
impl ValueCtor for LLVMValueRef {}

pub trait UseCtor : LLVMRefCtor<LLVMUseRef> {}

pub trait Use : LLVMRef<LLVMUseRef> {
    fn get_user(&self) -> UserRef {
        unsafe {
            UserRef::from_ref(LLVMGetUser(self.to_ref()))
        }
    }

    fn get_used_value(&self) -> LLVMValueRef {
        unsafe {
            LLVMGetUsedValue(self.to_ref())
        }
    }
}

impl LLVMRef<LLVMUseRef> for LLVMUseRef {
    fn to_ref(&self) -> LLVMUseRef {
        *self
    }
}

impl LLVMRefCtor<LLVMUseRef> for LLVMUseRef {
    unsafe fn from_ref(rf: LLVMUseRef) -> LLVMUseRef {
        rf
    }
}

impl Use for LLVMUseRef {}
impl UseCtor for LLVMUseRef {}

pub struct UseIter {
    current: Option<LLVMUseRef>
}

impl Iterator for UseIter {
    type Item = LLVMUseRef;

    fn next(&mut self) -> Option<LLVMUseRef> {
        match self.current {
            Some(cur) => {
                let next = unsafe {
                    LLVMGetNextUse(cur)
                };
                self.current = if next.is_null() {
                    None
                } else {
                    Some(next)
                };

                self.current
            },
            None => None
        }
    }
}

// TODO: implement iterator and some better indexing for User

pub trait User : Value {
    fn get_operand(&self, index: u32) -> LLVMValueRef {
        unsafe {
            LLVMGetOperand(self.to_ref(), index)
        }
    }

    fn get_operand_use(&self, index: u32) -> LLVMUseRef {
        unsafe {
            LLVMUseRef::from_ref(LLVMGetOperandUse(self.to_ref(), index))
        }
    }

    fn set_operand(&self, index: u32, op: &Value) {
        unsafe {
            LLVMSetOperand(self.to_ref(), index, op.to_ref())
        }
    }

    fn get_num_operands(&self) -> i32 {
        unsafe {
            LLVMGetNumOperands(self.to_ref())
        }
    }
}

new_ref_type!(UserRef for LLVMValueRef implementing Value);

pub trait ConstCtor<Ty: Type + ?Sized> : ValueCtor {
    fn get_null(ty: &Ty) -> Self {
        unsafe {
            Self::from_ref(LLVMConstNull(ty.to_ref()))
        }
    }

    fn get_undef(ty: &Ty) -> Self {
        unsafe {
            Self::from_ref(LLVMGetUndef(ty.to_ref()))
        }
    }

    fn get_pointer_null(ty: &Ty) -> Self {
        unsafe {
            Self::from_ref(LLVMConstPointerNull(ty.to_ref()))
        }
    }
}

pub trait Const : User {
    fn is_null(&self) -> bool {
        unsafe {
            LLVMIsNull(self.to_ref()) > 0
        }
    }
}

pub trait IntConstCtor : ConstCtor<IntType> {
    fn get_all_ones(ty: &IntType) -> Self {
        unsafe {
            Self::from_ref(LLVMConstAllOnes(ty.to_ref()))
        }
    }

    fn get(ty: &IntType, val: u64, sign_extend: bool) -> Self {
        unsafe {
            Self::from_ref(LLVMConstInt(ty.to_ref(), val, sign_extend as LLVMBool))
        }
    }

    fn get_arbitrary_precision(ty: &IntType, words: &[u64]) -> Self {
        unsafe {
            Self::from_ref(LLVMConstIntOfArbitraryPrecision(ty.to_ref(),
                                                            words.len() as c_uint,
                                                            words.as_ptr()))
        }
    }

    fn get_from_string(ty: &IntType, text: &str, radix: u8) -> Self {
        let text = CString::new(text).unwrap();
        unsafe {
            Self::from_ref(LLVMConstIntOfString(ty.to_ref(),
                                                text.as_ptr() as *const c_char,
                                                radix))
        }
    }
}

pub trait IntConst : Const {
    fn get_z_ext_value(&self) -> u64 {
        unsafe {
            LLVMConstIntGetZExtValue(self.to_ref())
        }
    }

    fn get_s_ext_value(&self) -> i64 {
        unsafe {
            LLVMConstIntGetSExtValue(self.to_ref())
        }
    }
}

new_ref_type!(IntConstRef for LLVMValueRef
              implementing
              Value,
              User,
              Const,
              ValueCtor,
              ConstCtor<IntType>,
              IntConstCtor,
              IntConst
              );

pub trait RealConstCtor : ConstCtor<RealType> {
    fn get(ty: &RealType, val: f64) -> Self {
        unsafe {
            Self::from_ref(LLVMConstReal(ty.to_ref(), val))
        }
    }

    fn get_from_string(ty: &RealType, text: &str) -> Self {
        let text = CString::new(text).unwrap();
        unsafe {
            Self::from_ref(LLVMConstRealOfString(ty.to_ref(), text.as_ptr() as *const c_char))
        }
    }
}

pub trait RealConst : Const {
    fn get_double(&self) -> (f64, bool) {
        let mut info_lost: LLVMBool = 0;
        let val = unsafe {
            LLVMConstRealGetDouble(self.to_ref(), &mut info_lost)
        };

        (val, info_lost > 0)
    }
}

new_ref_type!(RealConstRef for LLVMValueRef
              implementing
              Value,
              User,
              Const,
              ValueCtor,
              ConstCtor<RealType>,
              RealConstCtor,
              RealConst
              );

pub trait FunctionCtor : ValueCtor {
    fn new(module: &mut module::Module, name: &str, ty: &FunctionType) -> Self {
        let name = CString::new(name).unwrap();
        unsafe {
            Self::from_ref(LLVMAddFunction(module.to_ref(), name.as_ptr() as *const c_char, ty.to_ref()))
        }
    }
}

pub trait Function : Const {
    fn get_intrinsic_id(&self) -> u32 {
        unsafe {
            LLVMGetIntrinsicID(self.to_ref())
        }
    }

    fn get_call_conv(&self) -> LLVMCallConv {
        unsafe {
            std::mem::transmute(LLVMGetFunctionCallConv(self.to_ref()))
        }
    }

    fn set_call_conv(&self, cc: LLVMCallConv) {
        unsafe {
            LLVMSetFunctionCallConv(self.to_ref(), cc as c_uint)
        }
    }

    fn add_attr(&self, attr: LLVMAttribute) {
        unsafe {
            LLVMAddFunctionAttr(self.to_ref(), attr)
        }
    }

    fn get_attr(&self) -> LLVMAttribute {
        unsafe {
            LLVMGetFunctionAttr(self.to_ref())
        }
    }

    fn remove_attr(&self, attr: LLVMAttribute) {
        unsafe {
            LLVMRemoveFunctionAttr(self.to_ref(), attr)
        }
    }

    fn count_params(&self) -> u32 {
        unsafe {
            LLVMCountParams(self.to_ref())
        }
    }

    fn get_params(&self) -> Vec<LLVMValueRef> {
        let params_count = self.count_params();
        let mut buf : Vec<LLVMValueRef> = Vec::with_capacity(params_count as usize);
        let p = buf.as_mut_ptr();
        unsafe {
            std::mem::forget(buf);
            LLVMGetParams(self.to_ref(), p);
            Vec::from_raw_parts(p, params_count as usize, params_count as usize)
        }
    }

    fn get_param(&self, index: u32) -> ArgumentRef {
        unsafe {
            ArgumentRef::from_ref(LLVMGetParam(self.to_ref(), index))
        }
    }

    fn params_iter(&self) -> ArgsIter {
        ArgsIter{
            current: None,
            func: self.to_ref(),
            pos: 0,
            size: 0
        }
    }

    fn count_basic_blocks(&self) -> u32 {
        unsafe {
            LLVMCountBasicBlocks(self.to_ref())
        }
    }

    fn basic_blocks_iter(&self) -> BasicBlocksIter {
        let first = unsafe {
            LLVMGetFirstBasicBlock(self.to_ref())
        };

        let current = if first.is_null() {
            None
        } else {
            Some(first)
        };

        BasicBlocksIter{current: current}
    }

    fn get_entry(&self) -> LLVMBasicBlockRef {
        unsafe {
            LLVMGetEntryBasicBlock(self.to_ref())
        }
    }

    fn append_basic_block_in_context(&self, context: &mut Context, name: &str)  -> LLVMBasicBlockRef {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMAppendBasicBlockInContext(context.to_ref(), self.to_ref(), name.as_ptr() as *const c_char)
        }
    }

    fn append_basic_block(&self, name: &str)  -> LLVMBasicBlockRef {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMAppendBasicBlock(self.to_ref(), name.as_ptr() as *const c_char)
        }
    }
}

new_ref_type!(FunctionRef for LLVMValueRef
              implementing
              Value,
              User,
              Const,
              Function,
              ValueCtor,
              FunctionCtor
              );

//TODO Add args back iter

pub trait Argument : Value {
    fn get_parent(&self) -> FunctionRef {
        unsafe {
            FunctionRef::from_ref(LLVMGetParamParent(self.to_ref()))
        }
    }

    fn add_attr(&self, attr: LLVMAttribute) {
        unsafe {
            LLVMAddAttribute(self.to_ref(), attr)
        }
    }

    fn get_attr(&self) -> LLVMAttribute {
        unsafe {
            LLVMGetAttribute(self.to_ref())
        }
    }

    fn remove_attr(&self, attr: LLVMAttribute) {
        unsafe {
            LLVMRemoveAttribute(self.to_ref(), attr)
        }
    }

    fn set_alignment(&self, align: u32) {
        unsafe {
            LLVMSetParamAlignment(self.to_ref(), align)
        }
    }
}

new_ref_type!(ArgumentRef for LLVMValueRef
              implementing
              Value,
              Argument
              );

pub struct ArgsIter {
    current: Option<LLVMValueRef>,
    func: LLVMValueRef,
    pos: u32,
    size: u32
}

impl Iterator for ArgsIter {
    type Item = ArgumentRef;

    fn next(&mut self) -> Option<ArgumentRef> {
        let cur = match self.current {
            Some(cur) => {
                cur
            },
            None => {
                unsafe {
                    self.size = LLVMCountParams(self.func);
                    self.pos = 0;
                    if self.size == 0 {
                        return None
                    }
                    LLVMGetFirstParam(self.func)
                }
            }
        };

        if self.pos >= self.size {
            return None
        }

        unsafe {
            if self.pos < self.size - 1 {
                self.current = Some(LLVMGetNextParam(cur))
            }

            self.pos += 1;

            Some(ArgumentRef::from_ref(cur))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (pos, size) = match self.current {
            Some(_) => (self.pos, self.size),
            None => unsafe { (0, LLVMCountParams(self.func)) }
        };

        ((size - pos) as usize, Some((size - pos) as usize))
    }
}
<commit_msg>[core] add function verification and cfg showing.<commit_after>// Copyright 2015 Jauhien Piatlicki.
//
// 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.

// Core LLVM: Value hierarchy
// LLVM-C header Core.h

use std;
use std::ffi::CString;

use libc::{c_char, c_uint, c_ulonglong};

use llvm_sys::*;
use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::analysis::*;

use ::{LLVMRef, LLVMRefCtor};
use core::basic_block::{BasicBlock, BasicBlocksIter};
use core::context::Context;
use core::module;
use core::types::{Type, IntType, FunctionType, RealType};

pub trait ValueCtor : LLVMRefCtor<LLVMValueRef> {}

pub trait Value : LLVMRef<LLVMValueRef> {
    fn get_type(&self) -> LLVMTypeRef {
        unsafe {
            LLVMTypeOf(self.to_ref())
        }
    }

    fn get_name(&self) -> String {
        let buf = unsafe {
            std::ffi::CStr::from_ptr(LLVMGetValueName(self.to_ref()))
        };
        let result = String::from_utf8_lossy(buf.to_bytes()).into_owned();
        result
    }

    fn set_name(&self, name: &str) {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMSetValueName(self.to_ref(), name.as_ptr() as *const i8)
        }
    }

    fn dump(&self) {
        unsafe {
            LLVMDumpValue(self.to_ref())
        }
    }

    fn print_to_string(&self) -> String {
        unsafe {
            let buf = LLVMPrintValueToString(self.to_ref());
            let cstr_buf = std::ffi::CStr::from_ptr(buf);
            let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
            LLVMDisposeMessage(buf);
            result
        }
    }

    fn replace_all_uses_with(&self, new_val: &Value) {
        unsafe {
            LLVMReplaceAllUsesWith(self.to_ref(), new_val.to_ref())
        }
    }

    fn is_constant(&self) -> bool {
        unsafe {
            LLVMIsConstant(self.to_ref()) > 0
        }
    }

    fn is_undef(&self) -> bool {
        unsafe {
            LLVMIsUndef(self.to_ref()) > 0
        }
    }

    fn use_iter(&self) -> UseIter {
        let first = unsafe {
            LLVMGetFirstUse(self.to_ref())
        };

        let current = if first.is_null() {
            None
        } else {
            Some(first)
        };

        UseIter{current: current}
    }
}

impl LLVMRef<LLVMValueRef> for LLVMValueRef {
    fn to_ref(&self) -> LLVMValueRef {
        *self
    }
}

impl LLVMRefCtor<LLVMValueRef> for LLVMValueRef {
    unsafe fn from_ref(rf: LLVMValueRef) -> LLVMValueRef {
        rf
    }
}

impl Value for LLVMValueRef {}
impl ValueCtor for LLVMValueRef {}

pub trait UseCtor : LLVMRefCtor<LLVMUseRef> {}

pub trait Use : LLVMRef<LLVMUseRef> {
    fn get_user(&self) -> UserRef {
        unsafe {
            UserRef::from_ref(LLVMGetUser(self.to_ref()))
        }
    }

    fn get_used_value(&self) -> LLVMValueRef {
        unsafe {
            LLVMGetUsedValue(self.to_ref())
        }
    }
}

impl LLVMRef<LLVMUseRef> for LLVMUseRef {
    fn to_ref(&self) -> LLVMUseRef {
        *self
    }
}

impl LLVMRefCtor<LLVMUseRef> for LLVMUseRef {
    unsafe fn from_ref(rf: LLVMUseRef) -> LLVMUseRef {
        rf
    }
}

impl Use for LLVMUseRef {}
impl UseCtor for LLVMUseRef {}

pub struct UseIter {
    current: Option<LLVMUseRef>
}

impl Iterator for UseIter {
    type Item = LLVMUseRef;

    fn next(&mut self) -> Option<LLVMUseRef> {
        match self.current {
            Some(cur) => {
                let next = unsafe {
                    LLVMGetNextUse(cur)
                };
                self.current = if next.is_null() {
                    None
                } else {
                    Some(next)
                };

                self.current
            },
            None => None
        }
    }
}

// TODO: implement iterator and some better indexing for User

pub trait User : Value {
    fn get_operand(&self, index: u32) -> LLVMValueRef {
        unsafe {
            LLVMGetOperand(self.to_ref(), index)
        }
    }

    fn get_operand_use(&self, index: u32) -> LLVMUseRef {
        unsafe {
            LLVMUseRef::from_ref(LLVMGetOperandUse(self.to_ref(), index))
        }
    }

    fn set_operand(&self, index: u32, op: &Value) {
        unsafe {
            LLVMSetOperand(self.to_ref(), index, op.to_ref())
        }
    }

    fn get_num_operands(&self) -> i32 {
        unsafe {
            LLVMGetNumOperands(self.to_ref())
        }
    }
}

new_ref_type!(UserRef for LLVMValueRef implementing Value);

pub trait ConstCtor<Ty: Type + ?Sized> : ValueCtor {
    fn get_null(ty: &Ty) -> Self {
        unsafe {
            Self::from_ref(LLVMConstNull(ty.to_ref()))
        }
    }

    fn get_undef(ty: &Ty) -> Self {
        unsafe {
            Self::from_ref(LLVMGetUndef(ty.to_ref()))
        }
    }

    fn get_pointer_null(ty: &Ty) -> Self {
        unsafe {
            Self::from_ref(LLVMConstPointerNull(ty.to_ref()))
        }
    }
}

pub trait Const : User {
    fn is_null(&self) -> bool {
        unsafe {
            LLVMIsNull(self.to_ref()) > 0
        }
    }
}

pub trait IntConstCtor : ConstCtor<IntType> {
    fn get_all_ones(ty: &IntType) -> Self {
        unsafe {
            Self::from_ref(LLVMConstAllOnes(ty.to_ref()))
        }
    }

    fn get(ty: &IntType, val: u64, sign_extend: bool) -> Self {
        unsafe {
            Self::from_ref(LLVMConstInt(ty.to_ref(), val, sign_extend as LLVMBool))
        }
    }

    fn get_arbitrary_precision(ty: &IntType, words: &[u64]) -> Self {
        unsafe {
            Self::from_ref(LLVMConstIntOfArbitraryPrecision(ty.to_ref(),
                                                            words.len() as c_uint,
                                                            words.as_ptr()))
        }
    }

    fn get_from_string(ty: &IntType, text: &str, radix: u8) -> Self {
        let text = CString::new(text).unwrap();
        unsafe {
            Self::from_ref(LLVMConstIntOfString(ty.to_ref(),
                                                text.as_ptr() as *const c_char,
                                                radix))
        }
    }
}

pub trait IntConst : Const {
    fn get_z_ext_value(&self) -> u64 {
        unsafe {
            LLVMConstIntGetZExtValue(self.to_ref())
        }
    }

    fn get_s_ext_value(&self) -> i64 {
        unsafe {
            LLVMConstIntGetSExtValue(self.to_ref())
        }
    }
}

new_ref_type!(IntConstRef for LLVMValueRef
              implementing
              Value,
              User,
              Const,
              ValueCtor,
              ConstCtor<IntType>,
              IntConstCtor,
              IntConst
              );

pub trait RealConstCtor : ConstCtor<RealType> {
    fn get(ty: &RealType, val: f64) -> Self {
        unsafe {
            Self::from_ref(LLVMConstReal(ty.to_ref(), val))
        }
    }

    fn get_from_string(ty: &RealType, text: &str) -> Self {
        let text = CString::new(text).unwrap();
        unsafe {
            Self::from_ref(LLVMConstRealOfString(ty.to_ref(), text.as_ptr() as *const c_char))
        }
    }
}

pub trait RealConst : Const {
    fn get_double(&self) -> (f64, bool) {
        let mut info_lost: LLVMBool = 0;
        let val = unsafe {
            LLVMConstRealGetDouble(self.to_ref(), &mut info_lost)
        };

        (val, info_lost > 0)
    }
}

new_ref_type!(RealConstRef for LLVMValueRef
              implementing
              Value,
              User,
              Const,
              ValueCtor,
              ConstCtor<RealType>,
              RealConstCtor,
              RealConst
              );

pub trait FunctionCtor : ValueCtor {
    fn new(module: &mut module::Module, name: &str, ty: &FunctionType) -> Self {
        let name = CString::new(name).unwrap();
        unsafe {
            Self::from_ref(LLVMAddFunction(module.to_ref(), name.as_ptr() as *const c_char, ty.to_ref()))
        }
    }
}

pub trait Function : Const {
    fn get_intrinsic_id(&self) -> u32 {
        unsafe {
            LLVMGetIntrinsicID(self.to_ref())
        }
    }

    fn get_call_conv(&self) -> LLVMCallConv {
        unsafe {
            std::mem::transmute(LLVMGetFunctionCallConv(self.to_ref()))
        }
    }

    fn set_call_conv(&mut self, cc: LLVMCallConv) {
        unsafe {
            LLVMSetFunctionCallConv(self.to_ref(), cc as c_uint)
        }
    }

    fn add_attr(&mut self, attr: LLVMAttribute) {
        unsafe {
            LLVMAddFunctionAttr(self.to_ref(), attr)
        }
    }

    fn get_attr(&self) -> LLVMAttribute {
        unsafe {
            LLVMGetFunctionAttr(self.to_ref())
        }
    }

    fn remove_attr(&mut self, attr: LLVMAttribute) {
        unsafe {
            LLVMRemoveFunctionAttr(self.to_ref(), attr)
        }
    }

    fn count_params(&self) -> u32 {
        unsafe {
            LLVMCountParams(self.to_ref())
        }
    }

    fn get_params(&self) -> Vec<LLVMValueRef> {
        let params_count = self.count_params();
        let mut buf : Vec<LLVMValueRef> = Vec::with_capacity(params_count as usize);
        let p = buf.as_mut_ptr();
        unsafe {
            std::mem::forget(buf);
            LLVMGetParams(self.to_ref(), p);
            Vec::from_raw_parts(p, params_count as usize, params_count as usize)
        }
    }

    fn get_param(&self, index: u32) -> ArgumentRef {
        unsafe {
            ArgumentRef::from_ref(LLVMGetParam(self.to_ref(), index))
        }
    }

    fn params_iter(&self) -> ArgsIter {
        ArgsIter{
            current: None,
            func: self.to_ref(),
            pos: 0,
            size: 0
        }
    }

    fn count_basic_blocks(&self) -> u32 {
        unsafe {
            LLVMCountBasicBlocks(self.to_ref())
        }
    }

    fn basic_blocks_iter(&self) -> BasicBlocksIter {
        let first = unsafe {
            LLVMGetFirstBasicBlock(self.to_ref())
        };

        let current = if first.is_null() {
            None
        } else {
            Some(first)
        };

        BasicBlocksIter{current: current}
    }

    fn get_entry(&self) -> LLVMBasicBlockRef {
        unsafe {
            LLVMGetEntryBasicBlock(self.to_ref())
        }
    }

    fn append_basic_block_in_context(&mut self, context: &mut Context, name: &str)  -> LLVMBasicBlockRef {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMAppendBasicBlockInContext(context.to_ref(), self.to_ref(), name.as_ptr() as *const c_char)
        }
    }

    fn append_basic_block(&mut self, name: &str)  -> LLVMBasicBlockRef {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMAppendBasicBlock(self.to_ref(), name.as_ptr() as *const c_char)
        }
    }

    fn verify(&self, action: LLVMVerifierFailureAction) -> bool {
        unsafe {
            LLVMVerifyFunction(self.to_ref(), action) > 0
        }
    }

    fn view_cfg(&self) {
        unsafe {
            LLVMViewFunctionCFG(self.to_ref())
        }
    }

    fn view_cfg_only(&self) {
        unsafe {
            LLVMViewFunctionCFGOnly(self.to_ref())
        }
    }
}

new_ref_type!(FunctionRef for LLVMValueRef
              implementing
              Value,
              User,
              Const,
              Function,
              ValueCtor,
              FunctionCtor
              );

//TODO Add args back iter

pub trait Argument : Value {
    fn get_parent(&self) -> FunctionRef {
        unsafe {
            FunctionRef::from_ref(LLVMGetParamParent(self.to_ref()))
        }
    }

    fn add_attr(&self, attr: LLVMAttribute) {
        unsafe {
            LLVMAddAttribute(self.to_ref(), attr)
        }
    }

    fn get_attr(&self) -> LLVMAttribute {
        unsafe {
            LLVMGetAttribute(self.to_ref())
        }
    }

    fn remove_attr(&self, attr: LLVMAttribute) {
        unsafe {
            LLVMRemoveAttribute(self.to_ref(), attr)
        }
    }

    fn set_alignment(&self, align: u32) {
        unsafe {
            LLVMSetParamAlignment(self.to_ref(), align)
        }
    }
}

new_ref_type!(ArgumentRef for LLVMValueRef
              implementing
              Value,
              Argument
              );

pub struct ArgsIter {
    current: Option<LLVMValueRef>,
    func: LLVMValueRef,
    pos: u32,
    size: u32
}

impl Iterator for ArgsIter {
    type Item = ArgumentRef;

    fn next(&mut self) -> Option<ArgumentRef> {
        let cur = match self.current {
            Some(cur) => {
                cur
            },
            None => {
                unsafe {
                    self.size = LLVMCountParams(self.func);
                    self.pos = 0;
                    if self.size == 0 {
                        return None
                    }
                    LLVMGetFirstParam(self.func)
                }
            }
        };

        if self.pos >= self.size {
            return None
        }

        unsafe {
            if self.pos < self.size - 1 {
                self.current = Some(LLVMGetNextParam(cur))
            }

            self.pos += 1;

            Some(ArgumentRef::from_ref(cur))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (pos, size) = match self.current {
            Some(_) => (self.pos, self.size),
            None => unsafe { (0, LLVMCountParams(self.func)) }
        };

        ((size - pos) as usize, Some((size - pos) as usize))
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Hegv trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>


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

use std::slice::bytes::copy_memory;

mod ops;

static START_ADDR: u16 = 0x200;
static MEM_SIZE: uint = 4096;
pub static DISPLAY_WIDTH: uint = 64;
pub static DISPLAY_HEIGHT: uint = 32;

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

/// Draw callback.
///
/// Takes a slice of u8, where each u8 is a pixel.
///
/// A **non-zero** pixel is visible, a **zero** pixel is not visible.
///
/// The coordinate system is from top-left to bottom-right.
///
/// Example:
///
/// ```rust
///     use crustychip::{ DISPLAY_WIDTH, Chip8 };
///     // Dump the pixels to stdout
///     fn dump_pixels(pixels: &[u8]) {
///         for (i, px) in pixels.iter().enumerate() {
///             match *px {
///                 0 => print!(" "),
///                 _ => print!("#")
///             }
///             if i % DISPLAY_WIDTH == 0 {
///                 print!("\n");
///             }
///         }
///     }
///     let mut ch8 = Chip8::new(dump_pixels);
///     // ...
/// ```
pub type DrawCallback<'a> = |pixels: &[u8]|: 'a;

struct KeypressWait {
    wait: bool,
    vx: uint
}

/// CHIP-8 virtual machine
pub struct Chip8<'a> {
    ram: [u8, .. MEM_SIZE],
    v: [u8, .. 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16, .. 16],
    display: [u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT],
    draw_callback: DrawCallback<'a>,
    keys: [bool, .. 16],
    keypress_wait: KeypressWait
}

impl <'a> Chip8 <'a> {

    /// Create a new Chip8 VM
    ///
    /// ## Arguments ##
    /// * draw_callback - Callback used when drawing
    pub fn new(draw_callback: DrawCallback<'a>) -> Chip8<'a> {
        let mut ch8 = Chip8 {
            ram: [0u8, .. MEM_SIZE],
            v: [0u8, .. 16],
            i: 0u16,
            delay_timer: 0u8,
            sound_timer: 0u8,
            pc: START_ADDR,
            sp: 0,
            stack: [0u16, .. 16],
            display: [0u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT],
            draw_callback: draw_callback,
            keys: [false, .. 16],
            keypress_wait: KeypressWait {
                wait: false,
                vx: 0
            }
        };
        copy_memory(ch8.ram.mut_slice(0u, 5 * 0x10), fontset);
        ch8
    }

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

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

        let ins = self.get_ins();
        self.pc += 2;
        self.dispatch(ins);
    }

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

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

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

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

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

    /// Decrement the sound and delay timers
    ///
    /// They should be decremented at a rate of 60 Hz
    pub fn decrement_timers(&mut self) {
        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            self.sound_timer -= 1;
        }
    }
}
<commit_msg>Modify get_ins to increment pc and rename it to fetch_ins<commit_after>//! CHIP-8 emulator backend.
//! You can develop your own frontends for it.
//!
//! The reference frontend is
//! [crusty-chip-sfml](https://github.com/crumblingstatue/crusty-chip-sfml).
//!
//! The CHIP-8 technical documentation in the comments is copied from
//! http://devernay.free.fr/hacks/chip8/C8TECH10.HTM,
//! Copyright (c) Thomas P. Greene.

use std::slice::bytes::copy_memory;

mod ops;

static START_ADDR: u16 = 0x200;
static MEM_SIZE: uint = 4096;
pub static DISPLAY_WIDTH: uint = 64;
pub static DISPLAY_HEIGHT: uint = 32;

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

/// Draw callback.
///
/// Takes a slice of u8, where each u8 is a pixel.
///
/// A **non-zero** pixel is visible, a **zero** pixel is not visible.
///
/// The coordinate system is from top-left to bottom-right.
///
/// Example:
///
/// ```rust
///     use crustychip::{ DISPLAY_WIDTH, Chip8 };
///     // Dump the pixels to stdout
///     fn dump_pixels(pixels: &[u8]) {
///         for (i, px) in pixels.iter().enumerate() {
///             match *px {
///                 0 => print!(" "),
///                 _ => print!("#")
///             }
///             if i % DISPLAY_WIDTH == 0 {
///                 print!("\n");
///             }
///         }
///     }
///     let mut ch8 = Chip8::new(dump_pixels);
///     // ...
/// ```
pub type DrawCallback<'a> = |pixels: &[u8]|: 'a;

struct KeypressWait {
    wait: bool,
    vx: uint
}

/// CHIP-8 virtual machine
pub struct Chip8<'a> {
    ram: [u8, .. MEM_SIZE],
    v: [u8, .. 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16, .. 16],
    display: [u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT],
    draw_callback: DrawCallback<'a>,
    keys: [bool, .. 16],
    keypress_wait: KeypressWait
}

impl <'a> Chip8 <'a> {

    /// Create a new Chip8 VM
    ///
    /// ## Arguments ##
    /// * draw_callback - Callback used when drawing
    pub fn new(draw_callback: DrawCallback<'a>) -> Chip8<'a> {
        let mut ch8 = Chip8 {
            ram: [0u8, .. MEM_SIZE],
            v: [0u8, .. 16],
            i: 0u16,
            delay_timer: 0u8,
            sound_timer: 0u8,
            pc: START_ADDR,
            sp: 0,
            stack: [0u16, .. 16],
            display: [0u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT],
            draw_callback: draw_callback,
            keys: [false, .. 16],
            keypress_wait: KeypressWait {
                wait: false,
                vx: 0
            }
        };
        copy_memory(ch8.ram.mut_slice(0u, 5 * 0x10), fontset);
        ch8
    }

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

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

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

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

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

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

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

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

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


<commit_before>use std::cell::{Cell, RefCell};

use cairo::{Context, Format, ImageSurface, Matrix, MatrixTrait, Operator};

use gtk::DrawingArea;
use gtk::prelude::*;

use gui::DrawingArgs;
use gui::plot_context::{GenericContext, PlotContext};

use app::config;
use coords::{DeviceCoords, DeviceRect, WPCoords, ScreenCoords, XYCoords, XYRect};

pub struct RHOmegaContext {
    x_zoom: Cell<f64>,
    generic: GenericContext,

    pub matrix: Cell<Matrix>,

    dirty_background: Cell<bool>,
    background_layer: RefCell<ImageSurface>,

    dirty_data: Cell<bool>,
    data_layer: RefCell<ImageSurface>,

    dirty_overlay: Cell<bool>,
    overlay_layer: RefCell<ImageSurface>,
}

impl RHOmegaContext {
    pub fn new() -> Self {
        RHOmegaContext {
            x_zoom: Cell::new(1.0),
            generic: GenericContext::new(),

            matrix: Cell::new(Matrix::identity()),

            dirty_background: Cell::new(true),
            background_layer: RefCell::new(ImageSurface::create(Format::ARgb32, 5, 5).unwrap()),

            dirty_data: Cell::new(true),
            data_layer: RefCell::new(ImageSurface::create(Format::ARgb32, 5, 5).unwrap()),

            dirty_overlay: Cell::new(true),
            overlay_layer: RefCell::new(ImageSurface::create(Format::ARgb32, 5, 5).unwrap()),
        }
    }

    pub fn convert_wp_to_xy(coords: WPCoords) -> XYCoords {
        use std::f64;

        let y = (f64::log10(config::MAXP) - f64::log10(coords.p))
            / (f64::log10(config::MAXP) - f64::log10(config::MINP));

        // The + sign below looks weird, but is correct.
        let x = (coords.w + config::MAX_ABS_W) / (2.0 * config::MAX_ABS_W);

        XYCoords { x, y }
    }

    pub fn convert_xy_to_wp(coords: XYCoords) -> WPCoords {
        use std::f64;

        let p = 10.0f64.powf(
            -coords.y * (f64::log10(config::MAXP) - f64::log10(config::MINP))
                + f64::log10(config::MAXP),
        );
        let w = coords.x * (2.0 * config::MAX_ABS_W) - config::MAX_ABS_W;

        WPCoords { w, p }
    }

    pub fn convert_screen_to_wp(&self, coords: ScreenCoords) -> WPCoords {
        let xy = self.convert_screen_to_xy(coords);
        RHOmegaContext::convert_xy_to_wp(xy)
    }

    pub fn convert_wp_to_screen(&self, coords: WPCoords) -> ScreenCoords {
        let xy = RHOmegaContext::convert_wp_to_xy(coords);
        self.convert_xy_to_screen(xy)
    }

    pub fn convert_device_to_wp(&self, coords: DeviceCoords) -> WPCoords {
        let xy = self.convert_device_to_xy(coords);
        Self::convert_xy_to_wp(xy)
    }

    pub fn set_translate_y(&self, new_translate: XYCoords) {
        let mut translate = self.get_translate();
        translate.y = new_translate.y;
        self.generic.set_translate(translate);
    }
}

impl PlotContext for RHOmegaContext {
    fn set_device_rect(&self, rect: DeviceRect) {
        self.generic.set_device_rect(rect)
    }

    fn get_device_rect(&self) -> DeviceRect {
        self.generic.get_device_rect()
    }

    fn convert_xy_to_screen(&self, coords: XYCoords) -> ScreenCoords {
        // FIXME: use x_zoom
        self.generic.convert_xy_to_screen(coords)
    }

    fn convert_screen_to_xy(&self, coords: ScreenCoords) -> XYCoords {
        self.generic.convert_screen_to_xy(coords)
    }

    fn get_xy_envelope(&self) -> XYRect {
        self.generic.get_xy_envelope()
    }

    fn set_xy_envelope(&self, new_envelope: XYRect) {
        self.generic.set_xy_envelope(new_envelope);
    }

    fn get_zoom_factor(&self) -> f64 {
        self.generic.get_zoom_factor()
    }

    fn set_zoom_factor(&self, new_zoom_factor: f64) {
        self.generic.set_zoom_factor(new_zoom_factor);
    }

    fn get_translate(&self) -> XYCoords {
        self.generic.get_translate()
    }

    fn set_translate(&self, new_translate: XYCoords) {
        self.generic.set_translate(new_translate);
    }

    fn get_left_button_pressed(&self) -> bool {
        self.generic.get_left_button_pressed()
    }

    fn set_left_button_pressed(&self, pressed: bool) {
        self.generic.set_left_button_pressed(pressed);
    }

    fn get_last_cursor_position(&self) -> Option<DeviceCoords> {
        self.generic.get_last_cursor_position()
    }

    fn set_last_cursor_position<U>(&self, new_position: U)
    where
        Option<DeviceCoords>: From<U>,
    {
        self.generic.set_last_cursor_position(new_position);
    }

    fn zoom_to_envelope(&self) {
        let xy_envelope = self.get_xy_envelope();

        let lower_left = xy_envelope.lower_left;
        self.set_translate(lower_left);

        let width = xy_envelope.upper_right.x - xy_envelope.lower_left.x;
        let width_scale = 1.0 / width;

        self.x_zoom.set(width_scale);
    }

    fn bound_view(&self) {
        let device_rect = self.get_device_rect();

        let bounds = DeviceCoords {
            col: device_rect.width,
            row: device_rect.height,
        };
        let lower_right = self.convert_device_to_xy(bounds);
        let upper_left = self.convert_device_to_xy(device_rect.upper_left);
        let height = upper_left.y - lower_right.y;

        let mut translate = self.get_translate();
        if height < 1.0 {
            if translate.y < 0.0 {
                translate.y = 0.0;
            }
            let max_y = 1.0 - height;
            if translate.y > max_y {
                translate.y = max_y;
            }
        } else {
            translate.y = -(height - 1.0) / 2.0;
        }
        self.set_translate(translate);
    }
}

impl RHOmegaContext {

    pub fn mark_background_dirty(&self) {
        self.dirty_background.set(true);
        self.dirty_data.set(true);
        self.dirty_overlay.set(true);
    }

    pub fn mark_data_dirty(&self) {
        self.dirty_background.set(true);
        self.dirty_data.set(true);
    }

    pub fn mark_overlay_dirty(&self) {
        self.dirty_overlay.set(true);
    }

    pub fn init_matrix(&self, args: DrawingArgs) {
        use gui::plot_context::PlotContext;

        let cr = args.cr;

        cr.save();

        let (x1, y1, x2, y2) = cr.clip_extents();
        let width = f64::abs(x2 - x1);
        let height = f64::abs(y2 - y1);

        let device_rect = DeviceRect {
            upper_left: DeviceCoords { row: 0.0, col: 0.0 },
            width,
            height,
        };
        self.set_device_rect(device_rect);
        let scale_factor = self.scale_factor();

        // Start fresh
        cr.identity_matrix();
        // Set the scale factor
        cr.scale(scale_factor, scale_factor);
        // Set origin at lower left.
        cr.transform(Matrix {
            xx: 1.0,
            yx: 0.0,
            xy: 0.0,
            yy: -1.0,
            x0: 0.0,
            y0: device_rect.height / scale_factor,
        });

        self.matrix.set(cr.get_matrix());
        cr.restore();
    }

    pub fn update_cache_allocations(&self, da: &DrawingArea) {
        // Mark everything as dirty
        self.mark_background_dirty(); // Marks everything

        // Get the size
        let (width, height) = (da.get_allocation().width, da.get_allocation().height);

        // Make the new allocations
        *self.background_layer.borrow_mut() =
            ImageSurface::create(Format::ARgb32, width, height).unwrap();
        *self.data_layer.borrow_mut() =
            ImageSurface::create(Format::ARgb32, width, height).unwrap();
        *self.overlay_layer.borrow_mut() =
            ImageSurface::create(Format::ARgb32, width, height).unwrap();

    }

    pub fn draw_background_cached(&self, args: DrawingArgs) {
        let (ac, cr, config) = (args.ac, args.cr, args.ac.config.borrow());

        if self.dirty_background.get() {
            let tmp_cr = Context::new(&self.background_layer.borrow().clone());

            // Clear the previous drawing from the cache
            tmp_cr.save();
            let rgba = config.background_rgba;
            tmp_cr.set_source_rgba(rgba.0, rgba.1, rgba.2, rgba.3);
            tmp_cr.set_operator(Operator::Source);
            tmp_cr.paint();
            tmp_cr.restore();
            tmp_cr.transform(self.matrix.get());
            let tmp_args = DrawingArgs { cr: &tmp_cr, ac };

            self.bound_view();

            super::drawing::draw_background(tmp_args);

            self.dirty_background.set(false);
        }

        cr.set_source_surface(&self.background_layer.borrow().clone(), 0.0, 0.0);
        cr.paint();
    }

    pub fn draw_data_cached(&self, args: DrawingArgs) {
        let (ac, cr) = (args.ac, args.cr);

        if self.dirty_data.get() {
            let tmp_cr = Context::new(&self.data_layer.borrow().clone());

            // Clear the previous drawing from the cache
            tmp_cr.save();
            tmp_cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
            tmp_cr.set_operator(Operator::Source);
            tmp_cr.paint();
            tmp_cr.restore();
            tmp_cr.transform(self.matrix.get());
            let tmp_args = DrawingArgs { cr: &tmp_cr, ac };

            super::drawing::draw_data(tmp_args);

            self.dirty_data.set(false);
        }

        cr.set_source_surface(&self.data_layer.borrow().clone(), 0.0, 0.0);
        cr.paint();
    }

    pub fn draw_overlay_cached(&self, args: DrawingArgs) {
        let (ac, cr) = (args.ac, args.cr);

        if self.dirty_overlay.get() {
            let tmp_cr = Context::new(&self.overlay_layer.borrow().clone());

            // Clear the previous drawing from the cache
            tmp_cr.save();
            tmp_cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
            tmp_cr.set_operator(Operator::Source);
            tmp_cr.paint();
            tmp_cr.restore();
            tmp_cr.transform(self.matrix.get());
            let tmp_args = DrawingArgs { cr: &tmp_cr, ac };

            super::drawing::draw_overlays(tmp_args);

            self.dirty_overlay.set(false);
        }

        cr.set_source_surface(&self.overlay_layer.borrow().clone(), 0.0, 0.0);
        cr.paint();
    }
}
<commit_msg>Fixed rh-omega drawing.<commit_after>use std::cell::{Cell, RefCell};

use cairo::{Context, Format, ImageSurface, Matrix, MatrixTrait, Operator};

use gtk::DrawingArea;
use gtk::prelude::*;

use gui::DrawingArgs;
use gui::plot_context::{GenericContext, PlotContext};

use app::config;
use coords::{DeviceCoords, DeviceRect, WPCoords, ScreenCoords, XYCoords, XYRect};

pub struct RHOmegaContext {
    x_zoom: Cell<f64>,
    generic: GenericContext,

    pub matrix: Cell<Matrix>,

    dirty_background: Cell<bool>,
    background_layer: RefCell<ImageSurface>,

    dirty_data: Cell<bool>,
    data_layer: RefCell<ImageSurface>,

    dirty_overlay: Cell<bool>,
    overlay_layer: RefCell<ImageSurface>,
}

impl RHOmegaContext {
    pub fn new() -> Self {
        RHOmegaContext {
            x_zoom: Cell::new(1.0),
            generic: GenericContext::new(),

            matrix: Cell::new(Matrix::identity()),

            dirty_background: Cell::new(true),
            background_layer: RefCell::new(ImageSurface::create(Format::ARgb32, 5, 5).unwrap()),

            dirty_data: Cell::new(true),
            data_layer: RefCell::new(ImageSurface::create(Format::ARgb32, 5, 5).unwrap()),

            dirty_overlay: Cell::new(true),
            overlay_layer: RefCell::new(ImageSurface::create(Format::ARgb32, 5, 5).unwrap()),
        }
    }

    pub fn convert_wp_to_xy(coords: WPCoords) -> XYCoords {
        use std::f64;

        let y = (f64::log10(config::MAXP) - f64::log10(coords.p))
            / (f64::log10(config::MAXP) - f64::log10(config::MINP));

        // The + sign below looks weird, but is correct.
        let x = (coords.w + config::MAX_ABS_W) / (2.0 * config::MAX_ABS_W);

        XYCoords { x, y }
    }

    pub fn convert_xy_to_wp(coords: XYCoords) -> WPCoords {
        use std::f64;

        let p = 10.0f64.powf(
            -coords.y * (f64::log10(config::MAXP) - f64::log10(config::MINP))
                + f64::log10(config::MAXP),
        );
        let w = coords.x * (2.0 * config::MAX_ABS_W) - config::MAX_ABS_W;

        WPCoords { w, p }
    }

    pub fn convert_screen_to_wp(&self, coords: ScreenCoords) -> WPCoords {
        let xy = self.convert_screen_to_xy(coords);
        RHOmegaContext::convert_xy_to_wp(xy)
    }

    pub fn convert_wp_to_screen(&self, coords: WPCoords) -> ScreenCoords {
        let xy = RHOmegaContext::convert_wp_to_xy(coords);
        self.convert_xy_to_screen(xy)
    }

    pub fn convert_device_to_wp(&self, coords: DeviceCoords) -> WPCoords {
        let xy = self.convert_device_to_xy(coords);
        Self::convert_xy_to_wp(xy)
    }

    pub fn set_translate_y(&self, new_translate: XYCoords) {
        let mut translate = self.get_translate();
        translate.y = new_translate.y;
        self.generic.set_translate(translate);
    }
}

impl PlotContext for RHOmegaContext {
    fn set_device_rect(&self, rect: DeviceRect) {
        self.generic.set_device_rect(rect)
    }

    fn get_device_rect(&self) -> DeviceRect {
        self.generic.get_device_rect()
    }

    fn convert_xy_to_screen(&self, coords: XYCoords) -> ScreenCoords {
        // Apply translation first
        let x = coords.x - self.generic.get_translate().x;
        let y = coords.y - self.generic.get_translate().y;

        // Apply scaling
        let x = x * self.x_zoom.get();
        let y = y * self.get_zoom_factor();

        ScreenCoords { x, y }
    }

    fn convert_screen_to_xy(&self, coords: ScreenCoords) -> XYCoords {
        // Unapply scaling first
        let x = coords.x / self.x_zoom.get();
        let y = coords.y / self.get_zoom_factor();

        // Unapply translation
        let x = x + self.generic.get_translate().x;
        let y = y + self.generic.get_translate().y;

XYCoords { x, y }
    }

    fn get_xy_envelope(&self) -> XYRect {
        self.generic.get_xy_envelope()
    }

    fn set_xy_envelope(&self, new_envelope: XYRect) {
        self.generic.set_xy_envelope(new_envelope);
    }

    fn get_zoom_factor(&self) -> f64 {
        self.generic.get_zoom_factor()
    }

    fn set_zoom_factor(&self, new_zoom_factor: f64) {
        self.generic.set_zoom_factor(new_zoom_factor);
    }

    fn get_translate(&self) -> XYCoords {
        self.generic.get_translate()
    }

    fn set_translate(&self, new_translate: XYCoords) {
        self.generic.set_translate(new_translate);
    }

    fn get_left_button_pressed(&self) -> bool {
        self.generic.get_left_button_pressed()
    }

    fn set_left_button_pressed(&self, pressed: bool) {
        self.generic.set_left_button_pressed(pressed);
    }

    fn get_last_cursor_position(&self) -> Option<DeviceCoords> {
        self.generic.get_last_cursor_position()
    }

    fn set_last_cursor_position<U>(&self, new_position: U)
    where
        Option<DeviceCoords>: From<U>,
    {
        self.generic.set_last_cursor_position(new_position);
    }

    fn zoom_to_envelope(&self) {
        let xy_envelope = self.get_xy_envelope();

        let lower_left = xy_envelope.lower_left;
        self.set_translate(lower_left);

        let width = xy_envelope.upper_right.x - xy_envelope.lower_left.x;
        let width_scale = 1.0 / width;

        self.x_zoom.set(width_scale);
    }

    fn bound_view(&self) {
        let device_rect = self.get_device_rect();

        let bounds = DeviceCoords {
            col: device_rect.width,
            row: device_rect.height,
        };
        let lower_right = self.convert_device_to_xy(bounds);
        let upper_left = self.convert_device_to_xy(device_rect.upper_left);
        let height = upper_left.y - lower_right.y;

        let mut translate = self.get_translate();
        if height < 1.0 {
            if translate.y < 0.0 {
                translate.y = 0.0;
            }
            let max_y = 1.0 - height;
            if translate.y > max_y {
                translate.y = max_y;
            }
        } else {
            translate.y = -(height - 1.0) / 2.0;
        }
        self.set_translate(translate);
    }
}

impl RHOmegaContext {

    pub fn mark_background_dirty(&self) {
        self.dirty_background.set(true);
        self.dirty_data.set(true);
        self.dirty_overlay.set(true);
    }

    pub fn mark_data_dirty(&self) {
        self.dirty_background.set(true);
        self.dirty_data.set(true);
    }

    pub fn mark_overlay_dirty(&self) {
        self.dirty_overlay.set(true);
    }

    pub fn init_matrix(&self, args: DrawingArgs) {
        use gui::plot_context::PlotContext;

        let cr = args.cr;

        cr.save();

        let (x1, y1, x2, y2) = cr.clip_extents();
        let width = f64::abs(x2 - x1);
        let height = f64::abs(y2 - y1);

        let device_rect = DeviceRect {
            upper_left: DeviceCoords { row: 0.0, col: 0.0 },
            width,
            height,
        };
        self.set_device_rect(device_rect);
        let scale_factor = self.scale_factor();

        // Start fresh
        cr.identity_matrix();
        // Set the scale factor
        cr.scale(scale_factor, scale_factor);
        // Set origin at lower left.
        cr.transform(Matrix {
            xx: 1.0,
            yx: 0.0,
            xy: 0.0,
            yy: -1.0,
            x0: 0.0,
            y0: device_rect.height / scale_factor,
        });

        self.matrix.set(cr.get_matrix());
        cr.restore();
    }

    pub fn update_cache_allocations(&self, da: &DrawingArea) {
        // Mark everything as dirty
        self.mark_background_dirty(); // Marks everything

        // Get the size
        let (width, height) = (da.get_allocation().width, da.get_allocation().height);

        // Make the new allocations
        *self.background_layer.borrow_mut() =
            ImageSurface::create(Format::ARgb32, width, height).unwrap();
        *self.data_layer.borrow_mut() =
            ImageSurface::create(Format::ARgb32, width, height).unwrap();
        *self.overlay_layer.borrow_mut() =
            ImageSurface::create(Format::ARgb32, width, height).unwrap();

    }

    pub fn draw_background_cached(&self, args: DrawingArgs) {
        let (ac, cr, config) = (args.ac, args.cr, args.ac.config.borrow());

        if self.dirty_background.get() {
            let tmp_cr = Context::new(&self.background_layer.borrow().clone());

            // Clear the previous drawing from the cache
            tmp_cr.save();
            let rgba = config.background_rgba;
            tmp_cr.set_source_rgba(rgba.0, rgba.1, rgba.2, rgba.3);
            tmp_cr.set_operator(Operator::Source);
            tmp_cr.paint();
            tmp_cr.restore();
            tmp_cr.transform(self.matrix.get());
            let tmp_args = DrawingArgs { cr: &tmp_cr, ac };

            self.bound_view();

            super::drawing::draw_background(tmp_args);

            self.dirty_background.set(false);
        }

        cr.set_source_surface(&self.background_layer.borrow().clone(), 0.0, 0.0);
        cr.paint();
    }

    pub fn draw_data_cached(&self, args: DrawingArgs) {
        let (ac, cr) = (args.ac, args.cr);

        if self.dirty_data.get() {
            let tmp_cr = Context::new(&self.data_layer.borrow().clone());

            // Clear the previous drawing from the cache
            tmp_cr.save();
            tmp_cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
            tmp_cr.set_operator(Operator::Source);
            tmp_cr.paint();
            tmp_cr.restore();
            tmp_cr.transform(self.matrix.get());
            let tmp_args = DrawingArgs { cr: &tmp_cr, ac };

            super::drawing::draw_data(tmp_args);

            self.dirty_data.set(false);
        }

        cr.set_source_surface(&self.data_layer.borrow().clone(), 0.0, 0.0);
        cr.paint();
    }

    pub fn draw_overlay_cached(&self, args: DrawingArgs) {
        let (ac, cr) = (args.ac, args.cr);

        if self.dirty_overlay.get() {
            let tmp_cr = Context::new(&self.overlay_layer.borrow().clone());

            // Clear the previous drawing from the cache
            tmp_cr.save();
            tmp_cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
            tmp_cr.set_operator(Operator::Source);
            tmp_cr.paint();
            tmp_cr.restore();
            tmp_cr.transform(self.matrix.get());
            let tmp_args = DrawingArgs { cr: &tmp_cr, ac };

            super::drawing::draw_overlays(tmp_args);

            self.dirty_overlay.set(false);
        }

        cr.set_source_surface(&self.overlay_layer.borrow().clone(), 0.0, 0.0);
        cr.paint();
    }
}
<|endoftext|>


<commit_before>use super::node::read_unchecked;
use super::node::write_node;
use super::node::write_targeted;
use super::node::NodeWriteGuard;
use super::search::mut_search;
use super::search::MutSearchResult;
use super::*;
use std::fmt::Debug;

pub struct NodeSplit<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub new_right_node: NodeCellRef,
    pub left_node_latch: NodeWriteGuard<KS, PS>,
    pub pivot: EntryKey,
    pub parent_latch: NodeWriteGuard<KS, PS>,
}

pub fn insert_internal_tree_node<KS, PS>(
    split_res: Option<NodeSplit<KS, PS>>,
    parent: &NodeCellRef,
) -> Option<NodeSplit<KS, PS>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    match split_res {
        None => None,
        Some(split) => {
            trace!(
                "Sub level node split, shall insert new node to current level, pivot {:?}",
                split.pivot
            );
            let pivot = split.pivot;
            trace!("New pivot {:?}", pivot);
            trace!("obtain latch for internal node split");
            let mut target_guard = write_targeted(split.parent_latch, &pivot);
            debug_assert!(read_unchecked::<KS, PS>(&split.new_right_node).first_key() >= &pivot);
            let mut split_result =
                target_guard
                    .innode_mut()
                    .insert(pivot, split.new_right_node, parent);
            if let &mut Some(ref mut split) = &mut split_result {
                split.left_node_latch = target_guard;
            }
            split_result
        }
    }
}

pub fn insert_external_tree_node<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    node_ref: &NodeCellRef,
    parent: &NodeCellRef,
    key: &EntryKey,
) -> Option<Option<NodeSplit<KS, PS>>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    // latch nodes from left to right
    trace!("Obtain latch for external node");
    let mut searched_guard = write_targeted(write_node(node_ref), key);
    let self_ref = searched_guard.node_ref().clone();
    debug_assert!(
        searched_guard.is_ext(),
        "{:?}",
        searched_guard.innode().keys
    );
    let mut split_result = searched_guard
        .extnode_mut(tree)
        .insert(key, tree, &self_ref, parent);
    if split_result.is_some() {
        external::make_changed(node_ref, tree);
    }
    if let &mut Some(Some(ref mut split)) = &mut split_result {
        split.left_node_latch = searched_guard;
        external::make_changed(&split.new_right_node, tree);
    }
    split_result
}

pub fn check_root_modification<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    modification: &Option<NodeSplit<KS, PS>>,
    parent: &NodeCellRef,
) -> Option<NodeSplit<KS, PS>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    if let &Some(ref split) = modification {
        let current_root = tree.get_root();
        if read_unchecked::<KS, PS>(&current_root).first_key() != split.left_node_latch.first_key()
            && split.left_node_latch.has_vaild_right_node()
        {
            // at this point, root split occurred when waiting for the latch
            // the new right node should be inserted to any right node of the old root
            // hopefully that node won't split again
            let current_root_guard = write_node::<KS, PS>(&current_root);
            // at this point, the root may have split again, we need to search for the exact one
            let mut root_level_target = write_targeted(current_root_guard, &split.pivot);
            // assert this even in production
            assert!(!root_level_target.is_ext());
            root_level_target.innode_mut().insert(
                split.pivot.clone(),
                split.new_right_node.clone(),
                parent,
            );
        }
    }
    None
}

pub fn insert_to_tree_node<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    node_ref: &NodeCellRef,
    parent: &NodeCellRef,
    key: &EntryKey,
    level: usize,
) -> Option<Option<NodeSplit<KS, PS>>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let search = mut_search::<KS, PS>(node_ref, key);
    let modification = match search {
        MutSearchResult::External => {
            if let Some(insertion) = insert_external_tree_node(tree, node_ref, parent, key) {
                insertion
            } else {
                return None;
            }
        }
        MutSearchResult::Internal(sub_node) => {
            if let Some(split_res) = insert_to_tree_node(tree, &sub_node, node_ref, key, level + 1)
            {
                insert_internal_tree_node(split_res, parent)
            } else {
                return None;
            }
        }
    };
    if level == 0 {
        let root_modified = check_root_modification(tree, &modification, parent);
        if root_modified.is_some() {
            return Some(root_modified);
        }
    }
    Some(modification)
}
<commit_msg>cannot fix, moving to self heal<commit_after>use super::node::read_unchecked;
use super::node::write_node;
use super::node::write_targeted;
use super::node::NodeWriteGuard;
use super::search::mut_search;
use super::search::MutSearchResult;
use super::*;
use std::fmt::Debug;

pub struct NodeSplit<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub new_right_node: NodeCellRef,
    pub left_node_latch: NodeWriteGuard<KS, PS>,
    pub pivot: EntryKey,
    pub parent_latch: NodeWriteGuard<KS, PS>,
}

pub fn insert_internal_tree_node<KS, PS>(
    split_res: Option<NodeSplit<KS, PS>>,
    parent: &NodeCellRef,
) -> Option<NodeSplit<KS, PS>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    match split_res {
        None => None,
        Some(split) => {
            trace!(
                "Sub level node split, shall insert new node to current level, pivot {:?}, node {:?}",
                split.pivot, split.new_right_node
            );
            let pivot = split.pivot;
            let mut target_guard = write_targeted(split.parent_latch, &pivot);
            debug_assert!(read_unchecked::<KS, PS>(&split.new_right_node).first_key() >= &pivot);
            let mut split_result =
                target_guard
                    .innode_mut()
                    .insert(pivot, split.new_right_node, parent);
            if let &mut Some(ref mut split) = &mut split_result {
                split.left_node_latch = target_guard;
            }
            split_result
        }
    }
}

pub fn insert_external_tree_node<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    node_ref: &NodeCellRef,
    parent: &NodeCellRef,
    key: &EntryKey,
) -> Option<Option<NodeSplit<KS, PS>>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    // latch nodes from left to right
    let mut searched_guard = write_targeted(write_node(node_ref), key);
    let self_ref = searched_guard.node_ref().clone();
    debug_assert!(
        searched_guard.is_ext(),
        "{:?}",
        searched_guard.innode().keys
    );
    let mut split_result = searched_guard
        .extnode_mut(tree)
        .insert(key, tree, &self_ref, parent);
    if split_result.is_some() {
        external::make_changed(node_ref, tree);
    }
    if let &mut Some(Some(ref mut split)) = &mut split_result {
        split.left_node_latch = searched_guard;
        external::make_changed(&split.new_right_node, tree);
    }
    split_result
}

pub fn check_root_modification<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    modification: &Option<NodeSplit<KS, PS>>,
    parent: &NodeCellRef,
) -> Option<NodeSplit<KS, PS>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    if let &Some(ref split) = modification {
        let current_root = tree.get_root();
        if read_unchecked::<KS, PS>(&current_root).first_key() != split.left_node_latch.first_key()
            && split.left_node_latch.has_vaild_right_node()
        {
            // at this point, root split occurred when waiting for the latch
            // the new right node should be inserted to any right node of the old root
            // hopefully that node won't split again
            let current_root_guard = write_node::<KS, PS>(&current_root);
            // at this point, the root may have split again, we need to search for the exact one
            let mut root_level_target = write_targeted(current_root_guard, &split.pivot);
            // assert this even in production
            assert!(!root_level_target.is_ext());
            root_level_target.innode_mut().insert(
                split.pivot.clone(),
                split.new_right_node.clone(),
                parent,
            );
        }
    }
    None
}

pub fn insert_to_tree_node<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    node_ref: &NodeCellRef,
    parent: &NodeCellRef,
    key: &EntryKey,
    level: usize,
) -> Option<Option<NodeSplit<KS, PS>>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let search = mut_search::<KS, PS>(node_ref, key);
    let modification = match search {
        MutSearchResult::External => {
            if let Some(insertion) = insert_external_tree_node(tree, node_ref, parent, key) {
                insertion
            } else {
                return None;
            }
        }
        MutSearchResult::Internal(sub_node) => {
            if let Some(split_res) = insert_to_tree_node(tree, &sub_node, node_ref, key, level + 1)
            {
                insert_internal_tree_node(split_res, parent)
            } else {
                return None;
            }
        }
    };
    if level == 0 {
        let root_modified = check_root_modification(tree, &modification, parent);
        if root_modified.is_some() {
            return Some(root_modified);
        }
    }
    Some(modification)
}
<|endoftext|>


<commit_before>use engine::Tile;
use util::units::{Size, XYPair};

pub struct Map {
    tiles: Vec<Vec<Tile>>,
    size: Size,
}

impl Map {

    pub fn new(size: Size) -> Map {

        let (width, height) = size.as_tuple();

        // TODO: use range syntax
        let tiles: Vec<Vec<Tile>> = range(0, height).map(|h| range(0, width).map(|w| Tile::Empty).collect()).collect();

        Map {
            tiles: tiles,
            size: size
        }
    }

}
<commit_msg>More elegant map construction<commit_after>use engine::Tile;
use util::units::{Size, XYPair};

use std::iter::repeat;

pub struct Map {
    tiles: Vec<Vec<Tile>>,
    size: Size,
}

impl Map {

    pub fn new(size: Size) -> Map {

        let (width, height) = size.as_tuple();

        // TODO: use range syntax
        let tiles: Vec<Vec<Tile>> = range(0, height).map(|_| repeat(Tile::Empty).take(width).collect()).collect();

        Map {
            tiles: tiles,
            size: size
        }
    }

}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/check-if-matrix-is-x-matrix/
pub fn check_x_matrix(grid: Vec<Vec<i32>>) -> bool {
    todo!()
}

fn main() {
    println!(
        "{}",
        check_x_matrix(vec![
            vec![2, 0, 0, 1],
            vec![0, 3, 1, 0],
            vec![0, 5, 2, 0],
            vec![4, 0, 0, 2]
        ])
    ); // true
    println!(
        "{}",
        check_x_matrix(vec![vec![5, 7, 0], vec![0, 3, 1], vec![0, 5, 0]])
    ); // true
}
<commit_msg>Solve problem 2319<commit_after>use std::collections::HashSet;

// https://leetcode.com/problems/check-if-matrix-is-x-matrix/
pub fn check_x_matrix(grid: Vec<Vec<i32>>) -> bool {
    let n = grid.len();
    let mut set: HashSet<(i32, i32)> = HashSet::new();
    let mut row: i32 = 0;
    let mut col: i32 = 0;
    while row < n as i32 {
        if grid[row as usize][col as usize] == 0 {
            return false;
        }
        set.insert((row, col));
        row += 1;
        col += 1;
    }
    let mut row: i32 = 0;
    let mut col: i32 = n as i32 - 1;
    while row < n as i32 {
        if grid[row as usize][col as usize] == 0 {
            return false;
        }
        set.insert((row, col));
        row += 1;
        col -= 1;
    }
    let mut row: i32 = 0;
    while row < n as i32 {
        let mut col: i32 = 0;
        while col < n as i32 {
            if !set.contains(&(row, col)) {
                if grid[row as usize][col as usize] != 0 {
                    return false;
                }
            }
            col += 1;
        }
        row += 1;
    }
    true
}

fn main() {
    println!(
        "{}",
        check_x_matrix(vec![
            vec![2, 0, 0, 1],
            vec![0, 3, 1, 0],
            vec![0, 5, 2, 0],
            vec![4, 0, 0, 2]
        ])
    ); // true
    println!(
        "{}",
        check_x_matrix(vec![vec![5, 7, 0], vec![0, 3, 1], vec![0, 5, 0]])
    ); // false
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/task-scheduler-ii/
pub fn task_scheduler_ii(tasks: Vec<i32>, space: i32) -> i64 {
    todo!()
}

fn main() {
    println!("{}", task_scheduler_ii(vec![1, 2, 1, 2, 3, 1], 3)); // 9
    println!("{}", task_scheduler_ii(vec![5, 8, 8, 5], 2)); // 6
}
<commit_msg>Update problem 2365<commit_after>// https://leetcode.com/problems/task-scheduler-ii/
pub fn task_scheduler_ii(tasks: Vec<i32>, space: i32) -> i64 {
    todo!()
}

fn main() {
    println!("{}", task_scheduler_ii(vec![1, 2, 1, 2, 3, 1], 3)); // 9
    println!("{}", task_scheduler_ii(vec![5, 8, 8, 5], 2)); // 6
    println!("{}", task_scheduler_ii(vec![1, 2, 3], 3)); // 3
}
<|endoftext|>