<commit_before>//! Direct Memroy Access (DMA)

use core::cell::{Cell, UnsafeCell};
use core::marker::PhantomData;
use core::ops::Deref;
use core::ops;
use core::any::Any;

use nb;
use stm32f411::{DMA1, DMA2, dma2};

pub use stm32f411::dma2::scr::CHSELW as Channel;
pub use stm32f411::dma2::scr::DIRW as Direction;
pub use stm32f411::dma2::scr::MBURSTW as MemoryBurst;
pub use stm32f411::dma2::scr::PBURSTW as PeripheralBurst;
pub use stm32f411::dma2::scr::PLW as Priority;
pub use stm32f411::dma2::scr::MSIZEW as DataSize;

pub struct DMA1Stream0();
pub struct DMA2Stream1();
pub struct DMA2Stream4();

#[derive(Copy, Clone)]
pub enum DMAStream {
    Stream0,
    Stream1,
    Stream2,
    Stream3,
    Stream4,
    // Stream5,
    // Stream6,
    // Stream7,
}

/// DMA error
#[derive(Debug)]
pub enum Error {
    /// DMA channel in use
    InUse,
    /// Previous data got overwritten before it could be read because it was
    /// not accessed in a timely fashion
    Overrun,
    /// Transfer error
    Transfer,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum State {
    // A new `Buffer` starts in this state. We set it to zero to place this
    // buffer in the .bss section
    Unlocked = 0,

    Locked,
    MutLocked,
}

#[derive(Copy, Clone)]
pub enum Mode {
    Normal,
    Circular,
    PeripheralFlowControl,
}

pub unsafe trait DMA: Deref<Target = dma2::RegisterBlock> {
    fn scr(&self, stream: DMAStream) -> &dma2::SCR {
        match stream {
            DMAStream::Stream0 => &self.s0cr,
            DMAStream::Stream1 => &self.s1cr,
            DMAStream::Stream2 => &self.s2cr,
            DMAStream::Stream3 => &self.s3cr,
            DMAStream::Stream4 => &self.s4cr,
        }
    }

    fn sndtr(&self, stream: DMAStream) -> &dma2::SNDTR {
        match stream {
            DMAStream::Stream0 => &self.s0ndtr,
            DMAStream::Stream1 => &self.s1ndtr,
            DMAStream::Stream2 => &self.s2ndtr,
            DMAStream::Stream3 => &self.s3ndtr,
            DMAStream::Stream4 => &self.s4ndtr,
        }
    }

    fn spar(&self, stream: DMAStream) -> &dma2::SPAR {
        match stream {
            DMAStream::Stream0 => &self.s0par,
            DMAStream::Stream1 => &self.s1par,
            DMAStream::Stream2 => &self.s2par,
            DMAStream::Stream3 => &self.s3par,
            DMAStream::Stream4 => &self.s4par,
        }
    }

    fn sm0ar(&self, stream: DMAStream) -> &dma2::SM0AR {
        match stream {
            DMAStream::Stream0 => &self.s0m0ar,
            DMAStream::Stream1 => &self.s1m0ar,
            DMAStream::Stream2 => &self.s2m0ar,
            DMAStream::Stream3 => &self.s3m0ar,
            DMAStream::Stream4 => &self.s4m0ar,
        }
    }

    fn sm1ar(&self, stream: DMAStream) -> &dma2::SM1AR {
        match stream {
            DMAStream::Stream0 => &self.s0m1ar,
            DMAStream::Stream1 => &self.s1m1ar,
            DMAStream::Stream2 => &self.s2m1ar,
            DMAStream::Stream3 => &self.s3m1ar,
            DMAStream::Stream4 => &self.s4m1ar,
        }
    }

    fn sfcr(&self, stream: DMAStream) -> &dma2::SFCR {
        match stream {
            DMAStream::Stream0 => &self.s0fcr,
            DMAStream::Stream1 => &self.s1fcr,
            DMAStream::Stream2 => &self.s2fcr,
            DMAStream::Stream3 => &self.s3fcr,
            DMAStream::Stream4 => &self.s4fcr,
        }
    }
}

unsafe impl DMA for DMA1 {}

unsafe impl DMA for DMA2 {}

pub struct Dma<'a, U>
where
    U: Any + DMA,
{
    pub reg: &'a U,
    stream: DMAStream,
}
/*
impl<'a, U> Clone for DMAInstance<'a, U>
    where U: Any + DMA
{
    fn clone(&self) -> Self {
        *self
    }
}
*/
// impl<'a, U> Copy for DMAInstance<'a, U> where U: Any + DMA {}

impl<'a, U> Dma<'a, U>
where
    U: Any + DMA,
{
    pub fn new(reg: &'a U, stream: DMAStream) -> Dma<U> {
        Dma {
            reg: reg,
            stream: stream,
        }
    }

    pub fn init(&mut self, stream: DMAStream) {
        self.stream = stream;
    }

    pub fn channel(&self, channel: dma2::scr::CHSELW) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.chsel().variant(channel));
    }

    pub fn direction(&self, direction: Direction) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.dir().variant(direction));
    }

    pub fn peripheral_increment(&self, inc: bool) {
        if inc {
            self.reg.scr(self.stream).modify(|_, w| w.pinc().enable());
        } else {
            self.reg.scr(self.stream).modify(|_, w| w.pinc().disable());
        }
    }

    pub fn memory_increment(&self, inc: bool) {
        if inc {
            self.reg.scr(self.stream).modify(|_, w| w.minc().enable());
        } else {
            self.reg.scr(self.stream).modify(|_, w| w.minc().disable());
        }
    }

    pub fn periphdata_alignment(&self, size: DataSize) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.psize().variant(size));
    }

    pub fn memdata_alignment(&self, size: DataSize) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.msize().variant(size));
    }

    pub fn mode(&self, mode: Mode) {
        match mode {
            Mode::Normal => self.reg
                .scr(self.stream)
                .modify(|_, w| w.circ().clear_bit().pfctrl().clear_bit()),
            Mode::Circular => self.reg
                .scr(self.stream)
                .modify(|_, w| w.circ().enable().pfctrl().clear_bit()),
            Mode::PeripheralFlowControl => self.reg
                .scr(self.stream)
                .modify(|_, w| w.circ().disable().pfctrl().set_bit()),
        }
    }

    pub fn priority(&self, priority: Priority) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.pl().variant(priority));
    }

    // pub fn fifo_mode(&self) {
    //     self.reg.scr(self.stream).modify(|_, w| w.().variant(priority));
    // }

    // pub fn fifo_threshold(&self, ) {}

    pub fn memory_burst(&self, burst: MemoryBurst) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.mburst().variant(burst));
    }

    pub fn peripheral_burst(&self, burst: PeripheralBurst) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.pburst().variant(burst));
    }

    pub fn enable(&self) {
        self.reg.scr(self.stream).modify(|_, w| w.en().set_bit());
    }

    pub fn disable(&self) {
        self.reg.scr(self.stream).modify(|_, w| w.en().clear_bit());
    }

    pub fn is_enabled(&self) -> bool {
        if self.reg.scr(self.stream).read().en().bit_is_set() {
            true
        }
        else {
            false
        }
    }

    pub fn set_config(&self, src_address: u32, dst_address: u32, length: u16) {
        self.reg.sndtr(self.stream).write(|w| unsafe { w.ndt().bits(length) });
        if self.reg.scr(self.stream).read().dir().is_periph_to_memory() {
            self.reg.spar(self.stream).write(|w| unsafe { w.bits(src_address) });
            self.reg.sm0ar(self.stream).write(|w| unsafe { w.bits(dst_address) });
        }
        else {
            self.reg.spar(self.stream).write(|w| unsafe { w.bits(dst_address) });
            self.reg.sm0ar(self.stream).write(|w| unsafe { w.bits(src_address) });
        }
    }

}

// DMA buffer definitions
type BorrowFlag = usize;

const UNUSED: BorrowFlag = 0;
const WRITING: BorrowFlag = !0;

/// Wraps a borrowed reference to a value in a `Buffer`
pub struct Ref<'a, T>
where
    T: 'a,
{
    data: &'a T,
    flag: &'a Cell<BorrowFlag>,
}

impl<'a, T> ops::Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.data
    }
}

impl<'a, T> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        self.flag.set(self.flag.get() - 1);
    }
}

/// A wrapper type for a mutably borrowed value from a `Buffer`
pub struct RefMut<'a, T>
where
    T: 'a,
{
    data: &'a mut T,
    flag: &'a Cell<BorrowFlag>,
}

impl<'a, T> ops::Deref for RefMut<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.data
    }
}

impl<'a, T> ops::DerefMut for RefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.data
    }
}

impl<'a, T> Drop for RefMut<'a, T> {
    fn drop(&mut self) {
        self.flag.set(UNUSED);
    }
}

/// Buffer to be used with a certain DMA `CHANNEL`
// NOTE(packed) workaround for rust-lang/rust#41315
#[repr(packed)]
pub struct Buffer<T> {
    data: UnsafeCell<T>,
    flag: Cell<BorrowFlag>,
    state: Cell<State>,
    stream: DMAStream,
}

