<commit_before>use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
use lmd_ghost::LmdGhost;
use slot_clock::SlotClock;
use slot_clock::TestingSlotClock;
use state_processing::per_slot_processing;
use std::marker::PhantomData;
use std::sync::Arc;
use store::MemoryStore;
use store::Store;
use tree_hash::{SignedRoot, TreeHash};
use types::{
    test_utils::TestingBeaconStateBuilder, AggregateSignature, Attestation,
    AttestationDataAndCustodyBit, BeaconBlock, BeaconState, Bitfield, ChainSpec, Domain, EthSpec,
    Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
};

/// Indicates how the `BeaconChainHarness` should produce blocks.
#[derive(Clone, Copy, Debug)]
pub enum BlockStrategy {
    /// Produce blocks upon the canonical head (normal case).
    OnCanonicalHead,
    /// Ignore the canonical head and produce blocks upon the block at the given slot.
    ///
    /// Useful for simulating forks.
    ForkCanonicalChainAt(Slot),
}

/// Indicates how the `BeaconChainHarness` should produce attestations.
#[derive(Clone, Copy, Debug)]
pub enum AttestationStrategy {
    /// All validators attest to whichever block the `BeaconChainHarness` has produced.
    AllValidators,
}

/// Used to make the `BeaconChainHarness` generic over some types.
pub struct CommonTypes<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    _phantom_l: PhantomData<L>,
    _phantom_e: PhantomData<E>,
}

impl<L, E> BeaconChainTypes for CommonTypes<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    type Store = MemoryStore;
    type SlotClock = TestingSlotClock;
    type LmdGhost = L;
    type EthSpec = E;
}

/// A testing harness which can instantiate a `BeaconChain` and populate it with blocks and
/// attestations.
pub struct BeaconChainHarness<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    chain: BeaconChain<CommonTypes<L, E>>,
    keypairs: Vec<Keypair>,
    spec: ChainSpec,
}

impl<L, E> BeaconChainHarness<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    /// Instantiate a new harness with `validator_count` initial validators.
    pub fn new(validator_count: usize) -> Self {
        let spec = E::default_spec();

        let store = Arc::new(MemoryStore::open());

        let state_builder =
            TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
        let (genesis_state, keypairs) = state_builder.build();

        let mut genesis_block = BeaconBlock::empty(&spec);
        genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());

        // Slot clock
        let slot_clock = TestingSlotClock::new(
            spec.genesis_slot,
            genesis_state.genesis_time,
            spec.seconds_per_slot,
        );

        let chain = BeaconChain::from_genesis(
            store,
            slot_clock,
            genesis_state,
            genesis_block,
            spec.clone(),
        )
        .expect("Terminate if beacon chain generation fails");

        Self {
            chain,
            keypairs,
            spec,
        }
    }

    /// Advance the slot of the `BeaconChain`.
    ///
    /// Does not produce blocks or attestations.
    pub fn advance_slot(&self) {
        self.chain.slot_clock.advance_slot();
        self.chain.catchup_state().expect("should catchup state");
    }

    /// Extend the `BeaconChain` with some blocks and attestations.
    ///
    /// Chain will be extended by `num_blocks` blocks.
    ///
    /// The `block_strategy` dictates where the new blocks will be placed.
    ///
    /// The `attestation_strategy` dictates which validators will attest to the newly created
    /// blocks.
    pub fn extend_chain(
        &self,
        num_blocks: usize,
        block_strategy: BlockStrategy,
        attestation_strategy: AttestationStrategy,
    ) {
        // Get an initial state to build the block upon, based on the build strategy.
        let mut state = match block_strategy {
            BlockStrategy::OnCanonicalHead => self.chain.current_state().clone(),
            BlockStrategy::ForkCanonicalChainAt(fork_slot) => {
                let state_root = self
                    .chain
                    .rev_iter_state_roots(self.chain.head().beacon_state.slot - 1)
                    .find(|(_hash, slot)| *slot == fork_slot)
                    .map(|(hash, _slot)| hash)
                    .expect("could not find state root for fork");

                self.chain
                    .store
                    .get(&state_root)
                    .expect("should read db")
                    .expect("should find state root")
            }
        };

        // Get an initial slot to build upon, based on the build strategy.
        let mut slot = match block_strategy {
            BlockStrategy::OnCanonicalHead => self.chain.read_slot_clock().unwrap(),
            BlockStrategy::ForkCanonicalChainAt(slot) => slot,
        };

        for _ in 0..num_blocks {
            while self.chain.read_slot_clock().expect("should have a slot") < slot {
                self.advance_slot();
            }

            let (block, new_state) = self.build_block(state.clone(), slot, block_strategy);

            let outcome = self
                .chain
                .process_block(block)
                .expect("should not error during block processing");

            if let BlockProcessingOutcome::Processed { block_root } = outcome {
                self.add_attestations_to_op_pool(
                    attestation_strategy,
                    &new_state,
                    block_root,
                    slot,
                );
            } else {
                panic!("block should be successfully processed");
            }

            state = new_state;
            slot += 1;
        }
    }

    /// Returns a newly created block, signed by the proposer for the given slot.
    fn build_block(
        &self,
        mut state: BeaconState<E>,
        slot: Slot,
        block_strategy: BlockStrategy,
    ) -> (BeaconBlock, BeaconState<E>) {
        if slot < state.slot {
            panic!("produce slot cannot be prior to the state slot");
        }

        while state.slot < slot {
            per_slot_processing(&mut state, &self.spec)
                .expect("should be able to advance state to slot");
        }

        state.build_all_caches(&self.spec).unwrap();

        let proposer_index = match block_strategy {
            BlockStrategy::OnCanonicalHead => self
                .chain
                .block_proposer(slot)
                .expect("should get block proposer from chain"),
            _ => state
                .get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.spec)
                .expect("should get block proposer from state"),
        };

        let sk = &self.keypairs[proposer_index].sk;
        let fork = &state.fork.clone();

        let randao_reveal = {
            let epoch = slot.epoch(E::slots_per_epoch());
            let message = epoch.tree_hash_root();
            let domain = self.spec.get_domain(epoch, Domain::Randao, fork);
            Signature::new(&message, domain, sk)
        };

        let (mut block, state) = self
            .chain
            .produce_block_on_state(state, slot, randao_reveal)
            .expect("should produce block");

        block.signature = {
            let message = block.signed_root();
            let epoch = block.slot.epoch(E::slots_per_epoch());
            let domain = self.spec.get_domain(epoch, Domain::BeaconProposer, fork);
            Signature::new(&message, domain, sk)
        };

        (block, state)
    }

    /// Adds attestations to the `BeaconChain` operations pool to be included in future blocks.
    ///
    /// The `attestation_strategy` dictates which validators should attest.
    fn add_attestations_to_op_pool(
        &self,
        attestation_strategy: AttestationStrategy,
        state: &BeaconState<E>,
        head_block_root: Hash256,
        head_block_slot: Slot,
    ) {
        let spec = &self.spec;
        let fork = &state.fork;

        let attesting_validators: Vec<usize> = match attestation_strategy {
            AttestationStrategy::AllValidators => (0..self.keypairs.len()).collect(),
        };

        state
            .get_crosslink_committees_at_slot(state.slot)
            .expect("should get committees")
            .iter()
            .for_each(|cc| {
                let committee_size = cc.committee.len();

                for (i, validator_index) in cc.committee.iter().enumerate() {
                    // Note: searching this array is worst-case `O(n)`. A hashset could be a better
                    // alternative.
                    if attesting_validators.contains(validator_index) {
                        let data = self
                            .chain
                            .produce_attestation_data_for_block(
                                cc.shard,
                                head_block_root,
                                head_block_slot,
                                state,
                            )
                            .expect("should produce attestation data");

                        let mut aggregation_bitfield = Bitfield::new();
                        aggregation_bitfield.set(i, true);
                        aggregation_bitfield.set(committee_size, false);

                        let mut custody_bitfield = Bitfield::new();
                        custody_bitfield.set(committee_size, false);

                        let signature = {
                            let message = AttestationDataAndCustodyBit {
                                data: data.clone(),
                                custody_bit: false,
                            }
                            .tree_hash_root();

                            let domain =
                                spec.get_domain(data.target_epoch, Domain::Attestation, fork);

                            let mut agg_sig = AggregateSignature::new();
                            agg_sig.add(&Signature::new(
                                &message,
                                domain,
                                self.get_sk(*validator_index),
                            ));

                            agg_sig
                        };

                        let attestation = Attestation {
                            aggregation_bitfield,
                            data,
                            custody_bitfield,
                            signature,
                        };

                        self.chain
                            .process_attestation(attestation)
                            .expect("should process attestation");
                    }
                }
            });
    }

    /// Returns the secret key for the given validator index.
    fn get_sk(&self, validator_index: usize) -> &SecretKey {
        &self.keypairs[validator_index].sk
    }
}

#[cfg(test)]
// #[cfg(not(debug_assertions))]
mod test {
    use super::*;
    use lmd_ghost::ThreadSafeReducedTree;
    use types::MinimalEthSpec;

    pub const VALIDATOR_COUNT: usize = 16;

    fn get_harness(
        validator_count: usize,
    ) -> BeaconChainHarness<ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>, MinimalEthSpec>
    {
        let harness = BeaconChainHarness::new(validator_count);

        // Move past the zero slot.
        harness.advance_slot();

        harness
    }

    #[test]
    fn can_finalize() {
        let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;

        let harness = get_harness(VALIDATOR_COUNT);

        harness.extend_chain(
            num_blocks_produced as usize,
            BlockStrategy::OnCanonicalHead,
            AttestationStrategy::AllValidators,
        );

        let state = &harness.chain.head().beacon_state;

        assert_eq!(
            state.slot, num_blocks_produced,
            "head should be at the current slot"
        );
        assert_eq!(
            state.current_epoch(),
            num_blocks_produced / MinimalEthSpec::slots_per_epoch(),
            "head should be at the expected epoch"
        );
        assert_eq!(
            state.current_justified_epoch,
            state.current_epoch() - 1,
            "the head should be justified one behind the current epoch"
        );
        assert_eq!(
            state.finalized_epoch,
            state.current_epoch() - 2,
            "the head should be finalized two behind the current epoch"
        );
    }
}
<commit_msg>Add additional chain tests<commit_after>use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
use lmd_ghost::LmdGhost;
use slot_clock::SlotClock;
use slot_clock::TestingSlotClock;
use state_processing::per_slot_processing;
use std::marker::PhantomData;
use std::sync::Arc;
use store::MemoryStore;
use store::Store;
use tree_hash::{SignedRoot, TreeHash};
use types::{
    test_utils::TestingBeaconStateBuilder, AggregateSignature, Attestation,
    AttestationDataAndCustodyBit, BeaconBlock, BeaconState, Bitfield, ChainSpec, Domain, EthSpec,
    Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
};

