<commit_before>use regex::Regex;
use std::path::PathBuf;
use std::result::Result;
use subprocess::{Exec, Redirection};

const LOOP_BACKING_DEVICE_BASENAME: &'static str = "flaglock6-home";
const LOOP_DEVICE_PARTITION_LABEL: &'static str = "fl6";
const RSYNC_DOT_NET_REMOTE_DIR: &'static str = "usw-s007.rsync.net:./";

#[derive(Debug)]
pub enum AuricError {
    Invocation(String),
    Io(String),
    Subprocess(String),
    NotFound,
}

enum AuricOperationMode {
    Mount,
    Unmount,
}

impl From<subprocess::PopenError> for AuricError {
    fn from(err: subprocess::PopenError) -> AuricError {
        AuricError::Subprocess(err.to_string())
    }
}

struct SshfsManager {
    mountpoint: PathBuf,
}

struct LoopManager {
    target: Regex,
    backing: PathBuf,
}

struct LuksManager {
    device: PathBuf,
}

struct AuricImpl {
    sshfs_manager: SshfsManager,
    loop_manager: LoopManager,
    luks_manager: LuksManager,
}

impl SshfsManager {
    pub fn new() -> Result<SshfsManager, AuricError> {
        let xdg_runtime_dir = match std::env::var("XDG_RUNTIME_DIR") {
            Ok(val) => val,
            Err(e) => {
                return Err(AuricError::Invocation(format!(
                    "fatal error getting ${{XDG_RUNTIME_DIR}}: ``{}''",
                    e
                )))
            }
        };
        let mut mountpoint = PathBuf::new();
        mountpoint.push(xdg_runtime_dir);
        mountpoint.push("rsync.net-mountpoint");

        Ok(SshfsManager {
            mountpoint: mountpoint,
        })
    }

    fn ensure_mountpoint_is_dir(&self) -> Result<(), AuricError> {
        if self.mountpoint.is_dir() {
            return Ok(());
        }
        std::fs::create_dir(self.mountpoint.as_path())
            .map_err(|e| AuricError::Io(format!("bad mountpoint: ``{}''", e)))
    }

    // Does _not_ ensure that backing device exists.
    pub fn loop_backing_device_path(&self) -> PathBuf {
        let mut result: PathBuf = self.mountpoint.clone();
        result.push(LOOP_BACKING_DEVICE_BASENAME);
        result
    }

    fn loop_backing_device_present(&self) -> bool {
        self.loop_backing_device_path().is_file()
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        self.ensure_mountpoint_is_dir()?;
        if self.loop_backing_device_present() {
            return Ok(());
        }

        // Invoke `sshfs`
        // *    with compression and
        // *    allowing other users to access the mounted filesystem
        //      (necessary to allow loop-mounts).
        let result = Exec::cmd("sshfs")
            .arg("-C")
            .arg("-o")
            .arg("allow_other")
            .arg(RSYNC_DOT_NET_REMOTE_DIR)
            .arg(&self.mountpoint)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "sshfs failed: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        if !self.loop_backing_device_present() {
            return Ok(());
        }

        let result = Exec::cmd("fusermount")
            .arg("-u")
            .arg(&self.mountpoint)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "fusermount -u failed: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

impl LoopManager {
    pub fn new(backing: &PathBuf) -> LoopManager {
        let target = format!(
            r"^(/dev/loop\d)(\s+\d+){{4}}\s+({})\s+",
            backing.to_str().unwrap()
        );
        LoopManager {
            target: Regex::new(&target).unwrap(),
            backing: backing.clone(),
        }
    }

