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

use diem_crypto::hash::HashValue;
use diem_logger::prelude::*;
use diem_types::{
    block_info::BlockInfo,
    ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
    protocol_spec::DpnProto,
    transaction::Version,
};
use diem_vm::DiemVM;
use diemdb::metrics::DIEM_STORAGE_API_LATENCY_SECONDS;
use executor::{
    metrics::{
        DIEM_EXECUTOR_COMMIT_BLOCKS_SECONDS, DIEM_EXECUTOR_EXECUTE_BLOCK_SECONDS,
        DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS,
    },
    Executor,
};
use executor_types::BlockExecutor;
use std::{
    collections::BTreeMap,
    sync::{mpsc, Arc},
    time::{Duration, Instant},
};

pub(crate) fn gen_li_with_sigs(
    block_id: HashValue,
    root_hash: HashValue,
    version: Version,
) -> LedgerInfoWithSignatures {
    let block_info = BlockInfo::new(
        1,        /* epoch */
        0,        /* round, doesn't matter */
        block_id, /* id, doesn't matter */
        root_hash, version, 0,    /* timestamp_usecs, doesn't matter */
        None, /* next_epoch_state */
    );
    let ledger_info = LedgerInfo::new(
        block_info,
        HashValue::zero(), /* consensus_data_hash, doesn't matter */
    );
    LedgerInfoWithSignatures::new(ledger_info, BTreeMap::new() /* signatures */)
}

pub struct TransactionCommitter {
    executor: Arc<Executor<DpnProto, DiemVM>>,
    version: Version,
    block_receiver: mpsc::Receiver<(HashValue, HashValue, Instant, Instant, Duration, usize)>,
}

impl TransactionCommitter {
    pub fn new(
        executor: Arc<Executor<DpnProto, DiemVM>>,
        version: Version,
        block_receiver: mpsc::Receiver<(HashValue, HashValue, Instant, Instant, Duration, usize)>,
    ) -> Self {
        Self {
            version,
            executor,
            block_receiver,
        }
    }

    pub fn run(&mut self) {
        info!("Start with version: {}", self.version);

        while let Ok((
            block_id,
            root_hash,
            global_start_time,
            execution_start_time,
            execution_time,
            num_txns,
        )) = self.block_receiver.recv()
        {
            self.version += num_txns as u64;
            let commit_start = std::time::Instant::now();
            let ledger_info_with_sigs = gen_li_with_sigs(block_id, root_hash, self.version);
            self.executor
                .commit_blocks(vec![block_id], ledger_info_with_sigs)
                .unwrap();

            report_block(
                self.version,
                global_start_time,
                execution_start_time,
                execution_time,
                Instant::now().duration_since(commit_start),
                num_txns,
            );
        }
    }
}

fn report_block(
    version: Version,
    global_start_time: Instant,
    execution_start_time: Instant,
    execution_time: Duration,
    commit_time: Duration,
    block_size: usize,
) {
    info!(
        "Version: {}. latency: {} ms, execute time: {} ms. commit time: {} ms. TPS: {:.0}. Accumulative TPS: {:.0}",
        version,
        Instant::now().duration_since(execution_start_time).as_millis(),
        execution_time.as_millis(),
        commit_time.as_millis(),
        block_size as f64 / (std::cmp::max(execution_time, commit_time)).as_secs_f64(),
        version as f64 / global_start_time.elapsed().as_secs_f64(),
    );
    info!(
            "Accumulative total: VM time: {:.0} secs, executor time: {:.0} secs, commit time: {:.0} secs, DB commit time: {:.0} secs",
            DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum(),
            DIEM_EXECUTOR_EXECUTE_BLOCK_SECONDS.get_sample_sum() - DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum(),
            DIEM_EXECUTOR_COMMIT_BLOCKS_SECONDS.get_sample_sum(),
            DIEM_STORAGE_API_LATENCY_SECONDS.get_metric_with_label_values(&["save_transactions", "Ok"]).expect("must exist.").get_sample_sum(),
        );
    const NANOS_PER_SEC: f64 = 1_000_000_000.0;
    info!(
            "Accumulative per transaction: VM time: {:.0} ns, executor time: {:.0} ns, commit time: {:.0} ns, DB commit time: {:.0} ns",
            DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum() * NANOS_PER_SEC
                / version as f64,
            (DIEM_EXECUTOR_EXECUTE_BLOCK_SECONDS.get_sample_sum() - DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum()) * NANOS_PER_SEC
                / version as f64,
            DIEM_EXECUTOR_COMMIT_BLOCKS_SECONDS.get_sample_sum() * NANOS_PER_SEC
                / version as f64,
            DIEM_STORAGE_API_LATENCY_SECONDS.get_metric_with_label_values(&["save_transactions", "Ok"]).expect("must exist.").get_sample_sum() * NANOS_PER_SEC
                / version as f64,
        );
}
<commit_msg>[executor-benchmark] fix accumulative metrics<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use diem_crypto::hash::HashValue;
use diem_logger::prelude::*;
use diem_types::{
    block_info::BlockInfo,
    ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
    protocol_spec::DpnProto,
    transaction::Version,
};
use diem_vm::DiemVM;
use diemdb::metrics::DIEM_STORAGE_API_LATENCY_SECONDS;
use executor::{
    metrics::{
        DIEM_EXECUTOR_COMMIT_BLOCKS_SECONDS, DIEM_EXECUTOR_EXECUTE_BLOCK_SECONDS,
        DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS,
    },
    Executor,
};
use executor_types::BlockExecutor;
use std::{
    collections::BTreeMap,
    sync::{mpsc, Arc},
    time::{Duration, Instant},
};

pub(crate) fn gen_li_with_sigs(
    block_id: HashValue,
    root_hash: HashValue,
    version: Version,
) -> LedgerInfoWithSignatures {
    let block_info = BlockInfo::new(
        1,        /* epoch */
        0,        /* round, doesn't matter */
        block_id, /* id, doesn't matter */
        root_hash, version, 0,    /* timestamp_usecs, doesn't matter */
        None, /* next_epoch_state */
    );
    let ledger_info = LedgerInfo::new(
        block_info,
        HashValue::zero(), /* consensus_data_hash, doesn't matter */
    );
    LedgerInfoWithSignatures::new(ledger_info, BTreeMap::new() /* signatures */)
}

pub struct TransactionCommitter {
    executor: Arc<Executor<DpnProto, DiemVM>>,
    version: Version,
    block_receiver: mpsc::Receiver<(HashValue, HashValue, Instant, Instant, Duration, usize)>,
}

impl TransactionCommitter {
    pub fn new(
        executor: Arc<Executor<DpnProto, DiemVM>>,
        version: Version,
        block_receiver: mpsc::Receiver<(HashValue, HashValue, Instant, Instant, Duration, usize)>,
    ) -> Self {
        Self {
            version,
            executor,
            block_receiver,
        }
    }

    pub fn run(&mut self) {
        let start_version = self.version;
        info!("Start with version: {}", start_version);

        while let Ok((
            block_id,
            root_hash,
            global_start_time,
            execution_start_time,
            execution_time,
            num_txns,
        )) = self.block_receiver.recv()
        {
            self.version += num_txns as u64;
            let commit_start = std::time::Instant::now();
            let ledger_info_with_sigs = gen_li_with_sigs(block_id, root_hash, self.version);
            self.executor
                .commit_blocks(vec![block_id], ledger_info_with_sigs)
                .unwrap();

            report_block(
                start_version,
                self.version,
                global_start_time,
                execution_start_time,
                execution_time,
                Instant::now().duration_since(commit_start),
                num_txns,
            );
        }
    }
}

fn report_block(
    start_version: Version,
    version: Version,
    global_start_time: Instant,
    execution_start_time: Instant,
    execution_time: Duration,
    commit_time: Duration,
    block_size: usize,
) {
    let total_versions = (version - start_version) as f64;
    info!(
        "Version: {}. latency: {} ms, execute time: {} ms. commit time: {} ms. TPS: {:.0}. Accumulative TPS: {:.0}",
        version,
        Instant::now().duration_since(execution_start_time).as_millis(),
        execution_time.as_millis(),
        commit_time.as_millis(),
        block_size as f64 / (std::cmp::max(execution_time, commit_time)).as_secs_f64(),
        total_versions / global_start_time.elapsed().as_secs_f64(),
    );
    info!(
            "Accumulative total: VM time: {:.0} secs, executor time: {:.0} secs, commit time: {:.0} secs, DB commit time: {:.0} secs",
            DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum(),
            DIEM_EXECUTOR_EXECUTE_BLOCK_SECONDS.get_sample_sum() - DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum(),
            DIEM_EXECUTOR_COMMIT_BLOCKS_SECONDS.get_sample_sum(),
            DIEM_STORAGE_API_LATENCY_SECONDS.get_metric_with_label_values(&["save_transactions", "Ok"]).expect("must exist.").get_sample_sum(),
        );
    const NANOS_PER_SEC: f64 = 1_000_000_000.0;
    info!(
            "Accumulative per transaction: VM time: {:.0} ns, executor time: {:.0} ns, commit time: {:.0} ns, DB commit time: {:.0} ns",
            DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum() * NANOS_PER_SEC
                / total_versions,
            (DIEM_EXECUTOR_EXECUTE_BLOCK_SECONDS.get_sample_sum() - DIEM_EXECUTOR_VM_EXECUTE_BLOCK_SECONDS.get_sample_sum()) * NANOS_PER_SEC
                / total_versions,
            DIEM_EXECUTOR_COMMIT_BLOCKS_SECONDS.get_sample_sum() * NANOS_PER_SEC
                / total_versions,
            DIEM_STORAGE_API_LATENCY_SECONDS.get_metric_with_label_values(&["save_transactions", "Ok"]).expect("must exist.").get_sample_sum() * NANOS_PER_SEC
                / total_versions,
        );
}
<|endoftext|>


<commit_before>use super::ipv4_header::{Ipv4Header, Ipv4HeaderData, Ipv4HeaderMut};
use super::transport_header::{TransportHeader, TransportHeaderData, TransportHeaderMut};

pub const MAX_PACKET_LENGTH: usize = 1 << 16;

pub struct Ipv4Packet<'a> {
    raw: &'a mut [u8],
    ipv4_header_data: Ipv4HeaderData,
    transport_header_data: Option<TransportHeaderData>,
}

