<commit_before>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! So Diesel is able to validate your queries at compile time,
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` or `infer_schema!` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`][]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::sql_types::Integer`]).
//! You can find all the types supported by Diesel in [the `sql_types` module](sql_types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: deserialize/trait.Queryable.html
//! [`diesel::sql_types::Integer`]: sql_types/struct.Integer.html
//! [`ToSql`]: serialize/trait.ToSql.html
//! [`FromSql`]: deserialize/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "large-tables",
            deprecated(since = "1.2.0",
                       note = "The large-tables feature has been renamed to 32-column-tables"))]
#![cfg_attr(feature = "huge-tables",
            deprecated(since = "1.2.0",
                       note = "The huge-tables feature has been renamed to 64-column-tables"))]
#![cfg_attr(feature = "x32-column-tables",
            deprecated(since = "1.2.1",
                       note = "The x32-column-tables feature has been reanmed to 32-column-tables. The x was a workaround for a bug in crates.io that has since been resolved"))]
#![cfg_attr(feature = "x64-column-tables",
            deprecated(since = "1.2.1",
                       note = "The x64-column-tables feature has been reanmed to 64-column-tables. The x was a workaround for a bug in crates.io that has since been resolved"))]
#![cfg_attr(feature = "x128-column-tables",
            deprecated(since = "1.2.1",
                       note = "The x128-column-tables feature has been reanmed to 128-column-tables. The x was a workaround for a bug in crates.io that has since been resolved"))]
#![cfg_attr(feature = "unstable", feature(specialization, try_from))]
// Built-in Lints
#![deny(warnings, missing_debug_implementations, missing_copy_implementations, missing_docs)]
// Clippy lints
#![cfg_attr(feature = "clippy", allow(unstable_features))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature = "clippy",
            allow(option_map_unwrap_or_else, option_map_unwrap_or, match_same_arms,
                  type_complexity))]
#![cfg_attr(feature = "clippy",
            warn(option_unwrap_used, result_unwrap_used, print_stdout,
                 wrong_pub_self_convention, mut_mut, non_ascii_literal, similar_names,
                 unicode_not_nfc, enum_glob_use, if_not_else, items_after_statements,
                 used_underscore_binding))]
#![cfg_attr(all(test, feature = "clippy"), allow(option_unwrap_used, result_unwrap_used))]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
// This is required to make `diesel_derives` re-export, but clippy thinks its unused
#[cfg_attr(feature = "clippy", allow(useless_attribute))]
#[allow(unused_imports)]
#[macro_use]
extern crate diesel_derives;
#[doc(hidden)]
pub use diesel_derives::*;

#[macro_use]
mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
pub mod connection;
pub mod data_types;
pub mod deserialize;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
pub mod query_dsl;
pub mod query_source;
#[cfg(feature = "r2d2")]
pub mod r2d2;
pub mod result;
pub mod serialize;
#[macro_use]
pub mod sql_types;
pub mod types;
pub mod row;
pub mod migration;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

mod type_impls;
mod util;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use helper_types::*;

    #[doc(inline)]
    pub use expression::dsl::*;
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_dsl::*;
    use super::query_dsl::methods::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as ForUpdateDsl>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.or_filter(predicate)`
    pub type OrFilter<Source, Predicate> = <Source as OrFilterDsl<Predicate>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.then_order_by(ordering)`
    pub type ThenOrderBy<Source, Ordering> = <Source as ThenOrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;

    /// Represents the return type of `.single_value()`
    pub type SingleValue<Source> = <Source as SingleValueDsl>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.
    pub use associations::{GroupedBy, Identifiable};
    pub use connection::Connection;
    #[deprecated(since = "1.1.0", note = "Explicitly `use diesel::deserialize::Queryable")]
    pub use deserialize::Queryable;
    pub use expression::{AppearsOnTable, BoxableExpression, Expression, IntoSql,
                         SelectableExpression};
    pub use expression_methods::*;
    #[doc(inline)]
    pub use insertable::Insertable;
    #[doc(hidden)]
    pub use query_dsl::GroupByDsl;
    pub use query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};

    pub use query_source::{Column, JoinTo, QuerySource, Table};
    pub use result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "postgres")]
    pub use pg::PgConnection;
    #[cfg(feature = "sqlite")]
    pub use sqlite::SqliteConnection;
    #[cfg(feature = "mysql")]
    pub use mysql::MysqlConnection;
}

pub use prelude::*;
#[doc(inline)]
pub use query_builder::debug_query;
#[doc(inline)]
pub use query_builder::functions::{delete, insert_into, insert_or_ignore_into, replace_into,
                                   select, sql_query, update};
pub use result::Error::NotFound;
<commit_msg>Re-export querybuilder::functions through dsl<commit_after>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! So Diesel is able to validate your queries at compile time,
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` or `infer_schema!` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`][]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::sql_types::Integer`]).
//! You can find all the types supported by Diesel in [the `sql_types` module](sql_types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: deserialize/trait.Queryable.html
//! [`diesel::sql_types::Integer`]: sql_types/struct.Integer.html
//! [`ToSql`]: serialize/trait.ToSql.html
//! [`FromSql`]: deserialize/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "large-tables",
            deprecated(since = "1.2.0",
                       note = "The large-tables feature has been renamed to 32-column-tables"))]
#![cfg_attr(feature = "huge-tables",
            deprecated(since = "1.2.0",
                       note = "The huge-tables feature has been renamed to 64-column-tables"))]
#![cfg_attr(feature = "x32-column-tables",
            deprecated(since = "1.2.1",
                       note = "The x32-column-tables feature has been reanmed to 32-column-tables. The x was a workaround for a bug in crates.io that has since been resolved"))]
#![cfg_attr(feature = "x64-column-tables",
            deprecated(since = "1.2.1",
                       note = "The x64-column-tables feature has been reanmed to 64-column-tables. The x was a workaround for a bug in crates.io that has since been resolved"))]
#![cfg_attr(feature = "x128-column-tables",
            deprecated(since = "1.2.1",
                       note = "The x128-column-tables feature has been reanmed to 128-column-tables. The x was a workaround for a bug in crates.io that has since been resolved"))]
#![cfg_attr(feature = "unstable", feature(specialization, try_from))]
// Built-in Lints
#![deny(warnings, missing_debug_implementations, missing_copy_implementations, missing_docs)]
// Clippy lints
#![cfg_attr(feature = "clippy", allow(unstable_features))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature = "clippy",
            allow(option_map_unwrap_or_else, option_map_unwrap_or, match_same_arms,
                  type_complexity))]
#![cfg_attr(feature = "clippy",
            warn(option_unwrap_used, result_unwrap_used, print_stdout,
                 wrong_pub_self_convention, mut_mut, non_ascii_literal, similar_names,
                 unicode_not_nfc, enum_glob_use, if_not_else, items_after_statements,
                 used_underscore_binding))]
#![cfg_attr(all(test, feature = "clippy"), allow(option_unwrap_used, result_unwrap_used))]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
// This is required to make `diesel_derives` re-export, but clippy thinks its unused
#[cfg_attr(feature = "clippy", allow(useless_attribute))]
#[allow(unused_imports)]
#[macro_use]
extern crate diesel_derives;
#[doc(hidden)]
pub use diesel_derives::*;

#[macro_use]
mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
pub mod connection;
pub mod data_types;
pub mod deserialize;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
pub mod query_dsl;
pub mod query_source;
#[cfg(feature = "r2d2")]
pub mod r2d2;
pub mod result;
pub mod serialize;
#[macro_use]
pub mod sql_types;
pub mod types;
pub mod row;
pub mod migration;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

mod type_impls;
mod util;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use helper_types::*;

    #[doc(inline)]
    pub use expression::dsl::*;

    #[doc(inline)]
    pub use query_builder::functions::{delete, insert_into, insert_or_ignore_into, replace_into,
                                       select, sql_query, update};
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_dsl::*;
    use super::query_dsl::methods::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as ForUpdateDsl>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.or_filter(predicate)`
    pub type OrFilter<Source, Predicate> = <Source as OrFilterDsl<Predicate>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.then_order_by(ordering)`
    pub type ThenOrderBy<Source, Ordering> = <Source as ThenOrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;

    /// Represents the return type of `.single_value()`
    pub type SingleValue<Source> = <Source as SingleValueDsl>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.
    pub use associations::{GroupedBy, Identifiable};
    pub use connection::Connection;
    #[deprecated(since = "1.1.0", note = "Explicitly `use diesel::deserialize::Queryable")]
    pub use deserialize::Queryable;
    pub use expression::{AppearsOnTable, BoxableExpression, Expression, IntoSql,
                         SelectableExpression};
    pub use expression_methods::*;
    #[doc(inline)]
    pub use insertable::Insertable;
    #[doc(hidden)]
    pub use query_dsl::GroupByDsl;
    pub use query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};

    pub use query_source::{Column, JoinTo, QuerySource, Table};
    pub use result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "postgres")]
    pub use pg::PgConnection;
    #[cfg(feature = "sqlite")]
    pub use sqlite::SqliteConnection;
    #[cfg(feature = "mysql")]
    pub use mysql::MysqlConnection;
}