    pub fn find(&self) -> Result<PathBuf, AuricError> {
        let result = Exec::cmd("losetup")
            .arg("-l")
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to list loop devices: ``{}''",
                result.stderr_str()
            )));
        }

        for line in result.stdout_str().lines() {
            if let Some(captures) = self.target.captures(line) {
                return Ok(PathBuf::from(captures.get(1).unwrap().as_str()));
            }
        }
        Err(AuricError::NotFound)
    }

    pub fn attach(&self) -> Result<(), AuricError> {
        if let Ok(_attached_loop) = self.find() {
            return Ok(());
        }

        let result = Exec::cmd("udisksctl")
            .arg("loop-setup")
            .arg("-f")
            .arg(&self.backing)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to attach loop device: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }

    // Note that the loop device will linger if the volume remains
    // unlocked. Prefer not to call this before locking.
    pub fn detach(&self) -> Result<(), AuricError> {
        let attached_loop = match self.find() {
            Ok(path) => path,
            Err(e) => {
                if let AuricError::NotFound = e {
                    return Ok(());
                }
                return Err(e);
            }
        };
        let result = Exec::cmd("udisksctl")
            .arg("loop-delete")
            .arg("-b")
            .arg(&attached_loop)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to detach loop device: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

impl LuksManager {
    pub fn new() -> LuksManager {
        let mut device = PathBuf::from("/dev/disk/by-label");
        device.push(LOOP_DEVICE_PARTITION_LABEL);
        LuksManager { device: device }
    }

    pub fn unlock(&self, locked_device: &PathBuf) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("unlock")
            .arg("-b")
            .arg(locked_device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to unlock {}: ``{}''",
                locked_device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn lock(&self, underlying_device: &PathBuf) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("lock")
            .arg("-b")
            .arg(underlying_device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to lock {}: ``{}''",
                underlying_device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("mount")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to mount {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("unmount")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to unmount {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

fn get_action() -> Result<AuricOperationMode, AuricError> {
    let mut args_iter = std::env::args();
    args_iter.next();
    if let Some(action) = args_iter.next() {
        match action.as_str() {
            "mount" => return Ok(AuricOperationMode::Mount),
            "unmount" => return Ok(AuricOperationMode::Unmount),
            _ => {
                return Err(AuricError::Invocation(format!(
                    "unknown action: ``{}''",
                    action
                )))
            }
        }
    }
    Err(AuricError::Invocation("no action given".to_string()))
}

impl AuricImpl {
    pub fn new() -> Result<AuricImpl, AuricError> {
        let sshfs_manager = SshfsManager::new()?;
        let loop_backing_device_path = sshfs_manager.loop_backing_device_path();
        Ok(AuricImpl {
            sshfs_manager: sshfs_manager,
            loop_manager: LoopManager::new(&loop_backing_device_path),
            luks_manager: LuksManager::new(),
        })
    }

    fn mount(&self) -> Result<(), AuricError> {
        self.sshfs_manager.mount()?;
        self.loop_manager.attach()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.unlock(&loop_device)?;
        self.luks_manager.mount()
    }

    fn unmount(&self) -> Result<(), AuricError> {
        self.luks_manager.unmount()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.lock(&loop_device)?;
        self.loop_manager.detach()?;
        self.sshfs_manager.unmount()
    }

    pub fn act(&self, mode: AuricOperationMode) -> Result<(), AuricError> {
        match mode {
            AuricOperationMode::Mount => return self.mount(),
            AuricOperationMode::Unmount => return self.unmount(),
        }
    }
}

fn main_impl() -> Result<(), AuricError> {
    let action = get_action()?;
    let auric_impl = AuricImpl::new()?;
    auric_impl.act(action)
}

fn main() {
    std::process::exit(match main_impl() {
        Ok(_) => 0,
        Err(e) => {
            eprintln!("{:?}", e);
            1
        }
    });
}
<commit_msg>apricot-auric: Centralize subprocess handling<commit_after>use regex::Regex;
use std::path::PathBuf;
use std::result::Result;
use subprocess::{Exec, Redirection};

const LOOP_BACKING_DEVICE_BASENAME: &'static str = "flaglock6-home";
const LOOP_DEVICE_PARTITION_LABEL: &'static str = "fl6";
const RSYNC_DOT_NET_REMOTE_DIR: &'static str = "usw-s007.rsync.net:./";

#[derive(Debug)]
pub enum AuricError {
    Invocation(String),
    Io(String),
    Subprocess(String),
    NotFound,
}

enum AuricOperationMode {
    Mount,
    Unmount,
}

impl From<subprocess::PopenError> for AuricError {
    fn from(err: subprocess::PopenError) -> AuricError {
        AuricError::Subprocess(err.to_string())
    }
}

struct SshfsManager {
    mountpoint: PathBuf,
}

struct LoopManager {
    target: Regex,
    backing: PathBuf,
}

struct LuksManager {
    device: PathBuf,
}

struct AuricImpl {
    sshfs_manager: SshfsManager,
    loop_manager: LoopManager,
    luks_manager: LuksManager,
}

fn exec_with_stdout(command: &str, args: &[&str], error_hint: &str) -> Result<String, AuricError> {
    let result = Exec::cmd(command)
        .args(args)
        .stdout(Redirection::Pipe)
        .stderr(Redirection::Pipe)
        .capture()?;
    if !result.success() {
        return Err(AuricError::Subprocess(format!(
            "{} failed: ``{}''",
            error_hint,
            result.stderr_str(),
        )));
    }
    Ok(result.stdout_str())
}

fn exec(command: &str, args: &[&str], error_hint: &str) -> Result<(), AuricError> {
    exec_with_stdout(command, args, error_hint).map(|_stdout_str| ())
}

impl SshfsManager {
    pub fn new() -> Result<SshfsManager, AuricError> {
        let xdg_runtime_dir = match std::env::var("XDG_RUNTIME_DIR") {
            Ok(val) => val,
            Err(e) => {
                return Err(AuricError::Invocation(format!(
                    "fatal error getting ${{XDG_RUNTIME_DIR}}: ``{}''",
                    e
                )))
            }
        };
        let mut mountpoint = PathBuf::new();
        mountpoint.push(xdg_runtime_dir);
        mountpoint.push("rsync.net-mountpoint");

        Ok(SshfsManager {
            mountpoint: mountpoint,
        })
    }

    fn ensure_mountpoint_is_dir(&self) -> Result<(), AuricError> {
        if self.mountpoint.is_dir() {
            return Ok(());
        }
        std::fs::create_dir(self.mountpoint.as_path())
            .map_err(|e| AuricError::Io(format!("bad mountpoint: ``{}''", e)))
    }

    // Does _not_ ensure that backing device exists.
    pub fn loop_backing_device_path(&self) -> PathBuf {
        let mut result: PathBuf = self.mountpoint.clone();
        result.push(LOOP_BACKING_DEVICE_BASENAME);
        result
    }

    fn loop_backing_device_present(&self) -> bool {
        self.loop_backing_device_path().is_file()
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        self.ensure_mountpoint_is_dir()?;
        if self.loop_backing_device_present() {
            return Ok(());
        }

        // Invoke `sshfs`
        // *    with compression and
        // *    allowing other users to access the mounted filesystem
        //      (necessary to allow loop-mounts).
        exec(
            "sshfs",
            &[
                "-C",
                "-o",
                "allow_other",
                RSYNC_DOT_NET_REMOTE_DIR,
                self.mountpoint.to_str().unwrap(),
            ],
            "sshfs mount",
        )
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        if !self.loop_backing_device_present() {
            return Ok(());
        }
        exec(
            "fusermount",
            &["-u", self.mountpoint.to_str().unwrap()],
            "fusermount -u",
        )
    }
}

impl LoopManager {
    pub fn new(backing: &PathBuf) -> LoopManager {
        let target = format!(
            r"^(/dev/loop\d)(\s+\d+){{4}}\s+({})\s+",
            backing.to_str().unwrap()
        );
        LoopManager {
            target: Regex::new(&target).unwrap(),
            backing: backing.clone(),
        }
    }

    pub fn find(&self) -> Result<PathBuf, AuricError> {
        let losetup_stdout = exec_with_stdout("losetup", &["-l"], "loop device enumeration")?;
        for line in losetup_stdout.lines() {
            if let Some(captures) = self.target.captures(line) {
                return Ok(PathBuf::from(captures.get(1).unwrap().as_str()));
            }
        }
        Err(AuricError::NotFound)
    }

    pub fn attach(&self) -> Result<(), AuricError> {
        if let Ok(_attached_loop) = self.find() {
            return Ok(());
        }

        exec(
            "udisksctl",
            &["loop-setup", "-f", self.backing.to_str().unwrap()],
            "loop device attach",
        )
    }

    // Note that the loop device will linger if the volume remains
    // unlocked. Prefer not to call this before locking.
    pub fn detach(&self) -> Result<(), AuricError> {
        let attached_loop = match self.find() {
            Ok(path) => path,
            Err(e) => {
                if let AuricError::NotFound = e {
                    return Ok(());
                }
                return Err(e);
            }
        };
        exec(
            "udisksctl",
            &["loop-delete", "-b", attached_loop.to_str().unwrap()],
            "loop device detach",
        )
    }
}

impl LuksManager {
    pub fn new() -> LuksManager {
        let mut device = PathBuf::from("/dev/disk/by-label");
        device.push(LOOP_DEVICE_PARTITION_LABEL);
        LuksManager { device: device }
    }

    pub fn unlock(&self, locked_device: &PathBuf) -> Result<(), AuricError> {
        exec(
            "udisksctl",
            &["unlock", "-b", locked_device.to_str().unwrap()],
            format!("unlocking {}", locked_device.to_str().unwrap()).as_str(),
        )
    }

    pub fn lock(&self, underlying_device: &PathBuf) -> Result<(), AuricError> {
        exec(
            "udisksctl",
            &["lock", "-b", underlying_device.to_str().unwrap()],
            format!("locking {}", underlying_device.to_str().unwrap()).as_str(),
        )
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        exec(
            "udisksctl",
            &["mount", "-b", self.device.to_str().unwrap()],
            format!("mounting {}", self.device.to_str().unwrap()).as_str(),
        )
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        exec(
            "udisksctl",
            &["unmount", "-b", self.device.to_str().unwrap()],
            format!("unmounting {}", self.device.to_str().unwrap()).as_str(),
        )
    }
}

fn get_action() -> Result<AuricOperationMode, AuricError> {
    let mut args_iter = std::env::args();
    args_iter.next();
    if let Some(action) = args_iter.next() {
        match action.as_str() {
            "mount" => return Ok(AuricOperationMode::Mount),
            "unmount" => return Ok(AuricOperationMode::Unmount),
            _ => {
                return Err(AuricError::Invocation(format!(
                    "unknown action: ``{}''",
                    action
                )))
            }
        }
    }
    Err(AuricError::Invocation("no action given".to_string()))
}

impl AuricImpl {
    pub fn new() -> Result<AuricImpl, AuricError> {
        let sshfs_manager = SshfsManager::new()?;
        let loop_backing_device_path = sshfs_manager.loop_backing_device_path();
        Ok(AuricImpl {
            sshfs_manager: sshfs_manager,
            loop_manager: LoopManager::new(&loop_backing_device_path),
            luks_manager: LuksManager::new(),
        })
    }

    fn mount(&self) -> Result<(), AuricError> {
        self.sshfs_manager.mount()?;
        self.loop_manager.attach()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.unlock(&loop_device)?;
        self.luks_manager.mount()
    }

    fn unmount(&self) -> Result<(), AuricError> {
        self.luks_manager.unmount()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.lock(&loop_device)?;
        self.loop_manager.detach()?;
        self.sshfs_manager.unmount()
    }

    pub fn act(&self, mode: AuricOperationMode) -> Result<(), AuricError> {
        match mode {
            AuricOperationMode::Mount => return self.mount(),
            AuricOperationMode::Unmount => return self.unmount(),
        }
    }
}

fn main_impl() -> Result<(), AuricError> {
    let action = get_action()?;
    let auric_impl = AuricImpl::new()?;
    auric_impl.act(action)
}

fn main() {
    std::process::exit(match main_impl() {
        Ok(_) => 0,
        Err(e) => {
            eprintln!("{:?}", e);
            1
        }
    });
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Constructor methods for ndarray
//!
use libnum;

use imp_prelude::*;
use dimension;
use linspace;
use error::{self, ShapeError};

/// Constructor methods for one-dimensional arrays.
///
/// Note that the constructor methods apply to `OwnedArray` and `RcArray`,
/// the two array types that have owned storage.
impl<S> ArrayBase<S, Ix>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no copying needed).
    ///
    /// ```rust
    /// use ndarray::OwnedArray;
    ///
    /// let array = OwnedArray::from_vec(vec![1., 2., 3., 4.]);
    /// ```
    pub fn from_vec(v: Vec<S::Elem>) -> ArrayBase<S, Ix> {
        unsafe { Self::from_vec_dim_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    ///
    /// ```rust
    /// use ndarray::OwnedArray;
    /// use ndarray::arr1;
    ///
    /// let iter = (0..5).map(|x| x * x);
    /// let array = OwnedArray::from_iter(iter);
    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
    /// ```
    pub fn from_iter(iterable: I) -> ArrayBase<S, Ix>
        where I: IntoIterator<Item=S::Elem>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from the inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::OwnedArray;
    /// use ndarray::arr1;
    ///
    /// let array = OwnedArray::linspace(0., 1., 5);
    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
    /// ```
    pub fn linspace<F>(start: F, end: F, n: usize) -> ArrayBase<S, Ix>
        where S: Data<Elem=F>,
              F: libnum::Float,
    {
        Self::from_iter(linspace::linspace(start, end, n))
    }

    /// Create a one-dimensional array from the half-open interval
    /// `[start, end)` with elements spaced by `step`. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::OwnedArray;
    /// use ndarray::arr1;
    ///
    /// let array = OwnedArray::range(0., 5., 1.);
    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
    /// ```
    pub fn range<F>(start: F, end: F, step: F) -> ArrayBase<S, Ix>
        where S: Data<Elem=F>,
              F: libnum::Float,
    {
        Self::from_iter(linspace::range(start, end, step))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, (Ix, Ix)>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> ArrayBase<S, (Ix, Ix)>
        where S: DataMut,
              A: Clone + libnum::Zero + libnum::One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    ///
    /// ```
    /// use ndarray::OwnedArray;
    /// use ndarray::arr3;
    ///
    /// let a = OwnedArray::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    /// ```
    pub fn from_elem(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array with copies of `elem`, dimension `dim` and fortran
    /// memory order.
    ///
    /// **Panics** if the number of elements would overflow usize.
    ///
    /// ```
    /// use ndarray::OwnedArray;
    ///
    /// let a = OwnedArray::from_elem_f((2, 2, 2), 1.);
    /// assert!(a.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem_f(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked_f(dim, v) }
    }

    /// Create an array with zeros, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem(dim, libnum::zero())
    }

    /// Create an array with zeros, dimension `dim` and fortran memory order.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros_f(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem_f(dim, libnum::zero())
    }

    /// Create an array with default values, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn default(dim: D) -> ArrayBase<S, D>
        where A: Default
    {
        let v = (0..dim.size()).map(|_| A::default()).collect();
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array from a vector (no copying needed).
    ///
    /// **Errors** if `dim` does not correspond to the number of elements in `v`.
    pub fn from_vec_dim(dim: D, v: Vec) -> Result<ArrayBase<S, D>, ShapeError> {
        if dim.size_checked() != Some(v.len()) {
            return Err(error::incompatible_shapes(&v.len(), &dim));
        }
        unsafe { Ok(Self::from_vec_dim_unchecked(dim, v)) }
    }

    /// Create an array from a vector (no copying needed).
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.default_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector (with no copying needed),
    /// using fortran memory order to interpret the data.
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked_f(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.fortran_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Checks whether `dim` and `strides` are compatible with the vector's
    /// length, returning an `Err` if not compatible.
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    pub fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<ArrayBase<S, D>, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> ArrayBase<S, D>
    {
        debug_assert!(dimension::can_index_slice(&v, &dim, &strides).is_ok());
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}
<commit_msg>Shorten the constructor examples<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Constructor methods for ndarray
//!
use libnum;

use imp_prelude::*;
use dimension;
use linspace;
use error::{self, ShapeError};

/// Constructor methods for one-dimensional arrays.
///
/// Note that the constructor methods apply to `OwnedArray` and `RcArray`,
/// the two array types that have owned storage.
impl<S> ArrayBase<S, Ix>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no copying needed).
    ///
    /// ```rust
    /// use ndarray::OwnedArray;
    ///
    /// let array = OwnedArray::from_vec(vec![1., 2., 3., 4.]);
    /// ```
    pub fn from_vec(v: Vec<S::Elem>) -> ArrayBase<S, Ix> {
        unsafe { Self::from_vec_dim_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    ///
    /// ```rust
    /// use ndarray::{OwnedArray, arr1};
    ///
    /// let array = OwnedArray::from_iter((0..5).map(|x| x * x));
    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
    /// ```
    pub fn from_iter(iterable: I) -> ArrayBase<S, Ix>
        where I: IntoIterator<Item=S::Elem>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from the inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{OwnedArray, arr1};
    ///
    /// let array = OwnedArray::linspace(0., 1., 5);
    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
    /// ```
    pub fn linspace<F>(start: F, end: F, n: usize) -> ArrayBase<S, Ix>
        where S: Data<Elem=F>,
              F: libnum::Float,
    {
        Self::from_iter(linspace::linspace(start, end, n))
    }

    /// Create a one-dimensional array from the half-open interval
    /// `[start, end)` with elements spaced by `step`. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{OwnedArray, arr1};
    ///
    /// let array = OwnedArray::range(0., 5., 1.);
    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
    /// ```
    pub fn range<F>(start: F, end: F, step: F) -> ArrayBase<S, Ix>
        where S: Data<Elem=F>,
              F: libnum::Float,
    {
        Self::from_iter(linspace::range(start, end, step))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, (Ix, Ix)>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> ArrayBase<S, (Ix, Ix)>
        where S: DataMut,
              A: Clone + libnum::Zero + libnum::One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    ///
    /// ```
    /// use ndarray::OwnedArray;
    /// use ndarray::arr3;
    ///
    /// let a = OwnedArray::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    /// ```
    pub fn from_elem(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array with copies of `elem`, dimension `dim` and fortran
    /// memory order.
    ///
    /// **Panics** if the number of elements would overflow usize.
    ///
    /// ```
    /// use ndarray::OwnedArray;
    ///
    /// let a = OwnedArray::from_elem_f((2, 2, 2), 1.);
    /// assert!(a.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem_f(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked_f(dim, v) }
    }

    /// Create an array with zeros, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem(dim, libnum::zero())
    }

    /// Create an array with zeros, dimension `dim` and fortran memory order.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros_f(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem_f(dim, libnum::zero())
    }

    /// Create an array with default values, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn default(dim: D) -> ArrayBase<S, D>
        where A: Default
    {
        let v = (0..dim.size()).map(|_| A::default()).collect();
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array from a vector (no copying needed).
    ///
    /// **Errors** if `dim` does not correspond to the number of elements in `v`.
    pub fn from_vec_dim(dim: D, v: Vec) -> Result<ArrayBase<S, D>, ShapeError> {
        if dim.size_checked() != Some(v.len()) {
            return Err(error::incompatible_shapes(&v.len(), &dim));
        }
        unsafe { Ok(Self::from_vec_dim_unchecked(dim, v)) }
    }

    /// Create an array from a vector (no copying needed).
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.default_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector (with no copying needed),
    /// using fortran memory order to interpret the data.
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked_f(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.fortran_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Checks whether `dim` and `strides` are compatible with the vector's
    /// length, returning an `Err` if not compatible.
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    pub fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<ArrayBase<S, D>, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> ArrayBase<S, D>
    {
        debug_assert!(dimension::can_index_slice(&v, &dim, &strides).is_ok());
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}
<|endoftext|>


<commit_before>use std;
use std::error::Error;
use std::sync::Arc;

pub mod fs_storage;
pub mod ram_storage;

pub type Result<T> = std::result::Result<T, StorageError>;

#[derive(Debug)]
pub enum StorageError{
    KeyNotFound,
    ReadError(Option<std::io::Error>),
    WriteError(Option<std::io::Error>)
}

impl std::fmt::Display for StorageError{

    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }

}

impl Error for StorageError {
    fn description(&self) -> &str {
        match *self {
            StorageError::KeyNotFound => "Key was not found in storage!",
            StorageError::ReadError(_) => "An error occured while trying to read from storage!",
            StorageError::WriteError(_) => "An error occured while trying to write to storage!"
        }
    }

    fn cause(&self) -> Option<&Error>  {
        match *self {
            StorageError::ReadError(Some(ref cause)) => Some(cause),
            StorageError::WriteError(Some(ref cause)) => Some(cause),
            _ => None
        }
    }
}

/// Defines a common interface between multiple storage types
/// The index uses them to store data like the posting lists
//TODO: Needs methods to delete and/or update items
pub trait Storage<T> : Sync {

    /// Tries to get a value for a given Id.
    /// Returns an Error if read fails or if id is unknown.
    fn get(&self, id: u64) -> Result<Arc<T>>;

    /// Tries to store a value with a given Id.
    /// Returns an Error if Write fails or if there is no more space.
    fn store(&mut self, id: u64, data: T) -> Result<()>;
}
<commit_msg>fixed clippy issues<commit_after>use std;
use std::error::Error;
use std::sync::Arc;

pub mod fs_storage;
pub mod ram_storage;

pub type Result<T> = std::result::Result<T, StorageError>;

#[derive(Debug)]
pub enum StorageError {
    KeyNotFound,
    ReadError(Option<std::io::Error>),
    WriteError(Option<std::io::Error>),
}

impl std::fmt::Display for StorageError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl Error for StorageError {
    fn description(&self) -> &str {
        match *self {
            StorageError::KeyNotFound => "Key was not found in storage!",
            StorageError::ReadError(_) => "An error occured while trying to read from storage!",
            StorageError::WriteError(_) => "An error occured while trying to write to storage!",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StorageError::ReadError(Some(ref cause)) |
            StorageError::WriteError(Some(ref cause)) => Some(cause),
            _ => None,
        }
    }
}

/// Defines a common interface between multiple storage types
/// The index uses them to store data like the posting lists
// TODO: Needs methods to delete and/or update items
pub trait Storage<T>: Sync {
    /// Tries to get a value for a given Id.
    /// Returns an Error if read fails or if id is unknown.
    fn get(&self, id: u64) -> Result<Arc<T>>;

    /// Tries to store a value with a given Id.
    /// Returns an Error if Write fails or if there is no more space.
    fn store(&mut self, id: u64, data: T) -> Result<()>;
}
<|endoftext|>


<commit_before>use super::game_manager::GameManager;

use std::sync::Arc;
use std::str::FromStr;

use rustc_serialize::json;

use iron;
use iron::prelude::*;

pub struct Server {
    port: u16,
    manager: Arc<GameManager>,
}

struct Router { manager: Arc<GameManager> }

#[derive(RustcEncodable)]
struct HelpAction {
    href: &'static str,
    help: &'static str,
    method: &'static str,
}

#[derive(RustcEncodable)]
struct HelpMessage {
    title: &'static str,
    actions: Vec<HelpAction>,
}

fn help_message() -> String {

    json::encode(&HelpMessage {
        title: "Help Page",
        actions: vec![
            HelpAction {
                href: "/join",
                method: "POST",
                help: "Join a new game.",
            },
            HelpAction {
                href: "/hand/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current hand.",
            },
            HelpAction {
                href: "/wait/[PLAYER_ID]/[EVENT_ID]",
                method: "GET",
                help: "Wait until the next event, or return it if it already happened.",
            },
        ]
    }).unwrap()
}

fn help_resp() -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();
    return Ok(Response::with((content_type,
                              iron::status::NotFound,
                              help_message())));
}

fn err_resp(msg: &str) -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

    #[derive(RustcEncodable)]
    struct Error<'a>{
        error: &'a str,
    }

    return Ok(Response::with((content_type,
                              iron::status::Ok,
                              json::encode(&Error { error: msg }).unwrap(),
                              )));
}

impl iron::Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        if req.url.path.is_empty() {
            // ?!?
            panic!("Empty request path should never happen.");
        }

        // Weird deref trick to go from &String to &str
        let action: &str = &*req.url.path[0];

        let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

        match req.method {
            iron::method::Options => {
                if ["hand", "trick", "contracts", "last_trick", "scores"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Get,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else if ["pass", "coinche", "bid", "play", "join"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Post,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else {
                    help_resp()
                }
            },
            iron::method::Get => {
                let response = match action {
                    "wait" => {
                        if req.url.path.len() != 3 {
                            return err_resp(&format!("incorrect parameters (Usage: /{}/[PID]/[EID])", action));
                        }
                        let player_id = match u32::from_str(&*req.url.path[1]) {
                            Ok(id) => id,
                            Err(e) => return err_resp(&format!("invalid player ID: `{}` ({})", req.url.path[1], e)),
                        };
                        let event_id = match usize::from_str(&*req.url.path[2]) {
                            Ok(id) => id,
                            Err(e) => return err_resp(&format!("invalid event ID: `{}` ({})", req.url.path[2], e)),
                        };
                        match self.manager.wait(player_id, event_id) {
                            Err(err) => return err_resp(&format!("{}", err)),
                            Ok(event) => json::encode(&event).unwrap(),
                        }
                    },
                    "hand" => {
                        if req.url.path.len() != 2 {
                            return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", action));
                        }
                        let player_id = match u32::from_str(&*req.url.path[1]) {
                            Ok(id) => id,
                            Err(e) => return err_resp(&format!("invalid player ID: `{}` ({})", req.url.path[1], e)),
                        };
                        match self.manager.see_hand(player_id) {
                            Err(err) => return err_resp(&format!("{}", err)),
                            Ok(hand) => json::encode(&hand).unwrap(),
                        }
                    },
                    "trick" => {
                        if req.url.path.len() != 2 {
                            return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", action));
                        }
                        let player_id = match u32::from_str(&*req.url.path[1]) {
                            Ok(id) => id,
                            Err(e) => return err_resp(&format!("invalid player ID: `{}` ({})", req.url.path[1], e)),
                        };
                        match self.manager.see_trick(player_id) {
                            Err(err) => return err_resp(&format!("{}", err)),
                            Ok(trick) => json::encode(&trick).unwrap(),
                        }
                    },
                    "last_trick" => {
                        if req.url.path.len() != 2 {
                            return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", action));
                        }
                        let player_id = match u32::from_str(&*req.url.path[1]) {
                            Ok(id) => id,
                            Err(e) => return err_resp(&format!("invalid player ID: `{}` ({})", req.url.path[1], e)),
                        };
                        match self.manager.see_last_trick(player_id) {
                            Err(err) => return err_resp(&format!("{}", err)),
                            Ok(trick) => json::encode(&trick).unwrap(),
                        }
                    },
                    "scores" => {
                        if req.url.path.len() != 2 {
                            return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", action));
                        }
                        let player_id = match u32::from_str(&*req.url.path[1]) {
                            Ok(id) => id,
                            Err(e) => return err_resp(&format!("invalid player ID: `{}` ({})", req.url.path[1], e)),
                        };
                        match self.manager.see_scores(player_id) {
                            Err(err) => return err_resp(&format!("{}", err)),
                            Ok(trick) => json::encode(&trick).unwrap(),
                        }
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))

            },
            iron::method::Post => {
                // Read the JSON body
                // ...

                let response = match action {
                    "join" => match self.manager.join() {
                        Err(err) => return err_resp(&format!("{}", err)),
                        Ok(info) => json::encode(&info).unwrap(),
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))
            },
            _ => help_resp(),
        }
    }
}

impl Server {
    pub fn new(port: u16) -> Server {
        Server {
            port: port,
            manager: Arc::new(GameManager::new()),
        }
    }

    pub fn run(self) {
        let port = self.port;
        println!("Listening on port {}", port);

        let router = Router { manager: self.manager.clone() };

        Iron::new(router).http(("localhost", port)).unwrap();

    }
}
<commit_msg>Add macro to simplify dispatch<commit_after>use super::game_manager::GameManager;

use std::sync::Arc;
use std::str::FromStr;

use rustc_serialize::json;

use iron;
use iron::prelude::*;

pub struct Server {
    port: u16,
    manager: Arc<GameManager>,
}

struct Router { manager: Arc<GameManager> }

#[derive(RustcEncodable)]
struct HelpAction {
    href: &'static str,
    method: &'static str,
    help: &'static str,
}

#[derive(RustcEncodable)]
struct HelpMessage {
    title: &'static str,
    actions: Vec<HelpAction>,
}

fn help_message() -> String {

    json::encode(&HelpMessage {
        title: "Help Page",
        actions: vec![
            HelpAction {
                href: "/join",
                method: "POST",
                help: "Join a new game.",
            },
            HelpAction {
                href: "/pass/[PLAYER_ID]",
                method: "POST",
                help: "Pass during auction.",
            },
            HelpAction {
                href: "/coinche/[PLAYER_ID]",
                method: "POST",
                help: "Coinche the opponent's bid during auction.",
            },
            HelpAction {
                href: "/bid/[PLAYER_ID]",
                method: "POST",
                help: "Bid a contract during auction.",
            },
            HelpAction {
                href: "/play/[PLAYER_ID]",
                method: "POST",
                help: "Play a card.",
            },
            HelpAction {
                href: "/hand/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current hand.",
            },
            HelpAction {
                href: "/trick/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current trick.",
            },
            HelpAction {
                href: "/last_trick/[PLAYER_ID]",
                method: "GET",
                help: "Checks the last complete trick.",
            },
            HelpAction {
                href: "/scores/[PLAYER_ID]",
                method: "GET",
                help: "Get the current scores.",
            },
            HelpAction {
                href: "/pos/[PLAYER_ID]",
                method: "GET",
                help: "Get the player's position on the table.",
            },
            HelpAction {
                href: "/wait/[PLAYER_ID]/[EVENT_ID]",
                method: "GET",
                help: "Wait until the next event, or return it if it already happened.",
            },
        ]
    }).unwrap()
}

fn help_resp() -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();
    return Ok(Response::with((content_type,
                              iron::status::NotFound,
                              help_message())));
}

fn err_resp(msg: &str) -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

    #[derive(RustcEncodable)]
    struct Error<'a>{
        error: &'a str,
    }

    return Ok(Response::with((content_type,
                              iron::status::Ok,
                              json::encode(&Error { error: msg }).unwrap(),
                              )));
}

macro_rules! parse_id {
    ( $name:expr, $value:expr ) => {
        {
            match u32::from_str($value) {
                Ok(id) => id,
                Err(e) => return err_resp(&format!("invalid {} ID: `{}` ({})", $name, $value, e)),
            }
        }
    };
}

macro_rules! check_len {
    ( $path:expr, 1 ) => {
        {
            if $path.len() != 1 {
                return err_resp(&format!("incorrect parameters (Usage: /{})", $path[0]));
            }
        }
    };
    ( $path:expr, 2 ) => {
        {
            if $path.len() != 2 {
                return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", $path[0]));
            }
        }
    };
    ( $path:expr, 3 ) => {
        {
            if $path.len() != 3 {
                return err_resp(&format!("incorrect parameters (Usage: /{}/[PID]/[EID])", $path[0]));
            }
        }
    };
}

macro_rules! try_manager {
    ( $call:expr ) => {
        {
            match $call {
                Err(err) => return err_resp(&format!("{}", err)),
                Ok(thing) => json::encode(&thing).unwrap(),
            }
        }
    };
}

impl iron::Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        if req.url.path.is_empty() {
            // ?!?
            panic!("Empty request path should never happen.");
        }

        // Weird deref trick to go from &String to &str
        let action: &str = &*req.url.path[0];

        let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

        match req.method {
            iron::method::Options => {
                if ["hand", "trick", "contracts", "last_trick", "scores"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Get,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else if ["pass", "coinche", "bid", "play", "join"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Post,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else {
                    help_resp()
                }
            },
            iron::method::Get => {
                let response = match action {
                    "wait" => {
                        check_len!(req.url.path, 3);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        let event_id = parse_id!("event", &*req.url.path[2]) as usize;
                        try_manager!(self.manager.wait(player_id, event_id))
                    },
                    "hand" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_hand(player_id))
                    },
                    "trick" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_trick(player_id))
                    },
                    "last_trick" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_last_trick(player_id))
                    },
                    "scores" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_scores(player_id))
                    },
                    "pos" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_pos(player_id))
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))

            },
            iron::method::Post => {
                // Read the JSON body
                // ...

                let response = match action {
                    "join" => {
                        check_len!(req.url.path, 1);
                        try_manager!(self.manager.join())
                    },
                    "pass" => return help_resp(),
                    "coinche" => return help_resp(),
                    "bid" => return help_resp(),
                    "play" => return help_resp(),
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))
            },
            _ => help_resp(),
        }
    }
}

