<commit_before>use super::ValidatorHarness;
use beacon_chain::{BeaconChain, BlockProcessingOutcome};
pub use beacon_chain::{BeaconChainError, CheckPoint};
use db::{
    stores::{BeaconBlockStore, BeaconStateStore},
    MemoryDB,
};
use fork_choice::BitwiseLMDGhost;
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::collections::HashSet;
use std::iter::FromIterator;
use std::sync::Arc;
use types::{test_utils::TestingBeaconStateBuilder, *};

/// The beacon chain harness simulates a single beacon node with `validator_count` validators connected
/// to it. Each validator is provided a borrow to the beacon chain, where it may read
/// information and submit blocks/attestations for processing.
///
/// This test harness is useful for testing validator and internal state transition logic. It
/// is not useful for testing that multiple beacon nodes can reach consensus.
pub struct BeaconChainHarness {
    pub db: Arc<MemoryDB>,
    pub beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>>,
    pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
    pub state_store: Arc<BeaconStateStore<MemoryDB>>,
    pub validators: Vec<ValidatorHarness>,
    pub spec: Arc<ChainSpec>,
}

impl BeaconChainHarness {
    /// Create a new harness with:
    ///
    /// - A keypair, `BlockProducer` and `Attester` for each validator.
    /// - A new BeaconChain struct where the given validators are in the genesis.
    pub fn new(spec: ChainSpec, validator_count: usize) -> Self {
        let state_builder =
            TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
        Self::from_beacon_state_builder(state_builder, spec)
    }

    pub fn from_beacon_state_builder(
        state_builder: TestingBeaconStateBuilder,
        spec: ChainSpec,
    ) -> Self {
        let db = Arc::new(MemoryDB::open());
        let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
        let state_store = Arc::new(BeaconStateStore::new(db.clone()));
        let slot_clock = TestingSlotClock::new(spec.genesis_slot.as_u64());
        let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone());

        let (mut genesis_state, keypairs) = state_builder.build();

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

        genesis_state
            .build_epoch_cache(RelativeEpoch::Previous, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::Current, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &spec)
            .unwrap();

        // Create the Beacon Chain
        let beacon_chain = Arc::new(
            BeaconChain::from_genesis(
                state_store.clone(),
                block_store.clone(),
                slot_clock,
                genesis_state,
                genesis_block,
                spec.clone(),
                fork_choice,
            )
            .unwrap(),
        );

        let spec = Arc::new(spec);

        debug!("Creating validator producer and attester instances...");

        // Spawn the test validator instances.
        let validators: Vec<ValidatorHarness> = keypairs
            .iter()
            .map(|keypair| {
                ValidatorHarness::new(keypair.clone(), beacon_chain.clone(), spec.clone())
            })
            .collect();

        debug!("Created {} ValidatorHarnesss", validators.len());

        Self {
            db,
            beacon_chain,
            block_store,
            state_store,
            validators,
            spec,
        }
    }

    /// Move the `slot_clock` for the `BeaconChain` forward one slot.
    ///
    /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
    ///
    /// Returns the new slot.
    pub fn increment_beacon_chain_slot(&mut self) -> Slot {
        let slot = self.beacon_chain.present_slot() + 1;

        let nth_slot = slot
            - slot
                .epoch(self.spec.slots_per_epoch)
                .start_slot(self.spec.slots_per_epoch);
        let nth_epoch = slot.epoch(self.spec.slots_per_epoch) - self.spec.genesis_epoch;
        debug!(
            "Advancing BeaconChain to slot {}, epoch {} (epoch height: {}, slot {} in epoch.).",
            slot,
            slot.epoch(self.spec.slots_per_epoch),
            nth_epoch,
            nth_slot
        );

        self.beacon_chain.slot_clock.set_slot(slot.as_u64());
        self.beacon_chain.advance_state(slot).unwrap();
        slot
    }

    /// Gather the `FreeAttestation`s from the valiators.
    ///
    /// Note: validators will only produce attestations _once per slot_. So, if you call this twice
    /// you'll only get attestations on the first run.
    pub fn gather_free_attesations(&mut self) -> Vec<FreeAttestation> {
        let present_slot = self.beacon_chain.present_slot();

        let attesting_validators = self
            .beacon_chain
            .state
            .read()
            .get_crosslink_committees_at_slot(present_slot, &self.spec)
            .unwrap()
            .iter()
            .fold(vec![], |mut acc, c| {
                acc.append(&mut c.committee.clone());
                acc
            });
        let attesting_validators: HashSet<usize> =
            HashSet::from_iter(attesting_validators.iter().cloned());

        let free_attestations: Vec<FreeAttestation> = self
            .validators
            .par_iter_mut()
            .enumerate()
            .filter_map(|(i, validator)| {
                if attesting_validators.contains(&i) {
                    // Advance the validator slot.
                    validator.set_slot(present_slot);

                    // Prompt the validator to produce an attestation (if required).
                    validator.produce_free_attestation().ok()
                } else {
                    None
                }
            })
            .collect();

        debug!(
            "Gathered {} FreeAttestations for slot {}.",
            free_attestations.len(),
            present_slot
        );

        free_attestations
    }

    /// Get the block from the proposer for the slot.
    ///
    /// Note: the validator will only produce it _once per slot_. So, if you call this twice you'll
    /// only get a block once.
    pub fn produce_block(&mut self) -> BeaconBlock {
        let present_slot = self.beacon_chain.present_slot();

        let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();

        debug!(
            "Producing block from validator #{} for slot {}.",
            proposer, present_slot
        );

        // Ensure the validators slot clock is accurate.
        self.validators[proposer].set_slot(present_slot);
        self.validators[proposer].produce_block().unwrap()
    }

    /// Advances the chain with a BeaconBlock and attestations from all validators.
    ///
    /// This is the ideal scenario for the Beacon Chain, 100% honest participation from
    /// validators.
    pub fn advance_chain_with_block(&mut self) {
        self.increment_beacon_chain_slot();

        // Produce a new block.
        let block = self.produce_block();
        debug!("Submitting block for processing...");
        match self.beacon_chain.process_block(block) {
            Ok(BlockProcessingOutcome::ValidBlock(_)) => {}
            other => panic!("block processing failed with {:?}", other),
        };
        debug!("...block processed by BeaconChain.");

        debug!("Producing free attestations...");

        // Produce new attestations.
        let free_attestations = self.gather_free_attesations();

        debug!("Processing free attestations...");

        free_attestations.par_iter().for_each(|free_attestation| {
            self.beacon_chain
                .process_free_attestation(free_attestation.clone())
                .unwrap();
        });

        debug!("Free attestations processed.");
    }

    /// Signs a message using some validators secret key with the `Fork` info from the latest state
    /// of the `BeaconChain`.
    ///
    /// Useful for producing slashable messages and other objects that `BeaconChainHarness` does
    /// not produce naturally.
    pub fn validator_sign(
        &self,
        validator_index: usize,
        message: &[u8],
        epoch: Epoch,
        domain_type: Domain,
    ) -> Option<Signature> {
        let validator = self.validators.get(validator_index)?;

        let domain = self
            .spec
            .get_domain(epoch, domain_type, &self.beacon_chain.state.read().fork);

        Some(Signature::new(message, domain, &validator.keypair.sk))
    }

    /// Returns the current `Fork` of the `beacon_chain`.
    pub fn fork(&self) -> Fork {
        self.beacon_chain.state.read().fork.clone()
    }

    /// Returns the current `epoch` of the `beacon_chain`.
    pub fn epoch(&self) -> Epoch {
        self.beacon_chain
            .state
            .read()
            .slot
            .epoch(self.spec.slots_per_epoch)
    }

    /// Returns the keypair for some validator index.
    pub fn validator_keypair(&self, validator_index: usize) -> Option<&Keypair> {
        self.validators
            .get(validator_index)
            .and_then(|v| Some(&v.keypair))
    }

    /// Submit a deposit to the `BeaconChain` and, if given a keypair, create a new
    /// `ValidatorHarness` instance for this validator.
    ///
    /// If a new `ValidatorHarness` was created, the validator should become fully operational as
    /// if the validator were created during `BeaconChainHarness` instantiation.
    pub fn add_deposit(&mut self, deposit: Deposit, keypair: Option<Keypair>) {
        self.beacon_chain.receive_deposit_for_inclusion(deposit);

        // If a keypair is present, add a new `ValidatorHarness` to the rig.
        if let Some(keypair) = keypair {
            let validator =
                ValidatorHarness::new(keypair, self.beacon_chain.clone(), self.spec.clone());
            self.validators.push(validator);
        }
    }

    /// Submit an exit to the `BeaconChain` for inclusion in some block.
    ///
    /// Note: the `ValidatorHarness` for this validator continues to exist. Once it is exited it
    /// will stop receiving duties from the beacon chain and just do nothing when prompted to
    /// produce/attest.
    pub fn add_exit(&mut self, exit: VoluntaryExit) {
        self.beacon_chain.receive_exit_for_inclusion(exit);
    }

    /// Submit an transfer to the `BeaconChain` for inclusion in some block.
    pub fn add_transfer(&mut self, transfer: Transfer) {
        self.beacon_chain.receive_transfer_for_inclusion(transfer);
    }

    /// Submit a proposer slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_proposer_slashing(&mut self, proposer_slashing: ProposerSlashing) {
        self.beacon_chain
            .receive_proposer_slashing_for_inclusion(proposer_slashing);
    }

    /// Submit an attester slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_attester_slashing(&mut self, attester_slashing: AttesterSlashing) {
        self.beacon_chain
            .receive_attester_slashing_for_inclusion(attester_slashing);
    }

    /// Executes the fork choice rule on the `BeaconChain`, selecting a new canonical head.
    pub fn run_fork_choice(&mut self) {
        self.beacon_chain.fork_choice().unwrap()
    }

    /// Dump all blocks and states from the canonical beacon chain.
    pub fn chain_dump(&self) -> Result<Vec<CheckPoint>, BeaconChainError> {
        self.beacon_chain.chain_dump()
    }
}
<commit_msg>Add type alias to test_harness<commit_after>use super::ValidatorHarness;
use beacon_chain::{BeaconChain, BlockProcessingOutcome};
pub use beacon_chain::{BeaconChainError, CheckPoint};
use db::{
    stores::{BeaconBlockStore, BeaconStateStore},
    MemoryDB,
};
use fork_choice::BitwiseLMDGhost;
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::collections::HashSet;
use std::iter::FromIterator;
use std::sync::Arc;
use types::{test_utils::TestingBeaconStateBuilder, *};