/// Indicates how the `BeaconChainHarness` should produce blocks.
#[derive(Clone, Copy, Debug)]
pub enum BlockStrategy {
    /// Produce blocks upon the canonical head (normal case).
    OnCanonicalHead,
    /// Ignore the canonical head and produce blocks upon the block at the given slot.
    ///
    /// Useful for simulating forks.
    ForkCanonicalChainAt(Slot),
}

/// Indicates how the `BeaconChainHarness` should produce attestations.
#[derive(Clone, Debug)]
pub enum AttestationStrategy {
    /// All validators attest to whichever block the `BeaconChainHarness` has produced.
    AllValidators,
    /// Only the given validators should attest. All others should fail to produce attestations.
    SomeValidators(Vec<usize>),
}

/// Used to make the `BeaconChainHarness` generic over some types.
pub struct CommonTypes<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    _phantom_l: PhantomData<L>,
    _phantom_e: PhantomData<E>,
}

impl<L, E> BeaconChainTypes for CommonTypes<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    type Store = MemoryStore;
    type SlotClock = TestingSlotClock;
    type LmdGhost = L;
    type EthSpec = E;
}

/// A testing harness which can instantiate a `BeaconChain` and populate it with blocks and
/// attestations.
pub struct BeaconChainHarness<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    chain: BeaconChain<CommonTypes<L, E>>,
    keypairs: Vec<Keypair>,
    spec: ChainSpec,
}

impl<L, E> BeaconChainHarness<L, E>
where
    L: LmdGhost<MemoryStore, E>,
    E: EthSpec,
{
    /// Instantiate a new harness with `validator_count` initial validators.
    pub fn new(validator_count: usize) -> Self {
        let spec = E::default_spec();

        let store = Arc::new(MemoryStore::open());

        let state_builder =
            TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
        let (genesis_state, keypairs) = state_builder.build();

        let mut genesis_block = BeaconBlock::empty(&spec);
        genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());

        // Slot clock
        let slot_clock = TestingSlotClock::new(
            spec.genesis_slot,
            genesis_state.genesis_time,
            spec.seconds_per_slot,
        );

        let chain = BeaconChain::from_genesis(
            store,
            slot_clock,
            genesis_state,
            genesis_block,
            spec.clone(),
        )
        .expect("Terminate if beacon chain generation fails");

        Self {
            chain,
            keypairs,
            spec,
        }
    }

    /// Advance the slot of the `BeaconChain`.
    ///
    /// Does not produce blocks or attestations.
    pub fn advance_slot(&self) {
        self.chain.slot_clock.advance_slot();
        self.chain.catchup_state().expect("should catchup state");
    }

    /// Extend the `BeaconChain` with some blocks and attestations.
    ///
    /// Chain will be extended by `num_blocks` blocks.
    ///
    /// The `block_strategy` dictates where the new blocks will be placed.
    ///
    /// The `attestation_strategy` dictates which validators will attest to the newly created
    /// blocks.
    pub fn extend_chain(
        &self,
        num_blocks: usize,
        block_strategy: BlockStrategy,
        attestation_strategy: AttestationStrategy,
    ) {
        // Get an initial state to build the block upon, based on the build strategy.
        let mut state = match block_strategy {
            BlockStrategy::OnCanonicalHead => self.chain.current_state().clone(),
            BlockStrategy::ForkCanonicalChainAt(fork_slot) => {
                let state_root = self
                    .chain
                    .rev_iter_state_roots(self.chain.head().beacon_state.slot - 1)
                    .find(|(_hash, slot)| *slot == fork_slot)
                    .map(|(hash, _slot)| hash)
                    .expect("could not find state root for fork");

                self.chain
                    .store
                    .get(&state_root)
                    .expect("should read db")
                    .expect("should find state root")
            }
        };

        // Get an initial slot to build upon, based on the build strategy.
        let mut slot = match block_strategy {
            BlockStrategy::OnCanonicalHead => self.chain.read_slot_clock().unwrap(),
            BlockStrategy::ForkCanonicalChainAt(slot) => slot,
        };

        for _ in 0..num_blocks {
            while self.chain.read_slot_clock().expect("should have a slot") < slot {
                self.advance_slot();
            }

            let (block, new_state) = self.build_block(state.clone(), slot, block_strategy);

            let outcome = self
                .chain
                .process_block(block)
                .expect("should not error during block processing");

            if let BlockProcessingOutcome::Processed { block_root } = outcome {
                self.add_attestations_to_op_pool(
                    &attestation_strategy,
                    &new_state,
                    block_root,
                    slot,
                );
            } else {
                panic!("block should be successfully processed");
            }

            state = new_state;
            slot += 1;
        }
    }

    /// Returns a newly created block, signed by the proposer for the given slot.
    fn build_block(
        &self,
        mut state: BeaconState<E>,
        slot: Slot,
        block_strategy: BlockStrategy,
    ) -> (BeaconBlock, BeaconState<E>) {
        if slot < state.slot {
            panic!("produce slot cannot be prior to the state slot");
        }

        while state.slot < slot {
            per_slot_processing(&mut state, &self.spec)
                .expect("should be able to advance state to slot");
        }

        state.build_all_caches(&self.spec).unwrap();

        let proposer_index = match block_strategy {
            BlockStrategy::OnCanonicalHead => self
                .chain
                .block_proposer(slot)
                .expect("should get block proposer from chain"),
            _ => state
                .get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.spec)
                .expect("should get block proposer from state"),
        };

        let sk = &self.keypairs[proposer_index].sk;
        let fork = &state.fork.clone();

        let randao_reveal = {
            let epoch = slot.epoch(E::slots_per_epoch());
            let message = epoch.tree_hash_root();
            let domain = self.spec.get_domain(epoch, Domain::Randao, fork);
            Signature::new(&message, domain, sk)
        };

        let (mut block, state) = self
            .chain
            .produce_block_on_state(state, slot, randao_reveal)
            .expect("should produce block");

        block.signature = {
            let message = block.signed_root();
            let epoch = block.slot.epoch(E::slots_per_epoch());
            let domain = self.spec.get_domain(epoch, Domain::BeaconProposer, fork);
            Signature::new(&message, domain, sk)
        };

        (block, state)
    }

    /// Adds attestations to the `BeaconChain` operations pool to be included in future blocks.
    ///
    /// The `attestation_strategy` dictates which validators should attest.
    fn add_attestations_to_op_pool(
        &self,
        attestation_strategy: &AttestationStrategy,
        state: &BeaconState<E>,
        head_block_root: Hash256,
        head_block_slot: Slot,
    ) {
        let spec = &self.spec;
        let fork = &state.fork;

        let attesting_validators: Vec<usize> = match attestation_strategy {
            AttestationStrategy::AllValidators => (0..self.keypairs.len()).collect(),
            AttestationStrategy::SomeValidators(vec) => vec.clone(),
        };

        state
            .get_crosslink_committees_at_slot(state.slot)
            .expect("should get committees")
            .iter()
            .for_each(|cc| {
                let committee_size = cc.committee.len();

                for (i, validator_index) in cc.committee.iter().enumerate() {
                    // Note: searching this array is worst-case `O(n)`. A hashset could be a better
                    // alternative.
                    if attesting_validators.contains(validator_index) {
                        let data = self
                            .chain
                            .produce_attestation_data_for_block(
                                cc.shard,
                                head_block_root,
                                head_block_slot,
                                state,
                            )
                            .expect("should produce attestation data");

                        let mut aggregation_bitfield = Bitfield::new();
                        aggregation_bitfield.set(i, true);
                        aggregation_bitfield.set(committee_size, false);

                        let mut custody_bitfield = Bitfield::new();
                        custody_bitfield.set(committee_size, false);

                        let signature = {
                            let message = AttestationDataAndCustodyBit {
                                data: data.clone(),
                                custody_bit: false,
                            }
                            .tree_hash_root();

                            let domain =
                                spec.get_domain(data.target_epoch, Domain::Attestation, fork);

                            let mut agg_sig = AggregateSignature::new();
                            agg_sig.add(&Signature::new(
                                &message,
                                domain,
                                self.get_sk(*validator_index),
                            ));

                            agg_sig
                        };

                        let attestation = Attestation {
                            aggregation_bitfield,
                            data,
                            custody_bitfield,
                            signature,
                        };

                        self.chain
                            .process_attestation(attestation)
                            .expect("should process attestation");
                    }
                }
            });
    }

    /// Returns the secret key for the given validator index.
    fn get_sk(&self, validator_index: usize) -> &SecretKey {
        &self.keypairs[validator_index].sk
    }
}

#[cfg(test)]
// #[cfg(not(debug_assertions))]
mod test {
    use super::*;
    use lmd_ghost::ThreadSafeReducedTree;
    use types::MinimalEthSpec;

    // Should ideally be divisible by 3.
    pub const VALIDATOR_COUNT: usize = 24;

    fn get_harness(
        validator_count: usize,
    ) -> BeaconChainHarness<ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>, MinimalEthSpec>
    {
        let harness = BeaconChainHarness::new(validator_count);

        // Move past the zero slot.
        harness.advance_slot();

        harness
    }

    #[test]
    fn finalizes_with_full_participation() {
        let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;

        let harness = get_harness(VALIDATOR_COUNT);

        harness.extend_chain(
            num_blocks_produced as usize,
            BlockStrategy::OnCanonicalHead,
            AttestationStrategy::AllValidators,
        );

        let state = &harness.chain.head().beacon_state;

        assert_eq!(
            state.slot, num_blocks_produced,
            "head should be at the current slot"
        );
        assert_eq!(
            state.current_epoch(),
            num_blocks_produced / MinimalEthSpec::slots_per_epoch(),
            "head should be at the expected epoch"
        );
        assert_eq!(
            state.current_justified_epoch,
            state.current_epoch() - 1,
            "the head should be justified one behind the current epoch"
        );
        assert_eq!(
            state.finalized_epoch,
            state.current_epoch() - 2,
            "the head should be finalized two behind the current epoch"
        );
    }

