<commit_before>//! Module with the self-pipe pattern.
//!
//! One of the common patterns around signals is to have a pipe with both ends in the same program.
//! Whenever there's a signal, the signal handler writes one byte of garbage data to the write end,
//! unless the pipe's already full. The application then can handle the read end.
//!
//! This has two advantages. First, the real signal action moves outside of the signal handler
//! where there are a lot less restrictions. Second, it fits nicely in all kinds of asynchronous
//! loops and has less chance of race conditions.
//!
//! This module offers premade functions for the write end (and doesn't insist that it must be a
//! pipe ‒ anything that can be written to is fine ‒ sockets too, therefore `UnixStream::pair` is a
//! good candidate).
//!
//! If you want to integrate with some asynchronous library, plugging streams from `mio-uds` or
//! `tokio-uds` libraries should work.
//!
//! If it looks too low-level for your needs, the [`iterator`](../iterator/) module contains some
//! higher-lever interface that also uses a self-pipe pattern under the hood.
//!
//! # Correct order of handling
//!
//! A care needs to be taken to avoid race conditions, especially when handling the same signal in
//! a loop. Specifically, another signal might come when the action for the previous signal is
//! being taken. The correct order is first to clear the content of the pipe (read some/all data
//! from it) and then take the action. This way a spurious wakeup can happen (the pipe could wake
//! up even when no signal came after the signal was taken, because ‒ it arrived between cleaning
//! the pipe and taking the action). Note that some OS primitives (eg. `select`) suffer from
//! spurious wakeups themselves (they can claim a FD is readable when it is not true) and blocking
//! `read` might return prematurely (with eg. `EINTR`).
//!
//! The reverse order of first taking the action and then clearing the pipe might lose signals,
//! which is usually worse.
//!
//! This is not a problem with blocking on reading from the pipe (because both the blocking and
//! cleaning is the same action), but in case of asynchronous handling it matters.
//!
//! If you want to combine setting some flags with a self-pipe pattern, the flag needs to be set
//! first, then the pipe written. On the read end, first the pipe needs to be cleaned, then the
//! flag and then the action taken. This is what the [`Signals`](../iterator/struct.Signals.html)
//! structure does internally.
//!
//! # Write collating
//!
//! While unlikely if handled correctly, it is possible the write end is full when a signal comes.
//! In such case the signal handler simply does nothing. If the write end is full, the read end is
//! readable and therefore will wake up. On the other hand, blocking in the signal handler would
//! definitely be a bad idea.
//!
//! However, this also means the number of bytes read from the end might be lower than the number
//! of signals that arrived. This should not generally be a problem, since the OS already collates
//! signals of the same kind together.
//!
//! # Examples
//!
//! This example waits for at last one `SIGUSR1` signal to come before continuing (and
//! terminating). It sends the signal to itself, so it correctly terminates.
//!
//! ```rust
//! extern crate libc;
//! extern crate signal_hook;
//!
//! use std::io::{Error, Read};
//! use std::os::unix::net::UnixStream;
//!
//! fn main() -> Result<(), Error> {
//!     let (mut read, write) = UnixStream::pair()?;
//!     signal_hook::pipe::register(signal_hook::SIGUSR1, write)?;
//!     // This will write into the pipe write end through the signal handler
//!     unsafe { libc::raise(signal_hook::SIGUSR1) };
//!     let mut buff = [0];
//!     read.read_exact(&mut buff)?;
//!     println!("Happily terminating");
//!     Ok(())
//! }

use std::io::{Error, ErrorKind};
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};

use libc::{self, c_int};

use crate::SigId;

#[derive(Copy, Clone)]
pub(crate) enum WakeMethod {
    Send,
    Write,
}

struct WakeFd {
    fd: RawFd,
    method: WakeMethod,
}

impl WakeFd {
    /// Sets close on exec and nonblock on the inner file descriptor.
    fn set_flags(&self) -> Result<(), Error> {
        unsafe {
            let flags = libc::fcntl(self.as_raw_fd(), libc::F_GETFL, 0);
            if flags == -1 {
                return Err(Error::last_os_error());
            }
            let flags = flags | libc::O_NONBLOCK | libc::O_CLOEXEC;
            if libc::fcntl(self.as_raw_fd(), libc::F_SETFL, flags) == -1 {
                return Err(Error::last_os_error());
            }
        }
        Ok(())
    }
    fn wake(&self) {
        wake(self.fd, self.method);
    }
}