pub use prelude::*;
#[doc(inline)]
pub use query_builder::debug_query;
#[doc(inline)]
pub use query_builder::functions::{delete, insert_into, insert_or_ignore_into, replace_into,
                                   select, sql_query, update};
pub use result::Error::NotFound;
<|endoftext|>


<commit_before>use std::char;
use std::cmp::{max, min};
use std::collections::VecDeque;
use num::{Complex, Float};
use rustty;
use rustty::{Attr, Color, Terminal, Cell, CellAccessor, HasSize};
use rustty::ui::{Alignable, Widget, VerticalAlign};
use itertools::{Itertools, EitherOrBoth};

pub struct Canvas {
    term: Terminal,
    spectrum: Widget,
    waterfall: Widget,
    history: VecDeque<Vec<f32>>,
}

impl Canvas {
    pub fn new() -> Result<Self, rustty::Error> {
        let term = try!(Terminal::new());
        let (cols, rows) = term.size();

        let spectrum_height = rows / 2;
        let waterfall_height = if rows % 2 != 0 { rows / 2 } else { rows / 2 + 1 };

        let mut spectrum = Widget::new(cols, spectrum_height);
        spectrum.valign(&term, VerticalAlign::Top, 0);

        let mut waterfall = Widget::new(cols, waterfall_height);
        waterfall.valign(&term, VerticalAlign::Bottom, 0);

        Ok(Canvas {
            term: term,
            spectrum: spectrum,
            waterfall: waterfall,
            history: VecDeque::with_capacity(waterfall_height * 2),
        })
    }

    /// Adds a spectrum to the history and draws it on the waterfall
    /// and the spectrum view.
    pub fn add_spectrum(&mut self, spec: Vec<Complex<f32>>) {
        draw_spectrum(&mut self.spectrum, &spec);

        let normalized = normalize_spectrum(&spec, 26.0);
        let averaged = normalized.chunks(2).map(|v| (v[0] + v[1]) / 2.0).collect();
        self.history.push_front(averaged);

        draw_waterfall(&mut self.waterfall, &self.history);

        self.spectrum.draw_into(&mut self.term);
        self.waterfall.draw_into(&mut self.term);
        self.term.swap_buffers().unwrap();
    }

    pub fn get_term(&mut self) -> &mut Terminal {
        &mut self.term
    }
}

fn draw_waterfall<T: CellAccessor + HasSize>(canvas: &mut T, spectra: &VecDeque<Vec<f32>>) {
    let (cols, rows) = canvas.size();
    for (row, mut specs) in (0..rows).zip(&spectra.iter().chunks_lazy(2)) {
        if let Some(upper_heights) = specs.next().map(|vec| vec.iter()) {
            match specs.next().map(|vec| vec.iter()) {
                Some(lower_heights) => {
                    for (c, heights) in (0..cols).zip(upper_heights.zip_longest(lower_heights)) {
                        let (u, l) = match heights {
                            EitherOrBoth::Both(&upper, &lower) => (upper, lower),
                            EitherOrBoth::Left(&upper) => (upper, 0.0),
                            EitherOrBoth::Right(&lower) => (0.0, lower),
                        };
                        *canvas.get_mut(c, row).unwrap() = spectrum_heights_to_waterfall_cell(u, l);
                    }
                },
                None => {
                    for (c, u) in (0..cols).zip(upper_heights) {
                        *canvas.get_mut(c, row).unwrap() = spectrum_heights_to_waterfall_cell(*u, 0.0);
                    }
                }
            }
        }
    }
}

fn spectrum_heights_to_waterfall_cell(upper: f32, lower: f32) -> Cell {
    Cell::new('▀',
              Color::Byte(color_mapping(upper)),
              Color::Byte(color_mapping(lower)),
              Attr::Default)
}

/// Assumes `f` is between 0 and 1. Anything outside of this range
/// will be clamped.
fn color_mapping(f: f32) -> u8 {
    //let lower = 16.0;
    //let upper = 231.0;
    let lower = 232.0;
    let upper = 255.0;
    let mapped = f * (upper - lower) + lower;
    if mapped < lower {
        lower as u8
    } else if mapped > upper {
        upper as u8
    } else {
        mapped as u8
    }
}

fn normalize_spectrum(spec: &[Complex<f32>], max_db: f32) -> Vec<f32> {
    // FFT shift
    let (first_half, last_half) = spec.split_at((spec.len() + 1) / 2);
    let shifted_spec = last_half.iter().chain(first_half.iter());

    // normalize and take the log
    shifted_spec.map(Complex::norm)
                .map(Float::log10)
                .map(|x| 10.0 * x)
                .map(|x| x / max_db)
                .collect()
}

// indexing is from the top of the cell
fn pixel_nums_to_braille(p1: Option<u8>, p2: Option<u8>) -> char {
    let pixel_map = [[0x01, 0x08],
                     [0x02, 0x10],
                     [0x04, 0x20],
                     [0x40, 0x80]];

    let mut c = 0;
    if let Some(p) = p1 {
        for i in p..4 {
            c |= pixel_map[i as usize][0];
        }
    }

    if let Some(p) = p2 {
        for i in p..4 {
            c |= pixel_map[i as usize][1];
        }
    }

    char::from_u32((0x2800 + c) as u32).unwrap()
}

fn fft_shift<T: Clone>(spec: &mut [T]) {
    let spec_copy = spec.to_owned();

    let (first_half, last_half) = spec_copy.split_at((spec_copy.len() + 1) / 2);
    let shifted_spec = last_half.iter().chain(first_half.iter());
    for (x, y) in spec.iter_mut().zip(shifted_spec) {
        *x = y.clone();
    }
}

fn spectrum_to_bin_heights(spec: &[Complex<f32>], dest: &mut [f32]) {
    //TODO should be plotting in log scale

    // subsample
    let mut last_idx = -1isize;
    for (i, x) in spec.iter().map(Complex::norm).enumerate() {
        if (i * dest.len() / spec.len()) as isize > last_idx {
            last_idx += 1;
            dest[last_idx as usize] = x;
        }
    }

    //TODO unnecessary allocation
    fft_shift(dest);
}

fn char_to_cell(c: char) -> Cell {
    let mut cell = Cell::with_char(c);
    cell.set_attrs(Attr::Bold);
    cell
}

fn draw_pixel_pair<T>(canvas: &mut T, col_idx: usize, p1: usize, p2: usize)
    where T: CellAccessor + HasSize
{
    let (_, rows) = canvas.size();
    let max_pixel_height = 4 * rows;

    // clamp heights
    let p1 = if p1 >= max_pixel_height { max_pixel_height - 1} else { p1 };
    let p2 = if p2 >= max_pixel_height { max_pixel_height - 1} else { p2 };

    // Reverse it, since the terminal indexing is from the top
    let p1 = max_pixel_height - p1 - 1;
    let p2 = max_pixel_height - p2 - 1;

    // cell indices
    let c1 = p1 / 4;
    let c2 = p2 / 4;

    // Fill in full height cells.
    let full_cell_char = pixel_nums_to_braille(Some(0), Some(0));
    for row_idx in max(c1, c2)..rows {
        *canvas.get_mut(col_idx, row_idx).unwrap() = char_to_cell(full_cell_char);
    }

    let left_fill_cell_char = pixel_nums_to_braille(Some(0), None);
    for row_idx in min(c1, c2)..c2 {
        *canvas.get_mut(col_idx, row_idx).unwrap() = char_to_cell(left_fill_cell_char);
    }

    let right_fill_cell_char = pixel_nums_to_braille(None, Some(0));
    for row_idx in min(c1, c2)..c1 {
        *canvas.get_mut(col_idx, row_idx).unwrap() = char_to_cell(right_fill_cell_char);
    }

    // Now fill in partial height cells.
    if c1 == c2 {
        // top pixels are in the same cell
        *canvas.get_mut(col_idx, c1).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), Some((p2 % 4) as u8)));
    } else if c1 > c2 {
        // right pixel is in a higher cell.
        *canvas.get_mut(col_idx, c1).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), Some(0)));
        *canvas.get_mut(col_idx, c2).unwrap() = char_to_cell(
            pixel_nums_to_braille(None, Some((p2 % 4) as u8)));
    } else {
        // left pixel is in a higher cell.
        *canvas.get_mut(col_idx, c1).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), None));
        *canvas.get_mut(col_idx, c2).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some(0), Some((p2 % 4) as u8)));
    }
}