impl<'a> Ipv4Packet<'a> {
    pub fn parse(raw: &'a mut [u8]) -> Self {
        let ipv4_header_data = Ipv4HeaderData::parse(raw);
        let transport_header_data = {
            let payload = &raw[ipv4_header_data.header_length() as usize..];
            TransportHeaderData::parse(ipv4_header_data.protocol(), payload)
        };
        Self {
            raw: &mut raw[..ipv4_header_data.total_length() as usize],
            ipv4_header_data: ipv4_header_data,
            transport_header_data: transport_header_data,
        }
    }

    pub fn new(
        raw: &'a mut [u8],
        ipv4_header_data: Ipv4HeaderData,
        transport_header_data: TransportHeaderData,
    ) -> Self {
        Self {
            raw: raw,
            ipv4_header_data: ipv4_header_data,
            transport_header_data: Some(transport_header_data),
        }
    }

    #[inline]
    pub fn raw(&self) -> &[u8] {
        self.raw
    }

    #[inline]
    #[allow(dead_code)]
    pub fn ipv4_header_data(&self) -> &Ipv4HeaderData {
        &self.ipv4_header_data
    }

    #[inline]
    #[allow(dead_code)]
    pub fn ipv4_header(&self) -> Ipv4Header {
        let slice = &self.raw[..self.ipv4_header_data.header_length() as usize];
        self.ipv4_header_data.bind(slice)
    }

    #[inline]
    #[allow(dead_code)]
    pub fn ipv4_header_mut(&mut self) -> Ipv4HeaderMut {
        let slice = &mut self.raw[..self.ipv4_header_data.header_length() as usize];
        self.ipv4_header_data.bind_mut(slice)
    }

    #[inline]
    #[allow(dead_code)]
    pub fn transport_header_data(&self) -> &Option<TransportHeaderData> {
        &self.transport_header_data
    }

    #[inline]
    pub fn transport_header(&self) -> Option<TransportHeader> {
        if let Some(ref transport_header_data) = self.transport_header_data {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &self.raw[start..end];
            Some(transport_header_data.bind(slice))
        } else {
            None
        }
        /*        self.transport_header_data.as_ref().map(|transport_header_data| {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &self.raw[start..end];
            transport_header_data.bind(slice)
        })*/
    }

    #[inline]
    #[allow(dead_code)]
    fn transport_header_mut(&mut self) -> Option<TransportHeaderMut> {
        if let Some(ref mut transport_header_data) = self.transport_header_data {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &mut self.raw[start..end];
            Some(transport_header_data.bind_mut(slice))
        } else {
            None
        }
        /*        self.transport_header_data.as_mut().map(|transport_header_data| {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &mut self.raw[start..end];
            transport_header_data.bind_mut(slice)
        })*/
    }

    /// Devide the packet into parts:
    ///  - the IP v4 header
    ///  - the transport header (if any)
    ///  - the payload (if there is a transport at all)
    pub fn split(&self) -> (Ipv4Header, Option<(TransportHeader, &[u8])>) {
        let transport_index = self.ipv4_header_data.header_length() as usize;
        if let Some(ref transport_header_data) = self.transport_header_data {
            // payload_index is relative to transport
            let payload_index = transport_header_data.header_length() as usize;
            let (ipv4_header_slice, transport_slice) = self.raw.split_at(transport_index);
            let (transport_header_slice, payload_slice) = transport_slice.split_at(payload_index);
            let ipv4_header = self.ipv4_header_data.bind(ipv4_header_slice);
            let transport_header = transport_header_data.bind(transport_header_slice);
            (ipv4_header, Some((transport_header, payload_slice)))
        } else {
            let ipv4_header_slice = &self.raw[..transport_index];
            let ipv4_header = self.ipv4_header_data.bind(ipv4_header_slice);
            (ipv4_header, None)
        }
    }

    /// Devide the packet into mutable parts:
    ///  - the IP v4 header
    ///  - the transport header (if any)
    ///  - the payload (if there is a transport at all)
    pub fn split_mut(&mut self) -> (Ipv4HeaderMut, Option<(TransportHeaderMut, &mut [u8])>) {
        let transport_index = self.ipv4_header_data.header_length() as usize;
        if let Some(ref mut transport_header_data) = self.transport_header_data {
            // payload_index is relative to transport
            let payload_index = transport_header_data.header_length() as usize;
            let (ipv4_header_slice, transport_slice) = self.raw.split_at_mut(transport_index);
            let (transport_header_slice, payload_slice) =
                transport_slice.split_at_mut(payload_index);
            let ipv4_header = self.ipv4_header_data.bind_mut(ipv4_header_slice);
            let transport_header = transport_header_data.bind_mut(transport_header_slice);
            (ipv4_header, Some((transport_header, payload_slice)))
        } else {
            let ipv4_header_slice = &mut self.raw[..transport_index];
            let ipv4_header = self.ipv4_header_data.bind_mut(ipv4_header_slice);
            (ipv4_header, None)
        }
    }

    #[inline]
    pub fn is_valid(&self) -> bool {
        self.transport_header_data.is_some()
    }

    #[inline]
    pub fn length(&self) -> u16 {
        self.ipv4_header_data.total_length()
    }

    pub fn payload(&self) -> Option<&[u8]> {
        self.transport_header_data.as_ref().map(
            |transport_header_data| {
                let range = self.ipv4_header_data.header_length() as usize +
                    transport_header_data.header_length() as usize..;
                &self.raw[range]
            },
        )
    }

    pub fn compute_checksums(&mut self) {
        let (mut ipv4_header, transport) = self.split_mut();
        ipv4_header.update_checksum();
        if let Some((mut transport_header, payload)) = transport {
            transport_header.update_checksum(ipv4_header.data(), payload);
        }
    }

    /*#[inline]
    pub fn swap_source_and_destination(&mut self) {
        self.ipv4_header_mut().swap_source_and_destination();
        if let Some(mut transport_header) = self.transport_header_mut() {
            transport_header.swap_source_and_destination();
        }
    }*/
}

#[cfg(test)]
mod tests {
    use super::*;
    use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
    use relay::ipv4_header::Protocol;

    fn create_packet() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(32);

        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(32).unwrap(); // total length 20 + 8 + 4
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(17).unwrap(); // protocol (UDP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0x42424242).unwrap(); // destination address

        raw.write_u16::<BigEndian>(1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(5678).unwrap(); // destination port
        raw.write_u16::<BigEndian>(4).unwrap(); // length
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum

        raw.write_u32::<BigEndian>(0x11223344).unwrap(); // payload

        raw
    }

    #[test]
    fn parse_headers() {
        let raw = &mut create_packet()[..];
        let mut ipv4_packet = Ipv4Packet::parse(raw);

        {
            let ipv4_header = ipv4_packet.ipv4_header();
            assert_eq!(20, ipv4_header.header_length());
            assert_eq!(32, ipv4_header.total_length());
            assert_eq!(Protocol::Udp, ipv4_header.protocol());
            assert_eq!(0x12345678, ipv4_header.source());
            assert_eq!(0x42424242, ipv4_header.destination());

            if let Some(TransportHeaderData::Udp(ref udp_header)) =
                *ipv4_packet.transport_header_data()
            {
                assert_eq!(1234, udp_header.source_port());
                assert_eq!(5678, udp_header.destination_port());
            } else {
                panic!("No UDP transport header");
            }
        }
    }

    #[test]
    fn payload() {
        let raw = &mut create_packet()[..];
        let ipv4_packet = Ipv4Packet::parse(raw);
        assert_eq!([0x11, 0x22, 0x33, 0x44], ipv4_packet.payload().unwrap());
    }
}
<commit_msg>Fix rust tests warnings<commit_after>use super::ipv4_header::{Ipv4Header, Ipv4HeaderData, Ipv4HeaderMut};
use super::transport_header::{TransportHeader, TransportHeaderData, TransportHeaderMut};

pub const MAX_PACKET_LENGTH: usize = 1 << 16;

pub struct Ipv4Packet<'a> {
    raw: &'a mut [u8],
    ipv4_header_data: Ipv4HeaderData,
    transport_header_data: Option<TransportHeaderData>,
}

impl<'a> Ipv4Packet<'a> {
    pub fn parse(raw: &'a mut [u8]) -> Self {
        let ipv4_header_data = Ipv4HeaderData::parse(raw);
        let transport_header_data = {
            let payload = &raw[ipv4_header_data.header_length() as usize..];
            TransportHeaderData::parse(ipv4_header_data.protocol(), payload)
        };
        Self {
            raw: &mut raw[..ipv4_header_data.total_length() as usize],
            ipv4_header_data: ipv4_header_data,
            transport_header_data: transport_header_data,
        }
    }

    pub fn new(
        raw: &'a mut [u8],
        ipv4_header_data: Ipv4HeaderData,
        transport_header_data: TransportHeaderData,
    ) -> Self {
        Self {
            raw: raw,
            ipv4_header_data: ipv4_header_data,
            transport_header_data: Some(transport_header_data),
        }
    }

    #[inline]
    pub fn raw(&self) -> &[u8] {
        self.raw
    }

    #[inline]
    #[allow(dead_code)]
    pub fn ipv4_header_data(&self) -> &Ipv4HeaderData {
        &self.ipv4_header_data
    }

    #[inline]
    #[allow(dead_code)]
    pub fn ipv4_header(&self) -> Ipv4Header {
        let slice = &self.raw[..self.ipv4_header_data.header_length() as usize];
        self.ipv4_header_data.bind(slice)
    }

    #[inline]
    #[allow(dead_code)]
    pub fn ipv4_header_mut(&mut self) -> Ipv4HeaderMut {
        let slice = &mut self.raw[..self.ipv4_header_data.header_length() as usize];
        self.ipv4_header_data.bind_mut(slice)
    }

    #[inline]
    #[allow(dead_code)]
    pub fn transport_header_data(&self) -> &Option<TransportHeaderData> {
        &self.transport_header_data
    }

    #[inline]
    pub fn transport_header(&self) -> Option<TransportHeader> {
        if let Some(ref transport_header_data) = self.transport_header_data {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &self.raw[start..end];
            Some(transport_header_data.bind(slice))
        } else {
            None
        }
        /*        self.transport_header_data.as_ref().map(|transport_header_data| {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &self.raw[start..end];
            transport_header_data.bind(slice)
        })*/
    }