type TestingBeaconChain = BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>;

/// The beacon chain harness simulates a single beacon node with `validator_count` validators connected
/// to it. Each validator is provided a borrow to the beacon chain, where it may read
/// information and submit blocks/attestations for processing.
///
/// This test harness is useful for testing validator and internal state transition logic. It
/// is not useful for testing that multiple beacon nodes can reach consensus.
pub struct BeaconChainHarness {
    pub db: Arc<MemoryDB>,
    pub beacon_chain: Arc<TestingBeaconChain>,
    pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
    pub state_store: Arc<BeaconStateStore<MemoryDB>>,
    pub validators: Vec<ValidatorHarness>,
    pub spec: Arc<ChainSpec>,
}

impl BeaconChainHarness {
    /// Create a new harness with:
    ///
    /// - A keypair, `BlockProducer` and `Attester` for each validator.
    /// - A new BeaconChain struct where the given validators are in the genesis.
    pub fn new(spec: ChainSpec, validator_count: usize) -> Self {
        let state_builder =
            TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
        Self::from_beacon_state_builder(state_builder, spec)
    }

    pub fn from_beacon_state_builder(
        state_builder: TestingBeaconStateBuilder,
        spec: ChainSpec,
    ) -> Self {
        let db = Arc::new(MemoryDB::open());
        let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
        let state_store = Arc::new(BeaconStateStore::new(db.clone()));
        let slot_clock = TestingSlotClock::new(spec.genesis_slot.as_u64());
        let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone());

        let (mut genesis_state, keypairs) = state_builder.build();

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

        genesis_state
            .build_epoch_cache(RelativeEpoch::Previous, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::Current, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &spec)
            .unwrap();

        // Create the Beacon Chain
        let beacon_chain = Arc::new(
            BeaconChain::from_genesis(
                state_store.clone(),
                block_store.clone(),
                slot_clock,
                genesis_state,
                genesis_block,
                spec.clone(),
                fork_choice,
            )
            .unwrap(),
        );

        let spec = Arc::new(spec);

        debug!("Creating validator producer and attester instances...");

        // Spawn the test validator instances.
        let validators: Vec<ValidatorHarness> = keypairs
            .iter()
            .map(|keypair| {
                ValidatorHarness::new(keypair.clone(), beacon_chain.clone(), spec.clone())
            })
            .collect();

        debug!("Created {} ValidatorHarnesss", validators.len());