fn draw_spectrum<T: CellAccessor + HasSize>(canvas: &mut T, spec: &[Complex<f32>]) {
    canvas.clear(Cell::default());
    let (num_cols, num_rows) = canvas.size();
    let pixel_height = num_rows * 4;
    let pixel_width = num_cols * 2;
    // TODO what should this value be?
    let max_height = 500.0;

    let mut bins = vec![0.0; pixel_width];
    spectrum_to_bin_heights(spec, &mut bins[..]);

    for col_idx in 0..num_cols {
        // height in float between 0 and 1.
        let h1 = bins[col_idx * 2] / max_height;
        let h2 = bins[col_idx * 2 + 1] / max_height;

        // The "pixel" height of each point.
        let p1 = (h1 * pixel_height as f32).floor() as usize;
        let p2 = (h2 * pixel_height as f32).floor() as usize;

        draw_pixel_pair(canvas, col_idx, p1, p2);
    }
}

#[cfg(test)]
mod tests {
    use super::{pixel_nums_to_braille, fft_shift, draw_pixel_pair};
    use rustty::Terminal;

    #[test]
    fn test_fft_shift_dc() {
        let len = 9;
        let mut spec = vec![0; len];
        spec[0] = 1;
        fft_shift(&mut spec[..]);
        assert_eq!(spec[len / 2], 1);
    }

    #[test]
    fn test_fft_shift_even() {
        let mut before: Vec<usize> = (0..10).collect();
        let after = vec![5, 6, 7, 8, 9, 0, 1, 2, 3, 4];
        fft_shift(&mut before[..]);
        assert_eq!(before, after);
    }

    #[test]
    fn test_pixel_nums() {
        assert_eq!(pixel_nums_to_braille(Some(0), Some(0)), '⣿');
        assert_eq!(pixel_nums_to_braille(Some(1), Some(2)), '⣦');
        assert_eq!(pixel_nums_to_braille(None, Some(3)), '⢀');
        assert_eq!(pixel_nums_to_braille(Some(2), None), '⡄');
        assert_eq!(pixel_nums_to_braille(None, None), '⠀');
    }

    #[test]
    fn test_draw_pixel_pair() {
        let mut term = Terminal::new().unwrap();

        // Test drawing with the same top cell
        draw_pixel_pair(&mut term, 0, 4, 6);
        assert_eq!(term[(0, term.rows() - 3)].ch(), ' ');
        assert_eq!(term[(0, term.rows() - 2)].ch(), '⣰');
        assert_eq!(term[(0, term.rows() - 1)].ch(), '⣿');
        term.clear().unwrap();

        // Test drawing with the top pixel in each column being in
        // different cells
        draw_pixel_pair(&mut term, 0, 4, 8);
        assert_eq!(term[(0, term.rows() - 4)].ch(), ' ');
        assert_eq!(term[(0, term.rows() - 3)].ch(), '⢀');
        assert_eq!(term[(0, term.rows() - 2)].ch(), '⣸');
        assert_eq!(term[(0, term.rows() - 1)].ch(), '⣿');
        term.clear().unwrap();

        draw_pixel_pair(&mut term, 1, 13, 2);
        assert_eq!(term[(1, term.rows() - 5)].ch(), ' ');
        assert_eq!(term[(1, term.rows() - 4)].ch(), '⡄');
        assert_eq!(term[(1, term.rows() - 3)].ch(), '⡇');
        assert_eq!(term[(1, term.rows() - 2)].ch(), '⡇');
        assert_eq!(term[(1, term.rows() - 1)].ch(), '⣷');
        term.clear().unwrap();
    }
}
<commit_msg>Changed waterfall color mapping to a custom blue scale.<commit_after>use std::char;
use std::cmp::{max, min};
use std::collections::VecDeque;
use num::{Complex, Float};
use rustty;
use rustty::{Attr, Color, Terminal, Cell, CellAccessor, HasSize};
use rustty::ui::{Alignable, Widget, VerticalAlign};
use itertools::{Itertools, EitherOrBoth};

pub struct Canvas {
    term: Terminal,
    spectrum: Widget,
    waterfall: Widget,
    history: VecDeque<Vec<f32>>,
}

impl Canvas {
    pub fn new() -> Result<Self, rustty::Error> {
        let term = try!(Terminal::new());
        let (cols, rows) = term.size();

        let spectrum_height = rows / 2;
        let waterfall_height = if rows % 2 != 0 { rows / 2 } else { rows / 2 + 1 };

        let mut spectrum = Widget::new(cols, spectrum_height);
        spectrum.valign(&term, VerticalAlign::Top, 0);

        let mut waterfall = Widget::new(cols, waterfall_height);
        waterfall.valign(&term, VerticalAlign::Bottom, 0);

        Ok(Canvas {
            term: term,
            spectrum: spectrum,
            waterfall: waterfall,
            history: VecDeque::with_capacity(waterfall_height * 2),
        })
    }

    /// Adds a spectrum to the history and draws it on the waterfall
    /// and the spectrum view.
    pub fn add_spectrum(&mut self, spec: Vec<Complex<f32>>) {
        draw_spectrum(&mut self.spectrum, &spec);

        let normalized = normalize_spectrum(&spec, 50.0);
        let averaged = normalized.chunks(2).map(|v| (v[0] + v[1]) / 2.0).collect();
        self.history.push_front(averaged);

        draw_waterfall(&mut self.waterfall, &self.history);

        self.spectrum.draw_into(&mut self.term);
        self.waterfall.draw_into(&mut self.term);
        self.term.swap_buffers().unwrap();
    }

    pub fn get_term(&mut self) -> &mut Terminal {
        &mut self.term
    }
}

fn draw_waterfall<T: CellAccessor + HasSize>(canvas: &mut T, spectra: &VecDeque<Vec<f32>>) {
    let (cols, rows) = canvas.size();
    for (row, mut specs) in (0..rows).zip(&spectra.iter().chunks_lazy(2)) {
        if let Some(upper_heights) = specs.next().map(|vec| vec.iter()) {
            match specs.next().map(|vec| vec.iter()) {
                Some(lower_heights) => {
                    for (c, heights) in (0..cols).zip(upper_heights.zip_longest(lower_heights)) {
                        let (u, l) = match heights {
                            EitherOrBoth::Both(&upper, &lower) => (upper, lower),
                            EitherOrBoth::Left(&upper) => (upper, 0.0),
                            EitherOrBoth::Right(&lower) => (0.0, lower),
                        };
                        *canvas.get_mut(c, row).unwrap() = spectrum_heights_to_waterfall_cell(u, l);
                    }
                },
                None => {
                    for (c, u) in (0..cols).zip(upper_heights) {
                        *canvas.get_mut(c, row).unwrap() = spectrum_heights_to_waterfall_cell(*u, 0.0);
                    }
                }
            }
        }
    }
}

fn spectrum_heights_to_waterfall_cell(upper: f32, lower: f32) -> Cell {
    Cell::new('▀',
              Color::Byte(color_mapping(upper)),
              Color::Byte(color_mapping(lower)),
              Attr::Default)
}

/// Assumes `f` is between 0 and 1. Anything outside of this range
/// will be clamped.
fn color_mapping(f: f32) -> u8 {
    let mapping = [16, 17, 18, 19, 21, 27, 33, 39, 45, 51,
                   50, 49, 48, 47, 46, 82, 118, 154, 190, 226];
    let idx = (f * (mapping.len() as f32)) as i32;
    if idx < 0 {
        mapping[0]
    } else if idx >= mapping.len() as i32 {
        mapping[mapping.len() - 1]
    } else {
        mapping[idx as usize]
    }
    //let lower = 232.0;
    //let upper = 255.0;
    //let mapped = f * (upper - lower) + lower;
    //if mapped < lower {
        //lower as u8
    //} else if mapped > upper {
        //upper as u8
    //} else {
        //mapped as u8
    //}
}

