<commit_before>//! The main event loop which performs I/O on the pseudoterminal.

use std::borrow::Cow;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{self, ErrorKind, Read, Write};
use std::marker::Send;
use std::sync::Arc;
use std::thread::JoinHandle;
use std::time::Instant;

use log::error;
#[cfg(not(windows))]
use mio::unix::UnixReady;
use mio::{self, Events, PollOpt, Ready};
use mio_extras::channel::{self, Receiver, Sender};

use crate::event::{self, Event, EventListener};
use crate::sync::FairMutex;
use crate::term::{SizeInfo, Term};
use crate::{ansi, thread, tty};

/// Max bytes to read from the PTY before forced terminal synchronization.
const READ_BUFFER_SIZE: usize = 0x10_0000;

/// Max bytes to read from the PTY while the terminal is locked.
const MAX_LOCKED_READ: usize = u16::max_value() as usize;

/// Messages that may be sent to the `EventLoop`.
#[derive(Debug)]
pub enum Msg {
    /// Data that should be written to the PTY.
    Input(Cow<'static, [u8]>),

    /// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down.
    Shutdown,

    /// Instruction to resize the PTY.
    Resize(SizeInfo),
}

/// The main event!.. loop.
///
/// Handles all the PTY I/O and runs the PTY parser which updates terminal
/// state.
pub struct EventLoop<T: tty::EventedPty, U: EventListener> {
    poll: mio::Poll,
    pty: T,
    rx: Receiver<Msg>,
    tx: Sender<Msg>,
    terminal: Arc<FairMutex<Term<U>>>,
    event_proxy: U,
    hold: bool,
    ref_test: bool,
}

/// Helper type which tracks how much of a buffer has been written.
struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

pub struct Notifier(pub Sender<Msg>);

impl event::Notify for Notifier {
    fn notify<B>(&self, bytes: B)
    where
        B: Into<Cow<'static, [u8]>>,
    {
        let bytes = bytes.into();
        // terminal hangs if we send 0 bytes through.
        if bytes.len() == 0 {
            return;
        }

        let _ = self.0.send(Msg::Input(bytes));
    }
}

impl event::OnResize for Notifier {
    fn on_resize(&mut self, size: &SizeInfo) {
        let _ = self.0.send(Msg::Resize(*size));
    }
}

/// All of the mutable state needed to run the event loop.
///
/// Contains list of items to write, current write state, etc. Anything that
/// would otherwise be mutated on the `EventLoop` goes here.
#[derive(Default)]
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
    parser: ansi::Processor,
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list.pop_front().map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing { source: c, written: 0 }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

impl<T, U> EventLoop<T, U>
where
    T: tty::EventedPty + event::OnResize + Send + 'static,
    U: EventListener + Send + 'static,
{
    /// Create a new event loop.
    pub fn new(
        terminal: Arc<FairMutex<Term<U>>>,
        event_proxy: U,
        pty: T,
        hold: bool,
        ref_test: bool,
    ) -> EventLoop<T, U> {
        let (tx, rx) = channel::channel();
        EventLoop {
            poll: mio::Poll::new().expect("create mio Poll"),
            pty,
            tx,
            rx,
            terminal,
            event_proxy,
            hold,
            ref_test,
        }
    }

    pub fn channel(&self) -> Sender<Msg> {
        self.tx.clone()
    }

    /// Drain the channel.
    ///
    /// Returns `false` when a shutdown message was received.
    fn drain_recv_channel(&mut self, state: &mut State) -> bool {
        while let Ok(msg) = self.rx.try_recv() {
            match msg {
                Msg::Input(input) => state.write_list.push_back(input),
                Msg::Resize(size) => self.pty.on_resize(&size),
                Msg::Shutdown => return false,
            }
        }

        true
    }

    /// Returns a `bool` indicating whether or not the event loop should continue running.
    #[inline]
    fn channel_event(&mut self, token: mio::Token, state: &mut State) -> bool {
        if !self.drain_recv_channel(state) {
            return false;
        }

        self.poll
            .reregister(&self.rx, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())
            .unwrap();

        true
    }

    #[inline]
    fn pty_read<X>(
        &mut self,
        state: &mut State,
        buf: &mut [u8],
        mut writer: Option<&mut X>,
    ) -> io::Result<()>
    where
        X: Write,
    {
        let mut unprocessed = 0;
        let mut processed = 0;

        // Reserve the next terminal lock for PTY reading.
        let _terminal_lease = Some(self.terminal.lease());
        let mut terminal = None;

        loop {
            // Read from the PTY.
            match self.pty.reader().read(&mut buf[unprocessed..]) {
                // This is received on Windows/macOS when no more data is readable from the PTY.
                Ok(0) if unprocessed == 0 => break,
                Ok(got) => unprocessed += got,
                Err(err) => match err.kind() {
                    ErrorKind::Interrupted | ErrorKind::WouldBlock => {
                        // Go back to mio if we're caught up on parsing and the PTY would block.
                        if unprocessed == 0 {
                            break;
                        }
                    },
                    _ => return Err(err),
                },
            }

            // Attempt to lock the terminal.
            let terminal = match &mut terminal {
                Some(terminal) => terminal,
                None => terminal.insert(match self.terminal.try_lock_unfair() {
                    // Force block if we are at the buffer size limit.
                    None if unprocessed >= READ_BUFFER_SIZE => self.terminal.lock_unfair(),
                    None => continue,
                    Some(terminal) => terminal,
                }),
            };

            // Write a copy of the bytes to the ref test file.
            if let Some(writer) = &mut writer {
                writer.write_all(&buf[..unprocessed]).unwrap();
            }

            // Parse the incoming bytes.
            for byte in &buf[..unprocessed] {
                state.parser.advance(&mut **terminal, *byte);
            }

            processed += unprocessed;
            unprocessed = 0;

            // Assure we're not blocking the terminal too long unnecessarily.
            if processed >= MAX_LOCKED_READ {
                break;
            }
        }

        // Queue terminal redraw unless all processed bytes were synchronized.
        if state.parser.sync_bytes_count() < processed && processed > 0 {
            self.event_proxy.send_event(Event::Wakeup);
        }

        Ok(())
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) -> io::Result<()> {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.writer().write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    },
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    },
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted | ErrorKind::WouldBlock => break 'write_many,
                            _ => return Err(err),
                        }
                    },
                }
            }
        }

        Ok(())
    }

    pub fn spawn(mut self) -> JoinHandle<(Self, State)> {
        thread::spawn_named("PTY reader", move || {
            let mut state = State::default();
            let mut buf = [0u8; READ_BUFFER_SIZE];

            let mut tokens = (0..).map(Into::into);

            let poll_opts = PollOpt::edge() | PollOpt::oneshot();

            let channel_token = tokens.next().unwrap();
            self.poll.register(&self.rx, channel_token, Ready::readable(), poll_opts).unwrap();

            // Register TTY through EventedRW interface.
            self.pty.register(&self.poll, &mut tokens, Ready::readable(), poll_opts).unwrap();

            let mut events = Events::with_capacity(1024);

            let mut pipe = if self.ref_test {
                Some(File::create("./alacritty.recording").expect("create alacritty recording"))
            } else {
                None
            };

            'event_loop: loop {
                // Wakeup the event loop when a synchronized update timeout was reached.
                let sync_timeout = state.parser.sync_timeout();
                let timeout = sync_timeout.map(|st| st.saturating_duration_since(Instant::now()));

                if let Err(err) = self.poll.poll(&mut events, timeout) {
                    match err.kind() {
                        ErrorKind::Interrupted => continue,
                        _ => panic!("EventLoop polling error: {:?}", err),
                    }
                }

                // Handle synchronized update timeout.
                if events.is_empty() {
                    state.parser.stop_sync(&mut *self.terminal.lock());
                    self.event_proxy.send_event(Event::Wakeup);
                    continue;
                }

                for event in events.iter() {
                    match event.token() {
                        token if token == channel_token => {
                            if !self.channel_event(channel_token, &mut state) {
                                break 'event_loop;
                            }
                        },

                        token if token == self.pty.child_event_token() => {
                            if let Some(tty::ChildEvent::Exited) = self.pty.next_child_event() {
                                if self.hold {
                                    // With hold enabled, make sure the PTY is drained.
                                    let _ = self.pty_read(&mut state, &mut buf, pipe.as_mut());
                                } else {
                                    // Without hold, shutdown the terminal.
                                    self.terminal.lock().exit();
                                }

                                self.event_proxy.send_event(Event::Wakeup);
                                break 'event_loop;
                            }
                        },

                        token
                            if token == self.pty.read_token()
                                || token == self.pty.write_token() =>
                        {
                            #[cfg(unix)]
                            if UnixReady::from(event.readiness()).is_hup() {
                                // Don't try to do I/O on a dead PTY.
                                continue;
                            }

                            if event.readiness().is_readable() {
                                if let Err(err) = self.pty_read(&mut state, &mut buf, pipe.as_mut())
                                {
                                    // On Linux, a `read` on the master side of a PTY can fail
                                    // with `EIO` if the client side hangs up.  In that case,
                                    // just loop back round for the inevitable `Exited` event.
                                    // This sucks, but checking the process is either racy or
                                    // blocking.
                                    #[cfg(target_os = "linux")]
                                    if err.raw_os_error() == Some(libc::EIO) {
                                        continue;
                                    }

                                    error!("Error reading from PTY in event loop: {}", err);
                                    break 'event_loop;
                                }
                            }

                            if event.readiness().is_writable() {
                                if let Err(err) = self.pty_write(&mut state) {
                                    error!("Error writing to PTY in event loop: {}", err);
                                    break 'event_loop;
                                }
                            }
                        },
                        _ => (),
                    }
                }

                // Register write interest if necessary.
                let mut interest = Ready::readable();
                if state.needs_write() {
                    interest.insert(Ready::writable());
                }
                // Reregister with new interest.
                self.pty.reregister(&self.poll, interest, poll_opts).unwrap();
            }

            // The evented instances are not dropped here so deregister them explicitly.
            let _ = self.poll.deregister(&self.rx);
            let _ = self.pty.deregister(&self.poll);

            (self, state)
        })
    }
}