impl Server {
    pub fn new(port: u16) -> Server {
        Server {
            port: port,
            manager: Arc::new(GameManager::new()),
        }
    }

    pub fn run(self) {
        let port = self.port;
        println!("Listening on port {}", port);

        let router = Router { manager: self.manager.clone() };

        Iron::new(router).http(("localhost", port)).unwrap();

    }
}
<|endoftext|>


<commit_before>use bit_vec::BitVec;

pub fn shift(state: &mut BitVec) {
    let range = 1 .. state.len();

    for i in range.rev() {
        let pred = state[i - 1];
        state.set(i, pred);
    };

    state.set(0, false);
}

#[cfg(test)]
mod test {
    use bit_vec::BitVec;
    use super::shift;

    #[test]
    fn shift_works() {
        let ref mut bv = BitVec::from_elem(4, true);

        shift(bv);
        assert!(bv.eq_vec(&[false, true, true, true]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, true, true]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, false, true]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, false, false]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, false, false]));
    }
}
<commit_msg>Add first pass at LFSR trait<commit_after>use bit_vec::BitVec;

pub trait LFSR {
    fn output(&self) -> bool;
    fn step(&mut self);
}

pub fn shift(state: &mut BitVec) {
    let range = 1 .. state.len();

    for i in range.rev() {
        let pred = state[i - 1];
        state.set(i, pred);
    };

    state.set(0, false);
}

