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

use libc::SIGQUIT;

pub struct AgentController<'a> {
    heuristic: Box<super::Heuristic + 'a>,
    actions: Vec<Box<super::Action>>
}

impl<'a> AgentController<'a> {
    pub fn new(ti: ::env::JvmTiEnv, options: *mut ::std::os::raw::c_char) -> Result<Self, ::jvmti::jint> {
        let parms = super::parms::AgentParameters::parseParameters(options);

        let mut ac = Self {
            heuristic: Box::new(super::threshold::Threshold::new(parms.count_threshold, parms.time_threshold)),
            actions: Vec::new(),
        };

        if parms.print_heap_histogram {
            ac.actions.push(Box::new(super::heaphistogram::HeapHistogram::new(ti, parms.heap_histogram_max_entries).map_err(|err| err.rc())?));
        }

        if let Some(path) = parms.heap_dump_path {
            ac.actions.push(Box::new(super::heapdump::HeapDump::new(path)));
        }

        if parms.print_memory_usage {
            ac.actions.push(Box::new(super::poolstats::PoolStats::new()));
        }

        let mut threadDump = super::kill::Kill::new();
        threadDump.setSignal(SIGQUIT);
        ac.actions.push(Box::new(threadDump));

        ac.actions.push(Box::new(super::kill::Kill::new()));

        Ok(ac)
    }

    #[cfg(test)]
    fn test_new(heuristic: Box<super::Heuristic + 'a>, actions: Vec<Box<super::Action>>) -> Self {
        Self {
            heuristic: heuristic,
            actions: actions,
        }
    }
}

impl<'a> super::MutAction for AgentController<'a> {
    fn on_oom(&mut self, jni_env: ::env::JniEnv, resource_exhaustion_flags: ::jvmti::jint) {
        const heap_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP as ::jvmti::jint;
        const threads_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_THREADS as ::jvmti::jint;
        const oom_error: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR as ::jvmti::jint;

        if resource_exhaustion_flags & heap_exhausted == heap_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to allocate memory from the heap.");
        }
        if resource_exhaustion_flags & threads_exhausted == threads_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to create a thread.");
        }

        if self.heuristic.on_oom() {
            for action in &self.actions {
                if let Err(error) = action.on_oom(jni_env, resource_exhaustion_flags) {
                    eprintln!("ERROR: {} action failed: {}", action, error);
                }
            }
        } else if resource_exhaustion_flags & oom_error == oom_error {
            eprintln!("\nThe JVM is about to throw a java.lang.OutOfMemoryError.");
        }
    }
}

unsafe impl<'a> Send for AgentController<'a> {}

unsafe impl<'a> Sync for AgentController<'a> {}

#[cfg(test)]
mod tests {
    use agentcontroller::MutAction;

    pub struct TestHeuristic {
        call_count: u32
    }

    impl TestHeuristic {
        pub fn new() -> Self {
            Self {
                call_count: 0,
            }
        }
    }

    impl super::super::Heuristic for TestHeuristic {
        fn on_oom(&mut self) -> bool {
            self.call_count += 1;
            self.call_count >= 2
        }
    }

    pub struct TestAction {}

    impl TestAction {
        pub fn new() -> Self {
            Self {}
        }
    }

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

    impl super::super::Action for TestAction {
        fn on_oom(&self, _: ::env::JniEnv, _: ::jvmti::jint) -> Result<(), ::err::Error> {
            panic!("TestAction.on_oom")
        }
    }

    #[test]
    fn does_not_call_action_when_heuristic_returns_false() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(heuristic, vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
    }

    #[test]
    #[should_panic(expected = "TestAction.on_oom")]
    fn calls_action_when_heuristic_returns_true() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(heuristic, vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
        ac.on_oom(dummy_jni_env(), 0);
    }

