<commit_before>// Copyright 2017 Amos Onn.
//
// 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 std::result;
use libc;

pub type Result<T> = result::Result<T, libc::c_int>;

use super::fusefl::*;

pub trait ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
}

pub trait WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;

    fn flush(&self) -> Result<()> {
        Ok(())
    }
}

pub struct ReadWriteAdaptor<R, W> {
    reader: R,
    writer: W,
}

impl<R, _> ReadUnixExt for ReadWriteAdaptor<R, _> where R: ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        self.reader.read_at(buf, offset)
    }
}

impl<_, W> WriteUnixExt for ReadWriteAdaptor<_, W> where W: WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        self.writer.write_at(buf, offset)
    }

    fn flush(&self) -> Result<()> {
        self.writer.flush()
    }
}

pub enum ModalFileLike<R, W, RW> {
    ReadOnly(R),
    WriteOnly(W),
    ReadWrite(RW),
}

impl<R, _, RW> ReadUnixExt for ModalFileLike<R, _, RW> where
    R: ReadUnixExt, RW: ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(r) => r.read_at(buf, offset),
            WriteOnly(_) => Err(libc::EBADF),
            ReadWrite(rw) => rw.read_at(buf, offset),
        }
    }
}

impl<_, W, RW> WriteUnixExt for ModalFileLike<_, W, RW> where
    W: WriteUnixExt, RW: WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.write_at(buf, offset),
            ReadWrite(rw) => rw.write_at(buf, offset),
        }
    }

    fn flush(&self) -> Result<()> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.flush(),
            ReadWrite(rw) => rw.flush(),
        }
    }
}

// Part of this will become a default impl of FilesystemFL when RFC #1210 lands.
pub trait FilesystemFLOpen {
    type FileLike: ReadUnixExt+WriteUnixExt;

    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    /// If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the
    /// mknod() and open() methods will be called instead.
    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    fn read(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _size: u32) -> ResultData {
        let mut vec = Vec<u8>::with_capacity(_size);
        unsafe { vec.set_len(_size) };
        let num_read = _fl.read_at(vec.as_mut_slice(), _offset)?;
        assert!(num_read <= _size);
        unsafe { vec.set_len(num_read) };
        Ok(vec)
    }

    fn write(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
        assert!(_data.len() <= u32::max_value());
        _fl.write_at(vec.as_slice(), _offset).map(|x| x as u32)
    }

    fn fsync(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _datasync: bool) -> ResultEmpty {
        Err(libc::ENOSYS)
    }
}
<commit_msg>Renamed ..UnixExt to ..FileLike.<commit_after>// Copyright 2017 Amos Onn.
//
// 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 std::result;
use libc;

pub type Result<T> = result::Result<T, libc::c_int>;

use super::fusefl::*;

pub trait ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
}

pub trait WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;

    fn flush(&self) -> Result<()> {
        Ok(())
    }
}

pub struct ReadWriteAdaptor<R, W> {
    reader: R,
    writer: W,
}

impl<R, _> ReadFileLike for ReadWriteAdaptor<R, _> where R: ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        self.reader.read_at(buf, offset)
    }
}

impl<_, W> WriteFileLike for ReadWriteAdaptor<_, W> where W: WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        self.writer.write_at(buf, offset)
    }

    fn flush(&self) -> Result<()> {
        self.writer.flush()
    }
}

pub enum ModalFileLike<R, W, RW> {
    ReadOnly(R),
    WriteOnly(W),
    ReadWrite(RW),
}

impl<R, _, RW> ReadFileLike for ModalFileLike<R, _, RW> where
    R: ReadFileLike, RW: ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(r) => r.read_at(buf, offset),
            WriteOnly(_) => Err(libc::EBADF),
            ReadWrite(rw) => rw.read_at(buf, offset),
        }
    }
}

impl<_, W, RW> WriteFileLike for ModalFileLike<_, W, RW> where
    W: WriteFileLike, RW: WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.write_at(buf, offset),
            ReadWrite(rw) => rw.write_at(buf, offset),
        }
    }

    fn flush(&self) -> Result<()> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.flush(),
            ReadWrite(rw) => rw.flush(),
        }
    }
}

// Part of this will become a default impl of FilesystemFL when RFC #1210 lands.
pub trait FilesystemFLOpen {
    type FileLike: ReadFileLike+WriteFileLike;

    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    /// If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the
    /// mknod() and open() methods will be called instead.
    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    fn read(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _size: u32) -> ResultData {
        let mut vec = Vec<u8>::with_capacity(_size);
        unsafe { vec.set_len(_size) };
        let num_read = _fl.read_at(vec.as_mut_slice(), _offset)?;
        assert!(num_read <= _size);
        unsafe { vec.set_len(num_read) };
        Ok(vec)
    }

    fn write(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
        assert!(_data.len() <= u32::max_value());
        _fl.write_at(vec.as_slice(), _offset).map(|x| x as u32)
    }

    fn fsync(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _datasync: bool) -> ResultEmpty {
        Err(libc::ENOSYS)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#[cfg(any(test, feature = "testing"))]
use crate::account_config::{account_resource_path, AccountResource};
use crate::{
    account_address::AccountAddress,
    account_config::get_account_resource_or_default,
    ledger_info::LedgerInfo,
    proof::{verify_account_state, AccountStateProof},
    transaction::Version,
};

use canonical_serialization::{SimpleDeserializer, SimpleSerializer};
use crypto::{
    hash::{AccountStateBlobHasher, CryptoHash, CryptoHasher},
    HashValue,
};
use failure::prelude::*;
#[cfg(any(test, feature = "testing"))]
use proptest::{arbitrary::Arbitrary, prelude::*};
#[cfg(any(test, feature = "testing"))]
use proptest_derive::Arbitrary;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, convert::TryFrom, fmt};

#[derive(Clone, Eq, PartialEq, FromProto, IntoProto, Serialize, Deserialize)]
#[ProtoType(crate::proto::account_state_blob::AccountStateBlob)]
pub struct AccountStateBlob {
    blob: Vec<u8>,
}

impl fmt::Debug for AccountStateBlob {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let decoded = get_account_resource_or_default(&Some(self.clone()))
            .map(|resource| format!("{:#?}", resource))
            .unwrap_or_else(|_| String::from("[fail]"));

        write!(
            f,
            "AccountStateBlob {{ \n \
             Raw: 0x{} \n \
             Decoded: {} \n \
             }}",
            hex::encode(&self.blob),
            decoded,
        )
    }
}

impl AsRef<[u8]> for AccountStateBlob {
    fn as_ref(&self) -> &[u8] {
        &self.blob
    }
}

impl From<AccountStateBlob> for Vec<u8> {
    fn from(account_state_blob: AccountStateBlob) -> Vec<u8> {
        account_state_blob.blob
    }
}

impl From<Vec<u8>> for AccountStateBlob {
    fn from(blob: Vec<u8>) -> AccountStateBlob {
        AccountStateBlob { blob }
    }
}

impl TryFrom<&BTreeMap<Vec<u8>, Vec<u8>>> for AccountStateBlob {
    type Error = failure::Error;

    fn try_from(map: &BTreeMap<Vec<u8>, Vec<u8>>) -> Result<Self> {
        Ok(Self {
            blob: SimpleSerializer::serialize(map)?,
        })
    }
}

#[cfg(any(test, feature = "testing"))]
impl From<AccountResource> for AccountStateBlob {
    fn from(account_resource: AccountResource) -> Self {
        let mut account_state: BTreeMap<Vec<u8>, Vec<u8>> = BTreeMap::new();
        account_state.insert(
            account_resource_path(),
            SimpleSerializer::<Vec<u8>>::serialize(&account_resource).unwrap(),
        );
        AccountStateBlob::try_from(&account_state).unwrap()
    }
}

impl TryFrom<&AccountStateBlob> for BTreeMap<Vec<u8>, Vec<u8>> {
    type Error = failure::Error;

    fn try_from(account_state_blob: &AccountStateBlob) -> Result<Self> {
        SimpleDeserializer::deserialize(&account_state_blob.blob)
    }
}

impl CryptoHash for AccountStateBlob {
    type Hasher = AccountStateBlobHasher;

    fn hash(&self) -> HashValue {
        let mut hasher = Self::Hasher::default();
        hasher.write(&self.blob);
        hasher.finish()
    }
}

#[cfg(any(test, feature = "testing"))]
prop_compose! {
    pub fn account_state_blob_strategy()(account_resource in any::<AccountResource>()) -> AccountStateBlob {
        AccountStateBlob::from(account_resource)
    }
}

#[cfg(any(test, feature = "testing"))]
impl Arbitrary for AccountStateBlob {
    type Parameters = ();
    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
        account_state_blob_strategy().boxed()
    }

    type Strategy = BoxedStrategy<Self>;
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
pub struct AccountStateWithProof {
    /// The transaction version at which this account state is seen.
    pub version: Version,
    /// Blob value representing the account state. If this field is not set, it
    /// means the account does not exist.
    pub blob: Option<AccountStateBlob>,
    /// The proof the client can use to authenticate the value.
    pub proof: AccountStateProof,
}

impl AccountStateWithProof {
    /// Constructor.
    pub fn new(version: Version, blob: Option<AccountStateBlob>, proof: AccountStateProof) -> Self {
        Self {
            version,
            blob,
            proof,
        }
    }

    /// Verifies the the account state blob with the proof, both carried by `self`.
    ///
    /// Two things are ensured if no error is raised:
    ///   1. This account state exists in the ledger represented by `ledger_info`.
    ///   2. It belongs to account of `address` and is seen at the time the transaction at version
    /// `state_version` is just committed. To make sure this is the latest state, pass in
    /// `ledger_info.version()` as `state_version`.
    pub fn verify(
        &self,
        ledger_info: &LedgerInfo,
        version: Version,
        address: AccountAddress,
    ) -> Result<()> {
        ensure!(
            self.version == version,
            "State version ({}) is not expected ({}).",
            self.version,
            version,
        );

        verify_account_state(
            ledger_info,
            version,
            address.hash(),
            &self.blob,
            &self.proof,
        )
    }
}

