<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,
};

#[derive(Clone, Copy, Debug)]
pub enum BuildStrategy {
    OnCanonicalHead,
    ForkCanonicalChainAt(Slot),
}

#[derive(Clone, Copy, Debug)]
pub enum AttestationStrategy {
    AllValidators,
}

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;
}

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,
{
    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,
        }
    }

    pub fn advance_slot(&self) {
        self.chain.slot_clock.advance_slot();
        self.chain.catchup_state().expect("should catchup state");
    }

    pub fn extend_chain(
        &self,
        build_strategy: BuildStrategy,
        blocks: usize,
        attestation_strategy: AttestationStrategy,
    ) {
        // Get an initial state to build the block upon, based on the build strategy.
        let mut state = match build_strategy {
            BuildStrategy::OnCanonicalHead => self.chain.current_state().clone(),
            BuildStrategy::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 build_strategy {
            BuildStrategy::OnCanonicalHead => self.chain.read_slot_clock().unwrap(),
            BuildStrategy::ForkCanonicalChainAt(slot) => slot,
        };

        for _ in 0..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, build_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;
        }
    }

    fn build_block(
        &self,
        mut state: BeaconState<E>,
        slot: Slot,
        build_strategy: BuildStrategy,
    ) -> (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 build_strategy {
            BuildStrategy::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)
    }

    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");
                    }
                }
            });
    }

    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(
            BuildStrategy::OnCanonicalHead,
            num_blocks_produced as usize,
            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>Document beacon chain harness<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, 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"
        );
    }
}
<|endoftext|>


<commit_before>//! Color items, including everything from rgb, hsb/l/v, lap, alpha, luma and more, provided by the
//! palette crate. See [the palette docs](https://docs.rs/palette) for more details or see the
//! [**named**](./named/index.html) module for a set of provided color constants.

pub mod conv;

pub use self::conv::IntoLinSrgba;
pub use self::named::*;
use crate::ui::color;
#[doc(inline)]
pub use palette::*;

/// The default scalar value for working with color components, hues, etc.
pub type DefaultScalar = f32;

/// A color represented as red, green and blue intensities.
///
/// This type is an alias for the `Srgb` type, a type that represents the sRGB color space.
///
/// If you are looking for more advanced control over the RGB space and component type, please see
/// the `palette` crate's generic `Rgb` type.
pub type Rgb<S = DefaultScalar> = Srgb<S>;

/// The same as `Rgb`, but with an alpha value representing opacity.
///
/// This type is an alias for the `Srgba` type, a type that represents the sRGB color space
/// alongside an alpha value.
///
/// If you are looking for more advanced control over the RGB space and component type, please see
/// the `palette` crate's generic `Rgb` type.
pub type Rgba<S = DefaultScalar> = Srgba<S>;

/// A color represented as gray intensity.
///
/// This type is an alias for the `Srgb` type, a type that represents the sRGB color space.
///
/// If you are looking for more advanced control over the RGB space and component type, please see
/// the `palette` crate's generic `Rgb` type.
pub type Gray<S = DefaultScalar> = Srgb<S>;

/// A short-hand constructor for `Rgb::new`.
pub fn rgb<T>(r: T, g: T, b: T) -> Rgb<T>
where
    T: Component,
{
    srgb(r, g, b)
}

/// A short-hand constructor for `Rgb<u8>::new`.
pub fn rgb8(r: u8, g: u8, b: u8) -> Rgb<u8> {
    srgb8(r, g, b)
}

/// A short-hand constructor for `Rgba::new`.
pub fn rgba<T>(r: T, g: T, b: T, a: T) -> Rgba<T>
where
    T: Component,
{
    srgba(r, g, b, a)
}

/// A short-hand constructor for `Rgba<u8>::new`.
pub fn rgba8(r: u8, g: u8, b: u8, a: u8) -> Rgba<u8> {
    srgba8(r, g, b, a)
}

/// A short-hand constructor for `Srgb::new`.
pub fn srgb<T>(r: T, g: T, b: T) -> Srgb<T>
where
    T: Component,
{
    Srgb::new(r, g, b)
}

/// A short-hand constructor for `Srgb<u8>::new`.
pub fn srgb8(r: u8, g: u8, b: u8) -> Srgb<u8> {
    Srgb::new(r, g, b)
}

/// A short-hand constructor for `Srgba::new`.
pub fn srgba<T>(r: T, g: T, b: T, a: T) -> Srgba<T>
where
    T: Component,
{
    Srgba::new(r, g, b, a)
}

/// A short-hand constructor for `Srgba<u8>::new`.
pub fn srgba8(r: u8, g: u8, b: u8, a: u8) -> Srgba<u8> {
    Srgba::new(r, g, b, a)
}

/// A short-hand constructor for `LinSrgb::new`.
pub fn lin_srgb<T>(r: T, g: T, b: T) -> LinSrgb<T>
where
    T: Component,
{
    LinSrgb::new(r, g, b)
}

/// A short-hand constructor for `LinSrgba::new`.
pub fn lin_srgba<T>(r: T, g: T, b: T, a: T) -> LinSrgba<T>
where
    T: Component,
{
    LinSrgba::new(r, g, b, a)
}

/// Create a new color from a hexadecimal int literal
#[inline]
pub fn rgb_u32(c: u32) -> color::Color {
    let blue: u8 = (c & 0xFF) as u8;
    let green: u8 = ((c >> 8) & 0xFF) as u8;
    let red: u8 = ((c >> 16) & 0xFF) as u8;
    color::rgb_bytes(red, green, blue)
}

/// A short-hand constructor for `Hsl::new(RgbHue::from_degrees(h * 360.0), s, l)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsl(h: f32, s: f32, l: f32) -> Hsl {
    Hsl::new(RgbHue::from_degrees(h * 360.0), s, l)
}

/// A short-hand constructor for `Hsla::new(RgbHue::from_degrees(h * 360.0), s, l, a)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla {
    Hsla::new(RgbHue::from_degrees(h * 360.0), s, l, a)
}

/// A short-hand constructor for `Hsv::new(RgbHue::from_degrees(h * 360.0), s, v)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsv(h: f32, s: f32, v: f32) -> Hsv {
    Hsv::new(RgbHue::from_degrees(h * 360.0), s, v)
}

/// A short-hand constructor for `Hsva::new(RgbHue::from_degrees(h * 360.0), s, v, a)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsva(h: f32, s: f32, v: f32, a: f32) -> Hsva {
    Hsva::new(RgbHue::from_degrees(h * 360.0), s, v, a)
}

/// A short-hand constructor for `Gray::new`.
pub fn gray<T>(g: T) -> Gray<T>
where
    T: Component,
{
    srgb(g, g, g)
}

#[test]
fn test_rgb_u32() {
    assert_eq!(rgb_u32(0xFF8000), color::rgb_bytes(255, 128, 0));
}
<commit_msg>return Rgb<u8> instead of nannou::ui::color::Color<commit_after>//! Color items, including everything from rgb, hsb/l/v, lap, alpha, luma and more, provided by the
//! palette crate. See [the palette docs](https://docs.rs/palette) for more details or see the
//! [**named**](./named/index.html) module for a set of provided color constants.

pub mod conv;

pub use self::conv::IntoLinSrgba;
pub use self::named::*;
#[doc(inline)]
pub use palette::*;

/// The default scalar value for working with color components, hues, etc.
pub type DefaultScalar = f32;

/// A color represented as red, green and blue intensities.
///
/// This type is an alias for the `Srgb` type, a type that represents the sRGB color space.
///
/// If you are looking for more advanced control over the RGB space and component type, please see
/// the `palette` crate's generic `Rgb` type.
pub type Rgb<S = DefaultScalar> = Srgb<S>;