impl<T> Buffer<T> {
    /// Creates a new buffer
    pub const fn new(data: T, stream: DMAStream) -> Self {
        Buffer {
            stream: stream,
            data: UnsafeCell::new(data),
            state: Cell::new(State::Unlocked),
            flag: Cell::new(0),
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// # Panics
    ///
    /// Panics if the value is currently mutably borrowed.
    pub fn borrow(&self) -> Ref<T> {
        assert_ne!(self.flag.get(), WRITING);
        self.flag.set(self.flag.get() + 1);

        Ref {
            data: unsafe { &*self.data.get() },
            flag: &self.flag,
        }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// # Panics
    ///
    /// Panics if the value is currently borrowed.
    pub fn borrow_mut(&self) -> RefMut<T> {
        assert_eq!(self.flag.get(), UNUSED);
        self.flag.set(WRITING);

        RefMut {
            data: unsafe { &mut *self.data.get() },
            flag: &self.flag,
        }
    }

    pub(crate) fn lock(&self) -> &T {
        assert_eq!(self.state.get(), State::Unlocked);
        assert_ne!(self.flag.get(), WRITING);

        self.flag.set(self.flag.get() + 1);
        self.state.set(State::Locked);

        unsafe { &*self.data.get() }
    }

    pub(crate) fn lock_mut(&self) -> &mut T {
        assert_eq!(self.state.get(), State::Unlocked);
        assert_eq!(self.flag.get(), UNUSED);

        self.flag.set(WRITING);
        self.state.set(State::MutLocked);

        unsafe { &mut *self.data.get() }
    }

    unsafe fn unlock(&self, state: State) {
        match state {
            State::Locked => self.flag.set(self.flag.get() - 1),
            State::MutLocked => self.flag.set(UNUSED),
            _ => { /* unreachable!() */ }
        }

        self.state.set(State::Unlocked);
    }

    // FIXME these `release` methods probably want some of sort of barrier
    /// Waits until the DMA releases this buffer
    pub fn release<D:DMA>(&self, dma: &D) -> nb::Result<(), Error> {
        let state = self.state.get();

        if state == State::Unlocked {
            return Ok(());
        }

        let dma_status = match self.stream {
            DMAStream::Stream0 => (
                dma.lisr.read().teif0().bit_is_set(),
                dma.lisr.read().tcif0().bit_is_set(),
            ),
            DMAStream::Stream1 => (
                dma.lisr.read().teif1().bit_is_set(),
                dma.lisr.read().tcif1().bit_is_set(),
            ),
            DMAStream::Stream2 => (
                dma.lisr.read().teif2().bit_is_set(),
                dma.lisr.read().tcif2().bit_is_set(),
            ),
            DMAStream::Stream3 => (
                dma.lisr.read().teif3().bit_is_set(),
                dma.lisr.read().tcif3().bit_is_set(),
            ),
            DMAStream::Stream4 => (
                dma.hisr.read().teif4().bit_is_set(),
                dma.hisr.read().tcif4().bit_is_set(),
            ),
        };

        if dma_status.0 {
            return Err(nb::Error::Other(Error::Transfer));
        } else if dma_status.1 {
            unsafe { self.unlock(state) }
            match self.stream {
                DMAStream::Stream0 => dma.lifcr.write(|w| w.ctcif0().set_bit()),
                DMAStream::Stream1 => dma.lifcr.write(|w| w.ctcif1().set_bit()),
                DMAStream::Stream2 => dma.lifcr.write(|w| w.ctcif2().set_bit()),
                DMAStream::Stream3 => dma.lifcr.write(|w| w.ctcif3().set_bit()),
                DMAStream::Stream4 => dma.lifcr.write(|w| w.ctcif2().set_bit()),
            }

            dma.scr(self.stream).modify(|_, w| w.en().disable());
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
}
<commit_msg>Stream4 Rx flag was not cleared<commit_after>//! Direct Memroy Access (DMA)

use core::cell::{Cell, UnsafeCell};
use core::marker::PhantomData;
use core::ops::Deref;
use core::ops;
use core::any::Any;

use nb;
use stm32f411::{DMA1, DMA2, dma2};

pub use stm32f411::dma2::scr::CHSELW as Channel;
pub use stm32f411::dma2::scr::DIRW as Direction;
pub use stm32f411::dma2::scr::MBURSTW as MemoryBurst;
pub use stm32f411::dma2::scr::PBURSTW as PeripheralBurst;
pub use stm32f411::dma2::scr::PLW as Priority;
pub use stm32f411::dma2::scr::MSIZEW as DataSize;

pub struct DMA1Stream0();
pub struct DMA2Stream1();
pub struct DMA2Stream4();

#[derive(Copy, Clone)]
pub enum DMAStream {
    Stream0,
    Stream1,
    Stream2,
    Stream3,
    Stream4,
    // Stream5,
    // Stream6,
    // Stream7,
}

/// DMA error
#[derive(Debug)]
pub enum Error {
    /// DMA channel in use
    InUse,
    /// Previous data got overwritten before it could be read because it was
    /// not accessed in a timely fashion
    Overrun,
    /// Transfer error
    Transfer,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum State {
    // A new `Buffer` starts in this state. We set it to zero to place this
    // buffer in the .bss section
    Unlocked = 0,

    Locked,
    MutLocked,
}

#[derive(Copy, Clone)]
pub enum Mode {
    Normal,
    Circular,
    PeripheralFlowControl,
}

pub unsafe trait DMA: Deref<Target = dma2::RegisterBlock> {
    fn scr(&self, stream: DMAStream) -> &dma2::SCR {
        match stream {
            DMAStream::Stream0 => &self.s0cr,
            DMAStream::Stream1 => &self.s1cr,
            DMAStream::Stream2 => &self.s2cr,
            DMAStream::Stream3 => &self.s3cr,
            DMAStream::Stream4 => &self.s4cr,
        }
    }

    fn sndtr(&self, stream: DMAStream) -> &dma2::SNDTR {
        match stream {
            DMAStream::Stream0 => &self.s0ndtr,
            DMAStream::Stream1 => &self.s1ndtr,
            DMAStream::Stream2 => &self.s2ndtr,
            DMAStream::Stream3 => &self.s3ndtr,
            DMAStream::Stream4 => &self.s4ndtr,
        }
    }

    fn spar(&self, stream: DMAStream) -> &dma2::SPAR {
        match stream {
            DMAStream::Stream0 => &self.s0par,
            DMAStream::Stream1 => &self.s1par,
            DMAStream::Stream2 => &self.s2par,
            DMAStream::Stream3 => &self.s3par,
            DMAStream::Stream4 => &self.s4par,
        }
    }

    fn sm0ar(&self, stream: DMAStream) -> &dma2::SM0AR {
        match stream {
            DMAStream::Stream0 => &self.s0m0ar,
            DMAStream::Stream1 => &self.s1m0ar,
            DMAStream::Stream2 => &self.s2m0ar,
            DMAStream::Stream3 => &self.s3m0ar,
            DMAStream::Stream4 => &self.s4m0ar,
        }
    }

    fn sm1ar(&self, stream: DMAStream) -> &dma2::SM1AR {
        match stream {
            DMAStream::Stream0 => &self.s0m1ar,
            DMAStream::Stream1 => &self.s1m1ar,
            DMAStream::Stream2 => &self.s2m1ar,
            DMAStream::Stream3 => &self.s3m1ar,
            DMAStream::Stream4 => &self.s4m1ar,
        }
    }

    fn sfcr(&self, stream: DMAStream) -> &dma2::SFCR {
        match stream {
            DMAStream::Stream0 => &self.s0fcr,
            DMAStream::Stream1 => &self.s1fcr,
            DMAStream::Stream2 => &self.s2fcr,
            DMAStream::Stream3 => &self.s3fcr,
            DMAStream::Stream4 => &self.s4fcr,
        }
    }
}

unsafe impl DMA for DMA1 {}

unsafe impl DMA for DMA2 {}

pub struct Dma<'a, U>
where
    U: Any + DMA,
{
    pub reg: &'a U,
    stream: DMAStream,
}
/*
impl<'a, U> Clone for DMAInstance<'a, U>
    where U: Any + DMA
{
    fn clone(&self) -> Self {
        *self
    }
}
*/
// impl<'a, U> Copy for DMAInstance<'a, U> where U: Any + DMA {}

impl<'a, U> Dma<'a, U>
where
    U: Any + DMA,
{
    pub fn new(reg: &'a U, stream: DMAStream) -> Dma<U> {
        Dma {
            reg: reg,
            stream: stream,
        }
    }

    pub fn init(&mut self, stream: DMAStream) {
        self.stream = stream;
    }

    pub fn channel(&self, channel: dma2::scr::CHSELW) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.chsel().variant(channel));
    }

    pub fn direction(&self, direction: Direction) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.dir().variant(direction));
    }

    pub fn peripheral_increment(&self, inc: bool) {
        if inc {
            self.reg.scr(self.stream).modify(|_, w| w.pinc().enable());
        } else {
            self.reg.scr(self.stream).modify(|_, w| w.pinc().disable());
        }
    }

    pub fn memory_increment(&self, inc: bool) {
        if inc {
            self.reg.scr(self.stream).modify(|_, w| w.minc().enable());
        } else {
            self.reg.scr(self.stream).modify(|_, w| w.minc().disable());
        }
    }

    pub fn periphdata_alignment(&self, size: DataSize) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.psize().variant(size));
    }

    pub fn memdata_alignment(&self, size: DataSize) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.msize().variant(size));
    }

    pub fn mode(&self, mode: Mode) {
        match mode {
            Mode::Normal => self.reg
                .scr(self.stream)
                .modify(|_, w| w.circ().clear_bit().pfctrl().clear_bit()),
            Mode::Circular => self.reg
                .scr(self.stream)
                .modify(|_, w| w.circ().enable().pfctrl().clear_bit()),
            Mode::PeripheralFlowControl => self.reg
                .scr(self.stream)
                .modify(|_, w| w.circ().disable().pfctrl().set_bit()),
        }
    }

    pub fn priority(&self, priority: Priority) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.pl().variant(priority));
    }

    // pub fn fifo_mode(&self) {
    //     self.reg.scr(self.stream).modify(|_, w| w.().variant(priority));
    // }

    // pub fn fifo_threshold(&self, ) {}

    pub fn memory_burst(&self, burst: MemoryBurst) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.mburst().variant(burst));
    }

    pub fn peripheral_burst(&self, burst: PeripheralBurst) {
        self.reg
            .scr(self.stream)
            .modify(|_, w| w.pburst().variant(burst));
    }

    pub fn enable(&self) {
        self.reg.scr(self.stream).modify(|_, w| w.en().set_bit());
    }

    pub fn disable(&self) {
        self.reg.scr(self.stream).modify(|_, w| w.en().clear_bit());
    }

    pub fn is_enabled(&self) -> bool {
        if self.reg.scr(self.stream).read().en().bit_is_set() {
            true
        }
        else {
            false
        }
    }

    pub fn set_config(&self, src_address: u32, dst_address: u32, length: u16) {
        self.reg.sndtr(self.stream).write(|w| unsafe { w.ndt().bits(length) });
        if self.reg.scr(self.stream).read().dir().is_periph_to_memory() {
            self.reg.spar(self.stream).write(|w| unsafe { w.bits(src_address) });
            self.reg.sm0ar(self.stream).write(|w| unsafe { w.bits(dst_address) });
        }
        else {
            self.reg.spar(self.stream).write(|w| unsafe { w.bits(dst_address) });
            self.reg.sm0ar(self.stream).write(|w| unsafe { w.bits(src_address) });
        }
    }

}

// DMA buffer definitions
type BorrowFlag = usize;

const UNUSED: BorrowFlag = 0;
const WRITING: BorrowFlag = !0;

/// Wraps a borrowed reference to a value in a `Buffer`
pub struct Ref<'a, T>
where
    T: 'a,
{
    data: &'a T,
    flag: &'a Cell<BorrowFlag>,
}

impl<'a, T> ops::Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.data
    }
}

impl<'a, T> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        self.flag.set(self.flag.get() - 1);
    }
}

/// A wrapper type for a mutably borrowed value from a `Buffer`
pub struct RefMut<'a, T>
where
    T: 'a,
{
    data: &'a mut T,
    flag: &'a Cell<BorrowFlag>,
}

impl<'a, T> ops::Deref for RefMut<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.data
    }
}

impl<'a, T> ops::DerefMut for RefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.data
    }
}

impl<'a, T> Drop for RefMut<'a, T> {
    fn drop(&mut self) {
        self.flag.set(UNUSED);
    }
}

/// Buffer to be used with a certain DMA `CHANNEL`
// NOTE(packed) workaround for rust-lang/rust#41315
#[repr(packed)]
pub struct Buffer<T> {
    data: UnsafeCell<T>,
    flag: Cell<BorrowFlag>,
    state: Cell<State>,
    stream: DMAStream,
}