impl FromProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        Ok(AccountStateWithProof {
            version: object.get_version(),
            blob: object
                .blob
                .take()
                .map(AccountStateBlob::from_proto)
                .transpose()?,
            proof: AccountStateProof::from_proto(object.take_proof())?,
        })
    }
}

impl IntoProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn into_proto(self) -> Self::ProtoType {
        let mut out = Self::ProtoType::new();
        out.set_version(self.version);
        if let Some(blob) = self.blob {
            out.set_blob(blob.into_proto());
        }
        out.set_proof(self.proof.into_proto());
        out
    }
}

#[cfg(test)]
mod account_state_blob_test;
<commit_msg>[types] impl conversions from/to prost proto and AccountStateBlob<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#[cfg(any(test, feature = "testing"))]
use crate::account_config::{account_resource_path, AccountResource};
use crate::{
    account_address::AccountAddress,
    account_config::get_account_resource_or_default,
    ledger_info::LedgerInfo,
    proof::{verify_account_state, AccountStateProof},
    transaction::Version,
};

use canonical_serialization::{SimpleDeserializer, SimpleSerializer};
use crypto::{
    hash::{AccountStateBlobHasher, CryptoHash, CryptoHasher},
    HashValue,
};
use failure::prelude::*;
#[cfg(any(test, feature = "testing"))]
use proptest::{arbitrary::Arbitrary, prelude::*};
#[cfg(any(test, feature = "testing"))]
use proptest_derive::Arbitrary;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, convert::TryFrom, fmt};

#[derive(Clone, Eq, PartialEq, FromProto, IntoProto, Serialize, Deserialize)]
#[ProtoType(crate::proto::account_state_blob::AccountStateBlob)]
pub struct AccountStateBlob {
    blob: Vec<u8>,
}

impl fmt::Debug for AccountStateBlob {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let decoded = get_account_resource_or_default(&Some(self.clone()))
            .map(|resource| format!("{:#?}", resource))
            .unwrap_or_else(|_| String::from("[fail]"));

        write!(
            f,
            "AccountStateBlob {{ \n \
             Raw: 0x{} \n \
             Decoded: {} \n \
             }}",
            hex::encode(&self.blob),
            decoded,
        )
    }
}

impl AsRef<[u8]> for AccountStateBlob {
    fn as_ref(&self) -> &[u8] {
        &self.blob
    }
}

impl From<AccountStateBlob> for Vec<u8> {
    fn from(account_state_blob: AccountStateBlob) -> Vec<u8> {
        account_state_blob.blob
    }
}

impl From<Vec<u8>> for AccountStateBlob {
    fn from(blob: Vec<u8>) -> AccountStateBlob {
        AccountStateBlob { blob }
    }
}

impl TryFrom<&BTreeMap<Vec<u8>, Vec<u8>>> for AccountStateBlob {
    type Error = failure::Error;

    fn try_from(map: &BTreeMap<Vec<u8>, Vec<u8>>) -> Result<Self> {
        Ok(Self {
            blob: SimpleSerializer::serialize(map)?,
        })
    }
}

impl TryFrom<crate::proto::types::AccountStateBlob> for AccountStateBlob {
    type Error = Error;

    fn try_from(proto: crate::proto::types::AccountStateBlob) -> Result<Self> {
        Ok(proto.blob.into())
    }
}

impl From<AccountStateBlob> for crate::proto::types::AccountStateBlob {
    fn from(blob: AccountStateBlob) -> Self {
        Self { blob: blob.blob }
    }
}

#[cfg(any(test, feature = "testing"))]
impl From<AccountResource> for AccountStateBlob {
    fn from(account_resource: AccountResource) -> Self {
        let mut account_state: BTreeMap<Vec<u8>, Vec<u8>> = BTreeMap::new();
        account_state.insert(
            account_resource_path(),
            SimpleSerializer::<Vec<u8>>::serialize(&account_resource).unwrap(),
        );
        AccountStateBlob::try_from(&account_state).unwrap()
    }
}

impl TryFrom<&AccountStateBlob> for BTreeMap<Vec<u8>, Vec<u8>> {
    type Error = failure::Error;

    fn try_from(account_state_blob: &AccountStateBlob) -> Result<Self> {
        SimpleDeserializer::deserialize(&account_state_blob.blob)
    }
}

impl CryptoHash for AccountStateBlob {
    type Hasher = AccountStateBlobHasher;

    fn hash(&self) -> HashValue {
        let mut hasher = Self::Hasher::default();
        hasher.write(&self.blob);
        hasher.finish()
    }
}

#[cfg(any(test, feature = "testing"))]
prop_compose! {
    pub fn account_state_blob_strategy()(account_resource in any::<AccountResource>()) -> AccountStateBlob {
        AccountStateBlob::from(account_resource)
    }
}

#[cfg(any(test, feature = "testing"))]
impl Arbitrary for AccountStateBlob {
    type Parameters = ();
    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
        account_state_blob_strategy().boxed()
    }

    type Strategy = BoxedStrategy<Self>;
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
pub struct AccountStateWithProof {
    /// The transaction version at which this account state is seen.
    pub version: Version,
    /// Blob value representing the account state. If this field is not set, it
    /// means the account does not exist.
    pub blob: Option<AccountStateBlob>,
    /// The proof the client can use to authenticate the value.
    pub proof: AccountStateProof,
}

impl AccountStateWithProof {
    /// Constructor.
    pub fn new(version: Version, blob: Option<AccountStateBlob>, proof: AccountStateProof) -> Self {
        Self {
            version,
            blob,
            proof,
        }
    }

    /// Verifies the the account state blob with the proof, both carried by `self`.
    ///
    /// Two things are ensured if no error is raised:
    ///   1. This account state exists in the ledger represented by `ledger_info`.
    ///   2. It belongs to account of `address` and is seen at the time the transaction at version
    /// `state_version` is just committed. To make sure this is the latest state, pass in
    /// `ledger_info.version()` as `state_version`.
    pub fn verify(
        &self,
        ledger_info: &LedgerInfo,
        version: Version,
        address: AccountAddress,
    ) -> Result<()> {
        ensure!(
            self.version == version,
            "State version ({}) is not expected ({}).",
            self.version,
            version,
        );

        verify_account_state(
            ledger_info,
            version,
            address.hash(),
            &self.blob,
            &self.proof,
        )
    }
}

impl FromProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        Ok(AccountStateWithProof {
            version: object.get_version(),
            blob: object
                .blob
                .take()
                .map(AccountStateBlob::from_proto)
                .transpose()?,
            proof: AccountStateProof::from_proto(object.take_proof())?,
        })
    }
}

impl IntoProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn into_proto(self) -> Self::ProtoType {
        let mut out = Self::ProtoType::new();
        out.set_version(self.version);
        if let Some(blob) = self.blob {
            out.set_blob(blob.into_proto());
        }
        out.set_proof(self.proof.into_proto());
        out
    }
}

#[cfg(test)]
mod account_state_blob_test;
<|endoftext|>


<commit_before>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread;

use bincode::rustc_serialize::decode;

static LIB_NAME: &'static str = "ws-p2p";

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                let message: PeerMessage = decode(encoded_msg).unwrap();

                info!(target: LIB_NAME, "Peer {} with clocks: {:?} got message: {}",
                        message.sender, message.clocks, message.message);
                if message.sender.as_str() == "127.0.0.1:3013" {
                    info!(target: LIB_NAME, "Faking delay!");
                    thread::sleep(Duration::from_millis(4000))
                }
                //message_checking(&mut clocks, message.clone());
				message_handler(message, self.clocks.clone());
                Ok(())
            },
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to the client list", string);
                let mut clocks = self.clocks.lock().unwrap();
                clocks.insert(string, 0u32);
                Ok(())
            }
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        //TODO: Remove disconnected client's clock from our vclock copy.
        if reason.is_empty() {
            //This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "Client disconnected with code: {:?} and reason: {}", code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
}

pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks,
            me: String::from("undefined"),
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
        }
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
        }
    }
}

fn message_handler(message: PeerMessage, vclocks: Arc<Mutex<HashMap<String, u32>>>) {
    let mut vclocks = vclocks.lock().unwrap();
    for (key, val) in message.clocks.iter() {
        if let Some(lval) = vclocks.get(&key.clone()) {
            debug!(target: LIB_NAME, "key: {} incoming val: {} and lval: {}", key, val, lval);
            if lval <= val {
                debug!(target: LIB_NAME, "val <= lval");
                continue;
            } else { // There's a clock that is greater than what we have
                // Push to local buffer
                // return
                debug!(target: LIB_NAME, "clock discrepency");
                ()
            }
        }
    }

    // Update clocks
    for (key, val) in message.clocks.iter() {
        let lval = vclocks.get(&key.clone()).unwrap().clone();
        let max_val = cmp::max(val, &lval);
        vclocks.insert(key.clone(), *max_val);
    }
//	macro_rules! hashmap {
//		($( $key: expr => $val: expr ),*) => {{
//			 let mut map = ::std::collections::HashMap::new();
//			 $( map.insert($key, $val); )*
//			 map
//		}}
//	}
    //let map = hashmap!['a' => 0, 'b' => 1];
}

<commit_msg>Added mutex locked buffer to factory/handler<commit_after>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread;

use bincode::rustc_serialize::decode;

static LIB_NAME: &'static str = "ws-p2p";

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                let message: PeerMessage = decode(encoded_msg).unwrap();

                info!(target: LIB_NAME, "Peer {} with clocks: {:?} got message: {}",
                        message.sender, message.clocks, message.message);
                if message.sender.as_str() == "127.0.0.1:3013" {
                    info!(target: LIB_NAME, "Faking delay!");
                    thread::sleep(Duration::from_millis(4000))
                }
                //message_checking(&mut clocks, message.clone());
				message_handler(message, self.clocks.clone());
                Ok(())
            },
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to the client list", string);
                let mut clocks = self.clocks.lock().unwrap();
                clocks.insert(string, 0u32);
                Ok(())
            }
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        //TODO: Remove disconnected client's clock from our vclock copy.
        if reason.is_empty() {
            //This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "Client disconnected with code: {:?} and reason: {}", code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
}

pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks,
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
        }
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
        }
    }
}

