<commit_before>use bifrost::conshash::weights::Weights;
use bifrost::conshash::ConsistentHashing;
use bifrost::membership::member::MemberService;
use bifrost::membership::server::Membership;
use bifrost::raft;
use bifrost::raft::client::RaftClient;
use bifrost::raft::state_machine::master as sm_master;
use bifrost::rpc;
use bifrost::rpc::Server;
use bifrost::tcp::STANDALONE_ADDRESS_STRING;
use bifrost::utils::fut_exec::wait;
use futures::Future;
use ram::chunk::Chunks;
use ram::cleaner::Cleaner;
use ram::schema::sm as schema_sm;
use ram::schema::LocalSchemasCache;
use ram::types::Id;
use std::io;
use std::sync::Arc;

pub mod cell_rpc;
pub mod transactions;

pub static CONS_HASH_ID: u64 = hash_ident!(NEB_CONSHASH_MEM_WEIGHTS) as u64;

#[derive(Debug)]
pub enum ServerError {
    CannotJoinCluster,
    CannotJoinClusterGroup(sm_master::ExecError),
    CannotInitMemberTable,
    CannotSetServerWeight,
    CannotInitConsistentHashTable,
    CannotLoadMetaClient,
    CannotInitializeSchemaServer(sm_master::ExecError),
    StandaloneMustAlsoBeMetaServer,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerOptions {
    pub chunk_count: usize,
    pub memory_size: usize,
    pub backup_storage: Option<String>,
    pub wal_storage: Option<String>,
}

pub struct ServerMeta {
    pub schemas: LocalSchemasCache,
}

pub struct NebServer {
    pub chunks: Arc<Chunks>,
    pub meta: Arc<ServerMeta>,
    pub rpc: Arc<rpc::Server>,
    pub consh: Arc<ConsistentHashing>,
    pub member_pool: rpc::ClientPool,
    pub txn_peer: transactions::Peer,
    pub raft_service: Option<Arc<raft::RaftService>>,
    pub server_id: u64,
    pub cleaner: Cleaner,
}

pub fn init_conshash(
    group_name: &String,
    address: &String,
    memory_size: u64,
    raft_client: &Arc<RaftClient>,
) -> Result<Arc<ConsistentHashing>, ServerError> {
    match ConsistentHashing::new_with_id(CONS_HASH_ID, group_name, raft_client) {
        Ok(ch) => {
            ch.set_weight(address, memory_size).wait();
            if !ch.init_table().is_ok() {
                error!("Cannot initialize member table");
                return Err(ServerError::CannotInitMemberTable);
            }
            return Ok(ch);
        }
        _ => {
            error!("Cannot initialize consistent hash table");
            return Err(ServerError::CannotInitConsistentHashTable);
        }
    }
}

impl NebServer {
    pub fn new(
        opts: &ServerOptions,
        server_addr: &String,
        group_name: &String,
        rpc_server: &Arc<rpc::Server>,
        raft_service: &Option<Arc<raft::RaftService>>,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<NebServer>, ServerError> {
        debug!(
            "Creating key-value server instance, group name {}",
            group_name
        );
        if let &Some(ref raft_service) = raft_service {
            raft_service.register_state_machine(Box::new(schema_sm::SchemasSM::new(
                group_name,
                raft_service,
            )));
            Weights::new_with_id(CONS_HASH_ID, raft_service);
        }
        let schemas = LocalSchemasCache::new(group_name, Some(raft_client)).unwrap();
        let meta_rc = Arc::new(ServerMeta { schemas });
        let chunks = Chunks::new(
            opts.chunk_count,
            opts.memory_size,
            meta_rc.clone(),
            opts.backup_storage.clone(),
            opts.wal_storage.clone(),
        );
        let cleaner = Cleaner::new_and_start(chunks.clone());
        let conshasing = init_conshash(
            group_name,
            server_addr,
            opts.memory_size as u64,
            raft_client,
        )?;
        let server = Arc::new(NebServer {
            chunks,
            cleaner,
            meta: meta_rc,
            rpc: rpc_server.clone(),
            consh: conshasing.clone(),
            member_pool: rpc::ClientPool::new(),
            txn_peer: transactions::Peer::new(server_addr),
            raft_service: raft_service.clone(),
            server_id: rpc_server.server_id,
        });
        rpc_server.register_service(
            cell_rpc::DEFAULT_SERVICE_ID,
            &cell_rpc::NebRPCService::new(&server),
        );
        rpc_server.register_service(
            transactions::manager::DEFAULT_SERVICE_ID,
            &transactions::manager::TransactionManager::new(&server),
        );
        rpc_server.register_service(
            transactions::data_site::DEFAULT_SERVICE_ID,
            &transactions::data_site::DataManager::new(&server),
        );
        Ok(server)
    }

    pub fn new_from_opts<'a>(
        opts: &ServerOptions,
        server_addr: &'a str,
        group_name: &'a str,
    ) -> Arc<NebServer> {
        debug!("Creating key-value server from options");
        let group_name = &String::from(group_name);
        let server_addr = &String::from(server_addr);
        let rpc_server = rpc::Server::new(server_addr);
        let meta_mambers = &vec![server_addr.to_owned()];
        let raft_service = raft::RaftService::new(raft::Options {
            storage: raft::Storage::MEMORY,
            address: server_addr.to_owned(),
            service_id: raft::DEFAULT_SERVICE_ID,
        });
        Server::listen_and_resume(&rpc_server);
        rpc_server.register_service(raft::DEFAULT_SERVICE_ID, &raft_service);
        raft::RaftService::start(&raft_service);
        match raft_service.join(meta_mambers) {
            Err(sm_master::ExecError::CannotConstructClient) => {
                info!("Cannot join meta cluster, will bootstrap one.");
                raft_service.bootstrap();
            }
            Ok(Ok(())) => {
                info!(
                    "Joined meta cluster, number of members: {}",
                    raft_service.num_members()
                );
            }
            e => {
                error!("Cannot join into cluster: {:?}", e);
                panic!("{:?}", ServerError::CannotJoinCluster)
            }
        }
        Membership::new(&rpc_server, &raft_service);
        let raft_client = RaftClient::new(meta_mambers, raft::DEFAULT_SERVICE_ID).unwrap();
        RaftClient::prepare_subscription(&rpc_server);
        let member_service = MemberService::new(server_addr, &raft_client);
        member_service.join_group(group_name).wait().unwrap();
        NebServer::new(
            opts,
            server_addr,
            group_name,
            &rpc_server,
            &Some(raft_service),
            &raft_client,
        )
        .unwrap()
    }

    pub fn get_server_id_by_id(&self, id: &Id) -> Option<u64> {
        if let Some(server_id) = self.consh.get_server_id(id.higher) {
            Some(server_id)
        } else {
            None
        }
    }
    pub fn get_member_by_server_id(&self, server_id: u64) -> io::Result<Arc<rpc::RPCClient>> {
        self.member_pool
            .get_by_id(server_id, |_| self.consh.to_server_name(server_id))
    }
}

#[cfg(test)]
mod tests {
    extern crate test;

    use client;
    use client::AsyncClient;
    use dovahkiin::types::custom_types::id::Id;
    use dovahkiin::types::custom_types::map::Map;
    use dovahkiin::types::type_id_of;
    use futures::Future;
    use ram::cell::Cell;
    use ram::schema::Field;
    use ram::schema::Schema;
    use ram::types::*;
    use server::NebServer;
    use server::ServerOptions;
    use std::sync::Arc;
    use test::Bencher;

    const DATA: &'static str = "DATA";

    fn init_service(port: usize) -> (Arc<NebServer>, Arc<AsyncClient>, u32) {
        env_logger::init();
        let server_addr = String::from(format!("127.0.0.1:{}", port));
        let server_group = String::from("bench_test");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 512 * 1024 * 1024,
                backup_storage: Some(format!("test-data/{}-bak", port)),
                wal_storage: Some(format!("test-data/{}-wal", port)),
            },
            &server_addr,
            &server_group,
        );
        let schema_id = 123;
        let schema = Schema {
            id: schema_id,
            name: String::from("schema"),
            key_field: None,
            str_key_field: None,
            is_dynamic: false,
            fields: Field::new(
                "*",
                0,
                false,
                false,
                Some(vec![Field::new(
                    DATA,
                    type_id_of(Type::U64),
                    false,
                    false,
                    None,
                )]),
            ),
        };