fn normalize_spectrum(spec: &[Complex<f32>], max_db: f32) -> Vec<f32> {
    // FFT shift
    let (first_half, last_half) = spec.split_at((spec.len() + 1) / 2);
    let shifted_spec = last_half.iter().chain(first_half.iter());

    // normalize and take the log
    shifted_spec.map(Complex::norm)
                .map(Float::log10)
                .map(|x| 10.0 * x)
                .map(|x| x / max_db)
                .collect()
}

// indexing is from the top of the cell
fn pixel_nums_to_braille(p1: Option<u8>, p2: Option<u8>) -> char {
    let pixel_map = [[0x01, 0x08],
                     [0x02, 0x10],
                     [0x04, 0x20],
                     [0x40, 0x80]];

    let mut c = 0;
    if let Some(p) = p1 {
        for i in p..4 {
            c |= pixel_map[i as usize][0];
        }
    }

    if let Some(p) = p2 {
        for i in p..4 {
            c |= pixel_map[i as usize][1];
        }
    }

    char::from_u32((0x2800 + c) as u32).unwrap()
}

fn fft_shift<T: Clone>(spec: &mut [T]) {
    let spec_copy = spec.to_owned();

    let (first_half, last_half) = spec_copy.split_at((spec_copy.len() + 1) / 2);
    let shifted_spec = last_half.iter().chain(first_half.iter());
    for (x, y) in spec.iter_mut().zip(shifted_spec) {
        *x = y.clone();
    }
}

fn spectrum_to_bin_heights(spec: &[Complex<f32>], dest: &mut [f32]) {
    //TODO should be plotting in log scale

    // subsample
    let mut last_idx = -1isize;
    for (i, x) in spec.iter().map(Complex::norm).enumerate() {
        if (i * dest.len() / spec.len()) as isize > last_idx {
            last_idx += 1;
            dest[last_idx as usize] = x;
        }
    }

    //TODO unnecessary allocation
    fft_shift(dest);
}

fn char_to_cell(c: char) -> Cell {
    let mut cell = Cell::with_char(c);
    cell.set_attrs(Attr::Bold);
    cell
}

fn draw_pixel_pair<T>(canvas: &mut T, col_idx: usize, p1: usize, p2: usize)
    where T: CellAccessor + HasSize
{
    let (_, rows) = canvas.size();
    let max_pixel_height = 4 * rows;

    // clamp heights
    let p1 = if p1 >= max_pixel_height { max_pixel_height - 1} else { p1 };
    let p2 = if p2 >= max_pixel_height { max_pixel_height - 1} else { p2 };

    // Reverse it, since the terminal indexing is from the top
    let p1 = max_pixel_height - p1 - 1;
    let p2 = max_pixel_height - p2 - 1;

    // cell indices
    let c1 = p1 / 4;
    let c2 = p2 / 4;

    // Fill in full height cells.
    let full_cell_char = pixel_nums_to_braille(Some(0), Some(0));
    for row_idx in max(c1, c2)..rows {
        *canvas.get_mut(col_idx, row_idx).unwrap() = char_to_cell(full_cell_char);
    }

    let left_fill_cell_char = pixel_nums_to_braille(Some(0), None);
    for row_idx in min(c1, c2)..c2 {
        *canvas.get_mut(col_idx, row_idx).unwrap() = char_to_cell(left_fill_cell_char);
    }

    let right_fill_cell_char = pixel_nums_to_braille(None, Some(0));
    for row_idx in min(c1, c2)..c1 {
        *canvas.get_mut(col_idx, row_idx).unwrap() = char_to_cell(right_fill_cell_char);
    }

    // Now fill in partial height cells.
    if c1 == c2 {
        // top pixels are in the same cell
        *canvas.get_mut(col_idx, c1).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), Some((p2 % 4) as u8)));
    } else if c1 > c2 {
        // right pixel is in a higher cell.
        *canvas.get_mut(col_idx, c1).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), Some(0)));
        *canvas.get_mut(col_idx, c2).unwrap() = char_to_cell(
            pixel_nums_to_braille(None, Some((p2 % 4) as u8)));
    } else {
        // left pixel is in a higher cell.
        *canvas.get_mut(col_idx, c1).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), None));
        *canvas.get_mut(col_idx, c2).unwrap() = char_to_cell(
            pixel_nums_to_braille(Some(0), Some((p2 % 4) as u8)));
    }
}

fn draw_spectrum<T: CellAccessor + HasSize>(canvas: &mut T, spec: &[Complex<f32>]) {
    canvas.clear(Cell::default());
    let (num_cols, num_rows) = canvas.size();
    let pixel_height = num_rows * 4;
    let pixel_width = num_cols * 2;
    // TODO what should this value be?
    let max_height = 500.0;

    let mut bins = vec![0.0; pixel_width];
    spectrum_to_bin_heights(spec, &mut bins[..]);

    for col_idx in 0..num_cols {
        // height in float between 0 and 1.
        let h1 = bins[col_idx * 2] / max_height;
        let h2 = bins[col_idx * 2 + 1] / max_height;

        // The "pixel" height of each point.
        let p1 = (h1 * pixel_height as f32).floor() as usize;
        let p2 = (h2 * pixel_height as f32).floor() as usize;

        draw_pixel_pair(canvas, col_idx, p1, p2);
    }
}

#[cfg(test)]
mod tests {
    use super::{pixel_nums_to_braille, fft_shift, draw_pixel_pair};
    use rustty::Terminal;

    #[test]
    fn test_fft_shift_dc() {
        let len = 9;
        let mut spec = vec![0; len];
        spec[0] = 1;
        fft_shift(&mut spec[..]);
        assert_eq!(spec[len / 2], 1);
    }

    #[test]
    fn test_fft_shift_even() {
        let mut before: Vec<usize> = (0..10).collect();
        let after = vec![5, 6, 7, 8, 9, 0, 1, 2, 3, 4];
        fft_shift(&mut before[..]);
        assert_eq!(before, after);
    }

    #[test]
    fn test_pixel_nums() {
        assert_eq!(pixel_nums_to_braille(Some(0), Some(0)), '⣿');
        assert_eq!(pixel_nums_to_braille(Some(1), Some(2)), '⣦');
        assert_eq!(pixel_nums_to_braille(None, Some(3)), '⢀');
        assert_eq!(pixel_nums_to_braille(Some(2), None), '⡄');
        assert_eq!(pixel_nums_to_braille(None, None), '⠀');
    }

    #[test]
    fn test_draw_pixel_pair() {
        let mut term = Terminal::new().unwrap();

        // Test drawing with the same top cell
        draw_pixel_pair(&mut term, 0, 4, 6);
        assert_eq!(term[(0, term.rows() - 3)].ch(), ' ');
        assert_eq!(term[(0, term.rows() - 2)].ch(), '⣰');
        assert_eq!(term[(0, term.rows() - 1)].ch(), '⣿');
        term.clear().unwrap();

        // Test drawing with the top pixel in each column being in
        // different cells
        draw_pixel_pair(&mut term, 0, 4, 8);
        assert_eq!(term[(0, term.rows() - 4)].ch(), ' ');
        assert_eq!(term[(0, term.rows() - 3)].ch(), '⢀');
        assert_eq!(term[(0, term.rows() - 2)].ch(), '⣸');
        assert_eq!(term[(0, term.rows() - 1)].ch(), '⣿');
        term.clear().unwrap();

        draw_pixel_pair(&mut term, 1, 13, 2);
        assert_eq!(term[(1, term.rows() - 5)].ch(), ' ');
        assert_eq!(term[(1, term.rows() - 4)].ch(), '⡄');
        assert_eq!(term[(1, term.rows() - 3)].ch(), '⡇');
        assert_eq!(term[(1, term.rows() - 2)].ch(), '⡇');
        assert_eq!(term[(1, term.rows() - 1)].ch(), '⣷');
        term.clear().unwrap();
    }
}
<|endoftext|>


<commit_before>#![allow(unsafe_code)]
#![allow(clippy::match_like_matches_macro)]

/// This module started its life as crossbeam-epoch,
/// and was imported into the sled codebase to perform
/// a number of use-case specific runtime tests and
/// dynamic collection for when garbage spikes happen.
/// Unused functionality was stripped which further
/// improved compile times.
mod atomic;
mod collector;
mod deferred;
mod epoch;
mod internal;
mod list;
mod queue;

pub(crate) use self::{
    atomic::{Atomic, Owned, Shared},
    collector::pin,
};

use deferred::Deferred;
use internal::Local;

pub struct Guard {
    pub(super) local: *const Local,
    #[cfg(feature = "testing")]
    pub(super) began: std::time::Instant,
}

impl Guard {
    pub(crate) fn defer<F, R>(&self, f: F)
    where
        F: FnOnce() -> R + Send + 'static,
    {
        unsafe {
            self.defer_unchecked(f);
        }
    }