#[cfg(test)]
mod test {
    use bit_vec::BitVec;
    use super::shift;

    #[test]
    fn shift_works() {
        let ref mut bv = BitVec::from_elem(4, true);

        shift(bv);
        assert!(bv.eq_vec(&[false, true, true, true]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, true, true]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, false, true]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, false, false]));

        shift(bv);
        assert!(bv.eq_vec(&[false, false, false, false]));
    }
}
<|endoftext|>


<commit_before>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};
use std::rc::{Rc, Weak};

type Node = Box<Containable>;

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<Rc<Node>> {
        let mut container = self.get_parent().upgrade();
        loop {
            if let Some(parent) = container {
                if parent.get_type() == type_ {
                    return Some(parent);
                }
                container = parent.get_parent().upgrade();
            } else {
                return None;
            }
        }
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Weak<Node>,
    children: Vec<Rc<Node>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
        /*
        match self.type_ {
            ContainerType::Root => {
                // such hack
                unsafe {
                    // very unsafe
                    use std::mem;
                    let _dummy: Node = mem::uninitialized();
                    // much dummy
                    let _rc_dummy = Rc::new(_dummy);
                    Rc::downgrade(&_rc_dummy)}
            },
            _ => self.parent.clone(),
        }*/
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.iter().map(|child| Rc::downgrade(&child)).collect())
        }
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        for child in self.get_children().expect("No children") {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container();
                    drop(child);
                }
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<WlcView>,
    parent: Weak<Node>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        None
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        unimplemented!();
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}
<commit_msg>Changed View's handle to Box<WlcView>, implemented remove_container<commit_after>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};
use std::rc::{Rc, Weak};

