<commit_before>use std::cell::RefCell;
use std::rc::Rc;

// We have to share a lot of things around, so use reference-counting to keep
// track of them.
pub type SharedBasicBlock = Rc<RefCell<BasicBlock>>;
pub type SharedFunction = Rc<RefCell<Function>>;
pub type SharedValue = Rc<RefCell<Value>>;

#[derive(Debug)]
pub struct Unit {
    pub locals: Vec<String>,
    pub functions: Vec<SharedFunction>,
}

impl Unit {
    pub fn new() -> Self {
        Self {
            locals: vec![],
            functions: vec![Rc::new(RefCell::new(Function::new(0, "main")))],
        }
    }

    pub fn main_function(&self) -> SharedFunction {
        self.functions[0].clone()
    }
}

pub type Address = u32;

pub type ValueId = u32;

#[derive(Debug)]
pub struct Value {
    pub id: ValueId,
    // List of all the instructions that read this value.
    pub dependents: Vec<Address>,
}

impl Value {
    fn new(id: ValueId) -> Self {
        Value {
            id,
            dependents: vec![],
        }
    }

    fn null() -> Self {
        Value {
            id: 0,
            dependents: vec![],
        }
    }

    pub fn is_null(&self) -> bool {
        self.id == 0
    }

    // Call this to track that an instruction uses this value.
    fn used_by(&mut self, address: Address) {
        // The null register can be used freely.
        if self.is_null() {
            return;
        }
        if !self.dependents.contains(&address) {
            self.dependents.push(address)
        }
    }
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        self.id == other.id
    }
}

#[derive(Debug, PartialEq)]
pub struct Function {
    pub id: u16,
    pub name: String,
    pub locals: Vec<String>,

    // Always keep track of where we entered.
    entry: SharedBasicBlock,
    // Keep track of where we are.
    current: SharedBasicBlock,
    // Used for compilation.
    pub basic_blocks: Vec<SharedBasicBlock>,

    // All the values allocated within the function.
    pub values: Vec<SharedValue>,
    // Use to generate monotonically-increasing instruction addresses.
    pub instruction_counter: u32,
}

impl Function {
    fn new<V: Into<String>>(id: u16, name: V) -> Self {
        let entry = Rc::new(RefCell::new(BasicBlock::new("entry")));
        Self {
            id,
            name: name.into(),
            locals: vec![],
            entry: entry.clone(),
            current: entry.clone(),
            basic_blocks: vec![entry],
            values: vec![],
            instruction_counter: 0,
        }
    }

    pub fn null_value(&self) -> SharedValue {
        Rc::new(RefCell::new(Value::null()))
    }

    pub fn have_local(&self, local: &String) -> bool {
        self.locals.contains(local)
    }

    pub fn get_local(&self, local: &String) -> u8 {
        self.locals
            .iter()
            .position(|existing| existing == local)
            .expect("Local not found") as u8
    }

    pub fn get_or_add_local(&mut self, local: String) -> u8 {
        let position = self.locals.iter().position(|existing| existing == &local);
        match position {
            Some(index) => index as u8,
            None => {
                self.locals.push(local);
                (self.locals.len() - 1) as u8
            }
        }
    }

    fn next_address(&mut self) -> Address {
        let address = self.instruction_counter;
        self.instruction_counter += 1;
        address
    }
}

pub trait InstructionBuilder {
    // Build a new `Value`.
    fn new_value(&mut self) -> SharedValue;

    // Push an instruction: returns the address of the new instruction.
    fn push(&mut self, instruction: Instruction) -> Address;

    // Add an instruction address to the value's list of dependents.
    fn track(&mut self, rval: SharedValue, address: Address);

    fn build_get_local(&mut self, index: u8) -> SharedValue {
        let lval = self.new_value();
        self.push(Instruction::GetLocal(lval.clone(), index));
        lval
    }

    fn build_get_local_lexical(&mut self, name: String) -> SharedValue {
        let lval = self.new_value();
        self.push(Instruction::GetLocalLexical(lval.clone(), name));
        lval
    }

    fn build_set_local(&mut self, index: u8, rval: SharedValue) {
        let address = self.push(Instruction::SetLocal(index, rval.clone()));
        self.track(rval, address);
    }

    fn build_set_local_lexical(&mut self, name: String, rval: SharedValue) {
        let address = self.push(Instruction::SetLocalLexical(name, rval.clone()));
        self.track(rval, address);
    }

    fn build_make_integer(&mut self, value: i64) -> SharedValue {
        let lval = self.new_value();
        self.push(Instruction::MakeInteger(lval.clone(), value));
        lval
    }

    fn build_call(&mut self, target: SharedValue, arguments: Vec<SharedValue>) -> SharedValue {
        let lval = self.new_value();
        let address = self.push(Instruction::Call(
            lval.clone(),
            target.clone(),
            arguments.clone(),
        ));
        self.track(target, address);
        for argument in arguments {
            self.track(argument, address);
        }
        lval
    }
}

impl InstructionBuilder for Function {
    fn new_value(&mut self) -> SharedValue {
        let id = (self.values.len() as u32) + 1;
        let value = Rc::new(RefCell::new(Value::new(id)));
        self.values.push(value.clone());
        value
    }

    fn push(&mut self, instruction: Instruction) -> Address {
        let address = self.next_address();
        self.current
            .borrow_mut()
            .instructions
            .push((address, instruction));
        address
    }

    fn track(&mut self, rval: SharedValue, address: Address) {
        rval.borrow_mut().used_by(address)
    }
}

#[derive(Debug, PartialEq)]
pub enum Instruction {
    GetLocal(SharedValue, u8),
    GetLocalLexical(SharedValue, String),
    SetLocal(u8, SharedValue),
    SetLocalLexical(String, SharedValue),
    MakeInteger(SharedValue, i64),
    Call(SharedValue, SharedValue, Vec<SharedValue>),
}

#[derive(Debug, PartialEq)]
pub struct BasicBlock {
    pub name: String,
    pub instructions: Vec<(Address, Instruction)>,
}

impl BasicBlock {
    fn new<V: Into<String>>(name: V) -> Self {
        Self {
            name: name.into(),
            instructions: vec![],
        }
    }
}
<commit_msg>Give IR `BasicBlock`s unique IDs for easier comparison<commit_after>use std::cell::RefCell;
use std::rc::Rc;

// We have to share a lot of things around, so use reference-counting to keep
// track of them.
pub type SharedBasicBlock = Rc<RefCell<BasicBlock>>;
pub type SharedFunction = Rc<RefCell<Function>>;
pub type SharedValue = Rc<RefCell<Value>>;

#[derive(Debug)]
pub struct Unit {
    pub locals: Vec<String>,
    pub functions: Vec<SharedFunction>,
}

impl Unit {
    pub fn new() -> Self {
        Self {
            locals: vec![],
            functions: vec![Rc::new(RefCell::new(Function::new(0, "main")))],
        }
    }

    pub fn main_function(&self) -> SharedFunction {
        self.functions[0].clone()
    }
}

pub type Address = u32;

pub type ValueId = u32;

#[derive(Debug)]
pub struct Value {
    pub id: ValueId,
    // List of all the instructions that read this value.
    pub dependents: Vec<Address>,
}

impl Value {
    fn new(id: ValueId) -> Self {
        Value {
            id,
            dependents: vec![],
        }
    }

    fn null() -> Self {
        Value {
            id: 0,
            dependents: vec![],
        }
    }

    pub fn is_null(&self) -> bool {
        self.id == 0
    }

    // Call this to track that an instruction uses this value.
    fn used_by(&mut self, address: Address) {
        // The null register can be used freely.
        if self.is_null() {
            return;
        }
        if !self.dependents.contains(&address) {
            self.dependents.push(address)
        }
    }
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        self.id == other.id
    }
}

#[derive(Debug, PartialEq)]
pub struct Function {
    pub id: u16,
    pub name: String,
    pub locals: Vec<String>,

    // Always keep track of where we entered.
    entry: SharedBasicBlock,
    // Keep track of where we are.
    current: SharedBasicBlock,
    // Used for compilation.
    pub basic_blocks: Vec<SharedBasicBlock>,

    // All the values allocated within the function.
    pub values: Vec<SharedValue>,
    // Use to generate monotonically-increasing instruction addresses.
    pub instruction_counter: u32,
}

impl Function {
    fn new<V: Into<String>>(id: u16, name: V) -> Self {
        // NOTE: Normally we'd want to call `self.next_basic_block_id()`, but
        //   we don't exist yet to we have to hard-code the 0.
        let entry = Rc::new(RefCell::new(BasicBlock::new(0, "entry")));
        Self {
            id,
            name: name.into(),
            locals: vec![],
            entry: entry.clone(),
            current: entry.clone(),
            basic_blocks: vec![entry],
            values: vec![],
            instruction_counter: 0,
        }
    }

    pub fn null_value(&self) -> SharedValue {
        Rc::new(RefCell::new(Value::null()))
    }

    pub fn have_local(&self, local: &String) -> bool {
        self.locals.contains(local)
    }

    pub fn get_local(&self, local: &String) -> u8 {
        self.locals
            .iter()
            .position(|existing| existing == local)
            .expect("Local not found") as u8
    }

    pub fn get_or_add_local(&mut self, local: String) -> u8 {
        let position = self.locals.iter().position(|existing| existing == &local);
        match position {
            Some(index) => index as u8,
            None => {
                self.locals.push(local);
                (self.locals.len() - 1) as u8
            }
        }
    }

    fn next_address(&mut self) -> Address {
        let address = self.instruction_counter;
        self.instruction_counter += 1;
        address
    }
}

pub trait InstructionBuilder {
    // Build a new `Value`.
    fn new_value(&mut self) -> SharedValue;

    // Push an instruction: returns the address of the new instruction.
    fn push(&mut self, instruction: Instruction) -> Address;

    // Add an instruction address to the value's list of dependents.
    fn track(&mut self, rval: SharedValue, address: Address);