impl<T> Buffer<T> {
    /// Creates a new buffer
    pub const fn new(data: T, stream: DMAStream) -> Self {
        Buffer {
            stream: stream,
            data: UnsafeCell::new(data),
            state: Cell::new(State::Unlocked),
            flag: Cell::new(0),
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// # Panics
    ///
    /// Panics if the value is currently mutably borrowed.
    pub fn borrow(&self) -> Ref<T> {
        assert_ne!(self.flag.get(), WRITING);
        self.flag.set(self.flag.get() + 1);

        Ref {
            data: unsafe { &*self.data.get() },
            flag: &self.flag,
        }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// # Panics
    ///
    /// Panics if the value is currently borrowed.
    pub fn borrow_mut(&self) -> RefMut<T> {
        assert_eq!(self.flag.get(), UNUSED);
        self.flag.set(WRITING);

        RefMut {
            data: unsafe { &mut *self.data.get() },
            flag: &self.flag,
        }
    }

    pub(crate) fn lock(&self) -> &T {
        assert_eq!(self.state.get(), State::Unlocked);
        assert_ne!(self.flag.get(), WRITING);

        self.flag.set(self.flag.get() + 1);
        self.state.set(State::Locked);

        unsafe { &*self.data.get() }
    }

    pub(crate) fn lock_mut(&self) -> &mut T {
        assert_eq!(self.state.get(), State::Unlocked);
        assert_eq!(self.flag.get(), UNUSED);

        self.flag.set(WRITING);
        self.state.set(State::MutLocked);

        unsafe { &mut *self.data.get() }
    }

    unsafe fn unlock(&self, state: State) {
        match state {
            State::Locked => self.flag.set(self.flag.get() - 1),
            State::MutLocked => self.flag.set(UNUSED),
            _ => { /* unreachable!() */ }
        }

        self.state.set(State::Unlocked);
    }

    // FIXME these `release` methods probably want some of sort of barrier
    /// Waits until the DMA releases this buffer
    pub fn release<D:DMA>(&self, dma: &D) -> nb::Result<(), Error> {
        let state = self.state.get();

        if state == State::Unlocked {
            return Ok(());
        }

        let dma_status = match self.stream {
            DMAStream::Stream0 => (
                dma.lisr.read().teif0().bit_is_set(),
                dma.lisr.read().tcif0().bit_is_set(),
            ),
            DMAStream::Stream1 => (
                dma.lisr.read().teif1().bit_is_set(),
                dma.lisr.read().tcif1().bit_is_set(),
            ),
            DMAStream::Stream2 => (
                dma.lisr.read().teif2().bit_is_set(),
                dma.lisr.read().tcif2().bit_is_set(),
            ),
            DMAStream::Stream3 => (
                dma.lisr.read().teif3().bit_is_set(),
                dma.lisr.read().tcif3().bit_is_set(),
            ),
            DMAStream::Stream4 => (
                dma.hisr.read().teif4().bit_is_set(),
                dma.hisr.read().tcif4().bit_is_set(),
            ),
        };

        if dma_status.0 {
            return Err(nb::Error::Other(Error::Transfer));
        } else if dma_status.1 {
            unsafe { self.unlock(state) }
            match self.stream {
                DMAStream::Stream0 => dma.lifcr.write(|w| w.ctcif0().set_bit()),
                DMAStream::Stream1 => dma.lifcr.write(|w| w.ctcif1().set_bit()),
                DMAStream::Stream2 => dma.lifcr.write(|w| w.ctcif2().set_bit()),
                DMAStream::Stream3 => dma.lifcr.write(|w| w.ctcif3().set_bit()),
                DMAStream::Stream4 => dma.hifcr.write(|w| w.ctcif4().set_bit()),
            }

            dma.scr(self.stream).modify(|_, w| w.en().disable());
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
}
<|endoftext|>


<commit_before>use ast::{Expr, ConstExpr, BlockExpr, LocalExpr, GetConstFieldExpr, GetFieldExpr, CallExpr, WhileLoopExpr, IfExpr, SwitchExpr, ObjectDeclExpr, ArrayDeclExpr, FunctionDeclExpr, NumOpExpr, ConstructExpr, ReturnExpr, ThrowExpr, AssignExpr};
use ast::{CNum, CInt, CString, CBool, CRegExp, CNull, CUndefined};
use ast::{OpSub, OpAdd, OpMul, OpDiv, OpAnd, OpOr};
use js::value::{Value, VNull, VUndefined, VNumber, VString, VObject, VBoolean, VFunction, ResultValue};
use js::object::ObjectData;
use js::function::{RegularFunc, RegularFunction};
use js::{console, math, object, array, function, json};
use collections::treemap::TreeMap;
use std::vec::Vec;
use std::f64;
use std::gc::Gc;
use std::cell::RefCell;
/// An execution engine
pub trait Executor {
	/// Makes a new execution engine
	fn new() -> ~Self;
	/// Sets a global variable
	fn set_global(&mut self, name:~str, val:Value) -> ();
	/// Gets a global variable
	fn get_global(&self, name:~str) -> Value;
	/// Make a new scope
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>>;
	/// Destroy the current scope
	fn destroy_scope(&mut self) -> ();
	/// Runs the expression
	fn run(&mut self, expr:&Expr) -> ResultValue;
}
/// An intepreter
pub struct Interpreter {
	/// A hash map representing the global variables
	globals: ObjectData,
	/// The scopes
	scopes: Vec<Gc<RefCell<ObjectData>>>,
	/// The current function scope
	current_scope: uint
}
impl Executor for Interpreter {
	fn new() -> ~Interpreter {
		let mut globals : ObjectData = TreeMap::new();
		globals.swap(~"NaN", Gc::new(VNumber(f64::NAN)));
		globals.swap(~"Infinity", Gc::new(VNumber(f64::INFINITY)));
		globals.swap(~"console", console::_create());
		globals.swap(~"Math", math::_create());
		globals.swap(~"Object", object::_create());
		globals.swap(~"Array", array::_create());
		globals.swap(~"Function", function::_create());
		globals.swap(~"JSON", json::_create());
		return ~Interpreter {globals: globals, scopes: Vec::new(), current_scope: 0};
	}
	fn set_global(&mut self, name:~str, val:Value) {
		self.globals.swap(name, val);
	}
	fn get_global(&self, name:~str) -> Value {
		match self.globals.find(&name) {
			None => Gc::new(VUndefined),
			Some(ref g) => **g
		}
	}
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>> {
		let mut data = TreeMap::new();
		let value = Gc::new(RefCell::new(data));
		self.scopes.push(value.clone());
		value
	}
	fn destroy_scope(&mut self) -> () {
		self.scopes.pop();
	}
	fn run(&mut self, expr:&Expr) -> ResultValue {
		match *expr {
			ConstExpr(CNull) => Ok(Gc::new(VNull)),
			ConstExpr(CUndefined) => Ok(Gc::new(VUndefined)),
			ConstExpr(CNum(num)) => Ok(Gc::new(VNumber(num))),
			ConstExpr(CInt(num)) => Ok(Gc::new(VNumber(num as f64))),
			ConstExpr(CString(ref str)) => Ok(Gc::new(VString(str.to_owned()))),
			ConstExpr(CBool(val)) => Ok(Gc::new(VBoolean(val))),
			ConstExpr(CRegExp(ref reg, _, _)) => Ok(Gc::new(VBoolean(true))),
			BlockExpr(ref es) => {
				let mut obj = Gc::new(VNull);
				for e in es.iter() {
					let val = try!(self.run(*e));
					if e == es.last().unwrap() {
						obj = val;
					}
				}
				Ok(obj)
			},
			LocalExpr(ref name) => {
				let mut value = Gc::new(VUndefined);
				for scope in self.scopes.iter().rev() {
					println!("Searching {} for {}", scope.borrow().borrow().deref(), name.clone());
					match scope.borrow().borrow().find(name) {
						Some(v) => {
							value = v.clone();
							break;
						}
						None => ()
					}
				}
				Ok(if value.borrow() == &VUndefined {
					match self.globals.find(name) {
						None => Gc::new(VUndefined),
						Some(v) => v.clone()
					}
				} else {
					value
				})
			},
			GetConstFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				Ok(val_obj.borrow().get_field(field.clone()))
			},
			GetFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				let val_field = try!(self.run(*field));
				Ok(val_obj.borrow().get_field(val_field.borrow().to_str()))
			},
			CallExpr(ref callee, ref args) => {
				let func = try!(self.run(callee.clone()));
				let mut v_args = Vec::with_capacity(args.len());
				for arg in args.iter() {
					v_args.push(try!(self.run(*arg)));
				}
				Ok(match *func.borrow() {
					VFunction(ref func) => {
						let globals = self.globals.clone();
						func.borrow().call(self, Gc::new(VObject(RefCell::new(globals))), Gc::new(VNull), v_args).unwrap()
					},
					_ => Gc::new(VUndefined)
				})
			},
			WhileLoopExpr(ref cond, ref expr) => {
				let mut result = Gc::new(VUndefined);
				while try!(self.run(*cond)).borrow().is_true() {
					result = try!(self.run(*expr));
				}
				Ok(result)
			},
			IfExpr(ref cond, ref expr, None) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					Gc::new(VUndefined)
				})
			},
			IfExpr(ref cond, ref expr, Some(ref else_e)) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					try!(self.run(*else_e))
				})
			},
			SwitchExpr(ref val_e, ref vals, ref default) => {
				let val = try!(self.run(*val_e)).borrow().clone();
				let mut result = Gc::new(VNull);
				let mut matched = false;
				for tup in vals.iter() {
					let tup:&(~Expr, Vec<~Expr>) = tup;
					match *tup {
						(ref cond, ref block) if(val == *try!(self.run(*cond)).borrow()) => {
							matched = true;
							let last_expr = block.last().unwrap();
							for expr in block.iter() {
								let e_result = try!(self.run(*expr));
								if expr == last_expr {
									result = e_result;
								}
							}
						},
						_ => ()
					}
				}
				if !matched && default.is_some() {
					result = try!(self.run(*default.as_ref().unwrap()));
				}
				Ok(result)
			},
			ObjectDeclExpr(ref map) => {
				let mut obj = TreeMap::new();
				for (key, val) in map.iter() {
					obj.insert(key.clone(), try!(self.run(val.clone())));
				}
				obj.swap(~"__proto__", self.globals.find(&~"Object").unwrap().clone());
				Ok(Gc::new(VObject(RefCell::new(obj))))
			},
			ArrayDeclExpr(ref arr) => {
				let mut arr_map = TreeMap::new();
				let mut index = 0;
				for val in arr.iter() {
					let val = try!(self.run(val.clone()));
					arr_map.insert(index.to_str(), val);
					index += 1;
				}
				arr_map.swap(~"__proto__", self.globals.find(&~"Array").unwrap().clone());
				Ok(Gc::new(VObject(RefCell::new(arr_map))))
			},
			FunctionDeclExpr(ref name, ref args, ref expr) => {
				let function = RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
				let val = Gc::new(VFunction(RefCell::new(function)));
				if name.is_some() {
					self.globals.swap(name.clone().unwrap(), val);
				}
				Ok(val)
			},
			NumOpExpr(ref op, ref a, ref b) => {
				let v_a = try!(self.run(*a)).borrow().clone();
				let v_b = try!(self.run(*b)).borrow().clone();
				Ok(Gc::new(match *op {
					OpAdd => v_a + v_b,
					OpSub => v_a - v_b,
					OpMul => v_a * v_b,
					OpDiv => v_a / v_b,
					OpAnd => v_a & v_b,
					OpOr => v_a | v_b,
				}))
			},
			ConstructExpr(ref func, ref args) => {
				Ok(Gc::new(VNull))
			},
			ReturnExpr(ref ret) => {
				let v_ret = try!(self.run(ret.clone().unwrap()));
				Ok(Gc::new(VNull))
			},
			ThrowExpr(ref ex) => Err(try!(self.run(*ex))),
			AssignExpr(ref ref_e, ref val_e) => {
				let val = try!(self.run(*val_e));
				match **ref_e {
					LocalExpr(ref name) => {
						self.globals.insert(name.clone(), val);
					},
					_ => ()
				}
				Ok(val)
			}
		}
	}
}<commit_msg>Remove unnecessary debug code<commit_after>use ast::{Expr, ConstExpr, BlockExpr, LocalExpr, GetConstFieldExpr, GetFieldExpr, CallExpr, WhileLoopExpr, IfExpr, SwitchExpr, ObjectDeclExpr, ArrayDeclExpr, FunctionDeclExpr, NumOpExpr, ConstructExpr, ReturnExpr, ThrowExpr, AssignExpr};
use ast::{CNum, CInt, CString, CBool, CRegExp, CNull, CUndefined};
use ast::{OpSub, OpAdd, OpMul, OpDiv, OpAnd, OpOr};
use js::value::{Value, VNull, VUndefined, VNumber, VString, VObject, VBoolean, VFunction, ResultValue};
use js::object::ObjectData;
use js::function::{RegularFunc, RegularFunction};
use js::{console, math, object, array, function, json};
use collections::treemap::TreeMap;
use std::vec::Vec;
use std::f64;
use std::gc::Gc;
use std::cell::RefCell;
/// An execution engine
pub trait Executor {
	/// Makes a new execution engine
	fn new() -> ~Self;
	/// Sets a global variable
	fn set_global(&mut self, name:~str, val:Value) -> ();
	/// Gets a global variable
	fn get_global(&self, name:~str) -> Value;
	/// Make a new scope
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>>;
	/// Destroy the current scope
	fn destroy_scope(&mut self) -> ();
	/// Runs the expression
	fn run(&mut self, expr:&Expr) -> ResultValue;
}
/// An intepreter
pub struct Interpreter {
	/// A hash map representing the global variables
	globals: ObjectData,
	/// The scopes
	scopes: Vec<Gc<RefCell<ObjectData>>>,
	/// The current function scope
	current_scope: uint
}
impl Executor for Interpreter {
	fn new() -> ~Interpreter {
		let mut globals : ObjectData = TreeMap::new();
		globals.swap(~"NaN", Gc::new(VNumber(f64::NAN)));
		globals.swap(~"Infinity", Gc::new(VNumber(f64::INFINITY)));
		globals.swap(~"console", console::_create());
		globals.swap(~"Math", math::_create());
		globals.swap(~"Object", object::_create());
		globals.swap(~"Array", array::_create());
		globals.swap(~"Function", function::_create());
		globals.swap(~"JSON", json::_create());
		return ~Interpreter {globals: globals, scopes: Vec::new(), current_scope: 0};
	}
	fn set_global(&mut self, name:~str, val:Value) {
		self.globals.swap(name, val);
	}
	fn get_global(&self, name:~str) -> Value {
		match self.globals.find(&name) {
			None => Gc::new(VUndefined),
			Some(ref g) => **g
		}
	}
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>> {
		let mut data = TreeMap::new();
		let value = Gc::new(RefCell::new(data));
		self.scopes.push(value.clone());
		value
	}
	fn destroy_scope(&mut self) -> () {
		self.scopes.pop();
	}
	fn run(&mut self, expr:&Expr) -> ResultValue {
		match *expr {
			ConstExpr(CNull) => Ok(Gc::new(VNull)),
			ConstExpr(CUndefined) => Ok(Gc::new(VUndefined)),
			ConstExpr(CNum(num)) => Ok(Gc::new(VNumber(num))),
			ConstExpr(CInt(num)) => Ok(Gc::new(VNumber(num as f64))),
			ConstExpr(CString(ref str)) => Ok(Gc::new(VString(str.to_owned()))),
			ConstExpr(CBool(val)) => Ok(Gc::new(VBoolean(val))),
			ConstExpr(CRegExp(ref reg, _, _)) => Ok(Gc::new(VBoolean(true))),
			BlockExpr(ref es) => {
				let mut obj = Gc::new(VNull);
				for e in es.iter() {
					let val = try!(self.run(*e));
					if e == es.last().unwrap() {
						obj = val;
					}
				}
				Ok(obj)
			},
			LocalExpr(ref name) => {
				let mut value = Gc::new(VUndefined);
				for scope in self.scopes.iter().rev() {
					match scope.borrow().borrow().find(name) {
						Some(v) => {
							value = v.clone();
							break;
						}
						None => ()
					}
				}
				Ok(if value.borrow() == &VUndefined {
					match self.globals.find(name) {
						None => Gc::new(VUndefined),
						Some(v) => v.clone()
					}
				} else {
					value
				})
			},
			GetConstFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				Ok(val_obj.borrow().get_field(field.clone()))
			},
			GetFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				let val_field = try!(self.run(*field));
				Ok(val_obj.borrow().get_field(val_field.borrow().to_str()))
			},
			CallExpr(ref callee, ref args) => {
				let func = try!(self.run(callee.clone()));
				let mut v_args = Vec::with_capacity(args.len());
				for arg in args.iter() {
					v_args.push(try!(self.run(*arg)));
				}
				Ok(match *func.borrow() {
					VFunction(ref func) => {
						let globals = self.globals.clone();
						func.borrow().call(self, Gc::new(VObject(RefCell::new(globals))), Gc::new(VNull), v_args).unwrap()
					},
					_ => Gc::new(VUndefined)
				})
			},
			WhileLoopExpr(ref cond, ref expr) => {
				let mut result = Gc::new(VUndefined);
				while try!(self.run(*cond)).borrow().is_true() {
					result = try!(self.run(*expr));
				}
				Ok(result)
			},
			IfExpr(ref cond, ref expr, None) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					Gc::new(VUndefined)
				})
			},
			IfExpr(ref cond, ref expr, Some(ref else_e)) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					try!(self.run(*else_e))
				})
			},
			SwitchExpr(ref val_e, ref vals, ref default) => {
				let val = try!(self.run(*val_e)).borrow().clone();
				let mut result = Gc::new(VNull);
				let mut matched = false;
				for tup in vals.iter() {
					let tup:&(~Expr, Vec<~Expr>) = tup;
					match *tup {
						(ref cond, ref block) if(val == *try!(self.run(*cond)).borrow()) => {
							matched = true;
							let last_expr = block.last().unwrap();
							for expr in block.iter() {
								let e_result = try!(self.run(*expr));
								if expr == last_expr {
									result = e_result;
								}
							}
						},
						_ => ()
					}
				}
				if !matched && default.is_some() {
					result = try!(self.run(*default.as_ref().unwrap()));
				}
				Ok(result)
			},
			ObjectDeclExpr(ref map) => {
				let mut obj = TreeMap::new();
				for (key, val) in map.iter() {
					obj.insert(key.clone(), try!(self.run(val.clone())));
				}
				obj.swap(~"__proto__", self.globals.find(&~"Object").unwrap().clone());
				Ok(Gc::new(VObject(RefCell::new(obj))))
			},
			ArrayDeclExpr(ref arr) => {
				let mut arr_map = TreeMap::new();
				let mut index = 0;
				for val in arr.iter() {
					let val = try!(self.run(val.clone()));
					arr_map.insert(index.to_str(), val);
					index += 1;
				}
				arr_map.swap(~"__proto__", self.globals.find(&~"Array").unwrap().clone());
				Ok(Gc::new(VObject(RefCell::new(arr_map))))
			},
			FunctionDeclExpr(ref name, ref args, ref expr) => {
				let function = RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
				let val = Gc::new(VFunction(RefCell::new(function)));
				if name.is_some() {
					self.globals.swap(name.clone().unwrap(), val);
				}
				Ok(val)
			},
			NumOpExpr(ref op, ref a, ref b) => {
				let v_a = try!(self.run(*a)).borrow().clone();
				let v_b = try!(self.run(*b)).borrow().clone();
				Ok(Gc::new(match *op {
					OpAdd => v_a + v_b,
					OpSub => v_a - v_b,
					OpMul => v_a * v_b,
					OpDiv => v_a / v_b,
					OpAnd => v_a & v_b,
					OpOr => v_a | v_b,
				}))
			},
			ConstructExpr(ref func, ref args) => {
				Ok(Gc::new(VNull))
			},
			ReturnExpr(ref ret) => {
				let v_ret = try!(self.run(ret.clone().unwrap()));
				Ok(Gc::new(VNull))
			},
			ThrowExpr(ref ex) => Err(try!(self.run(*ex))),
			AssignExpr(ref ref_e, ref val_e) => {
				let val = try!(self.run(*val_e));
				match **ref_e {
					LocalExpr(ref name) => {
						self.globals.insert(name.clone(), val);
					},
					_ => ()
				}
				Ok(val)
			}
		}
	}
}<|endoftext|>