/// The same as `Rgb`, but with an alpha value representing opacity.
///
/// This type is an alias for the `Srgba` type, a type that represents the sRGB color space
/// alongside an alpha value.
///
/// If you are looking for more advanced control over the RGB space and component type, please see
/// the `palette` crate's generic `Rgb` type.
pub type Rgba<S = DefaultScalar> = Srgba<S>;

/// A color represented as gray intensity.
///
/// This type is an alias for the `Srgb` type, a type that represents the sRGB color space.
///
/// If you are looking for more advanced control over the RGB space and component type, please see
/// the `palette` crate's generic `Rgb` type.
pub type Gray<S = DefaultScalar> = Srgb<S>;

/// A short-hand constructor for `Rgb::new`.
pub fn rgb<T>(r: T, g: T, b: T) -> Rgb<T>
where
    T: Component,
{
    srgb(r, g, b)
}

/// A short-hand constructor for `Rgb<u8>::new`.
pub fn rgb8(r: u8, g: u8, b: u8) -> Rgb<u8> {
    srgb8(r, g, b)
}

/// A short-hand constructor for `Rgba::new`.
pub fn rgba<T>(r: T, g: T, b: T, a: T) -> Rgba<T>
where
    T: Component,
{
    srgba(r, g, b, a)
}

/// A short-hand constructor for `Rgba<u8>::new`.
pub fn rgba8(r: u8, g: u8, b: u8, a: u8) -> Rgba<u8> {
    srgba8(r, g, b, a)
}

/// A short-hand constructor for `Srgb::new`.
pub fn srgb<T>(r: T, g: T, b: T) -> Srgb<T>
where
    T: Component,
{
    Srgb::new(r, g, b)
}

/// A short-hand constructor for `Srgb<u8>::new`.
pub fn srgb8(r: u8, g: u8, b: u8) -> Srgb<u8> {
    Srgb::new(r, g, b)
}

/// A short-hand constructor for `Srgba::new`.
pub fn srgba<T>(r: T, g: T, b: T, a: T) -> Srgba<T>
where
    T: Component,
{
    Srgba::new(r, g, b, a)
}

/// A short-hand constructor for `Srgba<u8>::new`.
pub fn srgba8(r: u8, g: u8, b: u8, a: u8) -> Srgba<u8> {
    Srgba::new(r, g, b, a)
}

/// A short-hand constructor for `LinSrgb::new`.
pub fn lin_srgb<T>(r: T, g: T, b: T) -> LinSrgb<T>
where
    T: Component,
{
    LinSrgb::new(r, g, b)
}

/// A short-hand constructor for `LinSrgba::new`.
pub fn lin_srgba<T>(r: T, g: T, b: T, a: T) -> LinSrgba<T>
where
    T: Component,
{
    LinSrgba::new(r, g, b, a)
}

/// Create a new color from a hexadecimal int literal
#[inline]
pub fn rgb_u32(c: u32) -> Rgb<u8> {
    let blue: u8 = (c & 0xFF) as u8;
    let green: u8 = ((c >> 8) & 0xFF) as u8;
    let red: u8 = ((c >> 16) & 0xFF) as u8;
    rgb8(red, green, blue)
}

/// A short-hand constructor for `Hsl::new(RgbHue::from_degrees(h * 360.0), s, l)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsl(h: f32, s: f32, l: f32) -> Hsl {
    Hsl::new(RgbHue::from_degrees(h * 360.0), s, l)
}

/// A short-hand constructor for `Hsla::new(RgbHue::from_degrees(h * 360.0), s, l, a)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla {
    Hsla::new(RgbHue::from_degrees(h * 360.0), s, l, a)
}

/// A short-hand constructor for `Hsv::new(RgbHue::from_degrees(h * 360.0), s, v)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsv(h: f32, s: f32, v: f32) -> Hsv {
    Hsv::new(RgbHue::from_degrees(h * 360.0), s, v)
}

/// A short-hand constructor for `Hsva::new(RgbHue::from_degrees(h * 360.0), s, v, a)`.
///
/// The given hue expects a value between `0.0` and `1.0` where `0.0` is 0 degress and `1.0` is
/// 360 degrees (or 2 PI radians).
pub fn hsva(h: f32, s: f32, v: f32, a: f32) -> Hsva {
    Hsva::new(RgbHue::from_degrees(h * 360.0), s, v, a)
}

/// A short-hand constructor for `Gray::new`.
pub fn gray<T>(g: T) -> Gray<T>
where
    T: Component,
{
    srgb(g, g, g)
}

#[test]
fn test_rgb_u32() {
    assert_eq!(rgb_u32(0xFF8000), rgb8(255, 128, 0));
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![cfg(test)]
#![feature(plugin, test)]

extern crate app_units;
extern crate cssparser;
extern crate euclid;
#[macro_use] extern crate html5ever;
extern crate parking_lot;
extern crate rayon;
extern crate rustc_serialize;
extern crate selectors;
extern crate servo_arc;
extern crate servo_atoms;
extern crate servo_config;
extern crate servo_url;
#[macro_use] extern crate size_of_test;
#[macro_use] extern crate style;
extern crate style_traits;
extern crate test;

mod animated_properties;
mod attr;
mod custom_properties;
mod keyframes;
mod logical_geometry;
mod media_queries;
mod parsing;
mod properties;
mod rule_tree;
mod size_of;
#[path = "../stylo/specified_values.rs"]
mod specified_values;
mod str;
mod stylesheets;
mod stylist;
mod viewport;

mod writing_modes {
    use style::logical_geometry::WritingMode;
    use style::properties::{INITIAL_SERVO_VALUES, get_writing_mode};

    #[test]
    fn initial_writing_mode_is_empty() {
        assert_eq!(get_writing_mode(INITIAL_SERVO_VALUES.get_inheritedbox()), WritingMode::empty())
    }
}
<commit_msg>Remove unused feature flag<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![cfg(test)]
#![feature(test)]

extern crate app_units;
extern crate cssparser;
extern crate euclid;
#[macro_use] extern crate html5ever;
extern crate parking_lot;
extern crate rayon;
extern crate rustc_serialize;
extern crate selectors;
extern crate servo_arc;
extern crate servo_atoms;
extern crate servo_config;
extern crate servo_url;
#[macro_use] extern crate size_of_test;
#[macro_use] extern crate style;
extern crate style_traits;
extern crate test;

mod animated_properties;
mod attr;
mod custom_properties;
mod keyframes;
mod logical_geometry;
mod media_queries;
mod parsing;
mod properties;
mod rule_tree;
mod size_of;
#[path = "../stylo/specified_values.rs"]
mod specified_values;
mod str;
mod stylesheets;
mod stylist;
mod viewport;

mod writing_modes {
    use style::logical_geometry::WritingMode;
    use style::properties::{INITIAL_SERVO_VALUES, get_writing_mode};

    #[test]
    fn initial_writing_mode_is_empty() {
        assert_eq!(get_writing_mode(INITIAL_SERVO_VALUES.get_inheritedbox()), WritingMode::empty())
    }
}
<|endoftext|>


<commit_before>//! Pattern-sequence data structures and implementations.

use std::ops::Index;
use std::iter::FromIterator;

use util::set::{self, Contains};
use super::{Atom, Class, Element, Repetition, Union};
use super::{Reduce, flatten_and_reduce};

// To hide the implementation details, we wrap the type alias in
// a private submodule.
mod seq_impl {
    use ::pattern::Element;
    pub type Inner<T> = Vec<Element<T>>;
}

/// Sequence of patterns.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Sequence<T: Atom>(seq_impl::Inner<T>);

impl<T: Atom> Sequence<T> {
    /// Create a new sequence from the given vector.
    pub fn new(v: Vec<Element<T>>) -> Self {
        if v.len() < 2 {
            panic!("Sequences must have at least two elements");
        }
        Sequence(v)
    }

    /// Get the number of elements in the sequence.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Fetch an iterator over the elements in the sequence
    pub fn iter<'a>(&'a self) -> impl Iterator<Item=&'a Element<T>> {
        self.0.iter()
    }

    fn into_inner(self) -> seq_impl::Inner<T> {
        self.0
    }

    /// Transforms each contained atom using the supplied function or closure
    /// to produce a new sequence.
    pub fn map_atoms<U, F>(self, f: F) -> Sequence<U>
        where F: Fn(T) -> U,
              U: Atom
    {
        self.0.into_iter().map(|elt| elt.map_atoms(&f)).collect()
    }
}