    #[test]
    fn finalizes_with_two_thirds_participation() {
        let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;

        let harness = get_harness(VALIDATOR_COUNT);

        let two_thirds = (VALIDATOR_COUNT / 3) * 2;
        let attesters = (0..two_thirds).collect();

        harness.extend_chain(
            num_blocks_produced as usize,
            BlockStrategy::OnCanonicalHead,
            AttestationStrategy::SomeValidators(attesters),
        );

        let state = &harness.chain.head().beacon_state;

        assert_eq!(
            state.slot, num_blocks_produced,
            "head should be at the current slot"
        );
        assert_eq!(
            state.current_epoch(),
            num_blocks_produced / MinimalEthSpec::slots_per_epoch(),
            "head should be at the expected epoch"
        );

        // Note: the 2/3rds tests are not justifying the immediately prior epochs because the
        // `MIN_ATTESTATION_INCLUSION_DELAY` is preventing an adequate number of attestations being
        // included in blocks during that epoch.

        assert_eq!(
            state.current_justified_epoch,
            state.current_epoch() - 2,
            "the head should be justified two behind the current epoch"
        );
        assert_eq!(
            state.finalized_epoch,
            state.current_epoch() - 4,
            "the head should be finalized three behind the current epoch"
        );
    }

    #[test]
    fn does_not_finalize_with_less_than_two_thirds_participation() {
        let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;

        let harness = get_harness(VALIDATOR_COUNT);

        let two_thirds = (VALIDATOR_COUNT / 3) * 2;
        let less_than_two_thirds = two_thirds - 1;
        let attesters = (0..less_than_two_thirds).collect();

        harness.extend_chain(
            num_blocks_produced as usize,
            BlockStrategy::OnCanonicalHead,
            AttestationStrategy::SomeValidators(attesters),
        );

        let state = &harness.chain.head().beacon_state;

        assert_eq!(
            state.slot, num_blocks_produced,
            "head should be at the current slot"
        );
        assert_eq!(
            state.current_epoch(),
            num_blocks_produced / MinimalEthSpec::slots_per_epoch(),
            "head should be at the expected epoch"
        );
        assert_eq!(
            state.current_justified_epoch, 0,
            "no epoch should have been justified"
        );
        assert_eq!(
            state.finalized_epoch, 0,
            "no epoch should have been finalized"
        );
    }

    #[test]
    fn does_not_finalize_without_attestation() {
        let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;

        let harness = get_harness(VALIDATOR_COUNT);

        harness.extend_chain(
            num_blocks_produced as usize,
            BlockStrategy::OnCanonicalHead,
            AttestationStrategy::SomeValidators(vec![]),
        );

        let state = &harness.chain.head().beacon_state;

        assert_eq!(
            state.slot, num_blocks_produced,
            "head should be at the current slot"
        );
        assert_eq!(
            state.current_epoch(),
            num_blocks_produced / MinimalEthSpec::slots_per_epoch(),
            "head should be at the expected epoch"
        );
        assert_eq!(
            state.current_justified_epoch, 0,
            "no epoch should have been justified"
        );
        assert_eq!(
            state.finalized_epoch, 0,
            "no epoch should have been finalized"
        );
    }
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

use crate::block_enc::instr::*;
use crate::block_enc::*;
use crate::iced_error::IcedError;
use core::cell::RefCell;
use core::cmp;

pub(crate) struct CallInstr {
	bitness: u8,
	instruction: Instruction,
	target_instr: TargetInstr,
	orig_instruction_size: u8,
	pointer_data: Option<Rc<RefCell<BlockData>>>,
	use_orig_instruction: bool,
}

impl CallInstr {
	pub(super) fn new(block_encoder: &mut BlockEncInt, base: &mut InstrBase, instruction: &Instruction) -> Self {
		let mut instr_copy = *instruction;
		instr_copy.set_near_branch64(0);
		let orig_instruction_size = block_encoder.get_instruction_size(&instr_copy, 0) as u8;
		let mut use_orig_instruction = false;
		base.size = if !block_encoder.fix_branches() {
			use_orig_instruction = true;
			base.done = true;
			orig_instruction_size
		} else if block_encoder.bitness() == 64 {
			// Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes.
			cmp::max(orig_instruction_size, InstrUtils::CALL_OR_JMP_POINTER_DATA_INSTRUCTION_SIZE64 as u8)
		} else {
			orig_instruction_size
		} as u32;
		Self {
			bitness: block_encoder.bitness() as u8,
			instruction: *instruction,
			target_instr: TargetInstr::default(),
			orig_instruction_size,
			pointer_data: None,
			use_orig_instruction,
		}
	}

	fn try_optimize<'a>(&mut self, base: &mut InstrBase, ctx: &mut InstrContext<'a>, gained: u64) -> bool {
		if base.done {
			return false;
		}

		// If it's in the same block, we assume the target is at most 2GB away.
		let mut use_short = self.bitness != 64 || self.target_instr.is_in_block(ctx.block);
		if !use_short {
			let target_address = self.target_instr.address(ctx);
			let next_rip = ctx.ip.wrapping_add(self.orig_instruction_size as u64);
			let diff = target_address.wrapping_sub(next_rip) as i64;
			let diff = correct_diff(self.target_instr.is_in_block(ctx.block), diff, gained);
			use_short = i32::MIN as i64 <= diff && diff <= i32::MAX as i64;
		}

		if use_short {
			if let Some(ref pointer_data) = self.pointer_data {
				pointer_data.borrow_mut().is_valid = false;
			}
			base.size = self.orig_instruction_size as u32;
			self.use_orig_instruction = true;
			base.done = true;
			return true;
		}

		if self.pointer_data.is_none() {
			self.pointer_data = Some(ctx.block.alloc_pointer_location());
		}
		false
	}
}

impl Instr for CallInstr {
	fn get_target_instr(&mut self) -> (&mut TargetInstr, u64) {
		(&mut self.target_instr, self.instruction.near_branch_target())
	}

	fn optimize<'a>(&mut self, base: &mut InstrBase, ctx: &mut InstrContext<'a>, gained: u64) -> bool {
		self.try_optimize(base, ctx, gained)
	}

	fn encode<'a>(&mut self, base: &mut InstrBase, ctx: &mut InstrContext<'a>) -> Result<(ConstantOffsets, bool), IcedError> {
		if self.use_orig_instruction {
			self.instruction.set_near_branch64(self.target_instr.address(ctx));
			ctx.block.encoder.encode(&self.instruction, ctx.ip).map_or_else(
				|err| Err(IcedError::with_string(InstrUtils::create_error_message(&err, &self.instruction))),
				|_| Ok((ctx.block.encoder.get_constant_offsets(), true)),
			)
		} else {
			debug_assert!(self.pointer_data.is_some());
			let pointer_data = self.pointer_data.clone().ok_or_else(|| IcedError::new("Internal error"))?;
			pointer_data.borrow_mut().data = self.target_instr.address(ctx);
			InstrUtils::encode_branch_to_pointer_data(ctx.block, true, ctx.ip, pointer_data, base.size).map_or_else(
				|err| Err(IcedError::with_string(InstrUtils::create_error_message(&err, &self.instruction))),
				|_| Ok((ConstantOffsets::default(), false)),
			)
		}
	}
}
<commit_msg>Set `done = true` a little bit later<commit_after>// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

use crate::block_enc::instr::*;
use crate::block_enc::*;
use crate::iced_error::IcedError;
use core::cell::RefCell;
use core::cmp;

pub(crate) struct CallInstr {
	bitness: u8,
	instruction: Instruction,
	target_instr: TargetInstr,
	orig_instruction_size: u8,
	pointer_data: Option<Rc<RefCell<BlockData>>>,
	use_orig_instruction: bool,
}

impl CallInstr {
	pub(super) fn new(block_encoder: &mut BlockEncInt, base: &mut InstrBase, instruction: &Instruction) -> Self {
		let mut instr_copy = *instruction;
		instr_copy.set_near_branch64(0);
		let orig_instruction_size = block_encoder.get_instruction_size(&instr_copy, 0) as u8;
		let mut use_orig_instruction = false;
		base.size = if !block_encoder.fix_branches() {
			use_orig_instruction = true;
			orig_instruction_size
		} else if block_encoder.bitness() == 64 {
			// Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes.
			cmp::max(orig_instruction_size, InstrUtils::CALL_OR_JMP_POINTER_DATA_INSTRUCTION_SIZE64 as u8)
		} else {
			orig_instruction_size
		} as u32;
		Self {
			bitness: block_encoder.bitness() as u8,
			instruction: *instruction,
			target_instr: TargetInstr::default(),
			orig_instruction_size,
			pointer_data: None,
			use_orig_instruction,
		}
	}

	fn try_optimize<'a>(&mut self, base: &mut InstrBase, ctx: &mut InstrContext<'a>, gained: u64) -> bool {
		if base.done || self.use_orig_instruction {
			base.done = true;
			return false;
		}

		// If it's in the same block, we assume the target is at most 2GB away.
		let mut use_short = self.bitness != 64 || self.target_instr.is_in_block(ctx.block);
		if !use_short {
			let target_address = self.target_instr.address(ctx);
			let next_rip = ctx.ip.wrapping_add(self.orig_instruction_size as u64);
			let diff = target_address.wrapping_sub(next_rip) as i64;
			let diff = correct_diff(self.target_instr.is_in_block(ctx.block), diff, gained);
			use_short = i32::MIN as i64 <= diff && diff <= i32::MAX as i64;
		}

		if use_short {
			if let Some(ref pointer_data) = self.pointer_data {
				pointer_data.borrow_mut().is_valid = false;
			}
			base.size = self.orig_instruction_size as u32;
			self.use_orig_instruction = true;
			base.done = true;
			return true;
		}

		if self.pointer_data.is_none() {
			self.pointer_data = Some(ctx.block.alloc_pointer_location());
		}
		false
	}
}