fn message_handler(message: PeerMessage, vclocks: Arc<Mutex<HashMap<String, u32>>>) {
    let mut vclocks = vclocks.lock().unwrap();
    for (key, val) in message.clocks.iter() {
        if let Some(lval) = vclocks.get(&key.clone()) {
            debug!(target: LIB_NAME, "key: {} incoming val: {} and lval: {}", key, val, lval);
            if lval <= val {
                debug!(target: LIB_NAME, "val <= lval");
                continue;
            } else { // There's a clock that is greater than what we have
                // Push to local buffer
                // return
                debug!(target: LIB_NAME, "clock discrepency");
                ()
            }
        }
    }

    // Update clocks
    for (key, val) in message.clocks.iter() {
        let lval = vclocks.get(&key.clone()).unwrap().clone();
        let max_val = cmp::max(val, &lval);
        vclocks.insert(key.clone(), *max_val);
    }
//	macro_rules! hashmap {
//		($( $key: expr => $val: expr ),*) => {{
//			 let mut map = ::std::collections::HashMap::new();
//			 $( map.insert($key, $val); )*
//			 map
//		}}
//	}
    //let map = hashmap!['a' => 0, 'b' => 1];
}

<|endoftext|>


<commit_before>use std::cell::Cell;
use std::mem;
use std::ptr;

use super::{Allocator, AllocatorError, Block, HeapAllocator, HEAP};

/// A `FreeList` allocator manages a list of free memory blocks of uniform size.
/// Whenever a block is requested, it returns the first free block.
pub struct FreeList<'a, A: 'a + Allocator> {
    alloc: &'a A,
    block_size: usize,
    free_list: Cell<*mut u8>,
}

impl FreeList<'static, HeapAllocator> {
    /// Creates a new `FreeList` backed by the heap. `block_size` must be greater
    /// than or equal to the size of a pointer.
    pub fn new(block_size: usize, num_blocks: usize) -> Result<Self, AllocatorError> {
        FreeList::new_from(HEAP, block_size, num_blocks)
    }
}
impl<'a, A: 'a + Allocator> FreeList<'a, A> {
    /// Creates a new `FreeList` backed by another allocator. `block_size` must be greater
    /// than or equal to the size of a pointer.
    pub fn new_from(alloc: &'a A, block_size: usize, num_blocks: usize) -> Result<Self, AllocatorError> {
        if block_size < mem::size_of::<*mut u8>() {
            return Err(AllocatorError::AllocatorSpecific("Block size too small.".into()));
        }

        let mut free_list = ptr::null_mut();

        // allocate each block with maximal alignment.
        for _ in 0..num_blocks {

            match unsafe { alloc.allocate_raw(block_size, mem::align_of::<*mut u8>()) } {
                Ok(block) => {
                    let ptr: *mut *mut u8 = block.ptr() as *mut *mut u8;
                    unsafe { *ptr = free_list };
                    free_list = block.ptr();
                }
                Err(err) => {
                    // destructor cleans up after us.
                    drop(FreeList {
                        alloc: alloc,
                        block_size: block_size,
                        free_list: Cell::new(free_list),
                    });

                    return Err(err);
                }
            }
        }

        Ok(FreeList {
            alloc: alloc,
            block_size: block_size,
            free_list: Cell::new(free_list)
        })
    }
}

unsafe impl<'a, A: 'a + Allocator> Allocator for FreeList<'a, A> {
    unsafe fn allocate_raw(&self, size: usize, align: usize) -> Result<Block, AllocatorError> {
        debug_assert!(align <= mem::align_of::<*mut u8>(),
            "Cannot allocate higher than pointer-width alignment.");
        if size == 0 { return Ok(Block::empty()); }
        else if size > self.block_size {
            return Err(AllocatorError::OutOfMemory);
        }

        let free_list = self.free_list.get();
        if !free_list.is_null() {
            let next_block = *(free_list as *mut *mut u8);
            self.free_list.set(next_block);

            Ok(Block::new(free_list, self.block_size, align))
        } else {
            Err(AllocatorError::OutOfMemory)
        }
    }

    unsafe fn deallocate_raw(&self, blk: Block) {
        if blk.size() == self.block_size && !blk.ptr().is_null() {
            let first = self.free_list.get();
            let ptr = blk.ptr();
            *(ptr as *mut *mut u8) = first;
            self.free_list.set(ptr);
        }
    }
}

impl<'a, A: 'a + Allocator> Drop for FreeList<'a, A> {
    fn drop(&mut self) {
        let mut free_list = self.free_list.get();
        //free all the blocks in the list.
        while !free_list.is_null() {
            unsafe {
                let next = *(free_list as *mut *mut u8);
                self.alloc.deallocate_raw(
                    Block::new(free_list, self.block_size, mem::align_of::<*mut u8>())
                );
                free_list = next;
            }
        }
    }
}

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

    #[test]
    fn it_works() {
        let alloc = FreeList::new(1024, 64).ok().unwrap();
        let mut blocks = Vec::new();
        for _ in 0..64 {
            blocks.push(alloc.allocate([0u8; 1024]).ok().unwrap());
        }
        assert!(alloc.allocate([0u8; 1024]).is_err());
        drop(blocks);
        assert!(alloc.allocate([0u8; 1024]).is_ok());
    }
}<commit_msg>Fixed stupid bug in freelist<commit_after>use std::cell::Cell;
use std::mem;
use std::ptr;

use super::{Allocator, AllocatorError, Block, HeapAllocator, HEAP};

/// A `FreeList` allocator manages a list of free memory blocks of uniform size.
/// Whenever a block is requested, it returns the first free block.
pub struct FreeList<'a, A: 'a + Allocator> {
    alloc: &'a A,
    block_size: usize,
    free_list: Cell<*mut u8>,
}

impl FreeList<'static, HeapAllocator> {
    /// Creates a new `FreeList` backed by the heap. `block_size` must be greater
    /// than or equal to the size of a pointer.
    pub fn new(block_size: usize, num_blocks: usize) -> Result<Self, AllocatorError> {
        FreeList::new_from(HEAP, block_size, num_blocks)
    }
}
impl<'a, A: 'a + Allocator> FreeList<'a, A> {
    /// Creates a new `FreeList` backed by another allocator. `block_size` must be greater
    /// than or equal to the size of a pointer.
    pub fn new_from(alloc: &'a A, block_size: usize, num_blocks: usize) -> Result<Self, AllocatorError> {
        if block_size < mem::size_of::<*mut u8>() {
            return Err(AllocatorError::AllocatorSpecific("Block size too small.".into()));
        }

        let mut free_list = ptr::null_mut();

        // allocate each block with maximal alignment.
        for _ in 0..num_blocks {

            match unsafe { alloc.allocate_raw(block_size, mem::align_of::<*mut u8>()) } {
                Ok(block) => {
                    let ptr: *mut *mut u8 = block.ptr() as *mut *mut u8;
                    unsafe { *ptr = free_list };
                    free_list = block.ptr();
                }
                Err(err) => {
                    // destructor cleans up after us.
                    drop(FreeList {
                        alloc: alloc,
                        block_size: block_size,
                        free_list: Cell::new(free_list),
                    });

                    return Err(err);
                }
            }
        }

        Ok(FreeList {
            alloc: alloc,
            block_size: block_size,
            free_list: Cell::new(free_list)
        })
    }
}

unsafe impl<'a, A: 'a + Allocator> Allocator for FreeList<'a, A> {
    unsafe fn allocate_raw(&self, size: usize, align: usize) -> Result<Block, AllocatorError> {
        if size == 0 { return Ok(Block::empty()); }
        else if size > self.block_size {
            return Err(AllocatorError::OutOfMemory);
        }

        if align > mem::align_of::<*mut u8>() {
            return Err(AllocatorError::UnsupportedAlignment);
        }

        let free_list = self.free_list.get();
        if !free_list.is_null() {
            let next_block = *(free_list as *mut *mut u8);
            self.free_list.set(next_block);

            Ok(Block::new(free_list, self.block_size, align))
        } else {
            Err(AllocatorError::OutOfMemory)
        }
    }

    unsafe fn deallocate_raw(&self, blk: Block) {
        if blk.size() == self.block_size && !blk.ptr().is_null() {
            let first = self.free_list.get();
            let ptr = blk.ptr();
            *(ptr as *mut *mut u8) = first;
            self.free_list.set(ptr);
        }
    }
}

impl<'a, A: 'a + Allocator> Drop for FreeList<'a, A> {
    fn drop(&mut self) {
        let mut free_list = self.free_list.get();
        //free all the blocks in the list.
        while !free_list.is_null() {
            unsafe {
                let next = *(free_list as *mut *mut u8);
                self.alloc.deallocate_raw(
                    Block::new(free_list, self.block_size, mem::align_of::<*mut u8>())
                );
                free_list = next;
            }
        }
    }
}

unsafe impl<'a, A: 'a + Allocator + Send> Send for FreeList<'a, A> {}

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

    #[test]
    fn it_works() {
        let alloc = FreeList::new(1024, 64).ok().unwrap();
        let mut blocks = Vec::new();
        for _ in 0..64 {
            blocks.push(alloc.allocate([0u8; 1024]).ok().unwrap());
        }
        assert!(alloc.allocate([0u8; 1024]).is_err());
        drop(blocks);
        assert!(alloc.allocate([0u8; 1024]).is_ok());
    }
}<|endoftext|>


<commit_before>#[macro_use] extern crate log;
#[macro_use] extern crate gl;

extern crate gfx;
extern crate wad;
extern crate math;

extern crate num;
extern crate getopts;
extern crate libc;

extern crate env_logger;
extern crate sdl2;
extern crate time;

use ctrl::GameController;
use ctrl::Gesture;
use gfx::ShaderLoader;
use level::Level;
use libc::c_void;
use math::{Mat4, Vec3};
use player::Player;
use sdl2::Sdl;
use sdl2::scancode::ScanCode;
use sdl2::video::{GLAttr, GLProfile};
use sdl2::video::WindowPos;
use std::default::Default;
use std::path::PathBuf;
use wad::TextureDirectory;

