<commit_before>use utils::bigint::M256;
use utils::gas::Gas;
use super::commit::{AccountState, BlockhashState};
use super::errors::{RequireError, MachineError, CommitError, EvalError, PCError};
use super::{Stack, Context, BlockHeader, Patch, PC, Storage, Memory, AccountCommitment, Log};

use self::check::{check_opcode, extra_check_opcode};
use self::run::run_opcode;
use self::cost::{gas_refund, gas_stipend, gas_cost, memory_cost, memory_gas};
use self::utils::copy_into_memory;

mod cost;
mod run;
mod check;
mod utils;

/// A VM state without PC.
pub struct State<M, S> {
    pub memory: M,
    pub stack: Stack,

    pub context: Context,
    pub block: BlockHeader,
    pub patch: Patch,

    pub out: Vec<u8>,

    pub memory_cost: Gas,
    pub used_gas: Gas,
    pub refunded_gas: Gas,

    pub account_state: AccountState<S>,
    pub blockhash_state: BlockhashState,
    pub logs: Vec<Log>,

    pub depth: usize,
}

impl<M, S> State<M, S> {
    pub fn memory_gas(&self) -> Gas {
        memory_gas(self.memory_cost)
    }

    pub fn available_gas(&self) -> Gas {
        self.context.gas_limit - self.memory_gas() - self.used_gas
    }
}

/// A VM state with PC.
pub struct Machine<M, S> {
    state: State<M, S>,
    pc: PC,
    status: MachineStatus,
}

#[derive(Debug, Clone)]
pub enum MachineStatus {
    Running,
    ExitedOk,
    ExitedErr(MachineError),
    InvokeCreate(Context),
    InvokeCall(Context, (M256, M256)),
}

#[derive(Debug, Clone)]
pub enum ControlCheck {
    Jump(M256),
}

#[derive(Debug, Clone)]
pub enum Control {
    Stop,
    Jump(M256),
    InvokeCreate(Context),
    InvokeCall(Context, (M256, M256)),
}

impl<M: Memory + Default, S: Storage + Default + Clone> Machine<M, S> {
    pub fn new(context: Context, block: BlockHeader, patch: Patch, depth: usize) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: block,
                patch: patch,

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: AccountState::default(),
                blockhash_state: BlockhashState::default(),
                logs: Vec::new(),

                depth: depth,
            },
        }
    }

    pub fn derive(&self, context: Context) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: self.state.block.clone(),
                patch: self.state.patch.clone(),

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: self.state.account_state.clone(),
                blockhash_state: self.state.blockhash_state.clone(),
                logs: self.state.logs.clone(),

                depth: self.state.depth + 1,
            },
        }
    }

    pub fn commit_account(&mut self, commitment: AccountCommitment<S>) -> Result<(), CommitError> {
        self.state.account_state.commit(commitment)
    }

    pub fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError> {
        self.state.blockhash_state.commit(number, hash)
    }

    #[allow(unused_variables)]
    pub fn apply_sub(&mut self, sub: Machine<M, S>) {
        use std::mem::swap;
        let mut status = MachineStatus::Running;
        swap(&mut status, &mut self.status);
        match status {
            MachineStatus::InvokeCreate(_) => {
                self.apply_create(sub);
            },
            MachineStatus::InvokeCall(_, (out_start, out_len)) => {
                self.apply_call(sub, out_start, out_len);
            },
            _ => panic!(),
        }
    }

    fn apply_create(&mut self, sub: Machine<M, S>) {
        if self.state.available_gas() < sub.state.used_gas {
            panic!();
        }

        match sub.status() {
            MachineStatus::ExitedOk => {
                self.state.account_state = sub.state.account_state;
                self.state.blockhash_state = sub.state.blockhash_state;
                self.state.logs = sub.state.logs;
                self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.refunded_gas = self.state.refunded_gas + sub.state.refunded_gas;
                self.state.account_state.decrease_balance(self.state.context.address,
                                                          sub.state.context.value);
                self.state.account_state.create(sub.state.context.address,
                                                sub.state.context.value,
                                                sub.state.out.as_slice());
            },
            MachineStatus::ExitedErr(_) => {
                self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.stack.pop().unwrap();
                self.state.stack.push(M256::zero()).unwrap();
            },
            _ => panic!(),
        }
    }

    fn apply_call(&mut self, sub: Machine<M, S>, out_start: M256, out_len: M256) {
        if self.state.available_gas() < sub.state.used_gas {
            panic!();
        }

        match sub.status() {
            MachineStatus::ExitedOk => {
                self.state.account_state = sub.state.account_state;
                self.state.blockhash_state = sub.state.blockhash_state;
                self.state.logs = sub.state.logs;
                self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.refunded_gas = self.state.refunded_gas + sub.state.refunded_gas;
                self.state.account_state.decrease_balance(self.state.context.address,
                                                          sub.state.context.value);
                self.state.account_state.increase_balance(sub.state.context.address,
                                                          sub.state.context.value);
                copy_into_memory(&mut self.state.memory, sub.state.out.as_slice(),
                                 out_start, M256::zero(), out_len);
            },
            MachineStatus::ExitedErr(_) => {
                self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.stack.pop().unwrap();
                self.state.stack.push(M256::zero()).unwrap();
            },
            _ => panic!(),
        }
    }

    pub fn check(&self) -> Result<(), EvalError> {
        let instruction = self.pc.peek()?;
        check_opcode(instruction, &self.state).and_then(|v| {
            match v {
                None => Ok(()),
                Some(ControlCheck::Jump(dest)) => {
                    if dest <= M256::from(usize::max_value()) && self.pc.is_valid(dest.into()) {
                        Ok(())
                    } else {
                        Err(EvalError::Machine(MachineError::PC(PCError::BadJumpDest)))
                    }
                }
            }
        })
    }

    pub fn step(&mut self) -> Result<(), RequireError> {
        match &self.status {
            &MachineStatus::Running => (),
            _ => panic!(),
        }

        if self.pc.is_end() {
            self.status = MachineStatus::ExitedOk;
            return Ok(());
        }

        match self.check() {
            Ok(()) => (),
            Err(EvalError::Machine(error)) => {
                self.status = MachineStatus::ExitedErr(error);
                return Ok(());
            },
            Err(EvalError::Require(error)) => {
                return Err(error);
            },
        };

        let instruction = self.pc.peek().unwrap();
        let position = self.pc.position();
        let memory_cost = memory_cost(instruction, &self.state);
        let memory_gas = memory_gas(memory_cost);
        let gas_cost = gas_cost(instruction, &self.state);
        let gas_stipend = gas_stipend(instruction, &self.state);
        let gas_refund = gas_refund(instruction, &self.state);
        let after_gas = self.state.context.gas_limit - memory_gas - self.state.used_gas - gas_cost + gas_stipend;

        match extra_check_opcode(instruction, &self.state, gas_stipend, after_gas) {
            Ok(()) => (),
            Err(EvalError::Machine(error)) => {
                self.status = MachineStatus::ExitedErr(error);
                return Ok(());
            },
            Err(EvalError::Require(error)) => {
                return Err(error);
            },
        }

        if self.state.context.gas_limit < memory_gas + self.state.used_gas + gas_cost - gas_stipend {
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
            return Ok(());
        }

        let instruction = self.pc.read().unwrap();
        let result = run_opcode((instruction, position),
                                &mut self.state, gas_stipend, after_gas);

        self.state.used_gas = self.state.used_gas + gas_cost - gas_stipend;
        self.state.memory_cost = memory_cost;
        self.state.refunded_gas = self.state.refunded_gas + gas_refund;

        match result {
            None => Ok(()),
            Some(Control::Jump(dest)) => {
                self.pc.jump(dest.into()).unwrap();
                Ok(())
            },
            Some(Control::InvokeCall(context, (from, len))) => {
                self.status = MachineStatus::InvokeCall(context, (from, len));
                Ok(())
            },
            Some(Control::InvokeCreate(context)) => {
                self.status = MachineStatus::InvokeCreate(context);
                Ok(())
            },
            Some(Control::Stop) => {
                self.status = MachineStatus::ExitedOk;
                Ok(())
            },
        }
    }

    pub fn state(&self) -> &State<M, S> {
        &self.state
    }

    pub fn status(&self) -> MachineStatus {
        self.status.clone()
    }
}
<commit_msg>Problem: failing tests Solution: patch for tests<commit_after>use utils::bigint::M256;
use utils::gas::Gas;
use super::commit::{AccountState, BlockhashState};
use super::errors::{RequireError, MachineError, CommitError, EvalError, PCError};
use super::{Stack, Context, BlockHeader, Patch, PC, Storage, Memory, AccountCommitment, Log};

use self::check::{check_opcode, extra_check_opcode};
use self::run::run_opcode;
use self::cost::{gas_refund, gas_stipend, gas_cost, memory_cost, memory_gas};
use self::utils::copy_into_memory;

mod cost;
mod run;
mod check;
mod utils;

/// A VM state without PC.
pub struct State<M, S> {
    pub memory: M,
    pub stack: Stack,

    pub context: Context,
    pub block: BlockHeader,
    pub patch: Patch,

    pub out: Vec<u8>,

    pub memory_cost: Gas,
    pub used_gas: Gas,
    pub refunded_gas: Gas,

    pub account_state: AccountState<S>,
    pub blockhash_state: BlockhashState,
    pub logs: Vec<Log>,

    pub depth: usize,
}

impl<M, S> State<M, S> {
    pub fn memory_gas(&self) -> Gas {
        memory_gas(self.memory_cost)
    }

    pub fn available_gas(&self) -> Gas {
        self.context.gas_limit - self.memory_gas() - self.used_gas
    }
}

/// A VM state with PC.
pub struct Machine<M, S> {
    state: State<M, S>,
    pc: PC,
    status: MachineStatus,
}

#[derive(Debug, Clone)]
pub enum MachineStatus {
    Running,
    ExitedOk,
    ExitedErr(MachineError),
    InvokeCreate(Context),
    InvokeCall(Context, (M256, M256)),
}

#[derive(Debug, Clone)]
pub enum ControlCheck {
    Jump(M256),
}

#[derive(Debug, Clone)]
pub enum Control {
    Stop,
    Jump(M256),
    InvokeCreate(Context),
    InvokeCall(Context, (M256, M256)),
}

impl<M: Memory + Default, S: Storage + Default + Clone> Machine<M, S> {
    pub fn new(context: Context, block: BlockHeader, patch: Patch, depth: usize) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: block,
                patch: patch,

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: AccountState::default(),
                blockhash_state: BlockhashState::default(),
                logs: Vec::new(),