<commit_before>use once_cell::sync::Lazy;

use super::common::{build_inverted_map, generic_alphabet_calculate_scores};
use super::RawOutcome;
use crate::core::{FilterList, LowercaseText};
use crate::{Lang, Script};

const AFR: &str = "abcdefghijklmnopqrstuvwxyzáèéêëíîïóôúû";
const AKA: &str = "abdefghiklmnoprstuwyɔɛ";
const AZE: &str = "abcdefghijklmnopqrstuvxyzçöüğışə̇";
const CAT: &str = "abcdefghijklmnopqrstuvwxyz·àçèéíïòóúü";
const CES: &str = "abcdefghijklmnopqrstuvwxyzáéóúýčďěňřšťůž";
const DAN: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const DEU: &str = "abcdefghijklmnopqrstuvwxyzßäöü";
const ENG: &str = "abcdefghijklmnopqrstuvwxyz";
const EPO: &str = "abcdefghijklmnoprstuvzĉĝĥĵŝŭ";
const EST: &str = "abcdefghijklmnopqrstuvwxyzäõöü";
const FIN: &str = "abcdefghijklmnopqrstuvwxyzäöšž";
const FRA: &str = "abcdefghijklmnopqrstuvwxyzàâçèéêëîïôùûüÿœ";
const HRV: &str = "abcdefghijklmnopqrstuvwxyzćčđšž";
const HUN: &str = "abcdefghijklmnopqrstuvwxyzáéíóöúüőű";
const IND: &str = "abcdefghijklmnopqrstuvwxyz";
const ITA: &str = "abcdefghijklmnopqrstuvwxyzàèéìòù";
const JAV: &str = "abcdefghijklmnopqrstuvwxyzèé";
const LAT: &str = "abcdefghijklmnopqrstuvwxyz";
const LAV: &str = "abcdefghijklmnopqrstuvwxyzāčēģīķļņōŗšūž";
const LIT: &str = "abcdefghijklmnopqrstuvwxyząčėęįšūųž";
const NLD: &str = "abcdefghijklmnopqrstuvwxyzàèéëïĳ";
const NOB: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const POL: &str = "abcdefghijklmnopqrstuvwxyzóąćęłńśźż";
const POR: &str = "abcdefghijklmnopqrstuvwxyzàáâãçéêíóôõú";
const RON: &str = "abcdefghijklmnopqrstuvwxyzâîăşţ";
const SLK: &str = "abcdefghijklmnopqrstuvwxyzáäéíóôúýčďĺľňŕšťž";
const SLV: &str = "abcdefghijklmnopqrstuvwxyzčšž";
const SNA: &str = "abcdefghijklmnopqrstuvwxyz";
const SPA: &str = "abcdefghijklmnopqrstuvwxyz¡¿áéíñóúü";
const SWE: &str = "abcdefghijklmnopqrstuvwxyzäåö";
const TGL: &str = "abcdefghijklmnopqrstuvwxyzáéíñóú";
const TUK: &str = "abdefghijklmnoprstuwyzäçöüýňşž";
const TUR: &str = "abcdefghijklmnopqrstuvwxyzçöüğış̇";
const UZB: &str = "abcdefghijklmnopqrstuvxyzʻ";
const VIE: &str =
    "abcdefghijklmnopqrstuvwxyzàáâãèéêìíòóôõùúýăđĩũơưạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹ";