pub mod camera;
pub mod ctrl;
pub mod player;
pub mod level;

const WINDOW_TITLE: &'static str =
    "Rusty Doom v0.0.7 - Toggle mouse with backtick key (`))";
const OPENGL_DEPTH_SIZE: i32 = 24;
const SHADER_ROOT: &'static str = "src/shaders";

pub struct MainWindow {
    window: sdl2::video::Window,
    width: usize,
    height: usize,
    _context: sdl2::video::GLContext,
}
impl MainWindow {
    pub fn new(sdl: &Sdl, width: usize, height: usize) -> MainWindow {
        sdl2::video::gl_set_attribute(GLAttr::GLContextMajorVersion,
                                      gl::platform::GL_MAJOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLContextMinorVersion,
                                      gl::platform::GL_MINOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLDepthSize, OPENGL_DEPTH_SIZE);
        sdl2::video::gl_set_attribute(GLAttr::GLDoubleBuffer, 1);
        sdl2::video::gl_set_attribute(GLAttr::GLContextProfileMask,
                                      GLProfile::GLCoreProfile as i32);

        let window = sdl2::video::Window::new(
            sdl, WINDOW_TITLE, WindowPos::PosCentered, WindowPos::PosCentered,
            width as i32, height as i32,
            sdl2::video::OPENGL | sdl2::video::SHOWN).unwrap();

        let context = window.gl_create_context().unwrap();
        sdl2::clear_error();
        gl::load_with(|name| {
            match sdl2::video::gl_get_proc_address(name) {
                Some(glproc) => glproc as *const libc::c_void,
                None => {
                    warn!("missing GL function: {}", name);
                    std::ptr::null()
                }
            }
        });
        let mut vao_id = 0;
        check_gl_unsafe!(gl::GenVertexArrays(1, &mut vao_id));
        check_gl_unsafe!(gl::BindVertexArray(vao_id));
        MainWindow {
           window: window,
           width: width,
           height: height,
           _context: context,
        }
    }

    pub fn aspect_ratio(&self) -> f32 {
        self.width as f32 / self.height as f32
    }

    pub fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }
}

pub struct GameConfig<'a> {
    wad: &'a str,
    metadata: &'a str,
    level_index: usize,
    fov: f32,
}

pub struct Game {
    window: MainWindow,
    player: Player,
    level: Level,
}
impl Game {
    pub fn new(window: MainWindow, config: GameConfig) -> Game {
        let mut wad = wad::Archive::open(
                &config.wad, &config.metadata).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        let shader_loader = ShaderLoader::new(
                gl::platform::GLSL_VERSION_STRING, PathBuf::from(SHADER_ROOT));
        let level = Level::new(&shader_loader,
                               &mut wad, &textures, config.level_index);

        check_gl_unsafe!(gl::ClearColor(0.06, 0.07, 0.09, 0.0));
        check_gl_unsafe!(gl::Enable(gl::DEPTH_TEST));
        check_gl_unsafe!(gl::DepthFunc(gl::LESS));

        let start = *level.get_start_pos();
        let mut player = Player::new(config.fov, window.aspect_ratio(),
                                     Default::default());
        player.set_position(&Vec3::new(start.x, 0.3, start.y));

        Game {
            window: window,
            player: player,
            level: level
        }
    }

    pub fn run(&mut self, sdl: &Sdl) {
        let quit_gesture = Gesture::AnyOf(
            vec![Gesture::QuitTrigger,
                 Gesture::KeyTrigger(ScanCode::Escape)]);
        let grab_toggle_gesture = Gesture::KeyTrigger(ScanCode::Grave);

        let mut cum_time = 0.0;
        let mut cum_updates_time = 0.0;
        let mut num_frames = 0.0;
        let mut t0 = time::precise_time_s();
        let mut control = GameController::new(sdl.event_pump());
        let mut mouse_grabbed = true;
        loop {
            check_gl_unsafe!(
                gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
            let t1 = time::precise_time_s();
            let mut delta = (t1 - t0) as f32;
            if delta < 1e-10 { delta = 1.0 / 60.0; }
            let delta = delta;
            t0 = t1;

            let updates_t0 = time::precise_time_s();

            control.update();
            if control.poll_gesture(&quit_gesture) {
                break;
            } else if control.poll_gesture(&grab_toggle_gesture) {
                mouse_grabbed = !mouse_grabbed;
                control.set_mouse_enabled(mouse_grabbed);
                control.set_cursor_grabbed(mouse_grabbed);
            }

            self.player.update(delta, &control);
            self.level.render(
                delta,
                &self.player.get_camera()
                .multiply_transform(&Mat4::new_identity()));

            let updates_t1 = time::precise_time_s();
            cum_updates_time += updates_t1 - updates_t0;

            cum_time += delta as f64;
            num_frames += 1.0;
            if cum_time > 2.0 {
                let fps = num_frames / cum_time;
                let cpums = 1000.0 * cum_updates_time / num_frames;
                info!("Frame time: {:.2}ms ({:.2}ms cpu, FPS: {:.2})",
                      1000.0 / fps, cpums, fps);
                cum_time = 0.0;
                cum_updates_time = 0.0;
                num_frames = 0.0;
            }

            self.window.swap_buffers();
        }
    }
}

#[cfg(not(test))]
pub fn run() {
    use getopts::Options;
    use std::env;

    env_logger::init().unwrap();

    let args = env::args().collect::<Vec<_>>();
    let mut opts = Options::new();
    opts.optopt("i", "iwad",
                "set initial wad file to use wad [default='doom1.wad']",
                "FILE");
    opts.optopt("m", "metadata",
                "path to toml toml metadata file [default='doom.toml']",
                "FILE");
    opts.optopt("l", "level",
                "the index of the level to render [default=0]", "N");
    opts.optopt("f", "fov",
                "horizontal field of view to please TotalHalibut [default=65]",
                "FLOAT");
    opts.optopt("r", "resolution",
                "the resolution at which to render the game [default=1280x720]",
                "WIDTHxHEIGHT");
    opts.optflag("d", "dump-levels", "list all levels and exit.");
    opts.optflag("", "load-all", "loads all levels and exit; for debugging");
    opts.optflag("h", "help", "print this help message and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };

    let wad_filename = matches
        .opt_str("i")
        .unwrap_or("doom1.wad".to_string());
    let meta_filename = matches
        .opt_str("m")
        .unwrap_or("doom.toml".to_string());
    let (width, height) = matches
        .opt_str("r")
        .map(|r| {
            let r: Vec<&str> = r.splitn(2, 'x').collect();
            match &r[..] {
                wh if wh.len() == 2 => (wh[0].parse().unwrap(),
                                        wh[1].parse().unwrap()),
                _ => {
                    panic!("Invalid format for resolution, \
                            please use WIDTHxHEIGHT.");
                }
            }
        })
        .unwrap_or((1280, 720));
    let level_index = matches
        .opt_str("l")
        .map(|l| l.parse().ok()
                  .expect("Invalid value for --level. Expected integer."))
        .unwrap_or(0);
    let fov = matches
        .opt_str("f")
        .map(|f| f.parse().ok()
                    .expect("Invalid value for --fov. Expected float."))
        .unwrap_or(65.0);

    if matches.opt_present("h") {
        println!("{}", opts.usage("A rust doom renderer."));
        return;
    }

    if matches.opt_present("d") {
        let wad = wad::Archive::open(&wad_filename, &meta_filename).unwrap();
        for i_level in 0..wad.num_levels() {
            println!("{:3} {:8}", i_level, wad.get_level_name(i_level));
        }
        return;
    }

    let sdl = sdl2::init(sdl2::INIT_VIDEO).unwrap();
    let win = MainWindow::new(&sdl, width, height);

    if matches.opt_present("load-all") {
        let t0 = time::precise_time_s();
        let mut wad = wad::Archive::open(
            &wad_filename, &meta_filename).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        let shader_loader = ShaderLoader::new(
            gl::platform::GLSL_VERSION_STRING, PathBuf::from(SHADER_ROOT));
        for level_index in 0 .. wad.num_levels() {
            Level::new(&shader_loader, &mut wad, &textures, level_index);
        }
        println!("Done, loaded all levels in {:.4}s. Shutting down...",
                 time::precise_time_s() - t0);
        drop(win);
        return;
    }

    let mut game = Game::new(
        win,
        GameConfig {
            wad: &wad_filename,
            metadata: &meta_filename,
            level_index: level_index,
            fov: fov,
        });
    game.run(&sdl);

    info!("Shutting down.");
}
<commit_msg>Update to newest SDL2.<commit_after>#[macro_use] extern crate log;
#[macro_use] extern crate gl;

extern crate gfx;
extern crate wad;
extern crate math;

extern crate num;
extern crate getopts;
extern crate libc;

extern crate env_logger;
extern crate sdl2;
extern crate time;

use ctrl::GameController;
use ctrl::Gesture;
use gfx::ShaderLoader;
use level::Level;
use libc::c_void;
use math::{Mat4, Vec3};
use player::Player;
use sdl2::Sdl;
use sdl2::scancode::ScanCode;
use sdl2::video::{GLAttr, GLProfile};
use std::default::Default;
use std::path::PathBuf;
use wad::TextureDirectory;

pub mod camera;
pub mod ctrl;
pub mod player;
pub mod level;

const WINDOW_TITLE: &'static str =
    "Rusty Doom v0.0.7 - Toggle mouse with backtick key (`))";
const OPENGL_DEPTH_SIZE: i32 = 24;
const SHADER_ROOT: &'static str = "src/shaders";

pub struct MainWindow {
    window: sdl2::video::Window,
    width: usize,
    height: usize,
    _context: sdl2::video::GLContext,
}
impl MainWindow {
    pub fn new(sdl: &Sdl, width: usize, height: usize) -> MainWindow {
        sdl2::video::gl_set_attribute(GLAttr::GLContextMajorVersion,
                                      gl::platform::GL_MAJOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLContextMinorVersion,
                                      gl::platform::GL_MINOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLDepthSize, OPENGL_DEPTH_SIZE);
        sdl2::video::gl_set_attribute(GLAttr::GLDoubleBuffer, 1);
        sdl2::video::gl_set_attribute(GLAttr::GLContextProfileMask,
                                      GLProfile::GLCoreProfile as i32);

        let window = sdl.window(WINDOW_TITLE, width as u32, height as u32)
            .position_centered()
            .opengl()
            .build()
            .unwrap();

        let context = window.gl_create_context().unwrap();
        sdl2::clear_error();
        gl::load_with(|name| {
            sdl2::video::gl_get_proc_address(name) as *const libc::c_void
        });
        let mut vao_id = 0;
        check_gl_unsafe!(gl::GenVertexArrays(1, &mut vao_id));
        check_gl_unsafe!(gl::BindVertexArray(vao_id));
        MainWindow {
           window: window,
           width: width,
           height: height,
           _context: context,
        }
    }

    pub fn aspect_ratio(&self) -> f32 {
        self.width as f32 / self.height as f32
    }

    pub fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }
}

pub struct GameConfig<'a> {
    wad: &'a str,
    metadata: &'a str,
    level_index: usize,
    fov: f32,
}