    #[inline]
    #[allow(dead_code)]
    fn transport_header_mut(&mut self) -> Option<TransportHeaderMut> {
        if let Some(ref mut transport_header_data) = self.transport_header_data {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &mut self.raw[start..end];
            Some(transport_header_data.bind_mut(slice))
        } else {
            None
        }
        /*        self.transport_header_data.as_mut().map(|transport_header_data| {
            let start = self.ipv4_header_data.header_length() as usize;
            let end = start + transport_header_data.header_length() as usize;
            let slice = &mut self.raw[start..end];
            transport_header_data.bind_mut(slice)
        })*/
    }

    /// Devide the packet into parts:
    ///  - the IP v4 header
    ///  - the transport header (if any)
    ///  - the payload (if there is a transport at all)
    pub fn split(&self) -> (Ipv4Header, Option<(TransportHeader, &[u8])>) {
        let transport_index = self.ipv4_header_data.header_length() as usize;
        if let Some(ref transport_header_data) = self.transport_header_data {
            // payload_index is relative to transport
            let payload_index = transport_header_data.header_length() as usize;
            let (ipv4_header_slice, transport_slice) = self.raw.split_at(transport_index);
            let (transport_header_slice, payload_slice) = transport_slice.split_at(payload_index);
            let ipv4_header = self.ipv4_header_data.bind(ipv4_header_slice);
            let transport_header = transport_header_data.bind(transport_header_slice);
            (ipv4_header, Some((transport_header, payload_slice)))
        } else {
            let ipv4_header_slice = &self.raw[..transport_index];
            let ipv4_header = self.ipv4_header_data.bind(ipv4_header_slice);
            (ipv4_header, None)
        }
    }

    /// Devide the packet into mutable parts:
    ///  - the IP v4 header
    ///  - the transport header (if any)
    ///  - the payload (if there is a transport at all)
    pub fn split_mut(&mut self) -> (Ipv4HeaderMut, Option<(TransportHeaderMut, &mut [u8])>) {
        let transport_index = self.ipv4_header_data.header_length() as usize;
        if let Some(ref mut transport_header_data) = self.transport_header_data {
            // payload_index is relative to transport
            let payload_index = transport_header_data.header_length() as usize;
            let (ipv4_header_slice, transport_slice) = self.raw.split_at_mut(transport_index);
            let (transport_header_slice, payload_slice) =
                transport_slice.split_at_mut(payload_index);
            let ipv4_header = self.ipv4_header_data.bind_mut(ipv4_header_slice);
            let transport_header = transport_header_data.bind_mut(transport_header_slice);
            (ipv4_header, Some((transport_header, payload_slice)))
        } else {
            let ipv4_header_slice = &mut self.raw[..transport_index];
            let ipv4_header = self.ipv4_header_data.bind_mut(ipv4_header_slice);
            (ipv4_header, None)
        }
    }

    #[inline]
    pub fn is_valid(&self) -> bool {
        self.transport_header_data.is_some()
    }

    #[inline]
    pub fn length(&self) -> u16 {
        self.ipv4_header_data.total_length()
    }

    pub fn payload(&self) -> Option<&[u8]> {
        self.transport_header_data.as_ref().map(
            |transport_header_data| {
                let range = self.ipv4_header_data.header_length() as usize +
                    transport_header_data.header_length() as usize..;
                &self.raw[range]
            },
        )
    }

    pub fn compute_checksums(&mut self) {
        let (mut ipv4_header, transport) = self.split_mut();
        ipv4_header.update_checksum();
        if let Some((mut transport_header, payload)) = transport {
            transport_header.update_checksum(ipv4_header.data(), payload);
        }
    }

    /*#[inline]
    pub fn swap_source_and_destination(&mut self) {
        self.ipv4_header_mut().swap_source_and_destination();
        if let Some(mut transport_header) = self.transport_header_mut() {
            transport_header.swap_source_and_destination();
        }
    }*/
}

#[cfg(test)]
mod tests {
    use super::*;
    use byteorder::{BigEndian, WriteBytesExt};
    use relay::ipv4_header::Protocol;

    fn create_packet() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(32);

        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(32).unwrap(); // total length 20 + 8 + 4
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(17).unwrap(); // protocol (UDP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0x42424242).unwrap(); // destination address

        raw.write_u16::<BigEndian>(1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(5678).unwrap(); // destination port
        raw.write_u16::<BigEndian>(4).unwrap(); // length
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum

        raw.write_u32::<BigEndian>(0x11223344).unwrap(); // payload

        raw
    }

    #[test]
    fn parse_headers() {
        let raw = &mut create_packet()[..];
        let ipv4_packet = Ipv4Packet::parse(raw);

        {
            let ipv4_header = ipv4_packet.ipv4_header();
            assert_eq!(20, ipv4_header.header_length());
            assert_eq!(32, ipv4_header.total_length());
            assert_eq!(Protocol::Udp, ipv4_header.protocol());
            assert_eq!(0x12345678, ipv4_header.source());
            assert_eq!(0x42424242, ipv4_header.destination());

            if let Some(TransportHeaderData::Udp(ref udp_header)) =
                *ipv4_packet.transport_header_data()
            {
                assert_eq!(1234, udp_header.source_port());
                assert_eq!(5678, udp_header.destination_port());
            } else {
                panic!("No UDP transport header");
            }
        }
    }

    #[test]
    fn payload() {
        let raw = &mut create_packet()[..];
        let ipv4_packet = Ipv4Packet::parse(raw);
        assert_eq!([0x11, 0x22, 0x33, 0x44], ipv4_packet.payload().unwrap());
    }
}
<|endoftext|>


<commit_before>extern crate ws;
extern crate clap;
extern crate serde;
extern crate serde_json;

use serde_json::Value;

use clap::{App, Arg};

const NULL_PAYLOAD: &'static Value = &Value::Null;

struct BenchHandler {
    ws: ws::Sender,
    count: u32,
}

impl ws::Handler for BenchHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        if let Ok(body) = msg.as_text() {
            if let Ok(obj) = serde_json::from_str::<Value>(body) {
                if let Some((msg_type, payload)) = obj.as_object().map(|map| {
                    (map.get("type").and_then(Value::as_str).unwrap_or(""),
                     map.get("payload").unwrap_or(NULL_PAYLOAD))
                }) {
                    match msg_type {
                        "echo" => {
                            try!(self.ws.send(body));
                        }
                        "broadcast" => {
                            try!(self.ws.broadcast(body));
                            try!(self.ws.send(format!(r#"{{"type":"broadcastResult","listenCount": {}, "payload":{}}}"#,
                                                          self.count,
                                                          payload)))
                        }
                        _ => {}
                    }
                }
            }
        }
        Ok(())
    }

    fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
        self.count += 1;
        println!("Connection Open! {}", self.count);
        Ok(())
    }

    fn on_close(&mut self, _: ws::CloseCode, _: &str) {
        self.count -= 1;
        println!("Connection Closed! {}", self.count);
    }
}

fn main() {
    let matches = App::new("rust-ws-server")
                      .version("1.0")
                      .arg(Arg::with_name("address")
                               .short("a")
                               .long("address")
                               .required(true)
                               .takes_value(true)
                               .default_value("127.0.0.1"))
                      .arg(Arg::with_name("port")
                               .short("p")
                               .long("port")
                               .required(true)
                               .takes_value(true)
                               .default_value("3000"))
                      .get_matches();

    if let (Some(address), Some(port)) = (matches.value_of("address"), matches.value_of("port")) {
        ws::Builder::new()
            .with_settings(ws::Settings { max_connections: 500_000, ..Default::default() })
            .build(|out| {
                BenchHandler {
                    ws: out,
                    count: 0,
                }
            })
            .unwrap()
            .listen(&*format!("{}:{}", address, port))
            .unwrap();
    } else {
        println!("{}", matches.usage());
    }
}
<commit_msg>reduce indentation and method chains via nested patterns<commit_after>extern crate ws;
extern crate clap;
extern crate serde;
extern crate serde_json;

use serde_json::Value;

use clap::{App, Arg};

const NULL_PAYLOAD: &'static Value = &Value::Null;

struct BenchHandler {
    ws: ws::Sender,
    count: u32,
}

impl ws::Handler for BenchHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        if let Ok(Ok(Value::Object(obj))) = msg.as_text().map(serde_json::from_str::<Value>) {
            if let Some(&Value::String(ref s)) = obj.get("type") {
                if s == "echo" {
                    try!(self.ws.send(msg))
                } else if s == "broadcast" {
                    try!(self.ws.broadcast(msg));
                    try!(self.ws.send(format!(r#"{{"type":"broadcastResult","listenCount": {},"payload":{}}}"#,
                                              self.count,
                                              obj.get("payload").unwrap_or(NULL_PAYLOAD))))
                }
            }
        }
        Ok(())
    }

    fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
        self.count += 1;
        println!("Connection Open! {}", self.count);
        Ok(())
    }

    fn on_close(&mut self, _: ws::CloseCode, _: &str) {
        self.count -= 1;
        println!("Connection Closed! {}", self.count);
    }
}

fn main() {
    let matches = App::new("rust-ws-server")
                      .version("1.0")
                      .arg(Arg::with_name("address")
                               .short("a")
                               .long("address")
                               .required(true)
                               .takes_value(true)
                               .default_value("127.0.0.1"))
                      .arg(Arg::with_name("port")
                               .short("p")
                               .long("port")
                               .required(true)
                               .takes_value(true)
                               .default_value("3000"))
                      .get_matches();

    if let (Some(address), Some(port)) = (matches.value_of("address"), matches.value_of("port")) {
        ws::Builder::new()
            .with_settings(ws::Settings { max_connections: 500_000, ..Default::default() })
            .build(|out| {
                BenchHandler {
                    ws: out,
                    count: 0,
                }
            })
            .unwrap()
            .listen(&*format!("{}:{}", address, port))
            .unwrap();
    } else {
        println!("{}", matches.usage());
    }
}
<|endoftext|>


<commit_before>//! The module for the automatic map generation

use noise::{Brownian2, Seed, open_simplex2};