    pub(super) unsafe fn defer_unchecked<F, R>(&self, f: F)
    where
        F: FnOnce() -> R,
    {
        if let Some(local) = self.local.as_ref() {
            local.defer(Deferred::new(move || drop(f())), self);
        } else {
            drop(f());
        }
    }

    pub(crate) unsafe fn defer_destroy<T>(&self, ptr: Shared<'_, T>) {
        self.defer_unchecked(move || ptr.into_owned());
    }

    pub fn flush(&self) {
        if let Some(local) = unsafe { self.local.as_ref() } {
            local.flush(self);
        }
    }
}

impl Drop for Guard {
    #[inline]
    fn drop(&mut self) {
        if let Some(local) = unsafe { self.local.as_ref() } {
            local.unpin();
        }

        #[cfg(feature = "testing")]
        {
            if self.began.elapsed() > std::time::Duration::from_secs(1) {
                panic!("guard lived longer than allowed");
            }
        }
    }
}

#[inline]
unsafe fn unprotected() -> &'static Guard {
    // HACK(stjepang): An unprotected guard is just a `Guard` with its field `local` set to null.
    // Since this function returns a `'static` reference to a `Guard`, we must return a reference
    // to a global guard. However, it's not possible to create a `static` `Guard` because it does
    // not implement `Sync`. To get around the problem, we create a static `usize` initialized to
    // zero and then transmute it into a `Guard`. This is safe because `usize` and `Guard`
    // (consisting of a single pointer) have the same representation in memory.
    static UNPROTECTED: usize = 0;
    #[allow(trivial_casts)]
    &*(&UNPROTECTED as *const _ as *const Guard)
}
<commit_msg>Avoid unprotected UB when items are added to Guard for testing<commit_after>#![allow(unsafe_code)]
#![allow(clippy::match_like_matches_macro)]

/// This module started its life as crossbeam-epoch,
/// and was imported into the sled codebase to perform
/// a number of use-case specific runtime tests and
/// dynamic collection for when garbage spikes happen.
/// Unused functionality was stripped which further
/// improved compile times.
mod atomic;
mod collector;
mod deferred;
mod epoch;
mod internal;
mod list;
mod queue;

pub(crate) use self::{
    atomic::{Atomic, Owned, Shared},
    collector::pin,
};

use deferred::Deferred;
use internal::Local;

pub struct Guard {
    pub(super) local: *const Local,
    #[cfg(feature = "testing")]
    pub(super) began: std::time::Instant,
}

impl Guard {
    pub(crate) fn defer<F, R>(&self, f: F)
    where
        F: FnOnce() -> R + Send + 'static,
    {
        unsafe {
            self.defer_unchecked(f);
        }
    }

    pub(super) unsafe fn defer_unchecked<F, R>(&self, f: F)
    where
        F: FnOnce() -> R,
    {
        if let Some(local) = self.local.as_ref() {
            local.defer(Deferred::new(move || drop(f())), self);
        } else {
            drop(f());
        }
    }

    pub(crate) unsafe fn defer_destroy<T>(&self, ptr: Shared<'_, T>) {
        self.defer_unchecked(move || ptr.into_owned());
    }

    pub fn flush(&self) {
        if let Some(local) = unsafe { self.local.as_ref() } {
            local.flush(self);
        }
    }
}

impl Drop for Guard {
    #[inline]
    fn drop(&mut self) {
        if let Some(local) = unsafe { self.local.as_ref() } {
            local.unpin();
        }

        #[cfg(feature = "testing")]
        {
            if self.began.elapsed() > std::time::Duration::from_secs(1) {
                panic!("guard lived longer than allowed");
            }
        }
    }
}

#[inline]
unsafe fn unprotected() -> &'static Guard {
    // HACK(stjepang): An unprotected guard is just a `Guard` with its field `local` set to null.
    // Since this function returns a `'static` reference to a `Guard`, we must return a reference
    // to a global guard. However, it's not possible to create a `static` `Guard` because it does
    // not implement `Sync`. To get around the problem, we create a static `usize` initialized to
    // zero and then transmute it into a `Guard`. This is safe because `usize` and `Guard`
    // (consisting of a single pointer) have the same representation in memory.
    static UNPROTECTED: &[u8] = &[0; std::mem::size_of::<Guard>()];
    #[allow(trivial_casts)]
    &*(UNPROTECTED as *const _ as *const Guard)
}
<|endoftext|>


<commit_before>use memory::Memory;

/// Wraps another `Memory` and discards all writes.
pub struct ReadOnlyMemory(Box<Memory>);

impl ReadOnlyMemory {
    pub fn new(m: Box<Memory>) -> ReadOnlyMemory {
        ReadOnlyMemory(m)
    }
}

impl Memory for ReadOnlyMemory {
    fn get(&self, addr: usize) -> i32 {
        self.0.get(addr)
    }

    #[inline]
    fn set(&mut self, _: usize, _: i32) {}

    #[inline]
    fn size(&self) -> usize {
        self.0.size()
    }
}

#[cfg(test)]
mod tests {
    use memory::{Memory, SliceMemory};

    #[test]
    fn read() {
        let sm = Box::new(SliceMemory::from_slice(Box::new([0, 1, 2, 3])));
        let m = super::ReadOnlyMemory::new(sm);
        assert_eq!(m.get(0), 0);
        assert_eq!(m.get(3), 3);
    }

    #[test]
    fn write() {
        let sm = SliceMemory::from_slice(Box::new([0, 1, 2, 3]));
        let mut m = super::ReadOnlyMemory::new(Box::new(sm));
        m.set(0, 9);
        assert_eq!(m.get(0), 0);
        m.set(3, 4);
        assert_eq!(m.get(3), 3);
    }

    #[test]
    fn size() {
        let sm = SliceMemory::from_slice(Box::new([0, 1, 2, 3]));
        let m = super::ReadOnlyMemory::new(Box::new(sm));
        assert_eq!(m.size(), 4);
    }
}
<commit_msg>docs(readonlymemory): Update documentation<commit_after>//! Make a memory read-only.
use memory::Memory;

/// Wraps another `Memory` and discards all writes.
pub struct ReadOnlyMemory(Box<Memory>);

impl ReadOnlyMemory {
    pub fn new(m: Box<Memory>) -> ReadOnlyMemory {
        ReadOnlyMemory(m)
    }
}

impl Memory for ReadOnlyMemory {
    fn get(&self, addr: usize) -> i32 {
        self.0.get(addr)
    }

    #[inline]
    fn set(&mut self, _: usize, _: i32) {}

    #[inline]
    fn size(&self) -> usize {
        self.0.size()
    }
}

#[cfg(test)]
mod tests {
    use memory::{Memory, SliceMemory};

    #[test]
    fn read() {
        let sm = Box::new(SliceMemory::from_slice(Box::new([0, 1, 2, 3])));
        let m = super::ReadOnlyMemory::new(sm);
        assert_eq!(m.get(0), 0);
        assert_eq!(m.get(3), 3);
    }

    #[test]
    fn write() {
        let sm = SliceMemory::from_slice(Box::new([0, 1, 2, 3]));
        let mut m = super::ReadOnlyMemory::new(Box::new(sm));
        m.set(0, 9);
        assert_eq!(m.get(0), 0);
        m.set(3, 4);
        assert_eq!(m.get(3), 3);
    }

    #[test]
    fn size() {
        let sm = SliceMemory::from_slice(Box::new([0, 1, 2, 3]));
        let m = super::ReadOnlyMemory::new(Box::new(sm));
        assert_eq!(m.size(), 4);
    }
}
<|endoftext|>


<commit_before>use super::prelude::*;

use conduit_cookie::RequestSession;
use diesel::prelude::*;

use crate::db::RequestTransaction;
use crate::util::errors::{std_error, CargoResult, ChainError, Unauthorized};

use crate::models::User;
use crate::schema::users;

#[derive(Debug, Clone, Copy)]
pub struct CurrentUser;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum AuthenticationSource {
    SessionCookie,
    ApiToken { auth_header: String },
}

impl Middleware for CurrentUser {
    fn before(&self, req: &mut dyn Request) -> Result<(), Box<dyn Error + Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = {
            req.session()
                .get("user_id")
                .and_then(|s| s.parse::<i32>().ok())
        };

        let conn = req.db_conn().map_err(std_error)?;