const ZUL: &str = "abcdefghijklmnopqrstuvwxyz";

const LATIN_ALPHABETS: &[(Lang, &str)] = &[
    (Lang::Afr, AFR),
    (Lang::Aka, AKA),
    (Lang::Aze, AZE),
    (Lang::Cat, CAT),
    (Lang::Ces, CES),
    (Lang::Dan, DAN),
    (Lang::Deu, DEU),
    (Lang::Eng, ENG),
    (Lang::Epo, EPO),
    (Lang::Est, EST),
    (Lang::Fin, FIN),
    (Lang::Fra, FRA),
    (Lang::Hrv, HRV),
    (Lang::Hun, HUN),
    (Lang::Ind, IND),
    (Lang::Ita, ITA),
    (Lang::Jav, JAV),
    (Lang::Lat, LAT),
    (Lang::Lav, LAV),
    (Lang::Lit, LIT),
    (Lang::Nld, NLD),
    (Lang::Nob, NOB),
    (Lang::Pol, POL),
    (Lang::Por, POR),
    (Lang::Ron, RON),
    (Lang::Slk, SLK),
    (Lang::Slv, SLV),
    (Lang::Sna, SNA),
    (Lang::Spa, SPA),
    (Lang::Swe, SWE),
    (Lang::Tgl, TGL),
    (Lang::Tuk, TUK),
    (Lang::Tur, TUR),
    (Lang::Uzb, UZB),
    (Lang::Vie, VIE),
    (Lang::Zul, ZUL),
];

/// Inverted map binding a character to a set of languages.
pub static ALPHABET_LANG_MAP: Lazy<(Vec<char>, Vec<Vec<Lang>>)> =
    Lazy::new(|| build_inverted_map(LATIN_ALPHABETS));

pub fn alphabet_calculate_scores(text: &LowercaseText, filter_list: &FilterList) -> RawOutcome {
    generic_alphabet_calculate_scores(Script::Latin, &ALPHABET_LANG_MAP, text, filter_list)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::utils::is_stop_char;
    use crate::Script;

    // Old naive implementation, that is not very effective but easy to understand
    fn naive_alphabet_calculate_scores(
        text: &LowercaseText,
        filter_list: &FilterList,
    ) -> RawOutcome {
        let mut raw_scores: Vec<(Lang, i32)> = Script::Latin
            .langs()
            .iter()
            .filter(|&&l| filter_list.is_allowed(l))
            .map(|&l| (l, 0i32))
            .collect();

        let max_raw_score = text.chars().filter(|&ch| !is_stop_char(ch)).count();

        for (lang, score) in &mut raw_scores {
            let alphabet: Vec<char> = LATIN_ALPHABETS
                .iter()
                .find(|(l, _)| l == lang)
                .unwrap()
                .1
                .chars()
                .collect();

            for ch in text.chars() {
                if is_stop_char(ch) {
                    continue;
                };
                if alphabet.contains(&ch) {
                    *score += 1;
                } else {
                    *score -= 1;
                }
            }
        }

        raw_scores.sort_by(|a, b| b.1.cmp(&a.1));

        let raw_scores: Vec<(Lang, usize)> = raw_scores
            .into_iter()
            .map(|(l, s)| {
                let score = if s < 0 { 0usize } else { s as usize };
                (l, score)
            })
            .collect();

        let mut normalized_scores = vec![];

        for &(lang, raw_score) in &raw_scores {
            let normalized_score = raw_score as f64 / max_raw_score as f64;
            normalized_scores.push((lang, normalized_score));
        }

        RawOutcome {
            count: max_raw_score,
            raw_scores,
            scores: normalized_scores,
        }
    }

    #[test]
    fn test_alphabet_calculate_scores_against_harmaja_hauras() {
        let text =
            LowercaseText::new("Ja kulkee kylmä hetki pariimme, Olet hauras kuin jää, Ja kulke");
        let filter = FilterList::All;

        let outcome = alphabet_calculate_scores(&text, &filter);
        assert_eq!(outcome.count, 50);
        assert_eq!(outcome.raw_scores.len(), 36);
        assert_eq!(outcome.scores.len(), 36);

        let raw_scores_for = |lang: Lang| {
            outcome
                .raw_scores
                .iter()
                .find(|(l, _)| *l == lang)
                .unwrap()
                .1
        };
        let scores_for = |lang: Lang| outcome.scores.iter().find(|(l, _)| *l == lang).unwrap().1;

        assert_eq!(raw_scores_for(Lang::Fin), 50);
        assert_eq!(raw_scores_for(Lang::Deu), 50);
        assert_eq!(raw_scores_for(Lang::Epo), 42);

        assert_eq!(scores_for(Lang::Fin), 1.0);
        assert_eq!(scores_for(Lang::Deu), 1.0);
        assert_eq!(scores_for(Lang::Epo), 0.84);
    }

    #[test]
    fn test_works_as_the_old_naive_implementation() {
        let filter = FilterList::All;
        let texts = [
            "Tyrkiske språk eller turkotatariske språk er en språkgruppe bestående av minst 35 språk",
            "René Descartes est un mathématicien, physicien et philosophe français, né le 31 mars 1596 à La Haye-en-Touraine",
            "Die Sonne scheint in das Büro der Grabdenkmalsfirma Heinrich Kroll & Söhne. Es ist April 923, und das Geschäf geht gut.",
        ];

        for text in texts {
            let lowercase_text = LowercaseText::new(text);
            let outcome = alphabet_calculate_scores(&lowercase_text, &filter);
            let naive_outcome = naive_alphabet_calculate_scores(&lowercase_text, &filter);

            // We can just compare outcome against naive_outcome, because ordering maybe different,
            // what is acceptable.
            assert_eq!(
                outcome.count, naive_outcome.count,
                "count failed. Text: {}",
                text
            );
            for (lang, raw_naive_score) in naive_outcome.raw_scores.into_iter() {
                let lookup_raw_score = |lang| {
                    outcome
                        .raw_scores
                        .iter()
                        .find(|(l, _)| *l == lang)
                        .unwrap()
                        .1
                };
                let raw_score = lookup_raw_score(lang);
                assert_eq!(
                    raw_score, raw_naive_score,
                    "raw_score VS raw_naive_score failed. Lang={}, Text: {}",
                    lang, text
                );
            }
            for (lang, naive_score) in naive_outcome.scores.into_iter() {
                let lookup_score =
                    |lang| outcome.scores.iter().find(|(l, _)| *l == lang).unwrap().1;
                let score = lookup_score(lang);
                assert_eq!(
                    score, naive_score,
                    "score VS naive_score failed. Lang={}, Text: {}",
                    lang, text
                );
            }
        }
    }
}
<commit_msg>Fix Czech language alphabet<commit_after>use once_cell::sync::Lazy;

use super::common::{build_inverted_map, generic_alphabet_calculate_scores};
use super::RawOutcome;
use crate::core::{FilterList, LowercaseText};
use crate::{Lang, Script};

const AFR: &str = "abcdefghijklmnopqrstuvwxyzáèéêëíîïóôúû";
const AKA: &str = "abdefghiklmnoprstuwyɔɛ";
const AZE: &str = "abcdefghijklmnopqrstuvxyzçöüğışə̇";
const CAT: &str = "abcdefghijklmnopqrstuvwxyz·àçèéíïòóúü";
const CES: &str = "abcdefghijklmnopqrstuvwxyzáéíóúýčďěňřšťůž";
const DAN: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const DEU: &str = "abcdefghijklmnopqrstuvwxyzßäöü";
const ENG: &str = "abcdefghijklmnopqrstuvwxyz";
const EPO: &str = "abcdefghijklmnoprstuvzĉĝĥĵŝŭ";
const EST: &str = "abcdefghijklmnopqrstuvwxyzäõöü";
const FIN: &str = "abcdefghijklmnopqrstuvwxyzäöšž";
const FRA: &str = "abcdefghijklmnopqrstuvwxyzàâçèéêëîïôùûüÿœ";
const HRV: &str = "abcdefghijklmnopqrstuvwxyzćčđšž";
const HUN: &str = "abcdefghijklmnopqrstuvwxyzáéíóöúüőű";
const IND: &str = "abcdefghijklmnopqrstuvwxyz";
const ITA: &str = "abcdefghijklmnopqrstuvwxyzàèéìòù";
const JAV: &str = "abcdefghijklmnopqrstuvwxyzèé";
const LAT: &str = "abcdefghijklmnopqrstuvwxyz";
const LAV: &str = "abcdefghijklmnopqrstuvwxyzāčēģīķļņōŗšūž";
const LIT: &str = "abcdefghijklmnopqrstuvwxyząčėęįšūųž";
const NLD: &str = "abcdefghijklmnopqrstuvwxyzàèéëïĳ";
const NOB: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const POL: &str = "abcdefghijklmnopqrstuvwxyzóąćęłńśźż";
const POR: &str = "abcdefghijklmnopqrstuvwxyzàáâãçéêíóôõú";
const RON: &str = "abcdefghijklmnopqrstuvwxyzâîăşţ";
const SLK: &str = "abcdefghijklmnopqrstuvwxyzáäéíóôúýčďĺľňŕšťž";
const SLV: &str = "abcdefghijklmnopqrstuvwxyzčšž";
const SNA: &str = "abcdefghijklmnopqrstuvwxyz";
const SPA: &str = "abcdefghijklmnopqrstuvwxyz¡¿áéíñóúü";
const SWE: &str = "abcdefghijklmnopqrstuvwxyzäåö";
const TGL: &str = "abcdefghijklmnopqrstuvwxyzáéíñóú";
const TUK: &str = "abdefghijklmnoprstuwyzäçöüýňşž";
const TUR: &str = "abcdefghijklmnopqrstuvwxyzçöüğış̇";
const UZB: &str = "abcdefghijklmnopqrstuvxyzʻ";
const VIE: &str =
    "abcdefghijklmnopqrstuvwxyzàáâãèéêìíòóôõùúýăđĩũơưạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹ";
const ZUL: &str = "abcdefghijklmnopqrstuvwxyz";