// TODO pick:
// use core::*;
// use core::{Map, Tile, TileMap};
use core::*;

pub const CHUNK_SIZE: i64 = 64;

/// A map
///
/// Note: It's chunked into big chunks and small chunks.
///       Small chunks keeps the noise data. Big chunks
///       determines the overlay layer.
pub struct MapGenerator<'a> {
  seed: &'a Seed,
}

/// Types of big chunks
pub enum BChunkType {
  /// Reserved for history, empty per default, but gets opened as the game is
  /// played. Manually designed.
  History,
  /// Automatic map generated chunk
  Auto,
  /// Manually random generated chunk
  Manually,
  /// Empty chunk
  Empty,
}

// TODO: Find out how to prevent double islands (manually generated islands)

// TODO: Use Vec2 in this methods:
impl<'a> MapGenerator<'a> {
  /// Creates a new map
  pub fn new(seed: &'a Seed) -> MapGenerator<'a> {
    MapGenerator {
      seed: seed,
    }
  }

  // TODO: Add some sort of cache

  /// Get the noise value at a given point
  pub fn get_noise_value(&self, coord: Vec2<i64>) -> f64 {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    noise.apply(&self.seed, &[coord.x() as f64, coord.y() as f64])
    // Todo: Add some sort of converter method
  }

  /// Get big chunk coordinates
  pub fn get_bchunk(coord: Vec2<i64>) -> Vec2<i64> {
    // TODO: Chunk size 64?
    Vec2(((coord.x() as f64) / (CHUNK_SIZE as f64)).floor() as i64,
         ((coord.y() as f64) / (CHUNK_SIZE as f64)).floor() as i64)
  }

  /// Get the chunk type of the big chunk at (x, y)
  pub fn get_bchunk_type(&self, coord: Vec2<i64>) -> BChunkType {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    let noise_val =
      noise.apply(&self.seed, &[coord.x() as f64, coord.y() as f64]);
    if noise_val > 0.3 {
      BChunkType::Empty // Too many too few?
    } else if noise_val > 0.1 {
      BChunkType::Auto
    } else if noise_val > 0.05 {
      BChunkType::History
    } else {
      BChunkType::Manually
    }
  }

  /// Get overlay value (used for customizing the noise)
  pub fn get_overlay_value(&self, coord: Vec2<i64>) -> f64 {
    let Vec2(x, y) = coord;

    // Center chunk coordinate
    let Vec2(cx, cy) = MapGenerator::get_bchunk(coord) + Vec2(32, 32);
    let chunk_type = self.get_bchunk_type(Vec2(cx, cy));
    let chunk_int = self.seed.get2([cx, cy]);
    let chunk_value = (chunk_int as f64) / (usize::max_value() as f64);
    match chunk_type {
      BChunkType::Empty => 0.0,
      BChunkType::Auto => {
        // This is why we need vector math, kids.
        // TODO: Use vec math here

        use std::f64;

        // TODO: Make more shapes.
        let elip_dist = (((cx - x) * (cx - x) + (cy - y) * (cy - y)) as f64)
                        .sqrt();
        let angle = chunk_value * f64::consts::PI * 2.0;
        let (cirx, ciry) = (angle.sin() + cx as f64,
                            angle.cos() + cy as f64);
        let sec_dist = ((cirx - x as f64) * (cirx - x as f64)
                       + (ciry - y as f64) * (ciry - y as f64)).sqrt();
        let dist = sec_dist.max(elip_dist);

        let res = 1.0 - dist / 25.0;

        if res > 0.0 {
          res
        } else {
          0.0
        }
      },
      _ => 0.0,
    }
  }
}

impl<'a> TileMap for MapGenerator<'a> {

  // TODO: Rename to get block?
  /// Get the tile at a given point
  fn get_tile(&self, coord: Vec2<i64>) -> Block {
    let val = (self.get_noise_value(coord)
               + self.get_overlay_value(coord)) / 2.0;

    // Temporary map gen. Proof of concept.
    if val > 0.9 {
      Block::new(Tile::Water, Tile::Grass, Tile::Tree)
    } else {
      Block::new(Tile::Water, Tile::None, Tile::None)
    }
  }
}
<commit_msg>Small changes in mapgen<commit_after>//! The module for the automatic map generation

use noise::{Brownian2, Seed, open_simplex2};

// TODO pick:
// use core::*;
// use core::{Map, Tile, TileMap};
use core::*;

pub const CHUNK_SIZE: i64 = 128;

/// A map
///
/// Note: It's chunked into big chunks and small chunks.
///       Small chunks keeps the noise data. Big chunks
///       determines the overlay layer.
pub struct MapGenerator<'a> {
  seed: &'a Seed,
}

/// Types of big chunks
pub enum BChunkType {
  /// Reserved for history, empty per default, but gets opened as the game is
  /// played. Manually designed.
  History,
  /// Automatic map generated chunk
  Auto,
  /// Manually random generated chunk
  Manually,
  /// Empty chunk
  Empty,
}

// TODO: Find out how to prevent double islands (manually generated islands)

// TODO: Use Vec2 in this methods:
impl<'a> MapGenerator<'a> {
  /// Creates a new map
  pub fn new(seed: &'a Seed) -> MapGenerator<'a> {
    MapGenerator {
      seed: seed,
    }
  }

  // TODO: Add some sort of cache

  /// Get the noise value at a given point
  pub fn get_noise_value(&self, coord: Vec2<i64>) -> f64 {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    noise.apply(&self.seed, &[coord.x() as f64, coord.y() as f64])
    // Todo: Add some sort of converter method
  }

  /// Get big chunk coordinates
  pub fn get_bchunk(coord: Vec2<i64>) -> Vec2<i64> {
    // TODO: Chunk size 64?
    Vec2(((coord.x() as f64) / (CHUNK_SIZE as f64)).floor() as i64,
         ((coord.y() as f64) / (CHUNK_SIZE as f64)).floor() as i64)
  }

  /// Get the chunk type of the big chunk at (x, y)
  pub fn get_bchunk_type(&self, coord: Vec2<i64>) -> BChunkType {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    let noise_val =
      noise.apply(&self.seed, &[coord.x() as f64, coord.y() as f64]);
    if noise_val > 0.3 {
      BChunkType::Empty // Too many too few?
    } else if noise_val > 0.1 {
      BChunkType::Auto
    } else if noise_val > 0.05 {
      BChunkType::History
    } else {
      BChunkType::Manually
    }
  }

  /// Get overlay value (used for customizing the noise)
  pub fn get_overlay_value(&self, coord: Vec2<i64>) -> f64 {
    let Vec2(x, y) = coord;

    // Center chunk coordinate
    let Vec2(cx, cy) = MapGenerator::get_bchunk(coord) + Vec2(32, 32);
    let chunk_type = self.get_bchunk_type(Vec2(cx, cy));
    let chunk_int = self.seed.get2([cx, cy]);
    let chunk_value = (chunk_int as f64) / (usize::max_value() as f64);
    match chunk_type {
      BChunkType::Empty => 0.0,
      BChunkType::Auto => {
        // This is why we need vector math, kids.
        // TODO: Use vec math here

        use std::f64;

        // TODO: Make more shapes.
        let elip_dist = (((cx - x) * (cx - x) + (cy - y) * (cy - y)) as f64)
                        .sqrt();
        let angle = chunk_value * f64::consts::PI * 2.0;
        let (cirx, ciry) = (angle.sin() + cx as f64,
                            angle.cos() + cy as f64);
        let sec_dist = ((cirx - x as f64) * (cirx - x as f64)
                       + (ciry - y as f64) * (ciry - y as f64)).sqrt();
        let dist = sec_dist.max(elip_dist);

        let res = 1.0 - dist / 50.0;

        if res > 0.0 {
          res
        } else {
          0.0
        }
      },
      _ => 0.0,
    }
  }
}

impl<'a> TileMap for MapGenerator<'a> {

  // TODO: Rename to get block?
  /// Get the tile at a given point
  fn get_tile(&self, coord: Vec2<i64>) -> Block {
    let val = (self.get_noise_value(coord)
               + self.get_overlay_value(coord)) / 2.0;

    // Temporary map gen. Proof of concept.
    if val > 0.9 {
      Block::new(Tile::Water, Tile::Grass, Tile::Tree)
    } else {
      Block::new(Tile::Water, Tile::None, Tile::None)
    }
  }
}
<|endoftext|>


<commit_before>
use core::prelude::*;

struct FixedBuf
{
	len: usize,
	data: [u8; 256],
}
impl FixedBuf {
	const fn new() -> Self {
		FixedBuf { len: 0, data: [0; 256] }
	}
	fn clear(&mut self) {
		self.len = 0;
	}
	fn push_back(&mut self, data: &[u8]) {
		let len = self.data[self.len..].clone_from_slice( data );
		self.len += len;
		assert!(self.len <= 128);
	}
}
impl ::core::ops::Deref for FixedBuf {
	type Target = [u8];
	fn deref(&self) -> &[u8] {
		&self.data[..self.len]
	}
}

//#[thread_local]
static mut T_LOG_BUFFER: FixedBuf = FixedBuf::new();

// A simple writer that uses the kernel-provided per-thread logging channel
pub struct ThreadLogWriter;
impl ::core::fmt::Write for ThreadLogWriter {
	fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
		// SAFE: Thread-local
		unsafe {
			T_LOG_BUFFER.push_back(s.as_bytes());
		}
		Ok( () )
	}
}
impl ::core::ops::Drop for ThreadLogWriter {
	fn drop(&mut self) {
		// SAFE: Thread-local
		unsafe {
			let b = &*T_LOG_BUFFER;
			match ::core::str::from_utf8(b)
			{
			Ok(v) => ::log_write(v),
			Err(e) => {}
			}
			T_LOG_BUFFER.clear();
		}
	}
}

#[macro_export]
macro_rules! kernel_log {
	($($t:tt)+) => { {
		use std::fmt::Write;
		let _ = write!(&mut $crate::logging::ThreadLogWriter, $($t)*);
	} };
}

<commit_msg>Usermode - Fix kernel log hard-coded buffer size<commit_after>
use core::prelude::*;

const LOG_BUF_SIZE: usize = 256;

