<commit_before>//! Contains traits responsible for the actual construction of SQL statements
//!
//! The types in this module are part of Diesel's public API, but are generally
//! only useful for implementing Diesel plugins. Applications should generally
//! not need to care about the types inside of this module.

#[macro_use]
mod query_id;
#[macro_use]
mod clause_macro;

mod ast_pass;
pub mod bind_collector;
pub mod combination_clause;
mod debug_query;
mod delete_statement;
mod distinct_clause;
#[doc(hidden)]
pub mod functions;
mod group_by_clause;
mod insert_statement;
pub(crate) mod limit_clause;
pub(crate) mod limit_offset_clause;
pub(crate) mod locking_clause;
#[doc(hidden)]
pub mod nodes;
pub(crate) mod offset_clause;
mod order_clause;
mod returning_clause;
pub(crate) mod select_clause;
mod select_statement;
mod sql_query;
mod update_statement;
pub(crate) mod upsert;
mod where_clause;

pub use self::ast_pass::AstPass;
pub use self::bind_collector::BindCollector;
pub use self::debug_query::DebugQuery;
pub use self::delete_statement::{BoxedDeleteStatement, DeleteStatement};
#[doc(inline)]
pub use self::insert_statement::{
    IncompleteInsertStatement, InsertStatement, UndecoratedInsertRecord, ValuesClause,
};
pub use self::query_id::QueryId;
#[doc(inline)]
pub use self::select_clause::{
    IntoBoxedSelectClause, SelectClauseExpression, SelectClauseQueryFragment,
};
#[doc(hidden)]
pub use self::select_statement::{BoxedSelectStatement, SelectStatement};
pub use self::sql_query::{BoxedSqlQuery, SqlQuery};
#[doc(inline)]
pub use self::update_statement::{
    AsChangeset, BoxedUpdateStatement, IntoUpdateTarget, UpdateStatement, UpdateTarget,
};
pub use self::upsert::on_conflict_target_decorations::DecoratableTarget;

pub use self::limit_clause::{LimitClause, NoLimitClause};
pub use self::limit_offset_clause::{BoxedLimitOffsetClause, LimitOffsetClause};
pub use self::offset_clause::{NoOffsetClause, OffsetClause};

pub(crate) use self::insert_statement::ColumnList;

use std::error::Error;

use crate::backend::Backend;
use crate::result::QueryResult;

#[doc(hidden)]
pub type Binds = Vec<Option<Vec<u8>>>;
/// A specialized Result type used with the query builder.
pub type BuildQueryResult = Result<(), Box<dyn Error + Send + Sync>>;

/// Constructs a SQL query from a Diesel AST.
///
/// The only reason you should ever need to interact with this trait is if you
/// are extending Diesel with support for a new backend. Plugins which extend
/// the query builder with new capabilities will interact with [`AstPass`]
/// instead.
///
/// [`AstPass`]: struct.AstPass.html
pub trait QueryBuilder<DB: Backend> {
    /// Add `sql` to the end of the query being constructed.
    fn push_sql(&mut self, sql: &str);

    /// Quote `identifier`, and add it to the end of the query being
    /// constructed.
    fn push_identifier(&mut self, identifier: &str) -> QueryResult<()>;

    /// Add a placeholder for a bind parameter to the end of the query being
    /// constructed.
    fn push_bind_param(&mut self);

    /// Increases the internal counter for bind parameters without adding the
    /// bind parameter itself to the query
    fn push_bind_param_value_only(&mut self) {}

    /// Returns the constructed SQL query.
    fn finish(self) -> String;
}

/// A complete SQL query with a return type.
///
/// This can be a select statement, or a command such as `update` or `insert`
/// with a `RETURNING` clause. Unlike [`Expression`], types implementing this
/// trait are guaranteed to be executable on their own.
///
/// A type which doesn't implement this trait may still represent a complete SQL
/// query. For example, an `INSERT` statement without a `RETURNING` clause will
/// not implement this trait, but can still be executed.
///
/// [`Expression`]: ../expression/trait.Expression.html
pub trait Query {
    /// The SQL type that this query represents.
    ///
    /// This is the SQL type of the `SELECT` clause for select statements, and
    /// the SQL type of the `RETURNING` clause for insert, update, or delete
    /// statements.
    type SqlType;
}

impl<'a, T: Query> Query for &'a T {
    type SqlType = T::SqlType;
}

/// Indicates that a type is a `SELECT` statement.
///
/// This trait differs from `Query` in two ways:
/// - It is implemented only for select statements, rather than all queries
///   which return a value.
/// - It has looser constraints. A type implementing `SelectQuery` is known to
///   be potentially valid if used as a subselect, but it is not necessarily
///   able to be executed.
pub trait SelectQuery {
    /// The SQL type of the `SELECT` clause
    type SqlType;
}

/// An untyped fragment of SQL.
///
/// This may be a complete SQL command (such as an update statement without a
/// `RETURNING` clause), or a subsection (such as our internal types used to
/// represent a `WHERE` clause). Implementations of [`ExecuteDsl`] and
/// [`LoadQuery`] will generally require that this trait be implemented.
///
/// [`ExecuteDsl`]: ../query_dsl/methods/trait.ExecuteDsl.html
/// [`LoadQuery`]: ../query_dsl/methods/trait.LoadQuery.html
pub trait QueryFragment<DB: Backend> {
    /// Walk over this `QueryFragment` for all passes.
    ///
    /// This method is where the actual behavior of an AST node is implemented.
    /// This method will contain the behavior required for all possible AST
    /// passes. See [`AstPass`] for more details.
    ///
    /// [`AstPass`]: struct.AstPass.html
    fn walk_ast(&self, pass: AstPass<DB>) -> QueryResult<()>;

    /// Converts this `QueryFragment` to its SQL representation.
    ///
    /// This method should only be called by implementations of `Connection`.
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> QueryResult<()> {
        self.walk_ast(AstPass::to_sql(out))
    }

    /// Serializes all bind parameters in this query.
    ///
    /// A bind parameter is a value which is sent separately from the query
    /// itself. It is represented in SQL with a placeholder such as `?` or `$1`.
    ///
    /// This method should only be called by implementations of `Connection`.
    fn collect_binds(
        &self,
        out: &mut DB::BindCollector,
        metadata_lookup: &DB::MetadataLookup,
    ) -> QueryResult<()> {
        self.walk_ast(AstPass::collect_binds(out, metadata_lookup))
    }

    /// Is this query safe to store in the prepared statement cache?
    ///
    /// In order to keep our prepared statement cache at a reasonable size, we
    /// avoid caching any queries which represent a potentially unbounded number
    /// of SQL queries. Generally this will only return `true` for queries for
    /// which `to_sql` will always construct exactly identical SQL.
    ///
    /// Some examples of where this method will return `false` are:
    ///
    /// - `SqlLiteral` (We don't know if the SQL was constructed dynamically, so
    ///   we must assume that it was)
    /// - `In` and `NotIn` (Each value requires a separate bind param
    ///   placeholder)
    ///
    /// This method should only be called by implementations of `Connection`.
    fn is_safe_to_cache_prepared(&self) -> QueryResult<bool> {
        let mut result = true;
        self.walk_ast(AstPass::is_safe_to_cache_prepared(&mut result))?;
        Ok(result)
    }

    #[doc(hidden)]
    /// Does walking this AST have any effect?
    fn is_noop(&self) -> QueryResult<bool> {
        let mut result = true;
        self.walk_ast(AstPass::is_noop(&mut result))?;
        Ok(result)
    }
}

impl<T: ?Sized, DB> QueryFragment<DB> for Box<T>
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, pass: AstPass<DB>) -> QueryResult<()> {
        QueryFragment::walk_ast(&**self, pass)
    }
}

impl<'a, T: ?Sized, DB> QueryFragment<DB> for &'a T
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, pass: AstPass<DB>) -> QueryResult<()> {
        QueryFragment::walk_ast(&**self, pass)
    }
}

impl<DB: Backend> QueryFragment<DB> for () {
    fn walk_ast(&self, _: AstPass<DB>) -> QueryResult<()> {
        Ok(())
    }
}

impl<T, DB> QueryFragment<DB> for Option<T>
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, out: AstPass<DB>) -> QueryResult<()> {
        match *self {
            Some(ref c) => c.walk_ast(out),
            None => Ok(()),
        }
    }
}

/// A trait used to construct type erased boxed variant of the current query node
///
/// Mainly useful for implementing third party backends
pub trait IntoBoxedClause<'a, DB> {
    /// Resulting type
    type BoxedClause;

    /// Convert the given query node in it's boxed representation
    fn into_boxed(self) -> Self::BoxedClause;
}

/// Types that can be converted into a complete, typed SQL query.
///
/// This is used internally to automatically add the right select clause when
/// none is specified, or to automatically add `RETURNING *` in certain contexts.
///
/// A type which implements this trait is guaranteed to be valid for execution.
pub trait AsQuery {
    /// The SQL type of `Self::Query`
    type SqlType;

    /// What kind of query does this type represent?
    type Query: Query<SqlType = Self::SqlType>;

    /// Converts a type which semantically represents a SQL query into the
    /// actual query being executed. See the trait level docs for more.
    fn as_query(self) -> Self::Query;
}

impl<T: Query> AsQuery for T {
    type SqlType = <Self as Query>::SqlType;
    type Query = Self;

    fn as_query(self) -> Self::Query {
        self
    }
}