        let client = Arc::new(
            client::AsyncClient::new(&server.rpc, &vec![server_addr], &server_group).unwrap(),
        );
        client.new_schema_with_id(schema).wait();
        (server, client, schema_id)
    }

    #[bench]
    fn wr(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5302);
        let id = Id::new(0, 1);
        let mut value = Value::Map(Map::new());
        value[DATA] = Value::U64(2);
        let cell = Cell::new_with_id(schema_id, &id, value);
        b.iter(|| {
            client.upsert_cell(cell.clone()).wait();
        })
    }

    #[bench]
    fn txn_upsert(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5303);
        b.iter(|| {
            client
                .transaction(move |txn| {
                    let id = Id::new(0, 1);
                    let mut value = Value::Map(Map::new());
                    value[DATA] = Value::U64(2);
                    let cell = Cell::new_with_id(schema_id, &id, value);
                    txn.upsert(cell)
                })
                .wait()
        })
    }

    #[bench]
    fn txn_insert(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5305);
        let mut i = 0;
        b.iter(|| {
            client
                .transaction(move |txn| {
                    let id = Id::new(0, i);
                    let mut value = Value::Map(Map::new());
                    value[DATA] = Value::U64(i);
                    let cell = Cell::new_with_id(schema_id, &id, value);
                    txn.write(cell)
                })
                .wait();
            i += 1;
        })
    }

    #[bench]
    fn noop_txn(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5304);
        b.iter(|| client.transaction(move |txn| Ok(())).wait())
    }

    #[bench]
    fn cell_construct(b: &mut Bencher) {
        b.iter(|| {
            let id = Id::new(0, 1);
            let mut value = Value::Map(Map::new());
            value["DATA"] = Value::U64(2);
            Cell::new_with_id(1, &id, value);
        })
    }

    #[bench]
    fn cell_clone(b: &mut Bencher) {
        let id = Id::new(0, 1);
        let mut value = Value::Map(Map::new());
        value["DATA"] = Value::U64(2);
        let cell = Cell::new_with_id(1, &id, value);
        b.iter(|| {
            cell.clone();
        })
    }
}
<commit_msg>write bench<commit_after>use bifrost::conshash::weights::Weights;
use bifrost::conshash::ConsistentHashing;
use bifrost::membership::member::MemberService;
use bifrost::membership::server::Membership;
use bifrost::raft;
use bifrost::raft::client::RaftClient;
use bifrost::raft::state_machine::master as sm_master;
use bifrost::rpc;
use bifrost::rpc::Server;
use bifrost::tcp::STANDALONE_ADDRESS_STRING;
use bifrost::utils::fut_exec::wait;
use futures::Future;
use ram::chunk::Chunks;
use ram::cleaner::Cleaner;
use ram::schema::sm as schema_sm;
use ram::schema::LocalSchemasCache;
use ram::types::Id;
use std::io;
use std::sync::Arc;

pub mod cell_rpc;
pub mod transactions;

pub static CONS_HASH_ID: u64 = hash_ident!(NEB_CONSHASH_MEM_WEIGHTS) as u64;

#[derive(Debug)]
pub enum ServerError {
    CannotJoinCluster,
    CannotJoinClusterGroup(sm_master::ExecError),
    CannotInitMemberTable,
    CannotSetServerWeight,
    CannotInitConsistentHashTable,
    CannotLoadMetaClient,
    CannotInitializeSchemaServer(sm_master::ExecError),
    StandaloneMustAlsoBeMetaServer,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerOptions {
    pub chunk_count: usize,
    pub memory_size: usize,
    pub backup_storage: Option<String>,
    pub wal_storage: Option<String>,
}

pub struct ServerMeta {
    pub schemas: LocalSchemasCache,
}

pub struct NebServer {
    pub chunks: Arc<Chunks>,
    pub meta: Arc<ServerMeta>,
    pub rpc: Arc<rpc::Server>,
    pub consh: Arc<ConsistentHashing>,
    pub member_pool: rpc::ClientPool,
    pub txn_peer: transactions::Peer,
    pub raft_service: Option<Arc<raft::RaftService>>,
    pub server_id: u64,
    pub cleaner: Cleaner,
}

pub fn init_conshash(
    group_name: &String,
    address: &String,
    memory_size: u64,
    raft_client: &Arc<RaftClient>,
) -> Result<Arc<ConsistentHashing>, ServerError> {
    match ConsistentHashing::new_with_id(CONS_HASH_ID, group_name, raft_client) {
        Ok(ch) => {
            ch.set_weight(address, memory_size).wait();
            if !ch.init_table().is_ok() {
                error!("Cannot initialize member table");
                return Err(ServerError::CannotInitMemberTable);
            }
            return Ok(ch);
        }
        _ => {
            error!("Cannot initialize consistent hash table");
            return Err(ServerError::CannotInitConsistentHashTable);
        }
    }
}

impl NebServer {
    pub fn new(
        opts: &ServerOptions,
        server_addr: &String,
        group_name: &String,
        rpc_server: &Arc<rpc::Server>,
        raft_service: &Option<Arc<raft::RaftService>>,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<NebServer>, ServerError> {
        debug!(
            "Creating key-value server instance, group name {}",
            group_name
        );
        if let &Some(ref raft_service) = raft_service {
            raft_service.register_state_machine(Box::new(schema_sm::SchemasSM::new(
                group_name,
                raft_service,
            )));
            Weights::new_with_id(CONS_HASH_ID, raft_service);
        }
        let schemas = LocalSchemasCache::new(group_name, Some(raft_client)).unwrap();
        let meta_rc = Arc::new(ServerMeta { schemas });
        let chunks = Chunks::new(
            opts.chunk_count,
            opts.memory_size,
            meta_rc.clone(),
            opts.backup_storage.clone(),
            opts.wal_storage.clone(),
        );
        let cleaner = Cleaner::new_and_start(chunks.clone());
        let conshasing = init_conshash(
            group_name,
            server_addr,
            opts.memory_size as u64,
            raft_client,
        )?;
        let server = Arc::new(NebServer {
            chunks,
            cleaner,
            meta: meta_rc,
            rpc: rpc_server.clone(),
            consh: conshasing.clone(),
            member_pool: rpc::ClientPool::new(),
            txn_peer: transactions::Peer::new(server_addr),
            raft_service: raft_service.clone(),
            server_id: rpc_server.server_id,
        });
        rpc_server.register_service(
            cell_rpc::DEFAULT_SERVICE_ID,
            &cell_rpc::NebRPCService::new(&server),
        );
        rpc_server.register_service(
            transactions::manager::DEFAULT_SERVICE_ID,
            &transactions::manager::TransactionManager::new(&server),
        );
        rpc_server.register_service(
            transactions::data_site::DEFAULT_SERVICE_ID,
            &transactions::data_site::DataManager::new(&server),
        );
        Ok(server)
    }

    pub fn new_from_opts<'a>(
        opts: &ServerOptions,
        server_addr: &'a str,
        group_name: &'a str,
    ) -> Arc<NebServer> {
        debug!("Creating key-value server from options");
        let group_name = &String::from(group_name);
        let server_addr = &String::from(server_addr);
        let rpc_server = rpc::Server::new(server_addr);
        let meta_mambers = &vec![server_addr.to_owned()];
        let raft_service = raft::RaftService::new(raft::Options {
            storage: raft::Storage::MEMORY,
            address: server_addr.to_owned(),
            service_id: raft::DEFAULT_SERVICE_ID,
        });
        Server::listen_and_resume(&rpc_server);
        rpc_server.register_service(raft::DEFAULT_SERVICE_ID, &raft_service);
        raft::RaftService::start(&raft_service);
        match raft_service.join(meta_mambers) {
            Err(sm_master::ExecError::CannotConstructClient) => {
                info!("Cannot join meta cluster, will bootstrap one.");
                raft_service.bootstrap();
            }
            Ok(Ok(())) => {
                info!(
                    "Joined meta cluster, number of members: {}",
                    raft_service.num_members()
                );
            }
            e => {
                error!("Cannot join into cluster: {:?}", e);
                panic!("{:?}", ServerError::CannotJoinCluster)
            }
        }
        Membership::new(&rpc_server, &raft_service);
        let raft_client = RaftClient::new(meta_mambers, raft::DEFAULT_SERVICE_ID).unwrap();
        RaftClient::prepare_subscription(&rpc_server);
        let member_service = MemberService::new(server_addr, &raft_client);
        member_service.join_group(group_name).wait().unwrap();
        NebServer::new(
            opts,
            server_addr,
            group_name,
            &rpc_server,
            &Some(raft_service),
            &raft_client,
        )
        .unwrap()
    }

    pub fn get_server_id_by_id(&self, id: &Id) -> Option<u64> {
        if let Some(server_id) = self.consh.get_server_id(id.higher) {
            Some(server_id)
        } else {
            None
        }
    }
    pub fn get_member_by_server_id(&self, server_id: u64) -> io::Result<Arc<rpc::RPCClient>> {
        self.member_pool
            .get_by_id(server_id, |_| self.consh.to_server_name(server_id))
    }
}

#[cfg(test)]
mod tests {
    extern crate test;

    use client;
    use client::AsyncClient;
    use dovahkiin::types::custom_types::id::Id;
    use dovahkiin::types::custom_types::map::Map;
    use dovahkiin::types::type_id_of;
    use futures::Future;
    use ram::cell::Cell;
    use ram::schema::Field;
    use ram::schema::Schema;
    use ram::types::*;
    use server::NebServer;
    use server::ServerOptions;
    use std::sync::Arc;
    use test::Bencher;

    const DATA: &'static str = "DATA";

    fn init_service(port: usize) -> (Arc<NebServer>, Arc<AsyncClient>, u32) {
        env_logger::init();
        let server_addr = String::from(format!("127.0.0.1:{}", port));
        let server_group = String::from("bench_test");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 512 * 1024 * 1024,
                backup_storage: Some(format!("test-data/{}-bak", port)),
                wal_storage: Some(format!("test-data/{}-wal", port)),
            },
            &server_addr,
            &server_group,
        );
        let schema_id = 123;
        let schema = Schema {
            id: schema_id,
            name: String::from("schema"),
            key_field: None,
            str_key_field: None,
            is_dynamic: false,
            fields: Field::new(
                "*",
                0,
                false,
                false,
                Some(vec![Field::new(
                    DATA,
                    type_id_of(Type::U64),
                    false,
                    false,
                    None,
                )]),
            ),
        };