                depth: depth,
            },
        }
    }

    pub fn derive(&self, context: Context) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: self.state.block.clone(),
                patch: self.state.patch.clone(),

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: self.state.account_state.clone(),
                blockhash_state: self.state.blockhash_state.clone(),
                logs: self.state.logs.clone(),

                depth: self.state.depth + 1,
            },
        }
    }

    pub fn commit_account(&mut self, commitment: AccountCommitment<S>) -> Result<(), CommitError> {
        self.state.account_state.commit(commitment)
    }

    pub fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError> {
        self.state.blockhash_state.commit(number, hash)
    }

    #[allow(unused_variables)]
    pub fn apply_sub(&mut self, sub: Machine<M, S>) {
        use std::mem::swap;
        let mut status = MachineStatus::Running;
        swap(&mut status, &mut self.status);
        match status {
            MachineStatus::InvokeCreate(_) => {
                self.apply_create(sub);
            },
            MachineStatus::InvokeCall(_, (out_start, out_len)) => {
                self.apply_call(sub, out_start, out_len);
            },
            _ => panic!(),
        }
    }

    fn apply_create(&mut self, sub: Machine<M, S>) {
        if self.state.available_gas() < sub.state.used_gas {
            panic!();
        }

        match sub.status() {
            MachineStatus::ExitedOk => {
                self.state.account_state = sub.state.account_state;
                self.state.blockhash_state = sub.state.blockhash_state;
                self.state.logs = sub.state.logs;
                self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.refunded_gas = self.state.refunded_gas + sub.state.refunded_gas;
                self.state.account_state.decrease_balance(self.state.context.address,
                                                          sub.state.context.value);
                self.state.account_state.create(sub.state.context.address,
                                                sub.state.context.value,
                                                sub.state.out.as_slice());
            },
            MachineStatus::ExitedErr(_) => {
                // self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.stack.pop().unwrap();
                self.state.stack.push(M256::zero()).unwrap();
            },
            _ => panic!(),
        }
    }

    fn apply_call(&mut self, sub: Machine<M, S>, out_start: M256, out_len: M256) {
        if self.state.available_gas() < sub.state.used_gas {
            panic!();
        }

        match sub.status() {
            MachineStatus::ExitedOk => {
                self.state.account_state = sub.state.account_state;
                self.state.blockhash_state = sub.state.blockhash_state;
                self.state.logs = sub.state.logs;
                self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.refunded_gas = self.state.refunded_gas + sub.state.refunded_gas;
                self.state.account_state.decrease_balance(self.state.context.address,
                                                          sub.state.context.value);
                self.state.account_state.increase_balance(sub.state.context.address,
                                                          sub.state.context.value);
                copy_into_memory(&mut self.state.memory, sub.state.out.as_slice(),
                                 out_start, M256::zero(), out_len);
            },
            MachineStatus::ExitedErr(_) => {
                // self.state.used_gas = self.state.used_gas + sub.state.used_gas;
                self.state.stack.pop().unwrap();
                self.state.stack.push(M256::from(1u64)).unwrap();
            },
            _ => panic!(),
        }
    }

    pub fn check(&self) -> Result<(), EvalError> {
        let instruction = self.pc.peek()?;
        check_opcode(instruction, &self.state).and_then(|v| {
            match v {
                None => Ok(()),
                Some(ControlCheck::Jump(dest)) => {
                    if dest <= M256::from(usize::max_value()) && self.pc.is_valid(dest.into()) {
                        Ok(())
                    } else {
                        Err(EvalError::Machine(MachineError::PC(PCError::BadJumpDest)))
                    }
                }
            }
        })
    }

    pub fn step(&mut self) -> Result<(), RequireError> {
        match &self.status {
            &MachineStatus::Running => (),
            _ => panic!(),
        }

        if self.pc.is_end() {
            self.status = MachineStatus::ExitedOk;
            return Ok(());
        }

        match self.check() {
            Ok(()) => (),
            Err(EvalError::Machine(error)) => {
                self.status = MachineStatus::ExitedErr(error);
                return Ok(());
            },
            Err(EvalError::Require(error)) => {
                return Err(error);
            },
        };

        let instruction = self.pc.peek().unwrap();
        let position = self.pc.position();
        let memory_cost = memory_cost(instruction, &self.state);
        let memory_gas = memory_gas(memory_cost);
        let gas_cost = gas_cost(instruction, &self.state);
        let gas_stipend = gas_stipend(instruction, &self.state);
        let gas_refund = gas_refund(instruction, &self.state);
        let after_gas = self.state.context.gas_limit - memory_gas - self.state.used_gas - gas_cost + gas_stipend;

        match extra_check_opcode(instruction, &self.state, gas_stipend, after_gas) {
            Ok(()) => (),
            Err(EvalError::Machine(error)) => {
                self.status = MachineStatus::ExitedErr(error);
                return Ok(());
            },
            Err(EvalError::Require(error)) => {
                return Err(error);
            },
        }

        if self.state.context.gas_limit < memory_gas + self.state.used_gas + gas_cost - gas_stipend {
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
            return Ok(());
        }

        let instruction = self.pc.read().unwrap();
        let result = run_opcode((instruction, position),
                                &mut self.state, gas_stipend, after_gas);

        self.state.used_gas = self.state.used_gas + gas_cost - gas_stipend;
        self.state.memory_cost = memory_cost;
        self.state.refunded_gas = self.state.refunded_gas + gas_refund;

        match result {
            None => Ok(()),
            Some(Control::Jump(dest)) => {
                self.pc.jump(dest.into()).unwrap();
                Ok(())
            },
            Some(Control::InvokeCall(context, (from, len))) => {
                self.status = MachineStatus::InvokeCall(context, (from, len));
                Ok(())
            },
            Some(Control::InvokeCreate(context)) => {
                self.status = MachineStatus::InvokeCreate(context);
                Ok(())
            },
            Some(Control::Stop) => {
                self.status = MachineStatus::ExitedOk;
                Ok(())
            },
        }
    }

    pub fn state(&self) -> &State<M, S> {
        &self.state
    }

    pub fn status(&self) -> MachineStatus {
        self.status.clone()
    }
}
<|endoftext|>


<commit_before>use redox::*;

// nvp implementation version
pub const NV_VERSION: i32 = 0;

// nvlist header
//#[derive(Debug)]
pub struct NvList {
    pub version: i32,
    pub nvflag:  u32, // persistent flags
    pub pairs: Vec<(String, NvValue)>,
}

impl NvList {
    pub fn new(nvflag: u32) -> Self {
        NvList {
            version: NV_VERSION,
            nvflag: nvflag,
            pairs: Vec::new(),
        }
    }

    pub fn find(&self, name: &str) -> Option<&NvValue> {
        for pair in &self.pairs {
            if pair.0 == name {
                return Some(&pair.1);
            }
        }
        None
    }

    pub fn find_mut(&mut self, name: &str) -> Option<&mut NvValue> {
        for pair in &mut self.pairs {
            if pair.0 == name {
                return Some(&mut pair.1);
            }
        }
        None
    }
}

impl fmt::Debug for NvList {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "NvList {{ version: {:X}, nvflag: {:X}, pairs: [\n", self.version, self.nvflag));
        for &(ref name, ref value) in &self.pairs {
            if name.is_empty() { break; }
            try!(write!(f, "{} : {:?}\n", name, value));
        }
        try!(write!(f, "] }}\n"));
        Ok(())
    }
}

// TODO Auto implement Debug. format! currently crashes with big u32 values
//#[derive(Debug)]
pub enum NvValue {
    Unknown,
    Boolean,
    Byte(u8),
    Int16(i16),
    Uint16(u16),
    Int32(i32),
    Uint32(u32),
    Int64(i64),
    Uint64(u64),
    String(String),
    ByteArray(Vec<u8>),
    Int16Array(Vec<i16>),
    Uint16Array(Vec<u16>),
    Int32Array(Vec<i32>),
    Uint32Array(Vec<u32>),
    Int64Array(Vec<i64>),
    Uint64Array(Vec<u64>),
    StringArray(Vec<String>),
    HrTime(i64),
    NvList(Box<NvList>),
    NvListArray(Vec<Box<NvList>>),
    BooleanValue(bool),
    Int8(i8),
    Uint8(u8),
    BooleanArray(Vec<bool>),
    Int8Array(Vec<i8>),
    Uint8Array(Vec<u8>),
}

impl NvValue {
    pub fn data_type(&self) -> DataType {
        match *self {
            NvValue::Unknown => DataType::Unknown,
            NvValue::Boolean => DataType::Boolean,
            NvValue::Byte(_) => DataType::Byte,
            NvValue::Int16(_) => DataType::Int16,
            NvValue::Uint16(_) => DataType::Uint16,
            NvValue::Int32(_) => DataType::Int32,
            NvValue::Uint32(_) => DataType::Uint32,
            NvValue::Int64(_) => DataType::Int64,
            NvValue::Uint64(_) => DataType::Uint64,
            NvValue::String(_) => DataType::String,
            NvValue::ByteArray(_) => DataType::ByteArray,
            NvValue::Int16Array(_) => DataType::Int16Array,
            NvValue::Uint16Array(_) => DataType::Uint16Array,
            NvValue::Int32Array(_) => DataType::Int32Array,
            NvValue::Uint32Array(_) => DataType::Uint32Array,
            NvValue::Int64Array(_) => DataType::Int64Array,
            NvValue::Uint64Array(_) => DataType::Uint64Array,
            NvValue::StringArray(_) => DataType::StringArray,
            NvValue::HrTime(_) => DataType::HrTime,
            NvValue::NvList(_) => DataType::NvList,
            NvValue::NvListArray(_) => DataType::NvListArray,
            NvValue::BooleanValue(_) => DataType::BooleanValue,
            NvValue::Int8(_) => DataType::Int8,
            NvValue::Uint8(_) => DataType::Uint8,
            NvValue::BooleanArray(_) => DataType::BooleanArray,
            NvValue::Int8Array(_) => DataType::Int8Array,
            NvValue::Uint8Array(_) => DataType::Uint8Array,
        }
    }

    pub fn num_elements(&self) -> usize {
        match *self {
            NvValue::Unknown => 1,
            NvValue::Boolean => 1,
            NvValue::Byte(_) => 1,
            NvValue::Int16(_) => 1,
            NvValue::Uint16(_) => 1,
            NvValue::Int32(_) => 1,
            NvValue::Uint32(_) => 1,
            NvValue::Int64(_) => 1,
            NvValue::Uint64(_) => 1,
            NvValue::String(_) => 1,
            NvValue::ByteArray(ref a) => a.len(),
            NvValue::Int16Array(ref a) => a.len(),
            NvValue::Uint16Array(ref a) => a.len(),
            NvValue::Int32Array(ref a) => a.len(),
            NvValue::Uint32Array(ref a) => a.len(),
            NvValue::Int64Array(ref a) => a.len(),
            NvValue::Uint64Array(ref a) => a.len(),
            NvValue::StringArray(ref a) => a.len(),
            NvValue::HrTime(_) => 1,
            NvValue::NvList(_) => 1,
            NvValue::NvListArray(ref a) => a.len(),
            NvValue::BooleanValue(_) => 1,
            NvValue::Int8(_) => 1,
            NvValue::Uint8(_) => 1,
            NvValue::BooleanArray(ref a) => a.len(),
            NvValue::Int8Array(ref a) => a.len(),
            NvValue::Uint8Array(ref a) => a.len(),
        }
    }
}