trait OptionInsert {
    type T;
    fn insert(&mut self, value: Self::T) -> &mut Self::T;
}

// TODO: Remove when MSRV is >= 1.53.0.
//
/// Trait implementation to support Rust version < 1.53.0.
///
/// This is taken [from STD], further license information can be found in the [rust-lang/rust
/// repository].
///
///
/// [from STD]: https://github.com/rust-lang/rust/blob/6e0b554619a3bb7e75b3334e97f191af20ef5d76/library/core/src/option.rs#L829-L858
/// [rust-lang/rust repository]: https://github.com/rust-lang/rust/blob/master/LICENSE-MIT
impl<T> OptionInsert for Option<T> {
    type T = T;

    fn insert(&mut self, value: T) -> &mut T {
        *self = Some(value);

        match self {
            Some(v) => v,
            // SAFETY: the code above just filled the option
            None => unsafe { std::hint::unreachable_unchecked() },
        }
    }
}
<commit_msg>Remove outdated Rust compatibility code<commit_after>//! The main event loop which performs I/O on the pseudoterminal.

use std::borrow::Cow;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{self, ErrorKind, Read, Write};
use std::marker::Send;
use std::sync::Arc;
use std::thread::JoinHandle;
use std::time::Instant;

use log::error;
#[cfg(not(windows))]
use mio::unix::UnixReady;
use mio::{self, Events, PollOpt, Ready};
use mio_extras::channel::{self, Receiver, Sender};

use crate::event::{self, Event, EventListener};
use crate::sync::FairMutex;
use crate::term::{SizeInfo, Term};
use crate::{ansi, thread, tty};

/// Max bytes to read from the PTY before forced terminal synchronization.
const READ_BUFFER_SIZE: usize = 0x10_0000;

/// Max bytes to read from the PTY while the terminal is locked.
const MAX_LOCKED_READ: usize = u16::max_value() as usize;

/// Messages that may be sent to the `EventLoop`.
#[derive(Debug)]
pub enum Msg {
    /// Data that should be written to the PTY.
    Input(Cow<'static, [u8]>),

    /// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down.
    Shutdown,

    /// Instruction to resize the PTY.
    Resize(SizeInfo),
}

/// The main event!.. loop.
///
/// Handles all the PTY I/O and runs the PTY parser which updates terminal
/// state.
pub struct EventLoop<T: tty::EventedPty, U: EventListener> {
    poll: mio::Poll,
    pty: T,
    rx: Receiver<Msg>,
    tx: Sender<Msg>,
    terminal: Arc<FairMutex<Term<U>>>,
    event_proxy: U,
    hold: bool,
    ref_test: bool,
}

/// Helper type which tracks how much of a buffer has been written.
struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

pub struct Notifier(pub Sender<Msg>);

impl event::Notify for Notifier {
    fn notify<B>(&self, bytes: B)
    where
        B: Into<Cow<'static, [u8]>>,
    {
        let bytes = bytes.into();
        // terminal hangs if we send 0 bytes through.
        if bytes.len() == 0 {
            return;
        }

        let _ = self.0.send(Msg::Input(bytes));
    }
}

impl event::OnResize for Notifier {
    fn on_resize(&mut self, size: &SizeInfo) {
        let _ = self.0.send(Msg::Resize(*size));
    }
}

/// All of the mutable state needed to run the event loop.
///
/// Contains list of items to write, current write state, etc. Anything that
/// would otherwise be mutated on the `EventLoop` goes here.
#[derive(Default)]
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
    parser: ansi::Processor,
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list.pop_front().map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing { source: c, written: 0 }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

impl<T, U> EventLoop<T, U>
where
    T: tty::EventedPty + event::OnResize + Send + 'static,
    U: EventListener + Send + 'static,
{
    /// Create a new event loop.
    pub fn new(
        terminal: Arc<FairMutex<Term<U>>>,
        event_proxy: U,
        pty: T,
        hold: bool,
        ref_test: bool,
    ) -> EventLoop<T, U> {
        let (tx, rx) = channel::channel();
        EventLoop {
            poll: mio::Poll::new().expect("create mio Poll"),
            pty,
            tx,
            rx,
            terminal,
            event_proxy,
            hold,
            ref_test,
        }
    }

    pub fn channel(&self) -> Sender<Msg> {
        self.tx.clone()
    }

    /// Drain the channel.
    ///
    /// Returns `false` when a shutdown message was received.
    fn drain_recv_channel(&mut self, state: &mut State) -> bool {
        while let Ok(msg) = self.rx.try_recv() {
            match msg {
                Msg::Input(input) => state.write_list.push_back(input),
                Msg::Resize(size) => self.pty.on_resize(&size),
                Msg::Shutdown => return false,
            }
        }

        true
    }

    /// Returns a `bool` indicating whether or not the event loop should continue running.
    #[inline]
    fn channel_event(&mut self, token: mio::Token, state: &mut State) -> bool {
        if !self.drain_recv_channel(state) {
            return false;
        }

        self.poll
            .reregister(&self.rx, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())
            .unwrap();

        true
    }

    #[inline]
    fn pty_read<X>(
        &mut self,
        state: &mut State,
        buf: &mut [u8],
        mut writer: Option<&mut X>,
    ) -> io::Result<()>
    where
        X: Write,
    {
        let mut unprocessed = 0;
        let mut processed = 0;

        // Reserve the next terminal lock for PTY reading.
        let _terminal_lease = Some(self.terminal.lease());
        let mut terminal = None;

        loop {
            // Read from the PTY.
            match self.pty.reader().read(&mut buf[unprocessed..]) {
                // This is received on Windows/macOS when no more data is readable from the PTY.
                Ok(0) if unprocessed == 0 => break,
                Ok(got) => unprocessed += got,
                Err(err) => match err.kind() {
                    ErrorKind::Interrupted | ErrorKind::WouldBlock => {
                        // Go back to mio if we're caught up on parsing and the PTY would block.
                        if unprocessed == 0 {
                            break;
                        }
                    },
                    _ => return Err(err),
                },
            }

            // Attempt to lock the terminal.
            let terminal = match &mut terminal {
                Some(terminal) => terminal,
                None => terminal.insert(match self.terminal.try_lock_unfair() {
                    // Force block if we are at the buffer size limit.
                    None if unprocessed >= READ_BUFFER_SIZE => self.terminal.lock_unfair(),
                    None => continue,
                    Some(terminal) => terminal,
                }),
            };

            // Write a copy of the bytes to the ref test file.
            if let Some(writer) = &mut writer {
                writer.write_all(&buf[..unprocessed]).unwrap();
            }

            // Parse the incoming bytes.
            for byte in &buf[..unprocessed] {
                state.parser.advance(&mut **terminal, *byte);
            }

            processed += unprocessed;
            unprocessed = 0;

            // Assure we're not blocking the terminal too long unnecessarily.
            if processed >= MAX_LOCKED_READ {
                break;
            }
        }

        // Queue terminal redraw unless all processed bytes were synchronized.
        if state.parser.sync_bytes_count() < processed && processed > 0 {
            self.event_proxy.send_event(Event::Wakeup);
        }

        Ok(())
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) -> io::Result<()> {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.writer().write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    },
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    },
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted | ErrorKind::WouldBlock => break 'write_many,
                            _ => return Err(err),
                        }
                    },
                }
            }
        }

        Ok(())
    }

    pub fn spawn(mut self) -> JoinHandle<(Self, State)> {
        thread::spawn_named("PTY reader", move || {
            let mut state = State::default();
            let mut buf = [0u8; READ_BUFFER_SIZE];

            let mut tokens = (0..).map(Into::into);

            let poll_opts = PollOpt::edge() | PollOpt::oneshot();

            let channel_token = tokens.next().unwrap();
            self.poll.register(&self.rx, channel_token, Ready::readable(), poll_opts).unwrap();

            // Register TTY through EventedRW interface.
            self.pty.register(&self.poll, &mut tokens, Ready::readable(), poll_opts).unwrap();

            let mut events = Events::with_capacity(1024);

            let mut pipe = if self.ref_test {
                Some(File::create("./alacritty.recording").expect("create alacritty recording"))
            } else {
                None
            };

            'event_loop: loop {
                // Wakeup the event loop when a synchronized update timeout was reached.
                let sync_timeout = state.parser.sync_timeout();
                let timeout = sync_timeout.map(|st| st.saturating_duration_since(Instant::now()));

                if let Err(err) = self.poll.poll(&mut events, timeout) {
                    match err.kind() {
                        ErrorKind::Interrupted => continue,
                        _ => panic!("EventLoop polling error: {:?}", err),
                    }
                }

                // Handle synchronized update timeout.
                if events.is_empty() {
                    state.parser.stop_sync(&mut *self.terminal.lock());
                    self.event_proxy.send_event(Event::Wakeup);
                    continue;
                }

                for event in events.iter() {
                    match event.token() {
                        token if token == channel_token => {
                            if !self.channel_event(channel_token, &mut state) {
                                break 'event_loop;
                            }
                        },

                        token if token == self.pty.child_event_token() => {
                            if let Some(tty::ChildEvent::Exited) = self.pty.next_child_event() {
                                if self.hold {
                                    // With hold enabled, make sure the PTY is drained.
                                    let _ = self.pty_read(&mut state, &mut buf, pipe.as_mut());
                                } else {
                                    // Without hold, shutdown the terminal.
                                    self.terminal.lock().exit();
                                }

                                self.event_proxy.send_event(Event::Wakeup);
                                break 'event_loop;
                            }
                        },

                        token
                            if token == self.pty.read_token()
                                || token == self.pty.write_token() =>
                        {
                            #[cfg(unix)]
                            if UnixReady::from(event.readiness()).is_hup() {
                                // Don't try to do I/O on a dead PTY.
                                continue;
                            }

                            if event.readiness().is_readable() {
                                if let Err(err) = self.pty_read(&mut state, &mut buf, pipe.as_mut())
                                {
                                    // On Linux, a `read` on the master side of a PTY can fail
                                    // with `EIO` if the client side hangs up.  In that case,
                                    // just loop back round for the inevitable `Exited` event.
                                    // This sucks, but checking the process is either racy or
                                    // blocking.
                                    #[cfg(target_os = "linux")]
                                    if err.raw_os_error() == Some(libc::EIO) {
                                        continue;
                                    }

                                    error!("Error reading from PTY in event loop: {}", err);
                                    break 'event_loop;
                                }
                            }

                            if event.readiness().is_writable() {
                                if let Err(err) = self.pty_write(&mut state) {
                                    error!("Error writing to PTY in event loop: {}", err);
                                    break 'event_loop;
                                }
                            }
                        },
                        _ => (),
                    }
                }

                // Register write interest if necessary.
                let mut interest = Ready::readable();
                if state.needs_write() {
                    interest.insert(Ready::writable());
                }
                // Reregister with new interest.
                self.pty.reregister(&self.poll, interest, poll_opts).unwrap();
            }

            // The evented instances are not dropped here so deregister them explicitly.
            let _ = self.poll.deregister(&self.rx);
            let _ = self.pty.deregister(&self.poll);

            (self, state)
        })
    }
}
<|endoftext|>