impl Instr for CallInstr {
	fn get_target_instr(&mut self) -> (&mut TargetInstr, u64) {
		(&mut self.target_instr, self.instruction.near_branch_target())
	}

	fn optimize<'a>(&mut self, base: &mut InstrBase, ctx: &mut InstrContext<'a>, gained: u64) -> bool {
		self.try_optimize(base, ctx, gained)
	}

	fn encode<'a>(&mut self, base: &mut InstrBase, ctx: &mut InstrContext<'a>) -> Result<(ConstantOffsets, bool), IcedError> {
		if self.use_orig_instruction {
			self.instruction.set_near_branch64(self.target_instr.address(ctx));
			ctx.block.encoder.encode(&self.instruction, ctx.ip).map_or_else(
				|err| Err(IcedError::with_string(InstrUtils::create_error_message(&err, &self.instruction))),
				|_| Ok((ctx.block.encoder.get_constant_offsets(), true)),
			)
		} else {
			debug_assert!(self.pointer_data.is_some());
			let pointer_data = self.pointer_data.clone().ok_or_else(|| IcedError::new("Internal error"))?;
			pointer_data.borrow_mut().data = self.target_instr.address(ctx);
			InstrUtils::encode_branch_to_pointer_data(ctx.block, true, ctx.ip, pointer_data, base.size).map_or_else(
				|err| Err(IcedError::with_string(InstrUtils::create_error_message(&err, &self.instruction))),
				|_| Ok((ConstantOffsets::default(), false)),
			)
		}
	}
}
<|endoftext|>


<commit_before>
use std::sync::{Arc, RwLock};

use cgmath::{Point3, Matrix4};
use byteorder::{WriteBytesExt, NativeEndian};
use gl;
use super::glsl;

pub struct Clouds {
    program: gl::Program,
    // Shader props
    _a_position: gl::Attribute,
    u_perspective_matrix: gl::Uniform,
    u_camera_matrix: gl::Uniform,
    u_light_level: gl::Uniform,
    u_sky_offset: gl::Uniform,
    u_offset: gl::Uniform,
    u_texture_info: gl::Uniform,
    u_atlas: gl::Uniform,
    u_textures: gl::Uniform,
    u_cloud_map: gl::Uniform,
    u_cloud_offset: gl::Uniform,

    array: gl::VertexArray,
    _buffer: gl::Buffer,

    textures: Arc<RwLock<super::TextureManager>>,

    texture: gl::Texture,
    pub heightmap_data: Vec<u8>,
    pub dirty: bool,

    offset: f64,
    num_points: usize,
}

impl Clouds {
    pub fn new(greg: &glsl::Registry, textures: Arc<RwLock<super::TextureManager>>) -> Clouds {
        let program = gl::Program::new();

        let vertex = greg.get("clouds_vertex");
        let geo = greg.get("clouds_geo");
        let fragment = greg.get("clouds_frag");

        let v = gl::Shader::new(gl::VERTEX_SHADER);
        v.set_source(&vertex);
        v.compile();

        if v.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", vertex);
            panic!("Shader error: {}", v.get_info_log());
        } else {
            let log = v.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let g = gl::Shader::new(gl::GEOMETRY_SHADER);
        g.set_source(&geo);
        g.compile();

        if g.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", geo);
            panic!("Shader error: {}", g.get_info_log());
        } else {
            let log = g.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let f = gl::Shader::new(gl::FRAGMENT_SHADER);
        f.set_source(&fragment);
        f.compile();

        if f.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", fragment);
            panic!("Shader error: {}", f.get_info_log());
        } else {
            let log = f.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        program.attach_shader(v);
        program.attach_shader(g);
        program.attach_shader(f);
        program.link();
        program.use_program();

        let a_position = program.attribute_location("aPosition");
        let u_perspective_matrix = program.uniform_location("perspectiveMatrix");
        let u_camera_matrix = program.uniform_location("cameraMatrix");
        let u_light_level = program.uniform_location("lightLevel");
        let u_sky_offset = program.uniform_location("skyOffset");
        let u_offset = program.uniform_location("offset");
        let u_texture_info = program.uniform_location("textureInfo");
        let u_atlas = program.uniform_location("atlas");
        let u_textures = program.uniform_location("textures");
        let u_cloud_map = program.uniform_location("cloudMap");
        let u_cloud_offset = program.uniform_location("cloudOffset");

        let array = gl::VertexArray::new();
        array.bind();
        let buffer = gl::Buffer::new();
        buffer.bind(gl::ARRAY_BUFFER);
        a_position.enable();
        a_position.vertex_pointer(3, gl::FLOAT, false, 12, 0);

        let mut data = vec![];
        let mut num_points = 0;
        for x in -160 .. 160 {
            for z in -160 .. 160 {
                let _ = data.write_f32::<NativeEndian>(x as f32);
                let _ = data.write_f32::<NativeEndian>(128.0);
                let _ = data.write_f32::<NativeEndian>(z as f32);
                num_points += 1;
            }
        }

        buffer.set_data(gl::ARRAY_BUFFER, &data, gl::STATIC_DRAW);

        let heightmap_data = vec![120; 512*512];

        let texture = gl::Texture::new();
        texture.bind(gl::TEXTURE_2D);
        texture.image_2d(gl::TEXTURE_2D, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, Some(&heightmap_data));
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST);
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST);

        Clouds {
            program: program,
            // Shader props
            _a_position: a_position,
            u_perspective_matrix: u_perspective_matrix,
            u_camera_matrix: u_camera_matrix,
            u_light_level: u_light_level,
            u_sky_offset: u_sky_offset,
            u_offset: u_offset,
            u_texture_info: u_texture_info,
            u_atlas: u_atlas,
            u_textures: u_textures,
            u_cloud_map: u_cloud_map,
            u_cloud_offset: u_cloud_offset,

            array: array,
            _buffer: buffer,

            textures: textures,

            texture: texture,
            heightmap_data: heightmap_data,
            dirty: false,

            offset: 0.0,
            num_points: num_points,
        }
    }

    pub fn draw(&mut self, camera_pos: &Point3<f64>, perspective_matrix: &Matrix4<f32>, camera_matrix: &Matrix4<f32>, light_level: f32, sky_offset: f32, delta: f64) {
        self.offset += delta;

        let tex = super::Renderer::get_texture(&self.textures, "steven:environment/clouds");

        self.program.use_program();
        self.u_perspective_matrix.set_matrix4(perspective_matrix);
        self.u_camera_matrix.set_matrix4(camera_matrix);
        self.u_sky_offset.set_float(sky_offset);
        self.u_light_level.set_float(light_level);
        self.u_offset.set_float3(camera_pos.x.floor() as f32, 0.0, camera_pos.z.floor() as f32);
        self.u_texture_info.set_float4(
            tex.get_x() as f32,
            tex.get_y() as f32,
            tex.get_width() as f32,
            tex.get_height() as f32
        );
        self.u_atlas.set_float(tex.atlas as f32);
        self.u_cloud_offset.set_float((self.offset / 60.0) as f32);
        self.u_textures.set_int(0);

        gl::active_texture(1);
        self.texture.bind(gl::TEXTURE_2D);
        if self.dirty {
            self.texture.sub_image_2d(gl::TEXTURE_2D, 0, 0, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, &self.heightmap_data);
            self.dirty = false;
        }
        self.u_cloud_map.set_int(1);
        self.array.bind();
        gl::draw_arrays(gl::POINTS, 0, self.num_points);
    }
}
<commit_msg>Don't default the heightmap to 120<commit_after>
use std::sync::{Arc, RwLock};

use cgmath::{Point3, Matrix4};
use byteorder::{WriteBytesExt, NativeEndian};
use gl;
use super::glsl;

pub struct Clouds {
    program: gl::Program,
    // Shader props
    _a_position: gl::Attribute,
    u_perspective_matrix: gl::Uniform,
    u_camera_matrix: gl::Uniform,
    u_light_level: gl::Uniform,
    u_sky_offset: gl::Uniform,
    u_offset: gl::Uniform,
    u_texture_info: gl::Uniform,
    u_atlas: gl::Uniform,
    u_textures: gl::Uniform,
    u_cloud_map: gl::Uniform,
    u_cloud_offset: gl::Uniform,

    array: gl::VertexArray,
    _buffer: gl::Buffer,

    textures: Arc<RwLock<super::TextureManager>>,

    texture: gl::Texture,
    pub heightmap_data: Vec<u8>,
    pub dirty: bool,

    offset: f64,
    num_points: usize,
}