    fn build_get_local(&mut self, index: u8) -> SharedValue {
        let lval = self.new_value();
        self.push(Instruction::GetLocal(lval.clone(), index));
        lval
    }

    fn build_get_local_lexical(&mut self, name: String) -> SharedValue {
        let lval = self.new_value();
        self.push(Instruction::GetLocalLexical(lval.clone(), name));
        lval
    }

    fn build_set_local(&mut self, index: u8, rval: SharedValue) {
        let address = self.push(Instruction::SetLocal(index, rval.clone()));
        self.track(rval, address);
    }

    fn build_set_local_lexical(&mut self, name: String, rval: SharedValue) {
        let address = self.push(Instruction::SetLocalLexical(name, rval.clone()));
        self.track(rval, address);
    }

    fn build_make_integer(&mut self, value: i64) -> SharedValue {
        let lval = self.new_value();
        self.push(Instruction::MakeInteger(lval.clone(), value));
        lval
    }

    fn build_call(&mut self, target: SharedValue, arguments: Vec<SharedValue>) -> SharedValue {
        let lval = self.new_value();
        let address = self.push(Instruction::Call(
            lval.clone(),
            target.clone(),
            arguments.clone(),
        ));
        self.track(target, address);
        for argument in arguments {
            self.track(argument, address);
        }
        lval
    }
}

impl InstructionBuilder for Function {
    fn new_value(&mut self) -> SharedValue {
        let id = (self.values.len() as u32) + 1;
        let value = Rc::new(RefCell::new(Value::new(id)));
        self.values.push(value.clone());
        value
    }

    fn push(&mut self, instruction: Instruction) -> Address {
        let address = self.next_address();
        self.current
            .borrow_mut()
            .instructions
            .push((address, instruction));
        address
    }

    fn track(&mut self, rval: SharedValue, address: Address) {
        rval.borrow_mut().used_by(address)
    }
}

#[derive(Debug, PartialEq)]
pub enum Instruction {
    GetLocal(SharedValue, u8),
    GetLocalLexical(SharedValue, String),
    SetLocal(u8, SharedValue),
    SetLocalLexical(String, SharedValue),
    MakeInteger(SharedValue, i64),
    Call(SharedValue, SharedValue, Vec<SharedValue>),
}

#[derive(Debug, PartialEq)]
pub struct BasicBlock {
    pub id: u16,
    pub name: String,
    pub instructions: Vec<(Address, Instruction)>,
}

impl BasicBlock {
    fn new<V: Into<String>>(id: u16, name: V) -> Self {
        Self {
            id,
            name: name.into(),
            instructions: vec![],
        }
    }
}
<|endoftext|>


<commit_before>use std::marker;

use super::{Dimension, Ix, Ixs};
use super::{Elements, ElementsRepr, ElementsBase, ElementsBaseMut, ElementsMut, Indexed, IndexedMut};
use super::{
    ArrayView,
    ArrayViewMut,
};

/// Base for array iterators
///
/// Iterator element type is `&'a A`.
pub struct Baseiter<'a, A: 'a, D> {
    // Can have pub fields because it is not itself pub.
    pub ptr: *mut A,
    pub dim: D,
    pub strides: D,
    pub index: Option<D>,
    pub life: marker::PhantomData<&'a A>,
}

impl<'a, A, D: Dimension> Baseiter<'a, A, D>
{
    /// Creating a Baseiter is unsafe, because it can
    /// have any lifetime, be immut or mut, and the
    /// boundary and stride parameters need to be correct to
    /// avoid memory unsafety.
    ///
    /// It must be placed in the correct mother iterator to be safe.
    ///
    /// NOTE: Mind the lifetime, it's arbitrary
    #[inline]
    pub unsafe fn new(ptr: *mut A, len: D, stride: D) -> Baseiter<'a, A, D>
    {
        Baseiter {
            ptr: ptr,
            index: len.first_index(),
            dim: len,
            strides: stride,
            life: marker::PhantomData,
        }
    }
}

impl<'a, A, D: Dimension> Baseiter<'a, A, D>
{
    #[inline]
    pub fn next(&mut self) -> Option<*mut A>
    {
        let index = match self.index {
            None => return None,
            Some(ref ix) => ix.clone(),
        };
        let offset = Dimension::stride_offset(&index, &self.strides);
        self.index = self.dim.next_for(index);
        unsafe {
            Some(self.ptr.offset(offset))
        }
    }

    #[inline]
    fn next_ref(&mut self) -> Option<&'a A>
    {
        unsafe { self.next().map(|p| &*p) }
    }

    #[inline]
    fn next_ref_mut(&mut self) -> Option<&'a mut A>
    {
        unsafe { self.next().map(|p| &mut *p) }
    }

    fn size_hint(&self) -> usize
    {
        match self.index {
            None => 0,
            Some(ref ix) => {
                let gone = self.dim.default_strides().slice().iter()
                            .zip(ix.slice().iter())
                                 .fold(0, |s, (&a, &b)| s + a as usize * b as usize);
                self.dim.size() - gone
            }
        }
    }
}

impl<'a, A> Baseiter<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<*mut A>
    {
        let index = match self.index {
            None => return None,
            Some(ref ix) => ix.clone(),
        };
        self.dim -= 1;
        let offset = Dimension::stride_offset(&self.dim, &self.strides);
        if index == self.dim {
            self.index = None;
        }

        unsafe {
            Some(self.ptr.offset(offset))
        }
    }

    #[inline]
    fn next_back_ref(&mut self) -> Option<&'a A>
    {
        unsafe { self.next_back().map(|p| &*p) }
    }

    #[inline]
    fn next_back_ref_mut(&mut self) -> Option<&'a mut A>
    {
        unsafe { self.next_back().map(|p| &mut *p) }
    }
}

impl<'a, A, D: Clone> Clone for Baseiter<'a, A, D>
{
    fn clone(&self) -> Baseiter<'a, A, D>
    {
        Baseiter {
            ptr: self.ptr,
            dim: self.dim.clone(),
            strides: self.strides.clone(),
            index: self.index.clone(),
            life: self.life,
        }
    }
}

impl<'a, A, D: Clone> Clone for ElementsBase<'a, A, D>
{
    fn clone(&self) -> ElementsBase<'a, A, D> { ElementsBase{inner: self.inner.clone()} }
}

impl<'a, A, D: Dimension> Iterator for ElementsBase<'a, A, D>
{
    type Item = &'a A;
    #[inline]
    fn next(&mut self) -> Option<&'a A>
    {
        self.inner.next_ref()
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.inner.size_hint();
        (len, Some(len))
    }
}

impl<'a, A> DoubleEndedIterator for ElementsBase<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a A>
    {
        self.inner.next_back_ref()
    }
}

impl<'a, A> ExactSizeIterator for ElementsBase<'a, A, Ix> { }

macro_rules! either {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            ElementsRepr::Slice(ref $inner) => $result,
            ElementsRepr::Counted(ref $inner) => $result,
        }
    )
}

macro_rules! either_mut {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            ElementsRepr::Slice(ref mut $inner) => $result,
            ElementsRepr::Counted(ref mut $inner) => $result,
        }
    )
}

impl<'a, A, D: Clone> Clone for Elements<'a, A, D>
{
    fn clone(&self) -> Elements<'a, A, D> {
        Elements {
            inner: match self.inner {
                ElementsRepr::Slice(ref iter) => ElementsRepr::Slice(iter.clone()),
                ElementsRepr::Counted(ref iter) => ElementsRepr::Counted(iter.clone()),
            }
        }
    }
}

impl<'a, A, D: Dimension> Iterator for Elements<'a, A, D>
{
    type Item = &'a A;
    #[inline]
    fn next(&mut self) -> Option<&'a A> {
        either_mut!(self.inner, iter => iter.next())
    }

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

impl<'a, A> DoubleEndedIterator for Elements<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a A> {
        either_mut!(self.inner, iter => iter.next_back())
    }
}

impl<'a, A> ExactSizeIterator for Elements<'a, A, Ix> { }

impl<'a, A, D: Dimension> Iterator for Indexed<'a, A, D>
{
    type Item = (D, &'a A);
    #[inline]
    fn next(&mut self) -> Option<(D, &'a A)>
    {
        let index = match self.0.inner.index {
            None => return None,
            Some(ref ix) => ix.clone()
        };
        match self.0.inner.next_ref() {
            None => None,
            Some(p) => Some((index, p))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.0.inner.size_hint();
        (len, Some(len))
    }
}

impl<'a, A, D: Dimension> Iterator for ElementsMut<'a, A, D>
{
    type Item = &'a mut A;
    #[inline]
    fn next(&mut self) -> Option<&'a mut A> {
        either_mut!(self.inner, iter => iter.next())
    }

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

impl<'a, A> DoubleEndedIterator for ElementsMut<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a mut A> {
        either_mut!(self.inner, iter => iter.next_back())
    }
}

impl<'a, A, D: Dimension> Iterator for ElementsBaseMut<'a, A, D>
{
    type Item = &'a mut A;
    #[inline]
    fn next(&mut self) -> Option<&'a mut A>
    {
        self.inner.next_ref_mut()
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.inner.size_hint();
        (len, Some(len))
    }
}

impl<'a, A> DoubleEndedIterator for ElementsBaseMut<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a mut A>
    {
        self.inner.next_back_ref_mut()
    }
}