        Self {
            db,
            beacon_chain,
            block_store,
            state_store,
            validators,
            spec,
        }
    }

    /// Move the `slot_clock` for the `BeaconChain` forward one slot.
    ///
    /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
    ///
    /// Returns the new slot.
    pub fn increment_beacon_chain_slot(&mut self) -> Slot {
        let slot = self.beacon_chain.present_slot() + 1;

        let nth_slot = slot
            - slot
                .epoch(self.spec.slots_per_epoch)
                .start_slot(self.spec.slots_per_epoch);
        let nth_epoch = slot.epoch(self.spec.slots_per_epoch) - self.spec.genesis_epoch;
        debug!(
            "Advancing BeaconChain to slot {}, epoch {} (epoch height: {}, slot {} in epoch.).",
            slot,
            slot.epoch(self.spec.slots_per_epoch),
            nth_epoch,
            nth_slot
        );

        self.beacon_chain.slot_clock.set_slot(slot.as_u64());
        self.beacon_chain.advance_state(slot).unwrap();
        slot
    }

    /// Gather the `FreeAttestation`s from the valiators.
    ///
    /// Note: validators will only produce attestations _once per slot_. So, if you call this twice
    /// you'll only get attestations on the first run.
    pub fn gather_free_attesations(&mut self) -> Vec<FreeAttestation> {
        let present_slot = self.beacon_chain.present_slot();

        let attesting_validators = self
            .beacon_chain
            .state
            .read()
            .get_crosslink_committees_at_slot(present_slot, &self.spec)
            .unwrap()
            .iter()
            .fold(vec![], |mut acc, c| {
                acc.append(&mut c.committee.clone());
                acc
            });
        let attesting_validators: HashSet<usize> =
            HashSet::from_iter(attesting_validators.iter().cloned());

        let free_attestations: Vec<FreeAttestation> = self
            .validators
            .par_iter_mut()
            .enumerate()
            .filter_map(|(i, validator)| {
                if attesting_validators.contains(&i) {
                    // Advance the validator slot.
                    validator.set_slot(present_slot);

                    // Prompt the validator to produce an attestation (if required).
                    validator.produce_free_attestation().ok()
                } else {
                    None
                }
            })
            .collect();

        debug!(
            "Gathered {} FreeAttestations for slot {}.",
            free_attestations.len(),
            present_slot
        );

        free_attestations
    }

    /// Get the block from the proposer for the slot.
    ///
    /// Note: the validator will only produce it _once per slot_. So, if you call this twice you'll
    /// only get a block once.
    pub fn produce_block(&mut self) -> BeaconBlock {
        let present_slot = self.beacon_chain.present_slot();

        let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();

        debug!(
            "Producing block from validator #{} for slot {}.",
            proposer, present_slot
        );

        // Ensure the validators slot clock is accurate.
        self.validators[proposer].set_slot(present_slot);
        self.validators[proposer].produce_block().unwrap()
    }

    /// Advances the chain with a BeaconBlock and attestations from all validators.
    ///
    /// This is the ideal scenario for the Beacon Chain, 100% honest participation from
    /// validators.
    pub fn advance_chain_with_block(&mut self) {
        self.increment_beacon_chain_slot();

        // Produce a new block.
        let block = self.produce_block();
        debug!("Submitting block for processing...");
        match self.beacon_chain.process_block(block) {
            Ok(BlockProcessingOutcome::ValidBlock(_)) => {}
            other => panic!("block processing failed with {:?}", other),
        };
        debug!("...block processed by BeaconChain.");

        debug!("Producing free attestations...");

        // Produce new attestations.
        let free_attestations = self.gather_free_attesations();

        debug!("Processing free attestations...");

        free_attestations.par_iter().for_each(|free_attestation| {
            self.beacon_chain
                .process_free_attestation(free_attestation.clone())
                .unwrap();
        });

        debug!("Free attestations processed.");
    }

    /// Signs a message using some validators secret key with the `Fork` info from the latest state
    /// of the `BeaconChain`.
    ///
    /// Useful for producing slashable messages and other objects that `BeaconChainHarness` does
    /// not produce naturally.
    pub fn validator_sign(
        &self,
        validator_index: usize,
        message: &[u8],
        epoch: Epoch,
        domain_type: Domain,
    ) -> Option<Signature> {
        let validator = self.validators.get(validator_index)?;

        let domain = self
            .spec
            .get_domain(epoch, domain_type, &self.beacon_chain.state.read().fork);

        Some(Signature::new(message, domain, &validator.keypair.sk))
    }

    /// Returns the current `Fork` of the `beacon_chain`.
    pub fn fork(&self) -> Fork {
        self.beacon_chain.state.read().fork.clone()
    }

    /// Returns the current `epoch` of the `beacon_chain`.
    pub fn epoch(&self) -> Epoch {
        self.beacon_chain
            .state
            .read()
            .slot
            .epoch(self.spec.slots_per_epoch)
    }

    /// Returns the keypair for some validator index.
    pub fn validator_keypair(&self, validator_index: usize) -> Option<&Keypair> {
        self.validators
            .get(validator_index)
            .and_then(|v| Some(&v.keypair))
    }

    /// Submit a deposit to the `BeaconChain` and, if given a keypair, create a new
    /// `ValidatorHarness` instance for this validator.
    ///
    /// If a new `ValidatorHarness` was created, the validator should become fully operational as
    /// if the validator were created during `BeaconChainHarness` instantiation.
    pub fn add_deposit(&mut self, deposit: Deposit, keypair: Option<Keypair>) {
        self.beacon_chain.receive_deposit_for_inclusion(deposit);

        // If a keypair is present, add a new `ValidatorHarness` to the rig.
        if let Some(keypair) = keypair {
            let validator =
                ValidatorHarness::new(keypair, self.beacon_chain.clone(), self.spec.clone());
            self.validators.push(validator);
        }
    }

    /// Submit an exit to the `BeaconChain` for inclusion in some block.
    ///
    /// Note: the `ValidatorHarness` for this validator continues to exist. Once it is exited it
    /// will stop receiving duties from the beacon chain and just do nothing when prompted to
    /// produce/attest.
    pub fn add_exit(&mut self, exit: VoluntaryExit) {
        self.beacon_chain.receive_exit_for_inclusion(exit);
    }

    /// Submit an transfer to the `BeaconChain` for inclusion in some block.
    pub fn add_transfer(&mut self, transfer: Transfer) {
        self.beacon_chain.receive_transfer_for_inclusion(transfer);
    }

    /// Submit a proposer slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_proposer_slashing(&mut self, proposer_slashing: ProposerSlashing) {
        self.beacon_chain
            .receive_proposer_slashing_for_inclusion(proposer_slashing);
    }

    /// Submit an attester slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_attester_slashing(&mut self, attester_slashing: AttesterSlashing) {
        self.beacon_chain
            .receive_attester_slashing_for_inclusion(attester_slashing);
    }

    /// Executes the fork choice rule on the `BeaconChain`, selecting a new canonical head.
    pub fn run_fork_choice(&mut self) {
        self.beacon_chain.fork_choice().unwrap()
    }

    /// Dump all blocks and states from the canonical beacon chain.
    pub fn chain_dump(&self) -> Result<Vec<CheckPoint>, BeaconChainError> {
        self.beacon_chain.chain_dump()
    }
}
<|endoftext|>


<commit_before>use compact::{CDict, CVec, CHashMap};
use kay::{ID, ActorSystem, Fate, World};
use kay::swarm::{Swarm, SubActor};
use stagemaster::geometry::AnyShape;
use descartes::Band;
use super::lane::{Lane, TransferLane};
use super::connectivity::{Interaction, InteractionKind, OverlapKind};