impl fmt::Debug for NvValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            NvValue::Int64(v) => write!(f, "Int64(0x{:X})", v),
            NvValue::Uint64(v) => write!(f, "Uint64(0x{:X})", v),
            NvValue::NvList(ref v) => write!(f, "NvList({:?})", **v),
            NvValue::NvListArray(ref v) => {
                try!(write!(f, "NvListArray(["));
                for nv_list in v {
                    try!(write!(f, "NvList({:?})", **nv_list));
                }
                write!(f, "])")
            },
            NvValue::String(ref v) => { write!(f, "String({})", v) },
            _ => write!(f, "{:?}", self),
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub enum DataType {
    Unknown = 0,
    Boolean,
    Byte,
    Int16,
    Uint16,
    Int32,
    Uint32,
    Int64,
    Uint64,
    String,
    ByteArray,
    Int16Array,
    Uint16Array,
    Int32Array,
    Uint32Array,
    Int64Array,
    Uint64Array,
    StringArray,
    HrTime,
    NvList,
    NvListArray,
    BooleanValue,
    Int8,
    Uint8,
    BooleanArray,
    Int8Array,
    Uint8Array,
}

impl DataType {
    pub fn from_u8(u: u8) -> Option<DataType> {
        match u {
            0 => Some(DataType::Unknown),
            1 => Some(DataType::Boolean),
            2 => Some(DataType::Byte),
            3 => Some(DataType::Int16),
            4 => Some(DataType::Uint16),
            5 => Some(DataType::Int32),
            6 => Some(DataType::Uint32),
            7 => Some(DataType::Int64),
            8 => Some(DataType::Uint64),
            9 => Some(DataType::String),
            10 => Some(DataType::ByteArray),
            11 => Some(DataType::Int16Array),
            12 => Some(DataType::Uint16Array),
            13 => Some(DataType::Int32Array),
            14 => Some(DataType::Uint32Array),
            15 => Some(DataType::Int64Array),
            16 => Some(DataType::Uint64Array),
            17 => Some(DataType::StringArray),
            18 => Some(DataType::HrTime),
            19 => Some(DataType::NvList),
            20 => Some(DataType::NvListArray),
            21 => Some(DataType::BooleanValue),
            22 => Some(DataType::Int8),
            23 => Some(DataType::Uint8),
            24 => Some(DataType::BooleanArray),
            25 => Some(DataType::Int8Array),
            26 => Some(DataType::Uint8Array),
            _ => None,
        }
    }

    pub fn to_u8(self) -> u8 {
        match self {
            DataType::Unknown => 0,
            DataType::Boolean => 1,
            DataType::Byte => 2,
            DataType::Int16 => 3,
            DataType::Uint16 => 4,
            DataType::Int32 => 5,
            DataType::Uint32 => 6,
            DataType::Int64 => 7,
            DataType::Uint64 => 8,
            DataType::String => 9,
            DataType::ByteArray => 10,
            DataType::Int16Array => 11,
            DataType::Uint16Array => 12,
            DataType::Int32Array => 13,
            DataType::Uint32Array => 14,
            DataType::Int64Array => 15,
            DataType::Uint64Array => 16,
            DataType::StringArray => 17,
            DataType::HrTime => 18,
            DataType::NvList => 19,
            DataType::NvListArray => 20,
            DataType::BooleanValue => 21,
            DataType::Int8 => 22,
            DataType::Uint8 => 23,
            DataType::BooleanArray => 24,
            DataType::Int8Array => 25,
            DataType::Uint8Array => 26,
        }
    }
}
<commit_msg>Pimped out nvpairs for more convenience<commit_after>use redox::*;

// nvp implementation version
pub const NV_VERSION: i32 = 0;

// nvlist header
//#[derive(Debug)]
pub struct NvList {
    pub version: i32,
    pub nvflag:  u32, // persistent flags
    pub pairs: Vec<(String, NvValue)>,
}

impl NvList {
    pub fn new(nvflag: u32) -> Self {
        NvList {
            version: NV_VERSION,
            nvflag: nvflag,
            pairs: Vec::new(),
        }
    }

    pub fn find(&self, name: &str) -> Option<&NvValue> {
        for pair in &self.pairs {
            if pair.0 == name {
                return Some(&pair.1);
            }
        }
        None
    }

    pub fn find_mut(&mut self, name: &str) -> Option<&mut NvValue> {
        for pair in &mut self.pairs {
            if pair.0 == name {
                return Some(&mut pair.1);
            }
        }
        None
    }

    pub fn get<'a, T: GetNvValue<'a>>(&'a self, name: &str) -> Option<T> {
        self.find(name).and_then(|x| GetNvValue::get(x))
    }
}

impl fmt::Debug for NvList {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "NvList {{ version: {:X}, nvflag: {:X}, pairs: [\n", self.version, self.nvflag));
        for &(ref name, ref value) in &self.pairs {
            if name.is_empty() { break; }
            try!(write!(f, "{} : {:?}\n", name, value));
        }
        try!(write!(f, "] }}\n"));
        Ok(())
    }
}

// TODO Auto implement Debug. format! currently crashes with big u32 values
//#[derive(Debug)]
pub enum NvValue {
    Unknown,
    Boolean,
    Byte(u8),
    Int16(i16),
    Uint16(u16),
    Int32(i32),
    Uint32(u32),
    Int64(i64),
    Uint64(u64),
    String(String),
    ByteArray(Vec<u8>),
    Int16Array(Vec<i16>),
    Uint16Array(Vec<u16>),
    Int32Array(Vec<i32>),
    Uint32Array(Vec<u32>),
    Int64Array(Vec<i64>),
    Uint64Array(Vec<u64>),
    StringArray(Vec<String>),
    HrTime(i64),
    NvList(NvList),
    NvListArray(Vec<NvList>),
    BooleanValue(bool),
    Int8(i8),
    Uint8(u8),
    BooleanArray(Vec<bool>),
    Int8Array(Vec<i8>),
    Uint8Array(Vec<u8>),
}

impl NvValue {
    pub fn data_type(&self) -> DataType {
        match *self {
            NvValue::Unknown => DataType::Unknown,
            NvValue::Boolean => DataType::Boolean,
            NvValue::Byte(_) => DataType::Byte,
            NvValue::Int16(_) => DataType::Int16,
            NvValue::Uint16(_) => DataType::Uint16,
            NvValue::Int32(_) => DataType::Int32,
            NvValue::Uint32(_) => DataType::Uint32,
            NvValue::Int64(_) => DataType::Int64,
            NvValue::Uint64(_) => DataType::Uint64,
            NvValue::String(_) => DataType::String,
            NvValue::ByteArray(_) => DataType::ByteArray,
            NvValue::Int16Array(_) => DataType::Int16Array,
            NvValue::Uint16Array(_) => DataType::Uint16Array,
            NvValue::Int32Array(_) => DataType::Int32Array,
            NvValue::Uint32Array(_) => DataType::Uint32Array,
            NvValue::Int64Array(_) => DataType::Int64Array,
            NvValue::Uint64Array(_) => DataType::Uint64Array,
            NvValue::StringArray(_) => DataType::StringArray,
            NvValue::HrTime(_) => DataType::HrTime,
            NvValue::NvList(_) => DataType::NvList,
            NvValue::NvListArray(_) => DataType::NvListArray,
            NvValue::BooleanValue(_) => DataType::BooleanValue,
            NvValue::Int8(_) => DataType::Int8,
            NvValue::Uint8(_) => DataType::Uint8,
            NvValue::BooleanArray(_) => DataType::BooleanArray,
            NvValue::Int8Array(_) => DataType::Int8Array,
            NvValue::Uint8Array(_) => DataType::Uint8Array,
        }
    }

    pub fn num_elements(&self) -> usize {
        match *self {
            NvValue::Unknown => 1,
            NvValue::Boolean => 1,
            NvValue::Byte(_) => 1,
            NvValue::Int16(_) => 1,
            NvValue::Uint16(_) => 1,
            NvValue::Int32(_) => 1,
            NvValue::Uint32(_) => 1,
            NvValue::Int64(_) => 1,
            NvValue::Uint64(_) => 1,
            NvValue::String(_) => 1,
            NvValue::ByteArray(ref a) => a.len(),
            NvValue::Int16Array(ref a) => a.len(),
            NvValue::Uint16Array(ref a) => a.len(),
            NvValue::Int32Array(ref a) => a.len(),
            NvValue::Uint32Array(ref a) => a.len(),
            NvValue::Int64Array(ref a) => a.len(),
            NvValue::Uint64Array(ref a) => a.len(),
            NvValue::StringArray(ref a) => a.len(),
            NvValue::HrTime(_) => 1,
            NvValue::NvList(_) => 1,
            NvValue::NvListArray(ref a) => a.len(),
            NvValue::BooleanValue(_) => 1,
            NvValue::Int8(_) => 1,
            NvValue::Uint8(_) => 1,
            NvValue::BooleanArray(ref a) => a.len(),
            NvValue::Int8Array(ref a) => a.len(),
            NvValue::Uint8Array(ref a) => a.len(),
        }
    }
}

impl fmt::Debug for NvValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            NvValue::Int64(v) => write!(f, "Int64(0x{:X})", v),
            NvValue::Uint64(v) => write!(f, "Uint64(0x{:X})", v),
            NvValue::NvList(ref v) => write!(f, "NvList({:?})", v),
            NvValue::NvListArray(ref v) => {
                try!(write!(f, "NvListArray(["));
                for nv_list in v {
                    try!(write!(f, "NvList({:?})", nv_list));
                }
                write!(f, "])")
            },
            NvValue::String(ref v) => { write!(f, "String({})", v) },
            _ => write!(f, "{:?}", self),
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub enum DataType {
    Unknown = 0,
    Boolean,
    Byte,
    Int16,
    Uint16,
    Int32,
    Uint32,
    Int64,
    Uint64,
    String,
    ByteArray,
    Int16Array,
    Uint16Array,
    Int32Array,
    Uint32Array,
    Int64Array,
    Uint64Array,
    StringArray,
    HrTime,
    NvList,
    NvListArray,
    BooleanValue,
    Int8,
    Uint8,
    BooleanArray,
    Int8Array,
    Uint8Array,
}

impl DataType {
    pub fn from_u8(u: u8) -> Option<DataType> {
        match u {
            0 => Some(DataType::Unknown),
            1 => Some(DataType::Boolean),
            2 => Some(DataType::Byte),
            3 => Some(DataType::Int16),
            4 => Some(DataType::Uint16),
            5 => Some(DataType::Int32),
            6 => Some(DataType::Uint32),
            7 => Some(DataType::Int64),
            8 => Some(DataType::Uint64),
            9 => Some(DataType::String),
            10 => Some(DataType::ByteArray),
            11 => Some(DataType::Int16Array),
            12 => Some(DataType::Uint16Array),
            13 => Some(DataType::Int32Array),
            14 => Some(DataType::Uint32Array),
            15 => Some(DataType::Int64Array),
            16 => Some(DataType::Uint64Array),
            17 => Some(DataType::StringArray),
            18 => Some(DataType::HrTime),
            19 => Some(DataType::NvList),
            20 => Some(DataType::NvListArray),
            21 => Some(DataType::BooleanValue),
            22 => Some(DataType::Int8),
            23 => Some(DataType::Uint8),
            24 => Some(DataType::BooleanArray),
            25 => Some(DataType::Int8Array),
            26 => Some(DataType::Uint8Array),
            _ => None,
        }
    }