impl AsRawFd for WakeFd {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Drop for WakeFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

pub(crate) fn wake(pipe: RawFd, method: WakeMethod) {
    unsafe {
        // This writes some data into the pipe.
        //
        // There are two tricks:
        // * First, the crazy cast. The first part turns reference into pointer. The second part
        //   turns pointer to u8 into a pointer to void, which is what write requires.
        // * Second, we ignore errors, on purpose. We don't have any means to handling them. The
        //   two conceivable errors are EBADFD, if someone passes a non-existent file descriptor or
        //   if it is closed. The second is EAGAIN, in which case the pipe is full ‒ there were
        //   many signals, but the reader didn't have time to read the data yet. It'll still get
        //   woken up, so not fitting another letter in it is fine.
        let data = b"X" as *const _ as *const _;
        match method {
            WakeMethod::Write => libc::write(pipe, data, 1),
            WakeMethod::Send => libc::send(pipe, data, 1, libc::MSG_DONTWAIT),
        };
    }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// In this case, the pipe is taken as the `RawFd`. It'll be closed on deregistration. Effectively,
/// the function takes ownership of the file descriptor. This includes feeling free to set arbitrary
/// flags on it, including file status flags (that are shared across file descriptors created by
/// `dup`).
///
/// Note that passing the wrong file descriptor won't cause UB, but can still lead to severe bugs ‒
/// like data corruptions in files. Prefer using [`register`] if possible.
///
/// Also, it is perfectly legal for multiple writes to be collated together (if not consumed) and
/// to generate spurious wakeups (but will not generate spurious *bytes* in the pipe).
///
/// # Internal details
///
/// Internally, it *currently* does following. Note that this is *not* part of the stability
/// guarantees and may change if necessary.
///
/// * If the file descriptor can be used with [`send`][libc::send], it'll be used together with
///   [`MSG_DONTWAIT`][libc::MSG_DONTWAIT]. This is tested by sending `0` bytes of data (depending
///   on the socket type, this might wake the read end with an empty message).
/// * If it is not possible, the [`O_NONBLOCK`][libc::O_NONBLOCK] will be set on the file
///   descriptor and [`write`][libc::write] will be used instead.
pub fn register_raw(signal: c_int, pipe: RawFd) -> Result<SigId, Error> {
    let res = unsafe { libc::send(pipe, &[] as *const _, 0, libc::MSG_DONTWAIT) };
    let fd = match (res, Error::last_os_error().kind()) {
        (0, _) | (-1, ErrorKind::WouldBlock) => WakeFd {
            fd: pipe,
            method: WakeMethod::Send,
        },
        _ => {
            let fd = WakeFd {
                fd: pipe,
                method: WakeMethod::Write,
            };
            fd.set_flags()?;
            fd
        }
    };
    let action = move || fd.wake();
    unsafe { crate::register(signal, action) }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// The ownership of pipe is taken and will be closed whenever the created action is unregistered.
///
/// Note that if you want to register the same pipe for multiple signals, there's `try_clone`
/// method on many unix socket primitives.
///
/// See [`register_raw`] for further details.
pub fn register<P>(signal: c_int, pipe: P) -> Result<SigId, Error>
where
    P: IntoRawFd + 'static,
{
    register_raw(signal, pipe.into_raw_fd())
}

#[cfg(test)]
mod tests {
    use std::io::Read;
    use std::os::unix::net::{UnixDatagram, UnixStream};

    use super::*;

    // Note: multiple tests share the SIGUSR1 signal. This is fine, we only need to know the signal
    // arrives. It's OK to arrive multiple times, from multiple tests.
    fn wakeup() {
        unsafe { assert_eq!(0, libc::raise(libc::SIGUSR1)) }
    }

    #[test]
    fn register_with_socket() -> Result<(), Error> {
        let (mut read, write) = UnixStream::pair()?;
        register(libc::SIGUSR1, write)?;
        wakeup();
        let mut buff = [0; 1];
        read.read_exact(&mut buff)?;
        assert_eq!(b"X", &buff);
        Ok(())
    }

    #[test]
    fn register_dgram_socket() -> Result<(), Error> {
        let (read, write) = UnixDatagram::pair()?;
        register(libc::SIGUSR1, write)?;
        wakeup();
        let mut buff = [0; 1];
        // The attempt to detect if it is socket can generate an empty message. Therefore, do a few
        // retries.
        for _ in 0..3 {
            let len = read.recv(&mut buff)?;
            if len == 1 && &buff == b"X" {
                return Ok(());
            }
        }
        panic!("Haven't received the right data");
    }

    #[test]
    fn register_with_pipe() -> Result<(), Error> {
        let mut fds = [0; 2];
        unsafe { assert_eq!(0, libc::pipe(fds.as_mut_ptr())) };
        register_raw(libc::SIGUSR1, fds[1])?;
        wakeup();
        let mut buff = [0; 1];
        unsafe { assert_eq!(1, libc::read(fds[0], buff.as_mut_ptr() as *mut _, 1)) }
        assert_eq!(b"X", &buff);
        Ok(())
    }
}
<commit_msg>Fix documentation link<commit_after>//! Module with the self-pipe pattern.
//!
//! One of the common patterns around signals is to have a pipe with both ends in the same program.
//! Whenever there's a signal, the signal handler writes one byte of garbage data to the write end,
//! unless the pipe's already full. The application then can handle the read end.
//!
//! This has two advantages. First, the real signal action moves outside of the signal handler
//! where there are a lot less restrictions. Second, it fits nicely in all kinds of asynchronous
//! loops and has less chance of race conditions.
//!
//! This module offers premade functions for the write end (and doesn't insist that it must be a
//! pipe ‒ anything that can be written to is fine ‒ sockets too, therefore `UnixStream::pair` is a
//! good candidate).
//!
//! If you want to integrate with some asynchronous library, plugging streams from `mio-uds` or
//! `tokio-uds` libraries should work.
//!
//! If it looks too low-level for your needs, the [`iterator`](../iterator/) module contains some
//! higher-lever interface that also uses a self-pipe pattern under the hood.
//!
//! # Correct order of handling
//!
//! A care needs to be taken to avoid race conditions, especially when handling the same signal in
//! a loop. Specifically, another signal might come when the action for the previous signal is
//! being taken. The correct order is first to clear the content of the pipe (read some/all data
//! from it) and then take the action. This way a spurious wakeup can happen (the pipe could wake
//! up even when no signal came after the signal was taken, because ‒ it arrived between cleaning
//! the pipe and taking the action). Note that some OS primitives (eg. `select`) suffer from
//! spurious wakeups themselves (they can claim a FD is readable when it is not true) and blocking
//! `read` might return prematurely (with eg. `EINTR`).
//!
//! The reverse order of first taking the action and then clearing the pipe might lose signals,
//! which is usually worse.
//!
//! This is not a problem with blocking on reading from the pipe (because both the blocking and
//! cleaning is the same action), but in case of asynchronous handling it matters.
//!
//! If you want to combine setting some flags with a self-pipe pattern, the flag needs to be set
//! first, then the pipe written. On the read end, first the pipe needs to be cleaned, then the
//! flag and then the action taken. This is what the [`SignalsInfo`][crate::iterator::SignalsInfo]
//! structure does internally.
//!
//! # Write collating
//!
//! While unlikely if handled correctly, it is possible the write end is full when a signal comes.
//! In such case the signal handler simply does nothing. If the write end is full, the read end is
//! readable and therefore will wake up. On the other hand, blocking in the signal handler would
//! definitely be a bad idea.
//!
//! However, this also means the number of bytes read from the end might be lower than the number
//! of signals that arrived. This should not generally be a problem, since the OS already collates
//! signals of the same kind together.
//!
//! # Examples
//!
//! This example waits for at last one `SIGUSR1` signal to come before continuing (and
//! terminating). It sends the signal to itself, so it correctly terminates.
//!
//! ```rust
//! extern crate libc;
//! extern crate signal_hook;
//!
//! use std::io::{Error, Read};
//! use std::os::unix::net::UnixStream;
//!
//! fn main() -> Result<(), Error> {
//!     let (mut read, write) = UnixStream::pair()?;
//!     signal_hook::pipe::register(signal_hook::SIGUSR1, write)?;
//!     // This will write into the pipe write end through the signal handler
//!     unsafe { libc::raise(signal_hook::SIGUSR1) };
//!     let mut buff = [0];
//!     read.read_exact(&mut buff)?;
//!     println!("Happily terminating");
//!     Ok(())
//! }

use std::io::{Error, ErrorKind};
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};

use libc::{self, c_int};

use crate::SigId;

#[derive(Copy, Clone)]
pub(crate) enum WakeMethod {
    Send,
    Write,
}

struct WakeFd {
    fd: RawFd,
    method: WakeMethod,
}

impl WakeFd {
    /// Sets close on exec and nonblock on the inner file descriptor.
    fn set_flags(&self) -> Result<(), Error> {
        unsafe {
            let flags = libc::fcntl(self.as_raw_fd(), libc::F_GETFL, 0);
            if flags == -1 {
                return Err(Error::last_os_error());
            }
            let flags = flags | libc::O_NONBLOCK | libc::O_CLOEXEC;
            if libc::fcntl(self.as_raw_fd(), libc::F_SETFL, flags) == -1 {
                return Err(Error::last_os_error());
            }
        }
        Ok(())
    }
    fn wake(&self) {
        wake(self.fd, self.method);
    }
}

impl AsRawFd for WakeFd {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Drop for WakeFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

pub(crate) fn wake(pipe: RawFd, method: WakeMethod) {
    unsafe {
        // This writes some data into the pipe.
        //
        // There are two tricks:
        // * First, the crazy cast. The first part turns reference into pointer. The second part
        //   turns pointer to u8 into a pointer to void, which is what write requires.
        // * Second, we ignore errors, on purpose. We don't have any means to handling them. The
        //   two conceivable errors are EBADFD, if someone passes a non-existent file descriptor or
        //   if it is closed. The second is EAGAIN, in which case the pipe is full ‒ there were
        //   many signals, but the reader didn't have time to read the data yet. It'll still get
        //   woken up, so not fitting another letter in it is fine.
        let data = b"X" as *const _ as *const _;
        match method {
            WakeMethod::Write => libc::write(pipe, data, 1),
            WakeMethod::Send => libc::send(pipe, data, 1, libc::MSG_DONTWAIT),
        };
    }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// In this case, the pipe is taken as the `RawFd`. It'll be closed on deregistration. Effectively,
/// the function takes ownership of the file descriptor. This includes feeling free to set arbitrary
/// flags on it, including file status flags (that are shared across file descriptors created by
/// `dup`).
///
/// Note that passing the wrong file descriptor won't cause UB, but can still lead to severe bugs ‒
/// like data corruptions in files. Prefer using [`register`] if possible.
///
/// Also, it is perfectly legal for multiple writes to be collated together (if not consumed) and
/// to generate spurious wakeups (but will not generate spurious *bytes* in the pipe).
///
/// # Internal details
///
/// Internally, it *currently* does following. Note that this is *not* part of the stability
/// guarantees and may change if necessary.
///
/// * If the file descriptor can be used with [`send`][libc::send], it'll be used together with
///   [`MSG_DONTWAIT`][libc::MSG_DONTWAIT]. This is tested by sending `0` bytes of data (depending
///   on the socket type, this might wake the read end with an empty message).
/// * If it is not possible, the [`O_NONBLOCK`][libc::O_NONBLOCK] will be set on the file
///   descriptor and [`write`][libc::write] will be used instead.
pub fn register_raw(signal: c_int, pipe: RawFd) -> Result<SigId, Error> {
    let res = unsafe { libc::send(pipe, &[] as *const _, 0, libc::MSG_DONTWAIT) };
    let fd = match (res, Error::last_os_error().kind()) {
        (0, _) | (-1, ErrorKind::WouldBlock) => WakeFd {
            fd: pipe,
            method: WakeMethod::Send,
        },
        _ => {
            let fd = WakeFd {
                fd: pipe,
                method: WakeMethod::Write,
            };
            fd.set_flags()?;
            fd
        }
    };
    let action = move || fd.wake();
    unsafe { crate::register(signal, action) }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// The ownership of pipe is taken and will be closed whenever the created action is unregistered.
///
/// Note that if you want to register the same pipe for multiple signals, there's `try_clone`
/// method on many unix socket primitives.
///
/// See [`register_raw`] for further details.
pub fn register<P>(signal: c_int, pipe: P) -> Result<SigId, Error>
where
    P: IntoRawFd + 'static,
{
    register_raw(signal, pipe.into_raw_fd())
}

#[cfg(test)]
mod tests {
    use std::io::Read;
    use std::os::unix::net::{UnixDatagram, UnixStream};

    use super::*;

    // Note: multiple tests share the SIGUSR1 signal. This is fine, we only need to know the signal
    // arrives. It's OK to arrive multiple times, from multiple tests.
    fn wakeup() {
        unsafe { assert_eq!(0, libc::raise(libc::SIGUSR1)) }
    }

    #[test]
    fn register_with_socket() -> Result<(), Error> {
        let (mut read, write) = UnixStream::pair()?;
        register(libc::SIGUSR1, write)?;
        wakeup();
        let mut buff = [0; 1];
        read.read_exact(&mut buff)?;
        assert_eq!(b"X", &buff);
        Ok(())
    }

    #[test]
    fn register_dgram_socket() -> Result<(), Error> {
        let (read, write) = UnixDatagram::pair()?;
        register(libc::SIGUSR1, write)?;
        wakeup();
        let mut buff = [0; 1];
        // The attempt to detect if it is socket can generate an empty message. Therefore, do a few
        // retries.
        for _ in 0..3 {
            let len = read.recv(&mut buff)?;
            if len == 1 && &buff == b"X" {
                return Ok(());
            }
        }
        panic!("Haven't received the right data");
    }

    #[test]
    fn register_with_pipe() -> Result<(), Error> {
        let mut fds = [0; 2];
        unsafe { assert_eq!(0, libc::pipe(fds.as_mut_ptr())) };
        register_raw(libc::SIGUSR1, fds[1])?;
        wakeup();
        let mut buff = [0; 1];
        unsafe { assert_eq!(1, libc::read(fds[0], buff.as_mut_ptr() as *mut _, 1)) }
        assert_eq!(b"X", &buff);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use configuration::Configuration;
use search::Search;

#[derive(PartialEq, Show)]
enum Text {
    Normal(String),
    Highlight(String),
}

struct Renderer {
    search: Search,
}

impl Renderer {
    fn new(search: Search) -> Renderer {
        Renderer {
            search: search,
        }
    }

    fn render(self) -> Vec<Text> {
        let mut result = Vec::new();
        result.push(Text::Normal("> ".to_string()));

        let selection = self.search.selection.unwrap_or("".to_string());
        let max_results = self.search.config.visible_limit;

        for choice in self.search.result.iter() {
            if result.len() >= max_results { break; }

            if choice.as_slice() == selection.as_slice() {
                result.push(Text::Highlight(choice.to_string()));
            } else {
                result.push(Text::Normal(choice.to_string()));
            }
        }
        result
    }
}

#[cfg(test)]

#[test]
fn it_renderes_selected_matches_with_a_highlight() {
    let config = Configuration::from_inputs(vec!["one".to_string(),
                                                 "two".to_string(),
                                                 "three".to_string()], None, Some(3));
    let search = Search::blank(config).down();
    let renderer = Renderer::new(search);

    let output = renderer.render();

    assert_eq!(vec![Text::Normal("> ".to_string()),
                    Text::Normal("one".to_string()),
                    Text::Highlight("two".to_string())], output);
}
//  it "renders selected matches" do
//    search = Search.blank(config).down
//    renderer = Renderer.new(search)
//    expect(renderer.render.choices).to eq [
//      "> ",
//      "one",
//      Text[:inverse, "two", :reset],
//    ]
//  end
<commit_msg>Replace iteration with direct indexing<commit_after>use configuration::Configuration;
use search::Search;

#[derive(PartialEq, Show)]
enum Text {
    Normal(String),
    Highlight(String),
}

struct Renderer {
    search: Search,
}

impl Renderer {
    fn new(search: Search) -> Renderer {
        Renderer {
            search: search,
        }
    }

    fn render(self) -> Vec<Text> {
        let mut result = Vec::new();
        result.push(Text::Normal("> ".to_string()));

        let selection = self.search.selection.unwrap_or("".to_string());
        let max_results = self.search.config.visible_limit - 1;

        for position in range(0, max_results) {
            let choice = self.search.result[position].clone();

            if choice == selection {
                result.push(Text::Highlight(choice));
            } else {
                result.push(Text::Normal(choice))
            }
        }
        result
    }
}

#[cfg(test)]

#[test]
fn it_renderes_selected_matches_with_a_highlight() {
    let config = Configuration::from_inputs(vec!["one".to_string(),
                                                 "two".to_string(),
                                                 "three".to_string()], None, Some(3));
    let search = Search::blank(config).down();
    let renderer = Renderer::new(search);

    let output = renderer.render();

    assert_eq!(vec![Text::Normal("> ".to_string()),
                    Text::Normal("one".to_string()),
                    Text::Highlight("two".to_string())], output);
}
//  it "renders selected matches" do
//    search = Search.blank(config).down
//    renderer = Renderer.new(search)
//    expect(renderer.render.choices).to eq [
//      "> ",
//      "one",
//      Text[:inverse, "two", :reset],
//    ]
//  end
<|endoftext|>


<commit_before>use std::process;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::{
    PistonWindow,
    G2d,
    context,
    clear,
    line,
    polygon,
};

use turtle_window::ReadOnly;
use extensions::ConvertScreenCoordinates;
use state::{Path, Polygon, Pen, TurtleState};
use event::from_piston_event;
use {Point, Event, Color, color};

pub enum DrawingCommand {
    /// When a path is finished being animated, it needs to be persisted in the renderer
    /// so it can be redrawn every frame
    StorePath(Path),
    /// Begins filling with the current fill color from the next path onwards. If temporary_path is
    /// set, it is included in the fill shape. Any paths sent via StorePath will be added to the
    /// filled shape.
    /// This command should be passed the fill color that was set at the time when this command
    /// was issued. We cannot simply poll that from the state when this command is handled because
    /// that may be well after the fill color has changed.
    BeginFill(Color),
    /// Send EndFill to finish the filled shape.
    EndFill,
    /// Clears the image completely
    ///
    /// Panics if temporary_path is not None
    Clear,
}

#[derive(Debug)]
pub enum Drawing {
    Path(Path),
    Polygon(Polygon),
}

pub struct Renderer {
    drawings: Vec<Drawing>,
    /// Polygon that is currently in the process of being filled
    /// Removed when EndFill is sent
    fill_polygon: Option<(Vec<Path>, Polygon)>,
}

impl Renderer {
    pub fn new() -> Renderer {
        Self {
            drawings: Vec::new(),
            fill_polygon: None,
        }
    }

    pub fn run(
        &mut self,
        window: &mut PistonWindow,
        drawing_rx: mpsc::Receiver<DrawingCommand>,
        events_tx: mpsc::Sender<Event>,
        state: ReadOnly,
    ) {
        let mut center = [0.0, 0.0];

        'renderloop:
        while let Some(e) = window.next() {
            if let Some(event) = from_piston_event(&e, |pt| pt.to_local_coords(center)) {
                match events_tx.send(event) {
                    Ok(_) => {},
                    // Quit
                    Err(_) => break,
                }
            }

            loop {
                match drawing_rx.try_recv() {
                    Ok(cmd) => self.handle_drawing_command(cmd),
                    Err(TryRecvError::Empty) => break, // Do nothing
                    Err(TryRecvError::Disconnected) => break 'renderloop, // Quit
                }
            }

            window.draw_2d(&e, |c, g| {
                let background = state.drawing().background;
                clear(background.into(), g);

                let view = c.get_view_size();
                let width = view[0] as f64;
                let height = view[1] as f64;
                center = [width * 0.5, height * 0.5];

                for drawing in &self.drawings {
                    match *drawing {
                        Drawing::Path(ref path) => self.render_path(c, g, center, path),
                        Drawing::Polygon(ref poly) => self.render_polygon(c, g, center, poly, None),
                    }
                }

                if let Some(&(ref border, ref poly)) = self.fill_polygon.as_ref() {
                    self.render_polygon(c, g, center, poly, state.temporary_path().as_ref());
                    for path in border {
                        if path.pen.enabled {
                            self.render_path(c, g, center, path);
                        }
                    }
                }
                //TODO: Render the temporary_path as part of the polygon when fill_polygon.is_some()

                if let Some(ref path) = *state.temporary_path() {
                    if path.pen.enabled {
                        self.render_path(c, g, center, path);
                    }
                }

                self.render_shell(c, g, center, &state);
            });
        }

        // Quit immediately when the window is closed
        process::exit(0);
    }

    /// Handles a drawing command sent from the main thread
    fn handle_drawing_command(&mut self, command: DrawingCommand) {
        //NOTE: Do not pass the ReadOnly state to this function. By the time a DrawingCommand is
        // handled, that state may be completely out of date
        use self::DrawingCommand::*;
        match command {
            StorePath(path) => {
                if self.fill_polygon.is_some() {
                    let &mut (ref mut border, ref mut poly) = self.fill_polygon.as_mut().unwrap();
                    border.push(path.clone());

                    let Path {start, end, ..} = path;
                    if poly.vertices.last().map_or(true, |&v| v != start) {
                        poly.vertices.push(start);
                    }
                    poly.vertices.push(end);
                }
                else if path.pen.enabled {
                    self.drawings.push(Drawing::Path(path));
                }
            },
            BeginFill(fill_color) => {
                // Calling begin_fill multiple times is okay, it just won't do anything until
                // end_fill is called
                self.fill_polygon = self.fill_polygon.take().or_else(|| Some((Vec::new(), Polygon {
                    vertices: Vec::new(),
                    fill_color: fill_color,
                })));
            },
            // Calling end_fill multiple times is not a problem
            EndFill => if let Some((border, poly)) = self.fill_polygon.take() {
                // Always add the border over the filled polygon so the border is drawn on top
                self.drawings.push(Drawing::Polygon(poly));
                self.drawings.extend(border.into_iter().filter_map(|p| if p.pen.enabled {
                    Some(Drawing::Path(p))
                } else { None }));
            },
            Clear => {
                self.drawings.clear();
                // Because clear doesn't actually shorten the capacity of the vector
                // We don't want to leak memory by leaving this Vec at whatever its size was before
                self.drawings.shrink_to_fit();
                self.fill_polygon.take();
            }
        }
    }

    /// Render a path assuming that its pen is enabled
    fn render_path(&self, c: context::Context, g: &mut G2d, center: Point, path: &Path) {
        let &Path {start, end, ref pen} = path;
        let &Pen {thickness, color, enabled} = pen;
        debug_assert!(enabled, "bug: attempt to render path when pen was not enabled");

        let start = start.to_screen_coords(center);
        let end = end.to_screen_coords(center);

        line(color.into(), thickness,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
    }

    /// Render a polygon with an optional extra edge
    fn render_polygon(&self, c: context::Context, g: &mut G2d, center: Point, poly: &Polygon,
        extra_edge: Option<&Path>
    ) {
        let extra = if let Some(&Path {start, end, ..}) = extra_edge {
            if poly.vertices.last().map_or(true, |&v| v != start) {
                vec![start, end]
            }
            else {
                vec![end]
            }
        }
        else {
            Vec::new()
        };

        let verts = poly.vertices.iter()
            .chain(extra.iter())
            .map(|p| p.to_screen_coords(center))
            .collect::<Vec<_>>();
        polygon(poly.fill_color.into(), &verts, c.transform, g);
    }

    /// Draw the turtle's shell
    fn render_shell(&self, c: context::Context, g: &mut G2d, center: Point, state: &ReadOnly) {
        // Calculate all the points on the shell by rotating the shell shape by the turtle's
        // heading and moving it to the turtle's position
        let TurtleState {position, heading, visible, ..} = *state.turtle();
        if !visible {
            return;
        }

        let cos = heading.cos();
        let sin = heading.sin();
        let turtle_x = position[0];
        let turtle_y = position[1];
        let shell: Vec<_> = [
            [0., 15.],
            [10., 0.],
            [0., -15.],
        ].into_iter().map(|pt| {
            // Rotate each point by the heading and add the current turtle position
            let x = cos * pt[0] - sin * pt[1] + turtle_x;
            let y = sin * pt[0] + cos * pt[1] + turtle_y;
            [x, y].to_screen_coords(center)
        }).collect();

        // Draw the turtle shell with its background first, then its border
        polygon(color::WHITE.into(), &shell, c.transform, g);
        for i in 0..shell.len() {
            let start = shell[i];
            let end = shell[(i + 1) % shell.len()];

            line(color::BLACK.into(), 1.,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
        }
    }
}
<commit_msg>Made sure that render_polygon is very efficient given that it is called repeatedly in a loop every frame<commit_after>use std::process;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::{
    PistonWindow,
    G2d,
    context,
    clear,
    line,
    polygon,
};

use turtle_window::ReadOnly;
use extensions::ConvertScreenCoordinates;
use state::{Path, Polygon, Pen, TurtleState};
use event::from_piston_event;
use {Point, Event, Color, color};

pub enum DrawingCommand {
    /// When a path is finished being animated, it needs to be persisted in the renderer
    /// so it can be redrawn every frame
    StorePath(Path),
    /// Begins filling with the current fill color from the next path onwards. If temporary_path is
    /// set, it is included in the fill shape. Any paths sent via StorePath will be added to the
    /// filled shape.
    /// This command should be passed the fill color that was set at the time when this command
    /// was issued. We cannot simply poll that from the state when this command is handled because
    /// that may be well after the fill color has changed.
    BeginFill(Color),
    /// Send EndFill to finish the filled shape.
    EndFill,
    /// Clears the image completely
    ///
    /// Panics if temporary_path is not None
    Clear,
}

#[derive(Debug)]
pub enum Drawing {
    Path(Path),
    Polygon(Polygon),
}

pub struct Renderer {
    drawings: Vec<Drawing>,
    /// Polygon that is currently in the process of being filled
    /// Removed when EndFill is sent
    fill_polygon: Option<(Vec<Path>, Polygon)>,
}

impl Renderer {
    pub fn new() -> Renderer {
        Self {
            drawings: Vec::new(),
            fill_polygon: None,
        }
    }

    pub fn run(
        &mut self,
        window: &mut PistonWindow,
        drawing_rx: mpsc::Receiver<DrawingCommand>,
        events_tx: mpsc::Sender<Event>,
        state: ReadOnly,
    ) {
        let mut center = [0.0, 0.0];

        'renderloop:
        while let Some(e) = window.next() {
            if let Some(event) = from_piston_event(&e, |pt| pt.to_local_coords(center)) {
                match events_tx.send(event) {
                    Ok(_) => {},
                    // Quit
                    Err(_) => break,
                }
            }

            loop {
                match drawing_rx.try_recv() {
                    Ok(cmd) => self.handle_drawing_command(cmd),
                    Err(TryRecvError::Empty) => break, // Do nothing
                    Err(TryRecvError::Disconnected) => break 'renderloop, // Quit
                }
            }

            window.draw_2d(&e, |c, g| {
                let background = state.drawing().background;
                clear(background.into(), g);

                let view = c.get_view_size();
                let width = view[0] as f64;
                let height = view[1] as f64;
                center = [width * 0.5, height * 0.5];

                for drawing in &self.drawings {
                    match *drawing {
                        Drawing::Path(ref path) => self.render_path(c, g, center, path),
                        Drawing::Polygon(ref poly) => self.render_polygon(c, g, center,
                            poly.fill_color, poly.vertices.iter()),
                    }
                }

                if let Some(&(ref border, ref poly)) = self.fill_polygon.as_ref() {
                    // If the temporary_path is not None, we need to add it to the polygon being
                    // filled or else the polygon will fall one edge behind in the animation
                    let extra = state.temporary_path().as_ref().map_or(Vec::new(), |&Path {start, end, ..}| {
                        if poly.vertices.last().map_or(true, |&v| v != start) {
                            vec![start, end]
                        }
                        else {
                            vec![end]
                        }
                    });
                    self.render_polygon(c, g, center, poly.fill_color,
                        poly.vertices.iter().chain(extra.iter()));

                    for path in border {
                        if path.pen.enabled {
                            self.render_path(c, g, center, path);
                        }
                    }
                }

                if let Some(ref path) = *state.temporary_path() {
                    if path.pen.enabled {
                        self.render_path(c, g, center, path);
                    }
                }

                self.render_shell(c, g, center, &state);
            });
        }

        // Quit immediately when the window is closed
        process::exit(0);
    }

    /// Handles a drawing command sent from the main thread
    fn handle_drawing_command(&mut self, command: DrawingCommand) {
        //NOTE: Do not pass the ReadOnly state to this function. By the time a DrawingCommand is
        // handled, that state may be completely out of date
        use self::DrawingCommand::*;
        match command {
            StorePath(path) => {
                if self.fill_polygon.is_some() {
                    let &mut (ref mut border, ref mut poly) = self.fill_polygon.as_mut().unwrap();
                    border.push(path.clone());

                    let Path {start, end, ..} = path;
                    if poly.vertices.last().map_or(true, |&v| v != start) {
                        poly.vertices.push(start);
                    }
                    poly.vertices.push(end);
                }
                else if path.pen.enabled {
                    self.drawings.push(Drawing::Path(path));
                }
            },
            BeginFill(fill_color) => {
                // Calling begin_fill multiple times is okay, it just won't do anything until
                // end_fill is called
                self.fill_polygon = self.fill_polygon.take().or_else(|| Some((Vec::new(), Polygon {
                    vertices: Vec::new(),
                    fill_color: fill_color,
                })));
            },
            // Calling end_fill multiple times is not a problem
            EndFill => if let Some((border, poly)) = self.fill_polygon.take() {
                // Always add the border over the filled polygon so the border is drawn on top
                self.drawings.push(Drawing::Polygon(poly));
                self.drawings.extend(border.into_iter().filter_map(|p| if p.pen.enabled {
                    Some(Drawing::Path(p))
                } else { None }));
            },
            Clear => {
                self.drawings.clear();
                // Because clear doesn't actually shorten the capacity of the vector
                // We don't want to leak memory by leaving this Vec at whatever its size was before
                self.drawings.shrink_to_fit();
                self.fill_polygon.take();
            }
        }
    }

    /// Render a path assuming that its pen is enabled
    fn render_path(&self, c: context::Context, g: &mut G2d, center: Point, path: &Path) {
        let &Path {start, end, ref pen} = path;
        let &Pen {thickness, color, enabled} = pen;
        debug_assert!(enabled, "bug: attempt to render path when pen was not enabled");

        let start = start.to_screen_coords(center);
        let end = end.to_screen_coords(center);

        line(color.into(), thickness,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
    }

    /// Render a polygon given its vertices
    fn render_polygon<'a, T: Iterator<Item=&'a Point>>(
        &self,
        c: context::Context,
        g: &mut G2d,
        center: Point,
        fill_color: Color,
        verts: T,
    ) {
        // Performance note: Why make this function generic instead of just taking Polygon?
        // Answer: render_polygon is called multiple times. It's called repeatedly in a loop, and
        // it is also called when drawing the current fill_polygon. Rather than moving the
        // code to *maybe* add the temporary_path to the rendered polygon into this method, we
        // avoid branching unnecessarily by allowing the repeated caller to do what is fast, then
        // doing the slow thing (checking if the path is None) only once when it is needed.
        //
        // We pass in the points as an Iterator so that they do not need to be collected into any
        // struct. This avoids an allocation that really isn't needed since these are all temporary
        // anyway. Everything is going to get copied anyway on the next line. No need to do it
        // twice.
        //
        // See the commit before this comment was added for the approach that would have required
        // branching in every iteration of the loop where render_polygon is called over and over
        // again.
        let verts = verts.map(|p| p.to_screen_coords(center)).collect::<Vec<_>>();
        polygon(fill_color.into(), &verts, c.transform, g);
    }

    /// Draw the turtle's shell
    fn render_shell(&self, c: context::Context, g: &mut G2d, center: Point, state: &ReadOnly) {
        // Calculate all the points on the shell by rotating the shell shape by the turtle's
        // heading and moving it to the turtle's position
        let TurtleState {position, heading, visible, ..} = *state.turtle();
        if !visible {
            return;
        }

        let cos = heading.cos();
        let sin = heading.sin();
        let turtle_x = position[0];
        let turtle_y = position[1];
        let shell: Vec<_> = [
            [0., 15.],
            [10., 0.],
            [0., -15.],
        ].into_iter().map(|pt| {
            // Rotate each point by the heading and add the current turtle position
            let x = cos * pt[0] - sin * pt[1] + turtle_x;
            let y = sin * pt[0] + cos * pt[1] + turtle_y;
            [x, y].to_screen_coords(center)
        }).collect();

        // Draw the turtle shell with its background first, then its border
        polygon(color::WHITE.into(), &shell, c.transform, g);
        for i in 0..shell.len() {
            let start = shell[i];
            let end = shell[(i + 1) % shell.len()];

            line(color::BLACK.into(), 1.,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
        }
    }
}
<|endoftext|>


<commit_before>//! Futures integration.

use crate::stream::Stream;
use crate::sync::Mutex;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{LocalWaker, Poll, Waker};

/// The storage of a stream future.
#[derive(Debug)]
struct StreamFutureStorage<T> {
    value: Option<T>,
    waker: Option<Waker>,
}

impl<T> StreamFutureStorage<T> {
    fn new() -> Arc<Mutex<Self>> {
        Arc::new(Mutex::new(StreamFutureStorage {
            value: None,
            waker: None,
        }))
    }
}

/// A future that waits for a stream value.
///
/// This is created by `Stream::next`.
#[derive(Debug)]
pub struct StreamFuture<T> {
    storage: Arc<Mutex<StreamFutureStorage<T>>>,
    stream: Stream<T>,
}

impl<T> StreamFuture<T> {
    /// Creates a future that returns the next value sent to this stream.
    pub(crate) fn new(stream: Stream<T>) -> Self
    where
        T: Clone + Send + 'static,
    {
        let storage = StreamFutureStorage::new();
        let st = storage.clone();
        stream.observe(move |val| {
            let mut storage = st.lock();
            storage.value = Some(val.into_owned());
            if let Some(waker) = &storage.waker {
                waker.wake();
            }
            false
        });
        StreamFuture { storage, stream }
    }

    /// Obtains the source stream.
    pub fn get_source(&self) -> &Stream<T> {
        &self.stream
    }
}

impl<T> Future for StreamFuture<T> {
    type Output = T;

    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let mut storage = self.storage.lock();
        if let Some(value) = storage.value.take() {
            Poll::Ready(value)
        } else {
            storage.waker = Some(lw.clone().into_waker());
            Poll::Pending
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::stream::Sink;
    use futures::executor::block_on;

    #[test]
    fn basic() {
        let sink = Sink::new();
        let future = StreamFuture::new(sink.stream());

        sink.send(42);
        assert_eq!(block_on(future), 42);
    }
}
<commit_msg>updated test<commit_after>//! Futures integration.

use crate::stream::Stream;
use crate::sync::Mutex;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{LocalWaker, Poll, Waker};

/// The storage of a stream future.
#[derive(Debug)]
struct StreamFutureStorage<T> {
    value: Option<T>,
    waker: Option<Waker>,
}

impl<T> StreamFutureStorage<T> {
    fn new() -> Arc<Mutex<Self>> {
        Arc::new(Mutex::new(StreamFutureStorage {
            value: None,
            waker: None,
        }))
    }
}

/// A future that waits for a stream value.
///
/// This is created by `Stream::next`.
#[derive(Debug)]
pub struct StreamFuture<T> {
    storage: Arc<Mutex<StreamFutureStorage<T>>>,
    stream: Stream<T>,
}

impl<T> StreamFuture<T> {
    /// Creates a future that returns the next value sent to this stream.
    pub(crate) fn new(stream: Stream<T>) -> Self
    where
        T: Clone + Send + 'static,
    {
        let storage = StreamFutureStorage::new();
        let st = storage.clone();
        stream.observe(move |val| {
            let mut storage = st.lock();
            storage.value = Some(val.into_owned());
            if let Some(waker) = &storage.waker {
                waker.wake();
            }
            false
        });
        StreamFuture { storage, stream }
    }

    /// Obtains the source stream.
    pub fn get_source(&self) -> &Stream<T> {
        &self.stream
    }
}

impl<T> Future for StreamFuture<T> {
    type Output = T;

    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let mut storage = self.storage.lock();
        if let Some(value) = storage.value.take() {
            Poll::Ready(value)
        } else {
            storage.waker = Some(lw.clone().into_waker());
            Poll::Pending
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::stream::Sink;
    use futures::executor::block_on;

    #[test]
    fn basic() {
        let sink = Sink::new();
        let future = StreamFuture::new(sink.stream());

        sink.send(42);
        sink.send(13);
        assert_eq!(block_on(future), 42);
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::rc::Rc;
use std::cell::RefCell;
use std::io;
use std::io::ErrorKind;
use std::cmp::min;
use std::fmt;

use devicemapper::{DM, Device, DmFlags, DevId};

use types::{Sectors, SectorOffset, FroyoError};
use blockdev::{LinearDev, LinearDevSave};
use consts::*;
use util::setup_dm_dev;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidDevSave {
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    pub members: Vec<LinearDevSave>,
}

#[derive(Debug, Clone)]
pub struct RaidDev {
    pub id: String,
    dev: Device,
    dm_name: String,
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    members: Vec<RaidMember>,
    used: Vec<Rc<RefCell<RaidSegment>>>,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidStatus {
    Good,
    Degraded(usize),
    Failed,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidAction {
    Idle,
    Frozen,
    Resync,
    Recover,
    Check,
    Repair,
    Reshape,
    Unknown,
}

#[derive(Debug, Clone)]
pub enum RaidMember {
    Present(Rc<RefCell<LinearDev>>),
    Absent(LinearDevSave),
}

impl RaidMember {
    fn present(&self) -> Option<Rc<RefCell<LinearDev>>> {
        match *self {
            RaidMember::Present(ref x) => Some(x.clone()),
            RaidMember::Absent(_) => None,
        }
    }
}

impl RaidDev {
    pub fn create(dm: &DM, name: &str, id: String, devs: Vec<RaidMember>,
                  stripe: Sectors, region: Sectors)
                  -> io::Result<RaidDev> {
        let raid_texts: Vec<_> = devs.iter()
            .map(|dev|
                 match *dev {
                     RaidMember::Present(ref dev) => {
                         format!("{}:{} {}:{}",
                                 RefCell::borrow(dev).meta_dev.major,
                                 RefCell::borrow(dev).meta_dev.minor,
                                 RefCell::borrow(dev).data_dev.major,
                                 RefCell::borrow(dev).data_dev.minor)
                     },
                     RaidMember::Absent(_) => "- -".to_owned(),
                 })
            .collect();

        let present_devs = devs.iter().filter_map(|ref x| x.present()).count();
        if present_devs < (devs.len() - FROYO_REDUNDANCY) {
            return Err(io::Error::new(
                ErrorKind::InvalidInput,
                format!(
                    "Too many missing devs to create raid: {}. Need at least {} of {}",
                    devs.len() - present_devs, devs.len() - FROYO_REDUNDANCY,
                    devs.len())))
        }

        let first_present_dev = devs.iter()
            .filter_map(|ref x| x.present())
            .next()
            .unwrap();
        let first_present_dev_len = first_present_dev.borrow().data_length();

        // Verify all present devs are the same length
        if !devs.iter().filter_map(|x| x.present()).all(
            |x| x.borrow().data_length() == first_present_dev_len) {
            return Err(io::Error::new(
                ErrorKind::InvalidInput, "RAID member device sizes differ"));
        }

        let target_length = first_present_dev_len
            * Sectors::new((devs.len() - FROYO_REDUNDANCY) as u64);

        let params = format!("raid5_ls 3 {} region_size {} {} {}",
                             *stripe,
                             *region,
                             raid_texts.len(),
                             raid_texts.join(" "));
        let raid_table = [(0u64, *target_length, "raid", params)];
        let dm_name = format!("froyo-raid5-{}-{}", name, id);
        let raid_dev = try!(setup_dm_dev(dm, &dm_name, &raid_table));

        Ok(RaidDev {
            id: id,
            dev: raid_dev,
            dm_name: dm_name,
            stripe_sectors: stripe,
            region_sectors: region,
            length: target_length,
            members: devs,
            used: Vec::new()
        })
    }

    pub fn to_save(&self) -> RaidDevSave {
        RaidDevSave {
            stripe_sectors: self.stripe_sectors,
            region_sectors: self.region_sectors,
            length: self.length,
            members: self.members.iter()
                .map(|dev|
                     match *dev {
                         RaidMember::Present(ref x) => RefCell::borrow(x).to_save(),
                         RaidMember::Absent(ref x) => x.clone(),
                     })
                .collect(),
        }
    }

    fn used_areas(&self)-> Vec<(SectorOffset, Sectors)> {
        self.used.iter()
            .map(|rs| {
                let rs = RefCell::borrow(rs);
                (rs.start, rs.length)
            })
            .collect()
    }

    fn free_areas(&self) -> Vec<(SectorOffset, Sectors)> {
        let mut used_vec = self.used_areas();

        used_vec.sort();
        // Insert an entry to mark the end of the raiddev so the fold works
        // correctly
        used_vec.push((SectorOffset::new(*self.length), Sectors::new(0)));

        let mut free_vec = Vec::new();
        used_vec.iter()
            .fold(SectorOffset::new(0), |prev_end, &(start, len)| {
                if prev_end < start {
                    free_vec.push((prev_end, Sectors::new(*start-*prev_end)));
                }
                start + SectorOffset::new(*len)
            });

        free_vec
    }

    pub fn free_sectors(&self) -> Sectors {
        self.free_areas().into_iter()
            .map(|(_, len)| len)
            .sum()
    }

    // Find some sector ranges that could be allocated. If more sectors are needed than
    // our capacity, return partial results.
    pub fn get_some_space(&self, size: Sectors) -> (Sectors, Vec<(SectorOffset, Sectors)>) {
        let mut segs = Vec::new();
        let mut needed = size;

        for (start, len) in self.free_areas() {
            if needed == Sectors::new(0) {
                break
            }

            let to_use = min(needed, len);

            segs.push((start, to_use));
            needed = needed - to_use;
        }

        (size - needed, segs)
    }

    pub fn status(&self) -> Result<(RaidStatus, RaidAction), FroyoError> {
        let dm = try!(DM::new());

        let (_, mut status) = try!(dm.table_status(&DevId::Name(&self.dm_name), DmFlags::empty()));

        if status.len() != 1 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Expected 1 line from raid status")))
        }

        // See kernel's dm-raid.txt "Status Output"
        let status_line = status.pop().unwrap().3;
        let status_vals = status_line.split(' ').collect::<Vec<_>>();
        if status_vals.len() < 5 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Kernel returned too few values from raid status")))
        }

        let mut bad = 0;
        for c in status_vals[2].chars() {
            match c {
                'A' => {},
                'a' => {},
                'D' => bad += 1,
                x @ _ => return Err(FroyoError::Io(io::Error::new(
                    ErrorKind::InvalidData,
                    format!("Kernel returned unknown raid health char '{}'", x)))),
            }
        }

        let raid_status = match bad {
            0 => RaidStatus::Good,
            x @ 1...FROYO_REDUNDANCY => RaidStatus::Degraded(x),
            _ => RaidStatus::Failed,
        };

        let raid_action = match status_vals[4] {
            "idle" => RaidAction::Idle,
            "frozen" => RaidAction::Frozen,
            "resync" => RaidAction::Resync,
            "recover" => RaidAction::Recover,
            "check" => RaidAction::Check,
            "repair" => RaidAction::Repair,
            "reshape" => RaidAction::Reshape,
            _ => RaidAction::Unknown,
        };

        Ok((raid_status, raid_action))
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidSegmentSave {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: String,  // RaidDev id
}

#[derive(Clone)]
pub struct RaidSegment {
    start: SectorOffset,
    length: Sectors,
    parent: Rc<RefCell<RaidDev>>,
}

impl fmt::Debug for RaidSegment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", *self.start, *self.length,
               RefCell::borrow(&self.parent).id)
    }
}

impl RaidSegment {
    pub fn new(start: SectorOffset, length: Sectors, parent: &Rc<RefCell<RaidDev>>)
           -> Rc<RefCell<RaidSegment>> {
        let rs = Rc::new(RefCell::new(RaidSegment {
            start: start,
            length: length,
            parent: parent.clone(),
        }));
        RefCell::borrow_mut(parent).used.push(rs.clone());

        rs
    }

    pub fn to_save(&self) -> RaidSegmentSave {
        RaidSegmentSave {
            start: self.start,
            length: self.length,
            parent: RefCell::borrow(&self.parent).id.clone(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidLinearDevSave {
    pub id: String,
    pub segments: Vec<RaidSegmentSave>,
}

#[derive(Debug, Clone)]
pub struct RaidLinearDev {
    id: String,
    pub dev: Device,
    segments: Vec<Rc<RefCell<RaidSegment>>>,
}

impl RaidLinearDev {
    pub fn create(dm: &DM, name: &str, id: &str, segments: Vec<Rc<RefCell<RaidSegment>>>)
              -> io::Result<RaidLinearDev> {

        let mut table = Vec::new();
        let mut offset = SectorOffset::new(0);
        for seg in &segments {
            let seg = RefCell::borrow(seg);
            let line = (*offset, *seg.length, "linear",
                        format!("{}:{} {}", RefCell::borrow(&seg.parent).dev.major,
                                RefCell::borrow(&seg.parent).dev.minor, *seg.start));
            table.push(line);
            offset = offset + SectorOffset::new(*seg.length);
        }

        let dm_name = format!("froyo-raid-linear-{}", name);
        let linear_dev = try!(setup_dm_dev(dm, &dm_name, &table));

        Ok(RaidLinearDev {
            id: id.to_owned(),
            dev: linear_dev,
            segments: segments,
        })
    }

    pub fn to_save(&self) -> RaidLinearDevSave {
        RaidLinearDevSave {
            id: self.id.clone(),
            segments: self.segments.iter()
                .map(|x| RefCell::borrow(x).to_save())
                .collect()
        }
    }

    pub fn length(&self) -> Sectors {
        self.segments.iter().map(|x| RefCell::borrow(x).length).sum()
    }
}
<commit_msg>Split RaidLinearDev conversion to table into a helper fn<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::rc::Rc;
use std::cell::RefCell;
use std::io;
use std::io::ErrorKind;
use std::cmp::min;
use std::fmt;

use devicemapper::{DM, Device, DmFlags, DevId};

use types::{Sectors, SectorOffset, FroyoError};
use blockdev::{LinearDev, LinearDevSave};
use consts::*;
use util::setup_dm_dev;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidDevSave {
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    pub members: Vec<LinearDevSave>,
}

#[derive(Debug, Clone)]
pub struct RaidDev {
    pub id: String,
    dev: Device,
    dm_name: String,
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    members: Vec<RaidMember>,
    used: Vec<Rc<RefCell<RaidSegment>>>,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidStatus {
    Good,
    Degraded(usize),
    Failed,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidAction {
    Idle,
    Frozen,
    Resync,
    Recover,
    Check,
    Repair,
    Reshape,
    Unknown,
}

#[derive(Debug, Clone)]
pub enum RaidMember {
    Present(Rc<RefCell<LinearDev>>),
    Absent(LinearDevSave),
}

impl RaidMember {
    fn present(&self) -> Option<Rc<RefCell<LinearDev>>> {
        match *self {
            RaidMember::Present(ref x) => Some(x.clone()),
            RaidMember::Absent(_) => None,
        }
    }
}

impl RaidDev {
    pub fn create(dm: &DM, name: &str, id: String, devs: Vec<RaidMember>,
                  stripe: Sectors, region: Sectors)
                  -> io::Result<RaidDev> {
        let raid_texts: Vec<_> = devs.iter()
            .map(|dev|
                 match *dev {
                     RaidMember::Present(ref dev) => {
                         format!("{}:{} {}:{}",
                                 RefCell::borrow(dev).meta_dev.major,
                                 RefCell::borrow(dev).meta_dev.minor,
                                 RefCell::borrow(dev).data_dev.major,
                                 RefCell::borrow(dev).data_dev.minor)
                     },
                     RaidMember::Absent(_) => "- -".to_owned(),
                 })
            .collect();

        let present_devs = devs.iter().filter_map(|ref x| x.present()).count();
        if present_devs < (devs.len() - FROYO_REDUNDANCY) {
            return Err(io::Error::new(
                ErrorKind::InvalidInput,
                format!(
                    "Too many missing devs to create raid: {}. Need at least {} of {}",
                    devs.len() - present_devs, devs.len() - FROYO_REDUNDANCY,
                    devs.len())))
        }

        let first_present_dev = devs.iter()
            .filter_map(|ref x| x.present())
            .next()
            .unwrap();
        let first_present_dev_len = first_present_dev.borrow().data_length();

        // Verify all present devs are the same length
        if !devs.iter().filter_map(|x| x.present()).all(
            |x| x.borrow().data_length() == first_present_dev_len) {
            return Err(io::Error::new(
                ErrorKind::InvalidInput, "RAID member device sizes differ"));
        }

        let target_length = first_present_dev_len
            * Sectors::new((devs.len() - FROYO_REDUNDANCY) as u64);

        let params = format!("raid5_ls 3 {} region_size {} {} {}",
                             *stripe,
                             *region,
                             raid_texts.len(),
                             raid_texts.join(" "));
        let raid_table = [(0u64, *target_length, "raid", params)];
        let dm_name = format!("froyo-raid5-{}-{}", name, id);
        let raid_dev = try!(setup_dm_dev(dm, &dm_name, &raid_table));

        Ok(RaidDev {
            id: id,
            dev: raid_dev,
            dm_name: dm_name,
            stripe_sectors: stripe,
            region_sectors: region,
            length: target_length,
            members: devs,
            used: Vec::new()
        })
    }

    pub fn to_save(&self) -> RaidDevSave {
        RaidDevSave {
            stripe_sectors: self.stripe_sectors,
            region_sectors: self.region_sectors,
            length: self.length,
            members: self.members.iter()
                .map(|dev|
                     match *dev {
                         RaidMember::Present(ref x) => RefCell::borrow(x).to_save(),
                         RaidMember::Absent(ref x) => x.clone(),
                     })
                .collect(),
        }
    }

    fn used_areas(&self)-> Vec<(SectorOffset, Sectors)> {
        self.used.iter()
            .map(|rs| {
                let rs = RefCell::borrow(rs);
                (rs.start, rs.length)
            })
            .collect()
    }

    fn free_areas(&self) -> Vec<(SectorOffset, Sectors)> {
        let mut used_vec = self.used_areas();

        used_vec.sort();
        // Insert an entry to mark the end of the raiddev so the fold works
        // correctly
        used_vec.push((SectorOffset::new(*self.length), Sectors::new(0)));

        let mut free_vec = Vec::new();
        used_vec.iter()
            .fold(SectorOffset::new(0), |prev_end, &(start, len)| {
                if prev_end < start {
                    free_vec.push((prev_end, Sectors::new(*start-*prev_end)));
                }
                start + SectorOffset::new(*len)
            });

        free_vec
    }

    pub fn free_sectors(&self) -> Sectors {
        self.free_areas().into_iter()
            .map(|(_, len)| len)
            .sum()
    }

    // Find some sector ranges that could be allocated. If more sectors are needed than
    // our capacity, return partial results.
    pub fn get_some_space(&self, size: Sectors) -> (Sectors, Vec<(SectorOffset, Sectors)>) {
        let mut segs = Vec::new();
        let mut needed = size;

        for (start, len) in self.free_areas() {
            if needed == Sectors::new(0) {
                break
            }

            let to_use = min(needed, len);

            segs.push((start, to_use));
            needed = needed - to_use;
        }

        (size - needed, segs)
    }

    pub fn status(&self) -> Result<(RaidStatus, RaidAction), FroyoError> {
        let dm = try!(DM::new());

        let (_, mut status) = try!(dm.table_status(&DevId::Name(&self.dm_name), DmFlags::empty()));

        if status.len() != 1 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Expected 1 line from raid status")))
        }

        // See kernel's dm-raid.txt "Status Output"
        let status_line = status.pop().unwrap().3;
        let status_vals = status_line.split(' ').collect::<Vec<_>>();
        if status_vals.len() < 5 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Kernel returned too few values from raid status")))
        }

        let mut bad = 0;
        for c in status_vals[2].chars() {
            match c {
                'A' => {},
                'a' => {},
                'D' => bad += 1,
                x @ _ => return Err(FroyoError::Io(io::Error::new(
                    ErrorKind::InvalidData,
                    format!("Kernel returned unknown raid health char '{}'", x)))),
            }
        }

        let raid_status = match bad {
            0 => RaidStatus::Good,
            x @ 1...FROYO_REDUNDANCY => RaidStatus::Degraded(x),
            _ => RaidStatus::Failed,
        };

        let raid_action = match status_vals[4] {
            "idle" => RaidAction::Idle,
            "frozen" => RaidAction::Frozen,
            "resync" => RaidAction::Resync,
            "recover" => RaidAction::Recover,
            "check" => RaidAction::Check,
            "repair" => RaidAction::Repair,
            "reshape" => RaidAction::Reshape,
            _ => RaidAction::Unknown,
        };

        Ok((raid_status, raid_action))
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidSegmentSave {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: String,  // RaidDev id
}

#[derive(Clone)]
pub struct RaidSegment {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: Rc<RefCell<RaidDev>>,
}

impl fmt::Debug for RaidSegment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", *self.start, *self.length,
               RefCell::borrow(&self.parent).id)
    }
}

impl RaidSegment {
    pub fn new(start: SectorOffset, length: Sectors, parent: &Rc<RefCell<RaidDev>>)
           -> Rc<RefCell<RaidSegment>> {
        let rs = Rc::new(RefCell::new(RaidSegment {
            start: start,
            length: length,
            parent: parent.clone(),
        }));
        RefCell::borrow_mut(parent).used.push(rs.clone());

        rs
    }

    pub fn to_save(&self) -> RaidSegmentSave {
        RaidSegmentSave {
            start: self.start,
            length: self.length,
            parent: RefCell::borrow(&self.parent).id.clone(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidLinearDevSave {
    pub id: String,
    pub segments: Vec<RaidSegmentSave>,
}

#[derive(Debug, Clone)]
pub struct RaidLinearDev {
    id: String,
    dm_name: String,
    pub dev: Device,
    pub segments: Vec<Rc<RefCell<RaidSegment>>>,
}

impl RaidLinearDev {
    pub fn dm_table(segments: &Vec<Rc<RefCell<RaidSegment>>>)
                    -> Vec<(u64, u64, String, String)> {
        let mut table = Vec::new();
        let mut offset = SectorOffset::new(0);
        for seg in segments {
            let seg = RefCell::borrow(seg);
            let line = (*offset, *seg.length, "linear".to_owned(),
                        format!("{}:{} {}",
                                RefCell::borrow(&seg.parent).dev.major,
                                RefCell::borrow(&seg.parent).dev.minor,
                                *seg.start));
            table.push(line);
            offset = offset + SectorOffset::new(*seg.length);
        }

        table
    }

    pub fn create(dm: &DM, name: &str, id: &str,
                  segments: Vec<Rc<RefCell<RaidSegment>>>)
              -> io::Result<RaidLinearDev> {

        let table = Self::dm_table(&segments);
        let dm_name = format!("froyo-raid-linear-{}", name);
        let linear_dev = try!(setup_dm_dev(dm, &dm_name, &table));

        Ok(RaidLinearDev {
            id: id.to_owned(),
            dm_name: dm_name,
            dev: linear_dev,
            segments: segments,
        })
    }

    pub fn to_save(&self) -> RaidLinearDevSave {
        RaidLinearDevSave {
            id: self.id.clone(),
            segments: self.segments.iter()
                .map(|x| RefCell::borrow(x).to_save())
                .collect()
        }
    }

    pub fn length(&self) -> Sectors {
        self.segments.iter().map(|x| RefCell::borrow(x).length).sum()
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Div, Mul, Sub};

/// A real number.
pub trait Real: Copy + Add<Output=Self> + Div<Output=Self> + Mul<Output=Self> + Sub<Output=Self> {
    /// Return the unity.
    fn one() -> Self;

    /// Return the zero.
    fn zero() -> Self;

    /// Create a real number from a natural one.
    fn from_natural(usize) -> Self;
}

/// A means of converting an arbitrary quantity to a real number.
pub trait ToReal<T: Real> {
    /// Convert to a real number.
    fn to_real(&self) -> T;
}

macro_rules! real(
    ($kind:ty) => (
        impl Real for $kind {
            #[inline(always)]
            fn one() -> Self {
                1.0
            }

            #[inline(always)]
            fn zero() -> Self {
                0.0
            }

            #[inline(always)]
            fn from_natural(number: usize) -> Self {
                number as $kind
            }
        }
    );
);

real!(f32);
real!(f64);

macro_rules! to_real(
    ($kind:ty, $real:ty) => (
        impl ToReal<$real> for $kind {
            #[inline(always)]
            fn to_real(&self) -> $real {
                *self as $real
            }
        }
    );
);

to_real!(u8, f32);
to_real!(u8, f64);

to_real!(u16, f32);
to_real!(u16, f64);

to_real!(u32, f32);
to_real!(u32, f64);

to_real!(u64, f32);
to_real!(u64, f64);

to_real!(i8, f32);
to_real!(i8, f64);

to_real!(i16, f32);
to_real!(i16, f64);

to_real!(i32, f32);
to_real!(i32, f64);

to_real!(i64, f32);
to_real!(i64, f64);

to_real!(f32, f32);
to_real!(f64, f64);

to_real!(isize, f32);
to_real!(isize, f64);

to_real!(usize, f32);
to_real!(usize, f64);
<commit_msg>Refactor the macros a bit<commit_after>use std::ops::{Add, Div, Mul, Sub};

/// A real number.
pub trait Real: Copy + Add<Output=Self> + Div<Output=Self> + Mul<Output=Self> + Sub<Output=Self> {
    /// Return the unity.
    fn one() -> Self;

    /// Return the zero.
    fn zero() -> Self;

    /// Create a real number from a natural one.
    fn from_natural(usize) -> Self;
}

/// A means of converting an arbitrary quantity to a real number.
pub trait ToReal<T: Real> {
    /// Convert to a real number.
    fn to_real(&self) -> T;
}

macro_rules! implement {
    ($($kind:ty),*) => (
        $(
            impl Real for $kind {
                #[inline(always)]
                fn one() -> Self { 1.0 }

                #[inline(always)]
                fn zero() -> Self { 0.0 }

                #[inline(always)]
                fn from_natural(number: usize) -> Self { number as $kind }
            }
        )*
    );
}

implement!(f32, f64);

macro_rules! implement {
    ($($kind:ty => $real:ty,)*) => (
        $(
            impl ToReal<$real> for $kind {
                #[inline(always)]
                fn to_real(&self) -> $real { *self as $real }
            }
        )*
    );
}

implement! {
    u8 => f32,
    u8 => f64,

    u16 => f32,
    u16 => f64,

    u32 => f32,
    u32 => f64,

    u64 => f32,
    u64 => f64,

    i8 => f32,
    i8 => f64,

    i16 => f32,
    i16 => f64,

    i32 => f32,
    i32 => f64,

    i64 => f32,
    i64 => f64,

    f32 => f32,
    f64 => f64,

    isize => f32,
    isize => f64,

    usize => f32,
    usize => f64,
}
<|endoftext|>


<commit_before>use die::Die;
use die::DieType;
use uuid::Uuid;

#[derive(Debug, Deserialize, Serialize)]
pub struct Roll {
    /// Unique identifier for the roll
    pub _id: String,

    /// The dice that compose this roll
    pub dice: Vec<Die>,

    /// Modifiers to apply to the combined value
    pub modifiers: Vec<i8>,

    /// The combined value of the die before modifiers
    pub raw_value: i16,

    /// The associated token (optional)
    pub token: Option<String>,

    /// The final combined value of the die after modifiers
    pub value: i16,
}

impl Roll {
    pub fn new(mut dice: Vec<Die>) -> Roll {
        // Roll each dice
        for die in &mut dice {
            die.roll();
        }

        let value = dice.iter().fold(0, |sum, d| sum + d.value as i16);

        Roll {
            _id: Uuid::new_v4().to_string(),
            dice,
            modifiers: Vec::new(),
            raw_value: value,
            token: None,
            value,
        }
    }

    /// Associate this roll with a token
    pub fn add_token(&mut self, token: String) {
        self.token = Some(token)
    }

    /// Keep the highest rolled dice
    pub fn keep_high(&mut self, keep: u8) {
        // Sort the dice by value, drop everything below the keep value
        let mut count = 0;
        self.dice.sort_by(|a, b| b.value.cmp(&a.value));
        for die in &mut self.dice {
            if count >= keep {
                die.drop();
                self.value -= die.value as i16;
            }
            count += 1;
        }
        // sort by timestamp again before finishing the method
        self.dice.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
    }

    /// Keep the lowest rolled dice
    pub fn keep_low(&mut self, keep: u8) {
        // Sort the dice by value, drop everything below the keep value
        let mut count = 0;
        self.dice.sort_by(|a, b| a.value.cmp(&b.value));
        for die in &mut self.dice {
            if count >= keep {
                die.drop();
                self.value -= die.value as i16;
            }
            count += 1;
        }
        // sort by timestamp again before finishing the method
        self.dice.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
    }

    pub fn reroll_dice_once_below(&mut self, threshold: u8) {
    }

    pub fn reroll_dice_forever_below(&mut self, threshold: u8) {
    }
}

fn roll_type(count: i8, die: DieType) -> Roll {
    let mut dice = Vec::new();
    for _ in 0..count {
        dice.push(Die::new(die));
    }
    Roll::new(dice)
}

pub fn roll_d20(count: i8) -> Roll {
    roll_type(count, DieType::D20)
}

pub fn roll_d12(count: i8) -> Roll {
    roll_type(count, DieType::D12)
}

pub fn roll_d10(count: i8) -> Roll {
    roll_type(count, DieType::D10)
}

pub fn roll_d8(count: i8) -> Roll {
    roll_type(count, DieType::D8)
}

pub fn roll_d6(count: i8) -> Roll {
    roll_type(count, DieType::D6)
}

pub fn roll_d4(count: i8) -> Roll {
    roll_type(count, DieType::D4)
}

pub fn roll_and_keep_high(count: i8, die: DieType, keep: u8) -> Roll {
    let mut roll = roll_type(count, die);
    roll.keep_high(keep);
    roll
}

pub fn roll_and_keep_low(count: i8, die: DieType, keep: u8) -> Roll {
    let mut roll = roll_type(count, die);
    roll.keep_low(keep);
    roll
}

pub fn roll_with_advantage() -> Roll {
    let mut roll = roll_d20(2);
    roll.keep_high(1);
    roll
}

pub fn roll_with_disadvantage() -> Roll {
    let mut roll = roll_d20(2);
    roll.keep_low(1);
    roll
}
<commit_msg>formatting roll<commit_after>use die::Die;
use die::DieType;
use uuid::Uuid;

#[derive(Debug, Deserialize, Serialize)]
pub struct Roll {
    /// Unique identifier for the roll
    pub _id: String,

    /// The dice that compose this roll
    pub dice: Vec<Die>,

    /// Modifiers to apply to the combined value
    pub modifiers: Vec<i8>,

    /// The combined value of the die before modifiers
    pub raw_value: i16,

    /// The associated token (optional)
    pub token: Option<String>,

    /// The final combined value of the die after modifiers
    pub value: i16,
}

impl Roll {
    pub fn new(mut dice: Vec<Die>) -> Roll {
        // Roll each dice
        for die in &mut dice {
            die.roll();
        }

        let value = dice.iter().fold(0, |sum, d| sum + d.value as i16);

        Roll {
            _id: Uuid::new_v4().to_string(),
            dice,
            modifiers: Vec::new(),
            raw_value: value,
            token: None,
            value,
        }
    }

    /// Associate this roll with a token
    pub fn add_token(&mut self, token: String) {
        self.token = Some(token)
    }

    /// Keep the highest rolled dice
    pub fn keep_high(&mut self, keep: u8) {
        // Sort the dice by value, drop everything below the keep value
        let mut count = 0;
        self.dice.sort_by(|a, b| b.value.cmp(&a.value));
        for die in &mut self.dice {
            if count >= keep {
                die.drop();
                self.value -= die.value as i16;
            }
            count += 1;
        }
        // sort by timestamp again before finishing the method
        self.dice.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
    }

    /// Keep the lowest rolled dice
    pub fn keep_low(&mut self, keep: u8) {
        // Sort the dice by value, drop everything below the keep value
        let mut count = 0;
        self.dice.sort_by(|a, b| a.value.cmp(&b.value));
        for die in &mut self.dice {
            if count >= keep {
                die.drop();
                self.value -= die.value as i16;
            }
            count += 1;
        }
        // sort by timestamp again before finishing the method
        self.dice.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
    }

    pub fn reroll_dice_once_below(&mut self, threshold: u8) {
    }

    pub fn reroll_dice_forever_below(&mut self, threshold: u8) {
    }
}

pub fn roll_and_keep_high(count: i8, die: DieType, keep: u8) -> Roll {
    let mut roll = roll_type(count, die);
    roll.keep_high(keep);
    roll
}

pub fn roll_and_keep_low(count: i8, die: DieType, keep: u8) -> Roll {
    let mut roll = roll_type(count, die);
    roll.keep_low(keep);
    roll
}

pub fn roll_d4(count: i8) -> Roll {
    roll_type(count, DieType::D4)
}

pub fn roll_d6(count: i8) -> Roll {
    roll_type(count, DieType::D6)
}

pub fn roll_d8(count: i8) -> Roll {
    roll_type(count, DieType::D8)
}

pub fn roll_d10(count: i8) -> Roll {
    roll_type(count, DieType::D10)
}

pub fn roll_d12(count: i8) -> Roll {
    roll_type(count, DieType::D12)
}

pub fn roll_d20(count: i8) -> Roll {
    roll_type(count, DieType::D20)
}

fn roll_type(count: i8, die: DieType) -> Roll {
    let mut dice = Vec::new();
    for _ in 0..count {
        dice.push(Die::new(die));
    }
    Roll::new(dice)
}

pub fn roll_with_advantage() -> Roll {
    let mut roll = roll_d20(2);
    roll.keep_high(1);
    roll
}

pub fn roll_with_disadvantage() -> Roll {
    let mut roll = roll_d20(2);
    roll.keep_low(1);
    roll
}
<|endoftext|>


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

use {
    Whitespace,
    Token,
    UntilAny,
    UntilAnyOrWhitespace,
    Text,
    Number,
    NodeRef,
    NodeVisit,
    ParseError,
    ParseResult,
    Select,
    SeparatedBy,
    Repeat,
    Lines,
    Sequence,
    Optional,
    Tokenizer,
    TokenizerState,
};

/// A rule describes how some section of a document should be parsed.
#[derive(Clone)]
pub enum Rule {
    /// Read whitespace.
    Whitespace(Whitespace),
    /// Match against a token.
    Token(Token),
    /// Reads until any character.
    UntilAny(UntilAny),
    /// Read until any character or whitespace.
    UntilAnyOrWhitespace(UntilAnyOrWhitespace),
    /// Read text.
    Text(Text),
    /// Read number.
    Number(Number),
    /// Select one of the sub rules.
    /// If the first one does not succeed, try another and so on.
    /// If all sub rules fail, then the rule fails.
    Select(Select),
    /// Run each sub rule in sequence.
    /// If any sub rule fails, the rule fails.
    Sequence(Sequence),
    /// Repeat rule separated by another rule.
    SeparatedBy(Box<SeparatedBy>),
    /// Repeat rule.
    Repeat(Box<Repeat>),
    /// Repeat rule separated by one or more lines.
    Lines(Box<Lines>),
    /// Read node.
    Node(NodeRef),
    /// Read optional.
    Optional(Box<Optional>),
}

impl Rule {
    /// Parses rule.
    pub fn parse(
        &self,
        tokenizer: &mut Tokenizer,
        state: &TokenizerState,
        chars: &[char],
        offset: usize,
        refs: &[(Rc<String>, Rc<RefCell<Rule>>)]
    ) -> ParseResult<TokenizerState> {
        match self {
            &Rule::Whitespace(ref w) => {
                w.parse(chars, offset).map(|r| (r, state.clone(), None))
            }
            &Rule::Token(ref t) => {
                t.parse(tokenizer, state, chars, offset)
            }
            &Rule::UntilAny(ref u) => {
                u.parse(tokenizer, state, chars, offset)
            }
            &Rule::UntilAnyOrWhitespace(ref u) => {
                u.parse(tokenizer, state, chars, offset)
            }
            &Rule::Text(ref t) => {
                t.parse(tokenizer, state, chars, offset)
            }
            &Rule::Number(ref n) => {
                n.parse(tokenizer, state, chars, offset)
            }
            &Rule::Select(ref s) => {
                s.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Sequence(ref s) => {
                s.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::SeparatedBy(ref s) => {
                s.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Repeat(ref r) => {
                r.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Lines(ref l) => {
                l.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Node(ref p) => {
                match p.index.get() {
                    None => {
                        Err((
                            Range::empty(offset),
                            ParseError::InvalidRule(
                                "Node rule is not updated to reference",
                                p.debug_id
                            )
                        ))
                    }
                    Some(i) => {
                        refs[i].1.borrow().parse(
                            tokenizer, state, chars, offset, refs
                        )
                    }
                }
            }
            &Rule::Optional(ref o) => {
                Ok(o.parse(tokenizer, state, chars, offset, refs))
            }
        }
    }

    /// Updates replacing names with the references.
    ///
    /// The references contains the name,
    /// but this can not be borrowed as when the same reference is updated.
    pub fn update_refs(&mut self, refs: &[(Rc<String>, Rc<RefCell<Rule>>)]) {
        match self {
            &mut Rule::Node(ref mut p) => {
                use std::cell::BorrowState;

                match p.index.get() {
                    None => {
                        // Look through references and update if correct name
                        // is found.
                        let mut found: Option<usize> = None;
                        for (i, r) in refs.iter().enumerate() {
                            if &**p.name == &*r.0 {
                                found = Some(i);
                                break;
                            }
                        }
                        match found {
                            None => { return; }
                            Some(i) => {
                                p.index.set(Some(i));
                                p.node_visit.set(NodeVisit::Visited);
                                let q = &refs[i].1;
                                if q.borrow_state() == BorrowState::Unused {
                                    q.borrow_mut().update_refs(refs);
                                }
                                return;
                            }
                        }
                    }
                    Some(i) => {
                        // Update the sub rules of the reference,
                        // but only if it has not been visited.
                        if let NodeVisit::Unvisited = p.node_visit.get() {
                            p.node_visit.set(NodeVisit::Visited);
                            let q = &refs[i].1;
                            if q.borrow_state() == BorrowState::Unused {
                                q.borrow_mut().update_refs(refs);
                            }
                        }
                        return;
                    }
                };
            }
            &mut Rule::Whitespace(_) => {}
            &mut Rule::Token(_) => {}
            &mut Rule::UntilAny(_) => {}
            &mut Rule::UntilAnyOrWhitespace(_) => {}
            &mut Rule::Text(_) => {}
            &mut Rule::Number(_) => {}
            &mut Rule::Select(ref mut s) => {
                for sub_rule in &mut s.args {
                    sub_rule.update_refs(refs);
                }
            }
            &mut Rule::Sequence(ref mut s) => {
                for sub_rule in &mut s.args {
                    sub_rule.update_refs(refs);
                }
            }
            &mut Rule::SeparatedBy(ref mut s) => {
                s.rule.update_refs(refs);
                s.by.update_refs(refs);
            }
            &mut Rule::Repeat(ref mut r) => {
                r.rule.update_refs(refs);
            }
            &mut Rule::Lines(ref mut l) => {
                l.rule.update_refs(refs);
            }
            &mut Rule::Optional(ref mut o) => {
                o.rule.update_refs(refs);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::*;
    use std::rc::Rc;
    use std::cell::RefCell;
    use std::cell::Cell;

    #[test]
    fn node_ref() {
        // Create a node rule the refers to itself.
        let foo: Rc<String> = Rc::new("foo".into());
        let num: Rc<String> = Rc::new("num".into());
        let node = Rc::new(RefCell::new(Rule::Sequence(Sequence {
            debug_id: 1,
            args: vec![
                Rule::Number(Number {
                    debug_id: 2,
                    property: Some(num.clone()),
                    allow_underscore: false,
                }),
                Rule::Optional(Box::new(Optional {
                    debug_id: 3,
                    rule: Rule::Sequence(Sequence {
                        debug_id: 4,
                        args: vec![
                            Rule::Whitespace(Whitespace {
                                debug_id: 3,
                                optional: false
                            }),
                            Rule::Node(NodeRef {
                                name: foo.clone(),
                                debug_id: 3,
                                index: Cell::new(None),
                                node_visit: Cell::new(NodeVisit::Unvisited)
                            }),
                        ]
                    }),
                })),
            ],
        })));

        // Replace self referencing names with direct references.
        let refs = vec![(foo.clone(), node.clone())];
        let mut rules = Rule::Node(NodeRef {
            name: foo.clone(),
            debug_id: 0,
            index: Cell::new(None),
            node_visit: Cell::new(NodeVisit::Unvisited)
        });
        rules.update_refs(&refs);

        let text = "1 2 3";
        let data = parse(&rules, &refs, text).unwrap();
        assert_eq!(data.len(), 3);
        assert_eq!(&data[0].1, &MetaData::F64(num.clone(), 1.0));
        assert_eq!(&data[1].1, &MetaData::F64(num.clone(), 2.0));
        assert_eq!(&data[2].1, &MetaData::F64(num.clone(), 3.0));
    }
}
<commit_msg>Make `update_refs` take `&self`<commit_after>use range::Range;
use std::rc::Rc;
use std::cell::RefCell;

use {
    Whitespace,
    Token,
    UntilAny,
    UntilAnyOrWhitespace,
    Text,
    Number,
    NodeRef,
    NodeVisit,
    ParseError,
    ParseResult,
    Select,
    SeparatedBy,
    Repeat,
    Lines,
    Sequence,
    Optional,
    Tokenizer,
    TokenizerState,
};

/// A rule describes how some section of a document should be parsed.
#[derive(Clone)]
pub enum Rule {
    /// Read whitespace.
    Whitespace(Whitespace),
    /// Match against a token.
    Token(Token),
    /// Reads until any character.
    UntilAny(UntilAny),
    /// Read until any character or whitespace.
    UntilAnyOrWhitespace(UntilAnyOrWhitespace),
    /// Read text.
    Text(Text),
    /// Read number.
    Number(Number),
    /// Select one of the sub rules.
    /// If the first one does not succeed, try another and so on.
    /// If all sub rules fail, then the rule fails.
    Select(Select),
    /// Run each sub rule in sequence.
    /// If any sub rule fails, the rule fails.
    Sequence(Sequence),
    /// Repeat rule separated by another rule.
    SeparatedBy(Box<SeparatedBy>),
    /// Repeat rule.
    Repeat(Box<Repeat>),
    /// Repeat rule separated by one or more lines.
    Lines(Box<Lines>),
    /// Read node.
    Node(NodeRef),
    /// Read optional.
    Optional(Box<Optional>),
}

impl Rule {
    /// Parses rule.
    pub fn parse(
        &self,
        tokenizer: &mut Tokenizer,
        state: &TokenizerState,
        chars: &[char],
        offset: usize,
        refs: &[(Rc<String>, Rc<RefCell<Rule>>)]
    ) -> ParseResult<TokenizerState> {
        match self {
            &Rule::Whitespace(ref w) => {
                w.parse(chars, offset).map(|r| (r, state.clone(), None))
            }
            &Rule::Token(ref t) => {
                t.parse(tokenizer, state, chars, offset)
            }
            &Rule::UntilAny(ref u) => {
                u.parse(tokenizer, state, chars, offset)
            }
            &Rule::UntilAnyOrWhitespace(ref u) => {
                u.parse(tokenizer, state, chars, offset)
            }
            &Rule::Text(ref t) => {
                t.parse(tokenizer, state, chars, offset)
            }
            &Rule::Number(ref n) => {
                n.parse(tokenizer, state, chars, offset)
            }
            &Rule::Select(ref s) => {
                s.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Sequence(ref s) => {
                s.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::SeparatedBy(ref s) => {
                s.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Repeat(ref r) => {
                r.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Lines(ref l) => {
                l.parse(tokenizer, state, chars, offset, refs)
            }
            &Rule::Node(ref p) => {
                match p.index.get() {
                    None => {
                        Err((
                            Range::empty(offset),
                            ParseError::InvalidRule(
                                "Node rule is not updated to reference",
                                p.debug_id
                            )
                        ))
                    }
                    Some(i) => {
                        refs[i].1.borrow().parse(
                            tokenizer, state, chars, offset, refs
                        )
                    }
                }
            }
            &Rule::Optional(ref o) => {
                Ok(o.parse(tokenizer, state, chars, offset, refs))
            }
        }
    }

    /// Updates replacing names with the references.
    ///
    /// The references contains the name,
    /// but this can not be borrowed as when the same reference is updated.
    pub fn update_refs(&self, refs: &[(Rc<String>, Rc<RefCell<Rule>>)]) {
        match self {
            &Rule::Node(ref p) => {
                use std::cell::BorrowState;

                match p.index.get() {
                    None => {
                        // Look through references and update if correct name
                        // is found.
                        let mut found: Option<usize> = None;
                        for (i, r) in refs.iter().enumerate() {
                            if &**p.name == &*r.0 {
                                found = Some(i);
                                break;
                            }
                        }
                        match found {
                            None => { return; }
                            Some(i) => {
                                p.index.set(Some(i));
                                p.node_visit.set(NodeVisit::Visited);
                                let q = &refs[i].1;
                                if q.borrow_state() == BorrowState::Unused {
                                    q.borrow_mut().update_refs(refs);
                                }
                                return;
                            }
                        }
                    }
                    Some(i) => {
                        // Update the sub rules of the reference,
                        // but only if it has not been visited.
                        if let NodeVisit::Unvisited = p.node_visit.get() {
                            p.node_visit.set(NodeVisit::Visited);
                            let q = &refs[i].1;
                            if q.borrow_state() == BorrowState::Unused {
                                q.borrow_mut().update_refs(refs);
                            }
                        }
                        return;
                    }
                };
            }
            &Rule::Whitespace(_) => {}
            &Rule::Token(_) => {}
            &Rule::UntilAny(_) => {}
            &Rule::UntilAnyOrWhitespace(_) => {}
            &Rule::Text(_) => {}
            &Rule::Number(_) => {}
            &Rule::Select(ref s) => {
                for sub_rule in &s.args {
                    sub_rule.update_refs(refs);
                }
            }
            &Rule::Sequence(ref s) => {
                for sub_rule in &s.args {
                    sub_rule.update_refs(refs);
                }
            }
            &Rule::SeparatedBy(ref s) => {
                s.rule.update_refs(refs);
                s.by.update_refs(refs);
            }
            &Rule::Repeat(ref r) => {
                r.rule.update_refs(refs);
            }
            &Rule::Lines(ref l) => {
                l.rule.update_refs(refs);
            }
            &Rule::Optional(ref o) => {
                o.rule.update_refs(refs);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::*;
    use std::rc::Rc;
    use std::cell::RefCell;
    use std::cell::Cell;

    #[test]
    fn node_ref() {
        // Create a node rule the refers to itself.
        let foo: Rc<String> = Rc::new("foo".into());
        let num: Rc<String> = Rc::new("num".into());
        let node = Rc::new(RefCell::new(Rule::Sequence(Sequence {
            debug_id: 1,
            args: vec![
                Rule::Number(Number {
                    debug_id: 2,
                    property: Some(num.clone()),
                    allow_underscore: false,
                }),
                Rule::Optional(Box::new(Optional {
                    debug_id: 3,
                    rule: Rule::Sequence(Sequence {
                        debug_id: 4,
                        args: vec![
                            Rule::Whitespace(Whitespace {
                                debug_id: 3,
                                optional: false
                            }),
                            Rule::Node(NodeRef {
                                name: foo.clone(),
                                debug_id: 3,
                                index: Cell::new(None),
                                node_visit: Cell::new(NodeVisit::Unvisited)
                            }),
                        ]
                    }),
                })),
            ],
        })));

        // Replace self referencing names with direct references.
        let refs = vec![(foo.clone(), node.clone())];
        let rules = Rule::Node(NodeRef {
            name: foo.clone(),
            debug_id: 0,
            index: Cell::new(None),
            node_visit: Cell::new(NodeVisit::Unvisited)
        });
        rules.update_refs(&refs);

        let text = "1 2 3";
        let data = parse(&rules, &refs, text).unwrap();
        assert_eq!(data.len(), 3);
        assert_eq!(&data[0].1, &MetaData::F64(num.clone(), 1.0));
        assert_eq!(&data[1].1, &MetaData::F64(num.clone(), 2.0));
        assert_eq!(&data[2].1, &MetaData::F64(num.clone(), 3.0));
    }
}
<|endoftext|>


<commit_before>extern crate "pkg-config" as pkg_config;
extern crate gcc;

use std::path::PathBuf;

fn main() {
    let root = PathBuf::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
        .join("libogg");

    println!("cargo:include={}", root.join("include").display());

    match pkg_config::find_library("ogg") {
        Ok(_) => return,
        Err(..) => {}
    };

    gcc::Config::new()
                .file("libogg/src/bitwise.c")
                .file("libogg/src/framing.c")
                .define("_USRDLL", None)
                .define("LIBOGG_EXPORTS", None)
                .include(&root.join("include"))
                .compile("libogg.a");
}
<commit_msg>Follow rustc 1.7.0<commit_after>extern crate pkg_config;
extern crate gcc;

use std::path::PathBuf;

fn main() {
    let root = PathBuf::from(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
        .join("libogg");

    println!("cargo:include={}", root.join("include").display());

    match pkg_config::find_library("ogg") {
        Ok(_) => return,
        Err(..) => {}
    };

    gcc::Config::new()
                .file("libogg/src/bitwise.c")
                .file("libogg/src/framing.c")
                .define("_USRDLL", None)
                .define("LIBOGG_EXPORTS", None)
                .include(&root.join("include"))
                .compile("libogg.a");
}
<|endoftext|>