pub mod trip;

#[derive(Compact, Clone, Default)]
pub struct PathfindingInfo {
    pub as_destination: Option<Destination>,
    pub hops_from_landmark: u8,
    pub learned_landmark_from: Option<ID>,
    pub routes: CHashMap<Destination, RoutingInfo>,
    pub routes_changed: bool,
    pub tell_to_forget_next_tick: CVec<Destination>,
    pub query_routes_next_tick: bool,
    pub routing_timeout: u16,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Destination {
    pub landmark: ID,
    pub node: ID,
}

impl Destination {
    fn landmark(landmark: ID) -> Self {
        Destination { landmark: landmark, node: landmark }
    }
    pub fn is_landmark(&self) -> bool {
        self.landmark == self.node
    }
    pub fn landmark_destination(&self) -> Self {
        Self::landmark(self.landmark)
    }
}

#[derive(Copy, Clone, Default, Debug)]
pub struct RoutingInfo {
    pub outgoing_idx: u8,
    pub distance: f32,
    distance_hops: u8,
    learned_from: ID,
    fresh: bool,
}

use stagemaster::{UserInterface, AddInteractable};
const DEBUG_CARS_ON_LANES: bool = false;

pub fn on_build(lane: &mut Lane, world: &mut World) {
    lane.pathfinding.as_destination = None;
    if DEBUG_CARS_ON_LANES {
        world.send_to_id_of::<UserInterface, _>(AddInteractable(
            lane.id(),
            AnyShape::Band(
                Band::new(lane.construction.path.clone(), 3.0),
            ),
            5,
        ));
    }
}

pub fn on_connect(lane: &mut Lane) {
    lane.pathfinding.routing_timeout = ROUTING_TIMEOUT_AFTER_CHANGE;
}

pub fn on_disconnect(lane: &mut Lane, disconnected_id: ID) {
    let new_routes = lane.pathfinding
        .routes
        .pairs()
        .filter_map(|(destination, route)| if route.learned_from ==
            disconnected_id
        {
            None
        } else {
            Some((*destination, *route))
        })
        .collect();
    lane.pathfinding.routes = new_routes;
    lane.pathfinding.routes_changed = true;
    lane.pathfinding.query_routes_next_tick = true;
}

const MIN_LANDMARK_INCOMING: usize = 3;
const ROUTING_TIMEOUT_AFTER_CHANGE: u16 = 15;

pub fn tick(lane: &mut Lane, world: &mut World) {
    if let Some(as_destination) = lane.pathfinding.as_destination {
        for successor in successors(lane) {
            world.send(
                successor,
                JoinLandmark {
                    from: lane.id(),
                    join_as: Destination {
                        landmark: as_destination.landmark,
                        node: successor,
                    },
                    hops_from_landmark: lane.pathfinding.hops_from_landmark + 1,
                },
            )
        }
    } else if !lane.connectivity.on_intersection &&
               predecessors(lane).count() >= MIN_LANDMARK_INCOMING
    {
        lane.pathfinding = PathfindingInfo {
            as_destination: Some(Destination::landmark(lane.id())),
            hops_from_landmark: 0,
            learned_landmark_from: Some(lane.id()),
            routes: CHashMap::new(),
            routes_changed: true,
            query_routes_next_tick: false,
            tell_to_forget_next_tick: CVec::new(),
            routing_timeout: ROUTING_TIMEOUT_AFTER_CHANGE,
        }
    }

    if lane.pathfinding.routing_timeout > 0 {
        lane.pathfinding.routing_timeout -= 1;
    } else {
        if lane.pathfinding.query_routes_next_tick {
            for successor in successors(lane) {
                world.send(
                    successor,
                    QueryRoutes { requester: lane.id(), is_transfer: false },
                );
            }
            lane.pathfinding.query_routes_next_tick = false;
        }

        if !lane.pathfinding.tell_to_forget_next_tick.is_empty() {
            for (_, predecessor, _) in predecessors(lane) {
                world.send(
                    predecessor,
                    ForgetRoutes {
                        forget: lane.pathfinding.tell_to_forget_next_tick.clone(),
                        from: lane.id(),
                    },
                )
            }
            lane.pathfinding.tell_to_forget_next_tick.clear();
        }

        if lane.pathfinding.routes_changed {
            for (_, predecessor, is_transfer) in predecessors(lane) {
                let self_cost = if is_transfer {
                    0.0
                } else {
                    lane.construction.length
                };
                world.send(
                    predecessor,
                    ShareRoutes {
                        new_routes: lane.pathfinding
                            .routes
                            .pairs()
                            .filter_map(|(&destination,
                              &RoutingInfo { distance, distance_hops, .. })| {
                                if true
                                // fresh
                                {
                                    Some((destination, (distance + self_cost, distance_hops + 1)))
                                } else {
                                    None
                                }
                            })
                            .chain(
                                if lane.connectivity.on_intersection {
                                    None
                                } else {
                                    lane.pathfinding
                                        .as_destination
                                        .map(|destination| (destination, (self_cost, 0)))
                                },
                            )
                            .collect(),
                        from: lane.id(),
                    },
                );
            }
            for routing_info in lane.pathfinding.routes.values_mut() {
                routing_info.fresh = false;
            }
            lane.pathfinding.routes_changed = false;
        }
    }
}

#[allow(needless_lifetimes)]
fn successors<'a>(lane: &'a Lane) -> impl Iterator<Item = ID> + 'a {
    lane.connectivity.interactions.iter().filter_map(
        |interaction| {
            match *interaction {
                Interaction {
                    partner_lane,
                    kind: InteractionKind::Overlap { kind: OverlapKind::Transfer, .. },
                    ..
                } |
                Interaction {
                    partner_lane,
                    kind: InteractionKind::Next { .. },
                    ..
                } => Some(partner_lane),
                _ => None,
            }
        },
    )
}

#[allow(needless_lifetimes)]
fn predecessors<'a>(lane: &'a Lane) -> impl Iterator<Item = (u8, ID, bool)> + 'a {
    lane.connectivity
        .interactions
        .iter()
        .enumerate()
        .filter_map(|(i, interaction)| match *interaction {
            Interaction {
                partner_lane,
                kind: InteractionKind::Overlap { kind: OverlapKind::Transfer, .. },
                ..
            } => Some((i as u8, partner_lane, true)),
            Interaction {
                partner_lane,
                kind: InteractionKind::Previous { .. },
                ..
            } => Some((i as u8, partner_lane, false)),
            _ => None,
        })
}

#[derive(Copy, Clone)]
pub struct JoinLandmark {
    from: ID,
    join_as: Destination,
    hops_from_landmark: u8,
}

const IDEAL_LANDMARK_RADIUS: u8 = 3;