    pub fn to_u8(self) -> u8 {
        match self {
            DataType::Unknown => 0,
            DataType::Boolean => 1,
            DataType::Byte => 2,
            DataType::Int16 => 3,
            DataType::Uint16 => 4,
            DataType::Int32 => 5,
            DataType::Uint32 => 6,
            DataType::Int64 => 7,
            DataType::Uint64 => 8,
            DataType::String => 9,
            DataType::ByteArray => 10,
            DataType::Int16Array => 11,
            DataType::Uint16Array => 12,
            DataType::Int32Array => 13,
            DataType::Uint32Array => 14,
            DataType::Int64Array => 15,
            DataType::Uint64Array => 16,
            DataType::StringArray => 17,
            DataType::HrTime => 18,
            DataType::NvList => 19,
            DataType::NvListArray => 20,
            DataType::BooleanValue => 21,
            DataType::Int8 => 22,
            DataType::Uint8 => 23,
            DataType::BooleanArray => 24,
            DataType::Int8Array => 25,
            DataType::Uint8Array => 26,
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub trait GetNvValue<'a>: Sized {
    fn get(value: &'a NvValue) -> Option<Self>;
}

impl<'a> GetNvValue<'a> for bool {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::BooleanValue(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for u8 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Byte(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for u16 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Uint16(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for u32 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Uint32(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for u64 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Uint64(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for i16 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Int16(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for i32 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Int32(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for i64 {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::Int64(v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for &'a NvList {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::NvList(ref v) => Some(v),
            _ => None,
        }
    }
}

impl<'a> GetNvValue<'a> for &'a Vec<NvList> {
    fn get(value: &'a NvValue) -> Option<Self> {
        match *value {
            NvValue::NvListArray(ref v) => Some(v),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/24_game
// with a recursive descent parser for a simple calculator (+ - * /)
// using the shunting yard algorithm as explained on
// http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
// It follows operator precedence (i.e. 2 + 3 * 3 = 11),
// understands negation (-5 + 6 = 1), ignores whitespace
// and allows the use of parentheses

#![feature(macro_rules)]
use std::char::to_digit;

#[cfg(not(test))]
use std::rand;

#[cfg(not(test))]
fn main() {
    let mut rng=rand::task_rng();
    let mut input = std::io::stdin();

    loop {
        let mut sample = rand::sample(&mut rng, range(1u, 10), 4);

        println!("make 24 by combining the following 4 numbers with + - * / or (q)uit");
        println!("{}", sample);

        let line = input.read_line().unwrap();
        match line.as_slice().trim() {
            "q" => break,
            input if check_values(sample.as_mut_slice(), input) => {
                    let mut p = Parser :: new(input);
                    match p.parse() {
                        Ok(i) if i==24f32 => println!("you made it!"),
                        Ok(i) => println!("you entered {}, try again!", i),
                        Err(s)  => println!("{}",s)
                    };
                }
            _ => println!("unrecognized input, try again")
        }
    }
}

// Returns true if the entered expression uses the values contained in sample
fn check_values(sample:&mut [uint], input:&str) -> bool {
    let lex=Lexer::new(input);

    let mut numbers_used : Vec<uint> = lex.filter_map(|a| match a {
                                                        Int(i)  => Some(i),
                                                        _       => None
                                                    }).collect();
    numbers_used.sort();
    sample.sort();
    numbers_used.as_slice() == sample
}

// the tokens that our parser is going to recognize
#[deriving(PartialEq,Eq,Show)]
enum Token {LParen, RParen, Plus, Minus, Slash, Star, Int(uint)}

impl Token {
   // are tokens associated to a binary operation?
   fn is_binary(&self) -> bool {
        match self {
            &Plus | &Minus | &Slash | &Star => true,
            _ => false
        }
    }
}

#[inline]
// map a character to its corresponding token
fn single_char_to_token(ch:Option<char>) -> Option<Token> {
    match ch {
            Some('(') => Some(LParen),
            Some(')') => Some(RParen),
            Some('+') => Some(Plus),
            Some('-') => Some(Minus),
            Some('/') => Some(Slash),
            Some('*') => Some(Star),
            _         => None
    }
}

// Lexer reads an expression like (a + b) / c * d
// as an iterator on the tokens that compose it
// Int(a), LParen, Plus, Int(b), RParen...
struct Lexer<'a> {
    input_str:  &'a str,
    position:   uint
}

impl <'a> Lexer<'a> {
    fn new(input_str: &'a str) -> Lexer<'a> {
        Lexer { input_str: input_str, position: 0u }
    }

    fn expect(&mut self, expected:&[Token]) -> Result<Token, String> {
        let n = self.position;
        match self.next() {
            Some(a) if expected.contains(&a)  => Ok(a),
            other  => Err(format!("Parsing error: {} was unexpected at position {}", other, n))
        }
    }
}

impl <'a> Iterator<Token> for Lexer<'a> {
    fn next(&mut self) -> Option<Token> {
        let remaining_input=self.input_str.slice_from(self.position);
        let ch_iter=remaining_input.chars();

        // skip spaces and update position
        let mut spaces=ch_iter.take_while(|ch| ch.is_whitespace());
        let n_spaces=spaces.count();
        self.position+=n_spaces;
        let mut trimmed=ch_iter.skip(n_spaces);

        // read digits (note: not checking length, risks overflowing uint)
        let digits=trimmed.take_while(|d| d.is_digit());
        // transform char digits to a uint and update position
        let val=digits.map(|c| to_digit(c, 10).unwrap())
            .fold(0u, |a, b| {
                self.position+=1;
                b + a * 10
            });

        let ret = if val > 0 {
            Some(Int(val))
        } else {
            // not a value. Read other tokens
            let cur=trimmed.next();
            self.position +=1;
            single_char_to_token(cur)
        };
        ret
    }
}

// operators are a "higher level" concept than tokens
// as they define the semantics of the expression language
// e.g. token "Minus" can correspond to the unary Neg Operator (-a)
// or to the binary Sub operator (a - b)
#[deriving(PartialEq,Eq)]
enum Operator {Neg, Add, Sub, Mul, Div, Sentinel}

#[deriving(PartialEq,Eq)]
struct OperatorPrecedence(Operator);

impl Operator {
     fn precedence(self) -> OperatorPrecedence  {
        OperatorPrecedence(self)
    }
}

impl OperatorPrecedence {
    fn prec(self) -> uint {
        match self {
            OperatorPrecedence(Sentinel) => 0u,
            OperatorPrecedence(Add) | OperatorPrecedence(Sub) => 1u,
            OperatorPrecedence(Neg)        => 2u,
            OperatorPrecedence(Mul) | OperatorPrecedence(Div) => 3u
        }
    }
}

/*
    Operator precedence for binary operators:
    * if x has higher precedence than y precedence for x > precedence for y
    * if x and y have equal precedence the first one has precedence
    e.g. in expression (4 / 2 * 2) operators * and / have the same precedence,
    but the operations must be performed in the order they appear
    (division first, multiplication second) otherwise results are different
*/
impl PartialOrd for OperatorPrecedence {
    fn lt(&self, other: &OperatorPrecedence) -> bool {
        match (self, other) {
            (&OperatorPrecedence(Mul), &OperatorPrecedence(Div)) => false,
            (&OperatorPrecedence(Div), &OperatorPrecedence(Mul)) => false,
            (&OperatorPrecedence(Add), &OperatorPrecedence(Sub)) => false,
            (&OperatorPrecedence(Sub), &OperatorPrecedence(Add)) => false,
            _  => self.prec() < other.prec()
        }
    }

    fn gt(&self, other: &OperatorPrecedence) -> bool {
        match (self, other) {
            (&OperatorPrecedence(Mul), &OperatorPrecedence(Div)) => true,
            (&OperatorPrecedence(Div), &OperatorPrecedence(Mul)) => true,
            (&OperatorPrecedence(Add), &OperatorPrecedence(Sub)) => true,
            (&OperatorPrecedence(Sub), &OperatorPrecedence(Add)) => true,
            _          => self.prec() > other.prec()
        }
    }
}

// recursive descent parser
// with the shunting yard algorithm as explained on
// http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
// I followed the names of the methods as closely as possible vs the pseudo-code
// that illustrates the algorithm
struct Parser<'a> {
    operators: Vec<Operator>,
    operands:  Vec<f32>,
    lexer:     Lexer<'a>
}

impl <'a> Parser<'a> {
    fn new(input_str: &'a str) -> Parser<'a> {
        Parser {
            operators:  Vec::new(),
            operands:   Vec::new(),
            lexer:      Lexer::new(input_str)
        }
    }

    fn parse(&mut self) -> Result<f32, String> {
        self.operators.push(Sentinel);
        try!(self.e());
        let res=self.operands.last();
        let ret=match res {
            Some(&r) => Ok(r),
            None    => Err("something went wrong, got no result".to_string())
        };
        ret
    }

    fn e(&mut self) -> Result<(), String> {
        try!(self.p());

        let mut n=self.lexer.next();

        while n.is_some() && n.unwrap().is_binary() {
            match n {
                Some(Plus) => self.push_operator(Add),
                Some(Minus) => self.push_operator(Sub),
                Some(Star) => self.push_operator(Mul),
                Some(Slash) => self.push_operator(Div),
                _ => unreachable!() //shouldn't get there (there are no other
                                    // binary operators
            };
            try!(self.p());

            let mut n_peek = self.lexer.peekable();
            if n_peek.peek().is_none() || !n_peek.peek().unwrap().is_binary() { break; }
            n = self.lexer.next();
        }
        while self.operators.last().is_some() && self.operators.last().unwrap() != &Sentinel {
            self.pop_operator();
        }
        Ok(())
    }

    fn p(&mut self) -> Result<(), String> {
        match self.lexer.next() {
            Some(Int(n)) => {
                self.operands.push(n as f32);
            },
            Some(LParen) => {
                self.operators.push(Sentinel);
                try!(self.e());
                try!(self.lexer.expect(&[RParen]));
                self.operators.pop();
            },
            Some(Minus) => {
                self.push_operator(Neg);
                try!(self.p());
            },
            Some(e) => return Err(format!("unexpected token {}", e)),
            _       => return Err("unexpected end of command".to_string())
            //Some(Minus) =>
        }
        Ok(())
    }

    fn pop_operator(&mut self) {
        match self.operators.pop() {
            Some(Add) => self.binary_op(|t1,t2| t1+t2),
            Some(Sub) => self.binary_op(|t1,t2| t1-t2),
            Some(Mul) => self.binary_op(|t1,t2| t1*t2),
            Some(Div) => self.binary_op(|t1,t2| t1/t2),
            Some(Neg) => self.unary_op(|t1| -t1),
            _         => unreachable!()
            }
    }

    fn push_operator(&mut self, op:Operator) {
        match self.operators.last() {
            Some(&a) if a.precedence() > op.precedence() => self.pop_operator(),
            _ => ()
        }
        self.operators.push(op);
    }

    #[inline]
    fn binary_op(&mut self, op:|f32,f32| -> f32) {
        let t1=self.operands.pop().unwrap();
        let t2=self.operands.pop().unwrap();
        self.operands.push(op(t2,t1));
    }

    #[inline]
    fn unary_op(&mut self, op:|f32| -> f32) {
        let t1=self.operands.pop().unwrap();
        self.operands.push(op(t1));
    }
}

#[test]
fn test_precedence() {
    assert!(Mul.precedence() > Add.precedence());
    assert!(Mul.precedence() > Div.precedence());
    assert!((Mul.precedence() < Div.precedence())==false);
}

#[test]
fn lexer_iter() {
    // test read token and character's position in the iterator
    macro_rules! test_tok( ($tok:ident, $exp_tok:expr, $exp_pos:expr) =>
        ( assert_eq!(($tok.next(), $tok.position), (Some($exp_tok), $exp_pos));))

    let mut tok=Lexer::new("  15 + 4");
    test_tok!(tok, Int(15), 4);
    test_tok!(tok, Plus, 6);
    let read=tok.expect(&[LParen,Int(4),RParen]);
    assert_eq!(read, Ok(Int(4)));

    let mut tok=Lexer::new("");
    assert_eq!(tok.next(), None);

    let mut tok=Lexer::new("     ");
    assert_eq!(tok.next(), None);

    let mut tok=Lexer::new("2 * (3+4/2)");
    test_tok!(tok, Int(2), 1);
    test_tok!(tok, Star, 3);
    test_tok!(tok, LParen, 5);
    test_tok!(tok, Int(3), 6);
    test_tok!(tok, Plus, 7);
    test_tok!(tok, Int(4), 8);
    test_tok!(tok, Slash, 9);
    test_tok!(tok, Int(2), 10);
    test_tok!(tok, RParen, 11);
}

#[test]
fn parse()
{
    assert_eq!(Parser::new("2+2").parse(), Ok(4.));
    assert_eq!(Parser::new("2+3*4").parse(), Ok(14.));
    assert_eq!(Parser::new("4*(3+2)").parse(), Ok(20.));
    assert_eq!(Parser::new("5/(3+2)*3").parse(), Ok(3.));
    assert_eq!(Parser::new("2++12").parse(), Err("unexpected token Plus".to_string()));
    assert_eq!(Parser::new("-2+12").parse(), Ok(10.));
    assert_eq!(Parser::new("-2*(2+3)").parse(), Ok(-10.));
}

#[test]
fn try_check_values() {
    let m = &mut [1,2,3,4];
    assert!(check_values(m, "1+3 -(4/2)"));
}
<commit_msg>refectoring the Lexer iterator<commit_after>// Implements http://rosettacode.org/wiki/24_game
// with a recursive descent parser for a simple calculator (+ - * /)
// using the shunting yard algorithm as explained on
// http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
// It follows operator precedence (i.e. 2 + 3 * 3 = 11),
// understands negation (-5 + 6 = 1), ignores whitespace
// and allows the use of parentheses

#![feature(macro_rules)]
use std::char;

#[cfg(not(test))]
use std::rand;

#[cfg(not(test))]
fn main() {
    let mut rng=rand::task_rng();
    let mut input = std::io::stdin();

    loop {
        let mut sample = rand::sample(&mut rng, range(1u, 10), 4);

        println!("make 24 by combining the following 4 numbers with + - * / or (q)uit");
        println!("{}", sample);

        let line = input.read_line().unwrap();
        match line.as_slice().trim() {
            "q" => break,
            input if check_values(sample.as_mut_slice(), input) => {
                    let mut p = Parser :: new(input);
                    match p.parse() {
                        Ok(i) if i==24f32 => println!("you made it!"),
                        Ok(i) => println!("you entered {}, try again!", i),
                        Err(s)  => println!("{}",s)
                    };
                }
            _ => println!("unrecognized input, try again")
        }
    }
}

// Returns true if the entered expression uses the values contained in sample
fn check_values(sample:&mut [uint], input:&str) -> bool {
    let lex=Lexer::new(input);

    let mut numbers_used : Vec<uint> = lex.filter_map(|a| match a {
                                                        Int(i)  => Some(i),
                                                        _       => None
                                                    }).collect();
    numbers_used.sort();
    sample.sort();
    numbers_used.as_slice() == sample
}

// the tokens that our parser is going to recognize
#[deriving(PartialEq,Eq,Show)]
enum Token {LParen, RParen, Plus, Minus, Slash, Star, Int(uint)}

impl Token {
   // are tokens associated to a binary operation?
   fn is_binary(&self) -> bool {
        match self {
            &Plus | &Minus | &Slash | &Star => true,
            _ => false
        }
    }
}

#[inline]
// map a character to its corresponding token
fn single_char_to_token(ch: char) -> Option<Token> {
    match ch {
            '(' => Some(LParen),
            ')' => Some(RParen),
            '+' => Some(Plus),
            '-' => Some(Minus),
            '/' => Some(Slash),
            '*' => Some(Star),
            _    => None
    }
}

// Lexer reads an expression like (a + b) / c * d
// as an iterator on the tokens that compose it
// Int(a), LParen, Plus, Int(b), RParen...
struct Lexer<'a> {
    input_str:  &'a str,
    offset:     uint
}

impl <'a> Lexer<'a> {
    fn new(input_str: &'a str) -> Lexer<'a> {
        Lexer { input_str: input_str, offset: 0u }
    }

    fn expect(&mut self, expected:&[Token]) -> Result<Token, String> {
        let n = self.offset;
        match self.next() {
            Some(a) if expected.contains(&a)  => Ok(a),
            other  => Err(format!("Parsing error: {} was unexpected at offset {}", other, n))
        }
    }
}

impl <'a> Iterator<Token> for Lexer<'a> {
    fn next(&mut self) -> Option<Token> {
        // slice the original string starting from the current offset
        let remaining_input=self.input_str.slice_from(self.offset);

        // keep track of the offset while advancing chars, with enumerate()
        let ch_iter=remaining_input.chars().enumerate();

        // advance to the next non-whitespace character
        let mut trimmed=ch_iter.skip_while(|&(_, ch)| ch.is_whitespace());

        let (tok, cur_offset) = match trimmed.next() {
            // found digit, check if there are others
            // and transform them to a uint
            Some((o, d)) if d.is_digit() => {
                let (mut val, mut offset)=(char::to_digit(d, 10).unwrap(), o);
                for (idx, ch) in trimmed {
                    if ch.is_digit() {val=val*10 + char::to_digit(ch, 10).unwrap();}
                    else {
                        offset=idx;
                        break;
                    }
                }
                (Some(Int(val)), offset)
            },
            // found non-digit, try transforming it to the corresponding token
            Some((o, t)) => (single_char_to_token(t), o+1),
            _   => (None, 0u)
        };
        // update the offset for the next iteration
        self.offset += cur_offset;
        tok
    }
}

// operators are a "higher level" concept than tokens
// as they define the semantics of the expression language
// e.g. token "Minus" can correspond to the unary Neg Operator (-a)
// or to the binary Sub operator (a - b)
#[deriving(PartialEq,Eq)]
enum Operator {Neg, Add, Sub, Mul, Div, Sentinel}

#[deriving(PartialEq,Eq)]
struct OperatorPrecedence(Operator);

impl Operator {
     fn precedence(self) -> OperatorPrecedence  {
        OperatorPrecedence(self)
    }
}

impl OperatorPrecedence {
    fn prec(self) -> uint {
        match self {
            OperatorPrecedence(Sentinel) => 0u,
            OperatorPrecedence(Add) | OperatorPrecedence(Sub) => 1u,
            OperatorPrecedence(Neg)        => 2u,
            OperatorPrecedence(Mul) | OperatorPrecedence(Div) => 3u
        }
    }
}

/*
    Operator precedence for binary operators:
    * if x has higher precedence than y precedence for x > precedence for y
    * if x and y have equal precedence the first one has precedence
    e.g. in expression (4 / 2 * 2) operators * and / have the same precedence,
    but the operations must be performed in the order they appear
    (division first, multiplication second) otherwise results are different
*/
impl PartialOrd for OperatorPrecedence {
    fn lt(&self, other: &OperatorPrecedence) -> bool {
        match (self, other) {
            (&OperatorPrecedence(Mul), &OperatorPrecedence(Div)) => false,
            (&OperatorPrecedence(Div), &OperatorPrecedence(Mul)) => false,
            (&OperatorPrecedence(Add), &OperatorPrecedence(Sub)) => false,
            (&OperatorPrecedence(Sub), &OperatorPrecedence(Add)) => false,
            _  => self.prec() < other.prec()
        }
    }

    fn gt(&self, other: &OperatorPrecedence) -> bool {
        match (self, other) {
            (&OperatorPrecedence(Mul), &OperatorPrecedence(Div)) => true,
            (&OperatorPrecedence(Div), &OperatorPrecedence(Mul)) => true,
            (&OperatorPrecedence(Add), &OperatorPrecedence(Sub)) => true,
            (&OperatorPrecedence(Sub), &OperatorPrecedence(Add)) => true,
            _          => self.prec() > other.prec()
        }
    }
}

// recursive descent parser
// with the shunting yard algorithm as explained on
// http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
// I followed the names of the methods as closely as possible vs the pseudo-code
// that illustrates the algorithm
struct Parser<'a> {
    operators: Vec<Operator>,
    operands:  Vec<f32>,
    lexer:     Lexer<'a>
}

impl <'a> Parser<'a> {
    fn new(input_str: &'a str) -> Parser<'a> {
        Parser {
            operators:  Vec::new(),
            operands:   Vec::new(),
            lexer:      Lexer::new(input_str)
        }
    }

    fn parse(&mut self) -> Result<f32, String> {
        self.operators.push(Sentinel);
        try!(self.e());
        let res=self.operands.last();
        let ret=match res {
            Some(&r) => Ok(r),
            None    => Err("something went wrong, got no result".to_string())
        };
        ret
    }

    fn e(&mut self) -> Result<(), String> {
        try!(self.p());

        let mut n=self.lexer.next();

        while n.is_some() && n.unwrap().is_binary() {
            match n {
                Some(Plus) => self.push_operator(Add),
                Some(Minus) => self.push_operator(Sub),
                Some(Star) => self.push_operator(Mul),
                Some(Slash) => self.push_operator(Div),
                _ => unreachable!() //shouldn't get there (there are no other
                                    // binary operators
            };
            try!(self.p());

            let mut n_peek = self.lexer.peekable();
            if n_peek.peek().is_none() || !n_peek.peek().unwrap().is_binary() { break; }
            n = self.lexer.next();
        }
        while self.operators.last().is_some() && self.operators.last().unwrap() != &Sentinel {
            self.pop_operator();
        }
        Ok(())
    }

    fn p(&mut self) -> Result<(), String> {
        match self.lexer.next() {
            Some(Int(n)) => {
                self.operands.push(n as f32);
            },
            Some(LParen) => {
                self.operators.push(Sentinel);
                try!(self.e());
                try!(self.lexer.expect(&[RParen]));
                self.operators.pop();
            },
            Some(Minus) => {
                self.push_operator(Neg);
                try!(self.p());
            },
            Some(e) => return Err(format!("unexpected token {}", e)),
            _       => return Err("unexpected end of command".to_string())
            //Some(Minus) =>
        }
        Ok(())
    }

    fn pop_operator(&mut self) {
        match self.operators.pop() {
            Some(Add) => self.binary_op(|t1,t2| t1+t2),
            Some(Sub) => self.binary_op(|t1,t2| t1-t2),
            Some(Mul) => self.binary_op(|t1,t2| t1*t2),
            Some(Div) => self.binary_op(|t1,t2| t1/t2),
            Some(Neg) => self.unary_op(|t1| -t1),
            _         => unreachable!()
            }
    }

    fn push_operator(&mut self, op:Operator) {
        match self.operators.last() {
            Some(&a) if a.precedence() > op.precedence() => self.pop_operator(),
            _ => ()
        }
        self.operators.push(op);
    }

    #[inline]
    fn binary_op(&mut self, op:|f32,f32| -> f32) {
        let t1=self.operands.pop().unwrap();
        let t2=self.operands.pop().unwrap();
        self.operands.push(op(t2,t1));
    }

    #[inline]
    fn unary_op(&mut self, op:|f32| -> f32) {
        let t1=self.operands.pop().unwrap();
        self.operands.push(op(t1));
    }
}

#[test]
fn test_precedence() {
    assert!(Mul.precedence() > Add.precedence());
    assert!(Mul.precedence() > Div.precedence());
    assert!((Mul.precedence() < Div.precedence())==false);
}

#[test]
fn lexer_iter() {
    // test read token and character's offset in the iterator
    macro_rules! test_tok( ($tok:ident, $exp_tok:expr, $exp_pos:expr) =>
        ( assert_eq!(($tok.next(), $tok.offset), (Some($exp_tok), $exp_pos));))

    let mut tok=Lexer::new("  15 + 4");
    test_tok!(tok, Int(15), 4);
    test_tok!(tok, Plus, 6);
    let read=tok.expect(&[LParen,Int(4),RParen]);
    assert_eq!(read, Ok(Int(4)));

    let mut tok=Lexer::new("");
    assert_eq!(tok.next(), None);

    let mut tok=Lexer::new("     ");
    assert_eq!(tok.next(), None);

    let mut tok=Lexer::new("2 * (3+4/2)");
    test_tok!(tok, Int(2), 1);
    test_tok!(tok, Star, 3);
    test_tok!(tok, LParen, 5);
    test_tok!(tok, Int(3), 6);
    test_tok!(tok, Plus, 7);
    test_tok!(tok, Int(4), 8);
    test_tok!(tok, Slash, 9);
    test_tok!(tok, Int(2), 10);
    test_tok!(tok, RParen, 11);
}

#[test]
fn parse()
{
    assert_eq!(Parser::new("2+2").parse(), Ok(4.));
    assert_eq!(Parser::new("2+3*4").parse(), Ok(14.));
    assert_eq!(Parser::new("4*(3+2)").parse(), Ok(20.));
    assert_eq!(Parser::new("5/(3+2)*3").parse(), Ok(3.));
    assert_eq!(Parser::new("2++12").parse(), Err("unexpected token Plus".to_string()));
    assert_eq!(Parser::new("-2+12").parse(), Ok(10.));
    assert_eq!(Parser::new("-2*(2+3)").parse(), Ok(-10.));
}

#[test]
fn try_check_values() {
    let m = &mut [1,2,3,4];
    assert!(check_values(m, "1+3 -(4/2)"));
}<|endoftext|>


<commit_before>use ide_db::helpers::FamousDefs;
use ide_db::RootDatabase;
use syntax::ast::{self, AstNode, NameOwner};
use test_utils::mark;

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: generate_default_from_enum_variant
//
// Adds a Default impl for an enum using a variant.
//
// ```
// enum Version {
//  Undefined,
//  Minor<|>,
//  Major,
// }
// ```
// ->
// ```
// enum Version {
//  Undefined,
//  Minor,
//  Major,
// }
//
// impl Default for Version {
//     fn default() -> Self {
//         Self::Minor
//     }
// }
// ```
pub(crate) fn generate_default_from_enum_variant(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let variant = ctx.find_node_at_offset::<ast::Variant>()?;
    let variant_name = variant.name()?;
    let enum_name = variant.parent_enum().name()?;
    if !matches!(variant.kind(), ast::StructKind::Unit) {
        mark::hit!(test_gen_default_on_non_unit_variant_not_implemented);
        return None;
    }

    if existing_default_impl(&ctx.sema, &variant).is_some() {
        mark::hit!(test_gen_default_impl_already_exists);
        return None;
    }

    let target = variant.syntax().text_range();
    acc.add(
        AssistId("generate_default_from_enum_variant", AssistKind::Generate),
        "Generate `Default` impl from this enum variant",
        target,
        |edit| {
            let start_offset = variant.parent_enum().syntax().text_range().end();
            let buf = format!(
                r#"

impl Default for {0} {{
    fn default() -> Self {{
        Self::{1}
    }}
}}"#,
                enum_name, variant_name
            );
            edit.insert(start_offset, buf);
        },
    )
}

fn existing_default_impl(
    sema: &'_ hir::Semantics<'_, RootDatabase>,
    variant: &ast::Variant,
) -> Option<()> {
    let variant = sema.to_def(variant)?;
    let enum_ = variant.parent_enum(sema.db);
    let krate = enum_.module(sema.db).krate();

    let default_trait = FamousDefs(sema, Some(krate)).core_default_Default()?;
    let enum_type = enum_.ty(sema.db);

    if enum_type.impls_trait(sema.db, default_trait, &[]) {
        Some(())
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use test_utils::mark;

    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    fn check_not_applicable(ra_fixture: &str) {
        let fixture =
            format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE);
        check_assist_not_applicable(generate_default_from_enum_variant, &fixture)
    }

    #[test]
    fn test_generate_default_from_variant() {
        check_assist(
            generate_default_from_enum_variant,
            r#"enum Variant {
                Undefined,
                Minor<|>,
                Major,
            }"#,
            r#"enum Variant {
                Undefined,
                Minor,
                Major,
            }

impl Default for Variant {
    fn default() -> Self {
        Self::Minor
    }
}"#,
        );
    }

    #[test]
    fn test_generate_default_already_implemented() {
        mark::check!(test_gen_default_impl_already_exists);
        check_not_applicable(
            r#"enum Variant {
                Undefined,
                Minor<|>,
                Major,
            }

            impl Default for Variant {
                fn default() -> Self {
                    Self::Minor
                }
            }"#,
        );
    }

    #[test]
    fn test_add_from_impl_no_element() {
        mark::check!(test_gen_default_on_non_unit_variant_not_implemented);
        check_not_applicable(
            r#"enum Variant {
            Undefined,
            Minor(u32)<|>,
            Major,
        }"#,
        );
    }

    #[test]
    fn test_generate_default_from_variant_with_one_variant() {
        check_assist(
            generate_default_from_enum_variant,
            r#"enum Variant { Undefi<|>ned }"#,
            r#"enum Variant { Undefined }

impl Default for Variant {
    fn default() -> Self {
        Self::Undefined
    }
}"#,
        );
    }
}
<commit_msg>generate default implementation for an enum from an enum variant #6860<commit_after>use ide_db::helpers::FamousDefs;
use ide_db::RootDatabase;
use syntax::ast::{self, AstNode, NameOwner};
use test_utils::mark;

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: generate_default_from_enum_variant
//
// Adds a Default impl for an enum using a variant.
//
// ```
// enum Version {
//  Undefined,
//  Minor<|>,
//  Major,
// }
// ```
// ->
// ```
// enum Version {
//  Undefined,
//  Minor,
//  Major,
// }
//
// impl Default for Version {
//     fn default() -> Self {
//         Self::Minor
//     }
// }
// ```
pub(crate) fn generate_default_from_enum_variant(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let variant = ctx.find_node_at_offset::<ast::Variant>()?;
    let variant_name = variant.name()?;
    let enum_name = variant.parent_enum().name()?;
    if !matches!(variant.kind(), ast::StructKind::Unit) {
        mark::hit!(test_gen_default_on_non_unit_variant_not_implemented);
        return None;
    }

    if existing_default_impl(&ctx.sema, &variant).is_some() {
        mark::hit!(test_gen_default_impl_already_exists);
        return None;
    }

    let target = variant.syntax().text_range();
    acc.add(
        AssistId("generate_default_from_enum_variant", AssistKind::Generate),
        "Generate `Default` impl from this enum variant",
        target,
        |edit| {
            let start_offset = variant.parent_enum().syntax().text_range().end();
            let buf = format!(
                r#"

impl Default for {0} {{
    fn default() -> Self {{
        Self::{1}
    }}
}}"#,
                enum_name, variant_name
            );
            edit.insert(start_offset, buf);
        },
    )
}

fn existing_default_impl(
    sema: &'_ hir::Semantics<'_, RootDatabase>,
    variant: &ast::Variant,
) -> Option<()> {
    let variant = sema.to_def(variant)?;
    let enum_ = variant.parent_enum(sema.db);
    let krate = enum_.module(sema.db).krate();

    let default_trait = FamousDefs(sema, Some(krate)).core_default_Default()?;
    let enum_type = enum_.ty(sema.db);

    if enum_type.impls_trait(sema.db, default_trait, &[]) {
        Some(())
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use test_utils::mark;

    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    fn check_not_applicable(ra_fixture: &str) {
        let fixture =
            format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE);
        check_assist_not_applicable(generate_default_from_enum_variant, &fixture)
    }

    #[test]
    fn test_generate_default_from_variant() {
        check_assist(
            generate_default_from_enum_variant,
            r#"enum Variant {
    Undefined,
    Minor<|>,
    Major,
}"#,
            r#"enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Default for Variant {
    fn default() -> Self {
        Self::Minor
    }
}"#,
        );
    }

    #[test]
    fn test_generate_default_already_implemented() {
        mark::check!(test_gen_default_impl_already_exists);
        check_not_applicable(
            r#"enum Variant {
    Undefined,
    Minor<|>,
    Major,
}

impl Default for Variant {
    fn default() -> Self {
        Self::Minor
    }
}"#,
        );
    }

    #[test]
    fn test_add_from_impl_no_element() {
        mark::check!(test_gen_default_on_non_unit_variant_not_implemented);
        check_not_applicable(
            r#"enum Variant {
    Undefined,
    Minor(u32)<|>,
    Major,
}"#,
        );
    }

    #[test]
    fn test_generate_default_from_variant_with_one_variant() {
        check_assist(
            generate_default_from_enum_variant,
            r#"enum Variant { Undefi<|>ned }"#,
            r#"enum Variant { Undefined }

impl Default for Variant {
    fn default() -> Self {
        Self::Undefined
    }
}"#,
        );
    }
}
<|endoftext|>


<commit_before>use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

pub fn new<'a, 'b:'a>(gl: &'a GLContext) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, "
      #version 330 core

      void main() {
        if (gl_VertexID == 0) {
          gl_Position = vec4(1, -1, 0, 1);
        } else if (gl_VertexID == 1) {
          gl_Position = vec4(1, 1, 0, 1);
        } else if (gl_VertexID == 2) {
          gl_Position = vec4(-1, -1, 0, 1);
        } else if (gl_VertexID == 3) {
          gl_Position = vec4(-1, 1, 0, 1);
        }
      }".to_owned()),
    (gl::FRAGMENT_SHADER,
      format!(r#"
        #version 330 core

        uniform vec2 window_size;

        uniform struct Sun {{
          vec3 direction;
          vec3 intensity;
        }} sun;

        const float sun_angular_radius = 3.14/32;

        uniform mat4 projection_matrix;
        uniform vec3 eye_position;

        uniform float time_ms;

        out vec4 frag_color;

        // include depth fog
        {}

        // include cnoise
        {}

        vec3 pixel_direction(vec2 pixel) {{
          // Scale to [0, 1]
          pixel /= window_size;
          // Scale to [-1, 1]
          pixel = 2*pixel - 1;
          vec4 p = inverse(projection_matrix) * vec4(pixel, -1, 1);
          return normalize(vec3(p / p.w) - eye_position);
        }}

        float cloud_noise(vec3 seed) {{
          float f = cnoise(seed + vec3(0, time_ms / 8000, 0));
          return f;
        }}

        float cloud_density(vec3 seed) {{
          float f = (2.0*cloud_noise(seed / 2) + cloud_noise(seed) + 0.5*cloud_noise(2.0 * seed) + 0.25*cloud_noise(4.0*seed)) / 3.75;
          return (f + 1) / 2;
        }}

        void main() {{
          vec3 c = sun.intensity;

          vec3 direction = pixel_direction(gl_FragCoord.xy);

          const int HEIGHTS = 2;
          float heights[HEIGHTS] = float[](150, 1000);
          vec3 offsets[HEIGHTS] = vec3[](vec3(12,553,239), vec3(-10, 103, 10004));

          float sunniness = exp(64 * (dot(sun.direction, direction) - cos(sun_angular_radius)));
          c = mix(c, vec3(1), sunniness);

          float alpha = 0;
          for (int i = 0; i < HEIGHTS; ++i) {{
            float cloud_height = heights[i];
            float dist = (cloud_height - eye_position.y) / direction.y;
            if (dist <= 0 || dist > 1000000) {{
              continue;
            }} else {{
              vec3 seed = (eye_position + dist * direction + offsets[i]) / 1000 * vec3(1, 4, 1);
              float f = cloud_density(seed);
              alpha += f * (1 - fog_density(dist / 64));
            }}
          }}
          alpha = alpha / HEIGHTS;

          float min_cloud = 0.4;
          float max_cloud = 0.8;
          alpha = (alpha - min_cloud) / (max_cloud - min_cloud);
          alpha = min(max(alpha, 0), 1);
          vec3 cloud_color = mix(vec3(0.4), vec3(1), (exp(1 - alpha) - 1) / exp(1));
          c = mix(c, cloud_color, alpha);

          frag_color = min(vec4(c, 1), vec4(1));
        }}"#,
        ::shaders::depth_fog::to_string(),
        ::shaders::noise::cnoise(),
      )
    ),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<commit_msg>different sky color model<commit_after>use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

pub fn new<'a, 'b:'a>(gl: &'a GLContext) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, "
      #version 330 core

      void main() {
        if (gl_VertexID == 0) {
          gl_Position = vec4(1, -1, 0, 1);
        } else if (gl_VertexID == 1) {
          gl_Position = vec4(1, 1, 0, 1);
        } else if (gl_VertexID == 2) {
          gl_Position = vec4(-1, -1, 0, 1);
        } else if (gl_VertexID == 3) {
          gl_Position = vec4(-1, 1, 0, 1);
        }
      }".to_owned()),
    (gl::FRAGMENT_SHADER,
      format!(r#"
        #version 330 core

        uniform vec2 window_size;

        uniform struct Sun {{
          vec3 direction;
          vec3 intensity;
        }} sun;

        const float sun_angular_radius = 3.14/32;

        uniform mat4 projection_matrix;
        uniform vec3 eye_position;

        uniform float time_ms;

        out vec4 frag_color;

        // include depth fog
        {}

        // include cnoise
        {}

        vec3 pixel_direction(vec2 pixel) {{
          // Scale to [0, 1]
          pixel /= window_size;
          // Scale to [-1, 1]
          pixel = 2*pixel - 1;
          vec4 p = inverse(projection_matrix) * vec4(pixel, -1, 1);
          return normalize(vec3(p / p.w) - eye_position);
        }}

        float cloud_noise(vec3 seed) {{
          float f = cnoise(seed + vec3(0, time_ms / 8000, 0));
          return f;
        }}

        float cloud_density(vec3 seed) {{
          float d = (2.0*cloud_noise(seed / 2) + cloud_noise(seed) + 0.5*cloud_noise(2.0 * seed) + 0.25*cloud_noise(4.0*seed)) / 3.75;
          d = (d + 1) / 2;
          float min_cloud = 0.4;
          float max_cloud = 0.8;
          d = (d - min_cloud) / (max_cloud - min_cloud);
          d = min(max(d, 0), 1);
          return d;
        }}

        void main() {{
          vec3 direction = pixel_direction(gl_FragCoord.xy);

          const int HEIGHTS = 2;
          float heights[HEIGHTS] = float[](150, 1000);
          vec3 offsets[HEIGHTS] = vec3[](vec3(12,553,239), vec3(-10, 103, 10004));

          vec3 c = vec3(0);
          float alpha = 1;
          for (int i = 0; i < HEIGHTS; ++i) {{
            float cloud_height = heights[i];
            float dist = (cloud_height - eye_position.y) / direction.y;
            if (dist <= 0 || dist > 1000000) {{
              continue;
            }} else {{
              vec3 seed = (eye_position + dist * direction + offsets[i]) / 1000 * vec3(1, 4, 1);

              float depth_alpha = fog_density(dist / 64);
              float density = cloud_density(seed);
              float cloud_alpha = density * (1 - depth_alpha);
              c += alpha * cloud_alpha * vec3(mix(0.4, 1, (exp(1 - density) - 1) / (exp(1) - 1)));
              alpha *= (1 - cloud_alpha);
            }}
          }}

          float sunniness = exp(64 * (dot(sun.direction, direction) - cos(sun_angular_radius)));
          vec3 infinity_color = mix(sun.intensity, vec3(1), sunniness);
          c += alpha * infinity_color;

          frag_color = min(vec4(c, 1), vec4(1));
        }}"#,
        ::shaders::depth_fog::to_string(),
        ::shaders::noise::cnoise(),
      )
    ),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<|endoftext|>


<commit_before>// 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.

/// The location of something in an address space.
///
/// This is used to provide a location of a [`Function`], [`Instruction`],
/// or other item.
///
/// The meaning of this address is flexibly interpreted by the rest of this
/// library as the meaning depends upon the application embedding and using
/// this library. It may be an actual machine address or it might be something
/// as simple as the offset of an instruction into an array.
///
/// XXX: Should this have any indication for what type of address it is?
///      An address might be an address within a file, a resolved address
///      after being loaded, etc.
///
/// XXX: Should this include any information about the address space
///      that it is from?
///
/// [`Function`]: struct.Function.html
/// [`Instruction`]: trait.Instruction.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Address {
    address: u64,
}

impl Address {
    /// Construct an `Address`.
    pub fn new(address: u64) -> Self {
        Address { address: address }
    }
}

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