struct FixedBuf
{
	len: usize,
	data: [u8; LOG_BUF_SIZE],
}
impl FixedBuf {
	const fn new() -> Self {
		FixedBuf { len: 0, data: [0; LOG_BUF_SIZE] }
	}
	fn clear(&mut self) {
		self.len = 0;
	}
	fn push_back(&mut self, data: &[u8]) {
		let len = self.data[self.len..].clone_from_slice( data );
		self.len += len;
		if len > LOG_BUF_SIZE {
			self.len = 0;
			assert!(self.len <= 128);
		}
	}
}
impl ::core::ops::Deref for FixedBuf {
	type Target = [u8];
	fn deref(&self) -> &[u8] {
		&self.data[..self.len]
	}
}

//#[thread_local]
static mut T_LOG_BUFFER: FixedBuf = FixedBuf::new();

// A simple writer that uses the kernel-provided per-thread logging channel
pub struct ThreadLogWriter;
impl ::core::fmt::Write for ThreadLogWriter {
	fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
		// SAFE: Thread-local
		unsafe {
			T_LOG_BUFFER.push_back(s.as_bytes());
		}
		Ok( () )
	}
}
impl ::core::ops::Drop for ThreadLogWriter {
	fn drop(&mut self) {
		// SAFE: Thread-local
		unsafe {
			let b = &*T_LOG_BUFFER;
			match ::core::str::from_utf8(b)
			{
			Ok(v) => ::log_write(v),
			Err(e) => {}
			}
			T_LOG_BUFFER.clear();
		}
	}
}

#[macro_export]
macro_rules! kernel_log {
	($($t:tt)+) => { {
		use std::fmt::Write;
		let _ = write!(&mut $crate::logging::ThreadLogWriter, $($t)*);
	} };
}

<|endoftext|>


<commit_before>use crate::convert::*;
use core::hash::{Hasher};

///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
const MULTIPLE: u64 = 6364136223846793005;
const INCREMENT: u64 = 1442695040888963407;
const ROT: u32 = 23; //17

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [AHasher] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64
}

impl AHasher {

    /// Creates a new hasher keyed to the provided key.
    #[inline]
    pub(crate) fn new_with_key(key: u64) -> AHasher {
        AHasher { buffer: key }
    }

    /// Creates a new hasher keyed to the provided keys.
    #[inline]
    pub(crate) fn new_with_keys(key1: u64, key2: u64) -> AHasher {
        AHasher { buffer: key1 ^ (key2.rotate_left(ROT)) }
    }

    /// This update function has the goal of updating the buffer with a single multiply
    /// FxHash does this but is venerable to attack. To avoid this input needs to be masked to with an unpredictable value.
    /// However other hashes such as murmurhash have taken that approach but were found venerable to attack.
    /// The attack was based on the idea of reversing the pre-mixing (Which is necessarily reversible otherwise
    /// bits would be lost) then placing a difference in the highest bit before the multiply. Because a multiply
    /// can never affect the bits to the right of it. This version avoids this vulnerability by rotating and
    /// performing a second multiply. This makes it impossible for an attacker to place a single bit
    /// difference between two blocks so as to cancel each other. (While the transform is still reversible if you know the key)
    ///
    /// The update of the buffer to perform the second multiply is moved from the end to the beginning of the method.
    /// This has the effect of causing the next call to update to perform he second multiply. For the final
    /// update this is performed in the finalize method. This might seem wasteful, but its actually an optimization.
    /// If the method get's inlined into the caller where it is being invoked on a single primitive, the first call
    /// to update the buffer will be operating on constants and the compiler will optimize it out, by replacing it with
    #[inline(always)]
    fn update(&mut self, new_data: u64) {
        let result: [u64;2] = ((new_data ^ self.buffer) as u128).wrapping_mul(MULTIPLE as u128).convert();
        self.buffer = result[0] ^ result[1];
    }

    /// This is similar to the above update function (see it's description). But is designed to run in a loop
    /// that will be unrolled and vectorized. So instead of using the buffer, it uses a 'key' that it updates
    /// and returns. The buffer is only xored at the end. This structure is so that when the method is inlined,
    /// the compiler will unroll any loop this gets placed in and the loop can be automatically vectorized
    /// and the rotates, xors, and multiplies can be paralleled.
    ///
    /// The key needs to be incremented between consecutive calls to prevent (a,b) from hashing the same as (b,a).
    /// The adding of the increment is moved to the bottom rather than the top. This allows one less add to be
    /// performed overall, but more importantly, it follows the multiply, which is expensive. So the CPU can
    /// run another operation afterwords if does not depend on the output of the multiply operation.
    #[inline(always)]
    fn ordered_update(&mut self, new_data: u64, key: u64) -> u64 {
//        self.buffer ^= (new_data ^ key).wrapping_mul(MULTIPLE).rotate_left(ROT).wrapping_mul(MULTIPLE);
//        key.wrapping_add(INCREMENT)
        let result: [u64;2] =  ((new_data ^ key) as u128).wrapping_mul(MULTIPLE as u128).convert();
        self.buffer ^= result[0] ^ result[1];
        key.wrapping_add(INCREMENT)
    }
}

#[inline(never)]
#[no_mangle]
fn hash_test(input: &[u8]) -> u64 {
    let mut a = AHasher::new_with_key(67);
    a.write(input);
    a.finish()
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        let data: [u64;2] = i.convert();
        self.update(data[0]);
        self.update(data[1]);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
        self.buffer = self.buffer.wrapping_add(length.wrapping_mul(MULTIPLE));
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() > 8 {
            if data.len() > 16 {
                let tail = data.read_last_u64();
                let mut key: u64 = self.buffer;
                while data.len() > 8 {
                    let (val, rest) = data.read_u64();
                    key = self.ordered_update(val, key);
                    data = rest;
                }
                self.update(tail);
            } else {
                self.update(data.read_u64().0);
                self.update(data.read_last_u64());
            }
        } else {
            if data.len() >= 2 {
                if data.len() >= 4 {
                    let block: [u32; 2] = [data.read_u32().0, data.read_last_u32()];
                    self.update(block.convert());
                } else {
                    let block: [u16; 2] = [data.read_u16().0, data.read_last_u16()];
                    let val: u32 = block.convert();
                    self.update(val as u64);
                }
            } else {
                let value;
                if data.len() > 0 {
                    value = data[0]; //len 1
                } else {
                    value = 0;
                }
                self.update(value as u64);
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        //self.buffer.wrapping_mul(MULTIPLE).rotate_left(9).wrapping_mul(MULTIPLE)
        self.buffer
    }
}

#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0,0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0,0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<commit_msg>Switch fallback to use wrapping add instead of xor to avoid a implicet shift<commit_after>use crate::convert::*;
use core::hash::{Hasher};

///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
const MULTIPLE: u64 = 6364136223846793005;
const INCREMENT: u64 = 1442695040888963407;
const ROT: u32 = 23; //17

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [AHasher] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64
}

impl AHasher {

    /// Creates a new hasher keyed to the provided key.
    #[inline]
    pub(crate) fn new_with_key(key: u64) -> AHasher {
        AHasher { buffer: key }
    }

    /// Creates a new hasher keyed to the provided keys.
    #[inline]
    pub(crate) fn new_with_keys(key1: u64, key2: u64) -> AHasher {
        AHasher { buffer: key1 ^ (key2.rotate_left(ROT)) }
    }

    /// This update function has the goal of updating the buffer with a single multiply
    /// FxHash does this but is venerable to attack. To avoid this input needs to be masked to with an unpredictable value.
    /// However other hashes such as murmurhash have taken that approach but were found venerable to attack.
    /// The attack was based on the idea of reversing the pre-mixing (Which is necessarily reversible otherwise
    /// bits would be lost) then placing a difference in the highest bit before the multiply. Because a multiply
    /// can never affect the bits to the right of it. This version avoids this vulnerability by rotating and
    /// performing a second multiply. This makes it impossible for an attacker to place a single bit
    /// difference between two blocks so as to cancel each other. (While the transform is still reversible if you know the key)
    #[inline(always)]
    fn update(&mut self, new_data: u64) {
        let result: [u64;2] = ((new_data ^ self.buffer) as u128).wrapping_mul(MULTIPLE as u128).convert();
        self.buffer = result[0].wrapping_add(result[1]);
    }

    /// This is similar to the above update function (see it's description). But is designed to run in a loop
    /// that will be unrolled and vectorized. So instead of using the buffer, it uses a 'key' that it updates
    /// and returns. The buffer is only xored at the end. This structure is so that when the method is inlined,
    /// the compiler will unroll any loop this gets placed in and the loop can be automatically vectorized
    /// and the rotates, xors, and multiplies can be paralleled.
    ///
    /// The key needs to be incremented between consecutive calls to prevent (a,b) from hashing the same as (b,a).
    /// The adding of the increment is moved to the bottom rather than the top. This allows one less add to be
    /// performed overall, but more importantly, it follows the multiply, which is expensive. So the CPU can
    /// run another operation afterwords if does not depend on the output of the multiply operation.
    #[inline(always)]
    fn ordered_update(&mut self, new_data: u64, key: u64) -> u64 {
//        self.buffer ^= (new_data ^ key).wrapping_mul(MULTIPLE).rotate_left(ROT).wrapping_mul(MULTIPLE);
//        key.wrapping_add(INCREMENT)
        let result: [u64;2] =  ((new_data ^ key) as u128).wrapping_mul(MULTIPLE as u128).convert();
        self.buffer ^= result[0] ^ result[1];
        key.wrapping_add(INCREMENT)
    }
}