        let client = Arc::new(
            client::AsyncClient::new(&server.rpc, &vec![server_addr], &server_group).unwrap(),
        );
        client.new_schema_with_id(schema).wait();
        (server, client, schema_id)
    }

    #[bench]
    fn wr(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5302);
        let id = Id::new(0, 1);
        let mut value = Value::Map(Map::new());
        value[DATA] = Value::U64(2);
        let cell = Cell::new_with_id(schema_id, &id, value);
        b.iter(|| {
            client.upsert_cell(cell.clone()).wait();
        })
    }

    #[bench]
    fn w(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5306);
        let id = Id::new(0, 1);
        let mut value = Value::Map(Map::new());
        value[DATA] = Value::U64(2);
        let mut cell = Cell::new_with_id(schema_id, &id, value);
        let mut i = 0;
        b.iter(|| {
            let mut cell = cell.clone();
            cell.header.hash = i;
            client.write_cell(cell).wait();
            i += 1
        })
    }

    #[bench]
    fn txn_upsert(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5303);
        b.iter(|| {
            client
                .transaction(move |txn| {
                    let id = Id::new(0, 1);
                    let mut value = Value::Map(Map::new());
                    value[DATA] = Value::U64(2);
                    let cell = Cell::new_with_id(schema_id, &id, value);
                    txn.upsert(cell)
                })
                .wait()
        })
    }

    #[bench]
    fn txn_insert(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5305);
        let mut i = 0;
        b.iter(|| {
            client
                .transaction(move |txn| {
                    let id = Id::new(0, i);
                    let mut value = Value::Map(Map::new());
                    value[DATA] = Value::U64(i);
                    let cell = Cell::new_with_id(schema_id, &id, value);
                    txn.write(cell)
                })
                .wait();
            i += 1;
        })
    }

    #[bench]
    fn noop_txn(b: &mut Bencher) {
        let (_, client, schema_id) = init_service(5304);
        b.iter(|| client.transaction(move |txn| Ok(())).wait())
    }

    #[bench]
    fn cell_construct(b: &mut Bencher) {
        b.iter(|| {
            let id = Id::new(0, 1);
            let mut value = Value::Map(Map::new());
            value["DATA"] = Value::U64(2);
            Cell::new_with_id(1, &id, value);
        })
    }

    #[bench]
    fn cell_clone(b: &mut Bencher) {
        let id = Id::new(0, 1);
        let mut value = Value::Map(Map::new());
        value["DATA"] = Value::U64(2);
        let cell = Cell::new_with_id(1, &id, value);
        b.iter(|| {
            cell.clone();
        })
    }
}
<|endoftext|>


<commit_before>/// Conversion from an `Iterator`.
///
/// By implementing `FromIterator` for a type, you define how it will be
/// created from an iterator. This is common for types which describe a
/// collection of some kind.
///
/// `FromIterator`'s [`from_iter`] is rarely called explicitly, and is instead
/// used through [`Iterator`]'s [`collect`] method. See [`collect`]'s
/// documentation for more examples.
///
/// [`from_iter`]: #tymethod.from_iter
/// [`Iterator`]: trait.Iterator.html
/// [`collect`]: trait.Iterator.html#method.collect
///
/// See also: [`IntoIterator`].
///
/// [`IntoIterator`]: trait.IntoIterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::iter::FromIterator;
///
/// let five_fives = std::iter::repeat(5).take(5);
///
/// let v = Vec::from_iter(five_fives);
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
///
/// Using [`collect`] to implicitly use `FromIterator`:
///
/// ```
/// let five_fives = std::iter::repeat(5).take(5);
///
/// let v: Vec<i32> = five_fives.collect();
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
///
/// Implementing `FromIterator` for your type:
///
/// ```
/// use std::iter::FromIterator;
///
/// // A sample collection, that's just a wrapper over Vec<T>
/// #[derive(Debug)]
/// struct MyCollection(Vec<i32>);
///
/// // Let's give it some methods so we can create one and add things
/// // to it.
/// impl MyCollection {
///     fn new() -> MyCollection {
///         MyCollection(Vec::new())
///     }
///
///     fn add(&mut self, elem: i32) {
///         self.0.push(elem);
///     }
/// }
///
/// // and we'll implement FromIterator
/// impl FromIterator<i32> for MyCollection {
///     fn from_iter<I: IntoIterator<Item=i32>>(iter: I) -> Self {
///         let mut c = MyCollection::new();
///
///         for i in iter {
///             c.add(i);
///         }
///
///         c
///     }
/// }
///
/// // Now we can make a new iterator...
/// let iter = (0..5).into_iter();
///
/// // ... and make a MyCollection out of it
/// let c = MyCollection::from_iter(iter);
///
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
///
/// // collect works too!
///
/// let iter = (0..5).into_iter();
/// let c: MyCollection = iter.collect();
///
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
    message="a collection of type `{Self}` cannot be built from an iterator \
             over elements of type `{A}`",
    label="a collection of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`",
)]
pub trait FromIterator<A>: Sized {
    /// Creates a value from an iterator.
    ///
    /// See the [module-level documentation] for more.
    ///
    /// [module-level documentation]: index.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use std::iter::FromIterator;
    ///
    /// let five_fives = std::iter::repeat(5).take(5);
    ///
    /// let v = Vec::from_iter(five_fives);
    ///
    /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> Self;
}

/// Conversion into an `Iterator`.
///
/// By implementing `IntoIterator` for a type, you define how it will be
/// converted to an iterator. This is common for types which describe a
/// collection of some kind.
///
/// One benefit of implementing `IntoIterator` is that your type will [work
/// with Rust's `for` loop syntax](index.html#for-loops-and-intoiterator).
///
/// See also: [`FromIterator`].
///
/// [`FromIterator`]: trait.FromIterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let v = vec![1, 2, 3];
/// let mut iter = v.into_iter();
///
/// assert_eq!(Some(1), iter.next());
/// assert_eq!(Some(2), iter.next());
/// assert_eq!(Some(3), iter.next());
/// assert_eq!(None, iter.next());
/// ```
/// Implementing `IntoIterator` for your type:
///
/// ```
/// // A sample collection, that's just a wrapper over Vec<T>
/// #[derive(Debug)]
/// struct MyCollection(Vec<i32>);
///
/// // Let's give it some methods so we can create one and add things
/// // to it.
/// impl MyCollection {
///     fn new() -> MyCollection {
///         MyCollection(Vec::new())
///     }
///
///     fn add(&mut self, elem: i32) {
///         self.0.push(elem);
///     }
/// }
///
/// // and we'll implement IntoIterator
/// impl IntoIterator for MyCollection {
///     type Item = i32;
///     type IntoIter = ::std::vec::IntoIter<Self::Item>;
///
///     fn into_iter(self) -> Self::IntoIter {
///         self.0.into_iter()
///     }
/// }
///
/// // Now we can make a new collection...
/// let mut c = MyCollection::new();
///
/// // ... add some stuff to it ...
/// c.add(0);
/// c.add(1);
/// c.add(2);
///
/// // ... and then turn it into an Iterator:
/// for (i, n) in c.into_iter().enumerate() {
///     assert_eq!(i as i32, n);
/// }
/// ```
///
/// It is common to use `IntoIterator` as a trait bound. This allows
/// the input collection type to change, so long as it is still an
/// iterator. Additional bounds can be specified by restricting on
/// `Item`:
///
/// ```rust
/// #![feature(associated_type_bounds)]
///
/// fn collect_as_strings<T>(collection: T) -> Vec<String>
/// where
///     T: IntoIterator<Item: std::fmt::Debug>,
/// {
///     collection
///         .into_iter()
///         .map(|item| format!("{:?}", item))
///         .collect()
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
    /// The type of the elements being iterated over.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Item;

    /// Which kind of iterator are we turning this into?
    #[stable(feature = "rust1", since = "1.0.0")]
    type IntoIter: Iterator<Item=Self::Item>;

    /// Creates an iterator from a value.
    ///
    /// See the [module-level documentation] for more.
    ///
    /// [module-level documentation]: index.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let v = vec![1, 2, 3];
    /// let mut iter = v.into_iter();
    ///
    /// assert_eq!(Some(1), iter.next());
    /// assert_eq!(Some(2), iter.next());
    /// assert_eq!(Some(3), iter.next());
    /// assert_eq!(None, iter.next());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn into_iter(self) -> Self::IntoIter;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I;

    fn into_iter(self) -> I {
        self
    }
}