        if let Some(id) = id {
            // If it did, look for a user in the database with the given `user_id`
            let maybe_user = users::table.find(id).first::<User>(&*conn);
            drop(conn);
            if let Ok(user) = maybe_user {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions()
                    .insert(AuthenticationSource::SessionCookie);
            }
        } else {
            // Otherwise, look for an `Authorization` header on the request
            // and try to find a user in the database with a matching API token
            let user_auth = if let Some(headers) = req.headers().find("Authorization") {
                let auth_header = headers[0].to_string();

                User::find_by_api_token(&conn, &auth_header)
                    .map(|user| (AuthenticationSource::ApiToken { auth_header }, user))
                    .optional()
                    .map_err(|e| return Box::new(e) as Box<dyn Error + Send>)?
            } else {
                None
            };

            drop(conn);

            if let Some((api_token, user)) = user_auth {
                // Attach the `User` model from the database and the API token to the request
                req.mut_extensions().insert(user);
                req.mut_extensions().insert(api_token);
            }
        }

        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
    fn authentication_source(&self) -> CargoResult<AuthenticationSource>;
}

impl<'a> RequestUser for dyn Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions()
            .find::<User>()
            .chain_error(|| Unauthorized)
    }

    fn authentication_source(&self) -> CargoResult<AuthenticationSource> {
        self.extensions()
            .find::<AuthenticationSource>()
            .cloned()
            .chain_error(|| Unauthorized)
    }
}
<commit_msg>Fix clippy errors that I introduced while resolving merge conflicts<commit_after>use super::prelude::*;

use conduit_cookie::RequestSession;
use diesel::prelude::*;

use crate::db::RequestTransaction;
use crate::util::errors::{std_error, CargoResult, ChainError, Unauthorized};

use crate::models::User;
use crate::schema::users;

#[derive(Debug, Clone, Copy)]
pub struct CurrentUser;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum AuthenticationSource {
    SessionCookie,
    ApiToken { auth_header: String },
}

impl Middleware for CurrentUser {
    fn before(&self, req: &mut dyn Request) -> Result<(), Box<dyn Error + Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = {
            req.session()
                .get("user_id")
                .and_then(|s| s.parse::<i32>().ok())
        };

        let conn = req.db_conn().map_err(std_error)?;

        if let Some(id) = id {
            // If it did, look for a user in the database with the given `user_id`
            let maybe_user = users::table.find(id).first::<User>(&*conn);
            drop(conn);
            if let Ok(user) = maybe_user {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions()
                    .insert(AuthenticationSource::SessionCookie);
            }
        } else {
            // Otherwise, look for an `Authorization` header on the request
            // and try to find a user in the database with a matching API token
            let user_auth = if let Some(headers) = req.headers().find("Authorization") {
                let auth_header = headers[0].to_string();

                User::find_by_api_token(&conn, &auth_header)
                    .map(|user| (AuthenticationSource::ApiToken { auth_header }, user))
                    .optional()
                    .map_err(|e| Box::new(e) as Box<dyn Error + Send>)?
            } else {
                None
            };

            drop(conn);

            if let Some((api_token, user)) = user_auth {
                // Attach the `User` model from the database and the API token to the request
                req.mut_extensions().insert(user);
                req.mut_extensions().insert(api_token);
            }
        }

        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
    fn authentication_source(&self) -> CargoResult<AuthenticationSource>;
}

impl<'a> RequestUser for dyn Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions()
            .find::<User>()
            .chain_error(|| Unauthorized)
    }

    fn authentication_source(&self) -> CargoResult<AuthenticationSource> {
        self.extensions()
            .find::<AuthenticationSource>()
            .cloned()
            .chain_error(|| Unauthorized)
    }
}
<|endoftext|>


<commit_before>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    reply: *const api::Reply
}

impl Reply {
    unsafe fn new(reply: *const api::Reply) -> Reply {
        Reply {
            reply: reply
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /* TODO: Move to IoResult using context.err */
    pub fn exec(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise transmute the void pointer memory into a pointer
                 * to a reply structure and return it. */
                Some(Reply::new(transmute(result)))
            }
        })
    }
}

impl Drop for Redis {
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<commit_msg>Free Replies<commit_after>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    reply: *const api::Reply
}

impl Reply {
    unsafe fn new(reply: *const api::Reply) -> Reply {
        Reply {
            reply: reply
        }
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            api::freeReplyObject(transmute(self.reply))
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /* TODO: Move to IoResult using context.err */
    pub fn exec(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise transmute the void pointer memory into a pointer
                 * to a reply structure and return it. */
                Some(Reply::new(transmute(result)))
            }
        })
    }
}