impl Clouds {
    pub fn new(greg: &glsl::Registry, textures: Arc<RwLock<super::TextureManager>>) -> Clouds {
        let program = gl::Program::new();

        let vertex = greg.get("clouds_vertex");
        let geo = greg.get("clouds_geo");
        let fragment = greg.get("clouds_frag");

        let v = gl::Shader::new(gl::VERTEX_SHADER);
        v.set_source(&vertex);
        v.compile();

        if v.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", vertex);
            panic!("Shader error: {}", v.get_info_log());
        } else {
            let log = v.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let g = gl::Shader::new(gl::GEOMETRY_SHADER);
        g.set_source(&geo);
        g.compile();

        if g.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", geo);
            panic!("Shader error: {}", g.get_info_log());
        } else {
            let log = g.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let f = gl::Shader::new(gl::FRAGMENT_SHADER);
        f.set_source(&fragment);
        f.compile();

        if f.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", fragment);
            panic!("Shader error: {}", f.get_info_log());
        } else {
            let log = f.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        program.attach_shader(v);
        program.attach_shader(g);
        program.attach_shader(f);
        program.link();
        program.use_program();

        let a_position = program.attribute_location("aPosition");
        let u_perspective_matrix = program.uniform_location("perspectiveMatrix");
        let u_camera_matrix = program.uniform_location("cameraMatrix");
        let u_light_level = program.uniform_location("lightLevel");
        let u_sky_offset = program.uniform_location("skyOffset");
        let u_offset = program.uniform_location("offset");
        let u_texture_info = program.uniform_location("textureInfo");
        let u_atlas = program.uniform_location("atlas");
        let u_textures = program.uniform_location("textures");
        let u_cloud_map = program.uniform_location("cloudMap");
        let u_cloud_offset = program.uniform_location("cloudOffset");

        let array = gl::VertexArray::new();
        array.bind();
        let buffer = gl::Buffer::new();
        buffer.bind(gl::ARRAY_BUFFER);
        a_position.enable();
        a_position.vertex_pointer(3, gl::FLOAT, false, 12, 0);

        let mut data = vec![];
        let mut num_points = 0;
        for x in -160 .. 160 {
            for z in -160 .. 160 {
                let _ = data.write_f32::<NativeEndian>(x as f32);
                let _ = data.write_f32::<NativeEndian>(128.0);
                let _ = data.write_f32::<NativeEndian>(z as f32);
                num_points += 1;
            }
        }

        buffer.set_data(gl::ARRAY_BUFFER, &data, gl::STATIC_DRAW);

        let heightmap_data = vec![0; 512*512];

        let texture = gl::Texture::new();
        texture.bind(gl::TEXTURE_2D);
        texture.image_2d(gl::TEXTURE_2D, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, Some(&heightmap_data));
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST);
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST);

        Clouds {
            program: program,
            // Shader props
            _a_position: a_position,
            u_perspective_matrix: u_perspective_matrix,
            u_camera_matrix: u_camera_matrix,
            u_light_level: u_light_level,
            u_sky_offset: u_sky_offset,
            u_offset: u_offset,
            u_texture_info: u_texture_info,
            u_atlas: u_atlas,
            u_textures: u_textures,
            u_cloud_map: u_cloud_map,
            u_cloud_offset: u_cloud_offset,

            array: array,
            _buffer: buffer,

            textures: textures,

            texture: texture,
            heightmap_data: heightmap_data,
            dirty: false,

            offset: 0.0,
            num_points: num_points,
        }
    }

    pub fn draw(&mut self, camera_pos: &Point3<f64>, perspective_matrix: &Matrix4<f32>, camera_matrix: &Matrix4<f32>, light_level: f32, sky_offset: f32, delta: f64) {
        self.offset += delta;

        let tex = super::Renderer::get_texture(&self.textures, "steven:environment/clouds");

        self.program.use_program();
        self.u_perspective_matrix.set_matrix4(perspective_matrix);
        self.u_camera_matrix.set_matrix4(camera_matrix);
        self.u_sky_offset.set_float(sky_offset);
        self.u_light_level.set_float(light_level);
        self.u_offset.set_float3(camera_pos.x.floor() as f32, 0.0, camera_pos.z.floor() as f32);
        self.u_texture_info.set_float4(
            tex.get_x() as f32,
            tex.get_y() as f32,
            tex.get_width() as f32,
            tex.get_height() as f32
        );
        self.u_atlas.set_float(tex.atlas as f32);
        self.u_cloud_offset.set_float((self.offset / 60.0) as f32);
        self.u_textures.set_int(0);

        gl::active_texture(1);
        self.texture.bind(gl::TEXTURE_2D);
        if self.dirty {
            self.texture.sub_image_2d(gl::TEXTURE_2D, 0, 0, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, &self.heightmap_data);
            self.dirty = false;
        }
        self.u_cloud_map.set_int(1);
        self.array.bind();
        gl::draw_arrays(gl::POINTS, 0, self.num_points);
    }
}
<|endoftext|>


<commit_before>// This is a part of rust-encoding.
// Copyright (c) 2014-2015, Kang Seonghoon.
// See README.md and LICENSE.txt for details.

#![feature(core, collections)] // lib stability features as per RFC #507

extern crate core;
extern crate encoding;
extern crate getopts;

use std::{io, env};
use std::io::{Read, Write};
use std::fs::File;
use std::path::Path;
use encoding::{EncoderTrap, DecoderTrap};
use encoding::label::encoding_from_whatwg_label;
use getopts::Options;

fn main() {
    let args: Vec<_> = env::args().collect();

    let mut opts = Options::new();
    opts.optopt("f", "from-code", "set input encoding", "NAME");
    opts.optopt("t", "to-code", "set output encoding", "NAME");
    opts.optopt("e", "error-policy",
                "set error policy (one of strict, ignore, replace, ncr-escape)", "POLICY");
    opts.optflag("c", "", "same as `--error-policy=ignore`");
    opts.optopt("o", "output", "output file", "FILE");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(args.tail()) {
        Ok(m) => m,
        Err(e) => panic!(e.to_string()),
    };
    if matches.opt_present("h") {
        println!("{}", opts.usage("Converts the character encoding using rust-encoding."));
        return;
    }

    let inencname = matches.opt_str("f");
    let outencname = matches.opt_str("t");
    let inenc = match inencname.as_ref().map(|s| &s[..]) {
        Some(name) => match encoding_from_whatwg_label(name) {
            Some(enc) => enc,
            None => panic!("invalid input encoding name {}", name),
        },
        None => encoding::all::UTF_8 as encoding::EncodingRef,
    };
    let outenc = match outencname.as_ref().map(|s| &s[..]) {
        Some(name) => match encoding_from_whatwg_label(name) {
            Some(enc) => enc,
            None => panic!("invalid output encoding name {}", name),
        },
        None => encoding::all::UTF_8 as encoding::EncodingRef,
    };

    let mut policy = matches.opt_str("e");
    if matches.opt_present("c") {
        policy = Some("ignore".to_string());
    }
    let (intrap, outtrap) = match policy.as_ref().map(|s| &s[..]) {
        Some("strict") | None => (DecoderTrap::Strict, EncoderTrap::Strict),
        Some("ignore") => (DecoderTrap::Ignore, EncoderTrap::Ignore),
        Some("replace") => (DecoderTrap::Replace, EncoderTrap::Replace),
        Some("ncr-escape") => (DecoderTrap::Replace, EncoderTrap::NcrEscape),
        Some(s) => panic!("invalid error policy {}", s),
    };

    let mut input = match matches.free.first().map(|s| &s[..]) {
        Some("-") | None => Box::new(io::stdin()) as Box<Read>,
        Some(f) => match File::open(&Path::new(f)) {
            Ok(f) => Box::new(f) as Box<Read>,
            Err(e) => panic!("cannot open the input {}: {}", f, e),
        },
    };
    let mut output = match matches.opt_str("o").as_ref().map(|s| &s[..]) {
        Some("-") | None => Box::new(io::stdout()) as Box<Write>,
        Some(f) => match File::create(&Path::new(f)) {
            Ok(f) => Box::new(f) as Box<Write>,
            Err(e) => panic!("cannot open the output {}: {}", f, e),
        },
    };

    // XXX should really use the incremental interface
    let mut ret = Vec::new();
    input.read_to_end(&mut ret).ok().expect("cannot read from the input");
    let decoded = match inenc.decode(&ret, intrap) {
        Ok(s) => s,
        Err(e) => panic!("decoder error: {}", e),
    };
    let encoded = match outenc.encode(&decoded, outtrap) {
        Ok(s) => s,
        Err(e) => panic!("encoder error: {}", e),
    };
    output.write_all(&encoded).unwrap();
}

<commit_msg>Sabilize examples/recode.rs<commit_after>// This is a part of rust-encoding.
// Copyright (c) 2014-2015, Kang Seonghoon.
// See README.md and LICENSE.txt for details.

extern crate encoding;
extern crate getopts;

use std::{io, env};
use std::io::{Read, Write};
use std::fs::File;
use std::path::Path;
use encoding::{EncoderTrap, DecoderTrap};
use encoding::label::encoding_from_whatwg_label;
use getopts::Options;

fn main() {
    let args: Vec<_> = env::args().collect();

    let mut opts = Options::new();
    opts.optopt("f", "from-code", "set input encoding", "NAME");
    opts.optopt("t", "to-code", "set output encoding", "NAME");
    opts.optopt("e", "error-policy",
                "set error policy (one of strict, ignore, replace, ncr-escape)", "POLICY");
    opts.optflag("c", "", "same as `--error-policy=ignore`");
    opts.optopt("o", "output", "output file", "FILE");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => panic!(e.to_string()),
    };
    if matches.opt_present("h") {
        println!("{}", opts.usage("Converts the character encoding using rust-encoding."));
        return;
    }

    let inencname = matches.opt_str("f");
    let outencname = matches.opt_str("t");
    let inenc = match inencname.as_ref().map(|s| &s[..]) {
        Some(name) => match encoding_from_whatwg_label(name) {
            Some(enc) => enc,
            None => panic!("invalid input encoding name {}", name),
        },
        None => encoding::all::UTF_8 as encoding::EncodingRef,
    };
    let outenc = match outencname.as_ref().map(|s| &s[..]) {
        Some(name) => match encoding_from_whatwg_label(name) {
            Some(enc) => enc,
            None => panic!("invalid output encoding name {}", name),
        },
        None => encoding::all::UTF_8 as encoding::EncodingRef,
    };

    let mut policy = matches.opt_str("e");
    if matches.opt_present("c") {
        policy = Some("ignore".to_string());
    }
    let (intrap, outtrap) = match policy.as_ref().map(|s| &s[..]) {
        Some("strict") | None => (DecoderTrap::Strict, EncoderTrap::Strict),
        Some("ignore") => (DecoderTrap::Ignore, EncoderTrap::Ignore),
        Some("replace") => (DecoderTrap::Replace, EncoderTrap::Replace),
        Some("ncr-escape") => (DecoderTrap::Replace, EncoderTrap::NcrEscape),
        Some(s) => panic!("invalid error policy {}", s),
    };

    let mut input = match matches.free.first().map(|s| &s[..]) {
        Some("-") | None => Box::new(io::stdin()) as Box<Read>,
        Some(f) => match File::open(&Path::new(f)) {
            Ok(f) => Box::new(f) as Box<Read>,
            Err(e) => panic!("cannot open the input {}: {}", f, e),
        },
    };
    let mut output = match matches.opt_str("o").as_ref().map(|s| &s[..]) {
        Some("-") | None => Box::new(io::stdout()) as Box<Write>,
        Some(f) => match File::create(&Path::new(f)) {
            Ok(f) => Box::new(f) as Box<Write>,
            Err(e) => panic!("cannot open the output {}: {}", f, e),
        },
    };

    // XXX should really use the incremental interface
    let mut ret = Vec::new();
    input.read_to_end(&mut ret).ok().expect("cannot read from the input");
    let decoded = match inenc.decode(&ret, intrap) {
        Ok(s) => s,
        Err(e) => panic!("decoder error: {}", e),
    };
    let encoded = match outenc.encode(&decoded, outtrap) {
        Ok(s) => s,
        Err(e) => panic!("encoder error: {}", e),
    };
    output.write_all(&encoded).unwrap();
}