    #[test]
    fn address_comparison() {
        let addr1 = Address::new(5);
        let addr2 = Address::new(3);
        let addr3 = Address::new(5);
        assert!(addr2 < addr1);
        assert_eq!(addr1, addr3);
    }
}
<commit_msg>impl fmt::{Binary,Octal,LowerHex,UpperHex} for Address.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

/// The location of something in an address space.
///
/// This is used to provide a location of a [`Function`], [`Instruction`],
/// or other item.
///
/// The meaning of this address is flexibly interpreted by the rest of this
/// library as the meaning depends upon the application embedding and using
/// this library. It may be an actual machine address or it might be something
/// as simple as the offset of an instruction into an array.
///
/// XXX: Should this have any indication for what type of address it is?
///      An address might be an address within a file, a resolved address
///      after being loaded, etc.
///
/// XXX: Should this include any information about the address space
///      that it is from?
///
/// ## Formatting
///
/// `Address` implements the `fmt::Binary`, `fmt::Octal`, `fmt::LowerHex`
/// and `fmt::UpperHex` traits from `std::fmt`. This makes it integrate
/// readily with Rust's standard I/O facilities:
///
/// ```
/// # use disassemble::Address;
/// let a = Address::new(0x6502);
/// // Print with 0x in hex.
/// assert_eq!("0x6502", format!("{:#x}", a));
/// // Print with 0x, zero padded, 10 characters wide, in hex.
/// assert_eq!("0x00006502", format!("{:#010x}", a));
/// ```
///
/// [`Function`]: struct.Function.html
/// [`Instruction`]: trait.Instruction.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Address {
    address: u64,
}