<commit_before>use std::time::Instant;
use std::time::Duration;

use heuristic::Heuristic;

use bitboard::Board;
use bitboard::Move;
use bitboard::Turn;

use transposition::TranspositionTable;

use std::i32;

macro_rules! cerrln(
    ($($arg:tt)*) => { {
        use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

use NegamaxSearch;

///Implements the MTD(f) algorithm
///
/// * `ng` The negamax search object
/// * `bb` The root position to search from
/// * `g` A guess of the true minimax score.
/// * `d` The maximum depth to search to
/// * `ms_left` The number of milliseconds allocated to make the move
pub fn mtdf_timeout<H : Heuristic>(
    ng      : &mut NegamaxSearch<H>,
    bb      : Board,
    mut g   : i32,
    d       : u8,
    ms_left : u64,
) -> (Move, i32) {

    let mut best_move = Move::pass();
    let mut low = i32::MIN;
    let mut high = i32::MAX;

    let mut bounds = [i32::MIN, i32::MAX];

    while bounds[0] < bounds[1] {

        ////////////////////////////////////////////////////////////////////
        //do an alpha-beta search here
        ////////////////////////////////////////////////////////////////////

        let mut test = if g == bounds[0] { g+1 } else { g };

        g = ng.negamax(bb, test-1, test, d, ms_left, &mut best_move);

        ////////////////////////////////////////////////////////////////////
        //end alpha-beta search, get result. The result must not be a timeout
        ////////////////////////////////////////////////////////////////////

        //update MTD(f) bounds
        bounds[(g < test) as usize] = g;

        if ng.timeout() {
            return (Move::null(), 0);
        }

    }

    (best_move, g)
}

///Iterative deepening implementation of MTD(f).
/// * `bb` The root position to search from
/// * `h` The heuristic to use for searches
/// * `t` The current turn
/// * `alpha` The lower bound of the minimax score
/// * `beta` The upper bound of the minimax score
/// * `d` The maximum depth to search to
/// * `ms_left` The number of milliseconds allocated to make the move
pub fn mtdf_id_timeout<H : Heuristic + Clone, Hf : Heuristic + Clone>(
    bb      : Board,
    hs      : &[Box<H>],
    hz      : Box<Hf>,
    md      : u8,
    ms_left : u64
) -> Move {

    let start = Instant::now();

    //check if I have any moves
    if !bb.has_move().0 {
        cerrln!("[COIN]: Passing.");
        return Move::pass();
    }

    let empty = bb.total_empty();

    cerrln!("[COIN]: Starting MTD(f) search for {}!", bb.get_turn());

    let mut mv = Move::null();
    let mut f = 0;
    let mut d = 5;

    cerrln!("[COIN]: | {: <5} | {: <9} | {: <13} | {: <14} | {: <14} | {: <12} |",
            "Depth", "Best Move", "Minimax Value", "Transpositions", "Nodes Searched", "Time Elapsed");
    cerrln!("[COIN]: |{0:-<7}|{0:-<11}|{0:-<15}|{0:-<16}|{0:-<16}|{0:-<14}|", "");

    while d <= md && start.elapsed() < Duration::from_millis(ms_left) {

        //clears history heuristic for move ordering to match the current
        //depth of search
        //self.reinit_history();

        let mut hi = (if (empty as i16 - d as i16 - 1) < 0 {0} else {empty as i16 - d as i16 - 1})/3;

        let mut to = false;
        let mut sr = 0;
        let mut tr = 0;
        //isolate so compiler can detect types and optimize properly
        let (m, v) = if empty - d == 0 {
            let mut ng = NegamaxSearch::new(hz.clone(), start);
            let (m,v) = mtdf_timeout(&mut ng, bb.copy(), f, d, ms_left);
            tr = ng.get_transpositions();
            sr = ng.get_searched();
            to = ng.timeout();
            (m,v)
        } else {
            let mut ng = NegamaxSearch::new(hs[hi as usize].clone(), start);
            let (m,v) = mtdf_timeout(&mut ng, bb.copy(), f, d, ms_left);
            tr = ng.get_transpositions();
            sr = ng.get_searched();
            to = ng.timeout();
            (m,v)
        };

        if to {
            cerrln!("[COIN]: TIMEOUT");
            break;
        }
        f = v;
        mv = m;

        let elapsed = {
            let d = start.elapsed();
            (d.as_secs() as f32) + (d.subsec_nanos() as f32)/1_000_000_000f32
        };

        cerrln!("[COIN]: | {: >5} | {: >9} | {: >13} | {: >14} | {: >14} | {: >12.2} |",
                d, format!("{}",mv), f, tr, sr, elapsed);

        //This allows us to search deeper as well as compare scores between
        //iterations more accurately
        d += 2;

        // we've reached the end of the search depth.
        if hi == 0 {
            break;
        }
    }

     let d = start.elapsed();
    cerrln!(
        "[COIN]: Done searching ({} s). Best move is {}",
        (d.as_secs() as f32) + (d.subsec_nanos() as f32)/1_000_000_000f32,
        mv
    );

    return mv;
}<commit_msg>slight modifications to the mtdf to try to fix it<commit_after>use std::time::Instant;
use std::time::Duration;

use heuristic::Heuristic;

use bitboard::Board;
use bitboard::Move;
use bitboard::Turn;

use transposition::TranspositionTable;

use std::i32;

macro_rules! cerrln(
    ($($arg:tt)*) => { {
        use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

use NegamaxSearch;

///Implements the MTD(f) algorithm
///
/// * `ng` The negamax search object
/// * `bb` The root position to search from
/// * `g` A guess of the true minimax score.
/// * `d` The maximum depth to search to
/// * `ms_left` The number of milliseconds allocated to make the move
pub fn mtdf_timeout<H : Heuristic>(
    ng      : &mut NegamaxSearch<H>,
    bb      : Board,
    mut g   : i32,
    d       : u8,
    ms_left : u64,
) -> (Move, i32) {

    let mut best_move = Move::pass();
    let mut low = i32::MIN;
    let mut high = i32::MAX;

    let mut bounds = [i32::MIN, i32::MAX];

    while bounds[0] < bounds[1] {

        ////////////////////////////////////////////////////////////////////
        //do an alpha-beta search here
        ////////////////////////////////////////////////////////////////////

        let mut test = if g == bounds[0] { g+1 } else { g };

        let mut tmp_mv = Move::null();

        g = ng.negamax(bb, test-1, test, d, ms_left, &mut tmp_mv);

        ////////////////////////////////////////////////////////////////////
        //end alpha-beta search, get result. The result must not be a timeout
        ////////////////////////////////////////////////////////////////////

        //update MTD(f) bounds
        bounds[(g < test) as usize] = g;

        if ng.timeout() {
            return (Move::null(), 0);
        }

        best_move = tmp_mv;
    }

    (best_move, g)
}

///Iterative deepening implementation of MTD(f).
/// * `bb` The root position to search from
/// * `h` The heuristic to use for searches
/// * `t` The current turn
/// * `alpha` The lower bound of the minimax score
/// * `beta` The upper bound of the minimax score
/// * `d` The maximum depth to search to
/// * `ms_left` The number of milliseconds allocated to make the move
pub fn mtdf_id_timeout<H : Heuristic + Clone, Hf : Heuristic + Clone>(
    bb      : Board,
    hs      : &[Box<H>],
    hz      : Box<Hf>,
    md      : u8,
    ms_left : u64
) -> Move {

    let start = Instant::now();

    //check if I have any moves
    if !bb.has_move().0 {
        cerrln!("[COIN]: Passing.");
        return Move::pass();
    }

    let empty = bb.total_empty();

    cerrln!("[COIN]: Starting MTD(f) search for {}!", bb.get_turn());

    let mut mv = Move::null();
    let mut f = 0;
    let mut d = 5;

    cerrln!("[COIN]: | {: <5} | {: <9} | {: <13} | {: <14} | {: <14} | {: <12} |",
            "Depth", "Best Move", "Minimax Value", "Transpositions", "Nodes Searched", "Time Elapsed");
    cerrln!("[COIN]: |{0:-<7}|{0:-<11}|{0:-<15}|{0:-<16}|{0:-<16}|{0:-<14}|", "");

    while d <= md && start.elapsed() < Duration::from_millis(ms_left) {

        //clears history heuristic for move ordering to match the current
        //depth of search
        //self.reinit_history();

        let mut hi = (if (empty as i16 - d as i16 - 1) < 0 {0} else {empty as i16 - d as i16 - 1})/3;

        let mut to = false;
        let mut sr = 0;
        let mut tr = 0;
        //isolate so compiler can detect types and optimize properly
        let (m, v) = if empty as i32 - d as i32 <= 0 {
            let mut ng = NegamaxSearch::new(hz.clone(), start);
            let (m,v) = mtdf_timeout(&mut ng, bb.copy(), f, d, ms_left);
            tr = ng.get_transpositions();
            sr = ng.get_searched();
            to = ng.timeout();
            (m,v)
        } else {
            let mut ng = NegamaxSearch::new(hs[hi as usize].clone(), start);
            let (m,v) = mtdf_timeout(&mut ng, bb.copy(), f, d, ms_left);
            tr = ng.get_transpositions();
            sr = ng.get_searched();
            to = ng.timeout();
            (m,v)
        };

        if to {
            cerrln!("[COIN]: TIMEOUT");
            break;
        }
        f = v;
        mv = m;

        let elapsed = {
            let d = start.elapsed();
            (d.as_secs() as f32) + (d.subsec_nanos() as f32)/1_000_000_000f32
        };

        cerrln!("[COIN]: | {: >5} | {: >9} | {: >13} | {: >14} | {: >14} | {: >12.2} |",
                d, format!("{}",mv), f, tr, sr, elapsed);

        //This allows us to search deeper as well as compare scores between
        //iterations more accurately
        d += 2;

        // we've reached the end of the search depth.
        if hi == 0 {
            break;
        }
    }

     let d = start.elapsed();
    cerrln!(
        "[COIN]: Done searching ({} s). Best move is {}",
        (d.as_secs() as f32) + (d.subsec_nanos() as f32)/1_000_000_000f32,
        mv
    );

    return mv;
}<|endoftext|>


<commit_before>use bluetooth_session::BluetoothSession;
use dbus::{Message, MessageItem};
use std::error::Error;

static ADAPTER_INTERFACE: &'static str = "org.bluez.Adapter1";
static SERVICE_NAME: &'static str = "org.bluez";

pub struct BluetoothDiscoverySession<'a> {
    adapter: String,
    session: &'a BluetoothSession,
}

impl<'a> BluetoothDiscoverySession<'a> {
    pub fn create_session(
        session: &'a BluetoothSession,
        adapter: String,
    ) -> Result<BluetoothDiscoverySession, Box<Error>> {
        Ok(BluetoothDiscoverySession::new(session, adapter))
    }

    fn new(session: &'a BluetoothSession, adapter: String) -> BluetoothDiscoverySession<'a> {
        BluetoothDiscoverySession {
            adapter: adapter,
            session: session,
        }
    }

    fn call_method(&self, method: &str, param: Option<[MessageItem; 1]>) -> Result<(), Box<Error>> {
        let mut m = try!(Message::new_method_call(
            SERVICE_NAME,
            &self.adapter,
            ADAPTER_INTERFACE,
            method
        ));
        match param {
            Some(p) => m.append_items(&p),
            None => (),
        };
        try!(
            self.session
                .get_connection()
                .send_with_reply_and_block(m, 1000)
        );
        Ok(())
    }

    pub fn start_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StartDiscovery", None)
    }

    pub fn stop_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StopDiscovery", None)
    }
}
<commit_msg>implemented BluetoothDiscoverySession::set_discovery_filter()<commit_after>use bluetooth_session::BluetoothSession;
use dbus::{Message, MessageItem, MessageItemArray, Signature};
use std::error::Error;

static ADAPTER_INTERFACE: &'static str = "org.bluez.Adapter1";
static SERVICE_NAME: &'static str = "org.bluez";

pub struct BluetoothDiscoverySession<'a> {
    adapter: String,
    session: &'a BluetoothSession,
}

impl<'a> BluetoothDiscoverySession<'a> {
    pub fn create_session(
        session: &'a BluetoothSession,
        adapter: String,
    ) -> Result<BluetoothDiscoverySession, Box<Error>> {
        Ok(BluetoothDiscoverySession::new(session, adapter))
    }

    fn new(session: &'a BluetoothSession, adapter: String) -> BluetoothDiscoverySession<'a> {
        BluetoothDiscoverySession {
            adapter: adapter,
            session: session,
        }
    }

    fn call_method(&self, method: &str, param: Option<[MessageItem; 1]>) -> Result<(), Box<Error>> {
        let mut m = try!(Message::new_method_call(
            SERVICE_NAME,
            &self.adapter,
            ADAPTER_INTERFACE,
            method
        ));
        match param {
            Some(p) => m.append_items(&p),
            None => (),
        };
        try!(
            self.session
                .get_connection()
                .send_with_reply_and_block(m, 1000)
        );
        Ok(())
    }

    pub fn start_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StartDiscovery", None)
    }

    pub fn stop_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StopDiscovery", None)
    }

    pub fn set_discovery_filter(
        &self,
        uuids: Vec<String>,
        rssi: Option<i16>,
        pathloss: Option<u16>,
    ) -> Result<(), Box<Error>> {
        let uuids = {
            let mut res: Vec<MessageItem> = Vec::new();
            for u in uuids {
                res.push(u.into());
            }
            res
        };

        let mut m = vec![MessageItem::DictEntry(
            Box::new("UUIDs".into()),
            Box::new(MessageItem::Variant(Box::new(
                MessageItem::new_array(uuids).unwrap(),
            ))),
        )];

        if let Some(rssi) = rssi {
            m.push(MessageItem::DictEntry(
                Box::new("RSSI".into()),
                Box::new(MessageItem::Variant(Box::new(rssi.into()))),
            ))
        }

        if let Some(pathloss) = pathloss {
            m.push(MessageItem::DictEntry(
                Box::new("Pathloss".into()),
                Box::new(MessageItem::Variant(Box::new(pathloss.into()))),
            ))
        }

        self.call_method(
            "SetDiscoveryFilter",
            Some([MessageItem::Array(
                MessageItemArray::new(m, Signature::from("a{sv}")).unwrap(),
            )]),
        )
    }
}
<|endoftext|>


<commit_before>extern crate clap;

use clap::{App, Arg};

fn main() {
    // Args describe a possible valid argument which may be supplied by the user at runtime. There
    // are three different types of arguments (flags, options, and positional) as well as a fourth
    // special type of argument, called SubCommands (which will be discussed separately).
    //
    // Args are described in the same manner as Apps using the "builder pattern" with multiple
    // methods describing various settings for the individual arguments. Or by supplying a "usage"
    // string. Both methods have their pros and cons.
    //
    // Arguments can be added to applications in two manners, one at a time with the arg(), and
    // arg_from_usage() method, or multiple arguments at once via a Vec<Arg> inside the args() method,
    // or a single &str describing multiple Args (one per line) supplied to args_from_usage().
    //
    // There are various options which can be set for a given argument, some apply to any of the
    // three types of arguments, some only apply one or two of the types. *NOTE* if you set
    // incompatible options on a single argument, clap will panic! at runtime. This is by design,
    // so that you know right away an error was made by the developer, not the end user.
    //
    // # Help and Version
    // clap automatically generates a help and version flag for you, unless you specificy your
    // own. By default help uses "-h" and "--help", and version uses "-V" and "--version". You can
    // safely overide "-V" and "-h" to your own arguments, and "--help" and "--version" will stil
    // be automatically generated for you.
    let matches = App::new("MyApp")
                        // All application settings go here...

                        // A simple "Flag" argument example (i.e. "-d") using the builder pattern
                        .arg(Arg::with_name("debug")
                                    .help("turn on debugging information")
                                    .short("d"))

                        // Two arguments, one "Option" argument (i.e. one that takes a value) such
                        // as "-c some", and one positional argument (i.e. "myapp some_file")
                        .args(&[
                            Arg::with_name("config")
                                    .help("sets the config file to use")
                                    .takes_value(true)
                                    .short("c")
                                    .long("config"),
                            Arg::with_name("input")
                                    .help("the input file to use")
                                    .index(1)
                                    .required(true)
                        ])

                        // *Note* the following two examples are convienience methods, if you wish
                        // to still get the full configurability of Arg::with_name() and the readability
                        // of arg_from_usage(), you can instantiate a new Arg with Arg::from_usage() and
                        // still be able to set all the additional properties, just like Arg::with_name()
                        //
                        //
                        // One "Flag" using a usage string
                        .arg_from_usage("--license 'display the license file'")

                        // Two args, one "Positional", and one "Option" using a usage string
                        .args_from_usage("[output] 'Supply an output file to use'
                                          -i, --int=[IFACE] 'Set an interface to use'")
                        .get_matches();

    // Here are some examples of using the arguments defined above. Keep in mind that this is only
    // an example, and may be somewhat contrived
    //
    // First we check if debugging should be on or not
    println!("Debugging mode is: {}", if matches.is_present("debug") { "ON" } else { "OFF" });

    // Next we print the config file we're using, if any was defined with either -c <file> or
    // --config <file>
    if let Some(config) = matches.value_of("config") {
        println!("A config file was passed in: {}", config);
    }

    // Let's print the <INPUT> file the user passed in. We can use .unwrap() here becase the arg is
    // required, and parsing would have failed if the user forgot it
    println!("Using input file: {}", matches.value_of("input").unwrap());

    // We could continue checking for and using arguments in this manner, such as "license",
    // "output", and "interface". Keep in mind that "output" and "interface" are optional, so you
    // shouldn't call .unwrap(), instead prefer using an 'if let' expression as we did with
    // "config"
}
<commit_msg>Fix typos in 03_args.rs<commit_after>extern crate clap;

use clap::{App, Arg};

fn main() {
    // Args describe a possible valid argument which may be supplied by the user at runtime. There
    // are three different types of arguments (flags, options, and positional) as well as a fourth
    // special type of argument, called SubCommands (which will be discussed separately).
    //
    // Args are described in the same manner as Apps using the "builder pattern" with multiple
    // methods describing various settings for the individual arguments. Or by supplying a "usage"
    // string. Both methods have their pros and cons.
    //
    // Arguments can be added to applications in two manners, one at a time with the arg(), and
    // arg_from_usage() method, or multiple arguments at once via a Vec<Arg> inside the args() method,
    // or a single &str describing multiple Args (one per line) supplied to args_from_usage().
    //
    // There are various options which can be set for a given argument, some apply to any of the
    // three types of arguments, some only apply one or two of the types. *NOTE* if you set
    // incompatible options on a single argument, clap will panic! at runtime. This is by design,
    // so that you know right away an error was made by the developer, not the end user.
    //
    // # Help and Version
    // clap automatically generates a help and version flag for you, unless you specify your
    // own. By default help uses "-h" and "--help", and version uses "-V" and "--version". You can
    // safely override "-V" and "-h" to your own arguments, and "--help" and "--version" will still
    // be automatically generated for you.
    let matches = App::new("MyApp")
                        // All application settings go here...

                        // A simple "Flag" argument example (i.e. "-d") using the builder pattern
                        .arg(Arg::with_name("debug")
                                    .help("turn on debugging information")
                                    .short("d"))

                        // Two arguments, one "Option" argument (i.e. one that takes a value) such
                        // as "-c some", and one positional argument (i.e. "myapp some_file")
                        .args(&[
                            Arg::with_name("config")
                                    .help("sets the config file to use")
                                    .takes_value(true)
                                    .short("c")
                                    .long("config"),
                            Arg::with_name("input")
                                    .help("the input file to use")
                                    .index(1)
                                    .required(true)
                        ])

                        // *Note* the following two examples are convenience methods, if you wish
                        // to still get the full configurability of Arg::with_name() and the readability
                        // of arg_from_usage(), you can instantiate a new Arg with Arg::from_usage() and
                        // still be able to set all the additional properties, just like Arg::with_name()
                        //
                        //
                        // One "Flag" using a usage string
                        .arg_from_usage("--license 'display the license file'")

                        // Two args, one "Positional", and one "Option" using a usage string
                        .args_from_usage("[output] 'Supply an output file to use'
                                          -i, --int=[IFACE] 'Set an interface to use'")
                        .get_matches();

    // Here are some examples of using the arguments defined above. Keep in mind that this is only
    // an example, and may be somewhat contrived
    //
    // First we check if debugging should be on or not
    println!("Debugging mode is: {}", if matches.is_present("debug") { "ON" } else { "OFF" });

    // Next we print the config file we're using, if any was defined with either -c <file> or
    // --config <file>
    if let Some(config) = matches.value_of("config") {
        println!("A config file was passed in: {}", config);
    }

    // Let's print the <INPUT> file the user passed in. We can use .unwrap() here becase the arg is
    // required, and parsing would have failed if the user forgot it
    println!("Using input file: {}", matches.value_of("input").unwrap());

    // We could continue checking for and using arguments in this manner, such as "license",
    // "output", and "interface". Keep in mind that "output" and "interface" are optional, so you
    // shouldn't call .unwrap(). Instead, prefer using an 'if let' expression as we did with
    // "config"
}
<|endoftext|>


<commit_before>struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    fn new(data: T, next: Option<Box<Node<T>>>) -> Self {
        Node { data, next }
    }
}

struct LinkedListIterator<'a, T: 'a> {
    node: &'a Option<Box<Node<T>>>,
}

impl<'a, T> Iterator for LinkedListIterator<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(node) = self.node {
            self.node = &node.next;
            Some(&node)
        } else {
            None
        }
    }
}