pub fn setup(system: &mut ActorSystem) {
    system.extend(Swarm::<Lane>::subactors(|mut each_lane| {
        each_lane.on(|&JoinLandmark { join_as, hops_from_landmark, from },
         lane,
         _| {
            let join = lane.pathfinding
                .as_destination
                .map(|self_destination| {
                    join_as != self_destination &&
                        (if self_destination.is_landmark() {
                             hops_from_landmark < IDEAL_LANDMARK_RADIUS &&
                                 join_as.landmark.sub_actor_id < lane.id().sub_actor_id
                         } else {
                             hops_from_landmark < lane.pathfinding.hops_from_landmark ||
                                 lane.pathfinding
                                     .learned_landmark_from
                                     .map(|learned_from| learned_from == from)
                                     .unwrap_or(false)
                         })
                })
                .unwrap_or(true);
            if join {
                let tell_to_forget_next_tick = lane.pathfinding
                    .routes
                    .keys()
                    .cloned()
                    .chain(lane.pathfinding.as_destination.into_iter())
                    .collect();
                lane.pathfinding = PathfindingInfo {
                    as_destination: Some(join_as),
                    learned_landmark_from: Some(from),
                    hops_from_landmark: hops_from_landmark,
                    routes: CHashMap::new(),
                    routes_changed: true,
                    query_routes_next_tick: true,
                    tell_to_forget_next_tick: tell_to_forget_next_tick,
                    routing_timeout: ROUTING_TIMEOUT_AFTER_CHANGE,
                };
            }
            Fate::Live
        });

        each_lane.on(|&QueryRoutes { requester, is_transfer }, lane, world| {
            let self_cost = if is_transfer {
                0.0
            } else {
                lane.construction.length
            };
            world.send(
                requester,
                ShareRoutes {
                    new_routes: lane.pathfinding
                        .routes
                        .pairs()
                        .map(|(&destination,
                          &RoutingInfo { distance, distance_hops, .. })| {
                            (destination, (distance + self_cost, distance_hops + 1))
                        })
                        .chain(if lane.connectivity.on_intersection {
                            None
                        } else {
                            lane.pathfinding.as_destination.map(|destination| {
                                (destination, (self_cost, 0))
                            })
                        })
                        .collect(),
                    from: lane.id(),
                },
            );
            Fate::Live
        });

        each_lane.on(|&ShareRoutes { ref new_routes, from }, lane, _| {
            if let Some(from_interaction_idx) =
                lane.connectivity.interactions.iter().position(
                    |interaction| {
                        interaction.partner_lane == from
                    },
                )
            {
                for (&destination, &(new_distance, new_distance_hops)) in new_routes.pairs() {
                    if destination.is_landmark() || new_distance_hops <= IDEAL_LANDMARK_RADIUS ||
                        lane.pathfinding
                            .as_destination
                            .map(|self_dest| self_dest.landmark == destination.landmark)
                            .unwrap_or(false)
                    {
                        let insert = lane.pathfinding
                            .routes
                            .get_mru(destination)
                            .map(|&RoutingInfo { distance, .. }| new_distance < distance)
                            .unwrap_or(true);
                        if insert {
                            lane.pathfinding.routes.insert(
                                destination,
                                RoutingInfo {
                                    distance: new_distance,
                                    distance_hops: new_distance_hops,
                                    outgoing_idx: from_interaction_idx as u8,
                                    learned_from: from,
                                    fresh: true,
                                },
                            );
                            lane.pathfinding.routes_changed = true;
                        }
                    }
                }
            } else {
                println!("{:?} not yet connected to {:?}", lane.id(), from);
            }
            Fate::Live
        });

        each_lane.on(|&ForgetRoutes { ref forget, from }, lane, _| {
            let mut forgotten = CVec::<Destination>::new();
            for destination_to_forget in forget.iter() {
                let forget = if let Some(routing_info) =
                    lane.pathfinding.routes.get(*destination_to_forget)
                {
                    routing_info.learned_from == from
                } else {
                    false
                };
                if forget {
                    lane.pathfinding.routes.remove(*destination_to_forget);
                    if destination_to_forget.is_landmark() {
                        lane.microtraffic.cars.retain(|car| {
                            car.destination.landmark != destination_to_forget.landmark
                        })
                    } else {
                        lane.microtraffic.cars.retain(|car| {
                            &car.destination != destination_to_forget
                        })
                    }
                    forgotten.push(*destination_to_forget);
                }
            }
            lane.pathfinding.tell_to_forget_next_tick = forgotten;
            Fate::Live
        });

        each_lane.on(|&QueryAsDestination { requester }, lane, world| {
            world.send(
                requester,
                TellAsDestination {
                    id: lane.id(),
                    as_destination: lane.pathfinding.as_destination,
                },
            );
            Fate::Live
        })
    }));

    system.extend(Swarm::<TransferLane>::subactors(|mut each_t_lane| {
        each_t_lane.on(|&JoinLandmark { join_as, hops_from_landmark, from },
         lane,
         world| {
            world.send(
                lane.other_side(from),
                JoinLandmark {
                    join_as: Destination {
                        landmark: join_as.landmark,
                        node: lane.other_side(from),
                    },
                    hops_from_landmark: hops_from_landmark,
                    from: lane.id(),
                },
            );
            Fate::Live
        });

        each_t_lane.on(|&QueryRoutes { requester, .. }, lane, world| {
            world.send(
                lane.other_side(requester),
                QueryRoutes { requester: lane.id(), is_transfer: true },
            );
            Fate::Live
        });

        each_t_lane.on(|&ShareRoutes { ref new_routes, from }, lane, world| {
            world.send(
                lane.other_side(from),
                ShareRoutes {
                    new_routes: new_routes
                        .pairs()
                        .map(|(&destination, &(distance, hops))| {
                            (destination, (
                                distance +
                                    if from ==
                                        lane.connectivity
                                            .left
                                            .expect("should have left")
                                            .0
                                    {
                                        LANE_CHANGE_COST_RIGHT
                                    } else {
                                        LANE_CHANGE_COST_LEFT
                                    },
                                hops,
                            ))
                        })
                        .collect(),
                    from: lane.id(),
                },
            );
            Fate::Live
        });

        each_t_lane.on(|&ForgetRoutes { ref forget, from }, lane, world| {
            world.send(
                lane.other_side(from),
                ForgetRoutes { forget: forget.clone(), from: lane.id() },
            );
            Fate::Live
        })
    }));

    trip::setup(system);
}

#[derive(Copy, Clone)]
pub struct QueryRoutes {
    requester: ID,
    is_transfer: bool,
}

#[derive(Compact, Clone)]
pub struct ShareRoutes {
    new_routes: CDict<Destination, (f32, u8)>,
    from: ID,
}

const LANE_CHANGE_COST_LEFT: f32 = 5.0;
const LANE_CHANGE_COST_RIGHT: f32 = 3.0;

#[derive(Compact, Clone)]
pub struct ForgetRoutes {
    forget: CVec<Destination>,
    from: ID,
}