impl<T: Atom> Reduce for Sequence<T> {
    type Output = Option<Element<T>>;

    /// Flatten the sequence and apply implementation-defined optimizations.
    fn reduce(mut self) -> Self::Output {
        // Flatten and reduce the vector *first* so we can reduce `self` based
        // on the size of the *reduced* vector.
       flatten_and_reduce(&mut self.0, Element::Wildcard,
                           |elt| match elt { &Element::Sequence(ref s) => Some(s.len()), _ => None },
                           |elt| match elt { Element::Sequence(s) => s.into_inner(), _ => unreachable!() });
        match self.0.len() {
            0 => None,
            1 => Some(self.0.swap_remove(0)),
            _ => Some(Element::Sequence(self))
        }
    }
}

impl<T: Atom> Index<usize> for Sequence<T> {
    type Output = Element<T>;
    fn index(&self, index: usize) -> &Self::Output {
        &self.0[index]
    }

}

impl<T: Atom> FromIterator<Element<T>> for Sequence<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=Element<T>>
    {
        Sequence(iter.into_iter().collect())
    }
}

impl<T: Atom> set::Contains<T> for Sequence<T> {
    /// A sequence always contains at least two elements, and thus will never
    /// match a single atom.
    #[inline(always)]
    fn contains(&self, _: T) -> bool {
        false
    }
}

impl<T: Atom> set::IsSubsetOf<T> for Sequence<T> {
    /// A sequence is a subset of a particular atom whenever the sequence has
    /// length one, and the first element is a subset of that atom.
    #[inline(always)]
    fn is_subset_of(&self, atom: &T) -> bool {
        self.len() == 1 && self[0].is_subset_of(atom)
    }
}

// A sequence `A` can be a subset of another sequence `B` *if* both have the
// same length and each element in `A` is a subset of the corresponding element
// in `B`:
//
// A ⊂ B ⇔ |A|=|B|=n ∧ Aᵢ ⊂ Bᵢ ∀ i∈[0,n]
impl<T: Atom> set::IsSubsetOf<Sequence<T>> for Sequence<T> {
    fn is_subset_of(&self, other: &Sequence<T>) -> bool {
        other.len() == self.len() &&
            self.iter().zip(other.iter()).all(|(u, v)| u.is_subset_of(v))
    }
}

impl<T: Atom> set::IsSubsetOf<Class<T>> for Sequence<T> {
    /// A sequence is never a subset of an atom class because sequences are
    /// guaranteed to contain at least two elements.
    #[inline(always)]
    fn is_subset_of(&self, _: &Class<T>) -> bool {
        false
    }
}

impl<T: Atom> set::IsSubsetOf<Union<T>> for Sequence<T> {
    /// A sequence is a subset of a union whenever it is a subset of one of the
    /// union's members.
    fn is_subset_of(&self, union: &Union<T>) -> bool {
        union.iter().any(|m| self.is_subset_of(m))
    }
}

impl<T: Atom> set::IsSubsetOf<Repetition<T>> for Sequence<T> {
    /// A sequence is a subset of a repetition if the sequence's length is
    /// contained by the repetition's count and all members of the sequence are
    /// subsets of the repeated element.
    fn is_subset_of(&self, rep: &Repetition<T>) -> bool {
        rep.count().contains(self.len()) && self.iter().all(|elt| elt.is_subset_of(rep.element()))
    }
}

impl<T: Atom> set::IsSubsetOf<Element<T>> for Sequence<T> {
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),
            &Element::Sequence(ref s) => self.is_subset_of(s),
            &Element::Union(ref u) => self.is_subset_of(u),
            &Element::Repeat(ref r) => self.is_subset_of(r),

            &Element::Anchor(_) => false,
            &Element::Atom(_) => false,
            &Element::Class(_) => false,
            &Element::Wildcard => false,
        }
    }
}
<commit_msg>pattern/sequence: document panic behaviour of `Sequence::new`<commit_after>//! Pattern-sequence data structures and implementations.

use std::ops::Index;
use std::iter::FromIterator;

use util::set::{self, Contains};
use super::{Atom, Class, Element, Repetition, Union};
use super::{Reduce, flatten_and_reduce};

// To hide the implementation details, we wrap the type alias in
// a private submodule.
mod seq_impl {
    use ::pattern::Element;
    pub type Inner<T> = Vec<Element<T>>;
}

/// Sequence of patterns.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Sequence<T: Atom>(seq_impl::Inner<T>);

impl<T: Atom> Sequence<T> {
    /// Create a new sequence from the given vector.
    ///
    /// This method will **panic** if the given vector is not at least two
    /// elements long.
    pub fn new(v: Vec<Element<T>>) -> Self {
        if v.len() < 2 {
            panic!("Sequences must have at least two elements");
        }
        Sequence(v)
    }

    /// Get the number of elements in the sequence.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Fetch an iterator over the elements in the sequence
    pub fn iter<'a>(&'a self) -> impl Iterator<Item=&'a Element<T>> {
        self.0.iter()
    }

    fn into_inner(self) -> seq_impl::Inner<T> {
        self.0
    }

    /// Transforms each contained atom using the supplied function or closure
    /// to produce a new sequence.
    pub fn map_atoms<U, F>(self, f: F) -> Sequence<U>
        where F: Fn(T) -> U,
              U: Atom
    {
        self.0.into_iter().map(|elt| elt.map_atoms(&f)).collect()
    }
}

impl<T: Atom> Reduce for Sequence<T> {
    type Output = Option<Element<T>>;

    /// Flatten the sequence and apply implementation-defined optimizations.
    fn reduce(mut self) -> Self::Output {
        // Flatten and reduce the vector *first* so we can reduce `self` based
        // on the size of the *reduced* vector.
       flatten_and_reduce(&mut self.0, Element::Wildcard,
                           |elt| match elt { &Element::Sequence(ref s) => Some(s.len()), _ => None },
                           |elt| match elt { Element::Sequence(s) => s.into_inner(), _ => unreachable!() });
        match self.0.len() {
            0 => None,
            1 => Some(self.0.swap_remove(0)),
            _ => Some(Element::Sequence(self))
        }
    }
}

impl<T: Atom> Index<usize> for Sequence<T> {
    type Output = Element<T>;
    fn index(&self, index: usize) -> &Self::Output {
        &self.0[index]
    }

}

impl<T: Atom> FromIterator<Element<T>> for Sequence<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=Element<T>>
    {
        Sequence(iter.into_iter().collect())
    }
}

impl<T: Atom> set::Contains<T> for Sequence<T> {
    /// A sequence always contains at least two elements, and thus will never
    /// match a single atom.
    #[inline(always)]
    fn contains(&self, _: T) -> bool {
        false
    }
}