impl Address {
    /// Construct an `Address`.
    pub fn new(address: u64) -> Self {
        Address { address: address }
    }
}

impl fmt::Binary for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.address.fmt(f)
    }
}

impl fmt::Octal for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.address.fmt(f)
    }
}

impl fmt::LowerHex for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.address.fmt(f)
    }
}

impl fmt::UpperHex for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.address.fmt(f)
    }
}

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

    #[test]
    fn address_comparison() {
        let addr1 = Address::new(5);
        let addr2 = Address::new(3);
        let addr3 = Address::new(5);
        assert!(addr2 < addr1);
        assert_eq!(addr1, addr3);
    }

    #[test]
    fn binary_fmt() {
        let a = Address::new(4);
        assert_eq!("100", format!("{:b}", a));
    }

    #[test]
    fn octal_fmt() {
        let a = Address::new(10);
        assert_eq!("12", format!("{:o}", a));
    }

    #[test]
    fn lower_hex_fmt() {
        let a = Address::new(0xc1);
        assert_eq!("0xc1", format!("{:#x}", a));
        assert_eq!("  0xc1", format!("{:#6x}", a));
        assert_eq!("    c1", format!("{:6x}", a));
        assert_eq!("0000c1", format!("{:06x}", a));
    }

    #[test]
    fn upper_hex_fmt() {
        let a = Address::new(0xc1);
        assert_eq!("0xC1", format!("{:#X}", a));
        assert_eq!("  0xC1", format!("{:#6X}", a));
        assert_eq!("    C1", format!("{:6X}", a));
        assert_eq!("0000C1", format!("{:06X}", a));
    }
}
<|endoftext|>


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