type Node = Box<Containable>;

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<Rc<Node>> {
        let mut container = self.get_parent().upgrade();
        loop {
            if let Some(parent) = container {
                if parent.get_type() == type_ {
                    return Some(parent);
                }
                container = parent.get_parent().upgrade();
            } else {
                return None;
            }
        }
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Weak<Node>,
    children: Vec<Rc<Node>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
        /*
        match self.type_ {
            ContainerType::Root => {
                // such hack
                unsafe {
                    // very unsafe
                    use std::mem;
                    let _dummy: Node = mem::uninitialized();
                    // much dummy
                    let _rc_dummy = Rc::new(_dummy);
                    Rc::downgrade(&_rc_dummy)}
            },
            _ => self.parent.clone(),
        }*/
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.iter().map(|child| Rc::downgrade(&child)).collect())
        }
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        for child in self.get_children().expect("No children") {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container();
                    drop(child);
                }
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<Box<WlcView>>,
    parent: Weak<Node>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        None
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(ref handle) = self.handle {
            handle.close();
        }
        drop(self);
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}
<|endoftext|>


<commit_before>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};

enum ContainerTypes {
    Root,        /* Root container, only one exists */
    Output,      /* Output, like a monitor or head */
    Workspace,   /* A workspace */
    View         /* A view (aka a window) */
}

enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent<T: Containable>(&self) -> Option<T>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children<T: Containable>(&self) -> Vec<T>;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(self);

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(visibilty: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type
    fn get_parent_by_type<T: Containable>(&self, type_: T) -> T;
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    // Can't be a view, that's the View struct's job
    handle: Option<WlcOutput>,
    type_: ContainerTypes,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

struct View {
    handle: Option<WlcView>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}
<commit_msg>Switched comments to doc comments<commit_after>//! Layout handling

use rustwlc::{WlcView, WlcOutput};

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent<T: Containable>(&self) -> Option<T>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children<T: Containable>(&self) -> Vec<T>;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(self);

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(visibilty: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type
    fn get_parent_by_type<T: Containable>(&self, type_: T) -> T;
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    // Can't be a view, that's the View struct's job
    handle: Option<WlcOutput>,
    type_: ContainerTypes,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

struct View {
    handle: Option<WlcView>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}
<|endoftext|>