/// Takes a query `QueryFragment` expression as an argument and returns a type
/// that implements `fmt::Display` and `fmt::Debug` to show the query.
///
/// The `Display` implementation will show the exact query being sent to the
/// server, with a comment showing the values of the bind parameters. The
/// `Debug` implementation will include the same information in a more
/// structured form, and respects pretty printing.
///
/// # Example
///
/// ### Returning SQL from a count statement:
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// #
/// # use diesel::*;
/// # use schema::*;
/// #
/// # fn main() {
/// #   use schema::users::dsl::*;
/// let sql = debug_query::<DB, _>(&users.count()).to_string();
/// # if cfg!(feature = "postgres") {
/// #     assert_eq!(sql, r#"SELECT COUNT(*) FROM "users" -- binds: []"#);
/// # } else {
/// assert_eq!(sql, "SELECT COUNT(*) FROM `users` -- binds: []");
/// # }
///
/// let query = users.find(1);
/// let debug = debug_query::<DB, _>(&query);
/// # if cfg!(feature = "postgres") {
/// #     assert_eq!(debug.to_string(), "SELECT \"users\".\"id\", \"users\".\"name\" \
/// #         FROM \"users\" WHERE (\"users\".\"id\" = $1) -- binds: [1]");
/// # } else {
/// assert_eq!(debug.to_string(), "SELECT `users`.`id`, `users`.`name` FROM `users` \
///     WHERE (`users`.`id` = ?) -- binds: [1]");
/// # }
///
/// let debug = format!("{:?}", debug);
/// # if !cfg!(feature = "postgres") { // Escaping that string is a pain
/// let expected = "Query { \
///     sql: \"SELECT `users`.`id`, `users`.`name` FROM `users` WHERE \
///         (`users`.`id` = ?)\", \
///     binds: [1] \
/// }";
/// assert_eq!(debug, expected);
/// # }
/// # }
/// ```
pub fn debug_query<DB, T>(query: &T) -> DebugQuery<T, DB> {
    DebugQuery::new(query)
}
<commit_msg>Restrict combination_clause visibility<commit_after>//! Contains traits responsible for the actual construction of SQL statements
//!
//! The types in this module are part of Diesel's public API, but are generally
//! only useful for implementing Diesel plugins. Applications should generally
//! not need to care about the types inside of this module.

#[macro_use]
mod query_id;
#[macro_use]
mod clause_macro;

mod ast_pass;
pub mod bind_collector;
pub(crate) mod combination_clause;
mod debug_query;
mod delete_statement;
mod distinct_clause;
#[doc(hidden)]
pub mod functions;
mod group_by_clause;
mod insert_statement;
pub(crate) mod limit_clause;
pub(crate) mod limit_offset_clause;
pub(crate) mod locking_clause;
#[doc(hidden)]
pub mod nodes;
pub(crate) mod offset_clause;
mod order_clause;
mod returning_clause;
pub(crate) mod select_clause;
mod select_statement;
mod sql_query;
mod update_statement;
pub(crate) mod upsert;
mod where_clause;

pub use self::ast_pass::AstPass;
pub use self::bind_collector::BindCollector;
pub use self::debug_query::DebugQuery;
pub use self::delete_statement::{BoxedDeleteStatement, DeleteStatement};
#[doc(inline)]
pub use self::insert_statement::{
    IncompleteInsertStatement, InsertStatement, UndecoratedInsertRecord, ValuesClause,
};
pub use self::query_id::QueryId;
#[doc(inline)]
pub use self::select_clause::{
    IntoBoxedSelectClause, SelectClauseExpression, SelectClauseQueryFragment,
};
#[doc(hidden)]
pub use self::select_statement::{BoxedSelectStatement, SelectStatement};
pub use self::sql_query::{BoxedSqlQuery, SqlQuery};
#[doc(inline)]
pub use self::update_statement::{
    AsChangeset, BoxedUpdateStatement, IntoUpdateTarget, UpdateStatement, UpdateTarget,
};
pub use self::upsert::on_conflict_target_decorations::DecoratableTarget;

pub use self::limit_clause::{LimitClause, NoLimitClause};
pub use self::limit_offset_clause::{BoxedLimitOffsetClause, LimitOffsetClause};
pub use self::offset_clause::{NoOffsetClause, OffsetClause};

pub(crate) use self::insert_statement::ColumnList;

use std::error::Error;

use crate::backend::Backend;
use crate::result::QueryResult;

#[doc(hidden)]
pub type Binds = Vec<Option<Vec<u8>>>;
/// A specialized Result type used with the query builder.
pub type BuildQueryResult = Result<(), Box<dyn Error + Send + Sync>>;

/// Constructs a SQL query from a Diesel AST.
///
/// The only reason you should ever need to interact with this trait is if you
/// are extending Diesel with support for a new backend. Plugins which extend
/// the query builder with new capabilities will interact with [`AstPass`]
/// instead.
///
/// [`AstPass`]: struct.AstPass.html
pub trait QueryBuilder<DB: Backend> {
    /// Add `sql` to the end of the query being constructed.
    fn push_sql(&mut self, sql: &str);

    /// Quote `identifier`, and add it to the end of the query being
    /// constructed.
    fn push_identifier(&mut self, identifier: &str) -> QueryResult<()>;

    /// Add a placeholder for a bind parameter to the end of the query being
    /// constructed.
    fn push_bind_param(&mut self);

    /// Increases the internal counter for bind parameters without adding the
    /// bind parameter itself to the query
    fn push_bind_param_value_only(&mut self) {}

    /// Returns the constructed SQL query.
    fn finish(self) -> String;
}

/// A complete SQL query with a return type.
///
/// This can be a select statement, or a command such as `update` or `insert`
/// with a `RETURNING` clause. Unlike [`Expression`], types implementing this
/// trait are guaranteed to be executable on their own.
///
/// A type which doesn't implement this trait may still represent a complete SQL
/// query. For example, an `INSERT` statement without a `RETURNING` clause will
/// not implement this trait, but can still be executed.
///
/// [`Expression`]: ../expression/trait.Expression.html
pub trait Query {
    /// The SQL type that this query represents.
    ///
    /// This is the SQL type of the `SELECT` clause for select statements, and
    /// the SQL type of the `RETURNING` clause for insert, update, or delete
    /// statements.
    type SqlType;
}

impl<'a, T: Query> Query for &'a T {
    type SqlType = T::SqlType;
}

/// Indicates that a type is a `SELECT` statement.
///
/// This trait differs from `Query` in two ways:
/// - It is implemented only for select statements, rather than all queries
///   which return a value.
/// - It has looser constraints. A type implementing `SelectQuery` is known to
///   be potentially valid if used as a subselect, but it is not necessarily
///   able to be executed.
pub trait SelectQuery {
    /// The SQL type of the `SELECT` clause
    type SqlType;
}

/// An untyped fragment of SQL.
///
/// This may be a complete SQL command (such as an update statement without a
/// `RETURNING` clause), or a subsection (such as our internal types used to
/// represent a `WHERE` clause). Implementations of [`ExecuteDsl`] and
/// [`LoadQuery`] will generally require that this trait be implemented.
///
/// [`ExecuteDsl`]: ../query_dsl/methods/trait.ExecuteDsl.html
/// [`LoadQuery`]: ../query_dsl/methods/trait.LoadQuery.html
pub trait QueryFragment<DB: Backend> {
    /// Walk over this `QueryFragment` for all passes.
    ///
    /// This method is where the actual behavior of an AST node is implemented.
    /// This method will contain the behavior required for all possible AST
    /// passes. See [`AstPass`] for more details.
    ///
    /// [`AstPass`]: struct.AstPass.html
    fn walk_ast(&self, pass: AstPass<DB>) -> QueryResult<()>;

    /// Converts this `QueryFragment` to its SQL representation.
    ///
    /// This method should only be called by implementations of `Connection`.
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> QueryResult<()> {
        self.walk_ast(AstPass::to_sql(out))
    }

    /// Serializes all bind parameters in this query.
    ///
    /// A bind parameter is a value which is sent separately from the query
    /// itself. It is represented in SQL with a placeholder such as `?` or `$1`.
    ///
    /// This method should only be called by implementations of `Connection`.
    fn collect_binds(
        &self,
        out: &mut DB::BindCollector,
        metadata_lookup: &DB::MetadataLookup,
    ) -> QueryResult<()> {
        self.walk_ast(AstPass::collect_binds(out, metadata_lookup))
    }

    /// Is this query safe to store in the prepared statement cache?
    ///
    /// In order to keep our prepared statement cache at a reasonable size, we
    /// avoid caching any queries which represent a potentially unbounded number
    /// of SQL queries. Generally this will only return `true` for queries for
    /// which `to_sql` will always construct exactly identical SQL.
    ///
    /// Some examples of where this method will return `false` are:
    ///
    /// - `SqlLiteral` (We don't know if the SQL was constructed dynamically, so
    ///   we must assume that it was)
    /// - `In` and `NotIn` (Each value requires a separate bind param
    ///   placeholder)
    ///
    /// This method should only be called by implementations of `Connection`.
    fn is_safe_to_cache_prepared(&self) -> QueryResult<bool> {
        let mut result = true;
        self.walk_ast(AstPass::is_safe_to_cache_prepared(&mut result))?;
        Ok(result)
    }

    #[doc(hidden)]
    /// Does walking this AST have any effect?
    fn is_noop(&self) -> QueryResult<bool> {
        let mut result = true;
        self.walk_ast(AstPass::is_noop(&mut result))?;
        Ok(result)
    }
}

impl<T: ?Sized, DB> QueryFragment<DB> for Box<T>
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, pass: AstPass<DB>) -> QueryResult<()> {
        QueryFragment::walk_ast(&**self, pass)
    }
}

impl<'a, T: ?Sized, DB> QueryFragment<DB> for &'a T
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, pass: AstPass<DB>) -> QueryResult<()> {
        QueryFragment::walk_ast(&**self, pass)
    }
}

impl<DB: Backend> QueryFragment<DB> for () {
    fn walk_ast(&self, _: AstPass<DB>) -> QueryResult<()> {
        Ok(())
    }
}

impl<T, DB> QueryFragment<DB> for Option<T>
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, out: AstPass<DB>) -> QueryResult<()> {
        match *self {
            Some(ref c) => c.walk_ast(out),
            None => Ok(()),
        }
    }
}

/// A trait used to construct type erased boxed variant of the current query node
///
/// Mainly useful for implementing third party backends
pub trait IntoBoxedClause<'a, DB> {
    /// Resulting type
    type BoxedClause;

    /// Convert the given query node in it's boxed representation
    fn into_boxed(self) -> Self::BoxedClause;
}