use app::App;
use app::Msg::CreateWindow;
use webview::Msg::PageOpen;
use url::{Url, Position};
use urls::{offset, get_filename};

impl App {
    /// Open the given URL in the web view.
    pub fn open(&self, url: &str) {
        let url = self.transform_url(url);
        self.webview.emit(PageOpen(url));
    }

    /// Open the given URL in a new window.
    pub fn open_in_new_window(&mut self, url: &str) {
        let url = self.transform_url(url);
        self.model.relm.stream().emit(CreateWindow(url));
    }

    /// Open in a new window the url from the system clipboard.
    pub fn win_paste_url(&mut self) {
        if let Some(url) = self.get_url_from_clipboard() {
            self.open_in_new_window(&url);
        }
    }

    /// Go up one directory in url.
    pub fn go_parent_directory(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            let mut parent = String::new();

            // TODO: Do manually without use of get_filename
            if let Some(filename) = get_filename(url) {
                if filename.is_empty() {
                    if let Ok(base_url) = Url::parse(url) {
                        parent = base_url.join("../").unwrap().to_string();
                    }
                } else {
                    parent = url[..url.len()-filename.len()].to_string();
                }
            }

            if !parent.is_empty() {
                self.open(&parent);
            }
        }
    }

    /// Go to the root directory or url hostname.
    pub fn go_root_directory(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Ok(base_url) = Url::parse(url) {
                let root = &base_url[..Position::BeforePath];

                if !root.is_empty() {
                    self.open(root);
                }
            }
        }
    }

    pub fn url_increment(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Some(url) = offset(url, 1) {
                self.open(&url);
            }
        }
    }

    pub fn url_decrement(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Some(url) = offset(url, -1) {
                self.open(&url);
            }
        }
    }
}
<commit_msg>Simply go_parent_directory()<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