pub struct Game {
    window: MainWindow,
    player: Player,
    level: Level,
}
impl Game {
    pub fn new(window: MainWindow, config: GameConfig) -> Game {
        let mut wad = wad::Archive::open(
                &config.wad, &config.metadata).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        let shader_loader = ShaderLoader::new(
                gl::platform::GLSL_VERSION_STRING, PathBuf::from(SHADER_ROOT));
        let level = Level::new(&shader_loader,
                               &mut wad, &textures, config.level_index);

        check_gl_unsafe!(gl::ClearColor(0.06, 0.07, 0.09, 0.0));
        check_gl_unsafe!(gl::Enable(gl::DEPTH_TEST));
        check_gl_unsafe!(gl::DepthFunc(gl::LESS));

        let start = *level.get_start_pos();
        let mut player = Player::new(config.fov, window.aspect_ratio(),
                                     Default::default());
        player.set_position(&Vec3::new(start.x, 0.3, start.y));

        Game {
            window: window,
            player: player,
            level: level
        }
    }

    pub fn run(&mut self, sdl: &Sdl) {
        let quit_gesture = Gesture::AnyOf(
            vec![Gesture::QuitTrigger,
                 Gesture::KeyTrigger(ScanCode::Escape)]);
        let grab_toggle_gesture = Gesture::KeyTrigger(ScanCode::Grave);

        let mut cum_time = 0.0;
        let mut cum_updates_time = 0.0;
        let mut num_frames = 0.0;
        let mut t0 = time::precise_time_s();
        let mut control = GameController::new(sdl.event_pump());
        let mut mouse_grabbed = true;
        loop {
            check_gl_unsafe!(
                gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
            let t1 = time::precise_time_s();
            let mut delta = (t1 - t0) as f32;
            if delta < 1e-10 { delta = 1.0 / 60.0; }
            let delta = delta;
            t0 = t1;

            let updates_t0 = time::precise_time_s();

            control.update();
            if control.poll_gesture(&quit_gesture) {
                break;
            } else if control.poll_gesture(&grab_toggle_gesture) {
                mouse_grabbed = !mouse_grabbed;
                control.set_mouse_enabled(mouse_grabbed);
                control.set_cursor_grabbed(mouse_grabbed);
            }

            self.player.update(delta, &control);
            self.level.render(
                delta,
                &self.player.get_camera()
                .multiply_transform(&Mat4::new_identity()));

            let updates_t1 = time::precise_time_s();
            cum_updates_time += updates_t1 - updates_t0;

            cum_time += delta as f64;
            num_frames += 1.0;
            if cum_time > 2.0 {
                let fps = num_frames / cum_time;
                let cpums = 1000.0 * cum_updates_time / num_frames;
                info!("Frame time: {:.2}ms ({:.2}ms cpu, FPS: {:.2})",
                      1000.0 / fps, cpums, fps);
                cum_time = 0.0;
                cum_updates_time = 0.0;
                num_frames = 0.0;
            }

            self.window.swap_buffers();
        }
    }
}

#[cfg(not(test))]
pub fn run() {
    use getopts::Options;
    use std::env;

    env_logger::init().unwrap();

    let args = env::args().collect::<Vec<_>>();
    let mut opts = Options::new();
    opts.optopt("i", "iwad",
                "set initial wad file to use wad [default='doom1.wad']",
                "FILE");
    opts.optopt("m", "metadata",
                "path to toml toml metadata file [default='doom.toml']",
                "FILE");
    opts.optopt("l", "level",
                "the index of the level to render [default=0]", "N");
    opts.optopt("f", "fov",
                "horizontal field of view to please TotalHalibut [default=65]",
                "FLOAT");
    opts.optopt("r", "resolution",
                "the resolution at which to render the game [default=1280x720]",
                "WIDTHxHEIGHT");
    opts.optflag("d", "dump-levels", "list all levels and exit.");
    opts.optflag("", "load-all", "loads all levels and exit; for debugging");
    opts.optflag("h", "help", "print this help message and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };

    let wad_filename = matches
        .opt_str("i")
        .unwrap_or("doom1.wad".to_string());
    let meta_filename = matches
        .opt_str("m")
        .unwrap_or("doom.toml".to_string());
    let (width, height) = matches
        .opt_str("r")
        .map(|r| {
            let r: Vec<&str> = r.splitn(2, 'x').collect();
            match &r[..] {
                wh if wh.len() == 2 => (wh[0].parse().unwrap(),
                                        wh[1].parse().unwrap()),
                _ => {
                    panic!("Invalid format for resolution, \
                            please use WIDTHxHEIGHT.");
                }
            }
        })
        .unwrap_or((1280, 720));
    let level_index = matches
        .opt_str("l")
        .map(|l| l.parse().ok()
                  .expect("Invalid value for --level. Expected integer."))
        .unwrap_or(0);
    let fov = matches
        .opt_str("f")
        .map(|f| f.parse().ok()
                    .expect("Invalid value for --fov. Expected float."))
        .unwrap_or(65.0);

    if matches.opt_present("h") {
        println!("{}", opts.usage("A rust doom renderer."));
        return;
    }

    if matches.opt_present("d") {
        let wad = wad::Archive::open(&wad_filename, &meta_filename).unwrap();
        for i_level in 0..wad.num_levels() {
            println!("{:3} {:8}", i_level, wad.get_level_name(i_level));
        }
        return;
    }

    let sdl = sdl2::init().video().unwrap();
    let win = MainWindow::new(&sdl, width, height);

    if matches.opt_present("load-all") {
        let t0 = time::precise_time_s();
        let mut wad = wad::Archive::open(
            &wad_filename, &meta_filename).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        let shader_loader = ShaderLoader::new(
            gl::platform::GLSL_VERSION_STRING, PathBuf::from(SHADER_ROOT));
        for level_index in 0 .. wad.num_levels() {
            Level::new(&shader_loader, &mut wad, &textures, level_index);
        }
        println!("Done, loaded all levels in {:.4}s. Shutting down...",
                 time::precise_time_s() - t0);
        drop(win);
        return;
    }

    let mut game = Game::new(
        win,
        GameConfig {
            wad: &wad_filename,
            metadata: &meta_filename,
            level_index: level_index,
            fov: fov,
        });
    game.run(&sdl);

    info!("Shutting down.");
}
<|endoftext|>


<commit_before>use core::ops;

#[cfg(all(feature = "libm-math", not(feature = "std")))]
use crate::nostd_float::FloatExt;

/// A point in 2-dimensional space, with each dimension of type `N`.
///
/// Legal operations on points are addition and subtraction by vectors, and
/// subtraction between points, to give a vector representing the offset between
/// the two points. Combined with the legal operations on vectors, meaningful
/// manipulations of vectors and points can be performed.
///
/// For example, to interpolate between two points by a factor `t`:
///
/// ```
/// # use rusttype::*;
/// # let t = 0.5; let p0 = point(0.0, 0.0); let p1 = point(0.0, 0.0);
/// let interpolated_point = p0 + (p1 - p0) * t;
/// ```
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Point<N> {
    pub x: N,
    pub y: N,
}

impl <N: Default> Default for Point<N> {
    fn default() -> Self {
        Point {
            x: N::default(),
            y: N::default()
        }
    }
}

/// A vector in 2-dimensional space, with each dimension of type `N`.
///
/// Legal operations on vectors are addition and subtraction by vectors,
/// addition by points (to give points), and multiplication and division by
/// scalars.
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Vector<N> {
    pub x: N,
    pub y: N,
}

impl <N: Default> Default for Vector<N> {
    fn default() -> Self {
        Vector {
            x: N::default(),
            y: N::default()
        }
    }
}

/// A convenience function for generating `Point`s.
#[inline]
pub fn point<N>(x: N, y: N) -> Point<N> {
    Point { x, y }
}
/// A convenience function for generating `Vector`s.
#[inline]
pub fn vector<N>(x: N, y: N) -> Vector<N> {
    Vector { x, y }
}

impl<N: ops::Sub<Output = N>> ops::Sub for Point<N> {
    type Output = Vector<N>;
    fn sub(self, rhs: Point<N>) -> Vector<N> {
        vector(self.x - rhs.x, self.y - rhs.y)
    }
}

impl<N: ops::Add<Output = N>> ops::Add for Vector<N> {
    type Output = Vector<N>;
    fn add(self, rhs: Vector<N>) -> Vector<N> {
        vector(self.x + rhs.x, self.y + rhs.y)
    }
}

impl<N: ops::Sub<Output = N>> ops::Sub for Vector<N> {
    type Output = Vector<N>;
    fn sub(self, rhs: Vector<N>) -> Vector<N> {
        vector(self.x - rhs.x, self.y - rhs.y)
    }
}

impl ops::Mul<f32> for Vector<f32> {
    type Output = Vector<f32>;
    fn mul(self, rhs: f32) -> Vector<f32> {
        vector(self.x * rhs, self.y * rhs)
    }
}

impl ops::Mul<Vector<f32>> for f32 {
    type Output = Vector<f32>;
    fn mul(self, rhs: Vector<f32>) -> Vector<f32> {
        vector(self * rhs.x, self * rhs.y)
    }
}

impl ops::Mul<f64> for Vector<f64> {
    type Output = Vector<f64>;
    fn mul(self, rhs: f64) -> Vector<f64> {
        vector(self.x * rhs, self.y * rhs)
    }
}

impl ops::Mul<Vector<f64>> for f64 {
    type Output = Vector<f64>;
    fn mul(self, rhs: Vector<f64>) -> Vector<f64> {
        vector(self * rhs.x, self * rhs.y)
    }
}

impl ops::Div<f32> for Vector<f32> {
    type Output = Vector<f32>;
    fn div(self, rhs: f32) -> Vector<f32> {
        vector(self.x / rhs, self.y / rhs)
    }
}

impl ops::Div<Vector<f32>> for f32 {
    type Output = Vector<f32>;
    fn div(self, rhs: Vector<f32>) -> Vector<f32> {
        vector(self / rhs.x, self / rhs.y)
    }
}

impl ops::Div<f64> for Vector<f64> {
    type Output = Vector<f64>;
    fn div(self, rhs: f64) -> Vector<f64> {
        vector(self.x / rhs, self.y / rhs)
    }
}

impl ops::Div<Vector<f64>> for f64 {
    type Output = Vector<f64>;
    fn div(self, rhs: Vector<f64>) -> Vector<f64> {
        vector(self / rhs.x, self / rhs.y)
    }
}

impl<N: ops::Add<Output = N>> ops::Add<Vector<N>> for Point<N> {
    type Output = Point<N>;
    fn add(self, rhs: Vector<N>) -> Point<N> {
        point(self.x + rhs.x, self.y + rhs.y)
    }
}

impl<N: ops::Sub<Output = N>> ops::Sub<Vector<N>> for Point<N> {
    type Output = Point<N>;
    fn sub(self, rhs: Vector<N>) -> Point<N> {
        point(self.x - rhs.x, self.y - rhs.y)
    }
}

impl<N: ops::Add<Output = N>> ops::Add<Point<N>> for Vector<N> {
    type Output = Point<N>;
    fn add(self, rhs: Point<N>) -> Point<N> {
        point(self.x + rhs.x, self.y + rhs.y)
    }
}

/// A straight line between two points, `p[0]` and `p[1]`
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Line {
    pub p: [Point<f32>; 2],
}
/// A quadratic Bezier curve, starting at `p[0]`, ending at `p[2]`, with control
/// point `p[1]`.
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Curve {
    pub p: [Point<f32>; 3],
}
/// A rectangle, with top-left corner at `min`, and bottom-right corner at
/// `max`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Rect<N> {
    pub min: Point<N>,
    pub max: Point<N>,
}

impl <N: Default> Default for Rect<N> {
    fn default() -> Self {
        Rect {
            min: Point::default(),
            max: Point::default()
        }
    }
}

impl<N: ops::Sub<Output = N> + Copy> Rect<N> {
    pub fn width(&self) -> N {
        self.max.x - self.min.x
    }
    pub fn height(&self) -> N {
        self.max.y - self.min.y
    }
}

pub trait BoundingBox<N> {
    fn bounding_box(&self) -> Rect<N> {
        let (min_x, max_x) = self.x_bounds();
        let (min_y, max_y) = self.y_bounds();
        Rect {
            min: point(min_x, min_y),
            max: point(max_x, max_y),
        }
    }
    fn x_bounds(&self) -> (N, N);
    fn y_bounds(&self) -> (N, N);
}

impl BoundingBox<f32> for Line {
    fn x_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].x < p[1].x {
            (p[0].x, p[1].x)
        } else {
            (p[1].x, p[0].x)
        }
    }
    fn y_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].y < p[1].y {
            (p[0].y, p[1].y)
        } else {
            (p[1].y, p[0].y)
        }
    }
}