#[inline(never)]
#[no_mangle]
fn hash_test(input: &[u8]) -> u64 {
    let mut a = AHasher::new_with_key(67);
    a.write(input);
    a.finish()
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        let data: [u64;2] = i.convert();
        self.update(data[0]);
        self.update(data[1]);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
        self.buffer = self.buffer.wrapping_add(length.wrapping_mul(MULTIPLE));
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() > 8 {
            if data.len() > 16 {
                let tail = data.read_last_u64();
                let mut key: u64 = self.buffer;
                while data.len() > 8 {
                    let (val, rest) = data.read_u64();
                    key = self.ordered_update(val, key);
                    data = rest;
                }
                self.update(tail);
            } else {
                self.update(data.read_u64().0);
                self.update(data.read_last_u64());
            }
        } else {
            if data.len() >= 2 {
                if data.len() >= 4 {
                    let block: [u32; 2] = [data.read_u32().0, data.read_last_u32()];
                    self.update(block.convert());
                } else {
                    let block: [u16; 2] = [data.read_u16().0, data.read_last_u16()];
                    let val: u32 = block.convert();
                    self.update(val as u64);
                }
            } else {
                let value;
                if data.len() > 0 {
                    value = data[0]; //len 1
                } else {
                    value = 0;
                }
                self.update(value as u64);
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        //self.buffer.wrapping_mul(MULTIPLE).rotate_left(9).wrapping_mul(MULTIPLE)
        self.buffer
    }
}

#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0,0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0,0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use module::todo::TodoModule;

mod todo;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

pub mod file {

    use regex::Regex;

    pub struct ParserError {
        summary: String,
        parsertext: String,
        index: i32,
        explanation: Option<String>,
    }

    impl ParserError {
        fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: Some(String::from(expl)),
            }
        }

        fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: None
            }
        }
    }

    pub enum FileHeaderSpec {
        Null,
        Bool,
        Integer,
        UInteger,
        Float,
        Text,
        Key { name: String, value_type: Box<FileHeaderSpec> },
        Array { allowed_types: Box<Vec<FileHeaderSpec>> },
    }

    pub enum FileHeaderData {
        Null,
        Bool(bool),
        Integer(i64),
        UInteger(u64),
        Float(f64),
        Text(String),
        Key { name: String, value: Box<FileHeaderData> },
        Array { values: Box<Vec<FileHeaderData>> },
    }

    pub trait FileHeaderParser : Sized {
        fn new(spec: &FileHeaderSpec) -> Self;
        fn read(&self, string: String) -> Result<FileHeaderData, ParserError>;
        fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
    }

    pub trait FileData : Sized {
        fn get_fulltext(&self) -> String;
        fn get_abbrev(&self) -> String;
    }

    pub trait FileDataParser : Sized {
        fn new() -> FileDataParser;
        fn read(&self, string: String) -> FileData;
        fn write(&self, data: &FileData) -> Result<String, ParserError>;
    }

    pub type HeaderDataTpl = (Option<String>, Option<String>);

    pub fn divide_text(text: String) -> Result<HeaderDataTpl, ParserError> {
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));
        Ok((header, content))
    }

}
<commit_msg>FileDataParser::read() should return Result<><commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use module::todo::TodoModule;

mod todo;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

pub mod file {

    use regex::Regex;

    pub struct ParserError {
        summary: String,
        parsertext: String,
        index: i32,
        explanation: Option<String>,
    }

    impl ParserError {
        fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: Some(String::from(expl)),
            }
        }

        fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: None
            }
        }
    }

    pub enum FileHeaderSpec {
        Null,
        Bool,
        Integer,
        UInteger,
        Float,
        Text,
        Key { name: String, value_type: Box<FileHeaderSpec> },
        Array { allowed_types: Box<Vec<FileHeaderSpec>> },
    }

    pub enum FileHeaderData {
        Null,
        Bool(bool),
        Integer(i64),
        UInteger(u64),
        Float(f64),
        Text(String),
        Key { name: String, value: Box<FileHeaderData> },
        Array { values: Box<Vec<FileHeaderData>> },
    }

    pub trait FileHeaderParser : Sized {
        fn new(spec: &FileHeaderSpec) -> Self;
        fn read(&self, string: String) -> Result<FileHeaderData, ParserError>;
        fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
    }

    pub trait FileData : Sized {
        fn get_fulltext(&self) -> String;
        fn get_abbrev(&self) -> String;
    }

    pub trait FileDataParser : Sized {
        fn new() -> FileDataParser;
        fn read(&self, string: String) -> Result<FileData, ParserError>;
        fn write(&self, data: &FileData) -> Result<String, ParserError>;
    }

    pub type HeaderDataTpl = (Option<String>, Option<String>);

    pub fn divide_text(text: String) -> Result<HeaderDataTpl, ParserError> {
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));
        Ok((header, content))
    }

}
<|endoftext|>


<commit_before>extern crate nalgebra as na;

use glium;
use files;

struct ObjectData
{
    pub verts: Vec<[f32; 3]>,
    pub normals: Vec<[f32; 3]>,
    pub uvs: Vec<[f32; 3]>,
    pub faces: Vec<u8>,
}

fn parse_coord_list(coord_strs: Vec<&str>)
{
    const COORD_AMOUNT :usize = 3;
    let curr_index = 0;
    let coords: [f32; COORD_AMOUNT] = [0.0; COORD_AMOUNT];
    //Iterate over all the coordinates in the vertex and add them to the object data
    for coord_str in coord_strs
    {
        if(curr_index < COORD_AMOUNT)
        {
            coords[curr_index] = coord_str.parse::<f32>().unwrap()
        }
        curr_index += 1;
    }
}
fn handle_vertex(coord_strs: Vec<&str>, &mut obj_data: ObjectData)
{
}

pub fn load_obj_file(path :&String)
{
    let mut object_data = ObjectData{verts: vec!(), normals: vec!(), uvs: vec!(), faces: vec!()};

    let file_content: String = files::load_whole_file(path);

    //Split the file  into individual lines
    let file_lines: Vec<&str>= file_content.split("\n").collect();

    for line in file_lines
    {

    }
}
<commit_msg>Work on object loader<commit_after>use files;

pub struct ObjectData
{
    pub verts: Vec<[f32; 3]>,
    pub normals: Vec<[f32; 3]>,
    pub uvs: Vec<[f32; 3]>,
    pub faces: Vec<u8>,
}

fn parse_coord_list(coord_strs: &Vec<&str>) -> [f32; 3]
{
    const COORD_AMOUNT :usize = 3;
    let mut curr_index = 0;
    let mut coords: [f32; COORD_AMOUNT] = [0.0; COORD_AMOUNT];
    //Iterate over all the coordinates in the vertex and add them to the object data
    for coord_str in coord_strs
    {
        if curr_index < COORD_AMOUNT
        {
            match coord_str.parse::<f32>()
            {
                Ok(val) => coords[curr_index] = val,
                Err(e) => panic!("failed to load .obj file, malformed coordinates: {} \n{}", coord_str, e)
            }
        }
        curr_index += 1;
    }

    return coords;
}

pub fn load_obj_file(path :&String) -> ObjectData
{
    let mut obj_data = ObjectData{verts: vec!(), normals: vec!(), uvs: vec!(), faces: vec!()};

    let file_content: String = files::load_whole_file(path);

    //Split the file  into individual lines
    let file_lines: Vec<&str> = file_content.split("\n").collect();

    for line in file_lines
    {
        //split the line at spaces
        let segments: Vec<&str> = line.split(" ").collect();

        //Skipping empty lines or comments
        if segments.len() == 0
        {
            continue;
        }

        let first_char = segments[0].chars().nth(0);
        match first_char
        {
            Some(t) => if t == '#' {continue},
            None => continue
        }

        //let rest_of_line = segments[1..];
        let mut rest_of_line: Vec<&str> = Vec::new();
        rest_of_line.clone_from_slice(&(segments[1..]));

        match segments[0]
        {
            "v" => obj_data.verts.push(parse_coord_list(&rest_of_line)),
            "vn" => obj_data.verts.push(parse_coord_list(&rest_of_line)),
            _ => println!("Unknown obj file part: {} when loading {}", segments[0], path)
        }
    }

    return obj_data;
}
<|endoftext|>


<commit_before>use piston_window::{BuildFromWindowSettings, WindowSettings};
use self::super::super::Error;

/// Create a window based on the size of the target desktop.
///
/// Much like the raw equivalnt of creating the window, the return type is be dependent on the user-side's explicit
/// expression type.
///
/// Use `glutin::get_{primary,available}_monitor[s]()` to get the size of the respective desktops.
///
/// # Examples
///
/// Create a window for an HD monitor:
///
/// ```
/// # extern crate piston_window;
/// # extern crate poke_a_mango;
/// # use poke_a_mango::ops::create_window;
/// # use piston_window::NoWindow as PistonWindow;
/// # fn main() {
/// let window: PistonWindow = create_window((1280, 720)).unwrap();
/// # }
/// ```
pub fn create_window<W: BuildFromWindowSettings>(desktop_size: (u32, u32)) -> Result<W, Error> {
    let window_w = desktop_size.1 / 3;
    WindowSettings::new("poke-a-mango", [window_w, window_w * 2])
        .vsync(true)
        .build()
        .map_err(|e| {
            Error::Ui {
                desc: "create window",
                error: e,
            }
        })
}
<commit_msg>Enable MSAAx8<commit_after>use piston_window::{BuildFromWindowSettings, WindowSettings};
use self::super::super::Error;

/// Create a window based on the size of the target desktop.
///
/// Much like the raw equivalnt of creating the window, the return type is be dependent on the user-side's explicit
/// expression type.
///
/// Use `glutin::get_{primary,available}_monitor[s]()` to get the size of the respective desktops.
///
/// # Examples
///
/// Create a window for an HD monitor:
///
/// ```
/// # extern crate piston_window;
/// # extern crate poke_a_mango;
/// # use poke_a_mango::ops::create_window;
/// # use piston_window::NoWindow as PistonWindow;
/// # fn main() {
/// let window: PistonWindow = create_window((1280, 720)).unwrap();
/// # }
/// ```
pub fn create_window<W: BuildFromWindowSettings>(desktop_size: (u32, u32)) -> Result<W, Error> {
    let window_w = desktop_size.1 / 3;
    WindowSettings::new("poke-a-mango", [window_w, window_w * 2])
        .vsync(true)
        .samples(8)
        .build()
        .map_err(|e| {
            Error::Ui {
                desc: "create window",
                error: e,
            }
        })
}
<|endoftext|>


<commit_before>use graphics::*;

// Local crate.
use Vector2d = vector2d::Vector2d;

static EPSILON: f64 = 0.0000000001;

pub fn area(contour: &[Vector2d]) -> f64 {
    let n = contour.len();
    let mut A = 0.0_f64;

    for i in range(0, n) {
        let q = i;
        let p = (i + n - 1) % n;
        A += contour.get(p).unwrap().get_x() * contour.get(q).unwrap().get_y()
            - contour.get(q).unwrap().get_x() * contour.get(p).unwrap().get_y();
    }

    A * 0.5_f64
}