#[derive(Copy, Clone)]
pub struct QueryAsDestination {
    requester: ID,
}
#[derive(Copy, Clone)]
pub struct TellAsDestination {
    id: ID,
    as_destination: Option<Destination>,
}
<commit_msg>default is not needed for RoutingInfo<commit_after>use compact::{CDict, CVec, CHashMap};
use kay::{ID, ActorSystem, Fate, World};
use kay::swarm::{Swarm, SubActor};
use stagemaster::geometry::AnyShape;
use descartes::Band;
use super::lane::{Lane, TransferLane};
use super::connectivity::{Interaction, InteractionKind, OverlapKind};

pub mod trip;

#[derive(Compact, Clone, Default)]
pub struct PathfindingInfo {
    pub as_destination: Option<Destination>,
    pub hops_from_landmark: u8,
    pub learned_landmark_from: Option<ID>,
    pub routes: CHashMap<Destination, RoutingInfo>,
    pub routes_changed: bool,
    pub tell_to_forget_next_tick: CVec<Destination>,
    pub query_routes_next_tick: bool,
    pub routing_timeout: u16,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Destination {
    pub landmark: ID,
    pub node: ID,
}

impl Destination {
    fn landmark(landmark: ID) -> Self {
        Destination { landmark: landmark, node: landmark }
    }
    pub fn is_landmark(&self) -> bool {
        self.landmark == self.node
    }
    pub fn landmark_destination(&self) -> Self {
        Self::landmark(self.landmark)
    }
}

#[derive(Copy, Clone, Debug)]
pub struct RoutingInfo {
    pub outgoing_idx: u8,
    pub distance: f32,
    distance_hops: u8,
    learned_from: ID,
    fresh: bool,
}

use stagemaster::{UserInterface, AddInteractable};
const DEBUG_CARS_ON_LANES: bool = false;

pub fn on_build(lane: &mut Lane, world: &mut World) {
    lane.pathfinding.as_destination = None;
    if DEBUG_CARS_ON_LANES {
        world.send_to_id_of::<UserInterface, _>(AddInteractable(
            lane.id(),
            AnyShape::Band(
                Band::new(lane.construction.path.clone(), 3.0),
            ),
            5,
        ));
    }
}

pub fn on_connect(lane: &mut Lane) {
    lane.pathfinding.routing_timeout = ROUTING_TIMEOUT_AFTER_CHANGE;
}

pub fn on_disconnect(lane: &mut Lane, disconnected_id: ID) {
    let new_routes = lane.pathfinding
        .routes
        .pairs()
        .filter_map(|(destination, route)| if route.learned_from ==
            disconnected_id
        {
            None
        } else {
            Some((*destination, *route))
        })
        .collect();
    lane.pathfinding.routes = new_routes;
    lane.pathfinding.routes_changed = true;
    lane.pathfinding.query_routes_next_tick = true;
}

const MIN_LANDMARK_INCOMING: usize = 3;
const ROUTING_TIMEOUT_AFTER_CHANGE: u16 = 15;

pub fn tick(lane: &mut Lane, world: &mut World) {
    if let Some(as_destination) = lane.pathfinding.as_destination {
        for successor in successors(lane) {
            world.send(
                successor,
                JoinLandmark {
                    from: lane.id(),
                    join_as: Destination {
                        landmark: as_destination.landmark,
                        node: successor,
                    },
                    hops_from_landmark: lane.pathfinding.hops_from_landmark + 1,
                },
            )
        }
    } else if !lane.connectivity.on_intersection &&
               predecessors(lane).count() >= MIN_LANDMARK_INCOMING
    {
        lane.pathfinding = PathfindingInfo {
            as_destination: Some(Destination::landmark(lane.id())),
            hops_from_landmark: 0,
            learned_landmark_from: Some(lane.id()),
            routes: CHashMap::new(),
            routes_changed: true,
            query_routes_next_tick: false,
            tell_to_forget_next_tick: CVec::new(),
            routing_timeout: ROUTING_TIMEOUT_AFTER_CHANGE,
        }
    }

    if lane.pathfinding.routing_timeout > 0 {
        lane.pathfinding.routing_timeout -= 1;
    } else {
        if lane.pathfinding.query_routes_next_tick {
            for successor in successors(lane) {
                world.send(
                    successor,
                    QueryRoutes { requester: lane.id(), is_transfer: false },
                );
            }
            lane.pathfinding.query_routes_next_tick = false;
        }

        if !lane.pathfinding.tell_to_forget_next_tick.is_empty() {
            for (_, predecessor, _) in predecessors(lane) {
                world.send(
                    predecessor,
                    ForgetRoutes {
                        forget: lane.pathfinding.tell_to_forget_next_tick.clone(),
                        from: lane.id(),
                    },
                )
            }
            lane.pathfinding.tell_to_forget_next_tick.clear();
        }

        if lane.pathfinding.routes_changed {
            for (_, predecessor, is_transfer) in predecessors(lane) {
                let self_cost = if is_transfer {
                    0.0
                } else {
                    lane.construction.length
                };
                world.send(
                    predecessor,
                    ShareRoutes {
                        new_routes: lane.pathfinding
                            .routes
                            .pairs()
                            .filter_map(|(&destination,
                              &RoutingInfo { distance, distance_hops, .. })| {
                                if true
                                // fresh
                                {
                                    Some((destination, (distance + self_cost, distance_hops + 1)))
                                } else {
                                    None
                                }
                            })
                            .chain(
                                if lane.connectivity.on_intersection {
                                    None
                                } else {
                                    lane.pathfinding
                                        .as_destination
                                        .map(|destination| (destination, (self_cost, 0)))
                                },
                            )
                            .collect(),
                        from: lane.id(),
                    },
                );
            }
            for routing_info in lane.pathfinding.routes.values_mut() {
                routing_info.fresh = false;
            }
            lane.pathfinding.routes_changed = false;
        }
    }
}

#[allow(needless_lifetimes)]
fn successors<'a>(lane: &'a Lane) -> impl Iterator<Item = ID> + 'a {
    lane.connectivity.interactions.iter().filter_map(
        |interaction| {
            match *interaction {
                Interaction {
                    partner_lane,
                    kind: InteractionKind::Overlap { kind: OverlapKind::Transfer, .. },
                    ..
                } |
                Interaction {
                    partner_lane,
                    kind: InteractionKind::Next { .. },
                    ..
                } => Some(partner_lane),
                _ => None,
            }
        },
    )
}

#[allow(needless_lifetimes)]
fn predecessors<'a>(lane: &'a Lane) -> impl Iterator<Item = (u8, ID, bool)> + 'a {
    lane.connectivity
        .interactions
        .iter()
        .enumerate()
        .filter_map(|(i, interaction)| match *interaction {
            Interaction {
                partner_lane,
                kind: InteractionKind::Overlap { kind: OverlapKind::Transfer, .. },
                ..
            } => Some((i as u8, partner_lane, true)),
            Interaction {
                partner_lane,
                kind: InteractionKind::Previous { .. },
                ..
            } => Some((i as u8, partner_lane, false)),
            _ => None,
        })
}