/// Types that can be converted into a complete, typed SQL query.
///
/// This is used internally to automatically add the right select clause when
/// none is specified, or to automatically add `RETURNING *` in certain contexts.
///
/// A type which implements this trait is guaranteed to be valid for execution.
pub trait AsQuery {
    /// The SQL type of `Self::Query`
    type SqlType;

    /// What kind of query does this type represent?
    type Query: Query<SqlType = Self::SqlType>;

    /// Converts a type which semantically represents a SQL query into the
    /// actual query being executed. See the trait level docs for more.
    fn as_query(self) -> Self::Query;
}

impl<T: Query> AsQuery for T {
    type SqlType = <Self as Query>::SqlType;
    type Query = Self;

    fn as_query(self) -> Self::Query {
        self
    }
}

/// Takes a query `QueryFragment` expression as an argument and returns a type
/// that implements `fmt::Display` and `fmt::Debug` to show the query.
///
/// The `Display` implementation will show the exact query being sent to the
/// server, with a comment showing the values of the bind parameters. The
/// `Debug` implementation will include the same information in a more
/// structured form, and respects pretty printing.
///
/// # Example
///
/// ### Returning SQL from a count statement:
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// #
/// # use diesel::*;
/// # use schema::*;
/// #
/// # fn main() {
/// #   use schema::users::dsl::*;
/// let sql = debug_query::<DB, _>(&users.count()).to_string();
/// # if cfg!(feature = "postgres") {
/// #     assert_eq!(sql, r#"SELECT COUNT(*) FROM "users" -- binds: []"#);
/// # } else {
/// assert_eq!(sql, "SELECT COUNT(*) FROM `users` -- binds: []");
/// # }
///
/// let query = users.find(1);
/// let debug = debug_query::<DB, _>(&query);
/// # if cfg!(feature = "postgres") {
/// #     assert_eq!(debug.to_string(), "SELECT \"users\".\"id\", \"users\".\"name\" \
/// #         FROM \"users\" WHERE (\"users\".\"id\" = $1) -- binds: [1]");
/// # } else {
/// assert_eq!(debug.to_string(), "SELECT `users`.`id`, `users`.`name` FROM `users` \
///     WHERE (`users`.`id` = ?) -- binds: [1]");
/// # }
///
/// let debug = format!("{:?}", debug);
/// # if !cfg!(feature = "postgres") { // Escaping that string is a pain
/// let expected = "Query { \
///     sql: \"SELECT `users`.`id`, `users`.`name` FROM `users` WHERE \
///         (`users`.`id` = ?)\", \
///     binds: [1] \
/// }";
/// assert_eq!(debug, expected);
/// # }
/// # }
/// ```
pub fn debug_query<DB, T>(query: &T) -> DebugQuery<T, DB> {
    DebugQuery::new(query)
}
<|endoftext|>


<commit_before>// Copyright 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.

#![feature(phase)]

#[phase(plugin)]
extern crate green;
extern crate native;

use std::io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream};
use std::sync::{atomic, Arc};
use std::task::TaskBuilder;
use native::NativeTaskBuilder;

static N: uint = 8;
static M: uint = 100;

green_start!(main)

fn main() {
    test();

    let (tx, rx) = channel();
    TaskBuilder::new().native().spawn(proc() {
        tx.send(test());
    });
    rx.recv();
}

fn test() {
    let mut l = TcpListener::bind("127.0.0.1", 0).unwrap();
    let addr = l.socket_name().unwrap();
    let mut a = l.listen().unwrap();
    let cnt = Arc::new(atomic::AtomicUint::new(0));

    let (tx, rx) = channel();
    for _ in range(0, N) {
        let a = a.clone();
        let cnt = cnt.clone();
        let tx = tx.clone();
        spawn(proc() {
            let mut a = a;
            loop {
                match a.accept() {
                    Ok(..) => {
                        if cnt.fetch_add(1, atomic::SeqCst) == N * M - 1 {
                            break
                        }
                    }
                    Err(ref e) if e.kind == EndOfFile => break,
                    Err(e) => fail!("{}", e),
                }
            }
            tx.send(());
        });
    }

    for _ in range(0, N) {
        let tx = tx.clone();
        spawn(proc() {
            for _ in range(0, M) {
                let _s = TcpStream::connect(addr.ip.to_string().as_slice(),
                                            addr.port).unwrap();
            }
            tx.send(());
        });
    }
    drop(tx);

    // wait for senders
    assert_eq!(rx.iter().take(N).count(), N);

    // wait for one acceptor to die
    let _ = rx.recv();

    // Notify other receivers should die
    a.close_accept().unwrap();

    // wait for receivers
    assert_eq!(rx.iter().take(N - 1).count(), N - 1);

    // Everything should have been accepted.
    assert_eq!(cnt.load(atomic::SeqCst), N * M);
}

<commit_msg>test: Tweak tcp-accept-stress one last time<commit_after>// Copyright 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.

// ignore-macos osx really doesn't like cycling through large numbers of
//              sockets as calls to connect() will start returning EADDRNOTAVAIL
//              quite quickly and it takes a few seconds for the sockets to get
//              recycled.

#![feature(phase)]

#[phase(plugin)]
extern crate green;
extern crate native;

use std::io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream};
use std::sync::{atomic, Arc};
use std::task::TaskBuilder;
use native::NativeTaskBuilder;

static N: uint = 8;
static M: uint = 20;

green_start!(main)

fn main() {
    test();

    let (tx, rx) = channel();
    TaskBuilder::new().native().spawn(proc() {
        tx.send(test());
    });
    rx.recv();
}

fn test() {
    let mut l = TcpListener::bind("127.0.0.1", 0).unwrap();
    let addr = l.socket_name().unwrap();
    let mut a = l.listen().unwrap();
    let cnt = Arc::new(atomic::AtomicUint::new(0));

    let (srv_tx, srv_rx) = channel();
    let (cli_tx, cli_rx) = channel();
    for _ in range(0, N) {
        let a = a.clone();
        let cnt = cnt.clone();
        let srv_tx = srv_tx.clone();
        spawn(proc() {
            let mut a = a;
            loop {
                match a.accept() {
                    Ok(..) => {
                        if cnt.fetch_add(1, atomic::SeqCst) == N * M - 1 {
                            break
                        }
                    }
                    Err(ref e) if e.kind == EndOfFile => break,
                    Err(e) => fail!("{}", e),
                }
            }
            srv_tx.send(());
        });
    }

    for _ in range(0, N) {
        let cli_tx = cli_tx.clone();
        spawn(proc() {
            for _ in range(0, M) {
                let _s = TcpStream::connect(addr.ip.to_string().as_slice(),
                                            addr.port).unwrap();
            }
            cli_tx.send(());
        });
    }
    drop((cli_tx, srv_tx));

    // wait for senders
    if cli_rx.iter().take(N).count() != N {
        a.close_accept().unwrap();
        fail!("clients failed");
    }

    // wait for one acceptor to die
    let _ = srv_rx.recv();

    // Notify other receivers should die
    a.close_accept().unwrap();

    // wait for receivers
    assert_eq!(srv_rx.iter().take(N - 1).count(), N - 1);

    // Everything should have been accepted.
    assert_eq!(cnt.load(atomic::SeqCst), N * M);
}

<|endoftext|>


<commit_before>use config::gobjects::GObject;
use env::Env;
use library;
use nameutil::*;
use super::*;
use super::imports::Imports;
use traits::*;
use version::Version;

#[derive(Default)]
pub struct Info {
    pub full_name: String,
    pub record_tid: library::TypeId,
    pub name: String,
    pub functions: Vec<functions::Info>,
    pub specials: special_functions::Infos,
    pub imports: Imports,
    pub version: Option<Version>,
}

impl Info {
    //TODO: add test in tests/ for panic
    pub fn type_<'a>(&self, library: &'a library::Library) -> &'a library::Record {
        let type_ = library.type_(self.record_tid).maybe_ref()
            .unwrap_or_else(|| panic!("{} is not a record.", self.full_name));
        type_
    }
}

pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
    let full_name = obj.name.clone();

    let record_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(record_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let record: &library::Record = match type_.maybe_ref() {
        Some(record) => record,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*".into(), None);
    imports.add("ffi".into(), None);

    let mut functions =
        functions::analyze(env, &record.functions, record_tid, &obj, &mut imports);

    let version = functions.iter().filter_map(|f| f.version).min();

    let specials = special_functions::extract(&mut functions);

    //accept only boxed records
    if specials.get(&special_functions::Type::Copy).is_none() {
        return None;
    };
    if specials.get(&special_functions::Type::Free).is_none() {
        return None;
    };

    //don't `use` yourself
    imports.remove(&name);

    let info = Info {
        full_name: full_name,
        record_tid: record_tid,
        name: name,
        functions: functions,
        specials: specials,
        imports: imports,
        version: version,
    };

    Some(info)
}
<commit_msg>Rewrite boxed records detection to take into account `GtkTextAttributes`<commit_after>use config::gobjects::GObject;
use env::Env;
use library;
use nameutil::*;
use super::*;
use super::imports::Imports;
use traits::*;
use version::Version;

#[derive(Default)]
pub struct Info {
    pub full_name: String,
    pub record_tid: library::TypeId,
    pub name: String,
    pub functions: Vec<functions::Info>,
    pub specials: special_functions::Infos,
    pub imports: Imports,
    pub version: Option<Version>,
}

impl Info {
    //TODO: add test in tests/ for panic
    pub fn type_<'a>(&self, library: &'a library::Library) -> &'a library::Record {
        let type_ = library.type_(self.record_tid).maybe_ref()
            .unwrap_or_else(|| panic!("{} is not a record.", self.full_name));
        type_
    }
}

pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
    let full_name = obj.name.clone();

    let record_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(record_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let record: &library::Record = match type_.maybe_ref() {
        Some(record) => record,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*".into(), None);
    imports.add("ffi".into(), None);

    let mut functions =
        functions::analyze(env, &record.functions, record_tid, &obj, &mut imports);

    let version = functions.iter().filter_map(|f| f.version).min();

    let specials = special_functions::extract(&mut functions);

    let is_shared = specials.get(&special_functions::Type::Ref).is_some() &&
        specials.get(&special_functions::Type::Unref).is_some();
    if is_shared {
        // accept only boxed records
        return None;
    };

    //don't `use` yourself
    imports.remove(&name);

    let info = Info {
        full_name: full_name,
        record_tid: record_tid,
        name: name,
        functions: functions,
        specials: specials,
        imports: imports,
        version: version,
    };

    Some(info)
}
<|endoftext|>


<commit_before>#[cfg(feature = "suggestions")]
use strsim;

/// Produces a string from a given list of possible values which is similar to
/// the passed in value `v` with a certain confidence.
/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
/// `Some("foo")`, whereas "blark" would yield `None`.
#[cfg(feature = "suggestions")]
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean<'a, T, I>(v: &str, possible_values: I) -> Option<&'a str>
                    where T: AsRef<str> + 'a,
                          I: IntoIterator<Item=&'a T> {

    let mut candidate: Option<(f64, &str)> = None;
    for pv in possible_values.into_iter() {
        let confidence = strsim::jaro_winkler(v, pv.as_ref());
        if confidence > 0.8 && (candidate.is_none() ||
                               (candidate.as_ref().unwrap().0 < confidence)) {
            candidate = Some((confidence, pv.as_ref()));
        }
    }
    match candidate {
        None => None,
        Some((_, candidate)) => Some(candidate),
    }
}

#[cfg(not(feature = "suggestions"))]
pub fn did_you_mean<'a, T, I>(_: &str, _: I) -> Option<&'a str>
                    where T: AsRef<str> + 'a,
                          I: IntoIterator<Item=&'a T> {
    None
}

/// A helper to determine message formatting
pub enum DidYouMeanMessageStyle {
    /// Suggested value is a long flag
    LongFlag,
    /// Suggested value is one of various possible values
    EnumValue,
}<commit_msg>tests: adds tests for did_you_mean suggestions<commit_after>#[cfg(feature = "suggestions")]
use strsim;

/// Produces a string from a given list of possible values which is similar to
/// the passed in value `v` with a certain confidence.
/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
/// `Some("foo")`, whereas "blark" would yield `None`.
#[cfg(feature = "suggestions")]
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean<'a, T, I>(v: &str, possible_values: I) -> Option<&'a str>
                    where T: AsRef<str> + 'a,
                          I: IntoIterator<Item=&'a T> {

    let mut candidate: Option<(f64, &str)> = None;
    for pv in possible_values.into_iter() {
        let confidence = strsim::jaro_winkler(v, pv.as_ref());
        if confidence > 0.8 && (candidate.is_none() ||
                               (candidate.as_ref().unwrap().0 < confidence)) {
            candidate = Some((confidence, pv.as_ref()));
        }
    }
    match candidate {
        None => None,
        Some((_, candidate)) => Some(candidate),
    }
}

#[cfg(not(feature = "suggestions"))]
pub fn did_you_mean<'a, T, I>(_: &str, _: I) -> Option<&'a str>
                    where T: AsRef<str> + 'a,
                          I: IntoIterator<Item=&'a T> {
    None
}

/// A helper to determine message formatting
pub enum DidYouMeanMessageStyle {
    /// Suggested value is a long flag
    LongFlag,
    /// Suggested value is one of various possible values
    EnumValue,
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn did_you_mean_possible_values() {
        let p_vals = ["test", "possible", "values"];
        assert_eq!(did_you_mean("tst", p_vals.iter()), Some("test"));
        assert!(did_you_mean("hahaahahah", p_vals.iter()).is_none());

    }
}<|endoftext|>


<commit_before>extern crate chrono;
#[macro_use]
extern crate clap;
extern crate diesel;
extern crate dotenv;
extern crate diesel_infer_schema;

mod database_error;
#[macro_use]
mod database;
mod cli;
mod pretty_printing;

use chrono::*;
use clap::{ArgMatches,Shell};
#[cfg(feature = "postgres")]
use diesel::pg::PgConnection;
#[cfg(feature = "sqlite")]
use diesel::sqlite::SqliteConnection;
use diesel::migrations::schema::*;
use diesel::types::{FromSql, VarChar};
use diesel::{migrations, Connection, Insertable};
use std::error::Error;
use std::io::stdout;
use std::path::{PathBuf, Path};
use std::{env, fs};

use self::database_error::{DatabaseError, DatabaseResult};

fn main() {
    use self::dotenv::dotenv;
    dotenv().ok();

    let matches = cli::build_cli().get_matches();

    match matches.subcommand() {
        ("migration", Some(matches)) => run_migration_command(matches),
        ("setup", Some(matches)) => run_setup_command(matches),
        ("database", Some(matches)) => run_database_command(matches),
        ("bash-completion", Some(matches)) => generate_bash_completion_command(matches),
        ("print-schema", Some(matches)) => run_infer_schema(matches),
        _ => unreachable!("The cli parser should prevent reaching here"),
    }
}

fn run_migration_command(matches: &ArgMatches) {
    match matches.subcommand() {
        ("run", Some(args)) => {
            let database_url = database::database_url(matches);
            let dir = migrations_dir(args);
            call_with_conn!(database_url, migrations::run_pending_migrations_in_directory(&dir, &mut stdout()))
                .unwrap_or_else(handle_error);
        }
        ("revert", Some(_)) => {
            let database_url = database::database_url(matches);
            call_with_conn!(database_url, migrations::revert_latest_migration)
                .unwrap_or_else(handle_error);
        }
        ("redo", Some(_)) => {
            let database_url = database::database_url(matches);
            call_with_conn!(database_url, redo_latest_migration);
        }
        ("generate", Some(args)) => {
            let migration_name = args.value_of("MIGRATION_NAME").unwrap();
            let version = migration_version(args);
            let versioned_name = format!("{}_{}", version, migration_name);
            let migration_dir = migrations_dir(args).join(versioned_name);
            fs::create_dir(&migration_dir).unwrap();

            let migration_dir_relative = convert_absolute_path_to_relative(
                &migration_dir,
                &env::current_dir().unwrap()
            );

            let up_path = migration_dir.join("up.sql");
            println!("Creating {}", migration_dir_relative.join("up.sql").display());
            fs::File::create(up_path).unwrap();
            let down_path = migration_dir.join("down.sql");
            println!("Creating {}", migration_dir_relative.join("down.sql").display());
            fs::File::create(down_path).unwrap();
        }
        _ => unreachable!("The cli parser should prevent reaching here"),
    }
}

use std::fmt::Display;
fn migration_version<'a>(matches: &'a ArgMatches) -> Box<Display + 'a> {
    matches.value_of("MIGRATION_VERSION").map(|s| Box::new(s) as Box<Display>)
        .unwrap_or_else(|| Box::new(UTC::now().format("%Y%m%d%H%M%S")))
}

fn migrations_dir(matches: &ArgMatches) -> PathBuf {
    matches.value_of("MIGRATION_DIRECTORY")
        .map(PathBuf::from)
        .or_else(|| {
            env::var("MIGRATION_DIRECTORY").map(PathBuf::from).ok()
        }).unwrap_or_else(|| {
            migrations::find_migrations_directory()
                .unwrap_or_else(handle_error)
        })
}

fn run_setup_command(matches: &ArgMatches) {
    migrations::find_migrations_directory()
        .unwrap_or_else(|_| {
            create_migrations_directory()
                .unwrap_or_else(handle_error)
        });

    database::setup_database(matches).unwrap_or_else(handle_error);
}

fn run_database_command(matches: &ArgMatches) {
    match matches.subcommand() {
        ("setup", Some(args)) => database::setup_database(args).unwrap_or_else(handle_error),
        ("reset", Some(args)) => database::reset_database(args).unwrap_or_else(handle_error),
        ("drop", Some(args)) => database::drop_database_command(args).unwrap_or_else(handle_error),
        _ => unreachable!("The cli parser should prevent reaching here"),
    };
}

fn generate_bash_completion_command(_: &ArgMatches) {
    cli::build_cli().gen_completions_to("diesel", Shell::Bash, &mut stdout());
}

/// Looks for a migrations directory in the current path and all parent paths,
/// and creates one in the same directory as the Cargo.toml if it can't find
/// one. It also sticks a .gitkeep in the directory so git will pick it up.
/// Returns a `DatabaseError::CargoTomlNotFound` if no Cargo.toml is found.
fn create_migrations_directory() -> DatabaseResult<PathBuf> {
    let project_root = try!(find_project_root());
    println!("Creating migrations/ directory at: {}", project_root
                                                        .join("migrations")
                                                        .display());
    try!(fs::create_dir(project_root.join("migrations")));
    try!(fs::File::create(project_root.join("migrations/.gitkeep")));
    Ok(project_root)
}

fn find_project_root() -> DatabaseResult<PathBuf> {
    search_for_cargo_toml_directory(&try!(env::current_dir()))
}

/// Searches for the directory that holds the project's Cargo.toml, and returns
/// the path if it found it, or returns a `DatabaseError::CargoTomlNotFound`.
fn search_for_cargo_toml_directory(path: &Path) -> DatabaseResult<PathBuf> {
    let toml_path = path.join("Cargo.toml");
    if toml_path.is_file() {
        Ok(path.to_owned())
    } else {
        path.parent().map(search_for_cargo_toml_directory)
            .unwrap_or(Err(DatabaseError::CargoTomlNotFound))
    }
}

