<commit_before>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use bincode::serde::DeserializeError;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::io::{Error, ErrorKind};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;
use std::usize;

use uuid::Uuid;

#[derive(Clone)]
struct ServerRecord {
    sender: OsIpcSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Arc<Mutex<mpsc::Receiver<bool>>>,
}

impl ServerRecord {
    fn new(sender: OsIpcSender) -> ServerRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        ServerRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Arc::new(Mutex::new(rx)),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SERVERS: Mutex<HashMap<String,ServerRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<OsIpcChannel>, Vec<OsIpcSharedMemory>);

pub fn channel() -> Result<(OsIpcSender, OsIpcReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((OsIpcSender::new(base_sender), OsIpcReceiver::new(base_receiver)))
}

#[derive(Debug)]
pub struct OsIpcReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcReceiver {
    fn eq(&self, other: &OsIpcReceiver) -> bool {
        self.receiver.borrow().as_ref().map(|rx| rx as *const _) ==
            other.receiver.borrow().as_ref().map(|rx| rx as *const _)
    }
}

impl OsIpcReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> OsIpcReceiver {
        OsIpcReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> OsIpcReceiver {
        let receiver = self.receiver.borrow_mut().take();
        OsIpcReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

#[derive(Clone, Debug)]
pub struct OsIpcSender {
    sender: Arc<Mutex<mpsc::Sender<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcSender {
    fn eq(&self, other: &OsIpcSender) -> bool {
        &*self.sender.lock().unwrap() as *const _ ==
            &*other.sender.lock().unwrap() as *const _
    }
}

impl OsIpcSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> OsIpcSender {
        OsIpcSender {
            sender: Arc::new(Mutex::new(sender)),
        }
    }

    pub fn connect(name: String) -> Result<OsIpcSender,MpscError> {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&name).unwrap().clone();
        record.connect();
        Ok(record.sender)
    }

    pub fn get_max_fragment_size() -> usize {
        usize::MAX
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<OsIpcChannel>,
                shared_memory_regions: Vec<OsIpcSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.lock().unwrap().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::ChannelClosedError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct OsIpcReceiverSet {
    last_index: usize,
    receiver_ids: Vec<usize>,
    receivers: Vec<OsIpcReceiver>,
}

impl OsIpcReceiverSet {
    pub fn new() -> Result<OsIpcReceiverSet,MpscError> {
        Ok(OsIpcReceiverSet {
            last_index: 0,
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: OsIpcReceiver) -> Result<i64,MpscError> {
        self.last_index += 1;
        self.receiver_ids.push(self.last_index);
        self.receivers.push(receiver.consume());
        Ok(self.last_index as i64)
    }

    pub fn select(&mut self) -> Result<Vec<OsIpcSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: i64 = -1;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = self.receiver_ids[index] as i64;
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        if r_id == -1 {
            return Err(MpscError::UnknownError);
        }

        let receivers = &mut self.receivers;
        match receivers[r_index].recv() {
            Ok((data, channels, shmems)) =>
                Ok(vec![OsIpcSelectionResult::DataReceived(r_id, data, channels, shmems)]),
            Err(MpscError::ChannelClosedError) => {
                receivers.remove(r_index);
                self.receiver_ids.remove(r_index);
                Ok(vec![OsIpcSelectionResult::ChannelClosed(r_id)])
            },
            Err(err) => Err(err),
        }
    }
}

pub enum OsIpcSelectionResult {
    DataReceived(i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),
    ChannelClosed(i64),
}

impl OsIpcSelectionResult {
    pub fn unwrap(self) -> (i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>) {
        match self {
            OsIpcSelectionResult::DataReceived(id, data, channels, shared_memory_regions) => {
                (id, data, channels, shared_memory_regions)
            }
            OsIpcSelectionResult::ChannelClosed(id) => {
                panic!("OsIpcSelectionResult::unwrap(): receiver ID {} was closed!", id)
            }
        }
    }
}

pub struct OsIpcOneShotServer {
    receiver: RefCell<Option<OsIpcReceiver>>,
    name: String,
}

impl OsIpcOneShotServer {
    pub fn new() -> Result<(OsIpcOneShotServer, String),MpscError> {
        let (sender, receiver) = try!(channel());

        let name = Uuid::new_v4().to_string();
        let record = ServerRecord::new(sender);
        ONE_SHOT_SERVERS.lock().unwrap().insert(name.clone(), record);
        Ok((OsIpcOneShotServer {
            receiver: RefCell::new(Some(receiver)),
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(&self) -> Result<(OsIpcReceiver,
                                    Vec<u8>,
                                    Vec<OsOpaqueIpcChannel>,
                                    Vec<OsIpcSharedMemory>),MpscError>
    {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&self.name).unwrap().clone();
        record.accept();
        ONE_SHOT_SERVERS.lock().unwrap().remove(&self.name).unwrap();
        let receiver = self.receiver.borrow_mut().take().unwrap();
        let (data, channels, shmems) = receiver.recv().unwrap();
        Ok((receiver, data, channels, shmems))
    }
}

#[derive(PartialEq, Debug)]
pub enum OsIpcChannel {
    Sender(OsIpcSender),
    Receiver(OsIpcReceiver),
}

#[derive(PartialEq, Debug)]
pub struct OsOpaqueIpcChannel {
    channel: RefCell<Option<OsIpcChannel>>,
}

impl OsOpaqueIpcChannel {
    fn new(channel: OsIpcChannel) -> OsOpaqueIpcChannel {
        OsOpaqueIpcChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> OsIpcReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            OsIpcChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&mut self) -> OsIpcSender {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(s) => s,
            OsIpcChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct OsIpcSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for OsIpcSharedMemory {}
unsafe impl Sync for OsIpcSharedMemory {}

impl Clone for OsIpcSharedMemory {
    fn clone(&self) -> OsIpcSharedMemory {
        OsIpcSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for OsIpcSharedMemory {
    fn eq(&self, other: &OsIpcSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for OsIpcSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for OsIpcSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `OsIpcSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl OsIpcSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> OsIpcSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum MpscError {
    ChannelClosedError,
    UnknownError,
}

impl MpscError {
    #[allow(dead_code)]
    pub fn channel_is_closed(&self) -> bool {
        *self == MpscError::ChannelClosedError
    }
}

impl From<MpscError> for DeserializeError {
    fn from(mpsc_error: MpscError) -> DeserializeError {
        DeserializeError::IoError(mpsc_error.into())
    }
}

impl From<MpscError> for Error {
    fn from(mpsc_error: MpscError) -> Error {
        match mpsc_error {
            MpscError::ChannelClosedError => {
                Error::new(ErrorKind::BrokenPipe, "MPSC channel closed")
            }
            MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"),
        }
    }
}

<commit_msg>Cleanup: inprocess: Avoid an unneeded `RefCell<>`<commit_after>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use bincode::serde::DeserializeError;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::io::{Error, ErrorKind};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;
use std::usize;

use uuid::Uuid;

#[derive(Clone)]
struct ServerRecord {
    sender: OsIpcSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Arc<Mutex<mpsc::Receiver<bool>>>,
}

impl ServerRecord {
    fn new(sender: OsIpcSender) -> ServerRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        ServerRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Arc::new(Mutex::new(rx)),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SERVERS: Mutex<HashMap<String,ServerRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<OsIpcChannel>, Vec<OsIpcSharedMemory>);

pub fn channel() -> Result<(OsIpcSender, OsIpcReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((OsIpcSender::new(base_sender), OsIpcReceiver::new(base_receiver)))
}

#[derive(Debug)]
pub struct OsIpcReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcReceiver {
    fn eq(&self, other: &OsIpcReceiver) -> bool {
        self.receiver.borrow().as_ref().map(|rx| rx as *const _) ==
            other.receiver.borrow().as_ref().map(|rx| rx as *const _)
    }
}

impl OsIpcReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> OsIpcReceiver {
        OsIpcReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> OsIpcReceiver {
        let receiver = self.receiver.borrow_mut().take();
        OsIpcReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

#[derive(Clone, Debug)]
pub struct OsIpcSender {
    sender: Arc<Mutex<mpsc::Sender<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcSender {
    fn eq(&self, other: &OsIpcSender) -> bool {
        &*self.sender.lock().unwrap() as *const _ ==
            &*other.sender.lock().unwrap() as *const _
    }
}

impl OsIpcSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> OsIpcSender {
        OsIpcSender {
            sender: Arc::new(Mutex::new(sender)),
        }
    }

    pub fn connect(name: String) -> Result<OsIpcSender,MpscError> {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&name).unwrap().clone();
        record.connect();
        Ok(record.sender)
    }

    pub fn get_max_fragment_size() -> usize {
        usize::MAX
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<OsIpcChannel>,
                shared_memory_regions: Vec<OsIpcSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.lock().unwrap().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::ChannelClosedError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct OsIpcReceiverSet {
    last_index: usize,
    receiver_ids: Vec<usize>,
    receivers: Vec<OsIpcReceiver>,
}

impl OsIpcReceiverSet {
    pub fn new() -> Result<OsIpcReceiverSet,MpscError> {
        Ok(OsIpcReceiverSet {
            last_index: 0,
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: OsIpcReceiver) -> Result<i64,MpscError> {
        self.last_index += 1;
        self.receiver_ids.push(self.last_index);
        self.receivers.push(receiver.consume());
        Ok(self.last_index as i64)
    }

    pub fn select(&mut self) -> Result<Vec<OsIpcSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: i64 = -1;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = self.receiver_ids[index] as i64;
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        if r_id == -1 {
            return Err(MpscError::UnknownError);
        }

        let receivers = &mut self.receivers;
        match receivers[r_index].recv() {
            Ok((data, channels, shmems)) =>
                Ok(vec![OsIpcSelectionResult::DataReceived(r_id, data, channels, shmems)]),
            Err(MpscError::ChannelClosedError) => {
                receivers.remove(r_index);
                self.receiver_ids.remove(r_index);
                Ok(vec![OsIpcSelectionResult::ChannelClosed(r_id)])
            },
            Err(err) => Err(err),
        }
    }
}

pub enum OsIpcSelectionResult {
    DataReceived(i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),
    ChannelClosed(i64),
}

impl OsIpcSelectionResult {
    pub fn unwrap(self) -> (i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>) {
        match self {
            OsIpcSelectionResult::DataReceived(id, data, channels, shared_memory_regions) => {
                (id, data, channels, shared_memory_regions)
            }
            OsIpcSelectionResult::ChannelClosed(id) => {
                panic!("OsIpcSelectionResult::unwrap(): receiver ID {} was closed!", id)
            }
        }
    }
}

pub struct OsIpcOneShotServer {
    receiver: Option<OsIpcReceiver>,
    name: String,
}

impl OsIpcOneShotServer {
    pub fn new() -> Result<(OsIpcOneShotServer, String),MpscError> {
        let (sender, receiver) = try!(channel());

        let name = Uuid::new_v4().to_string();
        let record = ServerRecord::new(sender);
        ONE_SHOT_SERVERS.lock().unwrap().insert(name.clone(), record);
        Ok((OsIpcOneShotServer {
            receiver: Some(receiver),
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(mut self) -> Result<(OsIpcReceiver,
                                    Vec<u8>,
                                    Vec<OsOpaqueIpcChannel>,
                                    Vec<OsIpcSharedMemory>),MpscError>
    {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&self.name).unwrap().clone();
        record.accept();
        ONE_SHOT_SERVERS.lock().unwrap().remove(&self.name).unwrap();
        let receiver = self.receiver.take().unwrap();
        let (data, channels, shmems) = receiver.recv().unwrap();
        Ok((receiver, data, channels, shmems))
    }
}

#[derive(PartialEq, Debug)]
pub enum OsIpcChannel {
    Sender(OsIpcSender),
    Receiver(OsIpcReceiver),
}

#[derive(PartialEq, Debug)]
pub struct OsOpaqueIpcChannel {
    channel: RefCell<Option<OsIpcChannel>>,
}

impl OsOpaqueIpcChannel {
    fn new(channel: OsIpcChannel) -> OsOpaqueIpcChannel {
        OsOpaqueIpcChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> OsIpcReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            OsIpcChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&mut self) -> OsIpcSender {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(s) => s,
            OsIpcChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct OsIpcSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for OsIpcSharedMemory {}
unsafe impl Sync for OsIpcSharedMemory {}

impl Clone for OsIpcSharedMemory {
    fn clone(&self) -> OsIpcSharedMemory {
        OsIpcSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for OsIpcSharedMemory {
    fn eq(&self, other: &OsIpcSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for OsIpcSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for OsIpcSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `OsIpcSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl OsIpcSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> OsIpcSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum MpscError {
    ChannelClosedError,
    UnknownError,
}

impl MpscError {
    #[allow(dead_code)]
    pub fn channel_is_closed(&self) -> bool {
        *self == MpscError::ChannelClosedError
    }
}

impl From<MpscError> for DeserializeError {
    fn from(mpsc_error: MpscError) -> DeserializeError {
        DeserializeError::IoError(mpsc_error.into())
    }
}

impl From<MpscError> for Error {
    fn from(mpsc_error: MpscError) -> Error {
        match mpsc_error {
            MpscError::ChannelClosedError => {
                Error::new(ErrorKind::BrokenPipe, "MPSC channel closed")
            }
            MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"),
        }
    }
}

<|endoftext|>


<commit_before>extern crate onmf;
use onmf::helpers::{ToImage, Normalize};
use onmf::testimage_generator;
use onmf::testimage_generator::{magnify};

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

fn main() {
    let mag_factor = 10;

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let steps = 6;
    let per_step = 10;
    let nsamples = steps * per_step;
    let nobserved = 10 * 10;
    let nhidden = 10;

    let mut data = DMat::<f64>::new_zeros(nsamples, nobserved);

    // write on testimage into each row of data
    for (step, i, factor) in testimage_generator::testimages::<f64, _>(per_step, &mut rng) {
        let row = step * i;
        for (col, val) in factor.as_vec().iter().enumerate() {
            data[(row, col)] = val.clone();
        }
    }

    let mut nmf = onmf::OrthogonalNMF::<f64>::init_randomly(
        nhidden, nobserved, nsamples);

    // 100 iterations
    for _ in 0..100 { nmf.iterate(&data) }

    // snapshot
    // read testimage out of each row of nmf.hidden
    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-iter-100-{}.png", irow)[..]).unwrap();
    }

    for _ in 0..10000 { nmf.iterate(&data) }

    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-iter-final-{}.png", irow)[..]).unwrap();
    }
}
<commit_msg>ortho nmf: search for right number of hidden vars to not learn mixtures<commit_after>extern crate onmf;
use onmf::helpers::{ToImage, Normalize};
use onmf::testimage_generator;
use onmf::testimage_generator::{magnify};

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

fn main() {
    let mag_factor = 10;

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let steps = 6;
    let per_step = 10;
    let nsamples = steps * per_step;
    let nobserved = 10 * 10;
    let nhidden = 20;

    let mut data = DMat::<f64>::new_zeros(nsamples, nobserved);

    // write on testimage into each row of data
    for (step, i, factor) in testimage_generator::testimages::<f64, _>(per_step, &mut rng) {
        let row = step * i;
        for (col, val) in factor.as_vec().iter().enumerate() {
            data[(row, col)] = val.clone();
        }
    }

    let mut nmf = onmf::OrthogonalNMF::<f64>::init_randomly(
        nhidden, nobserved, nsamples);

    // 100 iterations
    for _ in 0..100 { nmf.iterate(&data) }

    // snapshot
    // read testimage out of each row of nmf.hidden
    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-iter-100-{}.png", irow)[..]).unwrap();
    }

    for _ in 0..10000 { nmf.iterate(&data) }

    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-iter-final-{}.png", irow)[..]).unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! SSHFP records for SSH public key fingerprints

use crate::error::*;
use crate::serialize::binary::*;

/// [RFC 4255](https://tools.ietf.org/html/rfc4255#section-3.1)
///
/// ```text
/// 3.1.  The SSHFP RDATA Format
///
///    The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
///    type and the fingerprint of the public host key.
///
///        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
///        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///        |   algorithm   |    fp type    |                               /
///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               /
///        /                                                               /
///        /                          fingerprint                          /
///        /                                                               /
///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///
/// 3.1.3.  Fingerprint
///
///    The fingerprint is calculated over the public key blob as described
///    in [7].
///
///    The message-digest algorithm is presumed to produce an opaque octet
///    string output, which is placed as-is in the RDATA fingerprint field.
/// ```
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct SSHFP {
    algorithm: Algorithm,
    fingerprint_type: FingerprintType,
    fingerprint: Vec<u8>,
}

impl SSHFP {
    /// Creates a new SSHFP record data.
    ///
    /// # Arguments
    ///
    /// * `algorithm` - the SSH public key algorithm.
    /// * `fingerprint_type` - the fingerprint type to use.
    /// * `fingerprint` - the fingerprint of the public key.
    pub fn new(
        algorithm: Algorithm,
        fingerprint_type: FingerprintType,
        fingerprint: Vec<u8>,
    ) -> Self {
        SSHFP {
            algorithm,
            fingerprint_type,
            fingerprint,
        }
    }

    /// The SSH public key algorithm.
    pub fn algorithm(&self) -> Algorithm {
        self.algorithm
    }

    /// The fingerprint type to use.
    pub fn fingerprint_type(&self) -> FingerprintType {
        self.fingerprint_type
    }

    /// The fingerprint of the public key.
    pub fn fingerprint(&self) -> &[u8] {
        &self.fingerprint
    }
}

/// ```text
/// 3.1.1.  Algorithm Number Specification
///
///    This algorithm number octet describes the algorithm of the public
///    key.  The following values are assigned:
///
///           Value    Algorithm name
///           -----    --------------
///           0        reserved
///           1        RSA
///           2        DSS
///
///    Reserving other types requires IETF consensus [4].
/// ```text
///
/// The algorithm values have been updated in
/// [RFC 6594](https://tools.ietf.org/html/rfc6594) and
/// [RFC 7479](https://tools.ietf.org/html/rfc7479).
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Algorithm {
    /// Reserved value
    Reserved,

    /// RSA
    RSA,

    /// DSS/DSA
    DSA,

    /// ECDSA
    ECDSA,

    /// Ed25519
    Ed25519,

    /// Unassigned value
    Unassigned(u8),
}

impl From<u8> for Algorithm {
    fn from(alg: u8) -> Self {
        match alg {
            0 => Algorithm::Reserved,
            1 => Algorithm::RSA,
            2 => Algorithm::DSA,
            3 => Algorithm::ECDSA,
            4 => Algorithm::Ed25519, // TODO more (XMSS)
            _ => Algorithm::Unassigned(alg),
        }
    }
}

impl Into<u8> for Algorithm {
    fn into(self) -> u8 {
        match self {
            Algorithm::Reserved => 0,
            Algorithm::RSA => 1,
            Algorithm::DSA => 2,
            Algorithm::ECDSA => 3,
            Algorithm::Ed25519 => 4,
            Algorithm::Unassigned(alg) => alg,
        }
    }
}

/// ```text
/// 3.1.2.  Fingerprint Type Specification
///
///    The fingerprint type octet describes the message-digest algorithm
///    used to calculate the fingerprint of the public key.  The following
///    values are assigned:
///
///           Value    Fingerprint type
///           -----    ----------------
///           0        reserved
///           1        SHA-1
///
///    Reserving other types requires IETF consensus [4].
///
///    For interoperability reasons, as few fingerprint types as possible
///    should be reserved.  The only reason to reserve additional types is
///    to increase security.
/// ```
///
/// The fingerprint type values have been updated in
/// [RFC 6594](https://tools.ietf.org/html/rfc6594).
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum FingerprintType {
    /// Reserved value
    Reserved,

    /// SHA-1
    SHA1,

    /// SHA-256
    SHA256,

    /// Unassigned value
    Unassigned(u8),
}

impl From<u8> for FingerprintType {
    fn from(ft: u8) -> Self {
        match ft {
            0 => FingerprintType::Reserved,
            1 => FingerprintType::SHA1,
            2 => FingerprintType::SHA256,
            _ => FingerprintType::Unassigned(ft),
        }
    }
}

impl Into<u8> for FingerprintType {
    fn into(self) -> u8 {
        match self {
            FingerprintType::Reserved => 0,
            FingerprintType::SHA1 => 1,
            FingerprintType::SHA256 => 2,
            FingerprintType::Unassigned(ft) => ft,
        }
    }
}

/// Read the RData from the given decoder.
pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<SSHFP> {
    let algorithm = decoder.read_u8()?.unverified().into();
    let fingerprint_type = decoder.read_u8()?.unverified().into();
    let fingerprint_len = rdata_length
        .map(|l| l as usize)
        .checked_sub(2)
        .map_err(|_| ProtoError::from("invalid rdata length in SSHFP"))?
        .unverified();
    let fingerprint = decoder.read_vec(fingerprint_len)?.unverified();
    Ok(SSHFP::new(algorithm, fingerprint_type, fingerprint))
}

/// Write the RData using the given encoder.
pub fn emit(encoder: &mut BinEncoder, sshfp: &SSHFP) -> ProtoResult<()> {
    encoder.emit_u8(sshfp.algorithm().into())?;
    encoder.emit_u8(sshfp.fingerprint_type().into())?;
    encoder.emit_vec(sshfp.fingerprint())
}

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

    #[test]
    fn read_algorithm() {
        assert_eq!(Algorithm::Reserved, 0.into());
        assert_eq!(Algorithm::RSA, 1.into());
        assert_eq!(Algorithm::DSA, 2.into());
        assert_eq!(Algorithm::ECDSA, 3.into());
        assert_eq!(Algorithm::Ed25519, 4.into());
        assert_eq!(Algorithm::Unassigned(17), 17.into());
        assert_eq!(Algorithm::Unassigned(42), 42.into());

        assert_eq!(0u8, Algorithm::Reserved.into());
        assert_eq!(1u8, Algorithm::RSA.into());
        assert_eq!(2u8, Algorithm::DSA.into());
        assert_eq!(3u8, Algorithm::ECDSA.into());
        assert_eq!(4u8, Algorithm::Ed25519.into());
        assert_eq!(17u8, Algorithm::Unassigned(17).into());
        assert_eq!(42u8, Algorithm::Unassigned(42).into());
    }

    #[test]
    fn read_fingerprint_type() {
        assert_eq!(FingerprintType::Reserved, 0.into());
        assert_eq!(FingerprintType::SHA1, 1.into());
        assert_eq!(FingerprintType::SHA256, 2.into());
        assert_eq!(FingerprintType::Unassigned(12), 12.into());
        assert_eq!(FingerprintType::Unassigned(89), 89.into());

        assert_eq!(0u8, FingerprintType::Reserved.into());
        assert_eq!(1u8, FingerprintType::SHA1.into());
        assert_eq!(2u8, FingerprintType::SHA256.into());
        assert_eq!(12u8, FingerprintType::Unassigned(12).into());
        assert_eq!(89u8, FingerprintType::Unassigned(89).into());
    }

    fn test_encode_decode(rdata: SSHFP, result: &[u8]) {
        let mut bytes = Vec::new();
        let mut encoder = BinEncoder::new(&mut bytes);
        emit(&mut encoder, &rdata).expect("failed to emit SSHFP");
        let bytes = encoder.into_bytes();
        assert_eq!(bytes, &result);

        let mut decoder = BinDecoder::new(result);
        let read_rdata =
            read(&mut decoder, Restrict::new(result.len() as u16)).expect("failed to read SSHFP");
        assert_eq!(read_rdata, rdata)
    }

    #[test]
    fn test_encode_decode_sshfp() {
        test_encode_decode(
            SSHFP::new(Algorithm::RSA, FingerprintType::SHA256, vec![]),
            &[1, 2],
        );
        test_encode_decode(
            SSHFP::new(
                Algorithm::ECDSA,
                FingerprintType::SHA1,
                vec![115, 115, 104, 102, 112],
            ),
            &[3, 1, 115, 115, 104, 102, 112],
        );
        test_encode_decode(
            SSHFP::new(
                Algorithm::Reserved,
                FingerprintType::Reserved,
                b"ssh fingerprint".to_vec(),
            ),
            &[
                0, 0, 115, 115, 104, 32, 102, 105, 110, 103, 101, 114, 112, 114, 105, 110, 116,
            ],
        );
        test_encode_decode(
            SSHFP::new(
                Algorithm::Unassigned(255),
                FingerprintType::Unassigned(13),
                vec![100, 110, 115, 115, 101, 99, 32, 100, 97, 110, 101],
            ),
            &[255, 13, 100, 110, 115, 115, 101, 99, 32, 100, 97, 110, 101],
        );
    }
}
<commit_msg>proto: Implement `From` instead of `Into` for SSHFP types<commit_after>// Copyright 2019 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! SSHFP records for SSH public key fingerprints

use crate::error::*;
use crate::serialize::binary::*;

/// [RFC 4255](https://tools.ietf.org/html/rfc4255#section-3.1)
///
/// ```text
/// 3.1.  The SSHFP RDATA Format
///
///    The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
///    type and the fingerprint of the public host key.
///
///        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
///        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///        |   algorithm   |    fp type    |                               /
///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               /
///        /                                                               /
///        /                          fingerprint                          /
///        /                                                               /
///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///
/// 3.1.3.  Fingerprint
///
///    The fingerprint is calculated over the public key blob as described
///    in [7].
///
///    The message-digest algorithm is presumed to produce an opaque octet
///    string output, which is placed as-is in the RDATA fingerprint field.
/// ```
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct SSHFP {
    algorithm: Algorithm,
    fingerprint_type: FingerprintType,
    fingerprint: Vec<u8>,
}

impl SSHFP {
    /// Creates a new SSHFP record data.
    ///
    /// # Arguments
    ///
    /// * `algorithm` - the SSH public key algorithm.
    /// * `fingerprint_type` - the fingerprint type to use.
    /// * `fingerprint` - the fingerprint of the public key.
    pub fn new(
        algorithm: Algorithm,
        fingerprint_type: FingerprintType,
        fingerprint: Vec<u8>,
    ) -> Self {
        SSHFP {
            algorithm,
            fingerprint_type,
            fingerprint,
        }
    }

    /// The SSH public key algorithm.
    pub fn algorithm(&self) -> Algorithm {
        self.algorithm
    }

    /// The fingerprint type to use.
    pub fn fingerprint_type(&self) -> FingerprintType {
        self.fingerprint_type
    }

    /// The fingerprint of the public key.
    pub fn fingerprint(&self) -> &[u8] {
        &self.fingerprint
    }
}

/// ```text
/// 3.1.1.  Algorithm Number Specification
///
///    This algorithm number octet describes the algorithm of the public
///    key.  The following values are assigned:
///
///           Value    Algorithm name
///           -----    --------------
///           0        reserved
///           1        RSA
///           2        DSS
///
///    Reserving other types requires IETF consensus [4].
/// ```text
///
/// The algorithm values have been updated in
/// [RFC 6594](https://tools.ietf.org/html/rfc6594) and
/// [RFC 7479](https://tools.ietf.org/html/rfc7479).
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Algorithm {
    /// Reserved value
    Reserved,

    /// RSA
    RSA,

    /// DSS/DSA
    DSA,

    /// ECDSA
    ECDSA,

    /// Ed25519
    Ed25519,

    /// Unassigned value
    Unassigned(u8),
}

impl From<u8> for Algorithm {
    fn from(alg: u8) -> Self {
        match alg {
            0 => Algorithm::Reserved,
            1 => Algorithm::RSA,
            2 => Algorithm::DSA,
            3 => Algorithm::ECDSA,
            4 => Algorithm::Ed25519, // TODO more (XMSS)
            _ => Algorithm::Unassigned(alg),
        }
    }
}

impl From<Algorithm> for u8 {
    fn from(algorithm: Algorithm) -> u8 {
        match algorithm {
            Algorithm::Reserved => 0,
            Algorithm::RSA => 1,
            Algorithm::DSA => 2,
            Algorithm::ECDSA => 3,
            Algorithm::Ed25519 => 4,
            Algorithm::Unassigned(alg) => alg,
        }
    }
}

/// ```text
/// 3.1.2.  Fingerprint Type Specification
///
///    The fingerprint type octet describes the message-digest algorithm
///    used to calculate the fingerprint of the public key.  The following
///    values are assigned:
///
///           Value    Fingerprint type
///           -----    ----------------
///           0        reserved
///           1        SHA-1
///
///    Reserving other types requires IETF consensus [4].
///
///    For interoperability reasons, as few fingerprint types as possible
///    should be reserved.  The only reason to reserve additional types is
///    to increase security.
/// ```
///
/// The fingerprint type values have been updated in
/// [RFC 6594](https://tools.ietf.org/html/rfc6594).
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum FingerprintType {
    /// Reserved value
    Reserved,

    /// SHA-1
    SHA1,

    /// SHA-256
    SHA256,

    /// Unassigned value
    Unassigned(u8),
}

impl From<u8> for FingerprintType {
    fn from(ft: u8) -> Self {
        match ft {
            0 => FingerprintType::Reserved,
            1 => FingerprintType::SHA1,
            2 => FingerprintType::SHA256,
            _ => FingerprintType::Unassigned(ft),
        }
    }
}

impl From<FingerprintType> for u8 {
    fn from(fingerprint_type: FingerprintType) -> u8 {
        match fingerprint_type {
            FingerprintType::Reserved => 0,
            FingerprintType::SHA1 => 1,
            FingerprintType::SHA256 => 2,
            FingerprintType::Unassigned(ft) => ft,
        }
    }
}

/// Read the RData from the given decoder.
pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<SSHFP> {
    let algorithm = decoder.read_u8()?.unverified().into();
    let fingerprint_type = decoder.read_u8()?.unverified().into();
    let fingerprint_len = rdata_length
        .map(|l| l as usize)
        .checked_sub(2)
        .map_err(|_| ProtoError::from("invalid rdata length in SSHFP"))?
        .unverified();
    let fingerprint = decoder.read_vec(fingerprint_len)?.unverified();
    Ok(SSHFP::new(algorithm, fingerprint_type, fingerprint))
}

/// Write the RData using the given encoder.
pub fn emit(encoder: &mut BinEncoder, sshfp: &SSHFP) -> ProtoResult<()> {
    encoder.emit_u8(sshfp.algorithm().into())?;
    encoder.emit_u8(sshfp.fingerprint_type().into())?;
    encoder.emit_vec(sshfp.fingerprint())
}

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

    #[test]
    fn read_algorithm() {
        assert_eq!(Algorithm::Reserved, 0.into());
        assert_eq!(Algorithm::RSA, 1.into());
        assert_eq!(Algorithm::DSA, 2.into());
        assert_eq!(Algorithm::ECDSA, 3.into());
        assert_eq!(Algorithm::Ed25519, 4.into());
        assert_eq!(Algorithm::Unassigned(17), 17.into());
        assert_eq!(Algorithm::Unassigned(42), 42.into());

        assert_eq!(0u8, Algorithm::Reserved.into());
        assert_eq!(1u8, Algorithm::RSA.into());
        assert_eq!(2u8, Algorithm::DSA.into());
        assert_eq!(3u8, Algorithm::ECDSA.into());
        assert_eq!(4u8, Algorithm::Ed25519.into());
        assert_eq!(17u8, Algorithm::Unassigned(17).into());
        assert_eq!(42u8, Algorithm::Unassigned(42).into());
    }

    #[test]
    fn read_fingerprint_type() {
        assert_eq!(FingerprintType::Reserved, 0.into());
        assert_eq!(FingerprintType::SHA1, 1.into());
        assert_eq!(FingerprintType::SHA256, 2.into());
        assert_eq!(FingerprintType::Unassigned(12), 12.into());
        assert_eq!(FingerprintType::Unassigned(89), 89.into());

        assert_eq!(0u8, FingerprintType::Reserved.into());
        assert_eq!(1u8, FingerprintType::SHA1.into());
        assert_eq!(2u8, FingerprintType::SHA256.into());
        assert_eq!(12u8, FingerprintType::Unassigned(12).into());
        assert_eq!(89u8, FingerprintType::Unassigned(89).into());
    }

    fn test_encode_decode(rdata: SSHFP, result: &[u8]) {
        let mut bytes = Vec::new();
        let mut encoder = BinEncoder::new(&mut bytes);
        emit(&mut encoder, &rdata).expect("failed to emit SSHFP");
        let bytes = encoder.into_bytes();
        assert_eq!(bytes, &result);

        let mut decoder = BinDecoder::new(result);
        let read_rdata =
            read(&mut decoder, Restrict::new(result.len() as u16)).expect("failed to read SSHFP");
        assert_eq!(read_rdata, rdata)
    }

    #[test]
    fn test_encode_decode_sshfp() {
        test_encode_decode(
            SSHFP::new(Algorithm::RSA, FingerprintType::SHA256, vec![]),
            &[1, 2],
        );
        test_encode_decode(
            SSHFP::new(
                Algorithm::ECDSA,
                FingerprintType::SHA1,
                vec![115, 115, 104, 102, 112],
            ),
            &[3, 1, 115, 115, 104, 102, 112],
        );
        test_encode_decode(
            SSHFP::new(
                Algorithm::Reserved,
                FingerprintType::Reserved,
                b"ssh fingerprint".to_vec(),
            ),
            &[
                0, 0, 115, 115, 104, 32, 102, 105, 110, 103, 101, 114, 112, 114, 105, 110, 116,
            ],
        );
        test_encode_decode(
            SSHFP::new(
                Algorithm::Unassigned(255),
                FingerprintType::Unassigned(13),
                vec![100, 110, 115, 115, 101, 99, 32, 100, 97, 110, 101],
            ),
            &[255, 13, 100, 110, 115, 115, 101, 99, 32, 100, 97, 110, 101],
        );
    }
}
<|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types for [Matrix](https://matrix.org/) identifiers for devices, events, keys, rooms, servers,
//! users and URIs.

#![warn(missing_docs)]
// FIXME: Remove once lint doesn't trigger on std::convert::TryFrom in macros.rs anymore
#![allow(unused_qualifications)]
#![cfg_attr(docsrs, feature(doc_cfg))]

// Renamed in `Cargo.toml` so we can have a serde feature.
// Rename it back here because `serde1` is ugly.
#[cfg(feature = "serde")]
extern crate serde1 as serde;

use std::convert::TryFrom;

#[cfg(feature = "serde")]
use serde::de::{self, Deserializer, Unexpected};

#[doc(inline)]
pub use crate::{
    crypto_algorithms::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, SigningKeyAlgorithm},
    device_key_id::DeviceKeyId,
    event_id::EventId,
    key_id::{DeviceSigningKeyId, KeyId, ServerSigningKeyId, SigningKeyId},
    mxc_uri::MxcUri,
    opaque_ids::{DeviceId, DeviceIdBox, KeyName, KeyNameBox},
    room_alias_id::RoomAliasId,
    room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId,
    room_version_id::RoomVersionId,
    server_name::{ServerName, ServerNameBox},
    signatures::{DeviceSignatures, EntitySignatures, ServerSignatures, Signatures},
    user_id::UserId,
};
#[doc(inline)]
pub use ruma_identifiers_validation::error::Error;

#[macro_use]
mod macros;

pub mod user_id;

mod crypto_algorithms;
mod device_key_id;
mod event_id;
mod key_id;
mod mxc_uri;
mod opaque_ids;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod server_name;
mod signatures;

/// Check whether a given string is a valid server name according to [the specification][].
///
/// [the specification]: https://matrix.org/docs/spec/appendices#server-name
#[deprecated = "Use the [`ServerName`](server_name/struct.ServerName.html) type instead."]
pub fn is_valid_server_name(name: &str) -> bool {
    <&ServerName>::try_from(name).is_ok()
}

/// Generates a random identifier localpart.
#[cfg(feature = "rand")]
fn generate_localpart(length: usize) -> Box<str> {
    use rand::Rng as _;
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .map(char::from)
        .take(length)
        .collect::<String>()
        .into_boxed_str()
}

/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
#[cfg(feature = "serde")]
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: for<'a> TryFrom<&'a str>,
{
    ruma_serde::deserialize_cow_str(deserializer).and_then(|v| {
        T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
    })
}

/// Shorthand for `Box::<DeviceId>::from`.
#[macro_export]
macro_rules! device_id {
    ($s:tt) => {
        ::std::boxed::Box::<$crate::DeviceId>::from($s)
    };
}

// A plain re-export shows up in rustdoc despite doc(hidden). Use a module instead.
// Bug report: https://github.com/rust-lang/rust/issues/83939
#[doc(hidden)]
pub mod _macros {
    pub use ruma_identifiers_macros::*;
}

/// Compile-time checked `DeviceKeyId` construction.
#[macro_export]
macro_rules! device_key_id {
    ($s:literal) => {
        $crate::_macros::device_key_id!($crate, $s)
    };
}

/// Compile-time checked `EventId` construction.
#[macro_export]
macro_rules! event_id {
    ($s:literal) => {
        $crate::_macros::event_id!($crate, $s)
    };
}

/// Compile-time checked `RoomAliasId` construction.
#[macro_export]
macro_rules! room_alias_id {
    ($s:literal) => {
        $crate::_macros::room_alias_id!($crate, $s)
    };
}

/// Compile-time checked `RoomId` construction.
#[macro_export]
macro_rules! room_id {
    ($s:literal) => {
        $crate::_macros::room_id!($crate, $s)
    };
}

/// Compile-time checked `RoomVersionId` construction.
#[macro_export]
macro_rules! room_version_id {
    ($s:literal) => {
        $crate::_macros::room_version_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
#[deprecated = "use server_signing_key_id!()"]
macro_rules! server_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
macro_rules! server_signing_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerName` construction.
#[macro_export]
macro_rules! server_name {
    ($s:literal) => {
        $crate::_macros::server_name!($crate, $s)
    };
}

/// Compile-time checked `MxcUri` construction.
#[macro_export]
macro_rules! mxc_uri {
    ($s:literal) => {
        $crate::_macros::mxc_uri!($crate, $s)
    };
}

/// Compile-time checked `UserId` construction.
#[macro_export]
macro_rules! user_id {
    ($s:literal) => {
        $crate::_macros::user_id!($crate, $s)
    };
}
<commit_msg>identifiers: Fix unused import without serde feature<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types for [Matrix](https://matrix.org/) identifiers for devices, events, keys, rooms, servers,
//! users and URIs.

#![warn(missing_docs)]
// FIXME: Remove once lint doesn't trigger on std::convert::TryFrom in macros.rs anymore
#![allow(unused_qualifications)]
#![cfg_attr(docsrs, feature(doc_cfg))]

// Renamed in `Cargo.toml` so we can have a serde feature.
// Rename it back here because `serde1` is ugly.
#[cfg(feature = "serde")]
extern crate serde1 as serde;

#[cfg(feature = "serde")]
use std::convert::TryFrom;

#[cfg(feature = "serde")]
use serde::de::{self, Deserializer, Unexpected};

#[doc(inline)]
pub use crate::{
    crypto_algorithms::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, SigningKeyAlgorithm},
    device_key_id::DeviceKeyId,
    event_id::EventId,
    key_id::{DeviceSigningKeyId, KeyId, ServerSigningKeyId, SigningKeyId},
    mxc_uri::MxcUri,
    opaque_ids::{DeviceId, DeviceIdBox, KeyName, KeyNameBox},
    room_alias_id::RoomAliasId,
    room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId,
    room_version_id::RoomVersionId,
    server_name::{ServerName, ServerNameBox},
    signatures::{DeviceSignatures, EntitySignatures, ServerSignatures, Signatures},
    user_id::UserId,
};
#[doc(inline)]
pub use ruma_identifiers_validation::error::Error;

#[macro_use]
mod macros;

pub mod user_id;

mod crypto_algorithms;
mod device_key_id;
mod event_id;
mod key_id;
mod mxc_uri;
mod opaque_ids;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod server_name;
mod signatures;

/// Check whether a given string is a valid server name according to [the specification][].
///
/// [the specification]: https://matrix.org/docs/spec/appendices#server-name
#[deprecated = "Use the [`ServerName`](server_name/struct.ServerName.html) type instead."]
pub fn is_valid_server_name(name: &str) -> bool {
    <&ServerName>::try_from(name).is_ok()
}

/// Generates a random identifier localpart.
#[cfg(feature = "rand")]
fn generate_localpart(length: usize) -> Box<str> {
    use rand::Rng as _;
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .map(char::from)
        .take(length)
        .collect::<String>()
        .into_boxed_str()
}

/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
#[cfg(feature = "serde")]
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: for<'a> TryFrom<&'a str>,
{
    ruma_serde::deserialize_cow_str(deserializer).and_then(|v| {
        T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
    })
}

/// Shorthand for `Box::<DeviceId>::from`.
#[macro_export]
macro_rules! device_id {
    ($s:tt) => {
        ::std::boxed::Box::<$crate::DeviceId>::from($s)
    };
}

// A plain re-export shows up in rustdoc despite doc(hidden). Use a module instead.
// Bug report: https://github.com/rust-lang/rust/issues/83939
#[doc(hidden)]
pub mod _macros {
    pub use ruma_identifiers_macros::*;
}

/// Compile-time checked `DeviceKeyId` construction.
#[macro_export]
macro_rules! device_key_id {
    ($s:literal) => {
        $crate::_macros::device_key_id!($crate, $s)
    };
}

/// Compile-time checked `EventId` construction.
#[macro_export]
macro_rules! event_id {
    ($s:literal) => {
        $crate::_macros::event_id!($crate, $s)
    };
}

/// Compile-time checked `RoomAliasId` construction.
#[macro_export]
macro_rules! room_alias_id {
    ($s:literal) => {
        $crate::_macros::room_alias_id!($crate, $s)
    };
}

/// Compile-time checked `RoomId` construction.
#[macro_export]
macro_rules! room_id {
    ($s:literal) => {
        $crate::_macros::room_id!($crate, $s)
    };
}

/// Compile-time checked `RoomVersionId` construction.
#[macro_export]
macro_rules! room_version_id {
    ($s:literal) => {
        $crate::_macros::room_version_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
#[deprecated = "use server_signing_key_id!()"]
macro_rules! server_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerSigningKeyId` construction.
#[macro_export]
macro_rules! server_signing_key_id {
    ($s:literal) => {
        $crate::_macros::server_signing_key_id!($crate, $s)
    };
}

/// Compile-time checked `ServerName` construction.
#[macro_export]
macro_rules! server_name {
    ($s:literal) => {
        $crate::_macros::server_name!($crate, $s)
    };
}

/// Compile-time checked `MxcUri` construction.
#[macro_export]
macro_rules! mxc_uri {
    ($s:literal) => {
        $crate::_macros::mxc_uri!($crate, $s)
    };
}

/// Compile-time checked `UserId` construction.
#[macro_export]
macro_rules! user_id {
    ($s:literal) => {
        $crate::_macros::user_id!($crate, $s)
    };
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate toornament;

use chrono::offset::Utc;
use toornament::*;

fn workflow() -> Result<()> {
    let tournament_website = Some("https://toornament.com/".to_owned());

    let toornament =
        Toornament::with_application("API_TOKEN", "CLIENT_ID", "CLIENT_SECRET")?.timeout(5)?;

    // Listing all the tournaments
    println!("Tournaments: {:?}\n", toornament.tournaments(None, true));
    // Listing all the disciplines
    println!("Disciplines: {:?}\n", toornament.disciplines(None));
    // Listing all the disciplines
    println!(
        "Disciplines with id=\"wwe2k17\": {:?}\n",
        toornament.disciplines(Some(DisciplineId("wwe2k17".to_owned())))
    );

    // Creating a `Tournament` object for adding it to the service
    let mut tournament = Tournament::create(
        DisciplineId("wwe2k17".to_owned()),
        "test tournament by fx",
        16,
        ParticipantType::Single,
    );
    assert!(tournament.website.is_none());
    // Sending it to the service
    tournament = toornament.edit_tournament(tournament)?;
    println!("Created tournament: {:?}\n", tournament);

    let wwe2k17_tournaments =
        toornament.tournaments(Some(tournament.id.clone().unwrap()), false)?;
    let wwe2k17_t = wwe2k17_tournaments.0.first().clone().unwrap();
    assert_eq!(wwe2k17_t.id, tournament.id);

    // Setting the website and making the tournament public so we can fetch matches.
    // For making the tournament public we must also set start date
    tournament = tournament
        .website(tournament_website.clone())
        .date_start(Some(Utc::today().naive_utc()))
        .public(true);
    assert_eq!(tournament.website, tournament_website);
    assert_eq!(tournament.public, true);

    // Updating our previously created tournament with new website information
    tournament = toornament.edit_tournament(tournament)?;
    assert_eq!(tournament.website, tournament_website);
    assert_eq!(wwe2k17_t.id, tournament.id);

    let my_wwe_t = toornament
        .my_tournaments()?
        .0
        .iter()
        .find(|t| t.id == tournament.id)
        .unwrap()
        .clone();
    println!("My tournaments: {:?}\n", my_wwe_t);

    // Matches are empty since we have just created our tournament
    println!(
        "My matches: {:?}\n",
        toornament.matches(tournament.id.clone().unwrap(), None, true)
    );
    // But let's look all the matches for wwe2k17 discipline
    println!(
        "Matches for wwe2k17: {:?}\n",
        toornament
            .matches_by_discipline(DisciplineId("wwe2k17".to_owned()), MatchFilter::default())
    );

    // Let's create participants and add them to our tournament so we can create matches
    let participants = vec![
        Participant::create("First participant"),
        Participant::create("Second participant"),
    ];

    // Send participants to a tournament with id = "1"
    let _ = toornament.update_tournament_participants(
        tournament.id.clone().unwrap(),
        Participants(participants),
    )?;

    // Get matches
    println!(
        "My matches: {:?}\n",
        toornament.matches(tournament.id.clone().unwrap(), None, true)
    );

    // Deleting our tournament
    println!(
        "Deleted tournament: {:?}\n",
        toornament.delete_tournament(tournament.id.unwrap())
    );

    Ok(())
}

#[cfg(feature = "fancy")]
fn fancy_workflow() -> Result<()> {
    let toornament =
        Toornament::with_application("API_TOKEN", "CLIENT_ID", "CLIENT_SECRET")?.timeout(5);

    let tournament_id = TournamentId("1".to_owned());

    let tournament = Tournament::with_id(tournament_id.clone(), false)?;
    assert_eq!(
        tournament,
        toornament
            .tournaments(Some(tournament_id.clone()), false)?
            .0
            .first()
            .unwrap()
            .clone()
    );

    assert_eq!(
        tournament.stages()?.0.len(),
        toornament.tournament_stages(tournament_id.clone())?.0.len()
    );

    assert_eq!(
        tournament
            .videos(TournamentVideosFilter::default())?
            .0
            .len(),
        toornament
            .tournament_videos(tournament_id.clone(), TournamentVideosFilter::default())?
            .0
            .len()
    );

    assert_eq!(
        Tournaments::all(false)?.0.len(),
        toornament.tournaments(None, false)?.0.len()
    );

    assert_eq!(
        Tournaments::my()?.0.len(),
        toornament.my_tournaments()?.0.len()
    );

    Ok(())
}

fn main() {
    if let Err(e) = workflow() {
        println!("Error occured during the work flow: {:?}", e);
    }

    #[cfg(feature = "fancy")]
    match fancy_workflow() {
        Ok(_) => {}
        Err(e) => println!("Error occured during the fancy work flow: {:?}", e),
    }
}
<commit_msg>Update the workflow example for Rust 2018.<commit_after>use chrono::offset::Utc;
use toornament::*;

fn workflow() -> Result<()> {
    let tournament_website = Some("https://toornament.com/".to_owned());

    let toornament =
        Toornament::with_application("API_TOKEN", "CLIENT_ID", "CLIENT_SECRET")?.timeout(5)?;

    // Listing all the tournaments
    println!("Tournaments: {:?}\n", toornament.tournaments(None, true));
    // Listing all the disciplines
    println!("Disciplines: {:?}\n", toornament.disciplines(None));
    // Listing all the disciplines
    println!(
        "Disciplines with id=\"wwe2k17\": {:?}\n",
        toornament.disciplines(Some(DisciplineId("wwe2k17".to_owned())))
    );

    // Creating a `Tournament` object for adding it to the service
    let mut tournament = Tournament::create(
        DisciplineId("wwe2k17".to_owned()),
        "test tournament by fx",
        16,
        ParticipantType::Single,
    );
    assert!(tournament.website.is_none());
    // Sending it to the service
    tournament = toornament.edit_tournament(tournament)?;
    println!("Created tournament: {:?}\n", tournament);

    let wwe2k17_tournaments =
        toornament.tournaments(Some(tournament.id.clone().unwrap()), false)?;
    let wwe2k17_t = wwe2k17_tournaments.0.first().clone().unwrap();
    assert_eq!(wwe2k17_t.id, tournament.id);

    // Setting the website and making the tournament public so we can fetch matches.
    // For making the tournament public we must also set start date
    tournament = tournament
        .website(tournament_website.clone())
        .date_start(Some(Utc::today().naive_utc()))
        .public(true);
    assert_eq!(tournament.website, tournament_website);
    assert_eq!(tournament.public, true);

    // Updating our previously created tournament with new website information
    tournament = toornament.edit_tournament(tournament)?;
    assert_eq!(tournament.website, tournament_website);
    assert_eq!(wwe2k17_t.id, tournament.id);

    let my_wwe_t = toornament
        .my_tournaments()?
        .0
        .iter()
        .find(|t| t.id == tournament.id)
        .unwrap()
        .clone();
    println!("My tournaments: {:?}\n", my_wwe_t);

    // Matches are empty since we have just created our tournament
    println!(
        "My matches: {:?}\n",
        toornament.matches(tournament.id.clone().unwrap(), None, true)
    );
    // But let's look all the matches for wwe2k17 discipline
    println!(
        "Matches for wwe2k17: {:?}\n",
        toornament
            .matches_by_discipline(DisciplineId("wwe2k17".to_owned()), MatchFilter::default())
    );

    // Let's create participants and add them to our tournament so we can create matches
    let participants = vec![
        Participant::create("First participant"),
        Participant::create("Second participant"),
    ];

    // Send participants to a tournament with id = "1"
    let _ = toornament.update_tournament_participants(
        tournament.id.clone().unwrap(),
        Participants(participants),
    )?;

    // Get matches
    println!(
        "My matches: {:?}\n",
        toornament.matches(tournament.id.clone().unwrap(), None, true)
    );

    // Deleting our tournament
    println!(
        "Deleted tournament: {:?}\n",
        toornament.delete_tournament(tournament.id.unwrap())
    );

    Ok(())
}

#[cfg(feature = "fancy")]
fn fancy_workflow() -> Result<()> {
    let toornament =
        Toornament::with_application("API_TOKEN", "CLIENT_ID", "CLIENT_SECRET")?.timeout(5);

    let tournament_id = TournamentId("1".to_owned());

    let tournament = Tournament::with_id(tournament_id.clone(), false)?;
    assert_eq!(
        tournament,
        toornament
            .tournaments(Some(tournament_id.clone()), false)?
            .0
            .first()
            .unwrap()
            .clone()
    );

    assert_eq!(
        tournament.stages()?.0.len(),
        toornament.tournament_stages(tournament_id.clone())?.0.len()
    );

    assert_eq!(
        tournament
            .videos(TournamentVideosFilter::default())?
            .0
            .len(),
        toornament
            .tournament_videos(tournament_id.clone(), TournamentVideosFilter::default())?
            .0
            .len()
    );

    assert_eq!(
        Tournaments::all(false)?.0.len(),
        toornament.tournaments(None, false)?.0.len()
    );

    assert_eq!(
        Tournaments::my()?.0.len(),
        toornament.my_tournaments()?.0.len()
    );

    Ok(())
}

fn main() {
    if let Err(e) = workflow() {
        println!("Error occured during the work flow: {:?}", e);
    }

    #[cfg(feature = "fancy")]
    match fancy_workflow() {
        Ok(_) => {}
        Err(e) => println!("Error occured during the fancy work flow: {:?}", e),
    }
}
<|endoftext|>


<commit_before>use super::Numeric;

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::ops;
use std::convert;
use std::mem::transmute;

#[cfg(test)] mod test;
#[macro_use] mod macros;

pub trait Matrix<N>: Sized
where N: Numeric {

    fn nrows(&self) -> usize;
    fn ncols(&self) -> usize;

}

#[cfg(not(simd))]
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Hash)]
pub struct Matrix2<N>
where N: Numeric { pub x1y1: N, pub x2y1: N
                 , pub x1y2: N, pub x2y2: N
                 }

 #[cfg(not(simd))]
 #[repr(C)]
 #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Hash)]
pub struct Matrix3<N>
where N: Numeric { pub x1y1: N, pub x2y1: N, pub x3y1: N
                 , pub x1y2: N, pub x2y2: N, pub x3y2: N
                 , pub x1y3: N, pub x2y3: N, pub x3y3: N
                 }

 #[cfg(not(simd))]
 #[repr(C)]
 #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Hash)]
pub struct Matrix4<N>
where N: Numeric { pub x1y1: N, pub x2y1: N, pub x3y1: N, pub x4y1: N
                 , pub x1y2: N, pub x2y2: N, pub x3y2: N, pub x4y2: N
                 , pub x1y3: N, pub x2y3: N, pub x3y3: N, pub x4y3: N
                 , pub x1y4: N, pub x2y4: N, pub x3y4: N, pub x4y4: N
                 }

impl_converts! { Matrix2, 2
               , Matrix3, 3
               , Matrix4, 4
               }
impl_index! { Matrix2, 2
            , Matrix3, 3
            , Matrix4, 4
            }
<commit_msg>[matrix] Relax numeric constraint on matrices<commit_after>use super::Numeric;

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::ops;
use std::convert;
use std::mem::transmute;

#[cfg(test)] mod test;
#[macro_use] mod macros;

pub trait Matrix<N>: Sized {

    fn nrows(&self) -> usize;
    fn ncols(&self) -> usize;

}

//#[cfg(not(simd))]
//#[repr(C)]
//#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Hash)]
//pub struct Matrix2<N>
//where N: Numeric { pub x1y1: N, pub x2y1: N
//                 , pub x1y2: N, pub x2y2: N
//                 }
//
// #[cfg(not(simd))]
// #[repr(C)]
// #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Hash)]
//pub struct Matrix3<N>
//where N: Numeric { pub x1y1: N, pub x2y1: N, pub x3y1: N
//                 , pub x1y2: N, pub x2y2: N, pub x3y2: N
//                 , pub x1y3: N, pub x2y3: N, pub x3y3: N
//                 }
//
// #[cfg(not(simd))]
// #[repr(C)]
// #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Hash)]
//pub struct Matrix4<N> {
//    pub x1y1: N, pub x2y1: N, pub x3y1: N, pub x4y1: N
// , pub x1y2: N, pub x2y2: N, pub x3y2: N, pub x4y2: N
// , pub x1y3: N, pub x2y3: N, pub x3y3: N, pub x4y3: N
// , pub x1y4: N, pub x2y4: N, pub x3y4: N, pub x4y4: N
// }

make_matrix! { Matrix2, rows: 2, cols: 2
             , x1y1, x2y1
             , x1y2, x2y2
             }
make_matrix! { Matrix3, rows: 3, cols: 3
             , x1y1, x2y1, x3y1
             , x1y2, x2y2, x3y2
             , x1y3, x2y3, x3y3
             }
make_matrix! { Matrix4, rows: 4, cols: 4
             , x1y1, x2y1, x3y1, x4y1
             , x1y2, x2y2, x3y2, x4y2
             , x1y3, x2y3, x3y3, x4y3
             , x1y4, x2y4, x3y4, x4y4
             }

//impl_converts! { Matrix2, 2
//               , Matrix3, 3
//               , Matrix4, 4
//               }
//impl_index! { Matrix2, 2
//            , Matrix3, 3
//            , Matrix4, 4
//            }
<|endoftext|>


<commit_before>use mime::{Mime, TopLevel, SubLevel};

use serialize::json;

use std::cell::RefCell;

use std::collections::HashMap;

/// Guess the MIME type of the `Path` by its extension.
///
/// **Guess** is the operative word here, as the contents of a file
/// may not or may not match its MIME type/extension.
pub fn guess_mime_type(path: &Path) -> Mime {
    let ext = path.extension_str().unwrap_or("");

    get_mime_type(ext)
}

/// Extract the extensioin of `filename` and guess its MIME type.
/// If there is no extension, or the extension has no known MIME association,
/// `applicaton/octet-stream` is assumed.
pub fn guess_mime_type_filename(filename: &str) -> Mime {
    let path = Path::new(filename);

    guess_mime_type(&path)
}

local_data_key!(mime_types_cache: RefCell<HashMap<String, Mime>>)

/// Get the MIME type associated with a file extension
/// If there is no association for the extension,
/// `application/octet-stream` is assumed.
pub fn get_mime_type(ext: &str) -> Mime {
    if ext.is_empty() { return octet_stream(); }

    let ext = ext.into_string();

    // MIME Types are cached in a task-local heap
    let cache = if let Some(cache) = mime_types_cache.get() { cache }
    else {
        mime_types_cache.replace(Some(RefCell::new(HashMap::new())));
        mime_types_cache.get().unwrap()
    };

    if let Some(mime_type) = cache.borrow().get(&ext) {
        return mime_type.clone();
    }

    let mime_type = find_mime_type(&*ext);

    cache.borrow_mut().insert(ext, mime_type.clone());

    mime_type
}

const MIME_TYPES: &'static str = include_str!("../mime_types.json");

/// Load the MIME_TYPES as JSON and try to locate `ext`
fn find_mime_type(ext: &str) -> Mime {
    json::from_str(MIME_TYPES).unwrap()
        .find(ext).and_then(|j| j.as_string())
        .and_then(from_str::<Mime>)
        .unwrap_or_else(octet_stream)
}

/// Get the `Mime` type for `application/octet-stream` (generic binary stream)
pub fn octet_stream() -> Mime {
    Mime(TopLevel::Application, SubLevel::Ext("octet-stream".into_string()), Vec::new())
}

#[test]
fn test_mime_type_guessing() {
    assert!(get_mime_type("gif").to_string() == "image/gif".to_string());
    assert!(get_mime_type("txt").to_string() == "text/plain".to_string());
    assert!(get_mime_type("blahblah").to_string() == "application/octet-stream".to_string());
}

<commit_msg>Update mime_guess.rs<commit_after>use mime::{Mime, TopLevel, SubLevel};

use serialize::json;

use std::cell::RefCell;

use std::collections::HashMap;

/// Guess the MIME type of the `Path` by its extension.
///
/// **Guess** is the operative word here, as the contents of a file
/// may not or may not match its MIME type/extension.
pub fn guess_mime_type(path: &Path) -> Mime {
    let ext = path.extension_str().unwrap_or("");

    get_mime_type(ext)
}

/// Extract the extensioin of `filename` and guess its MIME type.
/// If there is no extension, or the extension has no known MIME association,
/// `applicaton/octet-stream` is assumed.
pub fn guess_mime_type_filename(filename: &str) -> Mime {
    let path = Path::new(filename);

    guess_mime_type(&path)
}

local_data_key!(mime_types_cache: RefCell<HashMap<String, Mime>>)

/// Get the MIME type associated with a file extension
/// If there is no association for the extension, or `ext` is empty,
/// `application/octet-stream` is returned.
pub fn get_mime_type(ext: &str) -> Mime {
    if ext.is_empty() { return octet_stream(); }

    let ext = ext.into_string();

    // MIME Types are cached in a task-local heap
    let cache = if let Some(cache) = mime_types_cache.get() { cache }
    else {
        mime_types_cache.replace(Some(RefCell::new(HashMap::new())));
        mime_types_cache.get().unwrap()
    };

    if let Some(mime_type) = cache.borrow().get(&ext) {
        return mime_type.clone();
    }

    let mime_type = find_mime_type(&*ext);

    cache.borrow_mut().insert(ext, mime_type.clone());

    mime_type
}

const MIME_TYPES: &'static str = include_str!("../mime_types.json");

/// Load the MIME_TYPES as JSON and try to locate `ext`
fn find_mime_type(ext: &str) -> Mime {
    json::from_str(MIME_TYPES).unwrap()
        .find(ext).and_then(|j| j.as_string())
        .and_then(from_str::<Mime>)
        .unwrap_or_else(octet_stream)
}

/// Get the `Mime` type for `application/octet-stream` (generic binary stream)
pub fn octet_stream() -> Mime {
    Mime(TopLevel::Application, SubLevel::Ext("octet-stream".into_string()), Vec::new())
}

#[test]
fn test_mime_type_guessing() {
    assert!(get_mime_type("gif").to_string() == "image/gif".to_string());
    assert!(get_mime_type("txt").to_string() == "text/plain".to_string());
    assert!(get_mime_type("blahblah").to_string() == "application/octet-stream".to_string());
}

<|endoftext|>


<commit_before>//! Implements `Multipv`.

use super::{bogus_params, contains_dups};
use super::aspiration::Aspiration;
use std::cmp::{min, max};
use std::time::Duration;
use std::sync::{Arc, RwLock};
use std::sync::mpsc::TryRecvError;
use uci::{SetOption, OptionDescription};
use moves::Move;
use value::*;
use depth::*;
use hash_table::*;
use evaluator::Evaluator;
use search_node::SearchNode;
use search::{SearchParams, SearchReport};

// In this module we use the `DeepeningSearch` trait for depth-first
// searches too, so we rename it to avoid confusion.
use search::DeepeningSearch as SearchExecutor;

/// Executes mulit-PV searches with aspiration windows, complying with
/// `searchmoves`.
///
/// The auxiliary data field of searches' progress reports will
/// contain either an empty vector of moves, or the `searchmoves`
/// vector sorted by descending move strength. This allows the
/// iterative deepening routine to improve `searchmoves`' order on
/// each iteration.
pub struct Multipv<T: SearchExecutor> {
    tt: Arc<T::HashTable>,
    params: SearchParams<T::SearchNode>,
    search_is_terminated: bool,
    previously_searched_nodes: u64,

    // The real work will be handed over to `searcher`.
    searcher: Aspiration<T>,

    // The number of best lines of play that should be calculated.
    variation_count: usize,

    // Whether all legal moves in the root position are considered.
    all_moves_are_considered: bool,

    // The index in `self.params.searchmoves` of the currently
    // considered move.
    current_move_index: usize,

    // The values for the corresponding moves in `self.params.searchmoves`.
    values: Vec<Value>,
}

impl<T: SearchExecutor> SearchExecutor for Multipv<T> {
    type HashTable = T::HashTable;

    type SearchNode = T::SearchNode;

    type ReportData = Vec<Move>;

    fn new(tt: Arc<Self::HashTable>) -> Multipv<T> {
        Multipv {
            tt: tt.clone(),
            params: bogus_params(),
            search_is_terminated: false,
            previously_searched_nodes: 0,
            searcher: Aspiration::new(tt),
            variation_count: 1,
            all_moves_are_considered: true,
            current_move_index: 0,
            values: vec![VALUE_MIN],
        }
    }

    fn start_search(&mut self, params: SearchParams<T::SearchNode>) {
        debug_assert!(params.depth > 0);
        debug_assert!(params.depth <= DEPTH_MAX);
        debug_assert!(params.lower_bound >= VALUE_MIN);
        debug_assert!(params.upper_bound <= VALUE_MAX);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(!contains_dups(&params.searchmoves));

        let n = params.searchmoves.len();
        self.all_moves_are_considered = n == params.position.legal_moves().len();
        self.params = params;
        self.search_is_terminated = false;
        self.previously_searched_nodes = 0;
        self.variation_count = min(n, *VARIATION_COUNT.read().unwrap());
        if n == 0 || self.variation_count == 1 && self.all_moves_are_considered {
            // A plain aspiration search.
            //
            // A search is not a genuine multi-PV search if all legal
            // moves in the root position are being considered, and
            // the number of best lines of play that should be
            // calculated is one or zero. In those cases we fall-back
            // to a plain aspiration search.
            debug_assert!(self.variation_count <= 1);
            self.searcher.lmr_mode = false;
            self.searcher.start_search(self.params.clone());
        } else {
            // A genuine multi-PV search.
            debug_assert!(self.variation_count >= 1);
            self.searcher.lmr_mode = true;
            self.current_move_index = 0;
            self.values = vec![VALUE_MIN; n];
            self.search_current_move();
        }
    }

    fn try_recv_report(&mut self) -> Result<SearchReport<Self::ReportData>, TryRecvError> {
        if self.runs_genuine_multipv_search() {
            let SearchReport {
                searched_nodes,
                value,
                done,
                ..
            } = try!(self.searcher.try_recv_report());
            let mut report = SearchReport {
                search_id: self.params.search_id,
                searched_nodes: self.previously_searched_nodes + searched_nodes,
                depth: 0,
                value: VALUE_UNKNOWN,
                data: vec![],
                done: done,
            };
            if done && !self.search_is_terminated {
                self.previously_searched_nodes = report.searched_nodes;
                self.params.position.undo_last_move();
                self.advance_current_move(-value);
                if self.search_current_move() {
                    report.done = false;
                } else {
                    report.depth = self.params.depth;
                    report.value = self.values[0];
                    report.data = self.params.searchmoves.clone();
                }
            }
            Ok(report)
        } else {
            self.searcher.try_recv_report()
        }
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn send_message(&mut self, message: &str) {
        if message == "TERMINATE" {
            self.search_is_terminated = true;
        }
        self.searcher.send_message(message);
    }
}

impl<T: SearchExecutor> SetOption for Multipv<T> {
    fn options() -> Vec<(&'static str, OptionDescription)> {
        let mut options = vec![("MultiPV",
                                OptionDescription::Spin {
                                    min: 1,
                                    max: 500,
                                    default: 1,
                                })];
        options.extend(Aspiration::<T>::options());
        options
    }

    fn set_option(name: &str, value: &str) {
        if name == "MultiPV" {
            *VARIATION_COUNT.write().unwrap() = max(value.parse::<usize>().unwrap_or(0), 1);
        }
        Aspiration::<T>::set_option(name, value)
    }
}

impl<T: SearchExecutor> Multipv<T> {
    /// Returns the best lines of play so far.
    pub fn extract_variations(&mut self) -> Vec<Variation> {
        let mut variations = vec![];
        if self.runs_genuine_multipv_search() {
            for m in self.params
                    .searchmoves
                    .iter()
                    .take(self.variation_count) {
                let p = &mut self.params.position;
                assert!(p.do_move(*m));
                let mut v = self.tt.extract_pv(p);
                p.undo_last_move();
                v.moves.insert(0, *m);
                v.value = -v.value;
                v.bound = match v.bound {
                    BOUND_LOWER => BOUND_UPPER,
                    BOUND_UPPER => BOUND_LOWER,
                    x => x,
                };
                variations.push(v);
            }
        } else if self.variation_count != 0 {
            debug_assert_eq!(self.variation_count, 1);
            variations.push(self.tt.extract_pv(&self.params.position));
        }
        variations
    }

    fn search_current_move(&mut self) -> bool {
        if self.current_move_index < self.params.searchmoves.len() {
            let alpha = self.values[self.variation_count - 1];
            if alpha < self.params.upper_bound {
                let m = self.params.searchmoves[self.current_move_index];
                assert!(self.params.position.do_move(m));
                self.previously_searched_nodes += 1;
                self.searcher
                    .start_search(SearchParams {
                                      search_id: 0,
                                      depth: self.params.depth - 1,
                                      lower_bound: -self.params.upper_bound,
                                      upper_bound: -max(alpha, self.params.lower_bound),
                                      searchmoves: self.params.position.legal_moves(),
                                      ..self.params.clone()
                                  });
                return true;
            }
        }
        self.write_reslut_to_tt();
        false
    }

    fn write_reslut_to_tt(&self) {
        if self.all_moves_are_considered {
            let value = self.values[0];
            let bound = match value {
                v if v <= self.params.lower_bound => BOUND_UPPER,
                v if v >= self.params.upper_bound => BOUND_LOWER,
                _ => BOUND_EXACT,
            };
            let best_move = self.params.searchmoves[0];
            let p = &self.params.position;
            self.tt
                .store(p.hash(),
                       <T::HashTable as HashTable>::Entry::new(value, bound, self.params.depth)
                           .set_move_digest(best_move.digest())
                           .set_static_eval(p.evaluator().evaluate(p.board())));
        }
    }

    fn advance_current_move(&mut self, v: Value) {
        debug_assert!(v >= self.values[self.current_move_index]);
        let mut i = self.current_move_index;
        self.current_move_index += 1;

        // Update `self.values` making sure that it remains sorted.
        self.values[i] = v;
        while i > 0 && v > self.values[i - 1] {
            self.values.swap(i, i - 1);
            self.params.searchmoves.swap(i, i - 1);
            i -= 1;
        }
    }

    #[inline]
    fn runs_genuine_multipv_search(&self) -> bool {
        self.searcher.lmr_mode
    }
}

lazy_static! {
    static ref VARIATION_COUNT: RwLock<usize> = RwLock::new(1);
}
<commit_msg>make Multipv use get_option()<commit_after>//! Implements `Multipv`.

use super::{bogus_params, contains_dups};
use super::aspiration::Aspiration;
use std::cmp::{min, max};
use std::time::Duration;
use std::sync::Arc;
use std::sync::mpsc::TryRecvError;
use uci::{SetOption, OptionDescription};
use moves::Move;
use value::*;
use depth::*;
use hash_table::*;
use evaluator::Evaluator;
use search_node::SearchNode;
use search::{SearchParams, SearchReport};

// In this module we use the `DeepeningSearch` trait for depth-first
// searches too, so we rename it to avoid confusion.
use search::DeepeningSearch as SearchExecutor;

/// Executes mulit-PV searches with aspiration windows, complying with
/// `searchmoves`.
///
/// The auxiliary data field of searches' progress reports will
/// contain either an empty vector of moves, or the `searchmoves`
/// vector sorted by descending move strength. This allows the
/// iterative deepening routine to improve `searchmoves`' order on
/// each iteration.
pub struct Multipv<T: SearchExecutor> {
    tt: Arc<T::HashTable>,
    params: SearchParams<T::SearchNode>,
    search_is_terminated: bool,
    previously_searched_nodes: u64,

    // The real work will be handed over to `searcher`.
    searcher: Aspiration<T>,

    // The number of best lines of play that should be calculated.
    variation_count: usize,

    // Whether all legal moves in the root position are considered.
    all_moves_are_considered: bool,

    // The index in `self.params.searchmoves` of the currently
    // considered move.
    current_move_index: usize,

    // The values for the corresponding moves in `self.params.searchmoves`.
    values: Vec<Value>,
}

impl<T: SearchExecutor> SearchExecutor for Multipv<T> {
    type HashTable = T::HashTable;

    type SearchNode = T::SearchNode;

    type ReportData = Vec<Move>;

    fn new(tt: Arc<Self::HashTable>) -> Multipv<T> {
        Multipv {
            tt: tt.clone(),
            params: bogus_params(),
            search_is_terminated: false,
            previously_searched_nodes: 0,
            searcher: Aspiration::new(tt),
            variation_count: 1,
            all_moves_are_considered: true,
            current_move_index: 0,
            values: vec![VALUE_MIN],
        }
    }

    fn start_search(&mut self, params: SearchParams<T::SearchNode>) {
        debug_assert!(params.depth > 0);
        debug_assert!(params.depth <= DEPTH_MAX);
        debug_assert!(params.lower_bound >= VALUE_MIN);
        debug_assert!(params.upper_bound <= VALUE_MAX);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(!contains_dups(&params.searchmoves));

        let n = params.searchmoves.len();
        self.all_moves_are_considered = n == params.position.legal_moves().len();
        self.params = params;
        self.search_is_terminated = false;
        self.previously_searched_nodes = 0;
        self.variation_count = min(n, max(1, ::get_option("MultiPV").parse().unwrap_or(0)));
        if n == 0 || self.variation_count == 1 && self.all_moves_are_considered {
            // A plain aspiration search.
            //
            // A search is not a genuine multi-PV search if all legal
            // moves in the root position are being considered, and
            // the number of best lines of play that should be
            // calculated is one or zero. In those cases we fall-back
            // to a plain aspiration search.
            debug_assert!(self.variation_count <= 1);
            self.searcher.lmr_mode = false;
            self.searcher.start_search(self.params.clone());
        } else {
            // A genuine multi-PV search.
            debug_assert!(self.variation_count >= 1);
            self.searcher.lmr_mode = true;
            self.current_move_index = 0;
            self.values = vec![VALUE_MIN; n];
            self.search_current_move();
        }
    }

    fn try_recv_report(&mut self) -> Result<SearchReport<Self::ReportData>, TryRecvError> {
        if self.runs_genuine_multipv_search() {
            let SearchReport {
                searched_nodes,
                value,
                done,
                ..
            } = try!(self.searcher.try_recv_report());
            let mut report = SearchReport {
                search_id: self.params.search_id,
                searched_nodes: self.previously_searched_nodes + searched_nodes,
                depth: 0,
                value: VALUE_UNKNOWN,
                data: vec![],
                done: done,
            };
            if done && !self.search_is_terminated {
                self.previously_searched_nodes = report.searched_nodes;
                self.params.position.undo_last_move();
                self.advance_current_move(-value);
                if self.search_current_move() {
                    report.done = false;
                } else {
                    report.depth = self.params.depth;
                    report.value = self.values[0];
                    report.data = self.params.searchmoves.clone();
                }
            }
            Ok(report)
        } else {
            self.searcher.try_recv_report()
        }
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn send_message(&mut self, message: &str) {
        if message == "TERMINATE" {
            self.search_is_terminated = true;
        }
        self.searcher.send_message(message);
    }
}

impl<T: SearchExecutor> SetOption for Multipv<T> {
    fn options() -> Vec<(&'static str, OptionDescription)> {
        let mut options = vec![("MultiPV",
                                OptionDescription::Spin {
                                    min: 1,
                                    max: 500,
                                    default: 1,
                                })];
        options.extend(Aspiration::<T>::options());
        options
    }

    fn set_option(name: &str, value: &str) {
        Aspiration::<T>::set_option(name, value)
    }
}

impl<T: SearchExecutor> Multipv<T> {
    /// Returns the best lines of play so far.
    pub fn extract_variations(&mut self) -> Vec<Variation> {
        let mut variations = vec![];
        if self.runs_genuine_multipv_search() {
            for m in self.params
                    .searchmoves
                    .iter()
                    .take(self.variation_count) {
                let p = &mut self.params.position;
                assert!(p.do_move(*m));
                let mut v = self.tt.extract_pv(p);
                p.undo_last_move();
                v.moves.insert(0, *m);
                v.value = -v.value;
                v.bound = match v.bound {
                    BOUND_LOWER => BOUND_UPPER,
                    BOUND_UPPER => BOUND_LOWER,
                    x => x,
                };
                variations.push(v);
            }
        } else if self.variation_count != 0 {
            debug_assert_eq!(self.variation_count, 1);
            variations.push(self.tt.extract_pv(&self.params.position));
        }
        variations
    }

    fn search_current_move(&mut self) -> bool {
        if self.current_move_index < self.params.searchmoves.len() {
            let alpha = self.values[self.variation_count - 1];
            if alpha < self.params.upper_bound {
                let m = self.params.searchmoves[self.current_move_index];
                assert!(self.params.position.do_move(m));
                self.previously_searched_nodes += 1;
                self.searcher
                    .start_search(SearchParams {
                                      search_id: 0,
                                      depth: self.params.depth - 1,
                                      lower_bound: -self.params.upper_bound,
                                      upper_bound: -max(alpha, self.params.lower_bound),
                                      searchmoves: self.params.position.legal_moves(),
                                      ..self.params.clone()
                                  });
                return true;
            }
        }
        self.write_reslut_to_tt();
        false
    }

    fn write_reslut_to_tt(&self) {
        if self.all_moves_are_considered {
            let value = self.values[0];
            let bound = match value {
                v if v <= self.params.lower_bound => BOUND_UPPER,
                v if v >= self.params.upper_bound => BOUND_LOWER,
                _ => BOUND_EXACT,
            };
            let best_move = self.params.searchmoves[0];
            let p = &self.params.position;
            self.tt
                .store(p.hash(),
                       <T::HashTable as HashTable>::Entry::new(value, bound, self.params.depth)
                           .set_move_digest(best_move.digest())
                           .set_static_eval(p.evaluator().evaluate(p.board())));
        }
    }

    fn advance_current_move(&mut self, v: Value) {
        debug_assert!(v >= self.values[self.current_move_index]);
        let mut i = self.current_move_index;
        self.current_move_index += 1;

        // Update `self.values` making sure that it remains sorted.
        self.values[i] = v;
        while i > 0 && v > self.values[i - 1] {
            self.values.swap(i, i - 1);
            self.params.searchmoves.swap(i, i - 1);
            i -= 1;
        }
    }

    #[inline]
    fn runs_genuine_multipv_search(&self) -> bool {
        self.searcher.lmr_mode
    }
}
<|endoftext|>


<commit_before>/* Copyright 2013 Leon Sixt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::hashmap::HashSet;
use std::cast;
use extra::sync::Mutex;

pub trait LockManager<T> {
    fn lock(&self, id: T);
    fn unlock(&self, id: &T);
}

struct SimpleLockManager<T> {
    set: HashSet<T>,
    mutex: Mutex
}

impl<T: Hash + Eq + Freeze> SimpleLockManager<T> {
    pub fn new() -> SimpleLockManager<T> {
        SimpleLockManager {
            set: HashSet::new(),
            mutex: Mutex::new()
        }
    }
}
impl<T: Hash + Eq + Clone + Freeze + ToStr> LockManager<T> for SimpleLockManager<T> {
    fn lock(&self, id: T) {
        debug!("locking ptr: {}", id.to_str());
        do self.mutex.lock_cond |cond| {
            while self.set.contains(&id) {
                cond.wait();
            }
            unsafe {
                let mut_set = cast::transmute_mut(&self.set);
                mut_set.insert(id.clone());
            }
        }
    }
    fn unlock(&self, id: &T) {
        do self.mutex.lock_cond |cond| {
            unsafe {
                let mut_set = cast::transmute_mut(&self.set);
                mut_set.remove(id);
                cond.signal();
            }
        }
    }
}
<commit_msg>disabled locking<commit_after>/* Copyright 2013 Leon Sixt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::hashmap::HashSet;
use std::cast;
use extra::sync::Mutex;

pub trait LockManager<T> {
    fn lock(&self, id: T);
    fn unlock(&self, id: &T);
}

struct SimpleLockManager<T> {
    set: HashSet<T>,
    mutex: Mutex
}

impl<T: Hash + Eq + Freeze> SimpleLockManager<T> {
    pub fn new() -> SimpleLockManager<T> {
        SimpleLockManager {
            set: HashSet::new(),
            mutex: Mutex::new()
        }
    }
}
impl<T: Hash + Eq + Clone + Freeze + ToStr> LockManager<T> for SimpleLockManager<T> {
    fn lock(&self, id: T) {
        debug!("locking ptr: {}", id.to_str());
       /* do self.mutex.lock_cond |cond| {
            while self.set.contains(&id) {
                cond.wait();
            }
            unsafe {
                let mut_set = cast::transmute_mut(&self.set);
                mut_set.insert(id.clone());
            }
        }*/
    }
    fn unlock(&self, id: &T) {
        debug!("unlocking ptr: {}", id.to_str());
        /*do self.mutex.lock_cond |cond| {
            unsafe {
                let mut_set = cast::transmute_mut(&self.set);
                mut_set.remove(id);
                cond.signal();
            }
        }*/
    }
}
<|endoftext|>