const LATIN_ALPHABETS: &[(Lang, &str)] = &[
    (Lang::Afr, AFR),
    (Lang::Aka, AKA),
    (Lang::Aze, AZE),
    (Lang::Cat, CAT),
    (Lang::Ces, CES),
    (Lang::Dan, DAN),
    (Lang::Deu, DEU),
    (Lang::Eng, ENG),
    (Lang::Epo, EPO),
    (Lang::Est, EST),
    (Lang::Fin, FIN),
    (Lang::Fra, FRA),
    (Lang::Hrv, HRV),
    (Lang::Hun, HUN),
    (Lang::Ind, IND),
    (Lang::Ita, ITA),
    (Lang::Jav, JAV),
    (Lang::Lat, LAT),
    (Lang::Lav, LAV),
    (Lang::Lit, LIT),
    (Lang::Nld, NLD),
    (Lang::Nob, NOB),
    (Lang::Pol, POL),
    (Lang::Por, POR),
    (Lang::Ron, RON),
    (Lang::Slk, SLK),
    (Lang::Slv, SLV),
    (Lang::Sna, SNA),
    (Lang::Spa, SPA),
    (Lang::Swe, SWE),
    (Lang::Tgl, TGL),
    (Lang::Tuk, TUK),
    (Lang::Tur, TUR),
    (Lang::Uzb, UZB),
    (Lang::Vie, VIE),
    (Lang::Zul, ZUL),
];

/// Inverted map binding a character to a set of languages.
pub static ALPHABET_LANG_MAP: Lazy<(Vec<char>, Vec<Vec<Lang>>)> =
    Lazy::new(|| build_inverted_map(LATIN_ALPHABETS));

pub fn alphabet_calculate_scores(text: &LowercaseText, filter_list: &FilterList) -> RawOutcome {
    generic_alphabet_calculate_scores(Script::Latin, &ALPHABET_LANG_MAP, text, filter_list)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::utils::is_stop_char;
    use crate::Script;

    // Old naive implementation, that is not very effective but easy to understand
    fn naive_alphabet_calculate_scores(
        text: &LowercaseText,
        filter_list: &FilterList,
    ) -> RawOutcome {
        let mut raw_scores: Vec<(Lang, i32)> = Script::Latin
            .langs()
            .iter()
            .filter(|&&l| filter_list.is_allowed(l))
            .map(|&l| (l, 0i32))
            .collect();

        let max_raw_score = text.chars().filter(|&ch| !is_stop_char(ch)).count();

        for (lang, score) in &mut raw_scores {
            let alphabet: Vec<char> = LATIN_ALPHABETS
                .iter()
                .find(|(l, _)| l == lang)
                .unwrap()
                .1
                .chars()
                .collect();

            for ch in text.chars() {
                if is_stop_char(ch) {
                    continue;
                };
                if alphabet.contains(&ch) {
                    *score += 1;
                } else {
                    *score -= 1;
                }
            }
        }

        raw_scores.sort_by(|a, b| b.1.cmp(&a.1));

        let raw_scores: Vec<(Lang, usize)> = raw_scores
            .into_iter()
            .map(|(l, s)| {
                let score = if s < 0 { 0usize } else { s as usize };
                (l, score)
            })
            .collect();

        let mut normalized_scores = vec![];

        for &(lang, raw_score) in &raw_scores {
            let normalized_score = raw_score as f64 / max_raw_score as f64;
            normalized_scores.push((lang, normalized_score));
        }

        RawOutcome {
            count: max_raw_score,
            raw_scores,
            scores: normalized_scores,
        }
    }

    #[test]
    fn test_alphabet_calculate_scores_against_harmaja_hauras() {
        let text =
            LowercaseText::new("Ja kulkee kylmä hetki pariimme, Olet hauras kuin jää, Ja kulke");
        let filter = FilterList::All;

        let outcome = alphabet_calculate_scores(&text, &filter);
        assert_eq!(outcome.count, 50);
        assert_eq!(outcome.raw_scores.len(), 36);
        assert_eq!(outcome.scores.len(), 36);

        let raw_scores_for = |lang: Lang| {
            outcome
                .raw_scores
                .iter()
                .find(|(l, _)| *l == lang)
                .unwrap()
                .1
        };
        let scores_for = |lang: Lang| outcome.scores.iter().find(|(l, _)| *l == lang).unwrap().1;

        assert_eq!(raw_scores_for(Lang::Fin), 50);
        assert_eq!(raw_scores_for(Lang::Deu), 50);
        assert_eq!(raw_scores_for(Lang::Epo), 42);

        assert_eq!(scores_for(Lang::Fin), 1.0);
        assert_eq!(scores_for(Lang::Deu), 1.0);
        assert_eq!(scores_for(Lang::Epo), 0.84);
    }

    #[test]
    fn test_works_as_the_old_naive_implementation() {
        let filter = FilterList::All;
        let texts = [
            "Tyrkiske språk eller turkotatariske språk er en språkgruppe bestående av minst 35 språk",
            "René Descartes est un mathématicien, physicien et philosophe français, né le 31 mars 1596 à La Haye-en-Touraine",
            "Die Sonne scheint in das Büro der Grabdenkmalsfirma Heinrich Kroll & Söhne. Es ist April 923, und das Geschäf geht gut.",
        ];

        for text in texts {
            let lowercase_text = LowercaseText::new(text);
            let outcome = alphabet_calculate_scores(&lowercase_text, &filter);
            let naive_outcome = naive_alphabet_calculate_scores(&lowercase_text, &filter);

            // We can just compare outcome against naive_outcome, because ordering maybe different,
            // what is acceptable.
            assert_eq!(
                outcome.count, naive_outcome.count,
                "count failed. Text: {}",
                text
            );
            for (lang, raw_naive_score) in naive_outcome.raw_scores.into_iter() {
                let lookup_raw_score = |lang| {
                    outcome
                        .raw_scores
                        .iter()
                        .find(|(l, _)| *l == lang)
                        .unwrap()
                        .1
                };
                let raw_score = lookup_raw_score(lang);
                assert_eq!(
                    raw_score, raw_naive_score,
                    "raw_score VS raw_naive_score failed. Lang={}, Text: {}",
                    lang, text
                );
            }
            for (lang, naive_score) in naive_outcome.scores.into_iter() {
                let lookup_score =
                    |lang| outcome.scores.iter().find(|(l, _)| *l == lang).unwrap().1;
                let score = lookup_score(lang);
                assert_eq!(
                    score, naive_score,
                    "score VS naive_score failed. Lang={}, Text: {}",
                    lang, text
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use stack::Stack;

#[allow(non_camel_case_types)]
pub type uintptr_t = u64;

#[allow(raw_pointer_derive)]
#[derive(Copy, Clone)]
pub struct Registers {
  rsp: *mut uintptr_t
}

impl Registers {
  #[inline]
  pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
    let sp_limit = stack.limit();
    let mut sp = stack.top() as *mut uintptr_t;
    let f_ptr = push(&mut sp, f);

    asm!(include_str!("init.s")
          : "={rdi}"(sp)
          : "{rdi}" (sp),
            "{rsi}" (rust_trampoline::<F>),
            "{rdx}" (f_ptr),
            "{rcx}" (sp_limit)
          :
          : "volatile");

    Registers { rsp: sp }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    asm!(include_str!("swap.s")
          :
          : "{rdi}" (&mut self.rsp)
          : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
            "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
            "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
            "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
            "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
            "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
            "cc"
          : "volatile");
  }
}

unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
  ptr::read(f)()
}

unsafe fn push<T>(spp: &mut *mut uintptr_t, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), 16));
  *sp = value;
  *spp = sp as *mut uintptr_t;
  sp
}

fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<commit_msg>uintptr_t is pointless when usize is the same anyway<commit_after>// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use stack::Stack;

#[allow(raw_pointer_derive)]
#[derive(Copy, Clone)]
pub struct Registers {
  rsp: *mut usize
}

impl Registers {
  #[inline]
  pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
    let sp_limit = stack.limit();
    let mut sp = stack.top() as *mut usize;
    let f_ptr = push(&mut sp, f);

    asm!(include_str!("init.s")
          : "={rdi}"(sp)
          : "{rdi}" (sp),
            "{rsi}" (rust_trampoline::<F>),
            "{rdx}" (f_ptr),
            "{rcx}" (sp_limit)
          :
          : "volatile");

    Registers { rsp: sp }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    asm!(include_str!("swap.s")
          :
          : "{rdi}" (&mut self.rsp)
          : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
            "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
            "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
            "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
            "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
            "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
            "cc"
          : "volatile");
  }
}

unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
  ptr::read(f)()
}

unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), 16));
  *sp = value;
  *spp = sp as *mut usize;
  sp
}

fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<|endoftext|>


<commit_before>use std::fmt;

use futures::{Stream, Poll, Async};
use bytes::Bytes;

/// An asynchronous `Stream`.
pub struct Body {
    inner: Inner,
}

enum Inner {
    Reusable(Bytes),
    Hyper(::hyper::Body),
}

impl Body {
    fn poll_inner(&mut self) -> &mut ::hyper::Body {
        match self.inner {
            Inner::Hyper(ref mut body) => body,
            Inner::Reusable(_) => unreachable!(),
        }
    }
}

impl Stream for Body {
    type Item = Chunk;
    type Error = ::Error;

    #[inline]
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match try_!(self.poll_inner().poll()) {
            Async::Ready(opt) => Ok(Async::Ready(opt.map(|chunk| Chunk {
                inner: chunk,
            }))),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}

/// A chunk of bytes for a `Body`.
///
/// A `Chunk` can be treated like `&[u8]`.
#[derive(Default)]
pub struct Chunk {
    inner: ::hyper::Chunk,
}

impl ::std::ops::Deref for Chunk {
    type Target = [u8];
    #[inline]
    fn deref(&self) -> &Self::Target {
        self.inner.as_ref()
    }
}

impl Extend<u8> for Chunk {
    fn extend<T>(&mut self, iter: T)
    where T: IntoIterator<Item=u8> {
        self.inner.extend(iter)
    }
}

impl IntoIterator for Chunk {
    type Item = u8;
    //XXX: exposing type from hyper!
    type IntoIter = <::hyper::Chunk as IntoIterator>::IntoIter;
    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body")
            .finish()
    }
}

impl fmt::Debug for Chunk {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}

// pub(crate)

#[inline]
pub fn wrap(body: ::hyper::Body) -> Body {
    Body {
        inner: Inner::Hyper(body),
    }
}

#[inline]
pub fn take(body: &mut Body) -> Body {
    use std::mem;
    let inner = mem::replace(&mut body.inner, Inner::Hyper(::hyper::Body::empty()));
    Body {
        inner: inner,
    }
}

#[inline]
pub fn reusable(chunk: Bytes) -> Body {
    Body {
        inner: Inner::Reusable(chunk),
    }
}

#[inline]
pub fn into_hyper(body: Body) -> (Option<Bytes>, ::hyper::Body) {
    match body.inner {
        Inner::Reusable(chunk) => (Some(chunk.clone()), chunk.into()),
        Inner::Hyper(b) => (None, b),
    }
}
<commit_msg>From impls for Body<commit_after>use std::fmt;

use futures::{Stream, Poll, Async};
use bytes::Bytes;

/// An asynchronous `Stream`.
pub struct Body {
    inner: Inner,
}

enum Inner {
    Reusable(Bytes),
    Hyper(::hyper::Body),
}

impl Body {
    fn poll_inner(&mut self) -> &mut ::hyper::Body {
        match self.inner {
            Inner::Hyper(ref mut body) => body,
            Inner::Reusable(_) => unreachable!(),
        }
    }
}

impl Stream for Body {
    type Item = Chunk;
    type Error = ::Error;