pub struct SimpleLinkedList<T> {
    head: Option<Box<Node<T>>>,
}

impl<T> SimpleLinkedList<T> {
    pub fn new() -> Self {
        SimpleLinkedList { head: None }
    }

    pub fn len(&self) -> usize {
        self.iter().count()
    }

    pub fn push(&mut self, element: T) {
        self.head = Some(Box::new(Node::new(element, self.head.take())));
    }

    pub fn pop(&mut self) -> Option<T> {
        if let Some(mut head) = self.head.take() {
            self.head = head.next.take();
            Some(head.data)
        } else {
            None
        }
    }

    pub fn peek(&self) -> Option<&T> {
        if let Some(head) = &self.head {
            Some(&head.data)
        } else {
            None
        }
    }

    fn iter(&self) -> LinkedListIterator<T> {
        LinkedListIterator { node: &self.head }
    }
}

impl<T: Clone> SimpleLinkedList<T> {
    pub fn rev(&self) -> SimpleLinkedList<T> {
        let mut list = SimpleLinkedList::new();

        for i in self.iter() {
            list.push(i.data.clone());
        }

        list
    }
}

impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> {
    fn from(item: &[T]) -> Self {
        let mut list = SimpleLinkedList::new();

        for i in item {
            list.push(i.clone());
        }

        list
    }
}

impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
    fn into(self) -> Vec<T> {
        let mut vec = Vec::new();
        let mut node = self.head;

        while let Some(mut n) = node {
            node = n.next.take();
            vec.push(n.data);
        }

        vec.reverse();
        vec
    }
}
<commit_msg>Improve solution for Simple Linked List<commit_after>use std::iter::FromIterator;

struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    fn new(data: T, next: Option<Box<Node<T>>>) -> Self {
        Node { data, next }
    }
}

pub struct LinkedListIter<'a, T: 'a> {
    node: &'a Option<Box<Node<T>>>,
}

impl<'a, T> Iterator for LinkedListIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        if let Some(node) = self.node {
            self.node = &node.next;
            Some(&node.data)
        } else {
            None
        }
    }
}

pub struct LinkedListIntoIter<T> {
    node: Option<Box<Node<T>>>,
}

impl<T> Iterator for LinkedListIntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if let Some(mut node) = self.node.take() {
            self.node = node.next.take();
            Some(node.data)
        } else {
            None
        }
    }
}

pub struct SimpleLinkedList<T> {
    head: Option<Box<Node<T>>>,
}

impl<T> SimpleLinkedList<T> {
    pub fn new() -> Self {
        SimpleLinkedList { head: None }
    }

    pub fn len(&self) -> usize {
        self.iter().count()
    }

    pub fn push(&mut self, element: T) {
        self.head = Some(Box::new(Node::new(element, self.head.take())));
    }

    pub fn pop(&mut self) -> Option<T> {
        if let Some(mut head) = self.head.take() {
            self.head = head.next.take();
            Some(head.data)
        } else {
            None
        }
    }

    pub fn peek(&self) -> Option<&T> {
        self.iter().next()
    }

    fn iter(&self) -> LinkedListIter<T> {
        LinkedListIter { node: &self.head }
    }
}

impl<T> FromIterator<T> for SimpleLinkedList<T> {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        let mut list = SimpleLinkedList::new();

        for i in iter {
            list.push(i);
        }

        list
    }
}

impl<T> IntoIterator for SimpleLinkedList<T> {
    type Item = T;
    type IntoIter = LinkedListIntoIter<T>;

    fn into_iter(self) -> LinkedListIntoIter<T> {
        LinkedListIntoIter { node: self.head }
    }
}

impl<T: Clone> SimpleLinkedList<T> {
    pub fn rev(&self) -> SimpleLinkedList<T> {
        self.iter().cloned().collect()
    }
}

impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> {
    fn from(item: &[T]) -> Self {
        item.iter().cloned().collect()
    }
}

impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
    fn into(self) -> Vec<T> {
        let mut vec = self.into_iter().collect::<Vec<_>>();

        vec.reverse();
        vec
    }
}
<|endoftext|>


<commit_before><commit_msg>add methods to_le/be and to_le/be/ne_bytes for f16<commit_after><|endoftext|>


<commit_before>use client::Client;
use error::{Error, ErrorCode};
use params::{List, Metadata, RangeQuery, Timestamp};
use resources::{Address, Currency, CustomerSource, Refund, Source};
use serde_qs as qs;

#[derive(Debug, Deserialize)]
pub struct ChargeOutcome {
    #[serde(rename = "type")]
    pub outcome_type: String, // (authorized, manual_review, issuer_declined, blocked, invalid)
    pub network_status: String, // (approved_by_network, declined_by_network, not_sent_to_network, reversed_after_approval)
    #[serde(default)]
    pub reason: Option<String>,
    #[serde(default)]
    pub risk_level: Option<String>, // (normal, elevated, highest, not_assessed, unknown)
    #[serde(default)]
    pub seller_message: Option<String>,
    #[serde(default)]
    pub rule: Option<String>,
}

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct FraudDetails {
    pub user_report: Option<String>,
    #[serde(skip_serializing)]
    pub stripe_report: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ShippingDetails {
    pub name: String,
    pub address: Address,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub carrier: Option<String>, // eg. Fedex, UPS, USPS
    #[serde(skip_serializing_if = "Option::is_none")]
    pub phone: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tracking_number: Option<String>,
}

/// The set of parameters that can be used when capturing a charge.
///
/// For more details see https://stripe.com/docs/api#charge_capture.
#[derive(Default, Serialize)]
pub struct CaptureParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub receipt_email: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
}

#[derive(Serialize)]
pub struct DestinationParams<'a> {
    pub account: &'a str,
    pub amount: u64,
}

/// The set of parameters that can be used when creating or updating a charge.
///
/// For more details see https://stripe.com/docs/api#create_charge and https://stripe.com/docs/api#update_charge.
#[derive(Default, Serialize)]
pub struct ChargeParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub capture: Option<bool>, // NOTE: if None, Stripe assumes true
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub destination: Option<DestinationParams<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub fraud_details: Option<FraudDetails>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transfer_group: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub on_behalf_of: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<Metadata>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub receipt_email: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub shipping: Option<ShippingDetails>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source: Option<CustomerSource<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
}