/// Extend a collection with the contents of an iterator.
///
/// Iterators produce a series of values, and collections can also be thought
/// of as a series of values. The `Extend` trait bridges this gap, allowing you
/// to extend a collection by including the contents of that iterator. When
/// extending a collection with an already existing key, that entry is updated
/// or, in the case of collections that permit multiple entries with equal
/// keys, that entry is inserted.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // You can extend a String with some chars:
/// let mut message = String::from("The first three letters are: ");
///
/// message.extend(&['a', 'b', 'c']);
///
/// assert_eq!("abc", &message[29..32]);
/// ```
///
/// Implementing `Extend`:
///
/// ```
/// // A sample collection, that's just a wrapper over Vec<T>
/// #[derive(Debug)]
/// struct MyCollection(Vec<i32>);
///
/// // Let's give it some methods so we can create one and add things
/// // to it.
/// impl MyCollection {
///     fn new() -> MyCollection {
///         MyCollection(Vec::new())
///     }
///
///     fn add(&mut self, elem: i32) {
///         self.0.push(elem);
///     }
/// }
///
/// // since MyCollection has a list of i32s, we implement Extend for i32
/// impl Extend<i32> for MyCollection {
///
///     // This is a bit simpler with the concrete type signature: we can call
///     // extend on anything which can be turned into an Iterator which gives
///     // us i32s. Because we need i32s to put into MyCollection.
///     fn extend<T: IntoIterator<Item=i32>>(&mut self, iter: T) {
///
///         // The implementation is very straightforward: loop through the
///         // iterator, and add() each element to ourselves.
///         for elem in iter {
///             self.add(elem);
///         }
///     }
/// }
///
/// let mut c = MyCollection::new();
///
/// c.add(5);
/// c.add(6);
/// c.add(7);
///
/// // let's extend our collection with three more numbers
/// c.extend(vec![1, 2, 3]);
///
/// // we've added these elements onto the end
/// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{:?}", c));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Extend<A> {
    /// Extends a collection with the contents of an iterator.
    ///
    /// As this is the only method for this trait, the [trait-level] docs
    /// contain more details.
    ///
    /// [trait-level]: trait.Extend.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// // You can extend a String with some chars:
    /// let mut message = String::from("abc");
    ///
    /// message.extend(['d', 'e', 'f'].iter());
    ///
    /// assert_eq!("abcdef", &message);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T);
}

#[stable(feature = "extend_for_unit", since = "1.28.0")]
impl Extend<()> for () {
    fn extend<T: IntoIterator<Item = ()>>(&mut self, iter: T) {
        iter.into_iter().for_each(drop)
    }
}
<commit_msg>Don't use associated type bounds in docs until it is stable<commit_after>/// Conversion from an `Iterator`.
///
/// By implementing `FromIterator` for a type, you define how it will be
/// created from an iterator. This is common for types which describe a
/// collection of some kind.
///
/// `FromIterator`'s [`from_iter`] is rarely called explicitly, and is instead
/// used through [`Iterator`]'s [`collect`] method. See [`collect`]'s
/// documentation for more examples.
///
/// [`from_iter`]: #tymethod.from_iter
/// [`Iterator`]: trait.Iterator.html
/// [`collect`]: trait.Iterator.html#method.collect
///
/// See also: [`IntoIterator`].
///
/// [`IntoIterator`]: trait.IntoIterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::iter::FromIterator;
///
/// let five_fives = std::iter::repeat(5).take(5);
///
/// let v = Vec::from_iter(five_fives);
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
///
/// Using [`collect`] to implicitly use `FromIterator`:
///
/// ```
/// let five_fives = std::iter::repeat(5).take(5);
///
/// let v: Vec<i32> = five_fives.collect();
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
///
/// Implementing `FromIterator` for your type:
///
/// ```
/// use std::iter::FromIterator;
///
/// // A sample collection, that's just a wrapper over Vec<T>
/// #[derive(Debug)]
/// struct MyCollection(Vec<i32>);
///
/// // Let's give it some methods so we can create one and add things
/// // to it.
/// impl MyCollection {
///     fn new() -> MyCollection {
///         MyCollection(Vec::new())
///     }
///
///     fn add(&mut self, elem: i32) {
///         self.0.push(elem);
///     }
/// }
///
/// // and we'll implement FromIterator
/// impl FromIterator<i32> for MyCollection {
///     fn from_iter<I: IntoIterator<Item=i32>>(iter: I) -> Self {
///         let mut c = MyCollection::new();
///
///         for i in iter {
///             c.add(i);
///         }
///
///         c
///     }
/// }
///
/// // Now we can make a new iterator...
/// let iter = (0..5).into_iter();
///
/// // ... and make a MyCollection out of it
/// let c = MyCollection::from_iter(iter);
///
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
///
/// // collect works too!
///
/// let iter = (0..5).into_iter();
/// let c: MyCollection = iter.collect();
///
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
    message="a collection of type `{Self}` cannot be built from an iterator \
             over elements of type `{A}`",
    label="a collection of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`",
)]
pub trait FromIterator<A>: Sized {
    /// Creates a value from an iterator.
    ///
    /// See the [module-level documentation] for more.
    ///
    /// [module-level documentation]: index.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use std::iter::FromIterator;
    ///
    /// let five_fives = std::iter::repeat(5).take(5);
    ///
    /// let v = Vec::from_iter(five_fives);
    ///
    /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> Self;
}

/// Conversion into an `Iterator`.
///
/// By implementing `IntoIterator` for a type, you define how it will be
/// converted to an iterator. This is common for types which describe a
/// collection of some kind.
///
/// One benefit of implementing `IntoIterator` is that your type will [work
/// with Rust's `for` loop syntax](index.html#for-loops-and-intoiterator).
///
/// See also: [`FromIterator`].
///
/// [`FromIterator`]: trait.FromIterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let v = vec![1, 2, 3];
/// let mut iter = v.into_iter();
///
/// assert_eq!(Some(1), iter.next());
/// assert_eq!(Some(2), iter.next());
/// assert_eq!(Some(3), iter.next());
/// assert_eq!(None, iter.next());
/// ```
/// Implementing `IntoIterator` for your type:
///
/// ```
/// // A sample collection, that's just a wrapper over Vec<T>
/// #[derive(Debug)]
/// struct MyCollection(Vec<i32>);
///
/// // Let's give it some methods so we can create one and add things
/// // to it.
/// impl MyCollection {
///     fn new() -> MyCollection {
///         MyCollection(Vec::new())
///     }
///
///     fn add(&mut self, elem: i32) {
///         self.0.push(elem);
///     }
/// }
///
/// // and we'll implement IntoIterator
/// impl IntoIterator for MyCollection {
///     type Item = i32;
///     type IntoIter = ::std::vec::IntoIter<Self::Item>;
///
///     fn into_iter(self) -> Self::IntoIter {
///         self.0.into_iter()
///     }
/// }
///
/// // Now we can make a new collection...
/// let mut c = MyCollection::new();
///
/// // ... add some stuff to it ...
/// c.add(0);
/// c.add(1);
/// c.add(2);
///
/// // ... and then turn it into an Iterator:
/// for (i, n) in c.into_iter().enumerate() {
///     assert_eq!(i as i32, n);
/// }
/// ```
///
/// It is common to use `IntoIterator` as a trait bound. This allows
/// the input collection type to change, so long as it is still an
/// iterator. Additional bounds can be specified by restricting on
/// `Item`:
///
/// ```rust
/// fn collect_as_strings<T>(collection: T) -> Vec<String>
/// where
///     T: IntoIterator,
///     T::Item: std::fmt::Debug,
/// {
///     collection
///         .into_iter()
///         .map(|item| format!("{:?}", item))
///         .collect()
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
    /// The type of the elements being iterated over.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Item;

    /// Which kind of iterator are we turning this into?
    #[stable(feature = "rust1", since = "1.0.0")]
    type IntoIter: Iterator<Item=Self::Item>;

    /// Creates an iterator from a value.
    ///
    /// See the [module-level documentation] for more.
    ///
    /// [module-level documentation]: index.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let v = vec![1, 2, 3];
    /// let mut iter = v.into_iter();
    ///
    /// assert_eq!(Some(1), iter.next());
    /// assert_eq!(Some(2), iter.next());
    /// assert_eq!(Some(3), iter.next());
    /// assert_eq!(None, iter.next());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn into_iter(self) -> Self::IntoIter;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I;

    fn into_iter(self) -> I {
        self
    }
}

/// Extend a collection with the contents of an iterator.
///
/// Iterators produce a series of values, and collections can also be thought
/// of as a series of values. The `Extend` trait bridges this gap, allowing you
/// to extend a collection by including the contents of that iterator. When
/// extending a collection with an already existing key, that entry is updated
/// or, in the case of collections that permit multiple entries with equal
/// keys, that entry is inserted.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // You can extend a String with some chars:
/// let mut message = String::from("The first three letters are: ");
///
/// message.extend(&['a', 'b', 'c']);
///
/// assert_eq!("abc", &message[29..32]);
/// ```
///
/// Implementing `Extend`:
///
/// ```
/// // A sample collection, that's just a wrapper over Vec<T>
/// #[derive(Debug)]
/// struct MyCollection(Vec<i32>);
///
/// // Let's give it some methods so we can create one and add things
/// // to it.
/// impl MyCollection {
///     fn new() -> MyCollection {
///         MyCollection(Vec::new())
///     }
///
///     fn add(&mut self, elem: i32) {
///         self.0.push(elem);
///     }
/// }
///
/// // since MyCollection has a list of i32s, we implement Extend for i32
/// impl Extend<i32> for MyCollection {
///
///     // This is a bit simpler with the concrete type signature: we can call
///     // extend on anything which can be turned into an Iterator which gives
///     // us i32s. Because we need i32s to put into MyCollection.
///     fn extend<T: IntoIterator<Item=i32>>(&mut self, iter: T) {
///
///         // The implementation is very straightforward: loop through the
///         // iterator, and add() each element to ourselves.
///         for elem in iter {
///             self.add(elem);
///         }
///     }
/// }
///
/// let mut c = MyCollection::new();
///
/// c.add(5);
/// c.add(6);
/// c.add(7);
///
/// // let's extend our collection with three more numbers
/// c.extend(vec![1, 2, 3]);
///
/// // we've added these elements onto the end
/// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{:?}", c));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Extend<A> {
    /// Extends a collection with the contents of an iterator.
    ///
    /// As this is the only method for this trait, the [trait-level] docs
    /// contain more details.
    ///
    /// [trait-level]: trait.Extend.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// // You can extend a String with some chars:
    /// let mut message = String::from("abc");
    ///
    /// message.extend(['d', 'e', 'f'].iter());
    ///
    /// assert_eq!("abcdef", &message);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T);
}