impl BoundingBox<f32> for Curve {
    fn x_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].x <= p[1].x && p[1].x <= p[2].x {
            (p[0].x, p[2].x)
        } else if p[0].x >= p[1].x && p[1].x >= p[2].x {
            (p[2].x, p[0].x)
        } else {
            let t = (p[0].x - p[1].x) / (p[0].x - 2.0 * p[1].x + p[2].x);
            let _1mt = 1.0 - t;
            let inflection = _1mt * _1mt * p[0].x + 2.0 * _1mt * t * p[1].x + t * t * p[2].x;
            if p[1].x < p[0].x {
                (inflection, p[0].x.max(p[2].x))
            } else {
                (p[0].x.min(p[2].x), inflection)
            }
        }
    }

    fn y_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].y <= p[1].y && p[1].y <= p[2].y {
            (p[0].y, p[2].y)
        } else if p[0].y >= p[1].y && p[1].y >= p[2].y {
            (p[2].y, p[0].y)
        } else {
            let t = (p[0].y - p[1].y) / (p[0].y - 2.0 * p[1].y + p[2].y);
            let _1mt = 1.0 - t;
            let inflection = _1mt * _1mt * p[0].y + 2.0 * _1mt * t * p[1].y + t * t * p[2].y;
            if p[1].y < p[0].y {
                (inflection, p[0].y.max(p[2].y))
            } else {
                (p[0].y.min(p[2].y), inflection)
            }
        }
    }
}

pub trait Cut: Sized {
    fn cut_to(self, t: f32) -> Self;
    fn cut_from(self, t: f32) -> Self;
    fn cut_from_to(self, t0: f32, t1: f32) -> Self {
        self.cut_from(t0).cut_to((t1 - t0) / (1.0 - t0))
    }
}

impl Cut for Curve {
    fn cut_to(self, t: f32) -> Curve {
        let p = self.p;
        let a = p[0] + t * (p[1] - p[0]);
        let b = p[1] + t * (p[2] - p[1]);
        let c = a + t * (b - a);
        Curve { p: [p[0], a, c] }
    }
    fn cut_from(self, t: f32) -> Curve {
        let p = self.p;
        let a = p[0] + t * (p[1] - p[0]);
        let b = p[1] + t * (p[2] - p[1]);
        let c = a + t * (b - a);
        Curve { p: [c, b, p[2]] }
    }
}

impl Cut for Line {
    fn cut_to(self, t: f32) -> Line {
        let p = self.p;
        Line {
            p: [p[0], p[0] + t * (p[1] - p[0])],
        }
    }
    fn cut_from(self, t: f32) -> Line {
        let p = self.p;
        Line {
            p: [p[0] + t * (p[1] - p[0]), p[1]],
        }
    }
    fn cut_from_to(self, t0: f32, t1: f32) -> Line {
        let p = self.p;
        let v = p[1] - p[0];
        Line {
            p: [p[0] + t0 * v, p[0] + t1 * v],
        }
    }
}

/// The real valued solutions to a real quadratic equation.
#[derive(Copy, Clone, Debug)]
pub enum RealQuadraticSolution {
    /// Two zero-crossing solutions
    Two(f32, f32),
    /// One zero-crossing solution (equation is a straight line)
    One(f32),
    /// One zero-touching solution
    Touch(f32),
    /// No solutions
    None,
    /// All real numbers are solutions since a == b == c == 0.0
    All,
}

impl RealQuadraticSolution {
    /// If there are two solutions, this function ensures that they are in order
    /// (first < second)
    pub fn in_order(self) -> RealQuadraticSolution {
        use self::RealQuadraticSolution::*;
        match self {
            Two(x, y) => {
                if x < y {
                    Two(x, y)
                } else {
                    Two(y, x)
                }
            }
            other => other,
        }
    }
}

/// Solve a real quadratic equation, giving all real solutions, if any.
pub fn solve_quadratic_real(a: f32, b: f32, c: f32) -> RealQuadraticSolution {
    let discriminant = b * b - 4.0 * a * c;
    if discriminant > 0.0 {
        let sqrt_d = discriminant.sqrt();
        let common = -b + if b >= 0.0 { -sqrt_d } else { sqrt_d };
        let x1 = 2.0 * c / common;
        if a == 0.0 {
            RealQuadraticSolution::One(x1)
        } else {
            let x2 = common / (2.0 * a);
            RealQuadraticSolution::Two(x1, x2)
        }
    } else if discriminant < 0.0 {
        RealQuadraticSolution::None
    } else if b == 0.0 {
        if a == 0.0 {
            if c == 0.0 {
                RealQuadraticSolution::All
            } else {
                RealQuadraticSolution::None
            }
        } else {
            RealQuadraticSolution::Touch(0.0)
        }
    } else {
        RealQuadraticSolution::Touch(2.0 * c / -b)
    }
}

#[test]
fn quadratic_test() {
    solve_quadratic_real(-0.000_000_1, -2.0, 10.0);
}
<commit_msg>Derive defaults instead of implementing<commit_after>use core::ops;

#[cfg(all(feature = "libm-math", not(feature = "std")))]
use crate::nostd_float::FloatExt;

/// A point in 2-dimensional space, with each dimension of type `N`.
///
/// Legal operations on points are addition and subtraction by vectors, and
/// subtraction between points, to give a vector representing the offset between
/// the two points. Combined with the legal operations on vectors, meaningful
/// manipulations of vectors and points can be performed.
///
/// For example, to interpolate between two points by a factor `t`:
///
/// ```
/// # use rusttype::*;
/// # let t = 0.5; let p0 = point(0.0, 0.0); let p1 = point(0.0, 0.0);
/// let interpolated_point = p0 + (p1 - p0) * t;
/// ```
#[derive(Copy, Clone, Debug, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Point<N> {
    pub x: N,
    pub y: N,
}

/// A vector in 2-dimensional space, with each dimension of type `N`.
///
/// Legal operations on vectors are addition and subtraction by vectors,
/// addition by points (to give points), and multiplication and division by
/// scalars.
#[derive(Copy, Clone, Debug, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Vector<N> {
    pub x: N,
    pub y: N,
}

/// A convenience function for generating `Point`s.
#[inline]
pub fn point<N>(x: N, y: N) -> Point<N> {
    Point { x, y }
}
/// A convenience function for generating `Vector`s.
#[inline]
pub fn vector<N>(x: N, y: N) -> Vector<N> {
    Vector { x, y }
}