impl<'a, A, D: Dimension> Iterator for IndexedMut<'a, A, D>
{
    type Item = (D, &'a mut A);
    #[inline]
    fn next(&mut self) -> Option<(D, &'a mut A)>
    {
        let index = match self.0.inner.index {
            None => return None,
            Some(ref ix) => ix.clone()
        };
        match self.0.inner.next_ref_mut() {
            None => None,
            Some(p) => Some((index, p))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.0.inner.size_hint();
        (len, Some(len))
    }
}

/// an iterator that traverses over all dimensions but the innermost,
/// and yields each inner row.
pub struct InnerIter<'a, A: 'a, D> {
    inner_len: Ix,
    inner_stride: Ixs,
    iter: Baseiter<'a, A, D>,
}

pub fn new_outer<A, D>(mut v: ArrayView<A, D>) -> InnerIter<A, D>
    where D: Dimension,
{
    if v.shape().len() == 0 {
        InnerIter {
            inner_len: 1,
            inner_stride: 1,
            iter: v.into_base_iter(),
        }
    } else {
        // Set length of innerest dimension to 1, start iteration
        let ndim = v.shape().len();
        let len = v.shape()[ndim - 1];
        let stride = v.strides()[ndim - 1];
        v.dim.slice_mut()[ndim - 1] = 1;
        InnerIter {
            inner_len: len,
            inner_stride: stride,
            iter: v.into_base_iter(),
        }
    }
}

impl<'a, A, D> Iterator for InnerIter<'a, A, D>
    where D: Dimension,
{
    type Item = ArrayView<'a, A, Ix>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|ptr| {
            let view = ArrayView {
                data: &[],
                ptr: ptr,
                dim: self.inner_len,
                strides: self.inner_stride as Ix,
            };
            view
        })
    }
}

// NOTE: InnerIterMut is a mutable iterator and must not expose aliasing
// pointers. Due to this we use an empty slice for the raw data (it's unused
// anyway).
/// an iterator that traverses over all dimensions but the innermost,
/// and yields each inner row (mutable).
pub struct InnerIterMut<'a, A: 'a, D> {
    inner_len: Ix,
    inner_stride: Ixs,
    iter: Baseiter<'a, A, D>,
}

pub fn new_outer_mut<A, D>(mut v: ArrayViewMut<A, D>) -> InnerIterMut<A, D>
    where D: Dimension,
{
    if v.shape().len() == 0 {
        InnerIterMut {
            inner_len: 1,
            inner_stride: 1,
            iter: v.into_base_iter(),
        }
    } else {
        // Set length of innerest dimension to 1, start iteration
        let ndim = v.shape().len();
        let len = v.shape()[ndim - 1];
        let stride = v.strides()[ndim - 1];
        v.dim.slice_mut()[ndim - 1] = 1;
        InnerIterMut {
            inner_len: len,
            inner_stride: stride,
            iter: v.into_base_iter(),
        }
    }
}

impl<'a, A, D> Iterator for InnerIterMut<'a, A, D>
    where D: Dimension,
{
    type Item = ArrayViewMut<'a, A, Ix>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|ptr| {
            let view = ArrayViewMut {
                data: &mut [],
                ptr: ptr,
                dim: self.inner_len,
                strides: self.inner_stride as Ix,
            };
            view
        })
    }
}
<commit_msg>Edit doc<commit_after>use std::marker;

use super::{Dimension, Ix, Ixs};
use super::{Elements, ElementsRepr, ElementsBase, ElementsBaseMut, ElementsMut, Indexed, IndexedMut};
use super::{
    ArrayView,
    ArrayViewMut,
};

/// Base for array iterators
///
/// Iterator element type is `&'a A`.
pub struct Baseiter<'a, A: 'a, D> {
    // Can have pub fields because it is not itself pub.
    pub ptr: *mut A,
    pub dim: D,
    pub strides: D,
    pub index: Option<D>,
    pub life: marker::PhantomData<&'a A>,
}

impl<'a, A, D: Dimension> Baseiter<'a, A, D>
{
    /// Creating a Baseiter is unsafe, because it can
    /// have any lifetime, be immut or mut, and the
    /// boundary and stride parameters need to be correct to
    /// avoid memory unsafety.
    ///
    /// It must be placed in the correct mother iterator to be safe.
    ///
    /// NOTE: Mind the lifetime, it's arbitrary
    #[inline]
    pub unsafe fn new(ptr: *mut A, len: D, stride: D) -> Baseiter<'a, A, D>
    {
        Baseiter {
            ptr: ptr,
            index: len.first_index(),
            dim: len,
            strides: stride,
            life: marker::PhantomData,
        }
    }
}

impl<'a, A, D: Dimension> Baseiter<'a, A, D>
{
    #[inline]
    pub fn next(&mut self) -> Option<*mut A>
    {
        let index = match self.index {
            None => return None,
            Some(ref ix) => ix.clone(),
        };
        let offset = Dimension::stride_offset(&index, &self.strides);
        self.index = self.dim.next_for(index);
        unsafe {
            Some(self.ptr.offset(offset))
        }
    }

    #[inline]
    fn next_ref(&mut self) -> Option<&'a A>
    {
        unsafe { self.next().map(|p| &*p) }
    }

    #[inline]
    fn next_ref_mut(&mut self) -> Option<&'a mut A>
    {
        unsafe { self.next().map(|p| &mut *p) }
    }

    fn size_hint(&self) -> usize
    {
        match self.index {
            None => 0,
            Some(ref ix) => {
                let gone = self.dim.default_strides().slice().iter()
                            .zip(ix.slice().iter())
                                 .fold(0, |s, (&a, &b)| s + a as usize * b as usize);
                self.dim.size() - gone
            }
        }
    }
}

impl<'a, A> Baseiter<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<*mut A>
    {
        let index = match self.index {
            None => return None,
            Some(ref ix) => ix.clone(),
        };
        self.dim -= 1;
        let offset = Dimension::stride_offset(&self.dim, &self.strides);
        if index == self.dim {
            self.index = None;
        }

        unsafe {
            Some(self.ptr.offset(offset))
        }
    }

    #[inline]
    fn next_back_ref(&mut self) -> Option<&'a A>
    {
        unsafe { self.next_back().map(|p| &*p) }
    }

    #[inline]
    fn next_back_ref_mut(&mut self) -> Option<&'a mut A>
    {
        unsafe { self.next_back().map(|p| &mut *p) }
    }
}

impl<'a, A, D: Clone> Clone for Baseiter<'a, A, D>
{
    fn clone(&self) -> Baseiter<'a, A, D>
    {
        Baseiter {
            ptr: self.ptr,
            dim: self.dim.clone(),
            strides: self.strides.clone(),
            index: self.index.clone(),
            life: self.life,
        }
    }
}

impl<'a, A, D: Clone> Clone for ElementsBase<'a, A, D>
{
    fn clone(&self) -> ElementsBase<'a, A, D> { ElementsBase{inner: self.inner.clone()} }
}

impl<'a, A, D: Dimension> Iterator for ElementsBase<'a, A, D>
{
    type Item = &'a A;
    #[inline]
    fn next(&mut self) -> Option<&'a A>
    {
        self.inner.next_ref()
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.inner.size_hint();
        (len, Some(len))
    }
}

impl<'a, A> DoubleEndedIterator for ElementsBase<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a A>
    {
        self.inner.next_back_ref()
    }
}

impl<'a, A> ExactSizeIterator for ElementsBase<'a, A, Ix> { }

macro_rules! either {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            ElementsRepr::Slice(ref $inner) => $result,
            ElementsRepr::Counted(ref $inner) => $result,
        }
    )
}

macro_rules! either_mut {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            ElementsRepr::Slice(ref mut $inner) => $result,
            ElementsRepr::Counted(ref mut $inner) => $result,
        }
    )
}

impl<'a, A, D: Clone> Clone for Elements<'a, A, D>
{
    fn clone(&self) -> Elements<'a, A, D> {
        Elements {
            inner: match self.inner {
                ElementsRepr::Slice(ref iter) => ElementsRepr::Slice(iter.clone()),
                ElementsRepr::Counted(ref iter) => ElementsRepr::Counted(iter.clone()),
            }
        }
    }
}

impl<'a, A, D: Dimension> Iterator for Elements<'a, A, D>
{
    type Item = &'a A;
    #[inline]
    fn next(&mut self) -> Option<&'a A> {
        either_mut!(self.inner, iter => iter.next())
    }

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

impl<'a, A> DoubleEndedIterator for Elements<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a A> {
        either_mut!(self.inner, iter => iter.next_back())
    }
}

impl<'a, A> ExactSizeIterator for Elements<'a, A, Ix> { }