#[stable(feature = "extend_for_unit", since = "1.28.0")]
impl Extend<()> for () {
    fn extend<T: IntoIterator<Item = ()>>(&mut self, iter: T) {
        iter.into_iter().for_each(drop)
    }
}
<|endoftext|>


<commit_before>pub mod play_state;

use std::time::Duration;

use sdl2::mouse;

use ggez::{Context, GameResult};
use ggez::event::{Assets, EventHandler, Transition, Keycode, Mod, Button, Axis};
use states::play_state::PlayState;

/// A `StateManager` will manage requests to push, pop or swap states on the
/// state stack. It owns the `Assets` struct and dictates whether the game
/// continues to run or not.
pub struct StateManager {
    running: bool,
    states: Vec<Box<EventHandler>>,
}

impl StateManager {
    pub fn new(ctx: &mut Context, assets: &Assets) -> StateManager
    {
        let state = Box::new(PlayState::new(ctx, &assets).unwrap());

        StateManager {
            running: true,
            states: vec![state], // create empty state stack
        }
    }

    pub fn is_running(&self) -> bool {
        self.running
    }

    pub fn quit(&mut self) {
        // TODO: pop everything off the stack
        self.running = false
    }
}

impl StateManager {
    fn handle_transition(&mut self, transition: Transition) {
        match transition {
            Transition::None => (),
            Transition::Pop => self.pop(),
            Transition::Swap(state) => self.swap(state),
            Transition::Push(state) => self.push(state),
        }
    }

    fn pop(&mut self) {
        self.states.pop();

        if self.states.is_empty() {
            self.quit();
        }
    }

    fn push(&mut self, boxed_state: Box<EventHandler>) {
        self.states.push(boxed_state)
    }

    fn swap(&mut self, boxed_state: Box<EventHandler>) {
        self.states.pop();
        self.push(boxed_state);
    }
}

impl EventHandler for StateManager {
    fn update(&mut self, ctx: &mut Context, assets: &Assets, dt: Duration) -> GameResult<Transition> {
        let transition = match self.states.last_mut() {
            Some(state) => state.update(ctx, assets, dt),
            None => Ok(Transition::None),
        };

        self.handle_transition(transition?);

        Ok(Transition::None)
    }
    fn draw(&mut self, ctx: &mut Context, assets: &Assets) -> GameResult<()> {
        // draw everything in the stack
        use ggez::graphics;

        graphics::set_background_color(ctx, graphics::Color::new(0.0, 0.0, 0.0, 255.0));
        graphics::clear(ctx);

        for (_, state) in self.states.iter_mut().enumerate() {
            state.draw(ctx, assets)?;
        }

        graphics::present(ctx);
        Ok(())
        // match self.states.last_mut() {
        //     Some(state) => state.draw(ctx),
        //     None => Ok(()),
        // }
    }
    fn mouse_button_down_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_button_down_event(_button, _x, _y),
            None => (),
        }
    }

    fn mouse_button_up_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_button_up_event(_button, _x, _y),
            None => (),
        }
    }

    fn mouse_motion_event(&mut self,
                          _state: mouse::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_motion_event(_state, _x, _y, _xrel, _yrel),
            None => (),
        }

    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_wheel_event(_x, _y),
            None => (),
        }
    }

    fn key_down_event(&mut self, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
        match self.states.last_mut() {
            Some(state) => state.key_down_event(_keycode, _keymod, _repeat),
            None => (),
        }
    }

    fn key_up_event(&mut self, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
        match self.states.last_mut() {
            Some(state) => state.key_up_event(_keycode, _keymod, _repeat),
            None => (),
        }
    }

    fn controller_button_down_event(&mut self, _btn: Button, _instance_id: i32) {
        match self.states.last_mut() {
            Some(state) => state.controller_button_down_event(_btn, _instance_id),
            None => (),
        }
    }
    fn controller_button_up_event(&mut self, _btn: Button, _instance_id: i32) {
        match self.states.last_mut() {
            Some(state) => state.controller_button_up_event(_btn, _instance_id),
            None => (),
        }
    }
    fn controller_axis_event(&mut self, _axis: Axis, _value: i16, _instance_id: i32) {
        match self.states.last_mut() {
            Some(state) => state.controller_axis_event(_axis, _value, _instance_id),
            None => (),
        }
    }

    fn focus_event(&mut self, _gained: bool) {
        match self.states.last_mut() {
            Some(state) => state.focus_event(_gained),
            None => (),
        }
    }

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        match self.states.last_mut() {
            Some(state) => state.quit_event(),
            None => false,
        }
    }
}
<commit_msg>remove all states before push on Transiton::swap<commit_after>pub mod play_state;

use std::time::Duration;

use sdl2::mouse;

use ggez::{Context, GameResult};
use ggez::event::{Assets, EventHandler, Transition, Keycode, Mod, Button, Axis};
use states::play_state::PlayState;

/// A `StateManager` will manage requests to push, pop or swap states on the
/// state stack. It owns the `Assets` struct and dictates whether the game
/// continues to run or not.
pub struct StateManager {
    running: bool,
    states: Vec<Box<EventHandler>>,
}

impl StateManager {
    pub fn new(ctx: &mut Context, assets: &Assets) -> StateManager
    {
        let state = Box::new(PlayState::new(ctx, &assets).unwrap());

        StateManager {
            running: true,
            states: vec![state], // create empty state stack
        }
    }

    pub fn is_running(&self) -> bool {
        self.running
    }

    pub fn quit(&mut self) {
        // TODO: pop everything off the stack
        self.running = false
    }
}

impl StateManager {
    fn handle_transition(&mut self, transition: Transition) {
        match transition {
            Transition::None => (),
            Transition::Pop => self.pop(),
            Transition::Swap(state) => self.swap(state),
            Transition::Push(state) => self.push(state),
        }
    }

    fn pop(&mut self) {
        self.states.pop();

        if self.states.is_empty() {
            self.quit();
        }
    }

    fn push(&mut self, boxed_state: Box<EventHandler>) {
        self.states.push(boxed_state)
    }

    fn swap(&mut self, boxed_state: Box<EventHandler>) {
        self.states.clear();
        self.push(boxed_state);
    }
}

impl EventHandler for StateManager {
    fn update(&mut self, ctx: &mut Context, assets: &Assets, dt: Duration) -> GameResult<Transition> {
        let transition = match self.states.last_mut() {
            Some(state) => state.update(ctx, assets, dt),
            None => Ok(Transition::None),
        };

        self.handle_transition(transition?);

        Ok(Transition::None)
    }
    fn draw(&mut self, ctx: &mut Context, assets: &Assets) -> GameResult<()> {
        // draw everything in the stack
        use ggez::graphics;

        graphics::set_background_color(ctx, graphics::Color::new(0.0, 0.0, 0.0, 255.0));
        graphics::clear(ctx);

        for (_, state) in self.states.iter_mut().enumerate() {
            state.draw(ctx, assets)?;
        }

        graphics::present(ctx);
        Ok(())
        // match self.states.last_mut() {
        //     Some(state) => state.draw(ctx),
        //     None => Ok(()),
        // }
    }
    fn mouse_button_down_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_button_down_event(_button, _x, _y),
            None => (),
        }
    }

    fn mouse_button_up_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_button_up_event(_button, _x, _y),
            None => (),
        }
    }

    fn mouse_motion_event(&mut self,
                          _state: mouse::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_motion_event(_state, _x, _y, _xrel, _yrel),
            None => (),
        }

    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {
        match self.states.last_mut() {
            Some(state) => state.mouse_wheel_event(_x, _y),
            None => (),
        }
    }

    fn key_down_event(&mut self, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
        match self.states.last_mut() {
            Some(state) => state.key_down_event(_keycode, _keymod, _repeat),
            None => (),
        }
    }

    fn key_up_event(&mut self, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
        match self.states.last_mut() {
            Some(state) => state.key_up_event(_keycode, _keymod, _repeat),
            None => (),
        }
    }

    fn controller_button_down_event(&mut self, _btn: Button, _instance_id: i32) {
        match self.states.last_mut() {
            Some(state) => state.controller_button_down_event(_btn, _instance_id),
            None => (),
        }
    }
    fn controller_button_up_event(&mut self, _btn: Button, _instance_id: i32) {
        match self.states.last_mut() {
            Some(state) => state.controller_button_up_event(_btn, _instance_id),
            None => (),
        }
    }
    fn controller_axis_event(&mut self, _axis: Axis, _value: i16, _instance_id: i32) {
        match self.states.last_mut() {
            Some(state) => state.controller_axis_event(_axis, _value, _instance_id),
            None => (),
        }
    }

    fn focus_event(&mut self, _gained: bool) {
        match self.states.last_mut() {
            Some(state) => state.focus_event(_gained),
            None => (),
        }
    }

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        match self.states.last_mut() {
            Some(state) => state.quit_event(),
            None => false,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast;
use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,Ident};
use codemap::{Span, DUMMY_SP};
use diagnostic::SpanHandler;
use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident};
use parse::token::{ident_to_str};
use parse::lexer::TokenAndSpan;