impl<N: ops::Sub<Output = N>> ops::Sub for Point<N> {
    type Output = Vector<N>;
    fn sub(self, rhs: Point<N>) -> Vector<N> {
        vector(self.x - rhs.x, self.y - rhs.y)
    }
}

impl<N: ops::Add<Output = N>> ops::Add for Vector<N> {
    type Output = Vector<N>;
    fn add(self, rhs: Vector<N>) -> Vector<N> {
        vector(self.x + rhs.x, self.y + rhs.y)
    }
}

impl<N: ops::Sub<Output = N>> ops::Sub for Vector<N> {
    type Output = Vector<N>;
    fn sub(self, rhs: Vector<N>) -> Vector<N> {
        vector(self.x - rhs.x, self.y - rhs.y)
    }
}

impl ops::Mul<f32> for Vector<f32> {
    type Output = Vector<f32>;
    fn mul(self, rhs: f32) -> Vector<f32> {
        vector(self.x * rhs, self.y * rhs)
    }
}

impl ops::Mul<Vector<f32>> for f32 {
    type Output = Vector<f32>;
    fn mul(self, rhs: Vector<f32>) -> Vector<f32> {
        vector(self * rhs.x, self * rhs.y)
    }
}

impl ops::Mul<f64> for Vector<f64> {
    type Output = Vector<f64>;
    fn mul(self, rhs: f64) -> Vector<f64> {
        vector(self.x * rhs, self.y * rhs)
    }
}

impl ops::Mul<Vector<f64>> for f64 {
    type Output = Vector<f64>;
    fn mul(self, rhs: Vector<f64>) -> Vector<f64> {
        vector(self * rhs.x, self * rhs.y)
    }
}

impl ops::Div<f32> for Vector<f32> {
    type Output = Vector<f32>;
    fn div(self, rhs: f32) -> Vector<f32> {
        vector(self.x / rhs, self.y / rhs)
    }
}

impl ops::Div<Vector<f32>> for f32 {
    type Output = Vector<f32>;
    fn div(self, rhs: Vector<f32>) -> Vector<f32> {
        vector(self / rhs.x, self / rhs.y)
    }
}

impl ops::Div<f64> for Vector<f64> {
    type Output = Vector<f64>;
    fn div(self, rhs: f64) -> Vector<f64> {
        vector(self.x / rhs, self.y / rhs)
    }
}

impl ops::Div<Vector<f64>> for f64 {
    type Output = Vector<f64>;
    fn div(self, rhs: Vector<f64>) -> Vector<f64> {
        vector(self / rhs.x, self / rhs.y)
    }
}

impl<N: ops::Add<Output = N>> ops::Add<Vector<N>> for Point<N> {
    type Output = Point<N>;
    fn add(self, rhs: Vector<N>) -> Point<N> {
        point(self.x + rhs.x, self.y + rhs.y)
    }
}

impl<N: ops::Sub<Output = N>> ops::Sub<Vector<N>> for Point<N> {
    type Output = Point<N>;
    fn sub(self, rhs: Vector<N>) -> Point<N> {
        point(self.x - rhs.x, self.y - rhs.y)
    }
}

impl<N: ops::Add<Output = N>> ops::Add<Point<N>> for Vector<N> {
    type Output = Point<N>;
    fn add(self, rhs: Point<N>) -> Point<N> {
        point(self.x + rhs.x, self.y + rhs.y)
    }
}

/// A straight line between two points, `p[0]` and `p[1]`
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Line {
    pub p: [Point<f32>; 2],
}
/// A quadratic Bezier curve, starting at `p[0]`, ending at `p[2]`, with control
/// point `p[1]`.
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Curve {
    pub p: [Point<f32>; 3],
}
/// A rectangle, with top-left corner at `min`, and bottom-right corner at
/// `max`.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Rect<N> {
    pub min: Point<N>,
    pub max: Point<N>,
}

impl<N: ops::Sub<Output = N> + Copy> Rect<N> {
    pub fn width(&self) -> N {
        self.max.x - self.min.x
    }
    pub fn height(&self) -> N {
        self.max.y - self.min.y
    }
}

pub trait BoundingBox<N> {
    fn bounding_box(&self) -> Rect<N> {
        let (min_x, max_x) = self.x_bounds();
        let (min_y, max_y) = self.y_bounds();
        Rect {
            min: point(min_x, min_y),
            max: point(max_x, max_y),
        }
    }
    fn x_bounds(&self) -> (N, N);
    fn y_bounds(&self) -> (N, N);
}

impl BoundingBox<f32> for Line {
    fn x_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].x < p[1].x {
            (p[0].x, p[1].x)
        } else {
            (p[1].x, p[0].x)
        }
    }
    fn y_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].y < p[1].y {
            (p[0].y, p[1].y)
        } else {
            (p[1].y, p[0].y)
        }
    }
}

impl BoundingBox<f32> for Curve {
    fn x_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].x <= p[1].x && p[1].x <= p[2].x {
            (p[0].x, p[2].x)
        } else if p[0].x >= p[1].x && p[1].x >= p[2].x {
            (p[2].x, p[0].x)
        } else {
            let t = (p[0].x - p[1].x) / (p[0].x - 2.0 * p[1].x + p[2].x);
            let _1mt = 1.0 - t;
            let inflection = _1mt * _1mt * p[0].x + 2.0 * _1mt * t * p[1].x + t * t * p[2].x;
            if p[1].x < p[0].x {
                (inflection, p[0].x.max(p[2].x))
            } else {
                (p[0].x.min(p[2].x), inflection)
            }
        }
    }

    fn y_bounds(&self) -> (f32, f32) {
        let p = &self.p;
        if p[0].y <= p[1].y && p[1].y <= p[2].y {
            (p[0].y, p[2].y)
        } else if p[0].y >= p[1].y && p[1].y >= p[2].y {
            (p[2].y, p[0].y)
        } else {
            let t = (p[0].y - p[1].y) / (p[0].y - 2.0 * p[1].y + p[2].y);
            let _1mt = 1.0 - t;
            let inflection = _1mt * _1mt * p[0].y + 2.0 * _1mt * t * p[1].y + t * t * p[2].y;
            if p[1].y < p[0].y {
                (inflection, p[0].y.max(p[2].y))
            } else {
                (p[0].y.min(p[2].y), inflection)
            }
        }
    }
}

pub trait Cut: Sized {
    fn cut_to(self, t: f32) -> Self;
    fn cut_from(self, t: f32) -> Self;
    fn cut_from_to(self, t0: f32, t1: f32) -> Self {
        self.cut_from(t0).cut_to((t1 - t0) / (1.0 - t0))
    }
}

impl Cut for Curve {
    fn cut_to(self, t: f32) -> Curve {
        let p = self.p;
        let a = p[0] + t * (p[1] - p[0]);
        let b = p[1] + t * (p[2] - p[1]);
        let c = a + t * (b - a);
        Curve { p: [p[0], a, c] }
    }
    fn cut_from(self, t: f32) -> Curve {
        let p = self.p;
        let a = p[0] + t * (p[1] - p[0]);
        let b = p[1] + t * (p[2] - p[1]);
        let c = a + t * (b - a);
        Curve { p: [c, b, p[2]] }
    }
}

impl Cut for Line {
    fn cut_to(self, t: f32) -> Line {
        let p = self.p;
        Line {
            p: [p[0], p[0] + t * (p[1] - p[0])],
        }
    }
    fn cut_from(self, t: f32) -> Line {
        let p = self.p;
        Line {
            p: [p[0] + t * (p[1] - p[0]), p[1]],
        }
    }
    fn cut_from_to(self, t0: f32, t1: f32) -> Line {
        let p = self.p;
        let v = p[1] - p[0];
        Line {
            p: [p[0] + t0 * v, p[0] + t1 * v],
        }
    }
}

/// The real valued solutions to a real quadratic equation.
#[derive(Copy, Clone, Debug)]
pub enum RealQuadraticSolution {
    /// Two zero-crossing solutions
    Two(f32, f32),
    /// One zero-crossing solution (equation is a straight line)
    One(f32),
    /// One zero-touching solution
    Touch(f32),
    /// No solutions
    None,
    /// All real numbers are solutions since a == b == c == 0.0
    All,
}

impl RealQuadraticSolution {
    /// If there are two solutions, this function ensures that they are in order
    /// (first < second)
    pub fn in_order(self) -> RealQuadraticSolution {
        use self::RealQuadraticSolution::*;
        match self {
            Two(x, y) => {
                if x < y {
                    Two(x, y)
                } else {
                    Two(y, x)
                }
            }
            other => other,
        }
    }
}

/// Solve a real quadratic equation, giving all real solutions, if any.
pub fn solve_quadratic_real(a: f32, b: f32, c: f32) -> RealQuadraticSolution {
    let discriminant = b * b - 4.0 * a * c;
    if discriminant > 0.0 {
        let sqrt_d = discriminant.sqrt();
        let common = -b + if b >= 0.0 { -sqrt_d } else { sqrt_d };
        let x1 = 2.0 * c / common;
        if a == 0.0 {
            RealQuadraticSolution::One(x1)
        } else {
            let x2 = common / (2.0 * a);
            RealQuadraticSolution::Two(x1, x2)
        }
    } else if discriminant < 0.0 {
        RealQuadraticSolution::None
    } else if b == 0.0 {
        if a == 0.0 {
            if c == 0.0 {
                RealQuadraticSolution::All
            } else {
                RealQuadraticSolution::None
            }
        } else {
            RealQuadraticSolution::Touch(0.0)
        }
    } else {
        RealQuadraticSolution::Touch(2.0 * c / -b)
    }
}

#[test]
fn quadratic_test() {
    solve_quadratic_real(-0.000_000_1, -2.0, 10.0);
}
<|endoftext|>


<commit_before>extern crate cc;
extern crate ctest;

use std::env;
use std::str;