<|endoftext|>


<commit_before>extern crate sendmail;

fn main() {

    // Configure email body and header
    sendmail::email::create(
        "noreply@verge.website",
        "alex.steven.elias@gmail.com",
        "This Is Subject",
        "I am the body. hello wolrd!"
    );

    // Define the actual email address to recieve the email
    sendmail::email::send("alex.steven.elias@gmail.com");

}
<commit_msg>Base Build<commit_after>extern crate sendmail;

fn main() {

    // Configure email body and header
    sendmail::email::create(
        "noreply@example.com",
        "aemail@gmail.com",
        "This Is A Subject",
        "I am the body. Hello Wolrd!"
    );

    // Define the actual email address to recieve the email
    sendmail::email::send("aemail@gmail.com");

}
<|endoftext|>


<commit_before>extern crate libc;
extern crate neovim;

use std::old_io::{File, FileMode, FileAccess};

mod ffi {
    pub use libc::{c_int, c_uchar, c_void};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;
}

fn send_message(fd: ffi::c_int, command: &str) {
    let mut arr = neovim::Array::new();
    arr.add_string(command);
    let msg = neovim::serialize_message(1, "vim_command", &arr);
    let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
    unsafe { ffi::write(fd, msg_ptr, msg.len() as ffi::size_t) };
}

fn recv_message(fd: ffi::c_int) -> Option<neovim::Array> {
    let mut buf : [ffi::c_uchar; 1024] = [0; 1024];
    let n = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut ffi::c_void, 1024) };
    if n < 0 {
        return None;
    }
    unsafe {
        let v = Vec::from_raw_buf(buf.as_ptr(), n as usize);
        let s = String::from_utf8_unchecked(v);
        Some(neovim::deserialize_message(&s))
    }
}

fn main() {
    // two pairs of anonymous pipes for msgpack-rpc between the logger and nvim
    let mut nvim_log : [ffi::c_int; 2] = [0; 2]; // to nvim from logger
    let mut log_nvim : [ffi::c_int; 2] = [0; 2]; // to logger from nvim
    unsafe {
        ffi::pipe(nvim_log.as_mut_ptr());
        ffi::pipe(log_nvim.as_mut_ptr());
    };

    // listen for events in a separate thread and log them
    ::std::thread::Thread::spawn(move || {
        // listen for bufenter events
        send_message(nvim_log[1], "au BufEnter * call rpcnotify(1, 'bufenter', fnamemodify(bufname(''), ':p'))");

        // receive messages
        let mut file = File::open_mode(&Path::new("events.log"), FileMode::Append, FileAccess::Write);
        while let Some(recv_arr) = recv_message(log_nvim[0]) {
            if recv_arr.len() > 0 {
                file.write_all(format!("{:?}\n", recv_arr).into_bytes().as_slice());
            }
        }
    });

    // start nvim
    let mut args = Vec::new();
    for arg in ::std::env::args() {
        args.push(arg);
    }
    neovim::main_setup(&args);
    neovim::channel_from_fds(nvim_log[0], log_nvim[1]);
    neovim::main_loop();
}
<commit_msg>Remove unnecessary ffi module<commit_after>extern crate libc;
extern crate neovim;

use std::old_io::{File, FileMode, FileAccess};
use libc::{c_int, c_uchar, c_void};
use libc::funcs::posix88::unistd::{close, pipe, read, write};
use libc::types::os::arch::c95::size_t;

fn send_message(fd: c_int, command: &str) {
    let mut arr = neovim::Array::new();
    arr.add_string(command);
    let msg = neovim::serialize_message(1, "vim_command", &arr);
    let msg_ptr = msg.as_slice().as_ptr() as *const c_void;
    unsafe { write(fd, msg_ptr, msg.len() as size_t) };
}

fn recv_message(fd: c_int) -> Option<neovim::Array> {
    let mut buf : [c_uchar; 1024] = [0; 1024];
    let n = unsafe { read(fd, buf.as_mut_ptr() as *mut c_void, 1024) };
    if n < 0 {
        return None;
    }
    unsafe {
        let v = Vec::from_raw_buf(buf.as_ptr(), n as usize);
        let s = String::from_utf8_unchecked(v);
        Some(neovim::deserialize_message(&s))
    }
}

fn main() {
    // two pairs of anonymous pipes for msgpack-rpc between the logger and nvim
    let mut nvim_log : [c_int; 2] = [0; 2]; // to nvim from logger
    let mut log_nvim : [c_int; 2] = [0; 2]; // to logger from nvim
    unsafe {
        pipe(nvim_log.as_mut_ptr());
        pipe(log_nvim.as_mut_ptr());
    };

    // listen for events in a separate thread and log them
    ::std::thread::Thread::spawn(move || {
        // listen for bufenter events
        send_message(nvim_log[1], "au BufEnter * call rpcnotify(1, 'bufenter', fnamemodify(bufname(''), ':p'))");

        // receive messages
        let mut file = File::open_mode(&Path::new("events.log"), FileMode::Append, FileAccess::Write);
        while let Some(recv_arr) = recv_message(log_nvim[0]) {
            if recv_arr.len() > 0 {
                file.write_all(format!("{:?}\n", recv_arr).into_bytes().as_slice());
            }
        }
    });

    // start nvim
    let mut args = Vec::new();
    for arg in ::std::env::args() {
        args.push(arg);
    }
    neovim::main_setup(&args);
    neovim::channel_from_fds(nvim_log[0], log_nvim[1]);
    neovim::main_loop();
}
<|endoftext|>


<commit_before>extern crate conrod;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate piston;

use conrod::{
    Background,
    Button,
    Callable,
    Colorable,
    Shapeable,
    Drawable,
    Label,
    Positionable,
    Theme,
    Ui
};
use glutin_window::GlutinWindow;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event::*;
use piston::window::{ WindowSettings, Size };
use std::path::Path;

fn main() {

    let opengl = OpenGL::_3_2;
    let window = GlutinWindow::new(
        opengl,
        WindowSettings::new(
            "Hello Conrod".to_string(),
            Size { width: 200, height: 100 }
        )
        .exit_on_esc(true)
        .samples(4)
    );
    let event_iter = window.events().ups(180).max_fps(60);
    let mut gl = GlGraphics::new(opengl);
    let font_path = Path::new("./assets/NotoSans/NotoSans-Regular.ttf");
    let theme = Theme::default();
    let glyph_cache = GlyphCache::new(&font_path).unwrap();
    let ui = &mut Ui::new(glyph_cache, theme);

    let mut count = 0;

    for event in event_iter {
        ui.handle_event(&event);
        if let Some(args) = event.render_args() {
            gl.draw(args.viewport(), |_, gl| {

                // Draw the background.
                Background::new().rgba(0.2, 0.25, 0.4, 1.0).draw(ui, gl);

                // Draw the counter.
                counter(gl, ui, &mut count)

            });
        }
    }

}

/// Function for drawing the counter widget.
fn counter<'a>(gl: &mut GlGraphics,
               ui: &mut Ui<GlyphCache<'a>>,
               count: &mut u32) {

    // Draw the value.
    Label::new(&count.to_string()).position(10.0, 10.0).draw(ui, gl);

    // Draw the button and increment count if pressed..
    Button::new(0)
        .position(110.0, 10.0)
        .dimensions(80.0, 80.0)
        .callback(|| *count += 1)
        .draw(ui, gl)

}
<commit_msg>Removed Callable from counter example<commit_after>extern crate conrod;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate piston;

use conrod::{
    Background,
    Button,
    Colorable,
    Shapeable,
    Drawable,
    Label,
    Positionable,
    Theme,
    Ui
};
use glutin_window::GlutinWindow;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event::*;
use piston::window::{ WindowSettings, Size };
use std::path::Path;

fn main() {

    let opengl = OpenGL::_3_2;
    let window = GlutinWindow::new(
        opengl,
        WindowSettings::new(
            "Hello Conrod".to_string(),
            Size { width: 200, height: 100 }
        )
        .exit_on_esc(true)
        .samples(4)
    );
    let event_iter = window.events().ups(180).max_fps(60);
    let mut gl = GlGraphics::new(opengl);
    let font_path = Path::new("./assets/NotoSans/NotoSans-Regular.ttf");
    let theme = Theme::default();
    let glyph_cache = GlyphCache::new(&font_path).unwrap();
    let ui = &mut Ui::new(glyph_cache, theme);

    let mut count = 0;

    for event in event_iter {
        ui.handle_event(&event);
        if let Some(args) = event.render_args() {
            gl.draw(args.viewport(), |_, gl| {

                // Draw the background.
                Background::new().rgba(0.2, 0.25, 0.4, 1.0).draw(ui, gl);

                // Draw the counter.
                counter(gl, ui, &mut count)

            });
        }
    }

}

/// Function for drawing the counter widget.
fn counter<'a>(gl: &mut GlGraphics,
               ui: &mut Ui<GlyphCache<'a>>,
               count: &mut u32) {

    // Draw the value.
    Label::new(&count.to_string()).position(10.0, 10.0).draw(ui, gl);

    // Draw the button and increment count if pressed..
    Button::new(0)
        .position(110.0, 10.0)
        .dimensions(80.0, 80.0)
        .callback(|| *count += 1)
        .draw(ui, gl)

}
<|endoftext|>


<commit_before>//! parsing data from the configuration file
use std::collections::HashMap;
use std::io::{self,Error,ErrorKind,Read};
use std::fs::File;
use std::str::FromStr;
use serde::Deserialize;
use toml;

use command::data::ListenerType;
use sozu::messages::{HttpProxyConfiguration,TlsProxyConfiguration};