/// Reverts the most recent migration, and then runs it again, all in a
/// transaction. If either part fails, the transaction is not committed.
fn redo_latest_migration<Conn>(conn: &Conn) where
        Conn: Connection,
        String: FromSql<VarChar, Conn::Backend>,
        for<'a> &'a NewMigration<'a>:
            Insertable<__diesel_schema_migrations::table, Conn::Backend>,
{
    conn.transaction(|| {
        let reverted_version = try!(migrations::revert_latest_migration(conn));
        migrations::run_migration_with_version(conn, &reverted_version, &mut stdout())
    }).unwrap_or_else(handle_error);
}

fn handle_error<E: Error, T>(error: E) -> T {
    println!("{}", error);
    ::std::process::exit(1);
}

// Converts an absolute path to a relative path, with the restriction that the
// target path must be in the same directory or above the current path.
fn convert_absolute_path_to_relative(target_path: &Path, mut current_path: &Path)
    -> PathBuf
{
    let mut result = PathBuf::new();

    while !target_path.starts_with(current_path) {
        result.push("..");
        match current_path.parent() {
            Some(parent) => current_path = parent,
            None => return target_path.into(),
        }
    }

    result.join(target_path.strip_prefix(current_path).unwrap())
}

fn run_infer_schema(matches: &ArgMatches) {
    let database_url = database::database_url(matches);
    let schema_name = matches.value_of("schema");

    let filtering_tables = matches.values_of("table-name").map(|v| {
        if cfg!(feature = "postgres") {
            v.map(|v| {
                if v.contains(".") {
                   String::from(v)
                } else {
                   format!("{}.{}", schema_name.unwrap_or("public"), v)
                }
            }).collect()
        } else {
            v.map(String::from).collect()
        }
    })
        .unwrap_or(::std::collections::HashSet::new());
    let is_whitelist = matches.is_present("whitelist");
    let is_blacklist = matches.is_present("blacklist");

    let table_names = diesel_infer_schema::load_table_names(&database_url, schema_name)
        .expect(&format!("Could not load table names from database `{}`{}",
            database_url,
            if let Some(name) = schema_name {
                format!(" with schema `{}`", name)
            } else {
                "".into()
            }
        ));

    let tables = table_names.iter()
        .filter_map(|table| {
            let table_name = table.to_string();
            if is_whitelist && !filtering_tables.contains(&table_name[..]) {
                return None;
            }
            if is_blacklist && filtering_tables.contains(&table_name[..]) {
                return None;
            }
            Some(diesel_infer_schema::infer_schema_for_schema_name(table, &database_url)
                .expect(&format!("Could not load table `{}`", table.to_string()))
                .tokens())
        });

    let schema = diesel_infer_schema::handle_schema(tables, schema_name);

    let pretty = pretty_printing::format_schema(schema.as_str())
        .expect("Could not write to stdout");

    println!("{}", pretty);
}

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

    use database_error::DatabaseError;

    use self::tempdir::TempDir;

    use std::fs;
    use std::path::PathBuf;

    use super::convert_absolute_path_to_relative;
    use super::search_for_cargo_toml_directory;

    #[test]
    fn toml_directory_find_cargo_toml() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let toml_path = temp_path.join("Cargo.toml");

        fs::File::create(&toml_path).unwrap();

        assert_eq!(Ok(temp_path.clone()), search_for_cargo_toml_directory(&temp_path));
    }

    #[test]
    fn cargo_toml_not_found_if_no_cargo_toml() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();

        assert_eq!(Err(DatabaseError::CargoTomlNotFound),
            search_for_cargo_toml_directory(&temp_path));
    }

    #[test]
    fn convert_absolute_path_to_relative_works() {
        assert_eq!(PathBuf::from("migrations/12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo")));
        assert_eq!(PathBuf::from("../migrations/12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/src")));
        assert_eq!(PathBuf::from("../../../migrations/12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/src/controllers/errors")));
        assert_eq!(PathBuf::from("12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/migrations")));
        assert_eq!(PathBuf::from("../12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/migrations/67890_create_post")));
    }
}
<commit_msg>Improve Style<commit_after>extern crate chrono;
#[macro_use]
extern crate clap;
extern crate diesel;
extern crate dotenv;
extern crate diesel_infer_schema;

mod database_error;
#[macro_use]
mod database;
mod cli;
mod pretty_printing;

use chrono::*;
use clap::{ArgMatches,Shell};
#[cfg(feature = "postgres")]
use diesel::pg::PgConnection;
#[cfg(feature = "sqlite")]
use diesel::sqlite::SqliteConnection;
use diesel::migrations::schema::*;
use diesel::types::{FromSql, VarChar};
use diesel::{migrations, Connection, Insertable};
use std::error::Error;
use std::io::stdout;
use std::path::{PathBuf, Path};
use std::{env, fs};

use self::database_error::{DatabaseError, DatabaseResult};

fn main() {
    use self::dotenv::dotenv;
    dotenv().ok();

    let matches = cli::build_cli().get_matches();

    match matches.subcommand() {
        ("migration", Some(matches)) => run_migration_command(matches),
        ("setup", Some(matches)) => run_setup_command(matches),
        ("database", Some(matches)) => run_database_command(matches),
        ("bash-completion", Some(matches)) => generate_bash_completion_command(matches),
        ("print-schema", Some(matches)) => run_infer_schema(matches),
        _ => unreachable!("The cli parser should prevent reaching here"),
    }
}

fn run_migration_command(matches: &ArgMatches) {
    match matches.subcommand() {
        ("run", Some(args)) => {
            let database_url = database::database_url(matches);
            let dir = migrations_dir(args);
            call_with_conn!(database_url, migrations::run_pending_migrations_in_directory(&dir, &mut stdout()))
                .unwrap_or_else(handle_error);
        }
        ("revert", Some(_)) => {
            let database_url = database::database_url(matches);
            call_with_conn!(database_url, migrations::revert_latest_migration)
                .unwrap_or_else(handle_error);
        }
        ("redo", Some(_)) => {
            let database_url = database::database_url(matches);
            call_with_conn!(database_url, redo_latest_migration);
        }
        ("generate", Some(args)) => {
            let migration_name = args.value_of("MIGRATION_NAME").unwrap();
            let version = migration_version(args);
            let versioned_name = format!("{}_{}", version, migration_name);
            let migration_dir = migrations_dir(args).join(versioned_name);
            fs::create_dir(&migration_dir).unwrap();

            let migration_dir_relative = convert_absolute_path_to_relative(
                &migration_dir,
                &env::current_dir().unwrap()
            );

            let up_path = migration_dir.join("up.sql");
            println!("Creating {}", migration_dir_relative.join("up.sql").display());
            fs::File::create(up_path).unwrap();
            let down_path = migration_dir.join("down.sql");
            println!("Creating {}", migration_dir_relative.join("down.sql").display());
            fs::File::create(down_path).unwrap();
        }
        _ => unreachable!("The cli parser should prevent reaching here"),
    }
}

use std::fmt::Display;
fn migration_version<'a>(matches: &'a ArgMatches) -> Box<Display + 'a> {
    matches.value_of("MIGRATION_VERSION").map(|s| Box::new(s) as Box<Display>)
        .unwrap_or_else(|| Box::new(UTC::now().format("%Y%m%d%H%M%S")))
}

fn migrations_dir(matches: &ArgMatches) -> PathBuf {
    matches.value_of("MIGRATION_DIRECTORY")
        .map(PathBuf::from)
        .or_else(|| {
            env::var("MIGRATION_DIRECTORY").map(PathBuf::from).ok()
        }).unwrap_or_else(|| {
            migrations::find_migrations_directory()
                .unwrap_or_else(handle_error)
        })
}

fn run_setup_command(matches: &ArgMatches) {
    migrations::find_migrations_directory()
        .unwrap_or_else(|_| {
            create_migrations_directory()
                .unwrap_or_else(handle_error)
        });

    database::setup_database(matches).unwrap_or_else(handle_error);
}

fn run_database_command(matches: &ArgMatches) {
    match matches.subcommand() {
        ("setup", Some(args)) => database::setup_database(args).unwrap_or_else(handle_error),
        ("reset", Some(args)) => database::reset_database(args).unwrap_or_else(handle_error),
        ("drop", Some(args)) => database::drop_database_command(args).unwrap_or_else(handle_error),
        _ => unreachable!("The cli parser should prevent reaching here"),
    };
}

fn generate_bash_completion_command(_: &ArgMatches) {
    cli::build_cli().gen_completions_to("diesel", Shell::Bash, &mut stdout());
}

/// Looks for a migrations directory in the current path and all parent paths,
/// and creates one in the same directory as the Cargo.toml if it can't find
/// one. It also sticks a .gitkeep in the directory so git will pick it up.
/// Returns a `DatabaseError::CargoTomlNotFound` if no Cargo.toml is found.
fn create_migrations_directory() -> DatabaseResult<PathBuf> {
    let project_root = try!(find_project_root());
    println!("Creating migrations/ directory at: {}", project_root
                                                        .join("migrations")
                                                        .display());
    try!(fs::create_dir(project_root.join("migrations")));
    try!(fs::File::create(project_root.join("migrations/.gitkeep")));
    Ok(project_root)
}

fn find_project_root() -> DatabaseResult<PathBuf> {
    search_for_cargo_toml_directory(&try!(env::current_dir()))
}

/// Searches for the directory that holds the project's Cargo.toml, and returns
/// the path if it found it, or returns a `DatabaseError::CargoTomlNotFound`.
fn search_for_cargo_toml_directory(path: &Path) -> DatabaseResult<PathBuf> {
    let toml_path = path.join("Cargo.toml");
    if toml_path.is_file() {
        Ok(path.to_owned())
    } else {
        path.parent().map(search_for_cargo_toml_directory)
            .unwrap_or(Err(DatabaseError::CargoTomlNotFound))
    }
}

/// Reverts the most recent migration, and then runs it again, all in a
/// transaction. If either part fails, the transaction is not committed.
fn redo_latest_migration<Conn>(conn: &Conn) where
        Conn: Connection,
        String: FromSql<VarChar, Conn::Backend>,
        for<'a> &'a NewMigration<'a>:
            Insertable<__diesel_schema_migrations::table, Conn::Backend>,
{
    conn.transaction(|| {
        let reverted_version = try!(migrations::revert_latest_migration(conn));
        migrations::run_migration_with_version(conn, &reverted_version, &mut stdout())
    }).unwrap_or_else(handle_error);
}