#[derive(Copy, Clone)]
pub struct JoinLandmark {
    from: ID,
    join_as: Destination,
    hops_from_landmark: u8,
}

const IDEAL_LANDMARK_RADIUS: u8 = 3;

pub fn setup(system: &mut ActorSystem) {
    system.extend(Swarm::<Lane>::subactors(|mut each_lane| {
        each_lane.on(|&JoinLandmark { join_as, hops_from_landmark, from },
         lane,
         _| {
            let join = lane.pathfinding
                .as_destination
                .map(|self_destination| {
                    join_as != self_destination &&
                        (if self_destination.is_landmark() {
                             hops_from_landmark < IDEAL_LANDMARK_RADIUS &&
                                 join_as.landmark.sub_actor_id < lane.id().sub_actor_id
                         } else {
                             hops_from_landmark < lane.pathfinding.hops_from_landmark ||
                                 lane.pathfinding
                                     .learned_landmark_from
                                     .map(|learned_from| learned_from == from)
                                     .unwrap_or(false)
                         })
                })
                .unwrap_or(true);
            if join {
                let tell_to_forget_next_tick = lane.pathfinding
                    .routes
                    .keys()
                    .cloned()
                    .chain(lane.pathfinding.as_destination.into_iter())
                    .collect();
                lane.pathfinding = PathfindingInfo {
                    as_destination: Some(join_as),
                    learned_landmark_from: Some(from),
                    hops_from_landmark: hops_from_landmark,
                    routes: CHashMap::new(),
                    routes_changed: true,
                    query_routes_next_tick: true,
                    tell_to_forget_next_tick: tell_to_forget_next_tick,
                    routing_timeout: ROUTING_TIMEOUT_AFTER_CHANGE,
                };
            }
            Fate::Live
        });

        each_lane.on(|&QueryRoutes { requester, is_transfer }, lane, world| {
            let self_cost = if is_transfer {
                0.0
            } else {
                lane.construction.length
            };
            world.send(
                requester,
                ShareRoutes {
                    new_routes: lane.pathfinding
                        .routes
                        .pairs()
                        .map(|(&destination,
                          &RoutingInfo { distance, distance_hops, .. })| {
                            (destination, (distance + self_cost, distance_hops + 1))
                        })
                        .chain(if lane.connectivity.on_intersection {
                            None
                        } else {
                            lane.pathfinding.as_destination.map(|destination| {
                                (destination, (self_cost, 0))
                            })
                        })
                        .collect(),
                    from: lane.id(),
                },
            );
            Fate::Live
        });

        each_lane.on(|&ShareRoutes { ref new_routes, from }, lane, _| {
            if let Some(from_interaction_idx) =
                lane.connectivity.interactions.iter().position(
                    |interaction| {
                        interaction.partner_lane == from
                    },
                )
            {
                for (&destination, &(new_distance, new_distance_hops)) in new_routes.pairs() {
                    if destination.is_landmark() || new_distance_hops <= IDEAL_LANDMARK_RADIUS ||
                        lane.pathfinding
                            .as_destination
                            .map(|self_dest| self_dest.landmark == destination.landmark)
                            .unwrap_or(false)
                    {
                        let insert = lane.pathfinding
                            .routes
                            .get_mru(destination)
                            .map(|&RoutingInfo { distance, .. }| new_distance < distance)
                            .unwrap_or(true);
                        if insert {
                            lane.pathfinding.routes.insert(
                                destination,
                                RoutingInfo {
                                    distance: new_distance,
                                    distance_hops: new_distance_hops,
                                    outgoing_idx: from_interaction_idx as u8,
                                    learned_from: from,
                                    fresh: true,
                                },
                            );
                            lane.pathfinding.routes_changed = true;
                        }
                    }
                }
            } else {
                println!("{:?} not yet connected to {:?}", lane.id(), from);
            }
            Fate::Live
        });

        each_lane.on(|&ForgetRoutes { ref forget, from }, lane, _| {
            let mut forgotten = CVec::<Destination>::new();
            for destination_to_forget in forget.iter() {
                let forget = if let Some(routing_info) =
                    lane.pathfinding.routes.get(*destination_to_forget)
                {
                    routing_info.learned_from == from
                } else {
                    false
                };
                if forget {
                    lane.pathfinding.routes.remove(*destination_to_forget);
                    if destination_to_forget.is_landmark() {
                        lane.microtraffic.cars.retain(|car| {
                            car.destination.landmark != destination_to_forget.landmark
                        })
                    } else {
                        lane.microtraffic.cars.retain(|car| {
                            &car.destination != destination_to_forget
                        })
                    }
                    forgotten.push(*destination_to_forget);
                }
            }
            lane.pathfinding.tell_to_forget_next_tick = forgotten;
            Fate::Live
        });

        each_lane.on(|&QueryAsDestination { requester }, lane, world| {
            world.send(
                requester,
                TellAsDestination {
                    id: lane.id(),
                    as_destination: lane.pathfinding.as_destination,
                },
            );
            Fate::Live
        })
    }));

    system.extend(Swarm::<TransferLane>::subactors(|mut each_t_lane| {
        each_t_lane.on(|&JoinLandmark { join_as, hops_from_landmark, from },
         lane,
         world| {
            world.send(
                lane.other_side(from),
                JoinLandmark {
                    join_as: Destination {
                        landmark: join_as.landmark,
                        node: lane.other_side(from),
                    },
                    hops_from_landmark: hops_from_landmark,
                    from: lane.id(),
                },
            );
            Fate::Live
        });

        each_t_lane.on(|&QueryRoutes { requester, .. }, lane, world| {
            world.send(
                lane.other_side(requester),
                QueryRoutes { requester: lane.id(), is_transfer: true },
            );
            Fate::Live
        });

        each_t_lane.on(|&ShareRoutes { ref new_routes, from }, lane, world| {
            world.send(
                lane.other_side(from),
                ShareRoutes {
                    new_routes: new_routes
                        .pairs()
                        .map(|(&destination, &(distance, hops))| {
                            (destination, (
                                distance +
                                    if from ==
                                        lane.connectivity
                                            .left
                                            .expect("should have left")
                                            .0
                                    {
                                        LANE_CHANGE_COST_RIGHT
                                    } else {
                                        LANE_CHANGE_COST_LEFT
                                    },
                                hops,
                            ))
                        })
                        .collect(),
                    from: lane.id(),
                },
            );
            Fate::Live
        });

        each_t_lane.on(|&ForgetRoutes { ref forget, from }, lane, world| {
            world.send(
                lane.other_side(from),
                ForgetRoutes { forget: forget.clone(), from: lane.id() },
            );
            Fate::Live
        })
    }));

    trip::setup(system);
}