impl<T: Atom> set::IsSubsetOf<T> for Sequence<T> {
    /// A sequence is a subset of a particular atom whenever the sequence has
    /// length one, and the first element is a subset of that atom.
    #[inline(always)]
    fn is_subset_of(&self, atom: &T) -> bool {
        self.len() == 1 && self[0].is_subset_of(atom)
    }
}

// A sequence `A` can be a subset of another sequence `B` *if* both have the
// same length and each element in `A` is a subset of the corresponding element
// in `B`:
//
// A ⊂ B ⇔ |A|=|B|=n ∧ Aᵢ ⊂ Bᵢ ∀ i∈[0,n]
impl<T: Atom> set::IsSubsetOf<Sequence<T>> for Sequence<T> {
    fn is_subset_of(&self, other: &Sequence<T>) -> bool {
        other.len() == self.len() &&
            self.iter().zip(other.iter()).all(|(u, v)| u.is_subset_of(v))
    }
}

impl<T: Atom> set::IsSubsetOf<Class<T>> for Sequence<T> {
    /// A sequence is never a subset of an atom class because sequences are
    /// guaranteed to contain at least two elements.
    #[inline(always)]
    fn is_subset_of(&self, _: &Class<T>) -> bool {
        false
    }
}

impl<T: Atom> set::IsSubsetOf<Union<T>> for Sequence<T> {
    /// A sequence is a subset of a union whenever it is a subset of one of the
    /// union's members.
    fn is_subset_of(&self, union: &Union<T>) -> bool {
        union.iter().any(|m| self.is_subset_of(m))
    }
}

impl<T: Atom> set::IsSubsetOf<Repetition<T>> for Sequence<T> {
    /// A sequence is a subset of a repetition if the sequence's length is
    /// contained by the repetition's count and all members of the sequence are
    /// subsets of the repeated element.
    fn is_subset_of(&self, rep: &Repetition<T>) -> bool {
        rep.count().contains(self.len()) && self.iter().all(|elt| elt.is_subset_of(rep.element()))
    }
}

impl<T: Atom> set::IsSubsetOf<Element<T>> for Sequence<T> {
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),
            &Element::Sequence(ref s) => self.is_subset_of(s),
            &Element::Union(ref u) => self.is_subset_of(u),
            &Element::Repeat(ref r) => self.is_subset_of(r),

            &Element::Anchor(_) => false,
            &Element::Atom(_) => false,
            &Element::Class(_) => false,
            &Element::Wildcard => false,
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_debug_implementations, unreachable_pub, rust_2018_idioms)]
#![cfg_attr(test, deny(warnings))]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]

//! Macros for use with Tokio

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;