fn main() {
    let mut cfg = ctest::TestGenerator::new();

    let mut build = cc::Build::new();
    build.file("version_detect.c");
    if let Ok(out) = env::var("DEP_CURL_INCLUDE") {
        cfg.include(&out);
        build.include(&out);
    }
    let version = build.expand();
    let version = str::from_utf8(&version).unwrap();
    let version = version
        .lines()
        .filter(|l| !l.is_empty() && !l.starts_with("#"))
        .next()
        .and_then(|s| s.parse::<u32>().ok())
        .unwrap_or(10000);

    if env::var("TARGET").unwrap().contains("msvc") {
        cfg.flag("/wd4574"); // did you mean to use '#if INCL_WINSOCK_API_TYPEDEFS'
    }

    cfg.header("curl/curl.h");
    cfg.define("CURL_STATICLIB", None);
    cfg.field_name(|s, field| {
        if s == "curl_fileinfo" {
            field.replace("strings_", "strings.")
        } else if s == "CURLMsg" && field == "data" {
            "data.whatever".to_string()
        } else {
            field.to_string()
        }
    });
    cfg.type_name(|s, is_struct, _is_union| match s {
        "CURL" | "CURLM" | "CURLSH" | "curl_version_info_data" => s.to_string(),
        "curl_khtype" | "curl_khstat" | "curl_khmatch" => format!("enum {}", s),
        s if is_struct => format!("struct {}", s),
        "sockaddr" => format!("struct sockaddr"),
        s => s.to_string(),
    });
    // cfg.fn_cname(|s, l| l.unwrap_or(s).to_string());
    cfg.skip_type(|n| n == "__enum_ty");
    cfg.skip_signededness(|s| s.ends_with("callback") || s.ends_with("function"));

    cfg.skip_struct(move |s| {
        if version < 60 {
            match s {
                "curl_version_info_data" => return true,
                _ => {}
            }
        }

        false
    });

    cfg.skip_const(move |s| {
        if version < 61 {
            match s {
                "CURLOPT_PIPEWAIT" => return true,
                "CURLE_PEER_FAILED_VERIFICATION" => return true,
                _ => {}
            }
        }
        if version < 60 {
            match s {
                "CURLVERSION_FIFTH" | "CURLVERSION_NOW" => return true,
                _ => {}
            }
        }
        if version < 54 {
            match s {
                "CURL_SSLVERSION_TLSv1_3" => return true,
                _ => {}
            }
        }

        if version < 49 {
            if s.starts_with("CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE") {
                return true;
            }
        }

        if version < 47 {
            if s.starts_with("CURL_HTTP_VERSION_2") {
                return true;
            }
        }

        if version < 43 {
            if s.starts_with("CURLPIPE_") {
                return true;
            }
        }

        // OSX doesn't have this yet
        s == "CURLSSLOPT_NO_REVOKE" ||

        // A lot of curl versions doesn't support unix sockets
        s == "CURLOPT_UNIX_SOCKET_PATH" || s == "CURL_VERSION_UNIX_SOCKETS"
    });

    if cfg!(target_env = "msvc") {
        cfg.skip_fn_ptrcheck(|s| s.starts_with("curl_"));
    }

    cfg.generate("../curl-sys/lib.rs", "all.rs");
}
<commit_msg>Skip verifying new error consts.<commit_after>extern crate cc;
extern crate ctest;

use std::env;
use std::str;

fn main() {
    let mut cfg = ctest::TestGenerator::new();

    let mut build = cc::Build::new();
    build.file("version_detect.c");
    if let Ok(out) = env::var("DEP_CURL_INCLUDE") {
        cfg.include(&out);
        build.include(&out);
    }
    let version = build.expand();
    let version = str::from_utf8(&version).unwrap();
    let version = version
        .lines()
        .filter(|l| !l.is_empty() && !l.starts_with("#"))
        .next()
        .and_then(|s| s.parse::<u32>().ok())
        .unwrap_or(10000);

    if env::var("TARGET").unwrap().contains("msvc") {
        cfg.flag("/wd4574"); // did you mean to use '#if INCL_WINSOCK_API_TYPEDEFS'
    }

    cfg.header("curl/curl.h");
    cfg.define("CURL_STATICLIB", None);
    cfg.field_name(|s, field| {
        if s == "curl_fileinfo" {
            field.replace("strings_", "strings.")
        } else if s == "CURLMsg" && field == "data" {
            "data.whatever".to_string()
        } else {
            field.to_string()
        }
    });
    cfg.type_name(|s, is_struct, _is_union| match s {
        "CURL" | "CURLM" | "CURLSH" | "curl_version_info_data" => s.to_string(),
        "curl_khtype" | "curl_khstat" | "curl_khmatch" => format!("enum {}", s),
        s if is_struct => format!("struct {}", s),
        "sockaddr" => format!("struct sockaddr"),
        s => s.to_string(),
    });
    // cfg.fn_cname(|s, l| l.unwrap_or(s).to_string());
    cfg.skip_type(|n| n == "__enum_ty");
    cfg.skip_signededness(|s| s.ends_with("callback") || s.ends_with("function"));

    cfg.skip_struct(move |s| {
        if version < 60 {
            match s {
                "curl_version_info_data" => return true,
                _ => {}
            }
        }

        false
    });

    cfg.skip_const(move |s| {
        if version < 64 {
            match s {
                "CURLE_HTTP2" => return true,
                "CURLE_PEER_FAILED_VERIFICATION" => return true,
                "CURLE_NO_CONNECTION_AVAILABLE" => return true,
                "CURLE_SSL_PINNEDPUBKEYNOTMATCH" => return true,
                "CURLE_SSL_INVALIDCERTSTATUS" => return true,
                "CURLE_HTTP2_STREAM" => return true,
                "CURLE_RECURSIVE_API_CALL" => return true,
                _ => {}
            }
        }
        if version < 61 {
            match s {
                "CURLOPT_PIPEWAIT" => return true,
                "CURLE_PEER_FAILED_VERIFICATION" => return true,
                _ => {}
            }
        }
        if version < 60 {
            match s {
                "CURLVERSION_FIFTH" | "CURLVERSION_NOW" => return true,
                _ => {}
            }
        }
        if version < 54 {
            match s {
                "CURL_SSLVERSION_TLSv1_3" => return true,
                _ => {}
            }
        }

        if version < 49 {
            if s.starts_with("CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE") {
                return true;
            }
        }

        if version < 47 {
            if s.starts_with("CURL_HTTP_VERSION_2") {
                return true;
            }
        }

        if version < 43 {
            if s.starts_with("CURLPIPE_") {
                return true;
            }
        }

        // OSX doesn't have this yet
        s == "CURLSSLOPT_NO_REVOKE" ||

        // A lot of curl versions doesn't support unix sockets
        s == "CURLOPT_UNIX_SOCKET_PATH" || s == "CURL_VERSION_UNIX_SOCKETS"
    });

    if cfg!(target_env = "msvc") {
        cfg.skip_fn_ptrcheck(|s| s.starts_with("curl_"));
    }

    cfg.generate("../curl-sys/lib.rs", "all.rs");
}
<|endoftext|>


<commit_before>//! An RPC library for Rust.
//!
//! Example usage:
//!
//! ```
//! # #![feature(custom_derive, plugin)]
//! # #![plugin(serde_macros)]
//! # #[macro_use] extern crate tarpc;
//! # extern crate serde;
//! rpc! {
//!     mod my_server {
//!         service {
//!             rpc hello(name: String) -> String;
//!             rpc add(x: i32, y: i32) -> i32;
//!         }
//!     }
//! }
//!
//! use self::my_server::*;
//! use std::time::Duration;
//!
//! impl my_server::Service for () {
//!     fn hello(&self, s: String) -> String {
//!         format!("Hello, {}!", s)
//!     }
//!     fn add(&self, x: i32, y: i32) -> i32 {
//!         x + y
//!     }
//! }
//!
//! fn main() {
//!     let addr = "127.0.0.1:9000";
//! let shutdown = my_server::serve(addr, (),
//! Some(Duration::from_secs(30))).unwrap();
//!     let client = Client::new(addr, None).unwrap();
//!     assert_eq!(3, client.add(1, 2).unwrap());
//!     assert_eq!("Hello, Mom!".to_string(),
//!                client.hello("Mom".to_string()).unwrap());
//!     drop(client);
//!     shutdown.shutdown();
//! }
//! ```

#![feature(trace_macros)]
#![feature(const_fn)]
#![feature(braced_empty_structs)]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
#![deny(missing_docs)]

extern crate serde;
extern crate bincode;
#[macro_use]
extern crate log;

/// Provides the tarpc client and server, which implements the tarpc protocol.
/// The protocol is defined by the implementation.
pub mod protocol;

/// Provides the macro used for constructing rpc services and client stubs.
pub mod macros;

pub use protocol::{Error, Result};
<commit_msg>Remove unused feature enables<commit_after>//! An RPC library for Rust.
//!
//! Example usage:
//!
//! ```
//! # #![feature(custom_derive, plugin)]
//! # #![plugin(serde_macros)]
//! # #[macro_use] extern crate tarpc;
//! # extern crate serde;
//! rpc! {
//!     mod my_server {
//!         service {
//!             rpc hello(name: String) -> String;
//!             rpc add(x: i32, y: i32) -> i32;
//!         }
//!     }
//! }
//!
//! use self::my_server::*;
//! use std::time::Duration;
//!
//! impl my_server::Service for () {
//!     fn hello(&self, s: String) -> String {
//!         format!("Hello, {}!", s)
//!     }
//!     fn add(&self, x: i32, y: i32) -> i32 {
//!         x + y
//!     }
//! }
//!
//! fn main() {
//!     let addr = "127.0.0.1:9000";
//! let shutdown = my_server::serve(addr, (),
//! Some(Duration::from_secs(30))).unwrap();
//!     let client = Client::new(addr, None).unwrap();
//!     assert_eq!(3, client.add(1, 2).unwrap());
//!     assert_eq!("Hello, Mom!".to_string(),
//!                client.hello("Mom".to_string()).unwrap());
//!     drop(client);
//!     shutdown.shutdown();
//! }
//! ```

#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
#![deny(missing_docs)]

extern crate serde;
extern crate bincode;
#[macro_use]
extern crate log;

/// Provides the tarpc client and server, which implements the tarpc protocol.
/// The protocol is defined by the implementation.
pub mod protocol;

/// Provides the macro used for constructing rpc services and client stubs.
pub mod macros;

pub use protocol::{Error, Result};
<|endoftext|>