impl<'a, A, D: Dimension> Iterator for Indexed<'a, A, D>
{
    type Item = (D, &'a A);
    #[inline]
    fn next(&mut self) -> Option<(D, &'a A)>
    {
        let index = match self.0.inner.index {
            None => return None,
            Some(ref ix) => ix.clone()
        };
        match self.0.inner.next_ref() {
            None => None,
            Some(p) => Some((index, p))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.0.inner.size_hint();
        (len, Some(len))
    }
}

impl<'a, A, D: Dimension> Iterator for ElementsMut<'a, A, D>
{
    type Item = &'a mut A;
    #[inline]
    fn next(&mut self) -> Option<&'a mut A> {
        either_mut!(self.inner, iter => iter.next())
    }

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

impl<'a, A> DoubleEndedIterator for ElementsMut<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a mut A> {
        either_mut!(self.inner, iter => iter.next_back())
    }
}

impl<'a, A, D: Dimension> Iterator for ElementsBaseMut<'a, A, D>
{
    type Item = &'a mut A;
    #[inline]
    fn next(&mut self) -> Option<&'a mut A>
    {
        self.inner.next_ref_mut()
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.inner.size_hint();
        (len, Some(len))
    }
}

impl<'a, A> DoubleEndedIterator for ElementsBaseMut<'a, A, Ix>
{
    #[inline]
    fn next_back(&mut self) -> Option<&'a mut A>
    {
        self.inner.next_back_ref_mut()
    }
}

impl<'a, A, D: Dimension> Iterator for IndexedMut<'a, A, D>
{
    type Item = (D, &'a mut A);
    #[inline]
    fn next(&mut self) -> Option<(D, &'a mut A)>
    {
        let index = match self.0.inner.index {
            None => return None,
            Some(ref ix) => ix.clone()
        };
        match self.0.inner.next_ref_mut() {
            None => None,
            Some(p) => Some((index, p))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let len = self.0.inner.size_hint();
        (len, Some(len))
    }
}

/// An iterator that traverses over all dimensions but the innermost,
/// and yields each inner row.
pub struct InnerIter<'a, A: 'a, D> {
    inner_len: Ix,
    inner_stride: Ixs,
    iter: Baseiter<'a, A, D>,
}

pub fn new_outer<A, D>(mut v: ArrayView<A, D>) -> InnerIter<A, D>
    where D: Dimension,
{
    if v.shape().len() == 0 {
        InnerIter {
            inner_len: 1,
            inner_stride: 1,
            iter: v.into_base_iter(),
        }
    } else {
        // Set length of innerest dimension to 1, start iteration
        let ndim = v.shape().len();
        let len = v.shape()[ndim - 1];
        let stride = v.strides()[ndim - 1];
        v.dim.slice_mut()[ndim - 1] = 1;
        InnerIter {
            inner_len: len,
            inner_stride: stride,
            iter: v.into_base_iter(),
        }
    }
}

impl<'a, A, D> Iterator for InnerIter<'a, A, D>
    where D: Dimension,
{
    type Item = ArrayView<'a, A, Ix>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|ptr| {
            let view = ArrayView {
                data: &[],
                ptr: ptr,
                dim: self.inner_len,
                strides: self.inner_stride as Ix,
            };
            view
        })
    }
}

// NOTE: InnerIterMut is a mutable iterator and must not expose aliasing
// pointers. Due to this we use an empty slice for the raw data (it's unused
// anyway).
/// An iterator that traverses over all dimensions but the innermost,
/// and yields each inner row (mutable).
pub struct InnerIterMut<'a, A: 'a, D> {
    inner_len: Ix,
    inner_stride: Ixs,
    iter: Baseiter<'a, A, D>,
}

pub fn new_outer_mut<A, D>(mut v: ArrayViewMut<A, D>) -> InnerIterMut<A, D>
    where D: Dimension,
{
    if v.shape().len() == 0 {
        InnerIterMut {
            inner_len: 1,
            inner_stride: 1,
            iter: v.into_base_iter(),
        }
    } else {
        // Set length of innerest dimension to 1, start iteration
        let ndim = v.shape().len();
        let len = v.shape()[ndim - 1];
        let stride = v.strides()[ndim - 1];
        v.dim.slice_mut()[ndim - 1] = 1;
        InnerIterMut {
            inner_len: len,
            inner_stride: stride,
            iter: v.into_base_iter(),
        }
    }
}

impl<'a, A, D> Iterator for InnerIterMut<'a, A, D>
    where D: Dimension,
{
    type Item = ArrayViewMut<'a, A, Ix>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|ptr| {
            let view = ArrayViewMut {
                data: &mut [],
                ptr: ptr,
                dim: self.inner_len,
                strides: self.inner_stride as Ix,
            };
            view
        })
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::client::Context;
use crate::model::channel::Message;
use uwl::{StrExt, StringStream};

#[derive(Debug, Clone, PartialEq)]
pub enum Prefix<'a> {
    Punct(&'a str),
    Mention(&'a str),
    None,
    #[doc(hidden)]
    __Nonexhaustive,
}

pub fn parse_prefix<'a>(
    ctx: &mut Context,
    msg: &'a Message,
    config: &Configuration,
) -> (Prefix<'a>, &'a str) {
    let mut stream = StringStream::new(&msg.content);
    stream.take_while(|s| s.is_whitespace());

    if let Some(ref mention) = config.on_mention {
        if let Ok(id) = stream.parse("<@(!){}>") {
            if id.is_numeric() && mention == id {
                stream.take_while(|s| s.is_whitespace());
                return (Prefix::Mention(id), stream.rest());
            }
        }
    }

    let mut prefix = None;
    if !config.prefixes.is_empty() || !config.dynamic_prefixes.is_empty() {
        for f in &config.dynamic_prefixes {
            if let Some(p) = f(ctx, msg) {
                let pp = stream.peek_for(p.chars().count());

                if p == pp {
                    prefix = Some(pp);
                    break;
                }
            }
        }

        for p in &config.prefixes {
            // If `dynamic_prefixes` succeeded, don't iterate through the normal prefixes.
            if prefix.is_some() {
                break;
            }

            let pp = stream.peek_for(p.chars().count());

            if p == pp {
                prefix = Some(pp);
                break;
            }
        }
    }

    if let Some(prefix) = prefix {
        stream.increment(prefix.len());

        if config.with_whitespace.prefixes {
            stream.take_while(|s| s.is_whitespace());
        }

        let args = stream.rest();

        return (Prefix::Punct(prefix), args.trim());
    }

    if config.with_whitespace.prefixes {
        stream.take_while(|s| s.is_whitespace());
    }

    let args = stream.rest();
    (Prefix::None, args.trim())
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone, Copy, PartialEq)]
enum ParseMode {
    BySpace,
    ByLength,
}

struct CommandParser<'msg, 'groups, 'config, 'ctx> {
    msg: &'msg Message,
    stream: StringStream<'msg>,
    groups: &'groups [&'static CommandGroup],
    config: &'config Configuration,
    ctx: &'ctx Context,
    mode: ParseMode,
    unrecognised: Option<&'msg str>,
}