    #[inline]
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match try_!(self.poll_inner().poll()) {
            Async::Ready(opt) => Ok(Async::Ready(opt.map(|chunk| Chunk {
                inner: chunk,
            }))),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        reusable(bytes)
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        reusable(vec.into())
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        reusable(s.into())
    }
}

/// A chunk of bytes for a `Body`.
///
/// A `Chunk` can be treated like `&[u8]`.
#[derive(Default)]
pub struct Chunk {
    inner: ::hyper::Chunk,
}

impl ::std::ops::Deref for Chunk {
    type Target = [u8];
    #[inline]
    fn deref(&self) -> &Self::Target {
        self.inner.as_ref()
    }
}

impl Extend<u8> for Chunk {
    fn extend<T>(&mut self, iter: T)
    where T: IntoIterator<Item=u8> {
        self.inner.extend(iter)
    }
}

impl IntoIterator for Chunk {
    type Item = u8;
    //XXX: exposing type from hyper!
    type IntoIter = <::hyper::Chunk as IntoIterator>::IntoIter;
    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body")
            .finish()
    }
}

impl fmt::Debug for Chunk {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}

// pub(crate)

#[inline]
pub fn wrap(body: ::hyper::Body) -> Body {
    Body {
        inner: Inner::Hyper(body),
    }
}

#[inline]
pub fn take(body: &mut Body) -> Body {
    use std::mem;
    let inner = mem::replace(&mut body.inner, Inner::Hyper(::hyper::Body::empty()));
    Body {
        inner: inner,
    }
}

#[inline]
pub fn reusable(chunk: Bytes) -> Body {
    Body {
        inner: Inner::Reusable(chunk),
    }
}

#[inline]
pub fn into_hyper(body: Body) -> (Option<Bytes>, ::hyper::Body) {
    match body.inner {
        Inner::Reusable(chunk) => (Some(chunk.clone()), chunk.into()),
        Inner::Hyper(b) => (None, b),
    }
}
<|endoftext|>


<commit_before>extern crate termion;

extern crate chan_signal;

use self::termion::color as tcolor;
use self::termion::event::Event as TEvent;
use self::termion::event::Key as TKey;
use self::termion::input::TermRead;
use self::termion::raw::IntoRawMode;
use self::termion::screen::AlternateScreen;
use self::termion::style as tstyle;
use backend;
use chan;
use event::{Event, Key};
use std::cell::Cell;
use std::collections::HashMap;
use std::fmt;
use std::io::Write;
use std::thread;

use theme;

pub struct Concrete {
    terminal: AlternateScreen<termion::raw::RawTerminal<::std::io::Stdout>>,
    current_style: Cell<theme::ColorPair>,
    input: chan::Receiver<Event>,
    resize: chan::Receiver<chan_signal::Signal>,
    timeout: Option<u32>,
}

trait Effectable {
    fn on(&self);
    fn off(&self);
}

impl Effectable for theme::Effect {
    fn on(&self) {
        match *self {
            theme::Effect::Simple => (),
            theme::Effect::Reverse => print!("{}", tstyle::Invert),
        }
    }

    fn off(&self) {
        match *self {
            theme::Effect::Simple => (),
            theme::Effect::Reverse => print!("{}", tstyle::NoInvert),
        }
    }
}

fn apply_colors(fg: &tcolor::Color, bg: &tcolor::Color) {
    print!("{}{}", tcolor::Fg(fg), tcolor::Bg(bg));
}

impl Concrete {
    fn apply_colorstyle(&self, colors: theme::ColorPair) {
        with_color(&colors.front, |c| print!("{}", tcolor::Fg(c)));
        with_color(&colors.back, |c| print!("{}", tcolor::Bg(c)));
    }
}

impl backend::Backend for Concrete {
    fn init() -> Self {
        print!("{}", termion::cursor::Hide);

        let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]);

        let terminal = AlternateScreen::from(::std::io::stdout()
                                                 .into_raw_mode()
                                                 .unwrap());
        let (sender, receiver) = chan::async();

        thread::spawn(move || for key in ::std::io::stdin().events() {
                          if let Ok(key) = key {
                              sender.send(map_key(key))
                          }
                      });

        let backend = Concrete {
            terminal: terminal,
            current_style: Cell::new(theme::ColorPair::from_256colors(0, 0)),
            input: receiver,
            resize: resize,
            timeout: None,
        };

        backend
    }

    fn finish(&mut self) {
        print!("{}{}", termion::cursor::Show, termion::cursor::Goto(1, 1));
        print!("{}[49m{}[39m{}",
               27 as char,
               27 as char,
               termion::clear::All);
    }

    fn with_color<F: FnOnce()>(&self, color: theme::ColorPair, f: F) {
        let current_style = self.current_style.get();

        self.apply_colorstyle(color);

        self.current_style.set(color);
        f();
        self.current_style.set(current_style);

        self.apply_colorstyle(current_style);
    }

    fn with_effect<F: FnOnce()>(&self, effect: theme::Effect, f: F) {
        effect.on();
        f();
        effect.off();
    }

    fn has_colors(&self) -> bool {
        // TODO: color support detection?
        true
    }

    fn screen_size(&self) -> (usize, usize) {
        let (x, y) = termion::terminal_size().unwrap_or((1, 1));
        (x as usize, y as usize)
    }

    fn clear(&self, color: theme::Color) {
        self.apply_colorstyle(theme::ColorPair {
            front: color,
            back: color,
        });
        print!("{}", termion::clear::All);
    }

    fn refresh(&mut self) {
        self.terminal.flush().unwrap();
    }

    fn print_at(&self, (x, y): (usize, usize), text: &str) {
        print!("{}{}",
               termion::cursor::Goto(1 + x as u16, 1 + y as u16),
               text);
    }

    fn set_refresh_rate(&mut self, fps: u32) {
        self.timeout = Some(1000 / fps as u32);
    }

    fn poll_event(&self) -> Event {
        let input = &self.input;
        let resize = &self.resize;

        if let Some(timeout) = self.timeout {
            let timeout = chan::after_ms(timeout);
            chan_select!{
                timeout.recv() => return Event::Refresh,
                resize.recv() => return Event::WindowResize,
                input.recv() -> input => return input.unwrap(),
            }
        } else {
            chan_select!{
                resize.recv() => return Event::WindowResize,
                input.recv() -> input => return input.unwrap(),
            }
        }
    }
}

fn map_key(event: TEvent) -> Event {
    match event {
        TEvent::Unsupported(bytes) => Event::Unknown(bytes),
        TEvent::Key(TKey::Esc) => Event::Key(Key::Esc),
        TEvent::Key(TKey::Backspace) => Event::Key(Key::Backspace),
        TEvent::Key(TKey::Left) => Event::Key(Key::Left),
        TEvent::Key(TKey::Right) => Event::Key(Key::Right),
        TEvent::Key(TKey::Up) => Event::Key(Key::Up),
        TEvent::Key(TKey::Down) => Event::Key(Key::Down),
        TEvent::Key(TKey::Home) => Event::Key(Key::Home),
        TEvent::Key(TKey::End) => Event::Key(Key::End),
        TEvent::Key(TKey::PageUp) => Event::Key(Key::PageUp),
        TEvent::Key(TKey::PageDown) => Event::Key(Key::PageDown),
        TEvent::Key(TKey::Delete) => Event::Key(Key::Del),
        TEvent::Key(TKey::Insert) => Event::Key(Key::Ins),
        TEvent::Key(TKey::F(i)) if i < 12 => Event::Key(Key::from_f(i)),
        TEvent::Key(TKey::F(j)) => Event::Unknown(vec![j]),
        TEvent::Key(TKey::Char('\n')) => Event::Key(Key::Enter),
        TEvent::Key(TKey::Char('\t')) => Event::Key(Key::Tab),
        TEvent::Key(TKey::Char(c)) => Event::Char(c),
        TEvent::Key(TKey::Ctrl('c')) => Event::Exit,
        TEvent::Key(TKey::Ctrl(c)) => Event::CtrlChar(c),
        TEvent::Key(TKey::Alt(c)) => Event::AltChar(c),
        _ => Event::Unknown(vec![]),
    }

}

fn with_color<F, R>(clr: &theme::Color, f: F) -> R
    where F: FnOnce(&tcolor::Color) -> R
{

    match *clr {
          theme::Color::Dark(theme::BaseColor::Black) => f(&tcolor::Black),
          theme::Color::Dark(theme::BaseColor::Red) => f(&tcolor::Red),
          theme::Color::Dark(theme::BaseColor::Green) => f(&tcolor::Green),
          theme::Color::Dark(theme::BaseColor::Yellow) => f(&tcolor::Yellow),
          theme::Color::Dark(theme::BaseColor::Blue) => f(&tcolor::Blue),
          theme::Color::Dark(theme::BaseColor::Magenta) => f(&tcolor::Magenta),
          theme::Color::Dark(theme::BaseColor::Cyan) => f(&tcolor::Cyan),
          theme::Color::Dark(theme::BaseColor::White) => f(&tcolor::White),

          theme::Color::Light(theme::BaseColor::Black) => {
              f(&tcolor::LightBlack)
          }
          theme::Color::Light(theme::BaseColor::Red) => f(&tcolor::LightRed),
          theme::Color::Light(theme::BaseColor::Green) => {
              f(&tcolor::LightGreen)
          }
          theme::Color::Light(theme::BaseColor::Yellow) => {
              f(&tcolor::LightYellow)
          }
          theme::Color::Light(theme::BaseColor::Blue) => f(&tcolor::LightBlue),
          theme::Color::Light(theme::BaseColor::Magenta) => {
              f(&tcolor::LightMagenta)
          }
          theme::Color::Light(theme::BaseColor::Cyan) => f(&tcolor::LightCyan),
          theme::Color::Light(theme::BaseColor::White) => {
              f(&tcolor::LightWhite)
          }

          theme::Color::Rgb(r, g, b) => f(&tcolor::Rgb(r, g, b)),
          theme::Color::RgbLowRes(r, g, b) => {
              f(&tcolor::AnsiValue::rgb(r, g, b))
          }

      }
}
<commit_msg>Don't re-apply current color<commit_after>extern crate termion;

extern crate chan_signal;

use self::termion::color as tcolor;
use self::termion::event::Event as TEvent;
use self::termion::event::Key as TKey;
use self::termion::input::TermRead;
use self::termion::raw::IntoRawMode;
use self::termion::screen::AlternateScreen;
use self::termion::style as tstyle;
use backend;
use chan;
use event::{Event, Key};
use std::cell::Cell;
use std::collections::HashMap;
use std::fmt;
use std::io::Write;
use std::thread;

use theme;

pub struct Concrete {
    terminal: AlternateScreen<termion::raw::RawTerminal<::std::io::Stdout>>,
    current_style: Cell<theme::ColorPair>,
    input: chan::Receiver<Event>,
    resize: chan::Receiver<chan_signal::Signal>,
    timeout: Option<u32>,
}

trait Effectable {
    fn on(&self);
    fn off(&self);
}

impl Effectable for theme::Effect {
    fn on(&self) {
        match *self {
            theme::Effect::Simple => (),
            theme::Effect::Reverse => print!("{}", tstyle::Invert),
        }
    }

    fn off(&self) {
        match *self {
            theme::Effect::Simple => (),
            theme::Effect::Reverse => print!("{}", tstyle::NoInvert),
        }
    }
}