    fn dummy_jni_env() -> ::env::JniEnv {
        ::env::JniEnv::new(::std::ptr::null_mut())
    }
}
<commit_msg>Avoid abusing the term "heap" in resource exhaustion message<commit_after>/*
 * Copyright (c) 2015-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use libc::SIGQUIT;

pub struct AgentController<'a> {
    heuristic: Box<super::Heuristic + 'a>,
    actions: Vec<Box<super::Action>>
}

impl<'a> AgentController<'a> {
    pub fn new(ti: ::env::JvmTiEnv, options: *mut ::std::os::raw::c_char) -> Result<Self, ::jvmti::jint> {
        let parms = super::parms::AgentParameters::parseParameters(options);

        let mut ac = Self {
            heuristic: Box::new(super::threshold::Threshold::new(parms.count_threshold, parms.time_threshold)),
            actions: Vec::new(),
        };

        if parms.print_heap_histogram {
            ac.actions.push(Box::new(super::heaphistogram::HeapHistogram::new(ti, parms.heap_histogram_max_entries).map_err(|err| err.rc())?));
        }

        if let Some(path) = parms.heap_dump_path {
            ac.actions.push(Box::new(super::heapdump::HeapDump::new(path)));
        }

        if parms.print_memory_usage {
            ac.actions.push(Box::new(super::poolstats::PoolStats::new()));
        }

        let mut threadDump = super::kill::Kill::new();
        threadDump.setSignal(SIGQUIT);
        ac.actions.push(Box::new(threadDump));

        ac.actions.push(Box::new(super::kill::Kill::new()));

        Ok(ac)
    }

    #[cfg(test)]
    fn test_new(heuristic: Box<super::Heuristic + 'a>, actions: Vec<Box<super::Action>>) -> Self {
        Self {
            heuristic: heuristic,
            actions: actions,
        }
    }
}

impl<'a> super::MutAction for AgentController<'a> {
    fn on_oom(&mut self, jni_env: ::env::JniEnv, resource_exhaustion_flags: ::jvmti::jint) {
        const heap_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP as ::jvmti::jint;
        const threads_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_THREADS as ::jvmti::jint;
        const oom_error: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR as ::jvmti::jint;

        if resource_exhaustion_flags & heap_exhausted == heap_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to allocate memory.");
        }
        if resource_exhaustion_flags & threads_exhausted == threads_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to create a thread.");
        }

        if self.heuristic.on_oom() {
            for action in &self.actions {
                if let Err(error) = action.on_oom(jni_env, resource_exhaustion_flags) {
                    eprintln!("ERROR: {} action failed: {}", action, error);
                }
            }
        } else if resource_exhaustion_flags & oom_error == oom_error {
            eprintln!("\nThe JVM is about to throw a java.lang.OutOfMemoryError.");
        }
    }
}

unsafe impl<'a> Send for AgentController<'a> {}

unsafe impl<'a> Sync for AgentController<'a> {}

#[cfg(test)]
mod tests {
    use agentcontroller::MutAction;

    pub struct TestHeuristic {
        call_count: u32
    }

    impl TestHeuristic {
        pub fn new() -> Self {
            Self {
                call_count: 0,
            }
        }
    }

    impl super::super::Heuristic for TestHeuristic {
        fn on_oom(&mut self) -> bool {
            self.call_count += 1;
            self.call_count >= 2
        }
    }

    pub struct TestAction {}

    impl TestAction {
        pub fn new() -> Self {
            Self {}
        }
    }

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

    impl super::super::Action for TestAction {
        fn on_oom(&self, _: ::env::JniEnv, _: ::jvmti::jint) -> Result<(), ::err::Error> {
            panic!("TestAction.on_oom")
        }
    }

    #[test]
    fn does_not_call_action_when_heuristic_returns_false() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(heuristic, vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
    }

    #[test]
    #[should_panic(expected = "TestAction.on_oom")]
    fn calls_action_when_heuristic_returns_true() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(heuristic, vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
        ac.on_oom(dummy_jni_env(), 0);
    }

    fn dummy_jni_env() -> ::env::JniEnv {
        ::env::JniEnv::new(::std::ptr::null_mut())
    }
}
<|endoftext|>


<commit_before>use crate::{
    crypto::{double_sha256, Digest, KeyPair, SigPair},
    serializer::*,
    tx::*,
};
use std::{
    io::Cursor,
    ops::{Deref, DerefMut},
};

#[derive(Clone, Debug, PartialEq)]
pub enum Block {
    V0(BlockV0),
}

impl Block {
    #[inline]
    pub fn height(&self) -> u64 {
        match self {
            Block::V0(block) => block.height,
        }
    }

    #[inline]
    pub fn timestamp(&self) -> u64 {
        match self {
            Block::V0(block) => block.timestamp,
        }
    }

    #[inline]
    pub fn txs(&self) -> &[TxVariant] {
        match self {
            Block::V0(block) => &block.transactions,
        }
    }

    #[inline]
    pub fn signer(&self) -> Option<&SigPair> {
        match self {
            Block::V0(block) => block.sig_pair.as_ref(),
        }
    }

    pub fn sign(&mut self, key_pair: &KeyPair) {
        let buf = self.calc_header_hash();
        match self {
            Block::V0(block) => {
                block.sig_pair = Some(key_pair.sign(buf.as_ref()));
            }
        }
    }

    pub fn verify_previous_hash(&self, prev_block: &Self) -> bool {
        let cur_prev_hash = match self {
            Block::V0(block) => &block.previous_hash,
        };
        cur_prev_hash == &prev_block.calc_header_hash()
    }

    pub fn verify_tx_merkle_root(&self) -> bool {
        match self {
            Block::V0(block) => {
                let digest = calc_tx_merkle_root(&block.transactions);
                block.tx_merkle_root == digest
            }
        }
    }

    pub fn calc_header_hash(&self) -> Digest {
        match self {
            Block::V0(block) => block.calc_header_hash(),
        }
    }

    pub fn deserialize(cur: &mut Cursor<&[u8]>) -> Option<Self> {
        let header = BlockHeader::deserialize(cur)?;
        match header {
            BlockHeader::V0(header) => {
                let sig_pair = Some(cur.take_sig_pair().ok()?);

                let len = cur.take_u32().ok()?;
                let mut transactions = Vec::<TxVariant>::with_capacity(len as usize);
                for _ in 0..len {
                    transactions.push(TxVariant::deserialize(cur)?);
                }

                Some(Block::V0(BlockV0 {
                    header,
                    sig_pair,
                    transactions,
                }))
            }
        }
    }

    pub fn serialize(&self, buf: &mut Vec<u8>) {
        match self {
            Block::V0(block) => {
                block.header.serialize(buf);
                buf.push_sig_pair(
                    block
                        .sig_pair
                        .as_ref()
                        .expect("block must be signed to serialize"),
                );
                buf.push_u32(block.transactions.len() as u32);
                for tx in &block.transactions {
                    tx.serialize(buf)
                }
            }
        }
    }
}

pub enum BlockHeader {
    V0(BlockHeaderV0),
}

impl BlockHeader {
    pub(self) fn deserialize(cur: &mut Cursor<&[u8]>) -> Option<Self> {
        let header_ver = cur.take_u16().ok()?;
        match header_ver {
            0 => Some(BlockHeader::V0(BlockHeaderV0::deserialize(cur)?)),
            _ => None,
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct BlockHeaderV0 {
    pub previous_hash: Digest,
    pub height: u64,
    pub timestamp: u64,
    pub tx_merkle_root: Digest,
}

impl BlockHeaderV0 {
    pub(self) fn serialize(&self, buf: &mut Vec<u8>) {
        // Header version (2 bytes)
        buf.push_u16(0);

        buf.push_bytes(self.previous_hash.as_ref());
        buf.push_u64(self.height);
        buf.push_u64(self.timestamp);
        buf.push_bytes(self.tx_merkle_root.as_ref());
    }

    pub(self) fn deserialize(cur: &mut Cursor<&[u8]>) -> Option<Self> {
        // We expect the version to already be deserialized here

        let previous_hash = Digest::from_slice(&cur.take_bytes().ok()?)?;
        let height = cur.take_u64().ok()?;
        let timestamp = cur.take_u64().ok()?;
        let tx_merkle_root = Digest::from_slice(&cur.take_bytes().ok()?)?;
        Some(Self {
            previous_hash,
            height,
            timestamp,
            tx_merkle_root,
        })
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct BlockV0 {
    pub header: BlockHeaderV0,
    pub sig_pair: Option<SigPair>,
    pub transactions: Vec<TxVariant>,
}

impl BlockV0 {
    pub fn new_child(&self, txs: Vec<TxVariant>) -> Block {
        let previous_hash = self.calc_header_hash();
        let height = self.header.height + 1;
        let tx_merkle_root = calc_tx_merkle_root(&txs);
        let timestamp = crate::get_epoch_ms();
        Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash,
                height,
                timestamp,
                tx_merkle_root,
            },
            sig_pair: None,
            transactions: txs,
        })
    }

    pub fn calc_header_hash(&self) -> Digest {
        let mut buf = Vec::with_capacity(1024);
        self.header.serialize(&mut buf);
        double_sha256(&buf)
    }
}

impl Deref for BlockV0 {
    type Target = BlockHeaderV0;

    fn deref(&self) -> &BlockHeaderV0 {
        &self.header
    }
}

impl DerefMut for BlockV0 {
    fn deref_mut(&mut self) -> &mut BlockHeaderV0 {
        &mut self.header
    }
}

pub fn calc_tx_merkle_root(txs: &[TxVariant]) -> Digest {
    let mut buf = Vec::with_capacity(4096 * txs.len());
    for tx in txs {
        tx.serialize(&mut buf)
    }
    double_sha256(&buf)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{asset::Asset, crypto::KeyPair};

    #[test]
    fn serialize_block_v0() {
        let keys = KeyPair::gen();
        let transactions = vec![TxVariant::V0(TxVariantV0::RewardTx(RewardTx {
            base: Tx {
                fee: Asset::default(),
                timestamp: 1234567890,
                signature_pairs: Vec::new(),
            },
            to: keys.0.clone().into(),
            rewards: Asset::default(),
        }))];
        let tx_merkle_root = {
            let mut buf = Vec::new();
            for tx in &transactions {
                tx.serialize(&mut buf)
            }
            double_sha256(&buf)
        };
        let mut block = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0u8; 32]).unwrap(),
                height: 123,
                timestamp: 1532992800,
                tx_merkle_root,
            },
            sig_pair: None,
            transactions,
        });
        block.sign(&keys);

        let mut buf = Vec::new();
        block.serialize(&mut buf);

        let mut cur = Cursor::<&[u8]>::new(&buf);
        let dec = Block::deserialize(&mut cur).unwrap();

        assert_eq!(block, dec);
    }

    #[test]
    fn merkle_root() {
        let mut block = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0; 32]).unwrap(),
                height: 0,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });
        assert!(block.verify_tx_merkle_root());

        match &mut block {
            Block::V0(block) => {
                block.tx_merkle_root = Digest::from_slice(&[0; 32]).unwrap();
            }
        }

        assert!(!block.verify_tx_merkle_root());
    }

    #[test]
    fn previous_hash() {
        let block_0 = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0; 32]).unwrap(),
                height: 0,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });

        let block_1 = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: block_0.calc_header_hash(),
                height: 1,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });

        let block_1_invalid = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0; 32]).unwrap(),
                height: 1,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });

        assert!(block_1.verify_previous_hash(&block_0));
        assert!(!block_1_invalid.verify_previous_hash(&block_0));
    }
}
<commit_msg>Remove DerefMut impl on BlockHeaderV0<commit_after>use crate::{
    crypto::{double_sha256, Digest, KeyPair, SigPair},
    serializer::*,
    tx::*,
};
use std::{io::Cursor, ops::Deref};

#[derive(Clone, Debug, PartialEq)]
pub enum Block {
    V0(BlockV0),
}

impl Block {
    #[inline]
    pub fn height(&self) -> u64 {
        match self {
            Block::V0(block) => block.height,
        }
    }

    #[inline]
    pub fn timestamp(&self) -> u64 {
        match self {
            Block::V0(block) => block.timestamp,
        }
    }

    #[inline]
    pub fn txs(&self) -> &[TxVariant] {
        match self {
            Block::V0(block) => &block.transactions,
        }
    }

    #[inline]
    pub fn signer(&self) -> Option<&SigPair> {
        match self {
            Block::V0(block) => block.sig_pair.as_ref(),
        }
    }

    pub fn sign(&mut self, key_pair: &KeyPair) {
        let buf = self.calc_header_hash();
        match self {
            Block::V0(block) => {
                block.sig_pair = Some(key_pair.sign(buf.as_ref()));
            }
        }
    }

    pub fn verify_previous_hash(&self, prev_block: &Self) -> bool {
        let cur_prev_hash = match self {
            Block::V0(block) => &block.previous_hash,
        };
        cur_prev_hash == &prev_block.calc_header_hash()
    }

    pub fn verify_tx_merkle_root(&self) -> bool {
        match self {
            Block::V0(block) => {
                let digest = calc_tx_merkle_root(&block.transactions);
                block.tx_merkle_root == digest
            }
        }
    }

    pub fn calc_header_hash(&self) -> Digest {
        match self {
            Block::V0(block) => block.calc_header_hash(),
        }
    }

    pub fn deserialize(cur: &mut Cursor<&[u8]>) -> Option<Self> {
        let header = BlockHeader::deserialize(cur)?;
        match header {
            BlockHeader::V0(header) => {
                let sig_pair = Some(cur.take_sig_pair().ok()?);

                let len = cur.take_u32().ok()?;
                let mut transactions = Vec::<TxVariant>::with_capacity(len as usize);
                for _ in 0..len {
                    transactions.push(TxVariant::deserialize(cur)?);
                }

                Some(Block::V0(BlockV0 {
                    header,
                    sig_pair,
                    transactions,
                }))
            }
        }
    }

    pub fn serialize(&self, buf: &mut Vec<u8>) {
        match self {
            Block::V0(block) => {
                block.header.serialize(buf);
                buf.push_sig_pair(
                    block
                        .sig_pair
                        .as_ref()
                        .expect("block must be signed to serialize"),
                );
                buf.push_u32(block.transactions.len() as u32);
                for tx in &block.transactions {
                    tx.serialize(buf)
                }
            }
        }
    }
}

pub enum BlockHeader {
    V0(BlockHeaderV0),
}

impl BlockHeader {
    pub(self) fn deserialize(cur: &mut Cursor<&[u8]>) -> Option<Self> {
        let header_ver = cur.take_u16().ok()?;
        match header_ver {
            0 => Some(BlockHeader::V0(BlockHeaderV0::deserialize(cur)?)),
            _ => None,
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct BlockHeaderV0 {
    pub previous_hash: Digest,
    pub height: u64,
    pub timestamp: u64,
    pub tx_merkle_root: Digest,
}

impl BlockHeaderV0 {
    pub(self) fn serialize(&self, buf: &mut Vec<u8>) {
        // Header version (2 bytes)
        buf.push_u16(0);

        buf.push_bytes(self.previous_hash.as_ref());
        buf.push_u64(self.height);
        buf.push_u64(self.timestamp);
        buf.push_bytes(self.tx_merkle_root.as_ref());
    }

    pub(self) fn deserialize(cur: &mut Cursor<&[u8]>) -> Option<Self> {
        // We expect the version to already be deserialized here

        let previous_hash = Digest::from_slice(&cur.take_bytes().ok()?)?;
        let height = cur.take_u64().ok()?;
        let timestamp = cur.take_u64().ok()?;
        let tx_merkle_root = Digest::from_slice(&cur.take_bytes().ok()?)?;
        Some(Self {
            previous_hash,
            height,
            timestamp,
            tx_merkle_root,
        })
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct BlockV0 {
    pub header: BlockHeaderV0,
    pub sig_pair: Option<SigPair>,
    pub transactions: Vec<TxVariant>,
}

impl BlockV0 {
    pub fn new_child(&self, txs: Vec<TxVariant>) -> Block {
        let previous_hash = self.calc_header_hash();
        let height = self.header.height + 1;
        let tx_merkle_root = calc_tx_merkle_root(&txs);
        let timestamp = crate::get_epoch_ms();
        Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash,
                height,
                timestamp,
                tx_merkle_root,
            },
            sig_pair: None,
            transactions: txs,
        })
    }

    pub fn calc_header_hash(&self) -> Digest {
        let mut buf = Vec::with_capacity(1024);
        self.header.serialize(&mut buf);
        double_sha256(&buf)
    }
}

impl Deref for BlockV0 {
    type Target = BlockHeaderV0;

    fn deref(&self) -> &BlockHeaderV0 {
        &self.header
    }
}

pub fn calc_tx_merkle_root(txs: &[TxVariant]) -> Digest {
    let mut buf = Vec::with_capacity(4096 * txs.len());
    for tx in txs {
        tx.serialize(&mut buf)
    }
    double_sha256(&buf)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{asset::Asset, crypto::KeyPair};

    #[test]
    fn serialize_block_v0() {
        let keys = KeyPair::gen();
        let transactions = vec![TxVariant::V0(TxVariantV0::RewardTx(RewardTx {
            base: Tx {
                fee: Asset::default(),
                timestamp: 1234567890,
                signature_pairs: Vec::new(),
            },
            to: keys.0.clone().into(),
            rewards: Asset::default(),
        }))];
        let tx_merkle_root = {
            let mut buf = Vec::new();
            for tx in &transactions {
                tx.serialize(&mut buf)
            }
            double_sha256(&buf)
        };
        let mut block = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0u8; 32]).unwrap(),
                height: 123,
                timestamp: 1532992800,
                tx_merkle_root,
            },
            sig_pair: None,
            transactions,
        });
        block.sign(&keys);

        let mut buf = Vec::new();
        block.serialize(&mut buf);

        let mut cur = Cursor::<&[u8]>::new(&buf);
        let dec = Block::deserialize(&mut cur).unwrap();

        assert_eq!(block, dec);
    }

    #[test]
    fn merkle_root() {
        let mut block = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0; 32]).unwrap(),
                height: 0,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });
        assert!(block.verify_tx_merkle_root());

        match &mut block {
            Block::V0(block) => {
                block.header.tx_merkle_root = Digest::from_slice(&[0; 32]).unwrap();
            }
        }

        assert!(!block.verify_tx_merkle_root());
    }

    #[test]
    fn previous_hash() {
        let block_0 = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0; 32]).unwrap(),
                height: 0,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });

        let block_1 = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: block_0.calc_header_hash(),
                height: 1,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });

        let block_1_invalid = Block::V0(BlockV0 {
            header: BlockHeaderV0 {
                previous_hash: Digest::from_slice(&[0; 32]).unwrap(),
                height: 1,
                timestamp: 0,
                tx_merkle_root: double_sha256(&[0; 0]),
            },
            sig_pair: None,
            transactions: vec![],
        });

        assert!(block_1.verify_previous_hash(&block_0));
        assert!(!block_1_invalid.verify_previous_hash(&block_0));
    }
}
<|endoftext|>


<commit_before>//! Run-time feature detection for RISC-V on Linux.

use super::auxvec;
use crate::detect::{bit, cache, Feature};

/// Read list of supported features from the auxiliary vector.
pub(crate) fn detect_features() -> cache::Initializer {
    let mut value = cache::Initializer::default();
    let enable_feature = |value: &mut cache::Initializer, feature, enable| {
        if enable {
            value.set(feature as u32);
        }
    };
    let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
        if enable {
            for feature in feature_slice {
                value.set(*feature as u32);
            }
        }
    };

    // The values are part of the platform-specific [asm/hwcap.h][hwcap]
    //
    // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
    let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
    enable_feature(
        &mut value,
        Feature::a,
        bit::test(auxv.hwcap, (b'a' - b'a').into()),
    );
    enable_feature(
        &mut value,
        Feature::c,
        bit::test(auxv.hwcap, (b'c' - b'a').into()),
    );
    enable_features(
        &mut value,
        &[Feature::d, Feature::f, Feature::zicsr],
        bit::test(auxv.hwcap, (b'd' - b'a').into()),
    );
    enable_features(
        &mut value,
        &[Feature::f, Feature::zicsr],
        bit::test(auxv.hwcap, (b'f' - b'a').into()),
    );
    let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
    // If future RV128I is supported, implement with `enable_feature` here
    #[cfg(target_pointer_width = "64")]
    enable_feature(&mut value, Feature::rv64i, has_i);
    #[cfg(target_pointer_width = "32")]
    enable_feature(&mut value, Feature::rv32i, has_i);
    #[cfg(target_pointer_width = "32")]
    enable_feature(
        &mut value,
        Feature::rv32e,
        bit::test(auxv.hwcap, (b'e' - b'a').into()),
    );
    enable_feature(
        &mut value,
        Feature::h,
        bit::test(auxv.hwcap, (b'h' - b'a').into()),
    );
    enable_feature(
        &mut value,
        Feature::m,
        bit::test(auxv.hwcap, (b'm' - b'a').into()),
    );
    // FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
    // to detect when Rust is used to write Linux kernel modules.
    // These should be more than Auxvec way to detect supervisor features.

    value
}
<commit_msg>Fix line endings to use LF (#1350)<commit_after>//! Run-time feature detection for RISC-V on Linux.

use super::auxvec;
use crate::detect::{bit, cache, Feature};

/// Read list of supported features from the auxiliary vector.
pub(crate) fn detect_features() -> cache::Initializer {
    let mut value = cache::Initializer::default();
    let enable_feature = |value: &mut cache::Initializer, feature, enable| {
        if enable {
            value.set(feature as u32);
        }
    };
    let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
        if enable {
            for feature in feature_slice {
                value.set(*feature as u32);
            }
        }
    };

    // The values are part of the platform-specific [asm/hwcap.h][hwcap]
    //
    // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
    let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
    enable_feature(
        &mut value,
        Feature::a,
        bit::test(auxv.hwcap, (b'a' - b'a').into()),
    );
    enable_feature(
        &mut value,
        Feature::c,
        bit::test(auxv.hwcap, (b'c' - b'a').into()),
    );
    enable_features(
        &mut value,
        &[Feature::d, Feature::f, Feature::zicsr],
        bit::test(auxv.hwcap, (b'd' - b'a').into()),
    );
    enable_features(
        &mut value,
        &[Feature::f, Feature::zicsr],
        bit::test(auxv.hwcap, (b'f' - b'a').into()),
    );
    let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
    // If future RV128I is supported, implement with `enable_feature` here
    #[cfg(target_pointer_width = "64")]
    enable_feature(&mut value, Feature::rv64i, has_i);
    #[cfg(target_pointer_width = "32")]
    enable_feature(&mut value, Feature::rv32i, has_i);
    #[cfg(target_pointer_width = "32")]
    enable_feature(
        &mut value,
        Feature::rv32e,
        bit::test(auxv.hwcap, (b'e' - b'a').into()),
    );
    enable_feature(
        &mut value,
        Feature::h,
        bit::test(auxv.hwcap, (b'h' - b'a').into()),
    );
    enable_feature(
        &mut value,
        Feature::m,
        bit::test(auxv.hwcap, (b'm' - b'a').into()),
    );
    // FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
    // to detect when Rust is used to write Linux kernel modules.
    // These should be more than Auxvec way to detect supervisor features.

    value
}
<|endoftext|>


<commit_before>//! This example uses [hyper][] to create a http server which handles requests asynchronously in
//! gluon. To do this we define a few types and functions in Rust with which we register in gluon
//! so that we can communicate with `hyper`. The rest of the implementation is done in gluon,
//! routing the requests and constructing the responses.
//!
//! [hyper]:https://hyper.rs

extern crate gluon;
extern crate gluon_base as base;
#[macro_use]
extern crate gluon_vm as vm;

#[macro_use]
extern crate collect_mac;
extern crate env_logger;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;

use std::env;
use std::fmt;
use std::fs::File;
use std::io::{stderr, Read, Write};
use std::marker::PhantomData;
use std::str;
use std::sync::{Arc, Mutex};

use hyper::{Chunk, Method, StatusCode};
use hyper::server::Service;

use futures::Async;
use futures::future::Future;
use futures::sink::Sink;
use futures::stream::Stream;
use futures::sync::mpsc::Sender;

use base::types::{ArcType, Type};

use vm::{Error as VmError, Result as VmResult};

use vm::thread::ThreadInternal;
use vm::thread::{Context, RootedThread, Thread};
use vm::Variants;
use vm::api::{Function, FunctionRef, FutureResult, Getable, OpaqueValue, PushAsRef, Pushable,
              Userdata, ValueRef, VmType, WithVM, IO};
use vm::gc::{Gc, Traverseable};

use vm::internal::Value;

use gluon::{new_vm, Compiler};

// `Handler` is a type defined in http.glu but since we need to refer to it in the signature of
// listen we define a phantom type which we can use with `OpaqueValue` to store a `Handler` in Rust
struct Handler<T>(PhantomData<T>);

impl<T: VmType + 'static> VmType for Handler<T> {
    type Type = Self;
    fn make_type(vm: &Thread) -> ArcType {
        let typ = (*vm.global_env()
                       .get_env()
                       .find_type_info("examples.http_types.Handler")
                       .unwrap())
            .clone()
            .into_type();
        Type::app(typ, collect![T::make_type(vm)])
    }
}

// Rust does not let us define traits on types defined in a different crate such as `hyper`. We can
// however work around this by defining a wrapper type which we are then able to define the traits
// on.
struct Wrap<T>(T);

macro_rules! define_vmtype {
    ($name: ident) => {
        impl VmType for Wrap<$name> {
            type Type = $name;
            fn make_type(vm: &Thread) -> ArcType {
                let typ = concat!("examples.http_types.", stringify!($name));
                (*vm.global_env().get_env().find_type_info(typ).unwrap())
                    .clone()
                    .into_type()
            }
        }

    }
}

define_vmtype! { Method }

impl<'vm> Pushable<'vm> for Wrap<Method> {
    fn push(self, _: &'vm Thread, context: &mut Context) -> VmResult<()> {
        use hyper::Method::*;
        context.stack.push(Value::Tag(match self.0 {
            Get => 0,
            Post => 1,
            Delete => 2,
            _ => {
                return Err(
                    VmError::Message(format!("Method `{:?}` does not exist in gluon", self.0))
                        .into(),
                )
            }
        }));
        Ok(())
    }
}

define_vmtype! { StatusCode }

impl<'vm> Getable<'vm> for Wrap<StatusCode> {
    fn from_value(_: &'vm Thread, value: Variants) -> Option<Self> {
        use hyper::StatusCode::*;
        match value.as_ref() {
            ValueRef::Data(data) => Some(Wrap(match data.tag() {
                0 => Ok,
                1 => NotFound,
                2 => InternalServerError,
                _ => panic!("Unexpected tag"),
            })),
            _ => panic!(),
        }
    }
}

// Representation of a http body that is in the prograss of being read
pub struct Body(Arc<Mutex<Box<Stream<Item = PushAsRef<Chunk, [u8]>, Error = VmError> + Send + 'static>>>);

// By implementing `Userdata` on `Body` it can be automatically pushed and retrieved from gluon
// threads
impl Userdata for Body {}

// Types implementing `Userdata` requires a `std::fmt::Debug` implementation so it can be displayed
impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "hyper::Body")
    }
}

// `Traverseable` is required by `Userdata` so that the garbage collector knows how to scan the
// value for garbage collected references. Normally objects do not contain any references so this
// can be empty
impl Traverseable for Body {
    fn traverse(&self, _: &mut Gc) {}
}

// `VmType` is the last trait required for a type to implement `Userdata` and defines the type used
// in gluon for this Rust type. For opaque `Userdata` values this minimal implementation is enough
// as the default implementation of `make_type` will lookup `VmType::Type` from the virtual machine
// which should have been registered earlier with `Thread::register_type`
impl VmType for Body {
    type Type = Self;
}

// Since `Body` implements `Userdata` gluon will automatically marshal the gluon representation
// into `&Body` argument
fn read_chunk(
    body: &Body,
) -> FutureResult<
    Box<
        Future<Item = IO<Option<PushAsRef<Chunk, [u8]>>>, Error = VmError>
            + Send
            + 'static,
    >,
> {
    use futures::future::poll_fn;

    let body = body.0.clone();
    // `FutureResult` is a wrapper type around `Future` which when returned to the interpreter is
    // polled until completion. After `poll` returns `Ready` the value is then returned to the
    // gluon function which called `read_chunk`
    FutureResult(Box::new(poll_fn(move || {
        let mut stream = body.lock().unwrap();
        stream.poll().map(|async| async.map(IO::Value))
    })))
}

// A http body that is being written
pub struct ResponseBody(Arc<Mutex<Option<Sender<Result<Chunk, hyper::Error>>>>>);

impl fmt::Debug for ResponseBody {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "hyper::Response")
    }
}

impl Userdata for ResponseBody {}

impl Traverseable for ResponseBody {
    fn traverse(&self, _: &mut Gc) {}
}

impl VmType for ResponseBody {
    type Type = Self;
}

fn write_response(
    response: &ResponseBody,
    bytes: &[u8],
) -> FutureResult<Box<Future<Item = IO<()>, Error = VmError> + Send + 'static>> {
    use futures::future::poll_fn;
    use futures::AsyncSink;

    // Turn `bytes´ into a `Chunk` which can be sent to the http body
    let mut unsent_chunk = Some(Ok(bytes.to_owned().into()));
    let response = response.0.clone();
    FutureResult(Box::new(poll_fn(move || {
        info!("Starting response send");
        let mut sender = response.lock().unwrap();
        let sender = sender.as_mut().expect(
            "Sender has been dropped while still in use",
        );
        if let Some(chunk) = unsent_chunk.take() {
            match sender.start_send(chunk) {
                Ok(AsyncSink::NotReady(chunk)) => {
                    unsent_chunk = Some(chunk);
                    return Ok(Async::NotReady);
                }
                Ok(AsyncSink::Ready) => (),
                Err(_) => {
                    info!("Could not send http response");
                    return Ok(Async::Ready(IO::Value(())));
                }
            }
        }
        match sender.poll_complete() {
            Ok(async) => Ok(async.map(IO::Value)),
            Err(_) => {
                info!("Could not send http response");
                Ok(Async::Ready(IO::Value(())))
            }
        }
    })))
}

// Next we define some record types which are marshalled to and from gluon. These have equivalent
// definitions in http_types.glu
field_decl! { method, uri, status, body, request, response }

type Request = record_type!{
    method => Wrap<Method>,
    uri => String,
    body => Body
};

type Response = record_type!{
    status => Wrap<StatusCode>
};

type HttpState = record_type!{
    request => Request,
    response => ResponseBody
};

fn listen(port: i32, value: WithVM<OpaqueValue<RootedThread, Handler<Response>>>) -> IO<()> {
    let WithVM {
        value: handler,
        vm: thread,
    } = value;

    use hyper::server::{Http, Request as HyperRequest, Response as HyperResponse};

    // Retrieve the `handle` function from the http module which we use to evaluate values of type
    // `Handler Response`
    type ListenFn = fn(OpaqueValue<RootedThread, Handler<Response>>, HttpState) -> IO<Response>;
    let handle: Function<RootedThread, ListenFn> = thread
        .get_global("examples.http.handle")
        .unwrap_or_else(|err| panic!("{}", err));

    struct Listen {
        handle: Function<RootedThread, ListenFn>,
        handler: OpaqueValue<RootedThread, Handler<Response>>,
    }

    impl Service for Listen {
        type Request = HyperRequest;
        type Response = HyperResponse;
        type Error = hyper::Error;
        type Future = Box<Future<Item = HyperResponse, Error = hyper::Error> + Send + 'static>;

        fn call(&self, request: HyperRequest) -> Self::Future {
            let gluon_request =
                record_no_decl! {
                // Here we use to `Wrap` type to make `hyper::Request` into a type that can be
                // pushed to gluon
                method => Wrap(request.method().clone()),
                uri => request.uri().to_string(),
                // Since `Body` implements `Userdata` it can be directly pushed to gluon
                body => Body(Arc::new(Mutex::new(Box::new(request.body()
                    .map_err(|err| VmError::Message(format!("{}", err)))
                    // `PushAsRef` makes the `body` parameter act as a `&[u8]` which means it is
                    // marshalled to `Array Byte` in gluon
                    .map(PushAsRef::<_, [u8]>::new)))))
            };
            let (response_sender, response_body) = hyper::Body::pair();
            let response_sender = Arc::new(Mutex::new(Some(response_sender)));
            let http_state =
                record_no_decl!{
                request => gluon_request,
                response => ResponseBody(response_sender.clone())
            };

            Box::new(
                self.handle
                    .clone()
                    .call_async(self.handler.clone(), http_state)
                    .then(move |result| match result {
                        Ok(value) => {
                            match value {
                                IO::Value(record_p!{ status }) => {
                                    // Drop the sender to so that it the receiver stops waiting for
                                    // more chunks
                                    *response_sender.lock().unwrap() = None;
                                    Ok(HyperResponse::new().with_status(status.0).with_body(
                                        response_body,
                                    ))
                                }
                                IO::Exception(err) => {
                                    let _ = stderr().write(err.as_bytes());
                                    Ok(HyperResponse::new().with_status(
                                        StatusCode::InternalServerError,
                                    ))
                                }
                            }
                        }
                        Err(err) => {
                            let _ = stderr().write(format!("{}", err).as_bytes());
                            Ok(HyperResponse::new().with_status(
                                StatusCode::InternalServerError,
                            ))
                        }
                    }),
            )
        }
    }

    let addr = format!("127.0.0.1:{}", port).parse().unwrap();
    let result = Http::new()
        .bind(&addr, move || {
            Ok(Listen {
                handle: handle.clone(),
                handler: handler.clone(),
            })
        })
        .and_then(|server| server.run());

    match result {
        Ok(()) => IO::Value(()),
        Err(err) => IO::Exception(format!("{}", err)),
    }
}

// To let the `http_types` module refer to `Body` and `ResponseBody` we register these types in a
// separate function which is called before loading `http_types`
pub fn load_types(vm: &Thread) -> VmResult<()> {
    vm.register_type::<Body>("Body", &[])?;
    vm.register_type::<ResponseBody>("ResponseBody", &[])?;
    Ok(())
}

pub fn load(vm: &Thread) -> VmResult<()> {
    vm.define_global(
        "http_prim",
        record! {
            listen => primitive!(2 listen),
            read_chunk => primitive!(1 read_chunk),
            write_response => primitive!(2 write_response)
        },
    )?;
    Ok(())
}

fn main() {
    let _ = env_logger::init();
    let port = env::args()
        .nth(1)
        .map(|port| port.parse::<i32>().expect("port"))
        .unwrap_or(80);

    let thread = new_vm();

    // First load all the http types so we can refer to them from gluon
    load_types(&thread).unwrap();
    Compiler::new()
        .run_expr::<()>(
            &thread,
            "",
            r#"let _ = import! "examples/http_types.glu" in () "#,
        )
        .unwrap_or_else(|err| panic!("{}", err));

    // Load the primitive functions we define in this module
    load(&thread).unwrap();

    // Last we run our `http_server.glu` module which returns a function which starts listening
    // on the port we passed from the command line
    let mut expr = String::new();
    {
        let mut file = File::open("examples/http_server.glu").unwrap();
        file.read_to_string(&mut expr).unwrap();
    }
    let (mut listen, _) = Compiler::new()
        .run_expr::<FunctionRef<fn(i32) -> IO<()>>>(&thread, "http_test", &expr)
        .unwrap_or_else(|err| panic!("{}", err));

    listen.call(port).unwrap_or_else(|err| panic!("{}", err));
}
<commit_msg>refactor: Avoid using unwrap in the http example<commit_after>//! This example uses [hyper][] to create a http server which handles requests asynchronously in
//! gluon. To do this we define a few types and functions in Rust with which we register in gluon
//! so that we can communicate with `hyper`. The rest of the implementation is done in gluon,
//! routing the requests and constructing the responses.
//!
//! [hyper]:https://hyper.rs

extern crate gluon;
extern crate gluon_base as base;
#[macro_use]
extern crate gluon_vm as vm;

#[macro_use]
extern crate collect_mac;
extern crate env_logger;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;

use std::env;
use std::fmt;
use std::error::Error as StdError;
use std::fs::File;
use std::io::{stderr, Read, Write};
use std::marker::PhantomData;
use std::str;
use std::sync::{Arc, Mutex};

use hyper::{Chunk, Method, StatusCode};
use hyper::server::Service;

use futures::Async;
use futures::future::Future;
use futures::sink::Sink;
use futures::stream::Stream;
use futures::sync::mpsc::Sender;

use base::types::{ArcType, Type};

use vm::{Error as VmError, Result as VmResult};

use vm::thread::ThreadInternal;
use vm::thread::{Context, RootedThread, Thread};
use vm::Variants;
use vm::api::{Function, FunctionRef, FutureResult, Getable, OpaqueValue, PushAsRef, Pushable,
              Userdata, ValueRef, VmType, WithVM, IO};
use vm::gc::{Gc, Traverseable};

use vm::internal::Value;

use gluon::{new_vm, Compiler};

// `Handler` is a type defined in http.glu but since we need to refer to it in the signature of
// listen we define a phantom type which we can use with `OpaqueValue` to store a `Handler` in Rust
struct Handler<T>(PhantomData<T>);

impl<T: VmType + 'static> VmType for Handler<T> {
    type Type = Self;
    fn make_type(vm: &Thread) -> ArcType {
        let typ = (*vm.global_env()
            .get_env()
            .find_type_info("examples.http_types.Handler")
            .unwrap())
            .clone()
            .into_type();
        Type::app(typ, collect![T::make_type(vm)])
    }
}

// Rust does not let us define traits on types defined in a different crate such as `hyper`. We can
// however work around this by defining a wrapper type which we are then able to define the traits
// on.
struct Wrap<T>(T);

macro_rules! define_vmtype {
    ($name: ident) => {
        impl VmType for Wrap<$name> {
            type Type = $name;
            fn make_type(vm: &Thread) -> ArcType {
                let typ = concat!("examples.http_types.", stringify!($name));
                (*vm.global_env().get_env().find_type_info(typ).unwrap())
                    .clone()
                    .into_type()
            }
        }

    }
}

define_vmtype! { Method }

impl<'vm> Pushable<'vm> for Wrap<Method> {
    fn push(self, _: &'vm Thread, context: &mut Context) -> VmResult<()> {
        use hyper::Method::*;
        context.stack.push(Value::Tag(match self.0 {
            Get => 0,
            Post => 1,
            Delete => 2,
            _ => {
                return Err(
                    VmError::Message(format!("Method `{:?}` does not exist in gluon", self.0))
                        .into(),
                )
            }
        }));
        Ok(())
    }
}

define_vmtype! { StatusCode }

impl<'vm> Getable<'vm> for Wrap<StatusCode> {
    fn from_value(_: &'vm Thread, value: Variants) -> Option<Self> {
        use hyper::StatusCode::*;
        match value.as_ref() {
            ValueRef::Data(data) => Some(Wrap(match data.tag() {
                0 => Ok,
                1 => NotFound,
                2 => InternalServerError,
                _ => panic!("Unexpected tag"),
            })),
            _ => panic!(),
        }
    }
}

// Representation of a http body that is in the prograss of being read
pub struct Body(
    Arc<Mutex<Box<Stream<Item = PushAsRef<Chunk, [u8]>, Error = VmError> + Send + 'static>>>,
);

// By implementing `Userdata` on `Body` it can be automatically pushed and retrieved from gluon
// threads
impl Userdata for Body {}

// Types implementing `Userdata` requires a `std::fmt::Debug` implementation so it can be displayed
impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "hyper::Body")
    }
}

// `Traverseable` is required by `Userdata` so that the garbage collector knows how to scan the
// value for garbage collected references. Normally objects do not contain any references so this
// can be empty
impl Traverseable for Body {
    fn traverse(&self, _: &mut Gc) {}
}

// `VmType` is the last trait required for a type to implement `Userdata` and defines the type used
// in gluon for this Rust type. For opaque `Userdata` values this minimal implementation is enough
// as the default implementation of `make_type` will lookup `VmType::Type` from the virtual machine
// which should have been registered earlier with `Thread::register_type`
impl VmType for Body {
    type Type = Self;
}

// Since `Body` implements `Userdata` gluon will automatically marshal the gluon representation
// into `&Body` argument
fn read_chunk(
    body: &Body,
) -> FutureResult<
    Box<Future<Item = IO<Option<PushAsRef<Chunk, [u8]>>>, Error = VmError> + Send + 'static>,
> {
    use futures::future::poll_fn;

    let body = body.0.clone();
    // `FutureResult` is a wrapper type around `Future` which when returned to the interpreter is
    // polled until completion. After `poll` returns `Ready` the value is then returned to the
    // gluon function which called `read_chunk`
    FutureResult(Box::new(poll_fn(move || {
        let mut stream = body.lock().unwrap();
        stream.poll().map(|async| async.map(IO::Value))
    })))
}

// A http body that is being written
pub struct ResponseBody(Arc<Mutex<Option<Sender<Result<Chunk, hyper::Error>>>>>);

impl fmt::Debug for ResponseBody {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "hyper::Response")
    }
}

impl Userdata for ResponseBody {}

impl Traverseable for ResponseBody {
    fn traverse(&self, _: &mut Gc) {}
}

impl VmType for ResponseBody {
    type Type = Self;
}

fn write_response(
    response: &ResponseBody,
    bytes: &[u8],
) -> FutureResult<Box<Future<Item = IO<()>, Error = VmError> + Send + 'static>> {
    use futures::future::poll_fn;
    use futures::AsyncSink;

    // Turn `bytes´ into a `Chunk` which can be sent to the http body
    let mut unsent_chunk = Some(Ok(bytes.to_owned().into()));
    let response = response.0.clone();
    FutureResult(Box::new(poll_fn(move || {
        info!("Starting response send");
        let mut sender = response.lock().unwrap();
        let sender = sender
            .as_mut()
            .expect("Sender has been dropped while still in use");
        if let Some(chunk) = unsent_chunk.take() {
            match sender.start_send(chunk) {
                Ok(AsyncSink::NotReady(chunk)) => {
                    unsent_chunk = Some(chunk);
                    return Ok(Async::NotReady);
                }
                Ok(AsyncSink::Ready) => (),
                Err(_) => {
                    info!("Could not send http response");
                    return Ok(Async::Ready(IO::Value(())));
                }
            }
        }
        match sender.poll_complete() {
            Ok(async) => Ok(async.map(IO::Value)),
            Err(_) => {
                info!("Could not send http response");
                Ok(Async::Ready(IO::Value(())))
            }
        }
    })))
}

// Next we define some record types which are marshalled to and from gluon. These have equivalent
// definitions in http_types.glu
field_decl! { method, uri, status, body, request, response }

type Request = record_type!{
    method => Wrap<Method>,
    uri => String,
    body => Body
};

type Response = record_type!{
    status => Wrap<StatusCode>
};

type HttpState = record_type!{
    request => Request,
    response => ResponseBody
};

fn listen(port: i32, value: WithVM<OpaqueValue<RootedThread, Handler<Response>>>) -> IO<()> {
    let WithVM {
        value: handler,
        vm: thread,
    } = value;

    use hyper::server::{Http, Request as HyperRequest, Response as HyperResponse};

    // Retrieve the `handle` function from the http module which we use to evaluate values of type
    // `Handler Response`
    type ListenFn = fn(OpaqueValue<RootedThread, Handler<Response>>, HttpState)
        -> IO<Response>;
    let handle: Function<RootedThread, ListenFn> = thread
        .get_global("examples.http.handle")
        .unwrap_or_else(|err| panic!("{}", err));

    struct Listen {
        handle: Function<RootedThread, ListenFn>,
        handler: OpaqueValue<RootedThread, Handler<Response>>,
    }

    impl Service for Listen {
        type Request = HyperRequest;
        type Response = HyperResponse;
        type Error = hyper::Error;
        type Future = Box<Future<Item = HyperResponse, Error = hyper::Error> + Send + 'static>;

        fn call(&self, request: HyperRequest) -> Self::Future {
            let gluon_request = record_no_decl! {
                // Here we use to `Wrap` type to make `hyper::Request` into a type that can be
                // pushed to gluon
                method => Wrap(request.method().clone()),
                uri => request.uri().to_string(),
                // Since `Body` implements `Userdata` it can be directly pushed to gluon
                body => Body(Arc::new(Mutex::new(Box::new(request.body()
                    .map_err(|err| VmError::Message(format!("{}", err)))
                    // `PushAsRef` makes the `body` parameter act as a `&[u8]` which means it is
                    // marshalled to `Array Byte` in gluon
                    .map(PushAsRef::<_, [u8]>::new)))))
            };
            let (response_sender, response_body) = hyper::Body::pair();
            let response_sender = Arc::new(Mutex::new(Some(response_sender)));
            let http_state = record_no_decl!{
                request => gluon_request,
                response => ResponseBody(response_sender.clone())
            };

            Box::new(
                self.handle
                    .clone()
                    .call_async(self.handler.clone(), http_state)
                    .then(move |result| match result {
                        Ok(value) => {
                            match value {
                                IO::Value(record_p!{ status }) => {
                                    // Drop the sender to so that it the receiver stops waiting for
                                    // more chunks
                                    *response_sender.lock().unwrap() = None;
                                    Ok(
                                        HyperResponse::new()
                                            .with_status(status.0)
                                            .with_body(response_body),
                                    )
                                }
                                IO::Exception(err) => {
                                    let _ = stderr().write(err.as_bytes());
                                    Ok(
                                        HyperResponse::new()
                                            .with_status(StatusCode::InternalServerError),
                                    )
                                }
                            }
                        }
                        Err(err) => {
                            let _ = stderr().write(format!("{}", err).as_bytes());
                            Ok(
                                HyperResponse::new().with_status(StatusCode::InternalServerError),
                            )
                        }
                    }),
            )
        }
    }

    let addr = format!("127.0.0.1:{}", port).parse().unwrap();
    let result = Http::new()
        .bind(&addr, move || {
            Ok(Listen {
                handle: handle.clone(),
                handler: handler.clone(),
            })
        })
        .and_then(|server| server.run());

    match result {
        Ok(()) => IO::Value(()),
        Err(err) => IO::Exception(format!("{}", err)),
    }
}

// To let the `http_types` module refer to `Body` and `ResponseBody` we register these types in a
// separate function which is called before loading `http_types`
pub fn load_types(vm: &Thread) -> VmResult<()> {
    vm.register_type::<Body>("Body", &[])?;
    vm.register_type::<ResponseBody>("ResponseBody", &[])?;
    Ok(())
}

pub fn load(vm: &Thread) -> VmResult<()> {
    vm.define_global(
        "http_prim",
        record! {
            listen => primitive!(2 listen),
            read_chunk => primitive!(1 read_chunk),
            write_response => primitive!(2 write_response)
        },
    )?;
    Ok(())
}

fn main() {
    if let Err(err) = main_() {
        panic!("{}", err)
    }
}

fn main_() -> Result<(), Box<StdError>> {
    let _ = env_logger::init();
    let port = env::args()
        .nth(1)
        .map(|port| port.parse::<i32>().expect("port"))
        .unwrap_or(80);

    let thread = new_vm();

    // First load all the http types so we can refer to them from gluon
    load_types(&thread)?;
    Compiler::new().run_expr::<()>(
        &thread,
        "",
        r#"let _ = import! "examples/http_types.glu" in () "#,
    )?;

    // Load the primitive functions we define in this module
    load(&thread)?;

    // Last we run our `http_server.glu` module which returns a function which starts listening
    // on the port we passed from the command line
    let mut expr = String::new();
    {
        let mut file = File::open("examples/http_server.glu")?;
        file.read_to_string(&mut expr)?;
    }
    let (mut listen, _) =
        Compiler::new().run_expr::<FunctionRef<fn(i32) -> IO<()>>>(&thread, "http_test", &expr)?;

    listen.call(port)?;
    Ok(())
}
<|endoftext|>


<commit_before>use redox::{Box, String, Url};
use redox::{cmp, mem, ptr};
use redox::fs::File;
use redox::io::*;
use redox::ops::DerefMut;
use redox::to_num::ToNum;

use orbital::event::Event;
use orbital::Point;
use orbital::Size;

use self::display::Display;
use self::session::Session;
use self::window::Window;

pub mod display;
pub mod package;
pub mod scheduler;
pub mod session;
pub mod window;

pub static mut session_ptr: *mut Session = 0 as *mut Session;

/// A window resource
pub struct Resource {
    /// The window
    pub window: Box<Window>,
    /// Seek point
    pub seek: usize,
}

impl Resource {
    pub fn dup(&self) -> Option<Box<Resource>> {
        Some(box Resource {
            window: Window::new(self.window.point, self.window.size, self.window.title.clone()),
            seek: self.seek,
        })
    }

    /// Return the url of this resource
    pub fn path(&self) -> Option<String> {
        Some(format!("orbital:///{}/{}/{}/{}/{}",
                         self.window.point.x,
                         self.window.point.y,
                         self.window.size.width,
                         self.window.size.height,
                         self.window.title))
    }

    /// Read data to buffer
    pub fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        //Read events from window
        let mut i = 0;
        while buf.len() - i >= mem::size_of::<Event>() {
            match self.window.poll() {
                Some(event) => {
                    unsafe { ptr::write(buf.as_ptr().offset(i as isize) as *mut Event, event) };
                    i += mem::size_of::<Event>();
                }
                None => break,
            }
        }

        Some(i)
    }

    /// Write to resource
    pub fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let content = &mut self.window.content;

        let size = cmp::min(content.size - self.seek, buf.len());
        unsafe {
            Display::copy_run(buf.as_ptr() as usize,
                              content.offscreen + self.seek,
                              size);
        }
        self.seek += size;

        return Some(size);
    }

    /// Seek
    pub fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        let end = self.window.content.size;

        self.seek = match pos {
            SeekFrom::Start(offset) => cmp::min(end, cmp::max(0, offset)),
            SeekFrom::Current(offset) => cmp::min(end, cmp::max(0, self.seek as isize + offset) as usize),
            SeekFrom::End(offset) => cmp::min(end, cmp::max(0, end as isize + offset) as usize),
        };

        return Some(self.seek);
    }

    /// Sync the resource, should flip
    pub fn sync(&mut self) -> bool {
        self.window.redraw();
        true
    }
}

/// A window scheme
pub struct Scheme {
    pub session: Box<Session>,
    pub next_x: isize,
    pub next_y: isize,
}

impl Scheme {
    pub fn new() -> Box<Scheme> {
        debugln!("- Starting Orbital");
        debugln!("    Console: Press F1");
        debugln!("    Desktop: Press F2");
        let mut ret = box Scheme {
            session: Session::new(),
            next_x: 0,
            next_y: 0,
        };
        unsafe { session_ptr = ret.session.deref_mut() };
        ret
    }

    pub fn open(&mut self, url_str: &str, _: usize) -> Option<Box<Resource>> {
        //window://host/path/path/path is the path type we're working with.
        let url = Url::from_str(url_str);

        let host = url.host();
        if host.is_empty() {
            let path = url.path_parts();
            let mut pointx = match path.get(0) {
                Some(x) => x.to_num_signed(),
                None => 0,
            };
            let mut pointy = match path.get(1) {
                Some(y) => y.to_num_signed(),
                None => 0,
            };
            let size_width = match path.get(2) {
                Some(w) => w.to_num(),
                None => 100,
            };
            let size_height = match path.get(3) {
                Some(h) => h.to_num(),
                None => 100,
            };

            let mut title = match path.get(4) {
                Some(t) => t.clone(),
                None => String::new(),
            };
            for i in 5..path.len() {
                if let Some(t) = path.get(i) {
                    title = title + "/" + t;
                }
            }

            if pointx <= 0 || pointy <= 0 {
                if self.next_x > self.session.display.width as isize - size_width as isize {
                    self.next_x = 0;
                }
                self.next_x += 32;
                pointx = self.next_x;

                if self.next_y > self.session.display.height as isize - size_height as isize {
                    self.next_y = 0;
                }
                self.next_y += 32;
                pointy = self.next_y;
            }

            Some(box Resource {
                window: Window::new(Point::new(pointx, pointy), Size::new(size_width, size_height), title),
                seek: 0,
            })
        } else if host == "launch" {
            let path = url.path();

            unsafe {
                let reenable = scheduler::start_no_ints();

                for package in self.session.packages.iter() {
                    let mut accepted = false;
                    for accept in package.accepts.iter() {
                        if (accept.starts_with('*') && path.ends_with(&accept[1..]))
                        || (accept.ends_with('*') && path.starts_with(&accept[..accept.len() - 1]))
                        {
                            accepted = true;
                            break;
                        }
                    }
                    if accepted {
                        File::exec(&package.binary, &[&path]);
                        break;
                    }
                }

                scheduler::end_no_ints(reenable);
            }

            None
        } else {
            None
        }
    }

    pub fn event(&mut self, event: &Event) {
        unsafe {
            let reenable = scheduler::start_no_ints();

            self.session.event(event);

            scheduler::end_no_ints(reenable);

            self.session.redraw();
        }
    }
}

//TODO: This is a hack and it will go away
#[cold]
#[inline(never)]
#[no_mangle]
pub unsafe extern "C" fn _event(scheme: *mut Scheme, event: *const Event) {
    (*scheme).event(&*event);
}
<commit_msg>Use GetSlice<commit_after>use redox::{Box, String, Url};
use redox::{cmp, mem, ptr};
use redox::fs::File;
use redox::get_slice::GetSlice;
use redox::io::*;
use redox::ops::DerefMut;
use redox::to_num::ToNum;

use orbital::event::Event;
use orbital::Point;
use orbital::Size;

use self::display::Display;
use self::session::Session;
use self::window::Window;

pub mod display;
pub mod package;
pub mod scheduler;
pub mod session;
pub mod window;

pub static mut session_ptr: *mut Session = 0 as *mut Session;

/// A window resource
pub struct Resource {
    /// The window
    pub window: Box<Window>,
    /// Seek point
    pub seek: usize,
}

impl Resource {
    pub fn dup(&self) -> Option<Box<Resource>> {
        Some(box Resource {
            window: Window::new(self.window.point, self.window.size, self.window.title.clone()),
            seek: self.seek,
        })
    }

    /// Return the url of this resource
    pub fn path(&self) -> Option<String> {
        Some(format!("orbital:///{}/{}/{}/{}/{}",
                         self.window.point.x,
                         self.window.point.y,
                         self.window.size.width,
                         self.window.size.height,
                         self.window.title))
    }

    /// Read data to buffer
    pub fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        //Read events from window
        let mut i = 0;
        while buf.len() - i >= mem::size_of::<Event>() {
            match self.window.poll() {
                Some(event) => {
                    unsafe { ptr::write(buf.as_ptr().offset(i as isize) as *mut Event, event) };
                    i += mem::size_of::<Event>();
                }
                None => break,
            }
        }

        Some(i)
    }

    /// Write to resource
    pub fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let content = &mut self.window.content;

        let size = cmp::min(content.size - self.seek, buf.len());
        unsafe {
            Display::copy_run(buf.as_ptr() as usize,
                              content.offscreen + self.seek,
                              size);
        }
        self.seek += size;

        return Some(size);
    }

    /// Seek
    pub fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        let end = self.window.content.size;

        self.seek = match pos {
            SeekFrom::Start(offset) => cmp::min(end, cmp::max(0, offset)),
            SeekFrom::Current(offset) => cmp::min(end, cmp::max(0, self.seek as isize + offset) as usize),
            SeekFrom::End(offset) => cmp::min(end, cmp::max(0, end as isize + offset) as usize),
        };

        return Some(self.seek);
    }

    /// Sync the resource, should flip
    pub fn sync(&mut self) -> bool {
        self.window.redraw();
        true
    }
}

/// A window scheme
pub struct Scheme {
    pub session: Box<Session>,
    pub next_x: isize,
    pub next_y: isize,
}

impl Scheme {
    pub fn new() -> Box<Scheme> {
        debugln!("- Starting Orbital");
        debugln!("    Console: Press F1");
        debugln!("    Desktop: Press F2");
        let mut ret = box Scheme {
            session: Session::new(),
            next_x: 0,
            next_y: 0,
        };
        unsafe { session_ptr = ret.session.deref_mut() };
        ret
    }

    pub fn open(&mut self, url_str: &str, _: usize) -> Option<Box<Resource>> {
        //window://host/path/path/path is the path type we're working with.
        let url = Url::from_str(url_str);

        let host = url.host();
        if host.is_empty() {
            let path = url.path_parts();
            let mut pointx = match path.get(0) {
                Some(x) => x.to_num_signed(),
                None => 0,
            };
            let mut pointy = match path.get(1) {
                Some(y) => y.to_num_signed(),
                None => 0,
            };
            let size_width = match path.get(2) {
                Some(w) => w.to_num(),
                None => 100,
            };
            let size_height = match path.get(3) {
                Some(h) => h.to_num(),
                None => 100,
            };

            let mut title = match path.get(4) {
                Some(t) => t.clone(),
                None => String::new(),
            };
            for i in 5..path.len() {
                if let Some(t) = path.get(i) {
                    title = title + "/" + t;
                }
            }

            if pointx <= 0 || pointy <= 0 {
                if self.next_x > self.session.display.width as isize - size_width as isize {
                    self.next_x = 0;
                }
                self.next_x += 32;
                pointx = self.next_x;

                if self.next_y > self.session.display.height as isize - size_height as isize {
                    self.next_y = 0;
                }
                self.next_y += 32;
                pointy = self.next_y;
            }

            Some(box Resource {
                window: Window::new(Point::new(pointx, pointy), Size::new(size_width, size_height), title),
                seek: 0,
            })
        } else if host == "launch" {
            let path = url.path();

            unsafe {
                let reenable = scheduler::start_no_ints();

                for package in self.session.packages.iter() {
                    let mut accepted = false;
                    for accept in package.accepts.iter() {
                        if (accept.starts_with('*') && path.ends_with(&accept.get_slice(Some(1), None)))
                        || (accept.ends_with('*') && path.starts_with(&accept.get_slice(None, Some(accept.len() - 1))))
                        {
                            accepted = true;
                            break;
                        }
                    }
                    if accepted {
                        File::exec(&package.binary, &[&path]);
                        break;
                    }
                }

                scheduler::end_no_ints(reenable);
            }

            None
        } else {
            None
        }
    }

    pub fn event(&mut self, event: &Event) {
        unsafe {
            let reenable = scheduler::start_no_ints();

            self.session.event(event);

            scheduler::end_no_ints(reenable);

            self.session.redraw();
        }
    }
}

//TODO: This is a hack and it will go away
#[cold]
#[inline(never)]
#[no_mangle]
pub unsafe extern "C" fn _event(scheme: *mut Scheme, event: *const Event) {
    (*scheme).event(&*event);
}
<|endoftext|>


<commit_before>use std::io::{self, ErrorKind};
use std::mem;
use std::vec::Vec;

use {Async, Poll, Future, task};

use io::AsyncRead;

/// A future which can be used to easily read the entire contents of a stream
/// into a vector.
///
/// Created by the [`read_to_end`] function.
///
/// [`read_to_end`]: fn.read_to_end.html
#[derive(Debug)]
pub struct ReadToEnd {
    state: State,
}

#[derive(Debug)]
enum State {
    Reading {
        a: A,
        buf: Vec<u8>,
    },
    Empty,
}

pub fn read_to_end(a: A, buf: Vec<u8>) -> ReadToEnd
    where A: AsyncRead,
{
    ReadToEnd {
        state: State::Reading {
            a,
            buf,
        }
    }
}

struct Guard<'a> { buf: &'a mut Vec<u8>, len: usize }

impl<'a> Drop for Guard<'a> {
    fn drop(&mut self) {
        unsafe { self.buf.set_len(self.len); }
    }
}

// This uses an adaptive system to extend the vector when it fills. We want to
// avoid paying to allocate and zero a huge chunk of memory if the reader only
// has 4 bytes while still making large reads if the reader does have a ton
// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
// time is 4,500 times (!) slower than this if the reader has a very small
// amount of data to return.
//
// Because we're extending the buffer with uninitialized data for trusted
// readers, we need to make sure to truncate that if any of this panics.
fn read_to_end_internal<R: AsyncRead + ?Sized>(r: &mut R, cx: &mut task::Context, buf: &mut Vec<u8>)
    -> Poll<usize, io::Error>
{
    let start_len = buf.len();
    let mut g = Guard { len: buf.len(), buf: buf };
    let ret;
    loop {
        if g.len == g.buf.len() {
            unsafe {
                g.buf.reserve(32);
                let capacity = g.buf.capacity();
                g.buf.set_len(capacity);
                r.initializer().initialize(&mut g.buf[g.len..]);
            }
        }

        match r.poll_read(cx, &mut g.buf[g.len..]) {
            Ok(Async::Ready(0)) => {
                ret = Ok(Async::Ready(g.len - start_len));
                break;
            }
            Ok(Async::Ready(n)) => g.len += n,
            Ok(Async::Pending) => return Ok(Async::Pending),
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => {
                ret = Err(e);
                break;
            }
        }
    }

    ret
}

impl Future for ReadToEnd
    where A: AsyncRead,
{
    type Item = (A, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self, cx: &mut task::Context) -> Poll<(A, Vec<u8>), io::Error> {
        match self.state {
            State::Reading { ref mut a, ref mut buf } => {
                // If we get `Ok`, then we know the stream hit EOF and we're done. If we
                // hit "would block" then all the read data so far is in our buffer, and
                // otherwise we propagate errors
                try_ready!(read_to_end_internal(a, cx, buf));
            },
            State::Empty => panic!("poll ReadToEnd after it's done"),
        }

        match mem::replace(&mut self.state, State::Empty) {
            State::Reading { a, buf } => Ok((a, buf).into()),
            State::Empty => unreachable!(),
        }
    }
}
<commit_msg>Drop unnecessary handling of ErrorKind::Interrupted<commit_after>use std::io;
use std::mem;
use std::vec::Vec;

use {Async, Poll, Future, task};

use io::AsyncRead;

/// A future which can be used to easily read the entire contents of a stream
/// into a vector.
///
/// Created by the [`read_to_end`] function.
///
/// [`read_to_end`]: fn.read_to_end.html
#[derive(Debug)]
pub struct ReadToEnd {
    state: State,
}

#[derive(Debug)]
enum State {
    Reading {
        a: A,
        buf: Vec<u8>,
    },
    Empty,
}

pub fn read_to_end(a: A, buf: Vec<u8>) -> ReadToEnd
    where A: AsyncRead,
{
    ReadToEnd {
        state: State::Reading {
            a,
            buf,
        }
    }
}

struct Guard<'a> { buf: &'a mut Vec<u8>, len: usize }

impl<'a> Drop for Guard<'a> {
    fn drop(&mut self) {
        unsafe { self.buf.set_len(self.len); }
    }
}

// This uses an adaptive system to extend the vector when it fills. We want to
// avoid paying to allocate and zero a huge chunk of memory if the reader only
// has 4 bytes while still making large reads if the reader does have a ton
// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
// time is 4,500 times (!) slower than this if the reader has a very small
// amount of data to return.
//
// Because we're extending the buffer with uninitialized data for trusted
// readers, we need to make sure to truncate that if any of this panics.
fn read_to_end_internal<R: AsyncRead + ?Sized>(r: &mut R, cx: &mut task::Context, buf: &mut Vec<u8>)
    -> Poll<usize, io::Error>
{
    let start_len = buf.len();
    let mut g = Guard { len: buf.len(), buf: buf };
    let ret;
    loop {
        if g.len == g.buf.len() {
            unsafe {
                g.buf.reserve(32);
                let capacity = g.buf.capacity();
                g.buf.set_len(capacity);
                r.initializer().initialize(&mut g.buf[g.len..]);
            }
        }

        match r.poll_read(cx, &mut g.buf[g.len..]) {
            Ok(Async::Ready(0)) => {
                ret = Ok(Async::Ready(g.len - start_len));
                break;
            }
            Ok(Async::Ready(n)) => g.len += n,
            Ok(Async::Pending) => return Ok(Async::Pending),
            Err(e) => {
                ret = Err(e);
                break;
            }
        }
    }

    ret
}

impl Future for ReadToEnd
    where A: AsyncRead,
{
    type Item = (A, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self, cx: &mut task::Context) -> Poll<(A, Vec<u8>), io::Error> {
        match self.state {
            State::Reading { ref mut a, ref mut buf } => {
                // If we get `Ok`, then we know the stream hit EOF and we're done. If we
                // hit "would block" then all the read data so far is in our buffer, and
                // otherwise we propagate errors
                try_ready!(read_to_end_internal(a, cx, buf));
            },
            State::Empty => panic!("poll ReadToEnd after it's done"),
        }

        match mem::replace(&mut self.state, State::Empty) {
            State::Reading { a, buf } => Ok((a, buf).into()),
            State::Empty => unreachable!(),
        }
    }
}
<|endoftext|>


<commit_before>use self::closed01bipolar::Closed01Bipolar;

pub mod closed01bipolar;

// make generic over the x and y types.
trait ActivationFunction {
    fn formula(&self) -> String;
    fn calculate(&self, x: f64) -> Closed01Bipolar<f64>;
}

pub struct Linear;

impl ActivationFunction for Linear {
    fn formula(&self) -> String {
        "y = max(-1.0, min(1.0, x))".to_owned()
    }

    fn calculate(&self, x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_clipped(x)
    }
}

pub struct Sigmoid;

impl ActivationFunction for Sigmoid {
    fn formula(&self) -> String {
        "y = 2.0 / (1.0 + exp(-4.9 * x)) - 1.0".to_owned()
    }

    fn calculate(&self, x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new((2.0 / (1.0 + (-4.9 * x).exp())) - 1.0)
    }
}

pub struct Sine;

impl ActivationFunction for Sine {
    fn formula(&self) -> String {
        "y = sin(2.0 * x)".to_owned()
    }

    fn calculate(&self, x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new(2.0 * x.sin())
    }
}

pub struct Gaussian;

impl ActivationFunction for Gaussian {
    fn formula(&self) -> String {
        "y = 2.0 * exp(-(x * 2.5)^2.0) - 1.0".to_owned()
    }

    fn calculate(&self, x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new(2.0 * (-(x*2.5).powi(2)).exp() - 1.0)
    }
}
<commit_msg>The ActivityFunctions are stateless. Remove &self in the trait.<commit_after>use self::closed01bipolar::Closed01Bipolar;

pub mod closed01bipolar;

pub trait ActivationFunction {
    fn formula() -> &'static str;
    fn calculate(x: f64) -> Closed01Bipolar<f64>;
}

pub struct Linear;
pub struct Sigmoid;
pub struct Sine;
pub struct Gaussian;

impl ActivationFunction for Linear {
    fn formula() -> &'static str {
        "y = max(-1.0, min(1.0, x))"
    }

    fn calculate(x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_clipped(x)
    }
}

impl ActivationFunction for Sigmoid {
    fn formula() -> &'static str {
        "y = 2.0 / (1.0 + exp(-4.9 * x)) - 1.0"
    }

    fn calculate(x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new((2.0 / (1.0 + (-4.9 * x).exp())) - 1.0)
    }
}

impl ActivationFunction for Sine {
    fn formula() -> &'static str {
        "y = sin(2.0 * x)"
    }

    fn calculate(x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new(2.0 * x.sin())
    }
}

impl ActivationFunction for Gaussian {
    fn formula() -> &'static str {
        "y = 2.0 * exp(-(x * 2.5)^2.0) - 1.0"
    }

    fn calculate(x: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new(2.0 * (-(x*2.5).powi(2)).exp() - 1.0)
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Handlers and types for agent's actions.
//!
//! The basic functionality that a GRR agent exposes is called an _action_.
//! Actions are invoked by the server (when running a _flow_), should gather
//! requested information and report back to the server.
//!
//! In RRG each action consists of three components: a request type, a response
//! type and an action handler. Request and response types wrap lower-level
//! Protocol Buffer messages sent by and to the GRR server. Handlers accept one
//! instance of the corresponding request type and send some (zero or more)
//! instances of the corresponding response type.

#[cfg(feature = "action-filesystems")]
#[cfg(target_os = "linux")]
pub mod filesystems;

#[cfg(feature = "action-interfaces")]
#[cfg(target_family = "unix")]
pub mod interfaces;

#[cfg(feature = "action-metadata")]
pub mod metadata;

#[cfg(feature = "action-listdir")]
pub mod listdir;

#[cfg(feature = "action-timeline")]
pub mod timeline;

#[cfg(feature = "action-network")]
pub mod network;

#[cfg(feature = "action-stat")]
pub mod stat;

#[cfg(feature = "action-insttime")]
pub mod insttime;

#[cfg(feature = "action-memsize")]
pub mod memsize;

#[cfg(feature = "action-finder")]
pub mod finder;

use crate::session::{self, Session, Task};

/// Abstraction for action-specific requests.
///
/// Protocol Buffer messages received from the GRR server are not necessarily
/// easy to work with and are hardly idiomatic to Rust. For this reason, actions
/// should define more structured data types to represent their input and should
/// be able to parse raw messages into them.
pub trait Request: Sized {

    /// A type of the corresponding raw proto message.
    type Proto: protobuf::Message + Default;

    /// A method for converting raw proto messages into structured requests.
    fn from_proto(proto: Self::Proto) -> Result<Self, session::ParseError>;
}

/// Abstraction for action-specific responses.
///
/// Like with the [`Request`] type, Protocol Buffer messages sent to the GRR
/// server are very idiomatic to Rust. For this reason, actions should define
/// more structured data types to represent responses and provide a way to
/// convert them into the wire format.
///
/// Note that because of the design flaws in the protocol, actions also need to
/// specify a name of the wrapper RDF class from the Python implementation.
/// Hopefully, one day this issue would be fixed and class names will not leak
/// into the specification.
///
/// [`Request`]: trait.Request.html
pub trait Response: Sized {

    /// A name of the corresponding RDF class.
    const RDF_NAME: Option<&'static str>;

    /// A type of the corresponding raw proto message.
    type Proto: protobuf::Message + Default;

    /// A method for converting structured responses into raw proto messages.
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = protobuf::well_known_types::Empty;

    fn from_proto(_: protobuf::well_known_types::Empty) -> Result<(), session::ParseError> {
        Ok(())
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = protobuf::well_known_types::Empty;

    fn into_proto(self) -> protobuf::well_known_types::Empty {
        protobuf::well_known_types::Empty::new()
    }
}

/// Dispatches `task` to a handler appropriate for the given `action`.
///
/// This method is a mapping between action names (as specified in the protocol)
/// and action handlers (implemented on the agent).
///
/// If the given action is unknown (or not yet implemented), this function will
/// return an error.
pub fn dispatch<'s, S>(action: &str, task: Task<'s, S>) -> session::Result<()>
where
    S: Session,
{
    match action {
        #[cfg(feature = "action-metadata")]
        "GetClientInfo" => task.execute(self::metadata::handle),

        #[cfg(feature = "action-listdir")]
        "ListDirectory" => task.execute(self::listdir::handle),

        #[cfg(feature = "action-timeline")]
        "Timeline" => task.execute(self::timeline::handle),

        #[cfg(feature = "action-network")]
        "ListNetworkConnections" => task.execute(self::network::handle),

        #[cfg(feature = "action-stat")]
        "GetFileStat" => task.execute(self::stat::handle),

        #[cfg(feature = "action-insttime")]
        "GetInstallDate" => task.execute(self::insttime::handle),

        #[cfg(feature = "action-interfaces")]
        #[cfg(target_family = "unix")]
        "EnumerateInterfaces" => task.execute(self::interfaces::handle),

        #[cfg(feature = "action-filesystems")]
        #[cfg(target_os = "linux")]
        "EnumerateFilesystems" => task.execute(self::filesystems::handle),

        #[cfg(feature = "action-memsize")]
        "GetMemorySize" => task.execute(self::memsize::handle),

        action => return Err(session::Error::Dispatch(String::from(action))),
    }
}

// TODO(panhania@): Remove all usages of the `Request` trait and replace it with
// `Args`.
pub trait Args: Sized {
    /// Low-level Protocol Buffers type representing the action arguments.
    type Proto: protobuf::Message + Default;

    /// Converts a low-level type to a structured request arguments.
    fn from_proto(proto: Self::Proto) -> Result<Self, ParseArgsError>;
}

pub trait Item: Sized {
    /// Low-level Protocol Buffers type representing the action results.
    type Proto: protobuf::Message + Default;

    /// A name of the corresponding RDF class in GRR.
    const RDF_NAME: &'static str;

    /// Converts an action result ot its low-level representation.
    fn into_proto(self) -> Self::Proto;
}

/// The error type for cases when action argument parsing fails.
#[derive(Debug)]
pub struct ParseArgsError {
    /// A corresponding [`ParseArgsErrorKind`] of this error.
    kind: ParseArgsErrorKind,
    /// A detailed payload associated with the error.
    error: Box<dyn std::error::Error + Send + Sync>,
}

impl ParseArgsError {

    /// Creates a new error instance caused by some invalid field error.
    fn invalid_field<E>(error: E) -> ParseArgsError
    where
        E: std::error::Error + Send + Sync + 'static,
    {
        ParseArgsError {
            kind: ParseArgsErrorKind::InvalidField,
            error: Box::new(error),
        }
    }
}

/// Kinds of errors that can happen when parsing action arguments.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ParseArgsErrorKind {
    /// The serialized message with arguments was impossible to deserialize.
    InvalidProto,
    // TODO(panhania@): Augment with field name.
    /// One of the fields of the arguments struct is invalid.
    InvalidField,
}

impl ParseArgsErrorKind {

    fn as_str(&self) -> &'static str {
        use ParseArgsErrorKind::*;

        match *self {
            InvalidProto => "invalid serialized protobuf message",
            InvalidField => "invalid argument field",
        }
    }
}

impl std::fmt::Display for ParseArgsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(fmt, "{}: {}", self.kind.as_str(), self.error)
    }
}

impl std::error::Error for ParseArgsError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.error.source()
    }
}

impl From<protobuf::ProtobufError> for ParseArgsError {

    fn from(error: protobuf::ProtobufError) -> Self {
        ParseArgsError {
            kind: ParseArgsErrorKind::InvalidProto,
            error: Box::new(error),
        }
    }
}
<commit_msg>Provide empty-message impls for new action traits.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Handlers and types for agent's actions.
//!
//! The basic functionality that a GRR agent exposes is called an _action_.
//! Actions are invoked by the server (when running a _flow_), should gather
//! requested information and report back to the server.
//!
//! In RRG each action consists of three components: a request type, a response
//! type and an action handler. Request and response types wrap lower-level
//! Protocol Buffer messages sent by and to the GRR server. Handlers accept one
//! instance of the corresponding request type and send some (zero or more)
//! instances of the corresponding response type.

#[cfg(feature = "action-filesystems")]
#[cfg(target_os = "linux")]
pub mod filesystems;

#[cfg(feature = "action-interfaces")]
#[cfg(target_family = "unix")]
pub mod interfaces;

#[cfg(feature = "action-metadata")]
pub mod metadata;

#[cfg(feature = "action-listdir")]
pub mod listdir;

#[cfg(feature = "action-timeline")]
pub mod timeline;

#[cfg(feature = "action-network")]
pub mod network;

#[cfg(feature = "action-stat")]
pub mod stat;

#[cfg(feature = "action-insttime")]
pub mod insttime;

#[cfg(feature = "action-memsize")]
pub mod memsize;

#[cfg(feature = "action-finder")]
pub mod finder;

use crate::session::{self, Session, Task};

/// Abstraction for action-specific requests.
///
/// Protocol Buffer messages received from the GRR server are not necessarily
/// easy to work with and are hardly idiomatic to Rust. For this reason, actions
/// should define more structured data types to represent their input and should
/// be able to parse raw messages into them.
pub trait Request: Sized {

    /// A type of the corresponding raw proto message.
    type Proto: protobuf::Message + Default;

    /// A method for converting raw proto messages into structured requests.
    fn from_proto(proto: Self::Proto) -> Result<Self, session::ParseError>;
}

/// Abstraction for action-specific responses.
///
/// Like with the [`Request`] type, Protocol Buffer messages sent to the GRR
/// server are very idiomatic to Rust. For this reason, actions should define
/// more structured data types to represent responses and provide a way to
/// convert them into the wire format.
///
/// Note that because of the design flaws in the protocol, actions also need to
/// specify a name of the wrapper RDF class from the Python implementation.
/// Hopefully, one day this issue would be fixed and class names will not leak
/// into the specification.
///
/// [`Request`]: trait.Request.html
pub trait Response: Sized {

    /// A name of the corresponding RDF class.
    const RDF_NAME: Option<&'static str>;

    /// A type of the corresponding raw proto message.
    type Proto: protobuf::Message + Default;

    /// A method for converting structured responses into raw proto messages.
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = protobuf::well_known_types::Empty;

    fn from_proto(_: protobuf::well_known_types::Empty) -> Result<(), session::ParseError> {
        Ok(())
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = protobuf::well_known_types::Empty;

    fn into_proto(self) -> protobuf::well_known_types::Empty {
        protobuf::well_known_types::Empty::new()
    }
}

/// Dispatches `task` to a handler appropriate for the given `action`.
///
/// This method is a mapping between action names (as specified in the protocol)
/// and action handlers (implemented on the agent).
///
/// If the given action is unknown (or not yet implemented), this function will
/// return an error.
pub fn dispatch<'s, S>(action: &str, task: Task<'s, S>) -> session::Result<()>
where
    S: Session,
{
    match action {
        #[cfg(feature = "action-metadata")]
        "GetClientInfo" => task.execute(self::metadata::handle),

        #[cfg(feature = "action-listdir")]
        "ListDirectory" => task.execute(self::listdir::handle),

        #[cfg(feature = "action-timeline")]
        "Timeline" => task.execute(self::timeline::handle),

        #[cfg(feature = "action-network")]
        "ListNetworkConnections" => task.execute(self::network::handle),

        #[cfg(feature = "action-stat")]
        "GetFileStat" => task.execute(self::stat::handle),

        #[cfg(feature = "action-insttime")]
        "GetInstallDate" => task.execute(self::insttime::handle),

        #[cfg(feature = "action-interfaces")]
        #[cfg(target_family = "unix")]
        "EnumerateInterfaces" => task.execute(self::interfaces::handle),

        #[cfg(feature = "action-filesystems")]
        #[cfg(target_os = "linux")]
        "EnumerateFilesystems" => task.execute(self::filesystems::handle),

        #[cfg(feature = "action-memsize")]
        "GetMemorySize" => task.execute(self::memsize::handle),

        action => return Err(session::Error::Dispatch(String::from(action))),
    }
}

// TODO(panhania@): Remove all usages of the `Request` trait and replace it with
// `Args`.
pub trait Args: Sized {
    /// Low-level Protocol Buffers type representing the action arguments.
    type Proto: protobuf::Message + Default;

    /// Converts a low-level type to a structured request arguments.
    fn from_proto(proto: Self::Proto) -> Result<Self, ParseArgsError>;
}

impl Args for () {

    type Proto = protobuf::well_known_types::Empty;

    fn from_proto(_: protobuf::well_known_types::Empty) -> Result<(), ParseArgsError> {
        Ok(())
    }
}

pub trait Item: Sized {
    /// Low-level Protocol Buffers type representing the action results.
    type Proto: protobuf::Message + Default;

    /// A name of the corresponding RDF class in GRR.
    const RDF_NAME: &'static str;

    /// Converts an action result ot its low-level representation.
    fn into_proto(self) -> Self::Proto;
}

impl Item for () {

    // This implementation is intended to be used only in tests and we do not
    // really care about the `RDF_NAME` field there. And since GRR does not have
    // any RDF wrapper for empty type (except maybe `EmptyFlowArgs`, but this is
    // semantically different), we just leave it blank.
    const RDF_NAME: &'static str = "";

    type Proto = protobuf::well_known_types::Empty;

    fn into_proto(self) -> protobuf::well_known_types::Empty {
        protobuf::well_known_types::Empty::new()
    }
}

/// The error type for cases when action argument parsing fails.
#[derive(Debug)]
pub struct ParseArgsError {
    /// A corresponding [`ParseArgsErrorKind`] of this error.
    kind: ParseArgsErrorKind,
    /// A detailed payload associated with the error.
    error: Box<dyn std::error::Error + Send + Sync>,
}

impl ParseArgsError {

    /// Creates a new error instance caused by some invalid field error.
    fn invalid_field<E>(error: E) -> ParseArgsError
    where
        E: std::error::Error + Send + Sync + 'static,
    {
        ParseArgsError {
            kind: ParseArgsErrorKind::InvalidField,
            error: Box::new(error),
        }
    }
}

/// Kinds of errors that can happen when parsing action arguments.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ParseArgsErrorKind {
    /// The serialized message with arguments was impossible to deserialize.
    InvalidProto,
    // TODO(panhania@): Augment with field name.
    /// One of the fields of the arguments struct is invalid.
    InvalidField,
}

impl ParseArgsErrorKind {

    fn as_str(&self) -> &'static str {
        use ParseArgsErrorKind::*;

        match *self {
            InvalidProto => "invalid serialized protobuf message",
            InvalidField => "invalid argument field",
        }
    }
}

impl std::fmt::Display for ParseArgsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(fmt, "{}: {}", self.kind.as_str(), self.error)
    }
}

impl std::error::Error for ParseArgsError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.error.source()
    }
}

impl From<protobuf::ProtobufError> for ParseArgsError {

    fn from(error: protobuf::ProtobufError) -> Self {
        ParseArgsError {
            kind: ParseArgsErrorKind::InvalidProto,
            error: Box::new(error),
        }
    }
}
<|endoftext|>