impl<'msg, 'groups, 'config, 'ctx> CommandParser<'msg, 'groups, 'config, 'ctx> {
    fn new(
        msg: &'msg Message,
        stream: StringStream<'msg>,
        groups: &'groups [&'static CommandGroup],
        config: &'config Configuration,
        ctx: &'ctx Context,
    ) -> Self {
        CommandParser {
            msg,
            stream,
            groups,
            config,
            ctx,
            mode: if config.by_space { ParseMode::BySpace } else { ParseMode::ByLength },
            unrecognised: None,
        }
    }

    fn next_text(&self, length: impl FnOnce() -> usize) -> &'msg str {
        match self.mode {
            ParseMode::ByLength => self.stream.peek_for(length()),
            ParseMode::BySpace => self.stream.peek_until(|s| s.is_whitespace()),
        }
    }

    fn as_lowercase(&self, s: &str, f: impl FnOnce(&str) -> bool) -> bool {
        if self.config.case_insensitive {
            let s = s.to_lowercase();
            f(&s)
        } else {
            f(s)
        }
    }

    fn check_discrepancy(&self, options: &impl CommonOptions) -> Result<(), DispatchError> {
        if options.owners_only() {
            return Err(DispatchError::OnlyForOwners);
        }

        if options.only_in() == OnlyIn::Dm && !self.msg.is_private() {
            return Err(DispatchError::OnlyForDM);
        }

        if (!self.config.allow_dm || options.only_in() == OnlyIn::Guild) && self.msg.is_private() {
            return Err(DispatchError::OnlyForGuilds);
        }

        #[cfg(feature = "cache")]
        {
            if let Some(guild_id) = self.msg.guild_id {
                let guild = match guild_id.to_guild_cached(&self.ctx) {
                    Some(g) => g,
                    None => return Ok(()),
                };

                let guild = guild.read();

                let perms = guild.permissions_in(self.msg.channel_id, self.msg.author.id);

                if !perms.contains(*options.required_permissions()) {
                    return Err(DispatchError::LackingPermissions(*options.required_permissions()));
                }

                if let Some(member) = guild.members.get(&self.msg.author.id) {
                    if !perms.administrator() && !has_correct_roles(options, &guild, &member) {
                        return Err(DispatchError::LackingRole);
                    }
                }

            }
        }

        Ok(())
    }

    fn command(&mut self, command: &'static Command) -> Result<Option<&'static Command>, DispatchError> {
        for name in command.options.names {
            // FIXME: If `by_space` option is set true, we shouldn't be retrieving the block of text
            // again and again for the command name.
            let n = self.next_text(|| name.chars().count());

            let equals = self.as_lowercase(n, |n| n == *name && !self.config.disabled_commands.contains(n));

            if equals {
                self.stream.increment(n.len());

                if self.config.with_whitespace.commands {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub in command.options.sub_commands {
                    if let Some(cmd) = self.command(sub)? {
                        self.unrecognised = None;
                        return Ok(Some(cmd));
                    }
                }

                self.check_discrepancy(&command.options)?;

                self.unrecognised = None;
                return Ok(Some(command));
            }

            self.unrecognised = Some(n);
        }

        Ok(None)
    }

    fn group(&mut self, group: &'static CommandGroup) -> Result<(Option<&'msg str>, &'static CommandGroup), DispatchError> {
        for p in group.options.prefixes {
            let pp = self.next_text(|| p.chars().count());

            if *p == pp {
                self.stream.increment(pp.len());

                if self.config.with_whitespace.groups {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub_group in group.sub_groups {
                    let x = self.group(*sub_group)?;

                    if x.0.is_some() {
                        return Ok(x);
                    }
                }

                self.check_discrepancy(&group.options)?;
                return Ok((Some(pp), group));
            }
        }

        Ok((None, group))
    }

    fn parse(mut self, prefix: Prefix<'msg>) -> Result<Invoke<'msg>, Result<Option<&'msg str>, DispatchError>> {
        let pos = self.stream.offset();
        for group in self.groups {
            let (gprefix, group) = match self.group(*group) {
                Ok(t) => t,
                Err(err) => return Err(Err(err)),
            };

            if gprefix.is_none() && !group.options.prefixes.is_empty() {
                unsafe { self.stream.set_unchecked(pos) };
                continue;
            }

            for command in group.commands {
                let command = match self.command(command)  {
                    Ok(c) => c,
                    Err(err) => return Err(Err(err)),
                };

                if let Some(command) = command {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            // Only execute the default command if a group prefix is present.
            if let Some(command) = group.options.default_command {
                if gprefix.is_some() {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            unsafe { self.stream.set_unchecked(pos) };
        }

        Err(Ok(self.unrecognised))
    }
}

pub(crate) fn parse_command<'a>(
    message: &'a str,
    msg: &'a Message,
    prefix: Prefix<'a>,
    groups: &[&'static CommandGroup],
    config: &Configuration,
    ctx: &Context,
    help_was_set: Option<&[&'static str]>,
) -> Result<Invoke<'a>, Result<Option<&'a str>, DispatchError>> {
    let mut stream = StringStream::new(message);
    stream.take_while(|s| s.is_whitespace());

    // We take precedence over commands named help command's name.
    if let Some(names) = help_was_set {
        for name in names {
            if stream.eat(name) {
                stream.take_while(|s| s.is_whitespace());

                let args = stream.rest();

                return Ok(Invoke::Help { prefix, name, args });
            }
        }
    }

    CommandParser::new(msg, stream, groups, config, ctx).parse(prefix)
}

#[derive(Debug)]
pub enum Invoke<'a> {
    Command {
        prefix: Prefix<'a>,
        // Group prefix
        gprefix: Option<&'a str>,

        group: &'static CommandGroup,
        command: &'static Command,
        args: &'a str,
    },
    Help {
        prefix: Prefix<'a>,
        name: &'static str,
        args: &'a str,
    },
}
<commit_msg>Check if message author is in owners HashSet (#598)<commit_after>use super::*;
use crate::client::Context;
use crate::model::channel::Message;
use uwl::{StrExt, StringStream};

#[derive(Debug, Clone, PartialEq)]
pub enum Prefix<'a> {
    Punct(&'a str),
    Mention(&'a str),
    None,
    #[doc(hidden)]
    __Nonexhaustive,
}

pub fn parse_prefix<'a>(
    ctx: &mut Context,
    msg: &'a Message,
    config: &Configuration,
) -> (Prefix<'a>, &'a str) {
    let mut stream = StringStream::new(&msg.content);
    stream.take_while(|s| s.is_whitespace());

    if let Some(ref mention) = config.on_mention {
        if let Ok(id) = stream.parse("<@(!){}>") {
            if id.is_numeric() && mention == id {
                stream.take_while(|s| s.is_whitespace());
                return (Prefix::Mention(id), stream.rest());
            }
        }
    }

    let mut prefix = None;
    if !config.prefixes.is_empty() || !config.dynamic_prefixes.is_empty() {
        for f in &config.dynamic_prefixes {
            if let Some(p) = f(ctx, msg) {
                let pp = stream.peek_for(p.chars().count());

                if p == pp {
                    prefix = Some(pp);
                    break;
                }
            }
        }

        for p in &config.prefixes {
            // If `dynamic_prefixes` succeeded, don't iterate through the normal prefixes.
            if prefix.is_some() {
                break;
            }

            let pp = stream.peek_for(p.chars().count());

            if p == pp {
                prefix = Some(pp);
                break;
            }
        }
    }

    if let Some(prefix) = prefix {
        stream.increment(prefix.len());

        if config.with_whitespace.prefixes {
            stream.take_while(|s| s.is_whitespace());
        }

        let args = stream.rest();

        return (Prefix::Punct(prefix), args.trim());
    }

    if config.with_whitespace.prefixes {
        stream.take_while(|s| s.is_whitespace());
    }

    let args = stream.rest();
    (Prefix::None, args.trim())
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone, Copy, PartialEq)]
enum ParseMode {
    BySpace,
    ByLength,
}

struct CommandParser<'msg, 'groups, 'config, 'ctx> {
    msg: &'msg Message,
    stream: StringStream<'msg>,
    groups: &'groups [&'static CommandGroup],
    config: &'config Configuration,
    ctx: &'ctx Context,
    mode: ParseMode,
    unrecognised: Option<&'msg str>,
}

impl<'msg, 'groups, 'config, 'ctx> CommandParser<'msg, 'groups, 'config, 'ctx> {
    fn new(
        msg: &'msg Message,
        stream: StringStream<'msg>,
        groups: &'groups [&'static CommandGroup],
        config: &'config Configuration,
        ctx: &'ctx Context,
    ) -> Self {
        CommandParser {
            msg,
            stream,
            groups,
            config,
            ctx,
            mode: if config.by_space { ParseMode::BySpace } else { ParseMode::ByLength },
            unrecognised: None,
        }
    }

    fn next_text(&self, length: impl FnOnce() -> usize) -> &'msg str {
        match self.mode {
            ParseMode::ByLength => self.stream.peek_for(length()),
            ParseMode::BySpace => self.stream.peek_until(|s| s.is_whitespace()),
        }
    }

    fn as_lowercase(&self, s: &str, f: impl FnOnce(&str) -> bool) -> bool {
        if self.config.case_insensitive {
            let s = s.to_lowercase();
            f(&s)
        } else {
            f(s)
        }
    }

    fn check_discrepancy(&self, options: &impl CommonOptions) -> Result<(), DispatchError> {
        if options.owners_only() && !self.config.owners.contains(&self.msg.author.id) {
            return Err(DispatchError::OnlyForOwners);
        }

        if options.only_in() == OnlyIn::Dm && !self.msg.is_private() {
            return Err(DispatchError::OnlyForDM);
        }

        if (!self.config.allow_dm || options.only_in() == OnlyIn::Guild) && self.msg.is_private() {
            return Err(DispatchError::OnlyForGuilds);
        }

        #[cfg(feature = "cache")]
        {
            if let Some(guild_id) = self.msg.guild_id {
                let guild = match guild_id.to_guild_cached(&self.ctx) {
                    Some(g) => g,
                    None => return Ok(()),
                };

                let guild = guild.read();

                let perms = guild.permissions_in(self.msg.channel_id, self.msg.author.id);

                if !perms.contains(*options.required_permissions()) {
                    return Err(DispatchError::LackingPermissions(*options.required_permissions()));
                }

                if let Some(member) = guild.members.get(&self.msg.author.id) {
                    if !perms.administrator() && !has_correct_roles(options, &guild, &member) {
                        return Err(DispatchError::LackingRole);
                    }
                }

            }
        }

        Ok(())
    }

    fn command(&mut self, command: &'static Command) -> Result<Option<&'static Command>, DispatchError> {
        for name in command.options.names {
            // FIXME: If `by_space` option is set true, we shouldn't be retrieving the block of text
            // again and again for the command name.
            let n = self.next_text(|| name.chars().count());

            let equals = self.as_lowercase(n, |n| n == *name && !self.config.disabled_commands.contains(n));

            if equals {
                self.stream.increment(n.len());

                if self.config.with_whitespace.commands {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub in command.options.sub_commands {
                    if let Some(cmd) = self.command(sub)? {
                        self.unrecognised = None;
                        return Ok(Some(cmd));
                    }
                }

                self.check_discrepancy(&command.options)?;

                self.unrecognised = None;
                return Ok(Some(command));
            }

            self.unrecognised = Some(n);
        }

        Ok(None)
    }

    fn group(&mut self, group: &'static CommandGroup) -> Result<(Option<&'msg str>, &'static CommandGroup), DispatchError> {
        for p in group.options.prefixes {
            let pp = self.next_text(|| p.chars().count());

            if *p == pp {
                self.stream.increment(pp.len());

                if self.config.with_whitespace.groups {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub_group in group.sub_groups {
                    let x = self.group(*sub_group)?;

                    if x.0.is_some() {
                        return Ok(x);
                    }
                }

                self.check_discrepancy(&group.options)?;
                return Ok((Some(pp), group));
            }
        }

        Ok((None, group))
    }

    fn parse(mut self, prefix: Prefix<'msg>) -> Result<Invoke<'msg>, Result<Option<&'msg str>, DispatchError>> {
        let pos = self.stream.offset();
        for group in self.groups {
            let (gprefix, group) = match self.group(*group) {
                Ok(t) => t,
                Err(err) => return Err(Err(err)),
            };

            if gprefix.is_none() && !group.options.prefixes.is_empty() {
                unsafe { self.stream.set_unchecked(pos) };
                continue;
            }

            for command in group.commands {
                let command = match self.command(command)  {
                    Ok(c) => c,
                    Err(err) => return Err(Err(err)),
                };

                if let Some(command) = command {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            // Only execute the default command if a group prefix is present.
            if let Some(command) = group.options.default_command {
                if gprefix.is_some() {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            unsafe { self.stream.set_unchecked(pos) };
        }

        Err(Ok(self.unrecognised))
    }
}

pub(crate) fn parse_command<'a>(
    message: &'a str,
    msg: &'a Message,
    prefix: Prefix<'a>,
    groups: &[&'static CommandGroup],
    config: &Configuration,
    ctx: &Context,
    help_was_set: Option<&[&'static str]>,
) -> Result<Invoke<'a>, Result<Option<&'a str>, DispatchError>> {
    let mut stream = StringStream::new(message);
    stream.take_while(|s| s.is_whitespace());

    // We take precedence over commands named help command's name.
    if let Some(names) = help_was_set {
        for name in names {
            if stream.eat(name) {
                stream.take_while(|s| s.is_whitespace());

                let args = stream.rest();

                return Ok(Invoke::Help { prefix, name, args });
            }
        }
    }

    CommandParser::new(msg, stream, groups, config, ctx).parse(prefix)
}

#[derive(Debug)]
pub enum Invoke<'a> {
    Command {
        prefix: Prefix<'a>,
        // Group prefix
        gprefix: Option<&'a str>,

        group: &'static CommandGroup,
        command: &'static Command,
        args: &'a str,
    },
    Help {
        prefix: Prefix<'a>,
        name: &'static str,
        args: &'a str,
    },
}
<|endoftext|>


<commit_before>
//! Back-end agnostic controller events.

use {Event, Input, Motion};

/// Components of a controller button event. Not guaranteed consistent across
/// backends.
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ControllerButton {
    /// Which controller was the button on.
    pub id: i32,
    /// Which button was pressed.
    pub button: u8,
}

impl ControllerButton {
    /// Create a new ControllerButton object. Intended for use by backends when
    /// emitting events.
    pub fn new(id: i32, button: u8) -> Self {
        ControllerButton {
            id: id,
            button: button,
        }
    }
}

/// Components of a controller hat move event (d-Pad).
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ControllerHat {
  /// Which Controller was the button on.
  pub id: i32,
  /// Which button was pressed.
  pub state: ::HatState,
  /// Which hat on the controller was changed
  pub which: u8,
}

impl ControllerHat {
  /// Create a new ControllerButton object. Intended for use by backends when
  /// emitting events.
  pub fn new(id: i32, which: u8, state: ::HatState) -> Self {
    ControllerHat {
      id, state, which,
    }
  }
}

/// Components of a controller axis move event. Not guaranteed consistent across
/// backends.
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct ControllerAxisArgs {
    /// Which controller moved.
    pub id: i32,
    /// The axis that moved.
    pub axis: u8,
    /// Position of the controller. Usually [-1.0, 1.0], though backends may use
    /// a different range for various devices.
    pub position: f64,
}

impl ControllerAxisArgs {
    /// Create a new ControllerAxisArgs object. Intended for use by backends when
    /// emitting events.
    pub fn new(id: i32, axis: u8, position: f64) -> Self {
        ControllerAxisArgs {
            id: id,
            axis: axis,
            position: position,
        }
    }
}

/// The position of a controller axis changed.
pub trait ControllerAxisEvent: Sized {
    /// Creates a controller axis event.
    ///
    /// Preserves time stamp from original input event, if any.
    fn from_controller_axis_args(args: ControllerAxisArgs, old_event: &Self) -> Option<Self>;
    /// Calls closure if this is a controller axis event.
    fn controller_axis<U, F>(&self, f: F) -> Option<U> where F: FnMut(ControllerAxisArgs) -> U;
    /// Returns controller axis arguments.
    fn controller_axis_args(&self) -> Option<ControllerAxisArgs> {
        self.controller_axis(|args| args)
    }
}

impl ControllerAxisEvent for Event {
    fn from_controller_axis_args(args: ControllerAxisArgs, old_event: &Self) -> Option<Self> {
        let timestamp = if let Event::Input(_, x) = old_event {*x} else {None};
        Some(Event::Input(Input::Move(Motion::ControllerAxis(args)), timestamp))
    }

    fn controller_axis<U, F>(&self, mut f: F) -> Option<U>
        where F: FnMut(ControllerAxisArgs) -> U
    {
        match *self {
            Event::Input(Input::Move(Motion::ControllerAxis(args)), _) => Some(f(args)),
            _ => None,
        }
    }
}

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

    #[test]
    fn test_input_controller_axis() {
        let e: Event = ControllerAxisArgs::new(0, 1, 0.9).into();
        let a: Option<Event> =
            ControllerAxisEvent::from_controller_axis_args(ControllerAxisArgs::new(0, 1, 0.9), &e);
        let b: Option<Event> = a.clone()
            .unwrap()
            .controller_axis(|cnt| {
                ControllerAxisEvent::from_controller_axis_args(
                ControllerAxisArgs::new(cnt.id, cnt.axis, cnt.position),
                a.as_ref().unwrap())
            })
            .unwrap();
        assert_eq!(a, b);
    }
}
<commit_msg>Added `PartialOrd` for `ControllerAxisArgs`<commit_after>
//! Back-end agnostic controller events.

use {Event, Input, Motion};

/// Components of a controller button event. Not guaranteed consistent across
/// backends.
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ControllerButton {
    /// Which controller was the button on.
    pub id: i32,
    /// Which button was pressed.
    pub button: u8,
}

impl ControllerButton {
    /// Create a new ControllerButton object. Intended for use by backends when
    /// emitting events.
    pub fn new(id: i32, button: u8) -> Self {
        ControllerButton {
            id: id,
            button: button,
        }
    }
}

/// Components of a controller hat move event (d-Pad).
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ControllerHat {
  /// Which Controller was the button on.
  pub id: i32,
  /// Which button was pressed.
  pub state: ::HatState,
  /// Which hat on the controller was changed
  pub which: u8,
}

impl ControllerHat {
  /// Create a new ControllerButton object. Intended for use by backends when
  /// emitting events.
  pub fn new(id: i32, which: u8, state: ::HatState) -> Self {
    ControllerHat {
      id, state, which,
    }
  }
}

/// Components of a controller axis move event. Not guaranteed consistent across
/// backends.
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Debug)]
pub struct ControllerAxisArgs {
    /// Which controller moved.
    pub id: i32,
    /// The axis that moved.
    pub axis: u8,
    /// Position of the controller. Usually [-1.0, 1.0], though backends may use
    /// a different range for various devices.
    pub position: f64,
}

impl ControllerAxisArgs {
    /// Create a new ControllerAxisArgs object. Intended for use by backends when
    /// emitting events.
    pub fn new(id: i32, axis: u8, position: f64) -> Self {
        ControllerAxisArgs {
            id: id,
            axis: axis,
            position: position,
        }
    }
}

/// The position of a controller axis changed.
pub trait ControllerAxisEvent: Sized {
    /// Creates a controller axis event.
    ///
    /// Preserves time stamp from original input event, if any.
    fn from_controller_axis_args(args: ControllerAxisArgs, old_event: &Self) -> Option<Self>;
    /// Calls closure if this is a controller axis event.
    fn controller_axis<U, F>(&self, f: F) -> Option<U> where F: FnMut(ControllerAxisArgs) -> U;
    /// Returns controller axis arguments.
    fn controller_axis_args(&self) -> Option<ControllerAxisArgs> {
        self.controller_axis(|args| args)
    }
}

impl ControllerAxisEvent for Event {
    fn from_controller_axis_args(args: ControllerAxisArgs, old_event: &Self) -> Option<Self> {
        let timestamp = if let Event::Input(_, x) = old_event {*x} else {None};
        Some(Event::Input(Input::Move(Motion::ControllerAxis(args)), timestamp))
    }

    fn controller_axis<U, F>(&self, mut f: F) -> Option<U>
        where F: FnMut(ControllerAxisArgs) -> U
    {
        match *self {
            Event::Input(Input::Move(Motion::ControllerAxis(args)), _) => Some(f(args)),
            _ => None,
        }
    }
}

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

    #[test]
    fn test_input_controller_axis() {
        let e: Event = ControllerAxisArgs::new(0, 1, 0.9).into();
        let a: Option<Event> =
            ControllerAxisEvent::from_controller_axis_args(ControllerAxisArgs::new(0, 1, 0.9), &e);
        let b: Option<Event> = a.clone()
            .unwrap()
            .controller_axis(|cnt| {
                ControllerAxisEvent::from_controller_axis_args(
                ControllerAxisArgs::new(cnt.id, cnt.axis, cnt.position),
                a.as_ref().unwrap())
            })
            .unwrap();
        assert_eq!(a, b);
    }
}
<|endoftext|>


<commit_before>use std::convert::identity;

use futures::{future, stream, Future, Stream};
use log::{error, warn};
use rusoto_core::Region;
use rusoto_sqs::{
    DeleteMessageBatchRequest, DeleteMessageBatchRequestEntry, Message, ReceiveMessageRequest,
    Sqs as _, SqsClient,
};

pub fn sqs_receiver(
    queue_url: String,
    queue_region: Region,
) -> impl Stream<Item = Message, Error = ()> {
    // set up receiver client and receive request template
    let receive_client = SqsClient::new(queue_region.clone());
    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        wait_time_seconds: Some(10),
        max_number_of_messages: Some(10),
        ..Default::default()
    };
    // set up deleter client and delete request template
    let delete_client = SqsClient::new(queue_region.clone());
    let delete_request = DeleteMessageBatchRequest {
        queue_url: queue_url.clone(),
        ..Default::default()
    };

    // repeatedly poll for messages
    stream::unfold((), move |()| {
        Some(
            receive_client
                .receive_message(receive_request.clone())
                .map(|receive_result| (receive_result, ())),
        )
    })
    // log the errors and skip the errors
    .map_err(|e| error!("failed to receive message: {}", e))
    .then(|result| future::ok(result.ok()))
    .filter_map(identity)
    // delete messages from the queue
    .and_then(
        move |receive_result| -> Box<dyn Future<Item = Vec<Message>, Error = ()>> {
            let messages = receive_result.messages.unwrap_or_else(Vec::new);

            if messages.len() > 0 {
                // prepare delete request
                let delete_request = DeleteMessageBatchRequest {
                    entries: messages
                        .iter()
                        .filter_map(|message| message.receipt_handle.clone())
                        .enumerate()
                        .map(|(index, receipt_handle)| DeleteMessageBatchRequestEntry {
                            id: index.to_string(),
                            receipt_handle,
                        })
                        .collect(),
                    ..delete_request.clone()
                };

                // send delete request
                Box::new(delete_client.delete_message_batch(delete_request).then(
                    |delete_request_result| {
                        // log errors, if any
                        match delete_request_result {
                            Ok(ref delete_result) if delete_result.failed.len() > 0 => {
                                warn!("failed to delete some messages: {:?}", delete_result.failed);
                            }
                            Ok(_) => (),
                            Err(e) => {
                                error!("message delete request failed: {}", e);
                            }
                        }

                        // forward messages
                        future::ok(messages)
                    },
                ))
            } else {
                // timeout, no messages received
                Box::new(future::ok(messages))
            }
        },
    )
    // flatten messages to return one by one
    .map(|messages| stream::iter_ok(messages))
    .flatten()
}
<commit_msg>add missing Send bound<commit_after>use std::convert::identity;

use futures::{future, stream, Future, Stream};
use log::{error, warn};
use rusoto_core::Region;
use rusoto_sqs::{
    DeleteMessageBatchRequest, DeleteMessageBatchRequestEntry, Message, ReceiveMessageRequest,
    Sqs as _, SqsClient,
};

pub fn sqs_receiver(
    queue_url: String,
    queue_region: Region,
) -> impl Stream<Item = Message, Error = ()> {
    // set up receiver client and receive request template
    let receive_client = SqsClient::new(queue_region.clone());
    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        wait_time_seconds: Some(10),
        max_number_of_messages: Some(10),
        ..Default::default()
    };
    // set up deleter client and delete request template
    let delete_client = SqsClient::new(queue_region.clone());
    let delete_request = DeleteMessageBatchRequest {
        queue_url: queue_url.clone(),
        ..Default::default()
    };

    // repeatedly poll for messages
    stream::unfold((), move |()| {
        Some(
            receive_client
                .receive_message(receive_request.clone())
                .map(|receive_result| (receive_result, ())),
        )
    })
    // log the errors and skip the errors
    .map_err(|e| error!("failed to receive message: {}", e))
    .then(|result| future::ok(result.ok()))
    .filter_map(identity)
    // delete messages from the queue
    .and_then(
        move |receive_result| -> Box<dyn Future<Item = Vec<Message>, Error = ()> + Send> {
            let messages = receive_result.messages.unwrap_or_else(Vec::new);

            if messages.len() > 0 {
                // prepare delete request
                let delete_request = DeleteMessageBatchRequest {
                    entries: messages
                        .iter()
                        .filter_map(|message| message.receipt_handle.clone())
                        .enumerate()
                        .map(|(index, receipt_handle)| DeleteMessageBatchRequestEntry {
                            id: index.to_string(),
                            receipt_handle,
                        })
                        .collect(),
                    ..delete_request.clone()
                };

                // send delete request
                Box::new(delete_client.delete_message_batch(delete_request).then(
                    |delete_request_result| {
                        // log errors, if any
                        match delete_request_result {
                            Ok(ref delete_result) if delete_result.failed.len() > 0 => {
                                warn!("failed to delete some messages: {:?}", delete_result.failed);
                            }
                            Ok(_) => (),
                            Err(e) => {
                                error!("message delete request failed: {}", e);
                            }
                        }

                        // forward messages
                        future::ok(messages)
                    },
                ))
            } else {
                // timeout, no messages received
                Box::new(future::ok(messages))
            }
        },
    )
    // flatten messages to return one by one
    .map(|messages| stream::iter_ok(messages))
    .flatten()
}
<|endoftext|>


<commit_before>//! Tokenizes input strings.

use super::{SExpr, Cons, Nil, DataType, Operator, Literal, car, cdr};
use super::basictype::{BasicType, Boolean, Character, Number, String, Symbol};
use super::basictype::{NumericType, Floating, Integer};
use super::operator::OperatorType;

pub enum Token {
    LParen,
    RParen,
    Operator(OperatorType),
    Literal(BasicType)
}

pub fn tokenize(expr: &str) -> Result<Vec<Token>>, StrBuf> {
    let mut tokens = Vec::new();

    let mut i = 0;
    let len = expr.len();

    while i < len {
        let slice = expr.slice_from(i);

        if slice.chars().next().unwrap().is_whitespace() {
            i += 1;
            continue;
        }

        //Parentheses
        let token = match slice.chars().next().unwrap() {
            '(' => Some(LParen),
            ')' => Some(RParen),
            _   => None
        };
        if token.is_some() {
            tokens.push(token.unwrap());
            i += 1;
            continue;
        }

        //operators
        //there's at least one word, so it's safe to unwrap
        let word = slice.words().next().unwrap();

        //Discard dangling parens
        let word = word.slice(0, word.find(|c: char| c == ')').unwrap_or(word.len()));

        match operator::From_str(word) {
            Some(op_type)   => {
                tokens.push(Operator(op_type));
                i += word.len();
                continue;
            }
            _               => { } //do nothing
        };

        //Booleans
        match word {
            "#t"  => {
                tokens.push(Literal(Boolean(true)));
                i += word.len();
                continue;
            },
            "#f" => {
                tokens.push(Literal(Boolean(false)));
                i += word.len();
                continue;
            },
            _       => { } // do nothing
        }

        //Character literals
        if word.len() >= 2 && word.starts_with("\\#") && word.slice_from(1).starts_with("\\") {
            match word.len() {
                2   => tokens.push(Literal(Character(' '))),
                3   => tokens.push(Literal(Character(word.chars().nth(2).unwrap()))),
                _   => match word.slice_from(2) {
                    "space"     => tokens.push(Literal(Character(' '))),
                    "newline"   => tokens.push(Literal(Character('\n'))),
                    _           = {}
                }
            }

            i += word.len();
            continue;
        }

        //String literals
        if word.starts_with("\"") {
            let str_len = match expr.slice_from(i).find(|c: char| c == '\"') {
                Some(x) => x,
                None    => {
                    return Err("Unterminated quote!")
                }
            };

            tokens.push(Literal(String(expr.slice(i + 1, i + str_len + 1).to_strbuf())));
            i += str_len + 2; //add one to get to the next double quote, add one to escape that
            continue;
        }

        //Numeric literals (only machine words for now)
        let mut negative_counter = 0;
        let mut radix_point_counter = 0;

        for c in word.chars() {
            match c {
                '0'..'9'    => { }, //looks numeric to me
                '-'         => { negative_counter += 1 },
                '.'         => { radix_point_counter += 1 },
                _           => { return Err(("Unrecognized token".to_strbuf())) }
            }
        }

        match (negative_counter, radix_point_counter) {
            (0, 0) | (1, 0) => {
                match from_str::<int>(word) {
                    Some(x) => tokens.push(Literal(Number(Integer(x)))),
                    None    => {
                        return Err("Misplaced negative sign!".to_strbuf())
                    }
                }
            },

            (0, 1) | (1, 1) => {
                match from_str::<f64>(word) {
                    Some(x) => tokens.push(Literal(Number(Floating(x)))),
                    None    => {
                        return Err("Misplaced negative sign!".to_strbuf())
                    }
                }
            },

            _   => { return Err("Too many negative signs and/or points!".to_strbuf()) }
        }
    }

    Ok(tokens)
}
<commit_msg>I think this is a decent baseline to start from<commit_after>//! Tokenizes input strings.

use super::{SExpr, Cons, Nil, DataType, Operator, Literal, car, cdr};
use super::basictype::{BasicType, Boolean, Character, Number, String, Symbol};
use super::basictype::{NumericType, Floating, Integer};
use super::operator::OperatorType;

pub enum Token {
    LParen,
    RParen,
    Operator(OperatorType),
    Literal(BasicType),
    Symbol
}

pub fn tokenize(expr: &str) -> Result<Vec<Token>>, StrBuf> {
    let mut tokens = Vec::new();

    let mut i = 0;
    let len = expr.len();

    while i < len {
        let slice = expr.slice_from(i);

        if slice.chars().next().unwrap().is_whitespace() {
            i += 1;
            continue;
        }

        //Parentheses
        let token = match slice.chars().next().unwrap() {
            '(' => Some(LParen),
            ')' => Some(RParen),
            _   => None
        };
        if token.is_some() {
            tokens.push(token.unwrap());
            i += 1;
            continue;
        }

        //operators
        //there's at least one word, so it's safe to unwrap
        let word = slice.words().next().unwrap();

        //Discard dangling parens
        let word = word.slice(0, word.find(|c: char| c == ')').unwrap_or(word.len()));

        match operator::From_str(word) {
            Some(op_type)   => {
                tokens.push(Operator(op_type));
                i += word.len();
                continue;
            }
            _               => { } //do nothing
        };

        //Booleans
        match word {
            "#t"  => {
                tokens.push(Literal(Boolean(true)));
                i += word.len();
                continue;
            },
            "#f" => {
                tokens.push(Literal(Boolean(false)));
                i += word.len();
                continue;
            },
            _       => { } // do nothing
        }

        //Character literals
        if word.len() >= 2 && word.starts_with("\\#") && word.slice_from(1).starts_with("\\") {
            match word.len() {
                2   => tokens.push(Literal(Character(' '))),
                3   => tokens.push(Literal(Character(word.chars().nth(2).unwrap()))),
                _   => match word.slice_from(2) {
                    "space"     => tokens.push(Literal(Character(' '))),
                    "newline"   => tokens.push(Literal(Character('\n'))),
                    _           = {}
                }
            }

            i += word.len();
            continue;
        }

        //String literals
        if word.starts_with("\"") {
            let str_len = match expr.slice_from(i).find(|c: char| c == '\"') {
                Some(x) => x,
                None    => {
                    return Err("Unterminated quote!")
                }
            };

            tokens.push(Literal(String(expr.slice(i + 1, i + str_len + 1).to_strbuf())));
            i += str_len + 2; //add one to get to the next double quote, add one to escape that
            continue;
        }

        //Symbols/variables
        match word.chars().next().unwrap() {
            'a'..'z'|'A'..'Z'|'_'|'*'   => tokens.push(Literal(Symbol(word))),
            _   => {} //do nothing
        };

        //Numeric literals (only machine words for now)
        let mut negative_counter = 0;
        let mut radix_point_counter = 0;

        for c in word.chars() {
            match c {
                '0'..'9'    => { }, //looks numeric to me
                '-'         => { negative_counter += 1 },
                '.'         => { radix_point_counter += 1 },
                _           => { return Err(("Unrecognized token".to_strbuf())) }
            }
        }

        match (negative_counter, radix_point_counter) {
            (0, 0) | (1, 0) => {
                match from_str::<int>(word) {
                    Some(x) => tokens.push(Literal(Number(Integer(x)))),
                    None    => {
                        return Err("Misplaced negative sign!".to_strbuf())
                    }
                }
            },

            (0, 1) | (1, 1) => {
                match from_str::<f64>(word) {
                    Some(x) => tokens.push(Literal(Number(Floating(x)))),
                    None    => {
                        return Err("Misplaced negative sign!".to_strbuf())
                    }
                }
            },

            _   => { return Err("Too many negative signs and/or points!".to_strbuf()) }
        }
    }

    Ok(tokens)
}
<|endoftext|>


<commit_before>#![allow(unused_mut, unused_variables)]

use truetype::GlyphID;

use {Result, Tape, Value, Walue};
use glyph_substitution::{AlternateSet, ClassRuleSet, LigatureSet, RuleSet, Sequence};
use layout::Coverage;

/// A table.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Table {
    SingleSubstibution(SingleSubstibution),
    MultipleSubstibution(MultipleSubstibution),
    AlternateSubstibution(AlternateSubstibution),
    LigatureSubstibution(LigatureSubstibution),
    ContextSubstibution(ContextSubstibution),
    ChainedContextSubstibution(ChainedContextSubstibution),
    ExtensionSubstibution(ExtensionSubstibution),
    ReverseChainedContextSubstibution(ReverseChainedContextSubstibution),
}

/// A table for substituting one glyph with one glyph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SingleSubstibution {
    /// Format 1.
    Format1(SingleSubstibution1),
    /// Format 2.
    Format2(SingleSubstibution2),
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 1."]
    pub SingleSubstibution1 {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        delta_glyph_id  (i16), // DeltaGlyphID

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 2."]
    pub SingleSubstibution2 {
        format          (u16) = { 2 }, // SubstFormat
        coverage_offset (u16), // Coverage
        glyph_count     (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape, _| { // Substitute
            tape.take_given(this.glyph_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with more than one glyph."]
    pub MultipleSubstibution {
        format           (u16) = { 1 }, // SubstFormat
        coverage_offset  (u16), // Coverage
        sequence_count   (u16), // SequenceCount

        sequence_offsets (Vec<u16>) |this, tape, _| { // Sequence
            tape.take_given(this.sequence_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sequences (Vec<Sequence>) |this, tape, position| {
            jump_take!(tape, position, this.sequence_count, this.sequence_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one of many glyphs."]
    pub AlternateSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // AlternateSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // AlternateSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<AlternateSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting multiple glyphs with one glyph."]
    pub LigatureSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // LigSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // LigatureSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<LigatureSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

/// A table for substituting glyphs in a context.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ContextSubstibution {
    /// Format 1.
    Format1(ContextSubstibution1),
    /// Format 2.
    Format2(ContextSubstibution2),
    /// Format 3.
    Format3(ContextSubstibution3),
}

table! {
    @position
    #[doc = "A table for substituting glyphs in a context in format 1."]
    pub ContextSubstibution1 {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // SubRuleSetCount

        set_offsets (Vec<u16>) |this, tape, position| { // SubRuleSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<RuleSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting glyphs in a context in format 2."]
    pub ContextSubstibution2 {
        format          (u16) = { 2 }, // SubstFormat
        coverage_offset (u16), // Coverage
        class_offset    (u16), // ClassDef
        set_count       (u16), // SubClassSetCnt

        set_offsets (Vec<u16>) |this, tape, _| { // SubClassSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<ClassRuleSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

table! {
    #[doc = "A table for substituting glyphs in a context in format 3."]
    pub ContextSubstibution3 {
        format (u16) = { 3 }, // SubstFormat
    }
}

table! {
    #[doc = "A table for substituting glyphs in a chained context."]
    pub ChainedContextSubstibution {
    }
}

table! {
    #[doc = "A table for other types of substitution."]
    pub ExtensionSubstibution {
    }
}

table! {
    #[doc = "A table for substituting glyphs in reverse order in a chained context."]
    pub ReverseChainedContextSubstibution {
    }
}

impl Walue<u16> for Table {
    fn read<T: Tape>(tape: &mut T, kind: u16) -> Result<Self> {
        Ok(match kind {
            1 => Table::SingleSubstibution(try!(tape.take())),
            2 => Table::MultipleSubstibution(try!(tape.take())),
            3 => Table::AlternateSubstibution(try!(tape.take())),
            4 => Table::LigatureSubstibution(try!(tape.take())),
            5 => Table::ContextSubstibution(try!(tape.take())),
            6 => Table::ChainedContextSubstibution(try!(tape.take())),
            7 => Table::ExtensionSubstibution(try!(tape.take())),
            8 => Table::ReverseChainedContextSubstibution(try!(tape.take())),
            _ => raise!("found an unknown glyph-substitution type"),
        })
    }
}

impl Value for SingleSubstibution {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u16>()) {
            1 => SingleSubstibution::Format1(try!(tape.take())),
            2 => SingleSubstibution::Format2(try!(tape.take())),
            _ => raise!("found an unknown format of the single-substitution table"),
        })
    }
}

impl Value for ContextSubstibution {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u16>()) {
            1 => ContextSubstibution::Format1(try!(tape.take())),
            2 => ContextSubstibution::Format2(try!(tape.take())),
            3 => ContextSubstibution::Format3(try!(tape.take())),
            _ => raise!("found an unknown format of the context-substitution table"),
        })
    }
}
<commit_msg>Read the context-substitution table in format 3<commit_after>#![allow(unused_mut, unused_variables)]

use truetype::GlyphID;

use {Result, Tape, Value, Walue};
use glyph_substitution::{AlternateSet, ClassRuleSet, LigatureSet, RuleSet, Sequence, Substitution};
use layout::Coverage;

/// A table.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Table {
    SingleSubstibution(SingleSubstibution),
    MultipleSubstibution(MultipleSubstibution),
    AlternateSubstibution(AlternateSubstibution),
    LigatureSubstibution(LigatureSubstibution),
    ContextSubstibution(ContextSubstibution),
    ChainedContextSubstibution(ChainedContextSubstibution),
    ExtensionSubstibution(ExtensionSubstibution),
    ReverseChainedContextSubstibution(ReverseChainedContextSubstibution),
}

/// A table for substituting one glyph with one glyph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SingleSubstibution {
    /// Format 1.
    Format1(SingleSubstibution1),
    /// Format 2.
    Format2(SingleSubstibution2),
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 1."]
    pub SingleSubstibution1 {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        delta_glyph_id  (i16), // DeltaGlyphID

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 2."]
    pub SingleSubstibution2 {
        format          (u16) = { 2 }, // SubstFormat
        coverage_offset (u16), // Coverage
        glyph_count     (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape, _| { // Substitute
            tape.take_given(this.glyph_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with more than one glyph."]
    pub MultipleSubstibution {
        format           (u16) = { 1 }, // SubstFormat
        coverage_offset  (u16), // Coverage
        sequence_count   (u16), // SequenceCount

        sequence_offsets (Vec<u16>) |this, tape, _| { // Sequence
            tape.take_given(this.sequence_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sequences (Vec<Sequence>) |this, tape, position| {
            jump_take!(tape, position, this.sequence_count, this.sequence_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one of many glyphs."]
    pub AlternateSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // AlternateSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // AlternateSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<AlternateSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting multiple glyphs with one glyph."]
    pub LigatureSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // LigSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // LigatureSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<LigatureSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

/// A table for substituting glyphs in a context.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ContextSubstibution {
    /// Format 1.
    Format1(ContextSubstibution1),
    /// Format 2.
    Format2(ContextSubstibution2),
    /// Format 3.
    Format3(ContextSubstibution3),
}

table! {
    @position
    #[doc = "A table for substituting glyphs in a context in format 1."]
    pub ContextSubstibution1 {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // SubRuleSetCount

        set_offsets (Vec<u16>) |this, tape, position| { // SubRuleSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<RuleSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting glyphs in a context in format 2."]
    pub ContextSubstibution2 {
        format          (u16) = { 2 }, // SubstFormat
        coverage_offset (u16), // Coverage
        class_offset    (u16), // ClassDef
        set_count       (u16), // SubClassSetCnt

        set_offsets (Vec<u16>) |this, tape, _| { // SubClassSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        sets (Vec<ClassRuleSet>) |this, tape, position| {
            jump_take!(tape, position, this.set_count, this.set_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting glyphs in a context in format 3."]
    pub ContextSubstibution3 {
        format             (u16) = { 3 }, // SubstFormat
        glyph_count        (u16), // GlyphCount
        substitution_count (u16), // SubstCount

        coverage_offsets (Vec<u16>) |this, tape, _| { // Coverage
            tape.take_given(this.glyph_count as usize)
        },

        substitutions (Vec<Substitution>) |this, tape, _| { // SubstLookupRecord
            tape.take_given(this.substitution_count as usize)
        },

        coverages (Vec<Coverage>) |this, tape, position| {
            jump_take!(tape, position, this.glyph_count, this.coverage_offsets)
        },
    }
}

table! {
    #[doc = "A table for substituting glyphs in a chained context."]
    pub ChainedContextSubstibution {
    }
}

table! {
    #[doc = "A table for other types of substitution."]
    pub ExtensionSubstibution {
    }
}

table! {
    #[doc = "A table for substituting glyphs in reverse order in a chained context."]
    pub ReverseChainedContextSubstibution {
    }
}

impl Walue<u16> for Table {
    fn read<T: Tape>(tape: &mut T, kind: u16) -> Result<Self> {
        Ok(match kind {
            1 => Table::SingleSubstibution(try!(tape.take())),
            2 => Table::MultipleSubstibution(try!(tape.take())),
            3 => Table::AlternateSubstibution(try!(tape.take())),
            4 => Table::LigatureSubstibution(try!(tape.take())),
            5 => Table::ContextSubstibution(try!(tape.take())),
            6 => Table::ChainedContextSubstibution(try!(tape.take())),
            7 => Table::ExtensionSubstibution(try!(tape.take())),
            8 => Table::ReverseChainedContextSubstibution(try!(tape.take())),
            _ => raise!("found an unknown glyph-substitution type"),
        })
    }
}

impl Value for SingleSubstibution {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u16>()) {
            1 => SingleSubstibution::Format1(try!(tape.take())),
            2 => SingleSubstibution::Format2(try!(tape.take())),
            _ => raise!("found an unknown format of the single-substitution table"),
        })
    }
}

impl Value for ContextSubstibution {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u16>()) {
            1 => ContextSubstibution::Format1(try!(tape.take())),
            2 => ContextSubstibution::Format2(try!(tape.take())),
            3 => ContextSubstibution::Format3(try!(tape.take())),
            _ => raise!("found an unknown format of the context-substitution table"),
        })
    }
}
<|endoftext|>