#[derive(Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SourceType {
    All,
    AlipayAccount,
    BankAccount,
    BitcoinReceiver,
    Card,
}

#[derive(Serialize)]
pub struct SourceFilter {
    pub object: SourceType,
}

impl SourceFilter {
    pub fn all() -> SourceFilter {
        SourceFilter { object: SourceType::All }
    }
    pub fn alipay() -> SourceFilter {
        SourceFilter { object: SourceType::AlipayAccount }
    }
    pub fn bank() -> SourceFilter {
        SourceFilter { object: SourceType::BankAccount }
    }
    pub fn bitcoin() -> SourceFilter {
        SourceFilter { object: SourceType::BitcoinReceiver }
    }
    pub fn card() -> SourceFilter {
        SourceFilter { object: SourceType::Card }
    }
}

/// The set of parameters that can be used when listing charges.
///
/// For more details see https://stripe.com/docs/api#list_charges
#[derive(Default, Serialize)]
pub struct ChargeListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created: Option<RangeQuery<Timestamp>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ending_before: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source: Option<SourceFilter>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub starting_after: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transfer_group: Option<&'a str>,
}

/// The resource representing a Stripe charge.
///
/// For more details see https://stripe.com/docs/api#charges.
#[derive(Debug, Deserialize)]
pub struct Charge {
    pub id: String,
    pub amount: u64,
    pub amount_refunded: u64,
    pub application: Option<String>,
    pub application_fee: Option<String>,
    pub balance_transaction: String,
    pub captured: bool,
    pub created: Timestamp,
    pub currency: Currency,
    pub customer: Option<String>,
    pub description: Option<String>,
    pub destination: Option<String>,
    pub dispute: Option<String>,
    pub failure_code: Option<ErrorCode>,
    pub failure_message: Option<String>,
    pub fraud_details: FraudDetails,
    pub invoice: Option<String>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub on_behalf_of: Option<String>,
    pub order: Option<String>,
    pub outcome: Option<ChargeOutcome>,
    pub paid: bool,
    pub receipt_email: Option<String>,
    pub receipt_number: Option<String>,
    pub refunded: bool,
    pub refunds: List<Refund>,
    pub shipping: Option<ShippingDetails>,
    pub source: Source,
    pub source_transfer: Option<String>,
    pub statement_descriptor: Option<String>,
    pub status: String, // (succeeded, pending, failed)
    pub transfer_group: Option<String>,
}

impl Charge {
    /// Creates a new charge.
    ///
    /// For more details see https://stripe.com/docs/api#create_charge.
    pub fn create(client: &Client, params: ChargeParams) -> Result<Charge, Error> {
        client.post("/charges", params)
    }

    /// Retrieves the details of a charge.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_charge.
    pub fn retrieve(client: &Client, charge_id: &str) -> Result<Charge, Error> {
        client.get(&format!("/charges/{}", charge_id))
    }

    /// Updates a charge's properties.
    ///
    /// For more details see https://stripe.com/docs/api#update_charge.
    pub fn update(client: &Client, charge_id: &str, params: ChargeParams) -> Result<Charge, Error> {
        client.post(&format!("/charges/{}", charge_id), params)
    }

    /// Capture captures a previously created charge with capture set to false.
    ///
    /// For more details see https://stripe.com/docs/api#charge_capture.
    pub fn capture(client: &Client, charge_id: &str, params: CaptureParams) -> Result<Charge, Error> {
        client.post(&format!("/charges/{}/capture", charge_id), params)
    }

    /// List all charges.
    ///
    /// For more details see https://stripe.com/docs/api#list_charges.
    pub fn list(client: &Client, params: ChargeListParams) -> Result<Vec<Charge>, Error> {
        client.get(&format!("/charges?{}", qs::to_string(&params)?))
    }
}
<commit_msg>Add customer param to charge param<commit_after>use client::Client;
use error::{Error, ErrorCode};
use params::{List, Metadata, RangeQuery, Timestamp};
use resources::{Address, Currency, CustomerSource, Refund, Source};
use serde_qs as qs;

#[derive(Debug, Deserialize)]
pub struct ChargeOutcome {
    #[serde(rename = "type")]
    pub outcome_type: String, // (authorized, manual_review, issuer_declined, blocked, invalid)
    pub network_status: String, // (approved_by_network, declined_by_network, not_sent_to_network, reversed_after_approval)
    #[serde(default)]
    pub reason: Option<String>,
    #[serde(default)]
    pub risk_level: Option<String>, // (normal, elevated, highest, not_assessed, unknown)
    #[serde(default)]
    pub seller_message: Option<String>,
    #[serde(default)]
    pub rule: Option<String>,
}

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct FraudDetails {
    pub user_report: Option<String>,
    #[serde(skip_serializing)]
    pub stripe_report: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ShippingDetails {
    pub name: String,
    pub address: Address,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub carrier: Option<String>, // eg. Fedex, UPS, USPS
    #[serde(skip_serializing_if = "Option::is_none")]
    pub phone: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tracking_number: Option<String>,
}

/// The set of parameters that can be used when capturing a charge.
///
/// For more details see https://stripe.com/docs/api#charge_capture.
#[derive(Default, Serialize)]
pub struct CaptureParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub receipt_email: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
}

#[derive(Serialize)]
pub struct DestinationParams<'a> {
    pub account: &'a str,
    pub amount: u64,
}

/// The set of parameters that can be used when creating or updating a charge.
///
/// For more details see https://stripe.com/docs/api#create_charge and https://stripe.com/docs/api#update_charge.
#[derive(Default, Serialize)]
pub struct ChargeParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub capture: Option<bool>, // NOTE: if None, Stripe assumes true
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub destination: Option<DestinationParams<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub fraud_details: Option<FraudDetails>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transfer_group: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub on_behalf_of: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<Metadata>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub receipt_email: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub shipping: Option<ShippingDetails>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source: Option<CustomerSource<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
}

#[derive(Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SourceType {
    All,
    AlipayAccount,
    BankAccount,
    BitcoinReceiver,
    Card,
}

#[derive(Serialize)]
pub struct SourceFilter {
    pub object: SourceType,
}

impl SourceFilter {
    pub fn all() -> SourceFilter {
        SourceFilter { object: SourceType::All }
    }
    pub fn alipay() -> SourceFilter {
        SourceFilter { object: SourceType::AlipayAccount }
    }
    pub fn bank() -> SourceFilter {
        SourceFilter { object: SourceType::BankAccount }
    }
    pub fn bitcoin() -> SourceFilter {
        SourceFilter { object: SourceType::BitcoinReceiver }
    }
    pub fn card() -> SourceFilter {
        SourceFilter { object: SourceType::Card }
    }
}

/// The set of parameters that can be used when listing charges.
///
/// For more details see https://stripe.com/docs/api#list_charges
#[derive(Default, Serialize)]
pub struct ChargeListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created: Option<RangeQuery<Timestamp>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ending_before: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source: Option<SourceFilter>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub starting_after: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transfer_group: Option<&'a str>,
}

/// The resource representing a Stripe charge.
///
/// For more details see https://stripe.com/docs/api#charges.
#[derive(Debug, Deserialize)]
pub struct Charge {
    pub id: String,
    pub amount: u64,
    pub amount_refunded: u64,
    pub application: Option<String>,
    pub application_fee: Option<String>,
    pub balance_transaction: String,
    pub captured: bool,
    pub created: Timestamp,
    pub currency: Currency,
    pub customer: Option<String>,
    pub description: Option<String>,
    pub destination: Option<String>,
    pub dispute: Option<String>,
    pub failure_code: Option<ErrorCode>,
    pub failure_message: Option<String>,
    pub fraud_details: FraudDetails,
    pub invoice: Option<String>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub on_behalf_of: Option<String>,
    pub order: Option<String>,
    pub outcome: Option<ChargeOutcome>,
    pub paid: bool,
    pub receipt_email: Option<String>,
    pub receipt_number: Option<String>,
    pub refunded: bool,
    pub refunds: List<Refund>,
    pub shipping: Option<ShippingDetails>,
    pub source: Source,
    pub source_transfer: Option<String>,
    pub statement_descriptor: Option<String>,
    pub status: String, // (succeeded, pending, failed)
    pub transfer_group: Option<String>,
}

impl Charge {
    /// Creates a new charge.
    ///
    /// For more details see https://stripe.com/docs/api#create_charge.
    pub fn create(client: &Client, params: ChargeParams) -> Result<Charge, Error> {
        client.post("/charges", params)
    }

    /// Retrieves the details of a charge.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_charge.
    pub fn retrieve(client: &Client, charge_id: &str) -> Result<Charge, Error> {
        client.get(&format!("/charges/{}", charge_id))
    }

    /// Updates a charge's properties.
    ///
    /// For more details see https://stripe.com/docs/api#update_charge.
    pub fn update(client: &Client, charge_id: &str, params: ChargeParams) -> Result<Charge, Error> {
        client.post(&format!("/charges/{}", charge_id), params)
    }

    /// Capture captures a previously created charge with capture set to false.
    ///
    /// For more details see https://stripe.com/docs/api#charge_capture.
    pub fn capture(client: &Client, charge_id: &str, params: CaptureParams) -> Result<Charge, Error> {
        client.post(&format!("/charges/{}/capture", charge_id), params)
    }