fn handle_error<E: Error, T>(error: E) -> T {
    println!("{}", error);
    ::std::process::exit(1);
}

// Converts an absolute path to a relative path, with the restriction that the
// target path must be in the same directory or above the current path.
fn convert_absolute_path_to_relative(target_path: &Path, mut current_path: &Path)
    -> PathBuf
{
    let mut result = PathBuf::new();

    while !target_path.starts_with(current_path) {
        result.push("..");
        match current_path.parent() {
            Some(parent) => current_path = parent,
            None => return target_path.into(),
        }
    }

    result.join(target_path.strip_prefix(current_path).unwrap())
}

fn run_infer_schema(matches: &ArgMatches) {
    let database_url = database::database_url(matches);
    let schema_name = matches.value_of("schema");

    let filtering_tables = matches.values_of("table-name").map(|values| {
        values.map(|table_name| {
            if cfg!(not(feature = "postgres")) || table_name.contains(".") {
                String::from(table_name)
            } else {
                format!("{}.{}", schema_name.unwrap_or("public"), table_name)
            }
        }).collect()
    })
        .unwrap_or(::std::collections::HashSet::new());
    let is_whitelist = matches.is_present("whitelist");
    let is_blacklist = matches.is_present("blacklist");

    let table_names = diesel_infer_schema::load_table_names(&database_url, schema_name)
        .expect(&format!("Could not load table names from database `{}`{}",
            database_url,
            if let Some(name) = schema_name {
                format!(" with schema `{}`", name)
            } else {
                "".into()
            }
        ));

    let tables = table_names.iter()
        .filter_map(|table| {
            let table_name = table.to_string();
            if is_whitelist && !filtering_tables.contains(&table_name[..]) {
                return None;
            }
            if is_blacklist && filtering_tables.contains(&table_name[..]) {
                return None;
            }
            Some(diesel_infer_schema::infer_schema_for_schema_name(table, &database_url)
                .expect(&format!("Could not load table `{}`", table.to_string()))
                .tokens())
        });

    let schema = diesel_infer_schema::handle_schema(tables, schema_name);

    let pretty = pretty_printing::format_schema(schema.as_str())
        .expect("Could not write to stdout");

    println!("{}", pretty);
}

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

    use database_error::DatabaseError;

    use self::tempdir::TempDir;

    use std::fs;
    use std::path::PathBuf;

    use super::convert_absolute_path_to_relative;
    use super::search_for_cargo_toml_directory;

    #[test]
    fn toml_directory_find_cargo_toml() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let toml_path = temp_path.join("Cargo.toml");

        fs::File::create(&toml_path).unwrap();

        assert_eq!(Ok(temp_path.clone()), search_for_cargo_toml_directory(&temp_path));
    }

    #[test]
    fn cargo_toml_not_found_if_no_cargo_toml() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();

        assert_eq!(Err(DatabaseError::CargoTomlNotFound),
            search_for_cargo_toml_directory(&temp_path));
    }

    #[test]
    fn convert_absolute_path_to_relative_works() {
        assert_eq!(PathBuf::from("migrations/12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo")));
        assert_eq!(PathBuf::from("../migrations/12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/src")));
        assert_eq!(PathBuf::from("../../../migrations/12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/src/controllers/errors")));
        assert_eq!(PathBuf::from("12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/migrations")));
        assert_eq!(PathBuf::from("../12345_create_user"),
                   convert_absolute_path_to_relative(&PathBuf::from("projects/foo/migrations/12345_create_user"),
                                                     &PathBuf::from("projects/foo/migrations/67890_create_post")));
    }
}
<|endoftext|>


<commit_before>pub fn pathmatch(pattern: &str, pathstring: &str) -> bool
{
    return pattern == pathstring
}

#[test]
fn pathmatch_test_exact_equality()
{
    assert!(pathmatch("", ""));
    assert!(pathmatch("a", "a"));
    assert!(pathmatch("BC", "BC"));
    assert!(!pathmatch("a", ""));
    assert!(!pathmatch("", "BC"));
}

<commit_msg>tests for any character wildcard `?`<commit_after>pub fn pathmatch(pattern: &str, pathstring: &str) -> bool
{
    let mut pattern_chars = pattern.chars();
    let mut path_chars = pathstring.chars();
    loop {
        match pattern_chars.next() {
            None => return path_chars.next().is_none(),
            Some(pc) => {
                match pc {
                    '?' => return path_chars.next().is_some(),
                    _ => {
                        match path_chars.next() {
                            None => return false,
                            Some(sc) => if pc != sc { return false },
                        }
                    }
                }
            }
        }
    }
}

#[test]
fn pathmatch_test_anychar()
{
    assert!(pathmatch("?", "?"));
    assert!(pathmatch("?", "a"));
    assert!(pathmatch("??", "BC"));
    assert!(pathmatch("B?", "BC"));
    assert!(pathmatch("?C", "BC"));
    assert!(!pathmatch("?", ""));
    assert!(!pathmatch("D?", "BC"));
}

#[test]
fn pathmatch_test_exact_equality()
{
    assert!(pathmatch("", ""));
    assert!(pathmatch("a", "a"));
    assert!(pathmatch("BC", "BC"));
    assert!(!pathmatch("a", ""));
    assert!(!pathmatch("", "BC"));
}

<|endoftext|>


<commit_before>//!
//!
//! This module provides Traits reprensentating open devices
//! and their surfaces to render contents.
//!
//! ---
//!
//! Initialization of devices happens through an open file descriptor
//! of a drm device.
//!
//! ---
//!
//! Initialization of surfaces happens through the types provided by
//! [`drm-rs`](drm).
//!
//! Four entities are relevant for the initialization procedure.
//!
//! [`crtc`](drm::control::crtc)s represent scanout engines
//! of the device pointer to one framebuffer.
//! Their responsibility is to read the data of the framebuffer and export it into an "Encoder".
//! The number of crtc's represent the number of independant output devices the hardware may handle.
//!
//! An [`encoder`](drm::control::encoder) encodes the data of
//! connected crtcs into a video signal for a fixed set of connectors.
//! E.g. you might have an analog encoder based on a DAG for VGA ports, but another one for digital ones.
//! Also not every encoder might be connected to every crtc.
//!
//! A [`connector`](drm::control::connector) represents a port
//! on your computer, possibly with a connected monitor, TV, capture card, etc.
//!
//! On surface creation a matching encoder for your `encoder`-`connector` is automatically selected,
//! if it exists, which means you still need to check your configuration.
//!
//! At last a [`Mode`](drm::control::Mode) needs to be selected,
//! supported by the `crtc` in question.
//!

use drm::{
    control::{connector, crtc, encoder, framebuffer, plane, Device as ControlDevice, Mode, ResourceHandles},
    Device as BasicDevice, SystemError as DrmError,
};
use nix::libc::dev_t;

use std::error::Error;
use std::iter::IntoIterator;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

use calloop::generic::{Generic, SourceFd};
use calloop::mio::Interest;
use calloop::InsertError;
use calloop::{LoopHandle, Source};

use super::graphics::SwapBuffersError;

#[cfg(feature = "backend_drm_atomic")]
pub mod atomic;
#[cfg(feature = "backend_drm")]
pub mod common;
#[cfg(feature = "backend_drm_egl")]
pub mod egl;
#[cfg(feature = "backend_drm_gbm")]
pub mod gbm;
#[cfg(feature = "backend_drm_legacy")]
pub mod legacy;

/// Trait to receive events of a bound [`Device`]
///
/// See [`device_bind`]
pub trait DeviceHandler {
    /// The [`Device`] type this handler can handle
    type Device: Device + ?Sized;

    /// A vblank blank event on the provided crtc has happend
    fn vblank(&mut self, crtc: crtc::Handle);
    /// An error happend while processing events
    fn error(&mut self, error: <<<Self as DeviceHandler>::Device as Device>::Surface as Surface>::Error);
}

/// An open drm device
pub trait Device: AsRawFd + DevPath {
    /// Associated [`Surface`] of this [`Device`] type
    type Surface: Surface;

    /// Returns the id of this device node.
    fn device_id(&self) -> dev_t;

    /// Assigns a [`DeviceHandler`] called during event processing.
    ///
    /// See [`device_bind`] and [`DeviceHandler`]
    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static);
    /// Clear a set [`DeviceHandler`](trait.DeviceHandler.html), if any
    fn clear_handler(&mut self);

    /// Creates a new rendering surface.
    ///
    /// Initialization of surfaces happens through the types provided by
    /// [`drm-rs`](drm).
    ///
    /// [`crtc`](drm::control::crtc)s represent scanout engines
    /// of the device pointer to one framebuffer.
    /// Their responsibility is to read the data of the framebuffer and export it into an "Encoder".
    /// The number of crtc's represent the number of independant output devices the hardware may handle.
    fn create_surface(
        &mut self,
        ctrc: crtc::Handle,
    ) -> Result<Self::Surface, <Self::Surface as Surface>::Error>;

    /// Processes any open events of the underlying file descriptor.
    ///
    /// You should not call this function manually, but rather use
    /// [`device_bind`] to register the device
    /// to an [`EventLoop`](calloop::EventLoop)
    /// to synchronize your rendering to the vblank events of the open crtc's
    fn process_events(&mut self);

    /// Attempts to acquire a copy of the [`Device`]'s
    /// [`ResourceHandle`](drm::control::ResourceHandle)
    fn resource_handles(&self) -> Result<ResourceHandles, <Self::Surface as Surface>::Error>;

    /// Retrieve the information for a connector
    fn get_connector_info(&self, conn: connector::Handle) -> Result<connector::Info, DrmError>;

    /// Retrieve the information for a crtc
    fn get_crtc_info(&self, crtc: crtc::Handle) -> Result<crtc::Info, DrmError>;

    /// Retrieve the information for an encoder
    fn get_encoder_info(&self, enc: encoder::Handle) -> Result<encoder::Info, DrmError>;

    /// Retrieve the information for a framebuffer
    fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> Result<framebuffer::Info, DrmError>;

    /// Retrieve the information for a plane
    fn get_plane_info(&self, plane: plane::Handle) -> Result<plane::Info, DrmError>;
}