/// InsideTriangle decides if a point P is Inside of the triangle
/// defined by A, B, C.
pub fn inside_triangle(
    Ax: f64, Ay: f64,
    Bx: f64, By: f64,
    Cx: f64, Cy: f64,
    Px: f64, Py: f64
) -> bool {

    let ax = Cx - Bx;
    let ay = Cy - By;
    let bx = Ax - Cx;
    let by = Ay - Cy;
    let cx = Bx - Ax;
    let cy = By - Ay;
    let apx = Px - Ax;
    let apy = Py - Ay;
    let bpx = Px - Bx;
    let bpy = Py - By;
    let cpx = Px - Cx;
    let cpy = Py - Cy;

    let aCROSSbp = ax*bpy - ay*bpx;
    let cCROSSap = cx*apy - cy*apx;
    let bCROSScp = bx*cpy - by*cpx;

    (
        (aCROSSbp >= 0.0_f64)
        && (bCROSScp >= 0.0_f64)
        && (cCROSSap >= 0.0_f64)
    )
}

pub fn snip(
    contour: &[Vector2d],
    triangle: [uint, ..3],
    n: uint,
    V: &mut Vec<uint>
) -> bool {
    let u = triangle[0];
    let v = triangle[1];
    let w = triangle[2];

    let Ax = contour.get(*V.get(u)).unwrap().get_x();
    let Ay = contour.get(*V.get(u)).unwrap().get_y();

    let Bx = contour.get(*V.get(v)).unwrap().get_x();
    let By = contour.get(*V.get(v)).unwrap().get_y();

    let Cx = contour.get(*V.get(w)).unwrap().get_x();
    let Cy = contour.get(*V.get(w)).unwrap().get_y();

    if EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) {
        return false;
    }

    for p in range(0, n) {
        if (p == u) || (p == v) || (p == w) { continue; }

        let Px = contour.get(*V.get(p)).unwrap().get_x();
        let Py = contour.get(*V.get(p)).unwrap().get_y();

        if inside_triangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py) { return false; }
    }

    return true;
}

pub fn process(
    contour: &[Vector2d]
) -> Option<Vec<Vector2d>> {
    /* allocate and initialize list of Vertices in polygon */

    let n = contour.len();
    if n < 3 { return None; }

    let mut result: Vec<Vector2d> = Vec::new();
    let mut vertex_indices: Vec<uint> = Vec::with_capacity(n);

    /* we want a counter-clockwise polygon in V */

    // Computes the area which has opposite signs
    // whether the polygon is clock-wise or counter-clockwise.
    if 0.0_f64 < area(contour) {
        for v in range(0, n) { vertex_indices.push(v); }
    } else {
        for v in range(0, n) { vertex_indices.push((n-1)-v); }
    }

    let mut number_of_vertices = n;

    /*  remove nv-2 Vertices, creating 1 triangle every time */
    let mut count = 2 * number_of_vertices;   /* error detection */

    let mut m = 0;
    let mut v = number_of_vertices - 1;
    while number_of_vertices > 2 {
        /* if we loop, it is probably a non-simple polygon */
        if count <= 0 {
            //** Triangulate: ERROR - probable bad polygon!
            return None;
        }

        count -= 1;

        /* three consecutive vertices in current polygon, <u,v,w> */
        let triangle = [
            v,
            vecmath::modular_offset_index(number_of_vertices, v, 1),
            vecmath::modular_offset_index(number_of_vertices, v, 2)
        ];
        v = triangle[1];

        if snip(contour, triangle, number_of_vertices, &mut vertex_indices) {
            for &i in triangle.iter() {
                result.push(*contour.get(*vertex_indices.get(i)).unwrap());
            }

            m += 1;

            /* remove v from remaining polygon */
            for i in range(0, number_of_vertices - 3) {
                let s = v + i;
                let t = v + i + 1;

                *vertex_indices.get_mut(s) = *vertex_indices.get(t);
            }

            // "Removed" a vertex.
            number_of_vertices -= 1;

            /* resest error detection counter */
            count = 2 * number_of_vertices;
        }
    }

    Some(result)
}

<commit_msg>Removed unused variable<commit_after>use graphics::*;

// Local crate.
use Vector2d = vector2d::Vector2d;

static EPSILON: f64 = 0.0000000001;

pub fn area(contour: &[Vector2d]) -> f64 {
    let n = contour.len();
    let mut A = 0.0_f64;

    for i in range(0, n) {
        let q = i;
        let p = (i + n - 1) % n;
        A += contour.get(p).unwrap().get_x() * contour.get(q).unwrap().get_y()
            - contour.get(q).unwrap().get_x() * contour.get(p).unwrap().get_y();
    }

    A * 0.5_f64
}

/// InsideTriangle decides if a point P is Inside of the triangle
/// defined by A, B, C.
pub fn inside_triangle(
    Ax: f64, Ay: f64,
    Bx: f64, By: f64,
    Cx: f64, Cy: f64,
    Px: f64, Py: f64
) -> bool {

    let ax = Cx - Bx;
    let ay = Cy - By;
    let bx = Ax - Cx;
    let by = Ay - Cy;
    let cx = Bx - Ax;
    let cy = By - Ay;
    let apx = Px - Ax;
    let apy = Py - Ay;
    let bpx = Px - Bx;
    let bpy = Py - By;
    let cpx = Px - Cx;
    let cpy = Py - Cy;

    let aCROSSbp = ax*bpy - ay*bpx;
    let cCROSSap = cx*apy - cy*apx;
    let bCROSScp = bx*cpy - by*cpx;

    (
        (aCROSSbp >= 0.0_f64)
        && (bCROSScp >= 0.0_f64)
        && (cCROSSap >= 0.0_f64)
    )
}

pub fn snip(
    contour: &[Vector2d],
    triangle: [uint, ..3],
    n: uint,
    V: &mut Vec<uint>
) -> bool {
    let u = triangle[0];
    let v = triangle[1];
    let w = triangle[2];

    let Ax = contour.get(*V.get(u)).unwrap().get_x();
    let Ay = contour.get(*V.get(u)).unwrap().get_y();

    let Bx = contour.get(*V.get(v)).unwrap().get_x();
    let By = contour.get(*V.get(v)).unwrap().get_y();

    let Cx = contour.get(*V.get(w)).unwrap().get_x();
    let Cy = contour.get(*V.get(w)).unwrap().get_y();

    if EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) {
        return false;
    }

    for p in range(0, n) {
        if (p == u) || (p == v) || (p == w) { continue; }

        let Px = contour.get(*V.get(p)).unwrap().get_x();
        let Py = contour.get(*V.get(p)).unwrap().get_y();

        if inside_triangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py) { return false; }
    }

    return true;
}

pub fn process(
    contour: &[Vector2d]
) -> Option<Vec<Vector2d>> {
    /* allocate and initialize list of Vertices in polygon */

    let n = contour.len();
    if n < 3 { return None; }

    let mut result: Vec<Vector2d> = Vec::new();
    let mut vertex_indices: Vec<uint> = Vec::with_capacity(n);

    /* we want a counter-clockwise polygon in V */

    // Computes the area which has opposite signs
    // whether the polygon is clock-wise or counter-clockwise.
    if 0.0_f64 < area(contour) {
        for v in range(0, n) { vertex_indices.push(v); }
    } else {
        for v in range(0, n) { vertex_indices.push((n-1)-v); }
    }

    let mut number_of_vertices = n;

    /*  remove nv-2 Vertices, creating 1 triangle every time */
    let mut count = 2 * number_of_vertices;   /* error detection */

    let mut v = number_of_vertices - 1;
    while number_of_vertices > 2 {
        /* if we loop, it is probably a non-simple polygon */
        if count <= 0 {
            //** Triangulate: ERROR - probable bad polygon!
            return None;
        }

        count -= 1;

        /* three consecutive vertices in current polygon, <u,v,w> */
        let triangle = [
            v,
            vecmath::modular_offset_index(number_of_vertices, v, 1),
            vecmath::modular_offset_index(number_of_vertices, v, 2)
        ];
        v = triangle[1];

        if snip(contour, triangle, number_of_vertices, &mut vertex_indices) {
            for &i in triangle.iter() {
                result.push(*contour.get(*vertex_indices.get(i)).unwrap());
            }

            /* remove v from remaining polygon */
            for i in range(0, number_of_vertices - 3) {
                let s = v + i;
                let t = v + i + 1;

                *vertex_indices.get_mut(s) = *vertex_indices.get(t);
            }

            // "Removed" a vertex.
            number_of_vertices -= 1;

            /* resest error detection counter */
            count = 2 * number_of_vertices;
        }
    }

    Some(result)
}

<|endoftext|>


<commit_before>//! The parser module is responsible for parsing FITS files.

use std::str;
use std::str::FromStr;
use super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, BlankRecord};

named!(fits<&[u8], Fits>,
       do_parse!(
           ph: primary_header >>
               many0!(take!(2880)) >>
               (Fits::new(ph))
       ));

named!(primary_header<&[u8], PrimaryHeader>,
       do_parse!(
           records: many0!(keyword_record) >>
               end_record >>
               many0!(blank_record) >>
               (PrimaryHeader::new(records))
       ));

named!(keyword_record<&[u8], KeywordRecord>,
       do_parse!(
           key: keyword  >>
               tag!("=") >>
               take!(71) >>
               (KeywordRecord::new(key))
       ));

named!(keyword<&[u8], Keyword>,
       map_res!(
           map_res!(
               take!(8),
               str::from_utf8),
           Keyword::from_str
       ));

named!(end_record<&[u8], Keyword>,
       map!(
           flat_map!(
               take!(80),
               pair!(tag!("END"), many0!(tag!(" ")))
           ),
           |_| { Keyword::END }
       ));

named!(blank_record<&[u8], BlankRecord>,
       map!(
           count!(tag!(" "), 80),
           |_| { BlankRecord }
       ));