    /// List all charges.
    ///
    /// For more details see https://stripe.com/docs/api#list_charges.
    pub fn list(client: &Client, params: ChargeListParams) -> Result<Vec<Charge>, Error> {
        client.get(&format!("/charges?{}", qs::to_string(&params)?))
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::io;
use std::net::SocketAddr;

use futures::{Future, Stream};
use hyper::server::Http;
use core::net::TcpListener;
use core::reactor::Core;

pub use hyper::header as headers;
pub use hyper::{StatusCode, Error, Method, Body};
pub use hyper::server::{Request, Response};
pub use core::reactor::Handle;
pub use tokio::{Service, NewService};

pub fn serve<T, Fut, F>(routes: F) -> io::Result<()>
where
    T: NewService<Request = Request, Response = Response, Error = Error> + 'static,
    T::Instance: 'static,
    Fut: Future<Item = T, Error = io::Error>,
    F: FnOnce(&Handle) -> (SocketAddr, Fut),
{
    // TODO shutdown
    let mut core = Core::new()?;
    let protocol = Http::new();
    let handle = core.handle();
    let (mut addr, routes) = routes(&handle);
    set_port(&mut addr);
    let listener = TcpListener::bind(&addr, &handle)?;
    let srv = routes.and_then(|routes| {
        let handle = &handle;
        let protocol = &protocol;
        listener.incoming().for_each(move |(socket, remote_addr)| {
            routes.new_service().map(move |service| {
                protocol.bind_connection(handle, socket, remote_addr, service);
            })
        })
    });
    core.run(srv)
}

fn set_port(addr: &mut SocketAddr) {
    if let Ok(port) = env::var("PORT") {
        let port = port.parse().expect("PORT variable not a valid port number.");
        addr.set_port(port);
    }
}

pub type BoxFuture = Box<Future<Item = Response, Error = Error>>;
<commit_msg>Print address the server is running on (#14)<commit_after>use std::env;
use std::io;
use std::net::SocketAddr;

use futures::{Future, Stream};
use hyper::server::Http;
use core::net::TcpListener;
use core::reactor::Core;

pub use hyper::header as headers;
pub use hyper::{StatusCode, Error, Method, Body};
pub use hyper::server::{Request, Response};
pub use core::reactor::Handle;
pub use tokio::{Service, NewService};

pub fn serve<T, Fut, F>(routes: F) -> io::Result<()>
where
    T: NewService<Request = Request, Response = Response, Error = Error> + 'static,
    T::Instance: 'static,
    Fut: Future<Item = T, Error = io::Error>,
    F: FnOnce(&Handle) -> (SocketAddr, Fut),
{
    // TODO shutdown
    let mut core = Core::new()?;
    let protocol = Http::new();
    let handle = core.handle();
    let (mut addr, routes) = routes(&handle);
    set_port(&mut addr);
    let listener = TcpListener::bind(&addr, &handle)?;
    let srv = routes.and_then(|routes| {
        let handle = &handle;
        let protocol = &protocol;
        listener.incoming().for_each(move |(socket, remote_addr)| {
            routes.new_service().map(move |service| {
                protocol.bind_connection(handle, socket, remote_addr, service);
            })
        })
    });
    println!("Running on {}", addr);
    core.run(srv)
}

fn set_port(addr: &mut SocketAddr) {
    if let Ok(port) = env::var("PORT") {
        let port = port.parse().expect("PORT variable not a valid port number.");
        addr.set_port(port);
    }
}

pub type BoxFuture = Box<Future<Item = Response, Error = Error>>;
<|endoftext|>


<commit_before>use super::*;

use dpi::LogicalPosition;
use event::{DeviceId as RootDI, ElementState, Event, KeyboardInput, StartCause, WindowEvent};
use event_loop::{ControlFlow, EventLoopWindowTarget as RootELW, EventLoopClosed};
use window::{WindowId as RootWI};
use stdweb::{
    traits::*,
    web::{
        document,
        event::*,
        html_element::CanvasElement,
    },
};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::marker::PhantomData;
use std::rc::Rc;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(i32);

impl DeviceId {
    pub unsafe fn dummy() -> Self {
        DeviceId(0)
    }
}

pub struct EventLoop<T: 'static> {
    elw: RootELW<T>,
}

pub struct EventLoopWindowTarget<T: 'static> {
    pub(crate) runner: EventLoopRunnerShared<T>,
}

impl<T> EventLoopWindowTarget<T> {
    fn new() -> Self {
        EventLoopWindowTarget {
            runner: Rc::new(ELRShared {
                runner: RefCell::new(None),
                events: RefCell::new(VecDeque::new())
            })
        }
    }
}

#[derive(Clone)]
pub struct EventLoopProxy<T> {
    runner: EventLoopRunnerShared<T>
}

impl<T> EventLoopProxy<T> {
    pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> {
        self.runner.send_event(Event::UserEvent(event));
        Ok(())
    }
}

pub type EventLoopRunnerShared<T> = Rc<ELRShared<T>>;

pub struct ELRShared<T> {
    runner: RefCell<Option<EventLoopRunner<T>>>,
    events: RefCell<VecDeque<Event<T>>>, // TODO: this may not be necessary?
}

struct EventLoopRunner<T> {
    control: ControlFlow,
    handling: bool,
    event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
}

impl<T> EventLoop<T> {
    pub fn new() -> Self {
        EventLoop {
            elw: RootELW {
                p: EventLoopWindowTarget::new(),
                _marker: PhantomData
            },
        }
    }

    pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
        VecDeque::new().into_iter()
    }

    pub fn get_primary_monitor(&self) -> MonitorHandle {
        MonitorHandle
    }

    pub fn run<F>(self, mut event_handler: F) -> !
        where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow) {
        let runner = self.elw.p.runner;

        let relw = RootELW {
            p: EventLoopWindowTarget::new(),
            _marker: PhantomData
        };
        runner.set_listener(Box::new(move |evt, ctrl| event_handler(evt, &relw, ctrl)));

        let document = &document();
        add_event(&runner, document, |elrs, _: BlurEvent| {
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::Focused(false)
            });
        });
        add_event(&runner, document, |elrs, _: FocusEvent| {
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::Focused(true)
            });

        });
        add_event(&runner, document, |elrs, event: KeyDownEvent| {
            let key = event.key();
            let mut characters = key.chars();
            let first = characters.next();
            let second = characters.next();
            if let (Some(key), None) = (first, second) {
                elrs.send_event(Event::WindowEvent {
                    window_id: RootWI(WindowId),
                    event: WindowEvent::ReceivedCharacter(key)
                });
            }
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::KeyboardInput {
                    device_id: RootDI(unsafe { DeviceId::dummy() }),
                    input: KeyboardInput {
                        scancode: scancode(&event),
                        state: ElementState::Pressed,
                        virtual_keycode: button_mapping(&event),
                        modifiers: keyboard_modifiers_state(&event),
                    }
                }
            });
        });
        add_event(&runner, document, |elrs, event: KeyUpEvent| {
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::KeyboardInput {
                    device_id: RootDI(unsafe { DeviceId::dummy() }),
                    input: KeyboardInput {
                        scancode: scancode(&event),
                        state: ElementState::Released,
                        virtual_keycode: button_mapping(&event),
                        modifiers: keyboard_modifiers_state(&event),
                    }
                }
            });
        });
        stdweb::event_loop(); // TODO: this is only necessary for stdweb emscripten, should it be here?

        // Throw an exception to break out of Rust exceution and use unreachable to tell the
        // compiler this function won't return, giving it a return type of '!'
        js! {
            throw "Using exceptions for control flow, don't mind me";
        }
        unreachable!();
    }

    pub fn create_proxy(&self) -> EventLoopProxy<T> {
        EventLoopProxy {
            runner: self.elw.p.runner.clone()
        }
    }

    pub fn window_target(&self) -> &RootELW<T> {
        &self.elw
    }
}

pub fn register<T: 'static>(elrs: &EventLoopRunnerShared<T>, canvas: &CanvasElement) {
    add_event(elrs, canvas, |elrs, event: PointerOutEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::CursorLeft {
                device_id: RootDI(DeviceId(event.pointer_id()))
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerOverEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::CursorEntered {
                device_id: RootDI(DeviceId(event.pointer_id()))
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerMoveEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::CursorMoved {
                device_id: RootDI(DeviceId(event.pointer_id())),
                position: LogicalPosition {
                    x: event.offset_x(),
                    y: event.offset_y()
                },
                modifiers: mouse_modifiers_state(&event)
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerUpEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::MouseInput {
                device_id: RootDI(DeviceId(event.pointer_id())),
                state: ElementState::Pressed,
                button: mouse_button(&event),
                modifiers: mouse_modifiers_state(&event)
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerDownEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::MouseInput {
                device_id: RootDI(DeviceId(event.pointer_id())),
                state: ElementState::Released,
                button: mouse_button(&event),
                modifiers: mouse_modifiers_state(&event)
            }
        });
    });
}

fn add_event<T: 'static, E, F>(elrs: &EventLoopRunnerShared<T>, target: &impl IEventTarget, mut handler: F)
        where E: ConcreteEvent, F: FnMut(&EventLoopRunnerShared<T>, E) + 'static {
    let elrs = elrs.clone();

    target.add_event_listener(move |event: E| {
        // Don't capture the event if the events loop has been destroyed
        match &*elrs.runner.borrow() {
            Some(ref runner) if runner.control == ControlFlow::Exit => return,
            _ => ()
        }

        event.prevent_default();
        event.stop_propagation();
        event.cancel_bubble();

        handler(&elrs, event);
    });
}

impl<T> ELRShared<T> {
    fn set_listener(&self, event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>) {
        *self.runner.borrow_mut() = Some(EventLoopRunner {
            control: ControlFlow::Poll,
            handling: false,
            event_handler
        });
    }

    // TODO: handle event loop closures
    // TODO: handle event buffer
    pub fn send_event(&self, event: Event<T>) {
        let start_cause = StartCause::Poll; // TODO: this is obviously not right
        self.handle_start(start_cause);
        self.handle_event(event);
        self.handle_event(Event::EventsCleared);
    }

    fn handle_start(&self, start: StartCause) {
        let is_handling = if let Some(ref runner) = *self.runner.borrow() {
            runner.handling
        } else {
            false
        };
        if is_handling {
            self.handle_event(Event::NewEvents(start));
        }
    }