impl Drop for Redis {
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<|endoftext|>


<commit_before>extern crate pulldown_cmark as cmark;
extern crate mustache;

pub mod escape;
pub mod parser;
pub mod ast_to_md;
pub mod html;
pub mod cleaner;
pub mod token;
pub mod error;
pub mod book;

pub use html::HtmlRenderer;
pub use parser::Parser;
pub use token::Token;
pub use cleaner::Cleaner;
pub use cleaner::French;
pub use error::{Result, Error};
pub use book::Book;
<commit_msg>forgot to add lib.rs in previous commit (thanks Travis for telling me)<commit_after>extern crate pulldown_cmark as cmark;
extern crate mustache;
extern crate zip;
extern crate chrono;
extern crate uuid;

pub mod escape;
pub mod parser;
pub mod ast_to_md;
pub mod html;
pub mod cleaner;
pub mod token;
pub mod error;
pub mod book;
pub mod epub;

pub use html::HtmlRenderer;
pub use parser::Parser;
pub use token::Token;
pub use cleaner::Cleaner;
pub use cleaner::French;
pub use error::{Result, Error};
pub use book::Book;
pub use epub::EpubRenderer;
<|endoftext|>


<commit_before>
use libc;
use libc::{
    c_void,
    c_long,
    size_t,
};
use std;
use std::num::FromPrimitive;
use ffi;
use {
    Face,
    FtResult,
};

extern "C" fn alloc_library(_memory: ffi::FT_Memory, size: c_long) -> *mut c_void {
    unsafe {
        libc::malloc(size as size_t)
    }
}

extern "C" fn free_library(_memory: ffi::FT_Memory, block: *mut c_void) {
    unsafe {
        libc::free(block)
    }
}

extern "C" fn realloc_library(_memory: ffi::FT_Memory,
                              _cur_size: c_long,
                              new_size: c_long,
                              block: *mut c_void) -> *mut c_void {
    unsafe {
        libc::realloc(block, new_size as size_t)
    }
}

static MEMORY: ffi::FT_MemoryRec = ffi::FT_MemoryRec {
    user: 0 as *mut c_void,
    alloc: alloc_library,
    free: free_library,
    realloc: realloc_library,
};

pub struct Library {
    raw: ffi::FT_Library,
}

impl Library {
    pub fn init() -> FtResult<Library> {
        unsafe {
            let mut raw = std::ptr::null_mut();

            let err = ffi::FT_New_Library(&MEMORY, &mut raw);
            if err == ffi::FT_Err_Ok {
                ffi::FT_Add_Default_Modules(raw);
                Ok(Library {
                    raw: raw,
                })
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_face(&self, filepathname: &str, face_index: ffi::FT_Long) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();

            let path_str = filepathname.to_c_str();

            let err = ffi::FT_New_Face(self.raw, path_str.as_ptr(), face_index, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_memory_face(&self, buffer: &[u8], face_index: ffi::FT_Long) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();
            let err = ffi::FT_New_Memory_Face(self.raw, buffer.as_ptr(), buffer.len() as ffi::FT_Long, face_index, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn raw(&self) -> ffi::FT_Library {
        self.raw
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        unsafe {
            let err = ffi::FT_Done_Library(self.raw);
            if err != ffi::FT_Err_Ok {
                std::io::println(format!("Failed to drop Library. Error Code: {}", err).as_slice());
            }
        }
    }
}

<commit_msg>Moved `MEMORY` to local variable in `Library::init`<commit_after>
use libc;
use libc::{
    c_void,
    c_long,
    size_t,
};
use std;
use std::num::FromPrimitive;
use ffi;
use {
    Face,
    FtResult,
};

extern "C" fn alloc_library(_memory: ffi::FT_Memory, size: c_long) -> *mut c_void {
    unsafe {
        libc::malloc(size as size_t)
    }
}

extern "C" fn free_library(_memory: ffi::FT_Memory, block: *mut c_void) {
    unsafe {
        libc::free(block)
    }
}

extern "C" fn realloc_library(_memory: ffi::FT_Memory,
                              _cur_size: c_long,
                              new_size: c_long,
                              block: *mut c_void) -> *mut c_void {
    unsafe {
        libc::realloc(block, new_size as size_t)
    }
}

pub struct Library {
    raw: ffi::FT_Library,
}

impl Library {
    pub fn init() -> FtResult<Library> {
        let memory = ffi::FT_MemoryRec {
            user: 0 as *mut c_void,
            alloc: alloc_library,
            free: free_library,
            realloc: realloc_library,
        };
        unsafe {
            let mut raw = std::ptr::null_mut();

            let err = ffi::FT_New_Library(&memory, &mut raw);
            if err == ffi::FT_Err_Ok {
                ffi::FT_Add_Default_Modules(raw);
                Ok(Library {
                    raw: raw,
                })
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_face(&self, filepathname: &str, face_index: ffi::FT_Long) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();

            let path_str = filepathname.to_c_str();

            let err = ffi::FT_New_Face(self.raw, path_str.as_ptr(), face_index, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_memory_face(&self, buffer: &[u8], face_index: ffi::FT_Long) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();
            let err = ffi::FT_New_Memory_Face(self.raw, buffer.as_ptr(), buffer.len() as ffi::FT_Long, face_index, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn raw(&self) -> ffi::FT_Library {
        self.raw
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        unsafe {
            let err = ffi::FT_Done_Library(self.raw);
            if err != ffi::FT_Err_Ok {
                std::io::println(format!("Failed to drop Library. Error Code: {}", err).as_slice());
            }
        }
    }
}

<|endoftext|>


<commit_before>use rustc_serialize::json::Json;

#[derive(Debug)]
pub enum FieldType {
    String,
    Binary,
    Number{bits: u8, is_float: bool},
    Boolean,
    Date,
}

impl Default for FieldType {
    fn default() -> FieldType { FieldType::String }
}

#[derive(Debug)]
pub struct FieldMapping {
    data_type: FieldType,
    is_indexed: bool,
    is_stored: bool,
    is_in_all: bool,
    boost: f64,
}

impl Default for FieldMapping {
    fn default() -> FieldMapping {
        FieldMapping {
            data_type: FieldType::default(),
            is_indexed: true,
            is_stored: false,
            is_in_all: true,
            boost: 1.0f64,
        }
    }
}

fn parse_boolean(json: &Json) -> bool {
    match *json {
        Json::Boolean(val) => val,
        Json::String(ref s) => {
            match s.as_ref() {
                "yes" => true,
                "no" => false,
                _ => {
                    println!("bad boolean value {:?}", s);
                    false
                }
            }
        }
        _ => {
            // TODO: Raise error
            println!("bad boolean value {:?}", json);
            false
        }
    }
}

impl FieldMapping {
    pub fn from_json(json: &Json) -> FieldMapping {
        let json = json.as_object().unwrap();
        let mut field_mapping = FieldMapping::default();

        for (key, value) in json.iter() {
            match key.as_ref() {
                "type" => {
                    let type_name = value.as_string().unwrap();

                    field_mapping.data_type = match type_name.as_ref() {
                        "string" => FieldType::String,
                        "integer" => FieldType::Number{bits: 64, is_float: false},
                        "boolean" => FieldType::Boolean,
                        "date" => FieldType::Date,
                        _ => {
                            // TODO; make this an error
                            println!("unimplemented type name! {}", type_name);
                            FieldType::default()
                        }
                    };
                }
                "index" => {
                    let index = value.as_string().unwrap();
                    if index == "not_analyzed" {
                        field_mapping.is_indexed = false;
                    } else {
                        // TODO: Implement other variants and make this an error
                        println!("unimplemented index setting! {}", index);
                    }
                }
                "index_analyzer" => {
                    // TODO
                }
                "boost" => {
                    field_mapping.boost = value.as_f64().unwrap();
                }
                "store" => {
                    field_mapping.is_stored = parse_boolean(value);
                }
                "include_in_all" => {
                    field_mapping.is_in_all = parse_boolean(value);
                }
                _ => println!("unimplemented field mapping key! {}", key)
            }

        }

        field_mapping
    }
}
<commit_msg>bits => size<commit_after>use rustc_serialize::json::Json;

#[derive(Debug)]
pub enum FieldType {
    String,
    Binary,
    Number{size: u8, is_float: bool},
    Boolean,
    Date,
}

impl Default for FieldType {
    fn default() -> FieldType { FieldType::String }
}

#[derive(Debug)]
pub struct FieldMapping {
    data_type: FieldType,
    is_indexed: bool,
    is_stored: bool,
    is_in_all: bool,
    boost: f64,
}

impl Default for FieldMapping {
    fn default() -> FieldMapping {
        FieldMapping {
            data_type: FieldType::default(),
            is_indexed: true,
            is_stored: false,
            is_in_all: true,
            boost: 1.0f64,
        }
    }
}

fn parse_boolean(json: &Json) -> bool {
    match *json {
        Json::Boolean(val) => val,
        Json::String(ref s) => {
            match s.as_ref() {
                "yes" => true,
                "no" => false,
                _ => {
                    println!("bad boolean value {:?}", s);
                    false
                }
            }
        }
        _ => {
            // TODO: Raise error
            println!("bad boolean value {:?}", json);
            false
        }
    }
}

impl FieldMapping {
    pub fn from_json(json: &Json) -> FieldMapping {
        let json = json.as_object().unwrap();
        let mut field_mapping = FieldMapping::default();

        for (key, value) in json.iter() {
            match key.as_ref() {
                "type" => {
                    let type_name = value.as_string().unwrap();

                    field_mapping.data_type = match type_name.as_ref() {
                        "string" => FieldType::String,
                        "integer" => FieldType::Number{size: 64, is_float: false},
                        "boolean" => FieldType::Boolean,
                        "date" => FieldType::Date,
                        _ => {
                            // TODO; make this an error
                            println!("unimplemented type name! {}", type_name);
                            FieldType::default()
                        }
                    };
                }
                "index" => {
                    let index = value.as_string().unwrap();
                    if index == "not_analyzed" {
                        field_mapping.is_indexed = false;
                    } else {
                        // TODO: Implement other variants and make this an error
                        println!("unimplemented index setting! {}", index);
                    }
                }
                "index_analyzer" => {
                    // TODO
                }
                "boost" => {
                    field_mapping.boost = value.as_f64().unwrap();
                }
                "store" => {
                    field_mapping.is_stored = parse_boolean(value);
                }
                "include_in_all" => {
                    field_mapping.is_in_all = parse_boolean(value);
                }
                _ => println!("unimplemented field mapping key! {}", key)
            }

        }

        field_mapping
    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json::{self, DecoderError};
use rustc_serialize::{Decodable, Decoder};
use std::fmt;

use user::User;
use channel::Channel;

#[derive(Debug, Clone)]
pub struct Message {
    pub ts: Option<String>,
    pub text: Option<String>,
    pub user: Option<User>,
    pub channel: Option<Channel>,
    pub event_type: Option<String>,// TODO Enum
    pub user_id: Option<String>,
    pub channel_id: Option<String>,
    // payload: String

}

impl Message {
    pub fn new_from_str(payload: &str) -> Result<Message, DecoderError> {
        json::decode::<Message>(payload)
    }
}

impl Decodable for Message {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Message, D::Error> {
        decoder.read_struct("root", 0, |decoder| {
            Ok(Message {
                event_type: try!(decoder.read_struct_field("type", 0, |decoder| Decodable::decode(decoder))),
                user_id: try!(decoder.read_struct_field("user", 0, |decoder| Decodable::decode(decoder))),
                text: try!(decoder.read_struct_field("text", 0, |decoder| Decodable::decode(decoder))),
                ts: try!(decoder.read_struct_field("ts", 0, |decoder| Decodable::decode(decoder))),
                channel_id: try!(decoder.read_struct_field("channel", 0, |decoder| Decodable::decode(decoder))),
                channel: None,
                user: None
            })
        })
    }
}

// Temporary method for debugging purposes.
// Rendering is not the job of the message.
impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO This is weird.
        let formatted = match self.event_type.as_ref().unwrap_or(&"".to_string()).as_ref() {
            "message" => self.fmt_as_message(),
            _         => self.fmt_as_debug(),
        };
        write!(f, "{}", formatted)
    }
}

impl Message {
    fn fmt_as_message(&self) -> String {
        let channel: &Channel = self.channel.as_ref().unwrap();
        let user: &User = self.user.as_ref().unwrap();
        format!("{channel} - {user}: {message}", channel=channel.name, user=user.name, message=self.text.as_ref().unwrap() )
    }

    fn fmt_as_debug(&self) -> String {
        format!("DEBUG: {:?}", &self)
    }
}

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

    #[test]
    fn test_decode_from_json() {
        let json = "{
            \"type\": \"message\",
            \"user\": \"Timon\",
            \"text\": \"Bananas!\",
            \"ts\": \"today\",
            \"channel\": \"banter\"
        }";
        let message = Message::new_from_str(json).unwrap();
        assert_eq!(message.event_type.unwrap(), "message");
        assert_eq!(message.user_id.unwrap(), "Timon");
        assert_eq!(message.channel_id.unwrap(), "banter");
        assert_eq!(message.text.unwrap(), "Bananas!");
        assert_eq!(message.ts.unwrap(), "today");
    }

    #[test]
    fn test_missing_values() {
        let json = "{
            \"user\": \"Timon\",
            \"text\": \"Bananas!\",
            \"ts\": null
        }";
        let message = Message::new_from_str(json).unwrap();
        assert_eq!(message.event_type, None);
        assert_eq!(message.user_id.unwrap(), "Timon");
        assert_eq!(message.channel_id, None);
        assert_eq!(message.text.unwrap(), "Bananas!");
        assert_eq!(message.ts, None);

    }
}

<commit_msg>Better printing of messages<commit_after>use rustc_serialize::json::{self, DecoderError};
use rustc_serialize::{Decodable, Decoder};
use std::fmt;

use user::User;
use channel::Channel;

#[derive(Debug, Clone)]
pub struct Message {
    pub ts: Option<String>,
    pub text: Option<String>,
    pub user: Option<User>,
    pub channel: Option<Channel>,
    pub event_type: Option<String>,// TODO Enum
    pub user_id: Option<String>,
    pub channel_id: Option<String>,
    // payload: String

}

impl Message {
    pub fn new_from_str(payload: &str) -> Result<Message, DecoderError> {
        json::decode::<Message>(payload)
    }
}

impl Decodable for Message {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Message, D::Error> {
        decoder.read_struct("root", 0, |decoder| {
            Ok(Message {
                event_type: try!(decoder.read_struct_field("type", 0, |decoder| Decodable::decode(decoder))),
                user_id: try!(decoder.read_struct_field("user", 0, |decoder| Decodable::decode(decoder))),
                text: try!(decoder.read_struct_field("text", 0, |decoder| Decodable::decode(decoder))),
                ts: try!(decoder.read_struct_field("ts", 0, |decoder| Decodable::decode(decoder))),
                channel_id: try!(decoder.read_struct_field("channel", 0, |decoder| Decodable::decode(decoder))),
                channel: None,
                user: None
            })
        })
    }
}

// Temporary method for debugging purposes.
// Rendering is not the job of the message.
impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO This is weird.
        let formatted = match self.event_type.as_ref().unwrap_or(&"".to_string()).as_ref() {
            "message" => self.fmt_as_message(),
            _         => self.fmt_as_debug(),
        };
        write!(f, "{}", formatted)
    }
}

impl Message {
    fn fmt_as_message(&self) -> String {
        let user: &User = self.user.as_ref().unwrap();
        format!("{user}: {message}", user=user.name, message=self.text.as_ref().unwrap() )
    }

    fn fmt_as_debug(&self) -> String {
        format!("DEBUG: {:?}", &self);
    }
}

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

    #[test]
    fn test_decode_from_json() {
        let json = "{
            \"type\": \"message\",
            \"user\": \"Timon\",
            \"text\": \"Bananas!\",
            \"ts\": \"today\",
            \"channel\": \"banter\"
        }";
        let message = Message::new_from_str(json).unwrap();
        assert_eq!(message.event_type.unwrap(), "message");
        assert_eq!(message.user_id.unwrap(), "Timon");
        assert_eq!(message.channel_id.unwrap(), "banter");
        assert_eq!(message.text.unwrap(), "Bananas!");
        assert_eq!(message.ts.unwrap(), "today");
    }

    #[test]
    fn test_missing_values() {
        let json = "{
            \"user\": \"Timon\",
            \"text\": \"Bananas!\",
            \"ts\": null
        }";
        let message = Message::new_from_str(json).unwrap();
        assert_eq!(message.event_type, None);
        assert_eq!(message.user_id.unwrap(), "Timon");
        assert_eq!(message.channel_id, None);
        assert_eq!(message.text.unwrap(), "Bananas!");
        assert_eq!(message.ts, None);

    }
}

<|endoftext|>


<commit_before>use libc::{c_char, c_int};

use {raw, Buf, Error, IntoCString};
use util::Binding;

/// Clean up a message, removing extraneous whitespace, and ensure that the
/// message ends with a newline. If comment_char is Some, also remove comment
/// lines starting with that character.
pub fn message_prettify<T: IntoCString>(message: T, comment_char: Option<u8>) -> Result<String, Error> {
    let ret = Buf::new();
    let message = try!(message.into_c_string());
    unsafe {
        try_call!(raw::git_message_prettify(ret.raw(), message, comment_char.is_some() as c_int, comment_char.unwrap_or(0) as c_char));
    }
    Ok(ret.as_str().unwrap().to_string())
}

/// The default comment character for message_prettify ('#')
pub const DEFAULT_COMMENT_CHAR: Option<u8> = Some('#' as u8);

#[cfg(test)]
mod tests {
    use {message_prettify, DEFAULT_COMMENT_CHAR};

    #[test]
    fn prettify() {
        // This does not attempt to duplicate the extensive tests for
        // git_message_prettify in libgit2, just a few representative values to
        // make sure the interface works as expected.
        assert_eq!(message_prettify("1\n\n\n2", None).unwrap(), "1\n\n2\n");
        assert_eq!(message_prettify("1\n\n\n2\n\n\n3", None).unwrap(), "1\n\n2\n\n3\n");
        assert_eq!(message_prettify("1\n# comment\n# more", None).unwrap(), "1\n# comment\n# more\n");
        assert_eq!(message_prettify("1\n# comment\n# more", DEFAULT_COMMENT_CHAR).unwrap(), "1\n");
        assert_eq!(message_prettify("1\n; comment\n; more", Some(';' as u8)).unwrap(), "1\n");
    }
}
<commit_msg>Clean up a small bit of style<commit_after>use std::ffi::CString;

use libc::{c_char, c_int};

use {raw, Buf, Error, IntoCString};
use util::Binding;

/// Clean up a message, removing extraneous whitespace, and ensure that the
/// message ends with a newline. If comment_char is Some, also remove comment
/// lines starting with that character.
pub fn message_prettify<T: IntoCString>(message: T, comment_char: Option<u8>)
                                        -> Result<String, Error> {
    _message_prettify(try!(message.into_c_string()), comment_char)
}

fn _message_prettify(message: CString, comment_char: Option<u8>)
                     -> Result<String, Error> {
    let ret = Buf::new();
    unsafe {
        try_call!(raw::git_message_prettify(ret.raw(), message,
                                            comment_char.is_some() as c_int,
                                            comment_char.unwrap_or(0) as c_char));
    }
    Ok(ret.as_str().unwrap().to_string())
}

/// The default comment character for message_prettify ('#')
pub const DEFAULT_COMMENT_CHAR: Option<u8> = Some('#' as u8);

#[cfg(test)]
mod tests {
    use {message_prettify, DEFAULT_COMMENT_CHAR};

    #[test]
    fn prettify() {
        // This does not attempt to duplicate the extensive tests for
        // git_message_prettify in libgit2, just a few representative values to
        // make sure the interface works as expected.
        assert_eq!(message_prettify("1\n\n\n2", None).unwrap(),
                   "1\n\n2\n");
        assert_eq!(message_prettify("1\n\n\n2\n\n\n3", None).unwrap(),
                   "1\n\n2\n\n3\n");
        assert_eq!(message_prettify("1\n# comment\n# more", None).unwrap(),
                   "1\n# comment\n# more\n");
        assert_eq!(message_prettify("1\n# comment\n# more",
                                    DEFAULT_COMMENT_CHAR).unwrap(),
                   "1\n");
        assert_eq!(message_prettify("1\n; comment\n; more",
                                    Some(';' as u8)).unwrap(),
                   "1\n");
    }
}
<|endoftext|>


<commit_before>mod user;

use self::user::ChatUser;

#[derive(Debug)]
pub struct ChatMessage {
	pub sender: ChatUser,
	pub value: String,
}
<commit_msg>Fix multifile failure<commit_after>use ChatUser;

#[derive(Debug)]
pub struct ChatMessage {
	pub sender: ChatUser,
	pub value: String,
}
<|endoftext|>