/// Marks async function to be executed by selected runtime.
///
/// ## Options:
///
/// - `single_thread` - Uses `current_thread`.
/// - `multi_thread` - Uses multi-threaded runtime. Used by default.
///
/// ## Usage
///
/// ### Select runtime
///
/// ```rust
///#![feature(async_await)]
///
/// #[tokio::main(single_thread)]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
/// ### Using default
///
/// ```rust
///#![feature(async_await)]
///
/// #[tokio::main]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
    enum RuntimeType {
        Single,
        Multi,
    }

    let input = syn::parse_macro_input!(item as syn::ItemFn);
    let args = syn::parse_macro_input!(args as syn::AttributeArgs);

    let ret = &input.decl.output;
    let name = &input.ident;
    let body = &input.block;
    let attrs = &input.attrs;

    if input.asyncness.is_none() {
        let tokens = quote_spanned! { input.span() =>
          compile_error!("the async keyword is missing from the function declaration");
        };

        return TokenStream::from(tokens);
    }

    let mut runtime = RuntimeType::Multi;

    for arg in args {
        match arg {
            syn::NestedMeta::Meta(syn::Meta::Word(ident)) => {
                match ident.to_string().to_lowercase().as_str() {
                    "multi_thread" => runtime = RuntimeType::Multi,
                    "single_thread" => runtime = RuntimeType::Single,
                    name => panic!("Unknown attribute {} is specified", name),
                }
            }
            _ => (),
        }
    }

    let result = match runtime {
        RuntimeType::Multi => quote! {
            #(#attrs)*
            fn #name() #ret {
                let mut rt = tokio::runtime::Runtime::new().unwrap();
                rt.block_on(async { #body })
            }
        },
        RuntimeType::Single => quote! {
            #(#attrs)*
            fn #name() #ret {
                let mut rt = tokio::runtime::current_thread::Runtime::new().unwrap();
                rt.block_on(async { #body })
            }
        },
    };

    result.into()
}

/// Marks async function to be executed by runtime, suitable to test enviornment
///
/// Uses `current_thread` runtime.
///
/// # Examples
///
/// ```ignore
/// #![feature(async_await)]
///
/// #[tokio::test]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
#[proc_macro_attribute]
pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(item as syn::ItemFn);

    let ret = &input.decl.output;
    let name = &input.ident;
    let body = &input.block;
    let attrs = &input.attrs;

    if input.asyncness.is_none() {
        let tokens = quote_spanned! { input.span() =>
          compile_error!("the async keyword is missing from the function declaration");
        };

        return TokenStream::from(tokens);
    }

    let result = quote! {
        #[test]
        #(#attrs)*
        fn #name() #ret {
            let mut rt = tokio::runtime::current_thread::Runtime::new().unwrap();
            rt.block_on(async { #body })
        }
    };

    result.into()
}
<commit_msg>macros: detect double test attribute (#1336)<commit_after>#![deny(missing_debug_implementations, unreachable_pub, rust_2018_idioms)]
#![cfg_attr(test, deny(warnings))]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]

//! Macros for use with Tokio

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;

/// Marks async function to be executed by selected runtime.
///
/// ## Options:
///
/// - `single_thread` - Uses `current_thread`.
/// - `multi_thread` - Uses multi-threaded runtime. Used by default.
///
/// ## Usage
///
/// ### Select runtime
///
/// ```rust
///#![feature(async_await)]
///
/// #[tokio::main(single_thread)]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
/// ### Using default
///
/// ```rust
///#![feature(async_await)]
///
/// #[tokio::main]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
    enum RuntimeType {
        Single,
        Multi,
    }

    let input = syn::parse_macro_input!(item as syn::ItemFn);
    let args = syn::parse_macro_input!(args as syn::AttributeArgs);

    let ret = &input.decl.output;
    let name = &input.ident;
    let body = &input.block;
    let attrs = &input.attrs;

    if input.asyncness.is_none() {
        let tokens = quote_spanned! { input.span() =>
          compile_error!("the async keyword is missing from the function declaration");
        };

        return TokenStream::from(tokens);
    }

    let mut runtime = RuntimeType::Multi;

    for arg in args {
        match arg {
            syn::NestedMeta::Meta(syn::Meta::Word(ident)) => {
                match ident.to_string().to_lowercase().as_str() {
                    "multi_thread" => runtime = RuntimeType::Multi,
                    "single_thread" => runtime = RuntimeType::Single,
                    name => panic!("Unknown attribute {} is specified", name),
                }
            }
            _ => (),
        }
    }

    let result = match runtime {
        RuntimeType::Multi => quote! {
            #(#attrs)*
            fn #name() #ret {
                let mut rt = tokio::runtime::Runtime::new().unwrap();
                rt.block_on(async { #body })
            }
        },
        RuntimeType::Single => quote! {
            #(#attrs)*
            fn #name() #ret {
                let mut rt = tokio::runtime::current_thread::Runtime::new().unwrap();
                rt.block_on(async { #body })
            }
        },
    };

    result.into()
}

/// Marks async function to be executed by runtime, suitable to test enviornment
///
/// Uses `current_thread` runtime.
///
/// # Examples
///
/// ```ignore
/// #![feature(async_await)]
///
/// #[tokio::test]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
#[proc_macro_attribute]
pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(item as syn::ItemFn);

    let ret = &input.decl.output;
    let name = &input.ident;
    let body = &input.block;
    let attrs = &input.attrs;

    for attr in attrs {
        if attr.path.is_ident("test") {
            let tokens = quote_spanned! { input.span() =>
                compile_error!("second test attribute is supplied");
            };

            return TokenStream::from(tokens);
        }
    }

    if input.asyncness.is_none() {
        let tokens = quote_spanned! { input.span() =>
          compile_error!("the async keyword is missing from the function declaration");
        };

        return TokenStream::from(tokens);
    }

    let result = quote! {
        #[test]
        #(#attrs)*
        fn #name() #ret {
            let mut rt = tokio::runtime::current_thread::Runtime::new().unwrap();
            rt.block_on(async { #body })
        }
    };

    result.into()
}
<|endoftext|>


<commit_before>#![cfg_attr(not(feature = "rt"), allow(dead_code))]

//! Source of time abstraction.
//!
//! By default, `std::time::Instant::now()` is used. However, when the
//! `test-util` feature flag is enabled, the values returned for `now()` are
//! configurable.

cfg_not_test_util! {
    use crate::time::{Instant};

    #[derive(Debug, Clone)]
    pub(crate) struct Clock {}

    pub(crate) fn now() -> Instant {
        Instant::from_std(std::time::Instant::now())
    }

    impl Clock {
        pub(crate) fn new(_enable_pausing: bool, _start_paused: bool) -> Clock {
            Clock {}
        }

        pub(crate) fn now(&self) -> Instant {
            now()
        }
    }
}

cfg_test_util! {
    use crate::time::{Duration, Instant};
    use std::sync::{Arc, Mutex};

    cfg_rt! {
        fn clock() -> Option<Clock> {
            crate::runtime::context::clock()
        }
    }

    cfg_not_rt! {
        fn clock() -> Option<Clock> {
            None
        }
    }

    /// A handle to a source of time.
    #[derive(Debug, Clone)]
    pub(crate) struct Clock {
        inner: Arc<Mutex<Inner>>,
    }

    #[derive(Debug)]
    struct Inner {
        /// True if the ability to pause time is enabled.
        enable_pausing: bool,

        /// Instant to use as the clock's base instant.
        base: std::time::Instant,

        /// Instant at which the clock was last unfrozen
        unfrozen: Option<std::time::Instant>,
    }

    /// Pause time
    ///
    /// The current value of `Instant::now()` is saved and all subsequent calls
    /// to `Instant::now()` until the timer wheel is checked again will return
    /// the saved value. Once the timer wheel is checked, time will immediately
    /// advance to the next registered `Sleep`. This is useful for running tests
    /// that depend on time.
    ///
    /// Pausing time requires the `current_thread` Tokio runtime. This is the
    /// default runtime used by `#[tokio::test]`. The runtime can be initialized
    /// with time in a paused state using the `Builder::start_paused` method.
    ///
    /// # Panics
    ///
    /// Panics if time is already frozen or if called from outside of a
    /// `current_thread` Tokio runtime.
    pub fn pause() {
        let clock = clock().expect("time cannot be frozen from outside the Tokio runtime");
        clock.pause();
    }

    /// Resume time
    ///
    /// Clears the saved `Instant::now()` value. Subsequent calls to
    /// `Instant::now()` will return the value returned by the system call.
    ///
    /// # Panics
    ///
    /// Panics if time is not frozen or if called from outside of the Tokio
    /// runtime.
    pub fn resume() {
        let clock = clock().expect("time cannot be frozen from outside the Tokio runtime");
        let mut inner = clock.inner.lock().unwrap();

        if inner.unfrozen.is_some() {
            panic!("time is not frozen");
        }

        inner.unfrozen = Some(std::time::Instant::now());
    }

    /// Advance time
    ///
    /// Increments the saved `Instant::now()` value by `duration`. Subsequent
    /// calls to `Instant::now()` will return the result of the increment.
    ///
    /// # Panics
    ///
    /// Panics if time is not frozen or if called from outside of the Tokio
    /// runtime.
    pub async fn advance(duration: Duration) {
        let clock = clock().expect("time cannot be frozen from outside the Tokio runtime");
        clock.advance(duration);

        crate::task::yield_now().await;
    }

    /// Return the current instant, factoring in frozen time.
    pub(crate) fn now() -> Instant {
        if let Some(clock) = clock() {
            clock.now()
        } else {
            Instant::from_std(std::time::Instant::now())
        }
    }

    impl Clock {
        /// Return a new `Clock` instance that uses the current execution context's
        /// source of time.
        pub(crate) fn new(enable_pausing: bool, start_paused: bool) -> Clock {
            let now = std::time::Instant::now();

            let clock = Clock {
                inner: Arc::new(Mutex::new(Inner {
                    enable_pausing,
                    base: now,
                    unfrozen: Some(now),
                })),
            };

            if start_paused {
                clock.pause();
            }

            clock
        }

        pub(crate) fn pause(&self) {
            let mut inner = self.inner.lock().unwrap();

            if !inner.enable_pausing {
                drop(inner); // avoid poisoning the lock
                panic!("`time::pause()` requires the `current_thread` Tokio runtime. \
                        This is the default Runtime used by `#[tokio::test].");
            }

            let elapsed = inner.unfrozen.as_ref().expect("time is already frozen").elapsed();
            inner.base += elapsed;
            inner.unfrozen = None;
        }

        pub(crate) fn is_paused(&self) -> bool {
            let inner = self.inner.lock().unwrap();
            inner.unfrozen.is_none()
        }

        pub(crate) fn advance(&self, duration: Duration) {
            let mut inner = self.inner.lock().unwrap();

            if inner.unfrozen.is_some() {
                panic!("time is not frozen");
            }

            inner.base += duration;
        }

        pub(crate) fn now(&self) -> Instant {
            let inner = self.inner.lock().unwrap();

            let mut ret = inner.base;

            if let Some(unfrozen) = inner.unfrozen {
                ret += unfrozen.elapsed();
            }

            Instant::from_std(ret)
        }
    }
}
<commit_msg>time: document auto-advancing behavior of runtime (#3763)<commit_after>#![cfg_attr(not(feature = "rt"), allow(dead_code))]

//! Source of time abstraction.
//!
//! By default, `std::time::Instant::now()` is used. However, when the
//! `test-util` feature flag is enabled, the values returned for `now()` are
//! configurable.

cfg_not_test_util! {
    use crate::time::{Instant};

    #[derive(Debug, Clone)]
    pub(crate) struct Clock {}

    pub(crate) fn now() -> Instant {
        Instant::from_std(std::time::Instant::now())
    }

    impl Clock {
        pub(crate) fn new(_enable_pausing: bool, _start_paused: bool) -> Clock {
            Clock {}
        }

        pub(crate) fn now(&self) -> Instant {
            now()
        }
    }
}

cfg_test_util! {
    use crate::time::{Duration, Instant};
    use std::sync::{Arc, Mutex};

    cfg_rt! {
        fn clock() -> Option<Clock> {
            crate::runtime::context::clock()
        }
    }

    cfg_not_rt! {
        fn clock() -> Option<Clock> {
            None
        }
    }

    /// A handle to a source of time.
    #[derive(Debug, Clone)]
    pub(crate) struct Clock {
        inner: Arc<Mutex<Inner>>,
    }

    #[derive(Debug)]
    struct Inner {
        /// True if the ability to pause time is enabled.
        enable_pausing: bool,

        /// Instant to use as the clock's base instant.
        base: std::time::Instant,

        /// Instant at which the clock was last unfrozen
        unfrozen: Option<std::time::Instant>,
    }

    /// Pause time
    ///
    /// The current value of `Instant::now()` is saved and all subsequent calls
    /// to `Instant::now()` until the timer wheel is checked again will return
    /// the saved value. Once the timer wheel is checked, time will immediately
    /// advance to the next registered `Sleep`. This is useful for running tests
    /// that depend on time.
    ///
    /// Pausing time requires the `current_thread` Tokio runtime. This is the
    /// default runtime used by `#[tokio::test]`. The runtime can be initialized
    /// with time in a paused state using the `Builder::start_paused` method.
    ///
    /// # Panics
    ///
    /// Panics if time is already frozen or if called from outside of a
    /// `current_thread` Tokio runtime.
    ///
    /// # Auto-advance
    ///
    /// If time is paused and the runtime has no work to do, the clock is
    /// auto-advanced to the next pending timer. This means that [`Sleep`] or
    /// other timer-backed primitives can cause the runtime to advance the
    /// current time when awaited.
    ///
    /// [`Sleep`]: crate::time::Sleep
    pub fn pause() {
        let clock = clock().expect("time cannot be frozen from outside the Tokio runtime");
        clock.pause();
    }

    /// Resume time
    ///
    /// Clears the saved `Instant::now()` value. Subsequent calls to
    /// `Instant::now()` will return the value returned by the system call.
    ///
    /// # Panics
    ///
    /// Panics if time is not frozen or if called from outside of the Tokio
    /// runtime.
    pub fn resume() {
        let clock = clock().expect("time cannot be frozen from outside the Tokio runtime");
        let mut inner = clock.inner.lock().unwrap();

        if inner.unfrozen.is_some() {
            panic!("time is not frozen");
        }

        inner.unfrozen = Some(std::time::Instant::now());
    }

    /// Advance time
    ///
    /// Increments the saved `Instant::now()` value by `duration`. Subsequent
    /// calls to `Instant::now()` will return the result of the increment.
    ///
    /// # Panics
    ///
    /// Panics if time is not frozen or if called from outside of the Tokio
    /// runtime.
    ///
    /// # Auto-advance
    ///
    /// If the time is paused and there is no work to do, the runtime advances
    /// time to the next timer. See [`pause`](pause#auto-advance) for more
    /// details.
    pub async fn advance(duration: Duration) {
        let clock = clock().expect("time cannot be frozen from outside the Tokio runtime");
        clock.advance(duration);

        crate::task::yield_now().await;
    }

    /// Return the current instant, factoring in frozen time.
    pub(crate) fn now() -> Instant {
        if let Some(clock) = clock() {
            clock.now()
        } else {
            Instant::from_std(std::time::Instant::now())
        }
    }

    impl Clock {
        /// Return a new `Clock` instance that uses the current execution context's
        /// source of time.
        pub(crate) fn new(enable_pausing: bool, start_paused: bool) -> Clock {
            let now = std::time::Instant::now();

            let clock = Clock {
                inner: Arc::new(Mutex::new(Inner {
                    enable_pausing,
                    base: now,
                    unfrozen: Some(now),
                })),
            };

            if start_paused {
                clock.pause();
            }

            clock
        }

        pub(crate) fn pause(&self) {
            let mut inner = self.inner.lock().unwrap();

            if !inner.enable_pausing {
                drop(inner); // avoid poisoning the lock
                panic!("`time::pause()` requires the `current_thread` Tokio runtime. \
                        This is the default Runtime used by `#[tokio::test].");
            }

            let elapsed = inner.unfrozen.as_ref().expect("time is already frozen").elapsed();
            inner.base += elapsed;
            inner.unfrozen = None;
        }

        pub(crate) fn is_paused(&self) -> bool {
            let inner = self.inner.lock().unwrap();
            inner.unfrozen.is_none()
        }

        pub(crate) fn advance(&self, duration: Duration) {
            let mut inner = self.inner.lock().unwrap();

            if inner.unfrozen.is_some() {
                panic!("time is not frozen");
            }

            inner.base += duration;
        }

        pub(crate) fn now(&self) -> Instant {
            let inner = self.inner.lock().unwrap();

            let mut ret = inner.base;

            if let Some(unfrozen) = inner.unfrozen {
                ret += unfrozen.elapsed();
            }

            Instant::from_std(ret)
        }
    }
}
<|endoftext|>


<commit_before>use crate::support::{clippy_is_available, project, registry::Package};

#[cargo_test]
// Clippy should never be considered fresh.
fn clippy_force_rebuild() {
    if !clippy_is_available() {
        return;
    }

    Package::new("dep1", "0.1.0").publish();

    // This is just a random clippy lint (assertions_on_constants) that
    // hopefully won't change much in the future.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            dep1 = "0.1"
            "#,
        )
        .file("src/lib.rs", "pub fn f() { assert!(true); }")
        .build();

    p.cargo("clippy-preview -Zunstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[..]assert!(true)[..]")
        .run();

    // Make sure it runs again.
    p.cargo("clippy-preview -Zunstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[FRESH] dep1 v0.1.0")
        .with_stderr_contains("[..]assert!(true)[..]")
        .run();
}
<commit_msg>add unit test<commit_after>use crate::support::{clippy_is_available, project, registry::Package};

#[cargo_test]
// Clippy should never be considered fresh.
fn clippy_force_rebuild() {
    if !clippy_is_available() {
        return;
    }

    Package::new("dep1", "0.1.0").publish();

    // This is just a random clippy lint (assertions_on_constants) that
    // hopefully won't change much in the future.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            dep1 = "0.1"
            "#,
        )
        .file("src/lib.rs", "pub fn f() { assert!(true); }")
        .build();

    p.cargo("clippy-preview -Zunstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[..]assert!(true)[..]")
        .run();

    // Make sure it runs again.
    p.cargo("clippy-preview -Zunstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[FRESH] dep1 v0.1.0")
        .with_stderr_contains("[..]assert!(true)[..]")
        .run();
}

#[cargo_test]
fn clippy_passes_args() {
    if !clippy_is_available() {
        return;
    }

    // This is just a random clippy lint (assertions_on_constants) that
    // hopefully won't change much in the future.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            "#,
        )
        .file("src/lib.rs", "pub fn f() { assert!(true); }")
        .build();

    p.cargo("clippy-preview -Zunstable-options -v -- -Aclippy::assertions_on_constants")
        .masquerade_as_nightly_cargo()
        .with_stderr_does_not_contain("[..]assert!(true)[..]")
        .run();

    // Make sure it runs again.
    p.cargo("clippy-preview -Zunstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[..]assert!(true)[..]")
        .run();
}
<|endoftext|>


<commit_before>use na::{DVector, Real, Unit};
use std::ops::Range;

use crate::joint::JointConstraint;
use crate::math::{AngularVector, Point, Vector, DIM, SPATIAL_DIM};
use crate::object::{BodyPartHandle, BodySet};
use crate::solver::helper;
use crate::solver::{ConstraintSet, GenericNonlinearConstraint, IntegrationParameters,
             NonlinearConstraintGenerator};

/// A constraint that removes two translational and two rotational degrees of freedoms.
///
/// This is different frmo the cylindrical constraint since the remaining rotation and translation
/// are not restricted to be done wrt. the same axis.
pub struct PinSlotConstraint<N: Real> {
    b1: BodyPartHandle,
    b2: BodyPartHandle,
    anchor1: Point<N>,
    anchor2: Point<N>,
    axis_v1: Unit<Vector<N>>,
    axis_w1: Unit<Vector<N>>,
    axis_w2: Unit<Vector<N>>,
    lin_impulses: Vector<N>,
    ang_impulses: AngularVector<N>,
    bilateral_ground_rng: Range<usize>,
    bilateral_rng: Range<usize>,
    // min_offset: Option<N>,
    // max_offset: Option<N>,
}

impl<N: Real> PinSlotConstraint<N> {
    /// Creates a new pin-slot constraint.
    ///
    /// This will ensure the relative linear motions are always along `axis_v1` (here expressed
    /// in the local coordinate frame of `b1`), and that `axis_w1` and `axis_w2` always coincide.
    /// All axises and anchors are expressed in the local coordinate frame of their respective body
    /// part.
    pub fn new(
        b1: BodyPartHandle,
        b2: BodyPartHandle,
        anchor1: Point<N>,
        axis_v1: Unit<Vector<N>>,
        axis_w1: Unit<Vector<N>>,
        anchor2: Point<N>,
        axis_w2: Unit<Vector<N>>,
    ) -> Self {
        // let min_offset = None;
        // let max_offset = None;

        PinSlotConstraint {
            b1,
            b2,
            anchor1,
            anchor2,
            axis_v1,
            axis_w1,
            axis_w2,
            lin_impulses: Vector::zeros(),
            ang_impulses: AngularVector::zeros(),
            bilateral_ground_rng: 0..0,
            bilateral_rng: 0..0,
            // min_offset,
            // max_offset,
        }
    }

    // pub fn min_offset(&self) -> Option<N> {
    //     self.min_offset
    // }

    // pub fn max_offset(&self) -> Option<N> {
    //     self.max_offset
    // }

    // pub fn disable_min_offset(&mut self) {
    //     self.min_offset = None;
    // }

    // pub fn disable_max_offset(&mut self) {
    //     self.max_offset = None;
    // }

    // pub fn enable_min_offset(&mut self, limit: N) {
    //     self.min_offset = Some(limit);
    //     self.assert_limits();
    // }

    // pub fn enable_max_offset(&mut self, limit: N) {
    //     self.max_offset = Some(limit);
    //     self.assert_limits();
    // }

    // fn assert_limits(&self) {
    //     if let (Some(min_offset), Some(max_offset)) = (self.min_offset, self.max_offset) {
    //         assert!(
    //             min_offset <= max_offset,
    //             "RevoluteJoint constraint limits: the min angle must be larger than (or equal to) the max angle.");
    //     }
    // }
}

impl<N: Real> JointConstraint<N> for PinSlotConstraint<N> {
    fn num_velocity_constraints(&self) -> usize {
        SPATIAL_DIM - 2
    }

    fn anchors(&self) -> (BodyPartHandle, BodyPartHandle) {
        (self.b1, self.b2)
    }

    fn velocity_constraints(
        &mut self,
        _: &IntegrationParameters<N>,
        bodies: &BodySet<N>,
        ext_vels: &DVector<N>,
        ground_j_id: &mut usize,
        j_id: &mut usize,
        jacobians: &mut [N],
        constraints: &mut ConstraintSet<N>,
    ) {
        let body1 = bodies.body(self.b1.body_handle);
        let body2 = bodies.body(self.b2.body_handle);
        let part1 = body1.part(self.b1);
        let part2 = body2.part(self.b2);

        /*
         *
         * Joint constraints.
         *
         */
        let pos1 = part1.position();
        let pos2 = part2.position();

        let anchor1 = pos1 * self.anchor1;
        let anchor2 = pos2 * self.anchor2;

        let assembly_id1 = body1.companion_id();
        let assembly_id2 = body2.companion_id();

        let first_bilateral_ground = constraints.velocity.bilateral_ground.len();
        let first_bilateral = constraints.velocity.bilateral.len();

        let axis_v1 = pos1 * self.axis_v1;
        let axis_w1 = pos1 * self.axis_w1;

        helper::restrict_relative_linear_velocity_to_axis(
            body1,
            part1,
            body2,
            part2,
            assembly_id1,
            assembly_id2,
            &anchor1,
            &anchor2,
            &axis_v1,
            ext_vels,
            self.lin_impulses.as_slice(),
            0,
            ground_j_id,
            j_id,
            jacobians,
            constraints,
        );

        helper::restrict_relative_angular_velocity_to_axis(
            body1,
            part1,
            body2,
            part2,
            assembly_id1,
            assembly_id2,
            &axis_w1,
            &anchor1,
            &anchor2,
            ext_vels,
            self.ang_impulses.as_slice(),
            DIM - 1,
            ground_j_id,
            j_id,
            jacobians,
            constraints,
        );

        /*
         *
         * Limit constraints.
         *
         */

        self.bilateral_ground_rng =
            first_bilateral_ground..constraints.velocity.bilateral_ground.len();
        self.bilateral_rng = first_bilateral..constraints.velocity.bilateral.len();
    }

    fn cache_impulses(&mut self, constraints: &ConstraintSet<N>) {
        for c in &constraints.velocity.bilateral_ground[self.bilateral_ground_rng.clone()] {
            if c.impulse_id < DIM {
                self.lin_impulses[c.impulse_id] = c.impulse;
            } else {
                self.ang_impulses[c.impulse_id - DIM] = c.impulse;
            }
        }

        for c in &constraints.velocity.bilateral[self.bilateral_rng.clone()] {
            if c.impulse_id < DIM {
                self.lin_impulses[c.impulse_id] = c.impulse;
            } else {
                self.ang_impulses[c.impulse_id - DIM] = c.impulse;
            }
        }
    }
}

impl<N: Real> NonlinearConstraintGenerator<N> for PinSlotConstraint<N> {
    fn num_position_constraints(&self, bodies: &BodySet<N>) -> usize {
        // FIXME: calling this at each iteration of the non-linear resolution is costly.
        if self.is_active(bodies) {
            2
        } else {
            0
        }
    }

    fn position_constraint(
        &self,
        params: &IntegrationParameters<N>,
        i: usize,
        bodies: &mut BodySet<N>,
        jacobians: &mut [N],
    ) -> Option<GenericNonlinearConstraint<N>> {
        let body1 = bodies.body(self.b1.body_handle);
        let body2 = bodies.body(self.b2.body_handle);
        let part1 = body1.part(self.b1);
        let part2 = body2.part(self.b2);

        let pos1 = part1.position();
        let pos2 = part2.position();

        let anchor1 = pos1 * self.anchor1;
        let anchor2 = pos2 * self.anchor2;

        if i == 0 {
            let axis1 = pos1 * self.axis_w1;
            let axis2 = pos2 * self.axis_w2;

            return helper::align_axis(
                params,
                body1,
                part1,
                body2,
                part2,
                &anchor1,
                &anchor2,
                &axis1,
                &axis2,
                jacobians,
            );
        }

        if i == 1 {
            let axis = pos1 * self.axis_v1;

            return helper::project_anchor_to_axis(
                params,
                body1,
                part1,
                body2,
                part2,
                &anchor1,
                &anchor2,
                &axis,
                jacobians,
            );
        }

        return None;
    }
}
<commit_msg>Fix pin-slot constraint to work with deformable bodies.<commit_after>use na::{DVector, Real, Unit};
use std::ops::Range;

use crate::joint::JointConstraint;
use crate::math::{AngularVector, Point, Vector, DIM, SPATIAL_DIM};
use crate::object::{BodyPartHandle, BodySet};
use crate::solver::helper;
use crate::solver::{ConstraintSet, GenericNonlinearConstraint, IntegrationParameters,
             NonlinearConstraintGenerator};

/// A constraint that removes two translational and two rotational degrees of freedoms.
///
/// This is different frmo the cylindrical constraint since the remaining rotation and translation
/// are not restricted to be done wrt. the same axis.
pub struct PinSlotConstraint<N: Real> {
    b1: BodyPartHandle,
    b2: BodyPartHandle,
    anchor1: Point<N>,
    anchor2: Point<N>,
    axis_v1: Unit<Vector<N>>,
    axis_w1: Unit<Vector<N>>,
    axis_w2: Unit<Vector<N>>,
    lin_impulses: Vector<N>,
    ang_impulses: AngularVector<N>,
    bilateral_ground_rng: Range<usize>,
    bilateral_rng: Range<usize>,
    // min_offset: Option<N>,
    // max_offset: Option<N>,
}

impl<N: Real> PinSlotConstraint<N> {
    /// Creates a new pin-slot constraint.
    ///
    /// This will ensure the relative linear motions are always along `axis_v1` (here expressed
    /// in the local coordinate frame of `b1`), and that `axis_w1` and `axis_w2` always coincide.
    /// All axises and anchors are expressed in the local coordinate frame of their respective body
    /// part.
    pub fn new(
        b1: BodyPartHandle,
        b2: BodyPartHandle,
        anchor1: Point<N>,
        axis_v1: Unit<Vector<N>>,
        axis_w1: Unit<Vector<N>>,
        anchor2: Point<N>,
        axis_w2: Unit<Vector<N>>,
    ) -> Self {
        // let min_offset = None;
        // let max_offset = None;

        PinSlotConstraint {
            b1,
            b2,
            anchor1,
            anchor2,
            axis_v1,
            axis_w1,
            axis_w2,
            lin_impulses: Vector::zeros(),
            ang_impulses: AngularVector::zeros(),
            bilateral_ground_rng: 0..0,
            bilateral_rng: 0..0,
            // min_offset,
            // max_offset,
        }
    }

    // pub fn min_offset(&self) -> Option<N> {
    //     self.min_offset
    // }

    // pub fn max_offset(&self) -> Option<N> {
    //     self.max_offset
    // }

    // pub fn disable_min_offset(&mut self) {
    //     self.min_offset = None;
    // }

    // pub fn disable_max_offset(&mut self) {
    //     self.max_offset = None;
    // }

    // pub fn enable_min_offset(&mut self, limit: N) {
    //     self.min_offset = Some(limit);
    //     self.assert_limits();
    // }

    // pub fn enable_max_offset(&mut self, limit: N) {
    //     self.max_offset = Some(limit);
    //     self.assert_limits();
    // }

    // fn assert_limits(&self) {
    //     if let (Some(min_offset), Some(max_offset)) = (self.min_offset, self.max_offset) {
    //         assert!(
    //             min_offset <= max_offset,
    //             "RevoluteJoint constraint limits: the min angle must be larger than (or equal to) the max angle.");
    //     }
    // }
}

impl<N: Real> JointConstraint<N> for PinSlotConstraint<N> {
    fn num_velocity_constraints(&self) -> usize {
        SPATIAL_DIM - 2
    }

    fn anchors(&self) -> (BodyPartHandle, BodyPartHandle) {
        (self.b1, self.b2)
    }

    fn velocity_constraints(
        &mut self,
        _: &IntegrationParameters<N>,
        bodies: &BodySet<N>,
        ext_vels: &DVector<N>,
        ground_j_id: &mut usize,
        j_id: &mut usize,
        jacobians: &mut [N],
        constraints: &mut ConstraintSet<N>,
    ) {
        let body1 = bodies.body(self.b1.body_handle);
        let body2 = bodies.body(self.b2.body_handle);
        let part1 = body1.part(self.b1);
        let part2 = body2.part(self.b2);

        /*
         *
         * Joint constraints.
         *
         */
        let pos1 = body1.position_at_material_point(part1, &self.anchor1);
        let pos2 = body2.position_at_material_point(part2, &self.anchor2);

        let anchor1 = Point::from_coordinates(pos1.translation.vector);
        let anchor2 = Point::from_coordinates(pos2.translation.vector);

        let assembly_id1 = body1.companion_id();
        let assembly_id2 = body2.companion_id();

        let first_bilateral_ground = constraints.velocity.bilateral_ground.len();
        let first_bilateral = constraints.velocity.bilateral.len();

        let axis_v1 = pos1 * self.axis_v1;
        let axis_w1 = pos1 * self.axis_w1;

        helper::restrict_relative_linear_velocity_to_axis(
            body1,
            part1,
            body2,
            part2,
            assembly_id1,
            assembly_id2,
            &anchor1,
            &anchor2,
            &axis_v1,
            ext_vels,
            self.lin_impulses.as_slice(),
            0,
            ground_j_id,
            j_id,
            jacobians,
            constraints,
        );

        helper::restrict_relative_angular_velocity_to_axis(
            body1,
            part1,
            body2,
            part2,
            assembly_id1,
            assembly_id2,
            &axis_w1,
            &anchor1,
            &anchor2,
            ext_vels,
            self.ang_impulses.as_slice(),
            DIM - 1,
            ground_j_id,
            j_id,
            jacobians,
            constraints,
        );

        /*
         *
         * Limit constraints.
         *
         */

        self.bilateral_ground_rng =
            first_bilateral_ground..constraints.velocity.bilateral_ground.len();
        self.bilateral_rng = first_bilateral..constraints.velocity.bilateral.len();
    }

    fn cache_impulses(&mut self, constraints: &ConstraintSet<N>) {
        for c in &constraints.velocity.bilateral_ground[self.bilateral_ground_rng.clone()] {
            if c.impulse_id < DIM {
                self.lin_impulses[c.impulse_id] = c.impulse;
            } else {
                self.ang_impulses[c.impulse_id - DIM] = c.impulse;
            }
        }

        for c in &constraints.velocity.bilateral[self.bilateral_rng.clone()] {
            if c.impulse_id < DIM {
                self.lin_impulses[c.impulse_id] = c.impulse;
            } else {
                self.ang_impulses[c.impulse_id - DIM] = c.impulse;
            }
        }
    }
}

impl<N: Real> NonlinearConstraintGenerator<N> for PinSlotConstraint<N> {
    fn num_position_constraints(&self, bodies: &BodySet<N>) -> usize {
        // FIXME: calling this at each iteration of the non-linear resolution is costly.
        if self.is_active(bodies) {
            2
        } else {
            0
        }
    }

    fn position_constraint(
        &self,
        params: &IntegrationParameters<N>,
        i: usize,
        bodies: &mut BodySet<N>,
        jacobians: &mut [N],
    ) -> Option<GenericNonlinearConstraint<N>> {
        let body1 = bodies.body(self.b1.body_handle);
        let body2 = bodies.body(self.b2.body_handle);
        let part1 = body1.part(self.b1);
        let part2 = body2.part(self.b2);

        let pos1 = part1.position();
        let pos2 = part2.position();

        let anchor1 = pos1 * self.anchor1;
        let anchor2 = pos2 * self.anchor2;

        if i == 0 {
            let axis1 = pos1 * self.axis_w1;
            let axis2 = pos2 * self.axis_w2;

            return helper::align_axis(
                params,
                body1,
                part1,
                body2,
                part2,
                &anchor1,
                &anchor2,
                &axis1,
                &axis2,
                jacobians,
            );
        }

        if i == 1 {
            let axis = pos1 * self.axis_v1;

            return helper::project_anchor_to_axis(
                params,
                body1,
                part1,
                body2,
                part2,
                &anchor1,
                &anchor2,
                &axis,
                jacobians,
            );
        }

        return None;
    }
}
<|endoftext|>