use std::hashmap::HashMap;
use std::option;

///an unzipping of `token_tree`s
struct TtFrame {
    forest: @~[ast::token_tree],
    idx: uint,
    dotdotdoted: bool,
    sep: Option<Token>,
    up: Option<@mut TtFrame>,
}

pub struct TtReader {
    sp_diag: @mut SpanHandler,
    // the unzipped tree:
    stack: @mut TtFrame,
    /* for MBE-style macro transcription */
    interpolations: HashMap<Ident, @named_match>,
    repeat_idx: ~[uint],
    repeat_len: ~[uint],
    /* cached: */
    cur_tok: Token,
    cur_span: Span
}

/** This can do Macro-By-Example transcription. On the other hand, if
 *  `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and
 *  should) be none. */
pub fn new_tt_reader(sp_diag: @mut SpanHandler,
                     interp: Option<HashMap<Ident,@named_match>>,
                     src: ~[ast::token_tree])
                  -> @mut TtReader {
    let r = @mut TtReader {
        sp_diag: sp_diag,
        stack: @mut TtFrame {
            forest: @src,
            idx: 0u,
            dotdotdoted: false,
            sep: None,
            up: option::None
        },
        interpolations: match interp { /* just a convienience */
            None => HashMap::new(),
            Some(x) => x
        },
        repeat_idx: ~[],
        repeat_len: ~[],
        /* dummy values, never read: */
        cur_tok: EOF,
        cur_span: DUMMY_SP
    };
    tt_next_token(r); /* get cur_tok and cur_span set up */
    return r;
}

fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame {
    @mut TtFrame {
        forest: @(*f.forest).clone(),
        idx: f.idx,
        dotdotdoted: f.dotdotdoted,
        sep: f.sep.clone(),
        up: match f.up {
            Some(up_frame) => Some(dup_tt_frame(up_frame)),
            None => None
        }
    }
}

pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader {
    @mut TtReader {
        sp_diag: r.sp_diag,
        stack: dup_tt_frame(r.stack),
        repeat_idx: r.repeat_idx.clone(),
        repeat_len: r.repeat_len.clone(),
        cur_tok: r.cur_tok.clone(),
        cur_span: r.cur_span,
        interpolations: r.interpolations.clone(),
    }
}

fn lookup_cur_matched_by_matched(r: &mut TtReader,
                                      start: @named_match)
                                   -> @named_match {
    fn red(ad: @named_match, idx: &uint) -> @named_match {
        match *ad {
          matched_nonterminal(_) => {
            // end of the line; duplicate henceforth
            ad
          }
          matched_seq(ref ads, _) => ads[*idx]
        }
    }
    r.repeat_idx.iter().fold(start, red)
}

fn lookup_cur_matched(r: &mut TtReader, name: Ident) -> @named_match {
    match r.interpolations.find_copy(&name) {
        Some(s) => lookup_cur_matched_by_matched(r, s),
        None => {
            r.sp_diag.span_fatal(r.cur_span, format!("unknown macro variable `{}`",
                                                  ident_to_str(&name)));
        }
    }
}

#[deriving(Clone)]
enum lis {
    lis_unconstrained,
    lis_constraint(uint, Ident),
    lis_contradiction(~str),
}

fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
    fn lis_merge(lhs: lis, rhs: lis) -> lis {
        match lhs {
          lis_unconstrained => rhs.clone(),
          lis_contradiction(_) => lhs.clone(),
          lis_constraint(l_len, ref l_id) => match rhs {
            lis_unconstrained => lhs.clone(),
            lis_contradiction(_) => rhs.clone(),
            lis_constraint(r_len, _) if l_len == r_len => lhs.clone(),
            lis_constraint(r_len, ref r_id) => {
                let l_n = ident_to_str(l_id);
                let r_n = ident_to_str(r_id);
                lis_contradiction(format!("Inconsistent lockstep iteration: \
                                           '{}' has {} items, but '{}' has {}",
                                           l_n, l_len, r_n, r_len))
            }
          }
        }
    }
    match *t {
      tt_delim(ref tts) | tt_seq(_, ref tts, _, _) => {
        tts.iter().fold(lis_unconstrained, |lis, tt| {
            let lis2 = lockstep_iter_size(tt, r);
            lis_merge(lis, lis2)
        })
      }
      tt_tok(..) => lis_unconstrained,
      tt_nonterminal(_, name) => match *lookup_cur_matched(r, name) {
        matched_nonterminal(_) => lis_unconstrained,
        matched_seq(ref ads, _) => lis_constraint(ads.len(), name)
      }
    }
}

// return the next token from the TtReader.
// EFFECT: advances the reader's token field
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
    // XXX(pcwalton): Bad copy?
    let ret_val = TokenAndSpan {
        tok: r.cur_tok.clone(),
        sp: r.cur_span,
    };
    loop {
        {
            let stack = &mut *r.stack;
            if stack.idx < stack.forest.len() {
                break;
            }
        }

        /* done with this set; pop or repeat? */
        if ! r.stack.dotdotdoted
            || { *r.repeat_idx.last() == *r.repeat_len.last() - 1 } {

            match r.stack.up {
              None => {
                r.cur_tok = EOF;
                return ret_val;
              }
              Some(tt_f) => {
                if r.stack.dotdotdoted {
                    r.repeat_idx.pop();
                    r.repeat_len.pop();
                }

                r.stack = tt_f;
                r.stack.idx += 1u;
              }
            }

        } else { /* repeat */
            r.stack.idx = 0u;
            r.repeat_idx[r.repeat_idx.len() - 1u] += 1u;
            match r.stack.sep.clone() {
              Some(tk) => {
                r.cur_tok = tk; /* repeat same span, I guess */
                return ret_val;
              }
              None => ()
            }
        }
    }
    loop { /* because it's easiest, this handles `tt_delim` not starting
    with a `tt_tok`, even though it won't happen */
        // XXX(pcwalton): Bad copy.
        match r.stack.forest[r.stack.idx].clone() {
          tt_delim(tts) => {
            r.stack = @mut TtFrame {
                forest: tts,
                idx: 0u,
                dotdotdoted: false,
                sep: None,
                up: option::Some(r.stack)
            };
            // if this could be 0-length, we'd need to potentially recur here
          }
          tt_tok(sp, tok) => {
            r.cur_span = sp;
            r.cur_tok = tok;
            r.stack.idx += 1u;
            return ret_val;
          }
          tt_seq(sp, tts, sep, zerok) => {
            // XXX(pcwalton): Bad copy.
            let t = tt_seq(sp, tts, sep.clone(), zerok);
            match lockstep_iter_size(&t, r) {
              lis_unconstrained => {
                r.sp_diag.span_fatal(
                    sp, /* blame macro writer */
                      "attempted to repeat an expression \
                       containing no syntax \
                       variables matched as repeating at this depth");
                  }
                  lis_contradiction(ref msg) => {
                      /* FIXME #2887 blame macro invoker instead*/
                      r.sp_diag.span_fatal(sp, (*msg));
                  }
                  lis_constraint(len, _) => {
                    if len == 0 {
                      if !zerok {
                        r.sp_diag.span_fatal(sp, /* FIXME #2887 blame invoker
                        */
                                             "this must repeat at least \
                                              once");
                          }

                    r.stack.idx += 1u;
                    return tt_next_token(r);
                } else {
                    r.repeat_len.push(len);
                    r.repeat_idx.push(0u);
                    r.stack = @mut TtFrame {
                        forest: tts,
                        idx: 0u,
                        dotdotdoted: true,
                        sep: sep,
                        up: Some(r.stack)
                    };
                }
              }
            }
          }
          // FIXME #2887: think about span stuff here
          tt_nonterminal(sp, ident) => {
            match *lookup_cur_matched(r, ident) {
              /* sidestep the interpolation tricks for ident because
              (a) idents can be in lots of places, so it'd be a pain
              (b) we actually can, since it's a token. */
              matched_nonterminal(nt_ident(~sn,b)) => {
                r.cur_span = sp; r.cur_tok = IDENT(sn,b);
                r.stack.idx += 1u;
                return ret_val;
              }
              matched_nonterminal(ref other_whole_nt) => {
                // XXX(pcwalton): Bad copy.
                r.cur_span = sp;
                r.cur_tok = INTERPOLATED((*other_whole_nt).clone());
                r.stack.idx += 1u;
                return ret_val;
              }
              matched_seq(..) => {
                r.sp_diag.span_fatal(
                    r.cur_span, /* blame the macro writer */
                    format!("variable '{}' is still repeating at this depth",
                         ident_to_str(&ident)));
              }
            }
          }
        }
    }

}
<commit_msg>libsyntax: De-`@mut` `TtReader::interpolations`<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast;
use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,Ident};
use codemap::{Span, DUMMY_SP};
use diagnostic::SpanHandler;
use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident};
use parse::token::{ident_to_str};
use parse::lexer::TokenAndSpan;