impl Concrete {
    fn apply_colors(&self, colors: theme::ColorPair) {
        with_color(&colors.front, |c| print!("{}", tcolor::Fg(c)));
        with_color(&colors.back, |c| print!("{}", tcolor::Bg(c)));
    }
}

impl backend::Backend for Concrete {
    fn init() -> Self {
        print!("{}", termion::cursor::Hide);

        let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]);

        let terminal = AlternateScreen::from(::std::io::stdout()
                                                 .into_raw_mode()
                                                 .unwrap());
        let (sender, receiver) = chan::async();

        thread::spawn(move || for key in ::std::io::stdin().events() {
                          if let Ok(key) = key {
                              sender.send(map_key(key))
                          }
                      });

        let backend = Concrete {
            terminal: terminal,
            current_style: Cell::new(theme::ColorPair::from_256colors(0, 0)),
            input: receiver,
            resize: resize,
            timeout: None,
        };

        backend
    }

    fn finish(&mut self) {
        print!("{}{}", termion::cursor::Show, termion::cursor::Goto(1, 1));
        print!("{}[49m{}[39m{}",
               27 as char,
               27 as char,
               termion::clear::All);
    }

    fn with_color<F: FnOnce()>(&self, color: theme::ColorPair, f: F) {
        let current_style = self.current_style.get();

        if current_style != color {
            self.apply_colors(color);
            self.current_style.set(color);
        }

        f();

        if current_style != color {
            self.current_style.set(current_style);
            self.apply_colors(current_style);
        }
    }

    fn with_effect<F: FnOnce()>(&self, effect: theme::Effect, f: F) {
        effect.on();
        f();
        effect.off();
    }

    fn has_colors(&self) -> bool {
        // TODO: color support detection?
        true
    }

    fn screen_size(&self) -> (usize, usize) {
        let (x, y) = termion::terminal_size().unwrap_or((1, 1));
        (x as usize, y as usize)
    }

    fn clear(&self, color: theme::Color) {
        self.apply_colors(theme::ColorPair {
            front: color,
            back: color,
        });
        print!("{}", termion::clear::All);
    }

    fn refresh(&mut self) {
        self.terminal.flush().unwrap();
    }

    fn print_at(&self, (x, y): (usize, usize), text: &str) {
        print!("{}{}",
               termion::cursor::Goto(1 + x as u16, 1 + y as u16),
               text);
    }

    fn set_refresh_rate(&mut self, fps: u32) {
        self.timeout = Some(1000 / fps as u32);
    }

    fn poll_event(&self) -> Event {
        let input = &self.input;
        let resize = &self.resize;

        if let Some(timeout) = self.timeout {
            let timeout = chan::after_ms(timeout);
            chan_select!{
                timeout.recv() => return Event::Refresh,
                resize.recv() => return Event::WindowResize,
                input.recv() -> input => return input.unwrap(),
            }
        } else {
            chan_select!{
                resize.recv() => return Event::WindowResize,
                input.recv() -> input => return input.unwrap(),
            }
        }
    }
}

fn map_key(event: TEvent) -> Event {
    match event {
        TEvent::Unsupported(bytes) => Event::Unknown(bytes),
        TEvent::Key(TKey::Esc) => Event::Key(Key::Esc),
        TEvent::Key(TKey::Backspace) => Event::Key(Key::Backspace),
        TEvent::Key(TKey::Left) => Event::Key(Key::Left),
        TEvent::Key(TKey::Right) => Event::Key(Key::Right),
        TEvent::Key(TKey::Up) => Event::Key(Key::Up),
        TEvent::Key(TKey::Down) => Event::Key(Key::Down),
        TEvent::Key(TKey::Home) => Event::Key(Key::Home),
        TEvent::Key(TKey::End) => Event::Key(Key::End),
        TEvent::Key(TKey::PageUp) => Event::Key(Key::PageUp),
        TEvent::Key(TKey::PageDown) => Event::Key(Key::PageDown),
        TEvent::Key(TKey::Delete) => Event::Key(Key::Del),
        TEvent::Key(TKey::Insert) => Event::Key(Key::Ins),
        TEvent::Key(TKey::F(i)) if i < 12 => Event::Key(Key::from_f(i)),
        TEvent::Key(TKey::F(j)) => Event::Unknown(vec![j]),
        TEvent::Key(TKey::Char('\n')) => Event::Key(Key::Enter),
        TEvent::Key(TKey::Char('\t')) => Event::Key(Key::Tab),
        TEvent::Key(TKey::Char(c)) => Event::Char(c),
        TEvent::Key(TKey::Ctrl('c')) => Event::Exit,
        TEvent::Key(TKey::Ctrl(c)) => Event::CtrlChar(c),
        TEvent::Key(TKey::Alt(c)) => Event::AltChar(c),
        _ => Event::Unknown(vec![]),
    }

}

fn with_color<F, R>(clr: &theme::Color, f: F) -> R
    where F: FnOnce(&tcolor::Color) -> R
{

    match *clr {
          theme::Color::Dark(theme::BaseColor::Black) => f(&tcolor::Black),
          theme::Color::Dark(theme::BaseColor::Red) => f(&tcolor::Red),
          theme::Color::Dark(theme::BaseColor::Green) => f(&tcolor::Green),
          theme::Color::Dark(theme::BaseColor::Yellow) => f(&tcolor::Yellow),
          theme::Color::Dark(theme::BaseColor::Blue) => f(&tcolor::Blue),
          theme::Color::Dark(theme::BaseColor::Magenta) => f(&tcolor::Magenta),
          theme::Color::Dark(theme::BaseColor::Cyan) => f(&tcolor::Cyan),
          theme::Color::Dark(theme::BaseColor::White) => f(&tcolor::White),

          theme::Color::Light(theme::BaseColor::Black) => {
              f(&tcolor::LightBlack)
          }
          theme::Color::Light(theme::BaseColor::Red) => f(&tcolor::LightRed),
          theme::Color::Light(theme::BaseColor::Green) => {
              f(&tcolor::LightGreen)
          }
          theme::Color::Light(theme::BaseColor::Yellow) => {
              f(&tcolor::LightYellow)
          }
          theme::Color::Light(theme::BaseColor::Blue) => f(&tcolor::LightBlue),
          theme::Color::Light(theme::BaseColor::Magenta) => {
              f(&tcolor::LightMagenta)
          }
          theme::Color::Light(theme::BaseColor::Cyan) => f(&tcolor::LightCyan),
          theme::Color::Light(theme::BaseColor::White) => {
              f(&tcolor::LightWhite)
          }

          theme::Color::Rgb(r, g, b) => f(&tcolor::Rgb(r, g, b)),
          theme::Color::RgbLowRes(r, g, b) => {
              f(&tcolor::AnsiValue::rgb(r, g, b))
          }

      }
}
<|endoftext|>


<commit_before>#![warn(warnings)]

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate log;

mod args;
mod build;
mod debug;
mod error;
mod new;
#[cfg(feature = "serve")]
mod serve;

use std::alloc;

use clap::{AppSettings, Parser};

use crate::error::*;

#[global_allocator]
static GLOBAL: alloc::System = alloc::System;

/// Static site generator
#[derive(Clone, Debug, Parser)]
#[clap(global_setting = AppSettings::PropagateVersion)]
#[clap(version)]
struct Cli {
    #[clap(flatten)]
    pub logging: clap_verbosity_flag::Verbosity,

    #[clap(subcommand)]
    command: Command,
}

#[derive(Clone, Debug, PartialEq, Eq, Parser)]
enum Command {
    Init(new::InitArgs),
    New(new::NewArgs),
    Rename(new::RenameArgs),
    Publish(new::PublishArgs),
    Build(build::BuildArgs),
    Clean(build::CleanArgs),
    Import(build::ImportArgs),
    #[cfg(feature = "serve")]
    Serve(serve::ServeArgs),
    #[clap(subcommand)]
    Debug(debug::DebugCommands),
}

impl Cli {
    pub fn run(&self) -> Result<()> {
        let mut logging = self.logging.clone();
        logging.set_default(Some(log::Level::Info));
        if let Some(level) = logging.log_level() {
            let mut builder = args::get_logging(level)?;
            builder.init();
        }

        match &self.command {
            Command::Init(cmd) => cmd.run(),
            Command::New(cmd) => cmd.run(),
            Command::Rename(cmd) => cmd.run(),
            Command::Publish(cmd) => cmd.run(),
            Command::Build(cmd) => cmd.run(),
            Command::Clean(cmd) => cmd.run(),
            Command::Import(cmd) => cmd.run(),
            #[cfg(feature = "serve")]
            Command::Serve(cmd) => cmd.run(),
            Command::Debug(cmd) => cmd.run(),
        }
    }
}

fn main() -> std::result::Result<(), exitfailure::ExitFailure> {
    let cli = Cli::parse();
    cli.run()?;
    Ok(())
}

#[test]
fn verify_app() {
    use clap::IntoApp;
    Cli::into_app().debug_assert()
}
<commit_msg>feat(cli): Nice reports for panics<commit_after>#![warn(warnings)]

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate log;

mod args;
mod build;
mod debug;
mod error;
mod new;
#[cfg(feature = "serve")]
mod serve;

use std::alloc;

use clap::{AppSettings, Parser};

use crate::error::*;

#[global_allocator]
static GLOBAL: alloc::System = alloc::System;

/// Static site generator
#[derive(Clone, Debug, Parser)]
#[clap(global_setting = AppSettings::PropagateVersion)]
#[clap(version)]
struct Cli {
    #[clap(flatten)]
    pub logging: clap_verbosity_flag::Verbosity,

    #[clap(subcommand)]
    command: Command,
}

#[derive(Clone, Debug, PartialEq, Eq, Parser)]
enum Command {
    Init(new::InitArgs),
    New(new::NewArgs),
    Rename(new::RenameArgs),
    Publish(new::PublishArgs),
    Build(build::BuildArgs),
    Clean(build::CleanArgs),
    Import(build::ImportArgs),
    #[cfg(feature = "serve")]
    Serve(serve::ServeArgs),
    #[clap(subcommand)]
    Debug(debug::DebugCommands),
}

impl Cli {
    pub fn run(&self) -> Result<()> {
        let mut logging = self.logging.clone();
        logging.set_default(Some(log::Level::Info));
        if let Some(level) = logging.log_level() {
            let mut builder = args::get_logging(level)?;
            builder.init();
        }

        match &self.command {
            Command::Init(cmd) => cmd.run(),
            Command::New(cmd) => cmd.run(),
            Command::Rename(cmd) => cmd.run(),
            Command::Publish(cmd) => cmd.run(),
            Command::Build(cmd) => cmd.run(),
            Command::Clean(cmd) => cmd.run(),
            Command::Import(cmd) => cmd.run(),
            #[cfg(feature = "serve")]
            Command::Serve(cmd) => cmd.run(),
            Command::Debug(cmd) => cmd.run(),
        }
    }
}

fn main() -> std::result::Result<(), exitfailure::ExitFailure> {
    human_panic::setup_panic!();
    let cli = Cli::parse();
    cli.run()?;
    Ok(())
}

#[test]
fn verify_app() {
    use clap::IntoApp;
    Cli::into_app().debug_assert()
}
<|endoftext|>