use app::App;
use app::Msg::CreateWindow;
use webview::Msg::PageOpen;
use url::{Url, Position};
use urls::offset;

impl App {
    /// Open the given URL in the web view.
    pub fn open(&self, url: &str) {
        let url = self.transform_url(url);
        self.webview.emit(PageOpen(url));
    }

    /// Open the given URL in a new window.
    pub fn open_in_new_window(&mut self, url: &str) {
        let url = self.transform_url(url);
        self.model.relm.stream().emit(CreateWindow(url));
    }

    /// Open in a new window the url from the system clipboard.
    pub fn win_paste_url(&mut self) {
        if let Some(url) = self.get_url_from_clipboard() {
            self.open_in_new_window(&url);
        }
    }

    /// Go up one directory in url.
    pub fn go_parent_directory(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Ok(mut url) = Url::parse(url) {
                match url.path_segments_mut() {
                    Ok(mut segments) => {
                        let _ = segments.pop_if_empty()
                            .pop();
                    },
                    Err(_) => return,
                }
                self.open(url.as_str());
            }
        }
    }

    /// Go to the root directory or url hostname.
    pub fn go_root_directory(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Ok(base_url) = Url::parse(url) {
                let root = &base_url[..Position::BeforePath];

                if !root.is_empty() {
                    self.open(root);
                }
            }
        }
    }

    pub fn url_increment(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Some(url) = offset(url, 1) {
                self.open(&url);
            }
        }
    }

    pub fn url_decrement(&self) {
        if let Some(ref url) = self.webview.widget().get_uri() {
            if let Some(url) = offset(url, -1) {
                self.open(&url);
            }
        }
    }
}
<|endoftext|>


<commit_before>use ffmpeg_sys;
use libc::*;
use std::cmp;
use std::ffi::{ CStr, CString };
use std::ops::Deref;

use errors::*;

#[derive(Debug, Clone, Copy)]
pub struct Rational {
    pub numerator: i32,
    pub denominator: i32,
}

#[derive(Clone, Copy)]
pub struct Codec {
    ptr: *mut ffmpeg_sys::AVCodec,
}

unsafe impl Send for Codec {}
unsafe impl Sync for Codec {}

pub struct PixelFormats {
    codec: Codec,
    index: isize,
}

pub struct Context {
    ptr: *mut ffmpeg_sys::AVCodecContext,
}

impl From<(i32, i32)> for Rational {
    fn from((numerator, denominator): (i32, i32)) -> Self {
        Self {
            numerator,
            denominator,
        }
    }
}

impl From<ffmpeg_sys::AVRational> for Rational {
    fn from(rational: ffmpeg_sys::AVRational) -> Self {
        Self {
            numerator: rational.num,
            denominator: rational.den,
        }
    }
}

impl From<Rational> for ffmpeg_sys::AVRational {
    fn from(rational: Rational) -> Self {
        Self {
            num: rational.numerator,
            den: rational.denominator,
        }
    }
}

impl Codec {
    pub fn description(self) -> String {
        unsafe {
            CStr::from_ptr((*self.ptr).long_name).to_string_lossy().into_owned()
        }
    }

    pub fn kind(self) -> ffmpeg_sys::AVMediaType {
        unsafe {
            (*self.ptr).kind
        }
    }

    pub fn is_video(self) -> bool {
        self.kind() == ffmpeg_sys::AVMediaType::AVMEDIA_TYPE_VIDEO
    }

    pub fn pixel_formats(self) -> Option<PixelFormats> {
        unsafe {
            if (*self.ptr).pix_fmts.is_null() {
                None
            } else {
                Some(PixelFormats::new(self))
            }
        }
    }

    pub fn context(self) -> Result<Context> {
        let ptr = unsafe {
            ffmpeg_sys::avcodec_alloc_context3(self.ptr)
        };

        ensure!(!ptr.is_null(), "unable to allocate the codec context");

        Ok(Context { ptr })
    }
}

impl PixelFormats {
    fn new(codec: Codec) -> Self {
        Self {
            codec,
            index: 0,
        }
    }
}

impl Iterator for PixelFormats {
    type Item = ffmpeg_sys::AVPixelFormat;

    fn next(&mut self) -> Option<Self::Item> {
        let format = unsafe {
            *(*self.codec.ptr).pix_fmts.offset(self.index)
        };

        if format == ffmpeg_sys::AVPixelFormat::AV_PIX_FMT_NONE {
            None
        } else {
            self.index += 1;
            Some(format)
        }
    }
}

impl Context {
    pub fn width(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).width) as u32
        }
    }

    pub fn set_width(&mut self, width: u32) {
        unsafe {
            (*self.ptr).width = cmp::min(width, c_int::max_value() as u32) as c_int;
        }
    }

    pub fn height(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).height) as u32
        }
    }

    pub fn set_height(&mut self, height: u32) {
        unsafe {
            (*self.ptr).height = cmp::min(height, c_int::max_value() as u32) as c_int;
        }
    }

    pub fn time_base(&self) -> Rational {
        unsafe {
            (*self.ptr).time_base.into()
        }
    }

    pub fn set_time_base(&mut self, time_base: &Rational) {
        unsafe {
            (*self.ptr).time_base = (*time_base).into();
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            ffmpeg_sys::avcodec_free_context(&mut self.ptr);
        }
    }
}

pub fn initialize() {
    unsafe {
        ffmpeg_sys::avcodec_register_all();
    }
}

pub fn find_encoder_by_name(name: &str) -> Result<Option<Codec>> {
    let name = CString::new(name).chain_err(|| "could not convert name to CString")?;

    let codec = unsafe {
        ffmpeg_sys::avcodec_find_encoder_by_name(name.as_ptr())
    };

    if codec.is_null() {
        Ok(None)
    } else {
        Ok(Some(Codec { ptr: codec }))
    }
}
<commit_msg>Mark stuff as inline<commit_after>use ffmpeg_sys;
use libc::*;
use std::cmp;
use std::ffi::{ CStr, CString };
use std::ops::Deref;

use errors::*;

#[derive(Debug, Clone, Copy)]
pub struct Rational {
    pub numerator: i32,
    pub denominator: i32,
}

#[derive(Clone, Copy)]
pub struct Codec {
    ptr: *mut ffmpeg_sys::AVCodec,
}

unsafe impl Send for Codec {}
unsafe impl Sync for Codec {}

pub struct PixelFormats {
    codec: Codec,
    index: isize,
}

pub struct Context {
    ptr: *mut ffmpeg_sys::AVCodecContext,
}

impl From<(i32, i32)> for Rational {
    fn from((numerator, denominator): (i32, i32)) -> Self {
        Self {
            numerator,
            denominator,
        }
    }
}

impl From<ffmpeg_sys::AVRational> for Rational {
    fn from(rational: ffmpeg_sys::AVRational) -> Self {
        Self {
            numerator: rational.num,
            denominator: rational.den,
        }
    }
}

impl From<Rational> for ffmpeg_sys::AVRational {
    fn from(rational: Rational) -> Self {
        Self {
            num: rational.numerator,
            den: rational.denominator,
        }
    }
}

impl Codec {
    pub fn description(self) -> String {
        unsafe {
            CStr::from_ptr((*self.ptr).long_name).to_string_lossy().into_owned()
        }
    }

    #[inline]
    pub fn kind(self) -> ffmpeg_sys::AVMediaType {
        unsafe {
            (*self.ptr).kind
        }
    }

    #[inline]
    pub fn is_video(self) -> bool {
        self.kind() == ffmpeg_sys::AVMediaType::AVMEDIA_TYPE_VIDEO
    }

    pub fn pixel_formats(self) -> Option<PixelFormats> {
        unsafe {
            if (*self.ptr).pix_fmts.is_null() {
                None
            } else {
                Some(PixelFormats::new(self))
            }
        }
    }

    pub fn context(self) -> Result<Context> {
        let ptr = unsafe {
            ffmpeg_sys::avcodec_alloc_context3(self.ptr)
        };

        ensure!(!ptr.is_null(), "unable to allocate the codec context");

        Ok(Context { ptr })
    }
}

impl PixelFormats {
    fn new(codec: Codec) -> Self {
        Self {
            codec,
            index: 0,
        }
    }
}

impl Iterator for PixelFormats {
    type Item = ffmpeg_sys::AVPixelFormat;

    fn next(&mut self) -> Option<Self::Item> {
        let format = unsafe {
            *(*self.codec.ptr).pix_fmts.offset(self.index)
        };

        if format == ffmpeg_sys::AVPixelFormat::AV_PIX_FMT_NONE {
            None
        } else {
            self.index += 1;
            Some(format)
        }
    }
}

impl Context {
    #[inline]
    pub fn width(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).width) as u32
        }
    }

    #[inline]
    pub fn set_width(&mut self, width: u32) {
        unsafe {
            (*self.ptr).width = cmp::min(width, c_int::max_value() as u32) as c_int;
        }
    }

    #[inline]
    pub fn height(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).height) as u32
        }
    }

    #[inline]
    pub fn set_height(&mut self, height: u32) {
        unsafe {
            (*self.ptr).height = cmp::min(height, c_int::max_value() as u32) as c_int;
        }
    }

    #[inline]
    pub fn time_base(&self) -> Rational {
        unsafe {
            (*self.ptr).time_base.into()
        }
    }

    #[inline]
    pub fn set_time_base(&mut self, time_base: &Rational) {
        unsafe {
            (*self.ptr).time_base = (*time_base).into();
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            ffmpeg_sys::avcodec_free_context(&mut self.ptr);
        }
    }
}

pub fn initialize() {
    unsafe {
        ffmpeg_sys::avcodec_register_all();
    }
}

pub fn find_encoder_by_name(name: &str) -> Result<Option<Codec>> {
    let name = CString::new(name).chain_err(|| "could not convert name to CString")?;

    let codec = unsafe {
        ffmpeg_sys::avcodec_find_encoder_by_name(name.as_ptr())
    };

    if codec.is_null() {
        Ok(None)
    } else {
        Ok(Some(Codec { ptr: codec }))
    }
}
<|endoftext|>