use std::cell::RefCell;
use std::hashmap::HashMap;
use std::option;

///an unzipping of `token_tree`s
struct TtFrame {
    forest: @~[ast::token_tree],
    idx: uint,
    dotdotdoted: bool,
    sep: Option<Token>,
    up: Option<@mut TtFrame>,
}

pub struct TtReader {
    sp_diag: @mut SpanHandler,
    // the unzipped tree:
    stack: @mut TtFrame,
    /* for MBE-style macro transcription */
    priv interpolations: RefCell<HashMap<Ident, @named_match>>,
    repeat_idx: ~[uint],
    repeat_len: ~[uint],
    /* cached: */
    cur_tok: Token,
    cur_span: Span
}

/** This can do Macro-By-Example transcription. On the other hand, if
 *  `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and
 *  should) be none. */
pub fn new_tt_reader(sp_diag: @mut SpanHandler,
                     interp: Option<HashMap<Ident,@named_match>>,
                     src: ~[ast::token_tree])
                  -> @mut TtReader {
    let r = @mut TtReader {
        sp_diag: sp_diag,
        stack: @mut TtFrame {
            forest: @src,
            idx: 0u,
            dotdotdoted: false,
            sep: None,
            up: option::None
        },
        interpolations: match interp { /* just a convienience */
            None => RefCell::new(HashMap::new()),
            Some(x) => RefCell::new(x),
        },
        repeat_idx: ~[],
        repeat_len: ~[],
        /* dummy values, never read: */
        cur_tok: EOF,
        cur_span: DUMMY_SP
    };
    tt_next_token(r); /* get cur_tok and cur_span set up */
    return r;
}

fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame {
    @mut TtFrame {
        forest: @(*f.forest).clone(),
        idx: f.idx,
        dotdotdoted: f.dotdotdoted,
        sep: f.sep.clone(),
        up: match f.up {
            Some(up_frame) => Some(dup_tt_frame(up_frame)),
            None => None
        }
    }
}

pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader {
    @mut TtReader {
        sp_diag: r.sp_diag,
        stack: dup_tt_frame(r.stack),
        repeat_idx: r.repeat_idx.clone(),
        repeat_len: r.repeat_len.clone(),
        cur_tok: r.cur_tok.clone(),
        cur_span: r.cur_span,
        interpolations: r.interpolations.clone(),
    }
}

fn lookup_cur_matched_by_matched(r: &mut TtReader,
                                      start: @named_match)
                                   -> @named_match {
    fn red(ad: @named_match, idx: &uint) -> @named_match {
        match *ad {
          matched_nonterminal(_) => {
            // end of the line; duplicate henceforth
            ad
          }
          matched_seq(ref ads, _) => ads[*idx]
        }
    }
    r.repeat_idx.iter().fold(start, red)
}

fn lookup_cur_matched(r: &mut TtReader, name: Ident) -> @named_match {
    let matched_opt = {
        let interpolations = r.interpolations.borrow();
        interpolations.get().find_copy(&name)
    };
    match matched_opt {
        Some(s) => lookup_cur_matched_by_matched(r, s),
        None => {
            r.sp_diag.span_fatal(r.cur_span, format!("unknown macro variable `{}`",
                                                  ident_to_str(&name)));
        }
    }
}

#[deriving(Clone)]
enum lis {
    lis_unconstrained,
    lis_constraint(uint, Ident),
    lis_contradiction(~str),
}

fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
    fn lis_merge(lhs: lis, rhs: lis) -> lis {
        match lhs {
          lis_unconstrained => rhs.clone(),
          lis_contradiction(_) => lhs.clone(),
          lis_constraint(l_len, ref l_id) => match rhs {
            lis_unconstrained => lhs.clone(),
            lis_contradiction(_) => rhs.clone(),
            lis_constraint(r_len, _) if l_len == r_len => lhs.clone(),
            lis_constraint(r_len, ref r_id) => {
                let l_n = ident_to_str(l_id);
                let r_n = ident_to_str(r_id);
                lis_contradiction(format!("Inconsistent lockstep iteration: \
                                           '{}' has {} items, but '{}' has {}",
                                           l_n, l_len, r_n, r_len))
            }
          }
        }
    }
    match *t {
      tt_delim(ref tts) | tt_seq(_, ref tts, _, _) => {
        tts.iter().fold(lis_unconstrained, |lis, tt| {
            let lis2 = lockstep_iter_size(tt, r);
            lis_merge(lis, lis2)
        })
      }
      tt_tok(..) => lis_unconstrained,
      tt_nonterminal(_, name) => match *lookup_cur_matched(r, name) {
        matched_nonterminal(_) => lis_unconstrained,
        matched_seq(ref ads, _) => lis_constraint(ads.len(), name)
      }
    }
}

// return the next token from the TtReader.
// EFFECT: advances the reader's token field
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
    // XXX(pcwalton): Bad copy?
    let ret_val = TokenAndSpan {
        tok: r.cur_tok.clone(),
        sp: r.cur_span,
    };
    loop {
        {
            let stack = &mut *r.stack;
            if stack.idx < stack.forest.len() {
                break;
            }
        }

        /* done with this set; pop or repeat? */
        if ! r.stack.dotdotdoted
            || { *r.repeat_idx.last() == *r.repeat_len.last() - 1 } {

            match r.stack.up {
              None => {
                r.cur_tok = EOF;
                return ret_val;
              }
              Some(tt_f) => {
                if r.stack.dotdotdoted {
                    r.repeat_idx.pop();
                    r.repeat_len.pop();
                }

                r.stack = tt_f;
                r.stack.idx += 1u;
              }
            }

        } else { /* repeat */
            r.stack.idx = 0u;
            r.repeat_idx[r.repeat_idx.len() - 1u] += 1u;
            match r.stack.sep.clone() {
              Some(tk) => {
                r.cur_tok = tk; /* repeat same span, I guess */
                return ret_val;
              }
              None => ()
            }
        }
    }
    loop { /* because it's easiest, this handles `tt_delim` not starting
    with a `tt_tok`, even though it won't happen */
        // XXX(pcwalton): Bad copy.
        match r.stack.forest[r.stack.idx].clone() {
          tt_delim(tts) => {
            r.stack = @mut TtFrame {
                forest: tts,
                idx: 0u,
                dotdotdoted: false,
                sep: None,
                up: option::Some(r.stack)
            };
            // if this could be 0-length, we'd need to potentially recur here
          }
          tt_tok(sp, tok) => {
            r.cur_span = sp;
            r.cur_tok = tok;
            r.stack.idx += 1u;
            return ret_val;
          }
          tt_seq(sp, tts, sep, zerok) => {
            // XXX(pcwalton): Bad copy.
            let t = tt_seq(sp, tts, sep.clone(), zerok);
            match lockstep_iter_size(&t, r) {
              lis_unconstrained => {
                r.sp_diag.span_fatal(
                    sp, /* blame macro writer */
                      "attempted to repeat an expression \
                       containing no syntax \
                       variables matched as repeating at this depth");
                  }
                  lis_contradiction(ref msg) => {
                      /* FIXME #2887 blame macro invoker instead*/
                      r.sp_diag.span_fatal(sp, (*msg));
                  }
                  lis_constraint(len, _) => {
                    if len == 0 {
                      if !zerok {
                        r.sp_diag.span_fatal(sp, /* FIXME #2887 blame invoker
                        */
                                             "this must repeat at least \
                                              once");
                          }

                    r.stack.idx += 1u;
                    return tt_next_token(r);
                } else {
                    r.repeat_len.push(len);
                    r.repeat_idx.push(0u);
                    r.stack = @mut TtFrame {
                        forest: tts,
                        idx: 0u,
                        dotdotdoted: true,
                        sep: sep,
                        up: Some(r.stack)
                    };
                }
              }
            }
          }
          // FIXME #2887: think about span stuff here
          tt_nonterminal(sp, ident) => {
            match *lookup_cur_matched(r, ident) {
              /* sidestep the interpolation tricks for ident because
              (a) idents can be in lots of places, so it'd be a pain
              (b) we actually can, since it's a token. */
              matched_nonterminal(nt_ident(~sn,b)) => {
                r.cur_span = sp; r.cur_tok = IDENT(sn,b);
                r.stack.idx += 1u;
                return ret_val;
              }
              matched_nonterminal(ref other_whole_nt) => {
                // XXX(pcwalton): Bad copy.
                r.cur_span = sp;
                r.cur_tok = INTERPOLATED((*other_whole_nt).clone());
                r.stack.idx += 1u;
                return ret_val;
              }
              matched_seq(..) => {
                r.sp_diag.span_fatal(
                    r.cur_span, /* blame the macro writer */
                    format!("variable '{}' is still repeating at this depth",
                         ident_to_str(&ident)));
              }
            }
          }
        }
    }

}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp;
use symbol::Symbol;