/// Marker trait for [`Device`]s able to provide [`RawSurface`]s
pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface> {
    /// Associated [`RawSurface`] of this [`RawDevice`] type
    type Surface: RawSurface;
}

/// An open crtc that can be used for rendering
pub trait Surface {
    /// Type repesenting a collection of
    /// [`connector`](drm::control::connector)s
    /// returned by [`current_connectors`](Surface::current_connectors) and
    /// [`pending_connectors`](Surface::pending_connectors)
    type Connectors: IntoIterator<Item = connector::Handle>;
    /// Error type returned by methods of this trait
    type Error: Error + Send + 'static;

    /// Returns the underlying [`crtc`](drm::control::crtc) of this surface
    fn crtc(&self) -> crtc::Handle;
    /// Currently used [`connector`](drm::control::connector)s of this `Surface`
    fn current_connectors(&self) -> Self::Connectors;
    /// Returns the pending [`connector`](drm::control::connector)s
    /// used after the next [`commit`](RawSurface::commit) of this [`Surface`]
    ///
    /// *Note*: Only on a [`RawSurface`] you may directly trigger
    /// a [`commit`](RawSurface::commit). Other `Surface`s provide their
    /// own methods that *may* trigger a commit, you will need to read their docs.
    fn pending_connectors(&self) -> Self::Connectors;
    /// Tries to add a new [`connector`](drm::control::connector)
    /// to be used after the next commit.
    ///
    /// Fails if the `connector` is not compatible with the underlying [`crtc`](drm::control::crtc)
    /// (e.g. no suitable [`encoder`](drm::control::encoder) may be found)
    /// or is not compatible with the currently pending
    /// [`Mode`](drm::control::Mode).
    fn add_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>;
    /// Tries to mark a [`connector`](drm::control::connector)
    /// for removal on the next commit.
    fn remove_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>;
    /// Tries to replace the current connector set with the newly provided one on the next commit.
    ///
    /// Fails if one new `connector` is not compatible with the underlying [`crtc`](drm::control::crtc)
    /// (e.g. no suitable [`encoder`](drm::control::encoder) may be found)
    /// or is not compatible with the currently pending
    /// [`Mode`](drm::control::Mode).
    fn set_connectors(&self, connectors: &[connector::Handle]) -> Result<(), Self::Error>;
    /// Returns the currently active [`Mode`](drm::control::Mode)
    /// of the underlying [`crtc`](drm::control::crtc)
    /// if any.
    fn current_mode(&self) -> Option<Mode>;
    /// Returns the currently pending [`Mode`](drm::control::Mode)
    /// to be used after the next commit, if any.
    fn pending_mode(&self) -> Option<Mode>;
    /// Tries to set a new [`Mode`](drm::control::Mode)
    /// to be used after the next commit.
    ///
    /// Fails if the mode is not compatible with the underlying
    /// [`crtc`](drm::control::crtc) or any of the
    /// pending [`connector`](drm::control::connector)s.
    ///
    /// *Note*: Only on a [`RawSurface`] you may directly trigger
    /// a [`commit`](RawSurface::commit). Other [`Surface`]s provide their
    /// own methods that *may* trigger a commit, you will need to read their docs.
    fn use_mode(&self, mode: Option<Mode>) -> Result<(), Self::Error>;
}

/// An open bare crtc without any rendering abstractions
pub trait RawSurface: Surface + ControlDevice + BasicDevice {
    /// Returns true whenever any state changes are pending to be commited
    ///
    /// The following functions may trigger a pending commit:
    /// - [`add_connector`](Surface::add_connector)
    /// - [`remove_connector`](Surface::remove_connector)
    /// - [`use_mode`](Surface::use_mode)
    fn commit_pending(&self) -> bool;
    /// Commit the pending state rendering a given framebuffer.
    ///
    /// *Note*: This will trigger a full modeset on the underlying device,
    /// potentially causing some flickering. Check before performing this
    /// operation if a commit really is necessary using [`commit_pending`](RawSurface::commit_pending).
    ///
    /// This operation is not necessarily blocking until the crtc is in the desired state,
    /// but will trigger a `vblank` event once done.
    /// Make sure to [set a `DeviceHandler`](Device::set_handler) and
    /// [register the belonging `Device`](device_bind) before to receive the event in time.
    fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), <Self as Surface>::Error>;
    /// Page-flip the underlying [`crtc`](drm::control::crtc)
    /// to a new given [`framebuffer`].
    ///
    /// This will not cause the crtc to modeset.
    ///
    /// This operation is not blocking and will produce a `vblank` event once swapping is done.
    /// Make sure to [set a `DeviceHandler`](Device::set_handler) and
    /// [register the belonging `Device`](device_bind) before to receive the event in time.
    fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), SwapBuffersError>;
}

/// Trait representing open devices that *may* return a `Path`
pub trait DevPath {
    /// Returns the path of the open device if possible
    fn dev_path(&self) -> Option<PathBuf>;
}

impl<A: AsRawFd> DevPath for A {
    fn dev_path(&self) -> Option<PathBuf> {
        use std::fs;

        fs::read_link(format!("/proc/self/fd/{:?}", self.as_raw_fd())).ok()
    }
}

/// calloop source associated with a Device
pub type DrmSource<D> = Generic<SourceFd<D>>;

/// Bind a `Device` to an [`EventLoop`](calloop::EventLoop),
///
/// This will cause it to recieve events and feed them into a previously
/// set [`DeviceHandler`](DeviceHandler).
pub fn device_bind<D: Device + 'static, Data>(
    handle: &LoopHandle<Data>,
    device: D,
) -> ::std::result::Result<Source<DrmSource<D>>, InsertError<DrmSource<D>>>
where
    D: Device,
    Data: 'static,
{
    let mut source = Generic::from_fd_source(device);
    source.set_interest(Interest::READABLE);

    handle.insert_source(source, |evt, _| {
        evt.source.borrow_mut().0.process_events();
    })
}
<commit_msg>typo: ctrc -> crtc in drm/mod.rs<commit_after>//!
//!
//! This module provides Traits reprensentating open devices
//! and their surfaces to render contents.
//!
//! ---
//!
//! Initialization of devices happens through an open file descriptor
//! of a drm device.
//!
//! ---
//!
//! Initialization of surfaces happens through the types provided by
//! [`drm-rs`](drm).
//!
//! Four entities are relevant for the initialization procedure.
//!
//! [`crtc`](drm::control::crtc)s represent scanout engines
//! of the device pointer to one framebuffer.
//! Their responsibility is to read the data of the framebuffer and export it into an "Encoder".
//! The number of crtc's represent the number of independant output devices the hardware may handle.
//!
//! An [`encoder`](drm::control::encoder) encodes the data of
//! connected crtcs into a video signal for a fixed set of connectors.
//! E.g. you might have an analog encoder based on a DAG for VGA ports, but another one for digital ones.
//! Also not every encoder might be connected to every crtc.
//!
//! A [`connector`](drm::control::connector) represents a port
//! on your computer, possibly with a connected monitor, TV, capture card, etc.
//!
//! On surface creation a matching encoder for your `encoder`-`connector` is automatically selected,
//! if it exists, which means you still need to check your configuration.
//!
//! At last a [`Mode`](drm::control::Mode) needs to be selected,
//! supported by the `crtc` in question.
//!

use drm::{
    control::{connector, crtc, encoder, framebuffer, plane, Device as ControlDevice, Mode, ResourceHandles},
    Device as BasicDevice, SystemError as DrmError,
};
use nix::libc::dev_t;

use std::error::Error;
use std::iter::IntoIterator;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

use calloop::generic::{Generic, SourceFd};
use calloop::mio::Interest;
use calloop::InsertError;
use calloop::{LoopHandle, Source};

use super::graphics::SwapBuffersError;

#[cfg(feature = "backend_drm_atomic")]
pub mod atomic;
#[cfg(feature = "backend_drm")]
pub mod common;
#[cfg(feature = "backend_drm_egl")]
pub mod egl;
#[cfg(feature = "backend_drm_gbm")]
pub mod gbm;
#[cfg(feature = "backend_drm_legacy")]
pub mod legacy;

/// Trait to receive events of a bound [`Device`]
///
/// See [`device_bind`]
pub trait DeviceHandler {
    /// The [`Device`] type this handler can handle
    type Device: Device + ?Sized;

    /// A vblank blank event on the provided crtc has happend
    fn vblank(&mut self, crtc: crtc::Handle);
    /// An error happend while processing events
    fn error(&mut self, error: <<<Self as DeviceHandler>::Device as Device>::Surface as Surface>::Error);
}

/// An open drm device
pub trait Device: AsRawFd + DevPath {
    /// Associated [`Surface`] of this [`Device`] type
    type Surface: Surface;

    /// Returns the id of this device node.
    fn device_id(&self) -> dev_t;