#[derive(Debug,Clone,PartialEq,Eq,Hash,Serialize,Deserialize)]
pub struct ListenerConfig {
  pub listener_type:             ListenerType,
  pub address:                   String,
  pub public_address:            Option<String>,
  pub port:                      u16,
  pub max_connections:           usize,
  pub buffer_size:               usize,
  pub answer_404:                Option<String>,
  pub answer_503:                Option<String>,
  pub cipher_list:               Option<String>,
  pub worker_count:              Option<u16>,
  pub default_name:              Option<String>,
  pub default_app_id:            Option<String>,
  pub default_certificate:       Option<String>,
  pub default_certificate_chain: Option<String>,
  pub default_key:               Option<String>,

}

impl ListenerConfig {
  pub fn to_http(&self) -> Option<HttpProxyConfiguration> {
    let mut address = self.address.clone();
    address.push(':');
    address.push_str(&self.port.to_string());

    let public_address = self.public_address.as_ref().and_then(|addr| FromStr::from_str(&addr).ok());
    //FIXME: error message when we cannot parse the address
    address.parse().ok().map(|addr| {
      let mut configuration = HttpProxyConfiguration {
        front: addr,
        public_address: public_address,
        max_connections: self.max_connections,
        buffer_size: self.buffer_size,
        ..Default::default()
      };

      //FIXME: error messages if file not found?
      let mut answer_404 = String::new();
      if self.answer_404.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_404).ok()).is_some() {
        configuration.answer_404 = answer_404;
      }
      let mut answer_503 = String::new();
      if self.answer_503.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_503).ok()).is_some() {
        configuration.answer_503 = answer_503;
      }
      configuration
    })
  }

  pub fn to_tls(&self) -> Option<TlsProxyConfiguration> {
    let mut address = self.address.clone();
    address.push(':');
    address.push_str(&self.port.to_string());

    let public_address     = self.public_address.as_ref().and_then(|addr| FromStr::from_str(&addr).ok());
    let cipher_list:String = self.cipher_list.clone().unwrap_or(
      String::from(
        "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
        ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
        ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
        DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\
        ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:\
        ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:\
        ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:\
        ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:\
        DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:\
        DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:\
        ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:\
        AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:\
        AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"));

    //FIXME: error message when we cannot parse the address
    address.parse().ok().map(|addr| {
      let mut configuration = TlsProxyConfiguration {
        front:           addr,
        public_address:  public_address,
        max_connections: self.max_connections,
        buffer_size:     self.buffer_size,
        cipher_list:     cipher_list,
        ..Default::default()
      };

      //FIXME: error messages if file not found?
      let mut answer_404 = String::new();
      if self.answer_404.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_404).ok()).is_some() {
        configuration.answer_404 = answer_404;
      } else {
        error!("error loading default 404 answer file: {:?}", self.answer_404);
      }
      let mut answer_503 = String::new();
      if self.answer_503.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_503).ok()).is_some() {
        configuration.answer_503 = answer_503;
      } else {
        error!("error loading default 503 answer file: {:?}", self.answer_503);
      }
      if let Some(cipher_list) = self.cipher_list.as_ref() {
        configuration.cipher_list = cipher_list.clone();
      }
      let mut default_cert: Vec<u8> = vec!();
      if self.default_certificate.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_end(&mut default_cert).ok()).is_some() {
        configuration.default_certificate = Some(default_cert);
      }

      configuration.default_app_id            = self.default_app_id.clone();
      configuration.default_certificate_chain = self.default_certificate_chain.clone();

      let mut default_key: Vec<u8> = vec!();
      if self.default_key.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_end(&mut default_key).ok()).is_some() {
        configuration.default_key = Some(default_key);
      }

      configuration

    })
  }
}

#[derive(Debug,Clone,PartialEq,Eq,Hash,Serialize,Deserialize)]
pub struct MetricsConfig {
  pub address: String,
  pub port:    u16,
}

#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
pub struct Config {
  pub command_socket: String,
  pub command_buffer_size: Option<usize>,
  pub max_command_buffer_size: Option<usize>,
  pub saved_state:    Option<String>,
  pub metrics:        MetricsConfig,
  pub listeners:      HashMap<String, ListenerConfig>,
  pub log_level:      Option<String>,
}

impl Config {
  pub fn load_from_path(path: &str) -> io::Result<Config> {
    let mut f = try!(File::open(path));
    let mut data = String::new();
    try!(f.read_to_string(&mut data));

    let mut parser = toml::Parser::new(&data[..]);
    if let Some(table) = parser.parse() {
      match Deserialize::deserialize(&mut toml::Decoder::new(toml::Value::Table(table))) {
        Ok(config) => Ok(config),
        Err(e)     => {
          println!("decoding error: {:?}", e);
          Err(Error::new(
            ErrorKind::InvalidData,
            format!("decoding error: {:?}", e))
          )
        }
      }
    } else {
      println!("error parsing file:");
      let mut offset = 0usize;
      let mut index  = 0usize;
      for line in data.lines() {
        for error in &parser.errors {
          if error.lo >= offset && error.lo <= offset + line.len() {
            println!("line {}: {}", index, error.desc);
          }
        }
        offset += line.len();
        index  += 1;
      }
      Err(Error::new(ErrorKind::InvalidData, format!("could not parse the configuration file: {:?}", parser.errors)))
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::collections::HashMap;
  use toml::encode_str;
  use command::data::ListenerType;

  #[test]
  fn serialize() {
    let mut map = HashMap::new();
    map.insert(String::from("HTTP"), ListenerConfig {
      listener_type: ListenerType::HTTP,
      address: String::from("127.0.0.1"),
      port: 8080,
      max_connections: 500,
      buffer_size: 16384,
      answer_404: Some(String::from("404.html")),
      answer_503: None,
      public_address: None,
      cipher_list: None,
      worker_count: None,
    });
    map.insert(String::from("TLS"), ListenerConfig {
      listener_type: ListenerType::HTTPS,
      address: String::from("127.0.0.1"),
      port: 8080,
      max_connections: 500,
      buffer_size: 16384,
      answer_404: Some(String::from("404.html")),
      answer_503: None,
      public_address: None,
      cipher_list: None,
      worker_count: None,
    });
    let config = Config {
      command_socket: String::from("./command_folder/sock"),
      saved_state: None,
      command_buffer_size: None,
      max_command_buffer_size: None,
      log_level: None,
      metrics: MetricsConfig {
        address: String::from("192.168.59.103"),
        port:    8125,
      },
      listeners: map
    };

    let encoded = encode_str(&config);
    println!("conf:\n{}", encoded);
  }
}
<commit_msg>bin: fix tests<commit_after>//! parsing data from the configuration file
use std::collections::HashMap;
use std::io::{self,Error,ErrorKind,Read};
use std::fs::File;
use std::str::FromStr;
use serde::Deserialize;
use toml;

use command::data::ListenerType;
use sozu::messages::{HttpProxyConfiguration,TlsProxyConfiguration};

#[derive(Debug,Clone,PartialEq,Eq,Hash,Serialize,Deserialize)]
pub struct ListenerConfig {
  pub listener_type:             ListenerType,
  pub address:                   String,
  pub public_address:            Option<String>,
  pub port:                      u16,
  pub max_connections:           usize,
  pub buffer_size:               usize,
  pub answer_404:                Option<String>,
  pub answer_503:                Option<String>,
  pub cipher_list:               Option<String>,
  pub worker_count:              Option<u16>,
  pub default_name:              Option<String>,
  pub default_app_id:            Option<String>,
  pub default_certificate:       Option<String>,
  pub default_certificate_chain: Option<String>,
  pub default_key:               Option<String>,

}

impl ListenerConfig {
  pub fn to_http(&self) -> Option<HttpProxyConfiguration> {
    let mut address = self.address.clone();
    address.push(':');
    address.push_str(&self.port.to_string());

    let public_address = self.public_address.as_ref().and_then(|addr| FromStr::from_str(&addr).ok());
    //FIXME: error message when we cannot parse the address
    address.parse().ok().map(|addr| {
      let mut configuration = HttpProxyConfiguration {
        front: addr,
        public_address: public_address,
        max_connections: self.max_connections,
        buffer_size: self.buffer_size,
        ..Default::default()
      };

      //FIXME: error messages if file not found?
      let mut answer_404 = String::new();
      if self.answer_404.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_404).ok()).is_some() {
        configuration.answer_404 = answer_404;
      }
      let mut answer_503 = String::new();
      if self.answer_503.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_503).ok()).is_some() {
        configuration.answer_503 = answer_503;
      }
      configuration
    })
  }

  pub fn to_tls(&self) -> Option<TlsProxyConfiguration> {
    let mut address = self.address.clone();
    address.push(':');
    address.push_str(&self.port.to_string());

    let public_address     = self.public_address.as_ref().and_then(|addr| FromStr::from_str(&addr).ok());
    let cipher_list:String = self.cipher_list.clone().unwrap_or(
      String::from(
        "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
        ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
        ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
        DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\
        ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:\
        ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:\
        ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:\
        ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:\
        DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:\
        DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:\
        ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:\
        AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:\
        AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"));

    //FIXME: error message when we cannot parse the address
    address.parse().ok().map(|addr| {
      let mut configuration = TlsProxyConfiguration {
        front:           addr,
        public_address:  public_address,
        max_connections: self.max_connections,
        buffer_size:     self.buffer_size,
        cipher_list:     cipher_list,
        ..Default::default()
      };

      //FIXME: error messages if file not found?
      let mut answer_404 = String::new();
      if self.answer_404.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_404).ok()).is_some() {
        configuration.answer_404 = answer_404;
      } else {
        error!("error loading default 404 answer file: {:?}", self.answer_404);
      }
      let mut answer_503 = String::new();
      if self.answer_503.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_string(&mut answer_503).ok()).is_some() {
        configuration.answer_503 = answer_503;
      } else {
        error!("error loading default 503 answer file: {:?}", self.answer_503);
      }
      if let Some(cipher_list) = self.cipher_list.as_ref() {
        configuration.cipher_list = cipher_list.clone();
      }
      let mut default_cert: Vec<u8> = vec!();
      if self.default_certificate.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_end(&mut default_cert).ok()).is_some() {
        configuration.default_certificate = Some(default_cert);
      }

      configuration.default_app_id            = self.default_app_id.clone();
      configuration.default_certificate_chain = self.default_certificate_chain.clone();

      let mut default_key: Vec<u8> = vec!();
      if self.default_key.as_ref().and_then(|path| File::open(path).ok())
        .and_then(|mut file| file.read_to_end(&mut default_key).ok()).is_some() {
        configuration.default_key = Some(default_key);
      }

      configuration

    })
  }
}