/// To find the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
    // cases which don't require further computation
    if a.is_empty() {
        return b.chars().count();
    } else if b.is_empty() {
        return a.chars().count();
    }

    let mut dcol: Vec<_> = (0..b.len() + 1).collect();
    let mut t_last = 0;

    for (i, sc) in a.chars().enumerate() {
        let mut current = i;
        dcol[0] = current + 1;

        for (j, tc) in b.chars().enumerate() {
            let next = dcol[j + 1];
            if sc == tc {
                dcol[j + 1] = current;
            } else {
                dcol[j + 1] = cmp::min(current, next);
                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
            }
            current = next;
            t_last = j;
        }
    } dcol[t_last + 1]
}

/// To find the best match for a given string from an iterator of names
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word.
/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
/// a lower(upper)case letters mismatch.
pub fn find_best_match_for_name<'a, T>(iter_names: T,
                                       lookup: &str,
                                       dist: Option<usize>) -> Option<Symbol>
    where T: Iterator<Item = &'a Symbol> {
    let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);

    let (case_insensitive_match, levenstein_match) = iter_names
    .filter_map(|&name| {
        let dist = lev_distance(lookup, &name.as_str());
        if dist <= max_dist {
            Some((name, dist))
        } else {
            None
        }
    })
    // Here we are collecting the next structure:
    // (case_insensitive_match, (levenstein_match, levenstein_distance))
    .fold((None, None), |result, (candidate, dist)| {
        (
            if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
                Some(candidate)
            } else {
                result.0
            },
            match result.1 {
                None => Some((candidate, dist)),
                Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) })
            }
        )
    });

    if let Some(candidate) = case_insensitive_match {
        Some(candidate) // exact case insensitive match has a higher priority
    } else {
        if let Some((candidate, _)) = levenstein_match { Some(candidate) } else { None }
    }
}

#[test]
fn test_lev_distance() {
    use std::char::{from_u32, MAX};
    // Test bytelength agnosticity
    for c in (0..MAX as u32)
             .filter_map(|i| from_u32(i))
             .map(|i| i.to_string()) {
        assert_eq!(lev_distance(&c[..], &c[..]), 0);
    }

    let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
    let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
    let c = "Mary häd ä little lämb\n\nLittle lämb\n";
    assert_eq!(lev_distance(a, b), 1);
    assert_eq!(lev_distance(b, a), 1);
    assert_eq!(lev_distance(a, c), 2);
    assert_eq!(lev_distance(c, a), 2);
    assert_eq!(lev_distance(b, c), 1);
    assert_eq!(lev_distance(c, b), 1);
}
<commit_msg>Add some unit tests for find_best_match_for_name<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp;
use symbol::Symbol;

/// Find the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
    // cases which don't require further computation
    if a.is_empty() {
        return b.chars().count();
    } else if b.is_empty() {
        return a.chars().count();
    }

    let mut dcol: Vec<_> = (0..b.len() + 1).collect();
    let mut t_last = 0;

    for (i, sc) in a.chars().enumerate() {
        let mut current = i;
        dcol[0] = current + 1;

        for (j, tc) in b.chars().enumerate() {
            let next = dcol[j + 1];
            if sc == tc {
                dcol[j + 1] = current;
            } else {
                dcol[j + 1] = cmp::min(current, next);
                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
            }
            current = next;
            t_last = j;
        }
    } dcol[t_last + 1]
}

/// Find the best match for a given word in the given iterator
///
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word.
///
/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
/// a lower(upper)case letters mismatch.
pub fn find_best_match_for_name<'a, T>(iter_names: T,
                                       lookup: &str,
                                       dist: Option<usize>) -> Option<Symbol>
    where T: Iterator<Item = &'a Symbol> {
    let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);

    let (case_insensitive_match, levenstein_match) = iter_names
    .filter_map(|&name| {
        let dist = lev_distance(lookup, &name.as_str());
        if dist <= max_dist {
            Some((name, dist))
        } else {
            None
        }
    })
    // Here we are collecting the next structure:
    // (case_insensitive_match, (levenstein_match, levenstein_distance))
    .fold((None, None), |result, (candidate, dist)| {
        (
            if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
                Some(candidate)
            } else {
                result.0
            },
            match result.1 {
                None => Some((candidate, dist)),
                Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) })
            }
        )
    });

    if let Some(candidate) = case_insensitive_match {
        Some(candidate) // exact case insensitive match has a higher priority
    } else {
        if let Some((candidate, _)) = levenstein_match { Some(candidate) } else { None }
    }
}

#[test]
fn test_lev_distance() {
    use std::char::{from_u32, MAX};
    // Test bytelength agnosticity
    for c in (0..MAX as u32)
             .filter_map(|i| from_u32(i))
             .map(|i| i.to_string()) {
        assert_eq!(lev_distance(&c[..], &c[..]), 0);
    }

    let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
    let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
    let c = "Mary häd ä little lämb\n\nLittle lämb\n";
    assert_eq!(lev_distance(a, b), 1);
    assert_eq!(lev_distance(b, a), 1);
    assert_eq!(lev_distance(a, c), 2);
    assert_eq!(lev_distance(c, a), 2);
    assert_eq!(lev_distance(b, c), 1);
    assert_eq!(lev_distance(c, b), 1);
}

#[test]
fn test_find_best_match_for_name() {
    use with_globals;
    with_globals(|| {
        let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
        assert_eq!(
            find_best_match_for_name(input.iter(), "aaaa", None),
            Some(Symbol::intern("aaab"))
        );

        assert_eq!(
            find_best_match_for_name(input.iter(), "1111111111", None),
            None
        );

        let input = vec![Symbol::intern("aAAA")];
        assert_eq!(
            find_best_match_for_name(input.iter(), "AAAA", None),
            Some(Symbol::intern("aAAA"))
        );

        let input = vec![Symbol::intern("AAAA")];
        // Returns None because `lev_distance > max_dist / 3`
        assert_eq!(
            find_best_match_for_name(input.iter(), "aaaa", None),
            None
        );

        let input = vec![Symbol::intern("AAAA")];
        assert_eq!(
            find_best_match_for_name(input.iter(), "aaaa", Some(4)),
            Some(Symbol::intern("AAAA"))
        );
    })
}
<|endoftext|>


<commit_before><commit_msg>libxen: Add event dispatcher implementation<commit_after>//! Main utility to dispatch and manage Xen events

use shared_info;

use core::ptr::null_mut;

use defs::EvtchnPort;
use defs::ULONG_SIZE;

use intrinsics::{atomic_set_bit, atomic_clear_bit, atomic_xchg, first_bit, wmb};

const NUMBER_OF_EVENTS: usize = 1024;

pub type EventHandler = fn(port: EvtchnPort, data: *mut u8) -> ();

#[derive(Clone, Copy)]
struct EventData {
    pub handler: EventHandler,
    pub data: *mut u8,
}

impl EventData {
    pub const fn new(handler: EventHandler, data: *mut u8) -> Self {
        EventData {
            handler: handler,
            data: data,
        }
    }
}

pub struct Dispatcher {
    handlers: [EventData; NUMBER_OF_EVENTS],
}

impl Dispatcher {
    pub fn default_handler(port: EvtchnPort, _data: *mut u8) {
        panic!("Unhandled port ({})", port);
    }

    pub const fn new() -> Self {
        Dispatcher {
            handlers: [EventData::new(Dispatcher::default_handler, null_mut());
                       NUMBER_OF_EVENTS],
        }
    }

    #[inline(always)]
    pub unsafe fn serve_event(&self) {
        let cpu = &mut shared_info.vcpu_info[0];

        cpu.evtchn_upcall_pending = 0;

        wmb();

        let mut pending_sel = atomic_xchg(&mut cpu.evtchn_pending_sel, 0);

        while pending_sel != 0 {
            let next_event_offset = first_bit(pending_sel);

            pending_sel &= !(1 << next_event_offset);

            let mut event = shared_info.evtchn_pending[next_event_offset] &
                            !shared_info.evtchn_mask[next_event_offset];

            while event != 0 {
                let event_offset = first_bit(event);
                let port = (next_event_offset * ULONG_SIZE * 8) + event_offset;

                event &= !(1 << event_offset);

                if port >= NUMBER_OF_EVENTS {
                    panic!("Event occurred for out of bound port ({})", port);
                }

                (self.handlers[port].handler)(port as EvtchnPort,
                                              self.handlers[port].data);

                atomic_clear_bit(port, &mut shared_info.evtchn_pending[0]);
            }
        }
    }

    pub fn bind_port(&mut self, port: EvtchnPort, handler: EventHandler,
                     data: *mut u8) {
        if self.handlers[port as usize].handler !=
            Dispatcher::default_handler {
            panic!("Trying to override non default handler for port {}", port);
        }

        self.handlers[port as usize] = EventData::new(handler, data);
    }

    pub fn mask_all(&self) {
        let mut i: EvtchnPort = 0;

        while (i as usize) < NUMBER_OF_EVENTS {
            self.mask_event(i);

            i += 1;
        }
    }

    pub fn mask_event(&self, port: EvtchnPort) {
        unsafe {
            if port < (NUMBER_OF_EVENTS as EvtchnPort) {
                atomic_set_bit(port as usize, &mut shared_info.evtchn_mask[0]);
            }
        }
    }

    pub fn unmask_event(&self, port: EvtchnPort) {
        unsafe {
            if port < (NUMBER_OF_EVENTS as EvtchnPort) {
                atomic_clear_bit(port as usize,
                                 &mut shared_info.evtchn_mask[0]);
            }
        }
    }
}
<|endoftext|>