    fn handle_event(&self, event: Event<T>) {
        match *self.runner.borrow_mut() {
            Some(ref mut runner) if !runner.handling => {
                runner.handling = true;
                let closed = runner.control == ControlFlow::Exit;
                // TODO: bracket this in control flow events?
                (runner.event_handler)(event, &mut runner.control);
                if closed {
                    runner.control = ControlFlow::Exit;
                }
                runner.handling = false;
            }
            _ => self.events.borrow_mut().push_back(event)
        }
        if self.runner.borrow().is_some() {
            if let Some(event) = self.events.borrow_mut().pop_front() {
                self.handle_event(event);
            }
        }
    }

}

<commit_msg>Clean up and document the core of stdweb event handling<commit_after>use super::*;

use dpi::LogicalPosition;
use event::{DeviceId as RootDI, ElementState, Event, KeyboardInput, StartCause, WindowEvent};
use event_loop::{ControlFlow, EventLoopWindowTarget as RootELW, EventLoopClosed};
use window::{WindowId as RootWI};
use stdweb::{
    traits::*,
    web::{
        document,
        event::*,
        html_element::CanvasElement,
    },
};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::marker::PhantomData;
use std::rc::Rc;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(i32);

impl DeviceId {
    pub unsafe fn dummy() -> Self {
        DeviceId(0)
    }
}

pub struct EventLoop<T: 'static> {
    elw: RootELW<T>,
}

pub struct EventLoopWindowTarget<T: 'static> {
    pub(crate) runner: EventLoopRunnerShared<T>,
}

impl<T> EventLoopWindowTarget<T> {
    fn new() -> Self {
        EventLoopWindowTarget {
            runner: Rc::new(ELRShared {
                runner: RefCell::new(None),
                events: RefCell::new(VecDeque::new())
            })
        }
    }
}

#[derive(Clone)]
pub struct EventLoopProxy<T> {
    runner: EventLoopRunnerShared<T>
}

impl<T> EventLoopProxy<T> {
    pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> {
        self.runner.send_event(Event::UserEvent(event));
        Ok(())
    }
}

pub type EventLoopRunnerShared<T> = Rc<ELRShared<T>>;

pub struct ELRShared<T> {
    runner: RefCell<Option<EventLoopRunner<T>>>,
    events: RefCell<VecDeque<Event<T>>>, // TODO: this may not be necessary?
}

struct EventLoopRunner<T> {
    control: ControlFlow,
    is_busy: bool,
    event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
}

impl<T> EventLoop<T> {
    pub fn new() -> Self {
        EventLoop {
            elw: RootELW {
                p: EventLoopWindowTarget::new(),
                _marker: PhantomData
            },
        }
    }

    pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
        VecDeque::new().into_iter()
    }

    pub fn get_primary_monitor(&self) -> MonitorHandle {
        MonitorHandle
    }

    pub fn run<F>(self, mut event_handler: F) -> !
        where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow) {
        let runner = self.elw.p.runner;

        let relw = RootELW {
            p: EventLoopWindowTarget::new(),
            _marker: PhantomData
        };
        runner.set_listener(Box::new(move |evt, ctrl| event_handler(evt, &relw, ctrl)));

        let document = &document();
        add_event(&runner, document, |elrs, _: BlurEvent| {
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::Focused(false)
            });
        });
        add_event(&runner, document, |elrs, _: FocusEvent| {
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::Focused(true)
            });

        });
        add_event(&runner, document, |elrs, event: KeyDownEvent| {
            let key = event.key();
            let mut characters = key.chars();
            let first = characters.next();
            let second = characters.next();
            if let (Some(key), None) = (first, second) {
                elrs.send_event(Event::WindowEvent {
                    window_id: RootWI(WindowId),
                    event: WindowEvent::ReceivedCharacter(key)
                });
            }
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::KeyboardInput {
                    device_id: RootDI(unsafe { DeviceId::dummy() }),
                    input: KeyboardInput {
                        scancode: scancode(&event),
                        state: ElementState::Pressed,
                        virtual_keycode: button_mapping(&event),
                        modifiers: keyboard_modifiers_state(&event),
                    }
                }
            });
        });
        add_event(&runner, document, |elrs, event: KeyUpEvent| {
            elrs.send_event(Event::WindowEvent {
                window_id: RootWI(WindowId),
                event: WindowEvent::KeyboardInput {
                    device_id: RootDI(unsafe { DeviceId::dummy() }),
                    input: KeyboardInput {
                        scancode: scancode(&event),
                        state: ElementState::Released,
                        virtual_keycode: button_mapping(&event),
                        modifiers: keyboard_modifiers_state(&event),
                    }
                }
            });
        });
        stdweb::event_loop(); // TODO: this is only necessary for stdweb emscripten, should it be here?

        // Throw an exception to break out of Rust exceution and use unreachable to tell the
        // compiler this function won't return, giving it a return type of '!'
        js! {
            throw "Using exceptions for control flow, don't mind me";
        }
        unreachable!();
    }

    pub fn create_proxy(&self) -> EventLoopProxy<T> {
        EventLoopProxy {
            runner: self.elw.p.runner.clone()
        }
    }

    pub fn window_target(&self) -> &RootELW<T> {
        &self.elw
    }
}

pub fn register<T: 'static>(elrs: &EventLoopRunnerShared<T>, canvas: &CanvasElement) {
    add_event(elrs, canvas, |elrs, event: PointerOutEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::CursorLeft {
                device_id: RootDI(DeviceId(event.pointer_id()))
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerOverEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::CursorEntered {
                device_id: RootDI(DeviceId(event.pointer_id()))
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerMoveEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::CursorMoved {
                device_id: RootDI(DeviceId(event.pointer_id())),
                position: LogicalPosition {
                    x: event.offset_x(),
                    y: event.offset_y()
                },
                modifiers: mouse_modifiers_state(&event)
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerUpEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::MouseInput {
                device_id: RootDI(DeviceId(event.pointer_id())),
                state: ElementState::Pressed,
                button: mouse_button(&event),
                modifiers: mouse_modifiers_state(&event)
            }
        });
    });
    add_event(elrs, canvas, |elrs, event: PointerDownEvent| {
        elrs.send_event(Event::WindowEvent {
            window_id: RootWI(WindowId),
            event: WindowEvent::MouseInput {
                device_id: RootDI(DeviceId(event.pointer_id())),
                state: ElementState::Released,
                button: mouse_button(&event),
                modifiers: mouse_modifiers_state(&event)
            }
        });
    });
}

fn add_event<T: 'static, E, F>(elrs: &EventLoopRunnerShared<T>, target: &impl IEventTarget, mut handler: F)
        where E: ConcreteEvent, F: FnMut(&EventLoopRunnerShared<T>, E) + 'static {
    let elrs = elrs.clone();

    target.add_event_listener(move |event: E| {
        // Don't capture the event if the events loop has been destroyed
        match &*elrs.runner.borrow() {
            Some(ref runner) if runner.control == ControlFlow::Exit => return,
            _ => ()
        }

        event.prevent_default();
        event.stop_propagation();
        event.cancel_bubble();

        handler(&elrs, event);
    });
}

impl<T> ELRShared<T> {
    // Set the event callback to use for the event loop runner
    // This the event callback is a fairly thin layer over the user-provided callback that closes
    // over a RootEventLoopWindowTarget reference
    fn set_listener(&self, event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>) {
        *self.runner.borrow_mut() = Some(EventLoopRunner {
            control: ControlFlow::Poll,
            is_busy: false,
            event_handler
        });
    }

    // Add an event to the event loop runner
    //
    // It will determine if the event should be immediately sent to the user or buffered for later
    pub fn send_event(&self, event: Event<T>) {
        // If the event loop is closed, it should discard any new events
        if self.closed() {
            return;
        }

        let start_cause = StartCause::Poll; // TODO: determine start cause

        // Determine if event handling is in process, and then release the borrow on the runner
        let is_busy = if let Some(ref runner) = *self.runner.borrow() {
            runner.is_busy
        } else {
            true // If there is no event runner yet, then there's no point in processing events
        };

        if is_busy {
            self.events.borrow_mut().push_back(event);
        } else {
            // Handle starting a new batch of events
            //
            // The user is informed via Event::NewEvents that there is a batch of events to process
            // However, there is only one of these per batch of events
            self.handle_event(Event::NewEvents(start_cause));
            self.handle_event(event);
            self.handle_event(Event::EventsCleared);

            // If the event loop is closed, it has been closed this iteration and now the closing
            // event should be emitted
            if self.closed() {
                self.handle_event(Event::LoopDestroyed);
            }
        }
    }

    // Check if the event loop is currntly closed
    fn closed(&self) -> bool {
        match *self.runner.borrow() {
            Some(ref runner) => runner.control == ControlFlow::Exit,
            None => false, // If the event loop is None, it has not been intialised yet, so it cannot be closed
        }
    }

    // handle_event takes in events and either queues them or applies a callback
    //
    // It should only ever be called from send_event
    fn handle_event(&self, event: Event<T>) {
        let closed = self.closed();

        match *self.runner.borrow_mut() {
            Some(ref mut runner) => {
                // An event is being processed, so the runner should be marked busy
                runner.is_busy = true;

                // TODO: bracket this in control flow events?
                (runner.event_handler)(event, &mut runner.control);

                // Maintain closed state, even if the callback changes it
                if closed {
                    runner.control = ControlFlow::Exit;
                }

                // An event is no longer being processed
                runner.is_busy = false;
            }
            // If an event is being handled without a runner somehow, add it to the event queue so
            // it will eventually be processed
            _ => self.events.borrow_mut().push_back(event)
        }

        // Don't take events out of the queue if the loop is closed or the runner doesn't exist
        // If the runner doesn't exist and this method recurses, it will recurse infinitely
        if !closed && self.runner.borrow().is_some() {
            // Take an event out of the queue and handle it
            if let Some(event) = self.events.borrow_mut().pop_front() {
                self.handle_event(event);
            }
        }
    }

}

<|endoftext|>