#[derive(Debug,Clone,PartialEq,Eq,Hash,Serialize,Deserialize)]
pub struct MetricsConfig {
  pub address: String,
  pub port:    u16,
}

#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
pub struct Config {
  pub command_socket: String,
  pub command_buffer_size: Option<usize>,
  pub max_command_buffer_size: Option<usize>,
  pub saved_state:    Option<String>,
  pub metrics:        MetricsConfig,
  pub listeners:      HashMap<String, ListenerConfig>,
  pub log_level:      Option<String>,
}

impl Config {
  pub fn load_from_path(path: &str) -> io::Result<Config> {
    let mut f = try!(File::open(path));
    let mut data = String::new();
    try!(f.read_to_string(&mut data));

    let mut parser = toml::Parser::new(&data[..]);
    if let Some(table) = parser.parse() {
      match Deserialize::deserialize(&mut toml::Decoder::new(toml::Value::Table(table))) {
        Ok(config) => Ok(config),
        Err(e)     => {
          println!("decoding error: {:?}", e);
          Err(Error::new(
            ErrorKind::InvalidData,
            format!("decoding error: {:?}", e))
          )
        }
      }
    } else {
      println!("error parsing file:");
      let mut offset = 0usize;
      let mut index  = 0usize;
      for line in data.lines() {
        for error in &parser.errors {
          if error.lo >= offset && error.lo <= offset + line.len() {
            println!("line {}: {}", index, error.desc);
          }
        }
        offset += line.len();
        index  += 1;
      }
      Err(Error::new(ErrorKind::InvalidData, format!("could not parse the configuration file: {:?}", parser.errors)))
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::collections::HashMap;
  use toml::encode_str;
  use command::data::ListenerType;

  #[test]
  fn serialize() {
    let mut map = HashMap::new();
    map.insert(String::from("HTTP"), ListenerConfig {
      listener_type: ListenerType::HTTP,
      address: String::from("127.0.0.1"),
      port: 8080,
      max_connections: 500,
      buffer_size: 16384,
      answer_404: Some(String::from("404.html")),
      answer_503: None,
      public_address: None,
      cipher_list: None,
      worker_count: None,
      default_app_id: None,
      default_certificate: None,
      default_certificate_chain: None,
      default_key: None,
      default_name: None,
    });
    map.insert(String::from("TLS"), ListenerConfig {
      listener_type: ListenerType::HTTPS,
      address: String::from("127.0.0.1"),
      port: 8080,
      max_connections: 500,
      buffer_size: 16384,
      answer_404: Some(String::from("404.html")),
      answer_503: None,
      public_address: None,
      cipher_list: None,
      worker_count: None,
      default_app_id: None,
      default_certificate: None,
      default_certificate_chain: None,
      default_key: None,
      default_name: None,
    });
    let config = Config {
      command_socket: String::from("./command_folder/sock"),
      saved_state: None,
      command_buffer_size: None,
      max_command_buffer_size: None,
      log_level: None,
      metrics: MetricsConfig {
        address: String::from("192.168.59.103"),
        port:    8125,
      },
      listeners: map
    };

    let encoded = encode_str(&config);
    println!("conf:\n{}", encoded);
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::cell::{Cell, RefCell};
use std::rc::Rc;
use wlroots::compositor::Compositor;
use wlroots::cursor::{Cursor, XCursorTheme};
use wlroots::device::Device;
use wlroots::manager::{InputManagerHandler, OutputManagerHandler, PointerHandler};
use wlroots::output::{Output, OutputLayout};
use wlroots::pointer;
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;

struct OutputHandler {
    color: Rc<Cell<[f32; 4]>>,
    cursor: Cursor
}

struct InputHandler {
    color: Rc<Cell<[f32; 4]>>
}

struct Pointer {
    color: Rc<Cell<[f32; 4]>>,
    default_color: [f32; 4]
}

impl PointerHandler for Pointer {
    fn on_button(&mut self, _: &mut Device, event: &pointer::ButtonEvent) {
        if event.state() == WLR_BUTTON_RELEASED {
            self.color.set(self.default_color.clone())
        } else {
            let mut red: [f32; 4] = [0.25, 0.25, 0.25, 1.0];
            red[event.button() as usize % 3] = 1.0;
            self.color.set(red);
        }
    }
}

impl OutputManagerHandler for OutputHandler {
    fn output_added(&mut self, output: &mut Output) {
        let cursor = &mut self.cursor;
        {
            let xcursor = cursor.xcursor().expect("XCursor was not set!");
            let image = &xcursor.images()[0];
            // TODO use output config if present instead of auto
            let layout = cursor
                .output_layout()
                .as_ref()
                .expect("Could not get output layout");
            layout.borrow_mut().add_auto(output);
            if output.set_cursor(image).is_err() {
                wlr_log!(L_DEBUG, "Failed to set hardware cursor");
                return;
            }
        }
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
    }

    fn output_frame(&mut self, output: &mut Output) {
        output.make_current();
        unsafe {
            gl::ClearColor(self.color.get()[0],
                           self.color.get()[1],
                           self.color.get()[2],
                           1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputHandler {
    fn pointer_added(&mut self, _: &mut Device) -> Option<Box<PointerHandler>> {
        Some(Box::new(Pointer {
                          color: self.color.clone(),
                          default_color: self.color.get()
                      }))
    }
}

fn managers(mut cursor: Cursor) -> (OutputHandler, InputHandler) {
    let layout = Rc::new(RefCell::new(OutputLayout::new()));
    // TODO Ensure this can be safe...
    // e.g what's stopping me from simply dropping layout now that I gave it to
    // cursor?
    cursor.attach_output_layout(layout);
    let cursor = cursor;
    let color = Rc::new(Cell::new([0.25, 0.25, 0.25, 1.0]));
    (OutputHandler {
         color: color.clone(),
         cursor: cursor
     },
     InputHandler { color: color.clone() })
}

fn main() {
    let mut cursor = Cursor::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let xcursor = xcursor_theme
        .get_cursor("left_ptr".into())
        .expect("Could not load cursor from theme");
    cursor.set_xcursor(Some(xcursor));

    let (output_manager, input_manager) = managers(cursor);
    let compositor = Compositor::new(Box::new(input_manager), Box::new(output_manager));
    compositor.run();
}
<commit_msg>Added escape to the pointer example<commit_after>#[macro_use]
extern crate wlroots;

use std::cell::{Cell, RefCell};
use std::rc::Rc;
use wlroots::compositor::Compositor;
use wlroots::cursor::{Cursor, XCursorTheme};
use wlroots::device::Device;
use wlroots::key_event::KeyEvent;
use wlroots::manager::{InputManagerHandler, KeyboardHandler, OutputManagerHandler, PointerHandler};
use wlroots::output::{Output, OutputLayout};
use wlroots::pointer;
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct OutputHandler {
    color: Rc<Cell<[f32; 4]>>,
    cursor: Cursor
}

struct InputHandler {
    color: Rc<Cell<[f32; 4]>>
}

struct Pointer {
    color: Rc<Cell<[f32; 4]>>,
    default_color: [f32; 4]
}

struct Keyboard;

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self, dev: &mut Device, key_event: &KeyEvent) {
        let keys = key_event.get_input_keys(dev);
        for key in keys {
            if key == KEY_Escape {
                wlroots::terminate()
            }
        }
    }
}

impl PointerHandler for Pointer {
    fn on_button(&mut self, _: &mut Device, event: &pointer::ButtonEvent) {
        if event.state() == WLR_BUTTON_RELEASED {
            self.color.set(self.default_color.clone())
        } else {
            let mut red: [f32; 4] = [0.25, 0.25, 0.25, 1.0];
            red[event.button() as usize % 3] = 1.0;
            self.color.set(red);
        }
    }
}

impl OutputManagerHandler for OutputHandler {
    fn output_added(&mut self, output: &mut Output) {
        let cursor = &mut self.cursor;
        {
            let xcursor = cursor.xcursor().expect("XCursor was not set!");
            let image = &xcursor.images()[0];
            // TODO use output config if present instead of auto
            let layout = cursor
                .output_layout()
                .as_ref()
                .expect("Could not get output layout");
            layout.borrow_mut().add_auto(output);
            if output.set_cursor(image).is_err() {
                wlr_log!(L_DEBUG, "Failed to set hardware cursor");
                return;
            }
        }
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
    }

    fn output_frame(&mut self, output: &mut Output) {
        output.make_current();
        unsafe {
            gl::ClearColor(self.color.get()[0],
                           self.color.get()[1],
                           self.color.get()[2],
                           1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputHandler {
    fn pointer_added(&mut self, _: &mut Device) -> Option<Box<PointerHandler>> {
        Some(Box::new(Pointer {
                          color: self.color.clone(),
                          default_color: self.color.get()
                      }))
    }

    fn keyboard_added(&mut self, _: &mut Device) -> Option<Box<KeyboardHandler>> {
        Some(Box::new(Keyboard))
    }
}

fn managers(mut cursor: Cursor) -> (OutputHandler, InputHandler) {
    let layout = Rc::new(RefCell::new(OutputLayout::new()));
    // TODO Ensure this can be safe...
    // e.g what's stopping me from simply dropping layout now that I gave it to
    // cursor?
    cursor.attach_output_layout(layout);
    let cursor = cursor;
    let color = Rc::new(Cell::new([0.25, 0.25, 0.25, 1.0]));
    (OutputHandler {
         color: color.clone(),
         cursor: cursor
     },
     InputHandler { color: color.clone() })
}

fn main() {
    let mut cursor = Cursor::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let xcursor = xcursor_theme
        .get_cursor("left_ptr".into())
        .expect("Could not load cursor from theme");
    cursor.set_xcursor(Some(xcursor));

    let (output_manager, input_manager) = managers(cursor);
    let compositor = Compositor::new(Box::new(input_manager), Box::new(output_manager));
    compositor.run();
}
<|endoftext|>