    /// Assigns a [`DeviceHandler`] called during event processing.
    ///
    /// See [`device_bind`] and [`DeviceHandler`]
    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static);
    /// Clear a set [`DeviceHandler`](trait.DeviceHandler.html), if any
    fn clear_handler(&mut self);

    /// Creates a new rendering surface.
    ///
    /// Initialization of surfaces happens through the types provided by
    /// [`drm-rs`](drm).
    ///
    /// [`crtc`](drm::control::crtc)s represent scanout engines
    /// of the device pointer to one framebuffer.
    /// Their responsibility is to read the data of the framebuffer and export it into an "Encoder".
    /// The number of crtc's represent the number of independant output devices the hardware may handle.
    fn create_surface(
        &mut self,
        crtc: crtc::Handle,
    ) -> Result<Self::Surface, <Self::Surface as Surface>::Error>;

    /// Processes any open events of the underlying file descriptor.
    ///
    /// You should not call this function manually, but rather use
    /// [`device_bind`] to register the device
    /// to an [`EventLoop`](calloop::EventLoop)
    /// to synchronize your rendering to the vblank events of the open crtc's
    fn process_events(&mut self);

    /// Attempts to acquire a copy of the [`Device`]'s
    /// [`ResourceHandle`](drm::control::ResourceHandle)
    fn resource_handles(&self) -> Result<ResourceHandles, <Self::Surface as Surface>::Error>;

    /// Retrieve the information for a connector
    fn get_connector_info(&self, conn: connector::Handle) -> Result<connector::Info, DrmError>;

    /// Retrieve the information for a crtc
    fn get_crtc_info(&self, crtc: crtc::Handle) -> Result<crtc::Info, DrmError>;

    /// Retrieve the information for an encoder
    fn get_encoder_info(&self, enc: encoder::Handle) -> Result<encoder::Info, DrmError>;

    /// Retrieve the information for a framebuffer
    fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> Result<framebuffer::Info, DrmError>;

    /// Retrieve the information for a plane
    fn get_plane_info(&self, plane: plane::Handle) -> Result<plane::Info, DrmError>;
}

/// Marker trait for [`Device`]s able to provide [`RawSurface`]s
pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface> {
    /// Associated [`RawSurface`] of this [`RawDevice`] type
    type Surface: RawSurface;
}

/// An open crtc that can be used for rendering
pub trait Surface {
    /// Type repesenting a collection of
    /// [`connector`](drm::control::connector)s
    /// returned by [`current_connectors`](Surface::current_connectors) and
    /// [`pending_connectors`](Surface::pending_connectors)
    type Connectors: IntoIterator<Item = connector::Handle>;
    /// Error type returned by methods of this trait
    type Error: Error + Send + 'static;

    /// Returns the underlying [`crtc`](drm::control::crtc) of this surface
    fn crtc(&self) -> crtc::Handle;
    /// Currently used [`connector`](drm::control::connector)s of this `Surface`
    fn current_connectors(&self) -> Self::Connectors;
    /// Returns the pending [`connector`](drm::control::connector)s
    /// used after the next [`commit`](RawSurface::commit) of this [`Surface`]
    ///
    /// *Note*: Only on a [`RawSurface`] you may directly trigger
    /// a [`commit`](RawSurface::commit). Other `Surface`s provide their
    /// own methods that *may* trigger a commit, you will need to read their docs.
    fn pending_connectors(&self) -> Self::Connectors;
    /// Tries to add a new [`connector`](drm::control::connector)
    /// to be used after the next commit.
    ///
    /// Fails if the `connector` is not compatible with the underlying [`crtc`](drm::control::crtc)
    /// (e.g. no suitable [`encoder`](drm::control::encoder) may be found)
    /// or is not compatible with the currently pending
    /// [`Mode`](drm::control::Mode).
    fn add_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>;
    /// Tries to mark a [`connector`](drm::control::connector)
    /// for removal on the next commit.
    fn remove_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>;
    /// Tries to replace the current connector set with the newly provided one on the next commit.
    ///
    /// Fails if one new `connector` is not compatible with the underlying [`crtc`](drm::control::crtc)
    /// (e.g. no suitable [`encoder`](drm::control::encoder) may be found)
    /// or is not compatible with the currently pending
    /// [`Mode`](drm::control::Mode).
    fn set_connectors(&self, connectors: &[connector::Handle]) -> Result<(), Self::Error>;
    /// Returns the currently active [`Mode`](drm::control::Mode)
    /// of the underlying [`crtc`](drm::control::crtc)
    /// if any.
    fn current_mode(&self) -> Option<Mode>;
    /// Returns the currently pending [`Mode`](drm::control::Mode)
    /// to be used after the next commit, if any.
    fn pending_mode(&self) -> Option<Mode>;
    /// Tries to set a new [`Mode`](drm::control::Mode)
    /// to be used after the next commit.
    ///
    /// Fails if the mode is not compatible with the underlying
    /// [`crtc`](drm::control::crtc) or any of the
    /// pending [`connector`](drm::control::connector)s.
    ///
    /// *Note*: Only on a [`RawSurface`] you may directly trigger
    /// a [`commit`](RawSurface::commit). Other [`Surface`]s provide their
    /// own methods that *may* trigger a commit, you will need to read their docs.
    fn use_mode(&self, mode: Option<Mode>) -> Result<(), Self::Error>;
}

/// An open bare crtc without any rendering abstractions
pub trait RawSurface: Surface + ControlDevice + BasicDevice {
    /// Returns true whenever any state changes are pending to be commited
    ///
    /// The following functions may trigger a pending commit:
    /// - [`add_connector`](Surface::add_connector)
    /// - [`remove_connector`](Surface::remove_connector)
    /// - [`use_mode`](Surface::use_mode)
    fn commit_pending(&self) -> bool;
    /// Commit the pending state rendering a given framebuffer.
    ///
    /// *Note*: This will trigger a full modeset on the underlying device,
    /// potentially causing some flickering. Check before performing this
    /// operation if a commit really is necessary using [`commit_pending`](RawSurface::commit_pending).
    ///
    /// This operation is not necessarily blocking until the crtc is in the desired state,
    /// but will trigger a `vblank` event once done.
    /// Make sure to [set a `DeviceHandler`](Device::set_handler) and
    /// [register the belonging `Device`](device_bind) before to receive the event in time.
    fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), <Self as Surface>::Error>;
    /// Page-flip the underlying [`crtc`](drm::control::crtc)
    /// to a new given [`framebuffer`].
    ///
    /// This will not cause the crtc to modeset.
    ///
    /// This operation is not blocking and will produce a `vblank` event once swapping is done.
    /// Make sure to [set a `DeviceHandler`](Device::set_handler) and
    /// [register the belonging `Device`](device_bind) before to receive the event in time.
    fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), SwapBuffersError>;
}

/// Trait representing open devices that *may* return a `Path`
pub trait DevPath {
    /// Returns the path of the open device if possible
    fn dev_path(&self) -> Option<PathBuf>;
}

impl<A: AsRawFd> DevPath for A {
    fn dev_path(&self) -> Option<PathBuf> {
        use std::fs;

        fs::read_link(format!("/proc/self/fd/{:?}", self.as_raw_fd())).ok()
    }
}

/// calloop source associated with a Device
pub type DrmSource<D> = Generic<SourceFd<D>>;

/// Bind a `Device` to an [`EventLoop`](calloop::EventLoop),
///
/// This will cause it to recieve events and feed them into a previously
/// set [`DeviceHandler`](DeviceHandler).
pub fn device_bind<D: Device + 'static, Data>(
    handle: &LoopHandle<Data>,
    device: D,
) -> ::std::result::Result<Source<DrmSource<D>>, InsertError<DrmSource<D>>>
where
    D: Device,
    Data: 'static,
{
    let mut source = Generic::from_fd_source(device);
    source.set_interest(Interest::READABLE);

    handle.insert_source(source, |evt, _| {
        evt.source.borrow_mut().0.process_events();
    })
}
<|endoftext|>


<commit_before>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![crate_name="bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_upper_case_globals, unused_qualifications)]

extern crate collections;

use std::cmp;
use std::f64;
use std::hash::Hash;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use std::num::Float;
use std::rand;
use collections::bitv;

#[cfg(test)]
use std::rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    bitmap: bitv::Bitv,
    bitmap_bits: u64,
    k_num: u32,
    sips: [SipHasher; 2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: usize, items_count: usize) -> Bloom {
        assert!(bitmap_size > 0 && items_count > 0);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::from_elem(bitmap_bits as usize, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: usize, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
        assert!(items_count > 0);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * Float::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
    }

/// Record the presence of an item.
    pub fn set<T>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

/// Return the number of bits in the filter
    pub fn number_of_bits(&self) -> u64 {
        self.bitmap_bits
    }

/// Return the number of hash functions used for `check` and `set`
    pub fn number_of_hash_functions(&self) -> u32 {
        self.k_num
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: usize) -> u32 {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * Float::ln(2.0f64)).ceil() as u32;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T>(&self, hashes: & mut [u64; 2],
                  item: &T, k_i: u32) -> u64 {
        if k_i < 2 {
            let sip = &self.sips[k_i as usize];
            let hash = sip.hash(item);
            hashes[k_i as usize] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::thread_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<commit_msg>Use the new trait syntax<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![crate_name="bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_upper_case_globals, unused_qualifications)]

extern crate collections;

use std::cmp;
use std::f64;
use std::hash::Hash;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use std::num::Float;
use std::rand;
use collections::bitv;

#[cfg(test)]
use std::rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    bitmap: bitv::Bitv,
    bitmap_bits: u64,
    k_num: u32,
    sips: [SipHasher; 2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: usize, items_count: usize) -> Bloom {
        assert!(bitmap_size > 0 && items_count > 0);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::from_elem(bitmap_bits as usize, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: usize, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
        assert!(items_count > 0);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * Float::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
    }

/// Record the presence of an item.
    pub fn set<T, H>(& mut self, item: T) where T: Hash<H> {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T, H>(&self, item: T) -> bool where T: Hash<H> {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T, H>(&mut self, item: T)
                               -> bool where T: Hash<H> {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

/// Return the number of bits in the filter
    pub fn number_of_bits(&self) -> u64 {
        self.bitmap_bits
    }

/// Return the number of hash functions used for `check` and `set`
    pub fn number_of_hash_functions(&self) -> u32 {
        self.k_num
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: usize) -> u32 {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * Float::ln(2.0f64)).ceil() as u32;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T, H>(&self, hashes: & mut [u64; 2],
                  item: &T, k_i: u32) -> u64 where T: Hash<H> {
        if k_i < 2 {
            let sip = &self.sips[k_i as usize];
            let hash = sip.hash(item);
            hashes[k_i as usize] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::thread_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<|endoftext|>