#[derive(Copy, Clone)]
pub struct QueryRoutes {
    requester: ID,
    is_transfer: bool,
}

#[derive(Compact, Clone)]
pub struct ShareRoutes {
    new_routes: CDict<Destination, (f32, u8)>,
    from: ID,
}

const LANE_CHANGE_COST_LEFT: f32 = 5.0;
const LANE_CHANGE_COST_RIGHT: f32 = 3.0;

#[derive(Compact, Clone)]
pub struct ForgetRoutes {
    forget: CVec<Destination>,
    from: ID,
}

#[derive(Copy, Clone)]
pub struct QueryAsDestination {
    requester: ID,
}
#[derive(Copy, Clone)]
pub struct TellAsDestination {
    id: ID,
    as_destination: Option<Destination>,
}
<|endoftext|>


<commit_before>use tensor::Tensor;
use std::fmt;

// Display for floats
macro_rules! add_impl {
    ($t:ty, $name:tt) => (
        impl fmt::Display for Tensor<$t> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                let mv = &self.data[..];
                let mut s = format!("Tensor [{}]:\n", $name);
                if self.ndim() == 1 {
                    s.push_str("[");
                    for i in 0..self.shape[0] {
                        if i > 0 {
                            s.push_str(" ");
                        }
                        s = format!("{}{}", s, mv[i]);
                    }
                    s.push_str("]");
                } else if self.ndim() == 2 {
                    s.push_str("[[");
                    for i in 0..self.shape[0] {
                        if i > 0 {
                            s.push_str(" [");
                        }
                        for j in 0..self.shape[1] {
                            if j > 0 {
                                s.push_str(" ");
                            }
                            s = format!("{}{}", s, self.get(i, j));
                        }
                        if i == self.shape[0] - 1 {
                            s.push_str("]]");
                        } else {
                            s.push_str("]\n");
                        }
                    }
                } else {
                    s = format!("Tensor({:?}, type={})", self.shape, $name);
                }
                write!(f, "{}", s)
            }
        }
    )

}

add_impl!(f32,   "f32");
add_impl!(f64,   "f64");
add_impl!(usize, "usize");
add_impl!(u8,    "u8");
add_impl!(u16,   "u16");
add_impl!(u32,   "u32");
add_impl!(u64,   "u64");
add_impl!(isize, "isize");
add_impl!(i8,    "i8");
add_impl!(i16,   "i16");
add_impl!(i32,   "i32");
add_impl!(i64,   "i64");
add_impl!(bool,  "bool");
<commit_msg>Better padding in display code<commit_after>use tensor::Tensor;
use std::fmt;

// Display for floats
macro_rules! add_impl {
    ($t:ty, $name:tt) => (
        impl fmt::Display for Tensor<$t> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                let mv = &self.data[..];
                let mut ret = format!("Tensor [{}]:\n", $name);
                if self.ndim() <= 2 {
                    // Pre-generate all strings
                    let mut ss: Vec<String> = Vec::with_capacity(self.size());
                    let mut longest: usize = 0;
                    for i in 0..self.size() {
                        let s = format!("{}", mv[i]);
                        ss.push(s.to_string());
                        if s.len() > longest {
                            longest = s.len();
                        }
                    }

                    if self.ndim() == 1 {
                        //let ss_mv = &ss[..];

                        ret.push_str("[");
                        for i in 0..self.shape[0] {
                            let s = &ss[i];
                            if i > 0 {
                                ret.push_str(" ");
                            }
                            for _ in 0..(longest - s.len()) {
                                ret.push_str(" ");
                            }

                            ret = format!("{}{}", ret, s);
                        }
                        ret.push_str("]");
                    } else if self.ndim() == 2 {
                        let s0 = self.strides()[0];
                        ret.push_str("[[");
                        for i in 0..self.shape[0] {
                            if i > 0 {
                                ret.push_str(" [");
                            }
                            for j in 0..self.shape[1] {
                                let s = &ss[i * s0 + j];
                                if j > 0 {
                                    ret.push_str(" ");
                                }
                                for _ in 0..(longest - s.len()) {
                                    ret.push_str(" ");
                                }
                                ret = format!("{}{}", ret, s);
                            }
                            if i == self.shape[0] - 1 {
                                ret.push_str("]]");
                            } else {
                                ret.push_str("]\n");
                            }
                        }
                    }
                } else {
                    ret = format!("Tensor({:?}, type={})", self.shape, $name);
                }
                write!(f, "{}", ret)
            }
        }
    )

}

add_impl!(f32,   "f32");
add_impl!(f64,   "f64");
add_impl!(usize, "usize");
add_impl!(u8,    "u8");
add_impl!(u16,   "u16");
add_impl!(u32,   "u32");
add_impl!(u64,   "u64");
add_impl!(isize, "isize");
add_impl!(i8,    "i8");
add_impl!(i16,   "i16");
add_impl!(i32,   "i32");
add_impl!(i64,   "i64");
add_impl!(bool,  "bool");
<|endoftext|>


<commit_before>//! TODO Documentation
use std::{fmt, panic};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_keyboard, wlr_keyboard_get_modifiers, wlr_keyboard_led,
                  wlr_keyboard_led_update, wlr_keyboard_modifier, wlr_keyboard_set_keymap,
                  xkb_keymap};

use InputDevice;

/// The maximum number of keycodes stored in a `Keyboard`.
pub const WLR_KEYBOARD_KEYS_CAP: usize = 32;

#[derive(Debug)]
pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

#[derive(Debug)]
pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                Some(Keyboard { liveliness: Some(Rc::new(AtomicBool::new(false))),
                                device: InputDevice::from_ptr(device),
                                keyboard })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr() }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    // TODO: Implement keymap wrapper?
    pub fn set_keymap(&mut self, keymap: *mut xkb_keymap) {
        unsafe {
            wlr_keyboard_set_keymap(self.keyboard, keymap);
        }
    }

    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe {
            KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard))
        }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl KeyboardHandle {
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::DoubleUpgrade)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut keyboard))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}
<commit_msg>Fixed set_keymap to have a safe signature<commit_after>//! TODO Documentation
use std::{fmt, panic};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_keyboard, wlr_keyboard_get_modifiers, wlr_keyboard_led,
                  wlr_keyboard_led_update, wlr_keyboard_modifier, wlr_keyboard_set_keymap};

use xkbcommon::xkb::Keymap;

use InputDevice;

/// The maximum number of keycodes stored in a `Keyboard`.
pub const WLR_KEYBOARD_KEYS_CAP: usize = 32;

#[derive(Debug)]
pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

#[derive(Debug)]
pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                Some(Keyboard { liveliness: Some(Rc::new(AtomicBool::new(false))),
                                device: InputDevice::from_ptr(device),
                                keyboard })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr() }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe {
            KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard))
        }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl KeyboardHandle {
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::DoubleUpgrade)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut keyboard))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}
<|endoftext|>