#[cfg(test)]
mod tests {
    use nom::{IResult};
    use super::super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, BlankRecord};
    use super::{fits, primary_header, keyword_record, keyword, end_record, blank_record};

    #[test]
    fn it_should_parse_a_fits_file(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = fits(data);

        match result {
            IResult::Done(_, f) => {
                assert_eq!(f, Fits::new(long_cadence_header()));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn primary_header_should_parse_a_primary_header(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = primary_header(&data[0..(2*2880)]);

        match result {
            IResult::Done(_, h) => assert_eq!(h, long_cadence_header()),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    fn long_cadence_header() -> PrimaryHeader {
        PrimaryHeader::new(vec!(
            KeywordRecord::new(Keyword::SIMPLE),
            KeywordRecord::new(Keyword::BITPIX),
            KeywordRecord::new(Keyword::NAXIS),
            KeywordRecord::new(Keyword::EXTEND),
            KeywordRecord::new(Keyword::NEXTEND),
            KeywordRecord::new(Keyword::EXTNAME),
            KeywordRecord::new(Keyword::EXTVER),
            KeywordRecord::new(Keyword::ORIGIN),
            KeywordRecord::new(Keyword::DATE),
            KeywordRecord::new(Keyword::CREATOR),
            KeywordRecord::new(Keyword::PROCVER),
            KeywordRecord::new(Keyword::FILEVER),
            KeywordRecord::new(Keyword::TIMVERSN),
            KeywordRecord::new(Keyword::TELESCOP),
            KeywordRecord::new(Keyword::INSTRUME),
            KeywordRecord::new(Keyword::OBJECT),
            KeywordRecord::new(Keyword::KEPLERID),
            KeywordRecord::new(Keyword::CHANNEL),
            KeywordRecord::new(Keyword::MODULE),
            KeywordRecord::new(Keyword::OUTPUT),
            KeywordRecord::new(Keyword::CAMPAIGN),
            KeywordRecord::new(Keyword::DATA_REL),
            KeywordRecord::new(Keyword::OBSMODE),
            KeywordRecord::new(Keyword::MISSION),
            KeywordRecord::new(Keyword::TTABLEID),
            KeywordRecord::new(Keyword::RADESYS),
            KeywordRecord::new(Keyword::RA_OBJ),
            KeywordRecord::new(Keyword::DEC_OBJ),
            KeywordRecord::new(Keyword::EQUINOX),
            KeywordRecord::new(Keyword::PMRA),
            KeywordRecord::new(Keyword::PMDEC),
            KeywordRecord::new(Keyword::PMTOTAL),
            KeywordRecord::new(Keyword::PARALLAX),
            KeywordRecord::new(Keyword::GLON),
            KeywordRecord::new(Keyword::GLAT),
            KeywordRecord::new(Keyword::GMAG),
            KeywordRecord::new(Keyword::RMAG),
            KeywordRecord::new(Keyword::IMAG),
            KeywordRecord::new(Keyword::ZMAG),
            KeywordRecord::new(Keyword::JMAG),
            KeywordRecord::new(Keyword::HMAG),
            KeywordRecord::new(Keyword::KMAG),
            KeywordRecord::new(Keyword::KEPMAG),
            KeywordRecord::new(Keyword::GRCOLOR),
            KeywordRecord::new(Keyword::JKCOLOR),
            KeywordRecord::new(Keyword::GKCOLOR),
            KeywordRecord::new(Keyword::TEFF),
            KeywordRecord::new(Keyword::LOGG),
            KeywordRecord::new(Keyword::FEH),
            KeywordRecord::new(Keyword::EBMINUSV),
            KeywordRecord::new(Keyword::AV),
            KeywordRecord::new(Keyword::RADIUS),
            KeywordRecord::new(Keyword::TMINDEX),
            KeywordRecord::new(Keyword::CHECKSUM),
            KeywordRecord::new(Keyword::DATASUM),
        ))
    }

    #[test]
    fn keyword_record_should_parse_a_keyword_record(){
        let data = "OBJECT  = 'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = keyword_record(data);

        match result {
            IResult::Done(_,k) => assert_eq!(k, KeywordRecord::new(Keyword::OBJECT)),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_should_parse_a_keyword(){
        let data = "OBJECT  "
            .as_bytes();

        let result = keyword(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn end_record_should_parse_an_END_record(){
        let data = "END                                                                             "
            .as_bytes();

        let result = end_record(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::END),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn blank_record_should_parse_a_BLANK_record(){
        let data = "                                                                                "
            .as_bytes();

        let result = blank_record(data);

        match result {
            IResult::Done(_, record) => assert_eq!(record, BlankRecord),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }
}
<commit_msg>Correctly parse the value separator as `= `<commit_after>//! The parser module is responsible for parsing FITS files.

use std::str;
use std::str::FromStr;
use super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, BlankRecord};

named!(fits<&[u8], Fits>,
       do_parse!(
           ph: primary_header >>
               many0!(take!(2880)) >>
               (Fits::new(ph))
       ));

named!(primary_header<&[u8], PrimaryHeader>,
       do_parse!(
           records: many0!(keyword_record) >>
               end_record >>
               many0!(blank_record) >>
               (PrimaryHeader::new(records))
       ));

named!(keyword_record<&[u8], KeywordRecord>,
       do_parse!(
           key: keyword  >>
               tag!("= ") >>
               take!(70) >>
               (KeywordRecord::new(key))
       ));

named!(keyword<&[u8], Keyword>,
       map_res!(
           map_res!(
               take!(8),
               str::from_utf8),
           Keyword::from_str
       ));

named!(end_record<&[u8], Keyword>,
       map!(
           flat_map!(
               take!(80),
               pair!(tag!("END"), many0!(tag!(" ")))
           ),
           |_| { Keyword::END }
       ));

named!(blank_record<&[u8], BlankRecord>,
       map!(
           count!(tag!(" "), 80),
           |_| { BlankRecord }
       ));

#[cfg(test)]
mod tests {
    use nom::{IResult};
    use super::super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, BlankRecord};
    use super::{fits, primary_header, keyword_record, keyword, end_record, blank_record};

    #[test]
    fn it_should_parse_a_fits_file(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = fits(data);

        match result {
            IResult::Done(_, f) => {
                assert_eq!(f, Fits::new(long_cadence_header()));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn primary_header_should_parse_a_primary_header(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = primary_header(&data[0..(2*2880)]);

        match result {
            IResult::Done(_, h) => assert_eq!(h, long_cadence_header()),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    fn long_cadence_header() -> PrimaryHeader {
        PrimaryHeader::new(vec!(
            KeywordRecord::new(Keyword::SIMPLE),
            KeywordRecord::new(Keyword::BITPIX),
            KeywordRecord::new(Keyword::NAXIS),
            KeywordRecord::new(Keyword::EXTEND),
            KeywordRecord::new(Keyword::NEXTEND),
            KeywordRecord::new(Keyword::EXTNAME),
            KeywordRecord::new(Keyword::EXTVER),
            KeywordRecord::new(Keyword::ORIGIN),
            KeywordRecord::new(Keyword::DATE),
            KeywordRecord::new(Keyword::CREATOR),
            KeywordRecord::new(Keyword::PROCVER),
            KeywordRecord::new(Keyword::FILEVER),
            KeywordRecord::new(Keyword::TIMVERSN),
            KeywordRecord::new(Keyword::TELESCOP),
            KeywordRecord::new(Keyword::INSTRUME),
            KeywordRecord::new(Keyword::OBJECT),
            KeywordRecord::new(Keyword::KEPLERID),
            KeywordRecord::new(Keyword::CHANNEL),
            KeywordRecord::new(Keyword::MODULE),
            KeywordRecord::new(Keyword::OUTPUT),
            KeywordRecord::new(Keyword::CAMPAIGN),
            KeywordRecord::new(Keyword::DATA_REL),
            KeywordRecord::new(Keyword::OBSMODE),
            KeywordRecord::new(Keyword::MISSION),
            KeywordRecord::new(Keyword::TTABLEID),
            KeywordRecord::new(Keyword::RADESYS),
            KeywordRecord::new(Keyword::RA_OBJ),
            KeywordRecord::new(Keyword::DEC_OBJ),
            KeywordRecord::new(Keyword::EQUINOX),
            KeywordRecord::new(Keyword::PMRA),
            KeywordRecord::new(Keyword::PMDEC),
            KeywordRecord::new(Keyword::PMTOTAL),
            KeywordRecord::new(Keyword::PARALLAX),
            KeywordRecord::new(Keyword::GLON),
            KeywordRecord::new(Keyword::GLAT),
            KeywordRecord::new(Keyword::GMAG),
            KeywordRecord::new(Keyword::RMAG),
            KeywordRecord::new(Keyword::IMAG),
            KeywordRecord::new(Keyword::ZMAG),
            KeywordRecord::new(Keyword::JMAG),
            KeywordRecord::new(Keyword::HMAG),
            KeywordRecord::new(Keyword::KMAG),
            KeywordRecord::new(Keyword::KEPMAG),
            KeywordRecord::new(Keyword::GRCOLOR),
            KeywordRecord::new(Keyword::JKCOLOR),
            KeywordRecord::new(Keyword::GKCOLOR),
            KeywordRecord::new(Keyword::TEFF),
            KeywordRecord::new(Keyword::LOGG),
            KeywordRecord::new(Keyword::FEH),
            KeywordRecord::new(Keyword::EBMINUSV),
            KeywordRecord::new(Keyword::AV),
            KeywordRecord::new(Keyword::RADIUS),
            KeywordRecord::new(Keyword::TMINDEX),
            KeywordRecord::new(Keyword::CHECKSUM),
            KeywordRecord::new(Keyword::DATASUM),
        ))
    }

    #[test]
    fn keyword_record_should_parse_a_keyword_record(){
        let data = "OBJECT  = 'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = keyword_record(data);

        match result {
            IResult::Done(_,k) => assert_eq!(k, KeywordRecord::new(Keyword::OBJECT)),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_should_parse_a_keyword(){
        let data = "OBJECT  "
            .as_bytes();

        let result = keyword(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn end_record_should_parse_an_END_record(){
        let data = "END                                                                             "
            .as_bytes();

        let result = end_record(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::END),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn blank_record_should_parse_a_BLANK_record(){
        let data = "                                                                                "
            .as_bytes();

        let result = blank_record(data);

        match result {
            IResult::Done(_, record) => assert_eq!(record, BlankRecord),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }
}
<|endoftext|>