<commit_before>use quote::{Tokens, ToTokens};
use syn::{Body, Field, VariantData, MacroInput};
use utils::{number_idents, get_field_types, field_idents, numbered_vars};

/// Provides the hook to expand `#[derive(Constructor)]` into an implementation of `Constructor`
pub fn expand(input: &MacroInput, _: &str) -> Tokens {
    match input.body {
        Body::Struct(VariantData::Tuple(ref fields)) => tuple_constructor(input, fields),
        Body::Struct(VariantData::Struct(ref fields)) => struct_constructor(input, fields),
        _ => panic!("Only structs can derive a constructor"),
    }
}

fn constructor_impl<T: ToTokens>(input: &MacroInput, fields: &Vec<Field>, body: T) -> Tokens {
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
    let input_type = &input.ident;
    let original_types = &get_field_types(fields);
    let vars = &numbered_vars(fields.len(), "");
    quote!{
        impl#impl_generics #input_type#ty_generics #where_clause {
            #[allow(unused_parens)]
            fn new(#(#vars: #original_types),*) -> #input_type#ty_generics {
                let original = (#(#vars),*);
                #body
            }
        }
    }
}

fn tuple_constructor(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = tuple_body(input_type, fields);
    constructor_impl(input, fields, body)
}

fn tuple_body<T: ToTokens>(return_type: T, fields: &Vec<Field>) -> Tokens {
    if fields.len() == 1 {
        quote!(#return_type(original))
    } else {
        let field_names = &number_idents(fields.len());
        quote!(#return_type(#(original.#field_names),*))
    }
}

fn struct_constructor(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = struct_body(input_type, fields);
    constructor_impl(input, fields, body)
}

fn struct_body<T: ToTokens>(return_type: T, fields: &Vec<Field>) -> Tokens {
    if fields.len() == 1 {
        let field_name = &fields[0].ident;
        quote!(#return_type{#field_name: original})
    } else {
        let argument_field_names = &number_idents(fields.len());
        let field_names = &field_idents(fields);
        quote!(#return_type{#(#field_names: original.#argument_field_names),*})
    }
}
<commit_msg>Constructor: Cleanup constructor code<commit_after>use quote::{Tokens, ToTokens};
use syn::{Body, Ident, Field, VariantData, MacroInput};
use utils::{number_idents, get_field_types, field_idents, numbered_vars};

/// Provides the hook to expand `#[derive(Constructor)]` into an implementation of `Constructor`
pub fn expand(input: &MacroInput, _: &str) -> Tokens {
    let input_type = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
    let ((body, vars), fields) = match input.body {
        Body::Struct(VariantData::Tuple(ref fields)) => (tuple_body(input_type, fields), fields),
        Body::Struct(VariantData::Struct(ref fields)) => (struct_body(input_type, fields), fields),
        _ => panic!("Only structs can derive a constructor"),
    };
    let original_types = &get_field_types(fields);
    quote!{
        impl#impl_generics #input_type#ty_generics #where_clause {
            fn new(#(#vars: #original_types),*) -> #input_type#ty_generics {
                #body
            }
        }
    }
}

fn tuple_body(return_type: &Ident, fields: &Vec<Field>) -> (Tokens, Vec<Ident>) {
    let vars = &numbered_vars(fields.len(), "");
    (quote!(#return_type(#(#vars),*)), vars.clone())
}

fn struct_body(return_type: &Ident, fields: &Vec<Field>) -> (Tokens, Vec<Ident>) {
    let field_names: &Vec<Ident> = &field_idents(fields).iter().map(|f| (*f).clone()).collect();
    let vars = field_names;
    (quote!(#return_type{#(#field_names: #vars),*}), vars.clone())
}
<|endoftext|>


<commit_before>use std::mem;
use std::f64;

use itertools::Itertools;
use ndarray::prelude::*;
use bit_vec::BitVec;
use ordered_float::NotNaN;
use ndarray_rand::RandomExt;
use rand::distributions::Range;

use bio::stats::{Prob, LogProb};

use io::codebook::Codebook;

pub type Readout = BitVec;

pub fn estimate<I: Iterator<Item=(String, Readout)>>(
    codebook: &Codebook,
    readouts: I
) -> (Vec<Prob>, Vec<Prob>) {
    let max_diff = 0.001;
    let shape = (codebook.len(), codebook.N as usize);

    let mut observed_01_errors = Array2::from_elem(shape, 0.0);
    let mut observed_10_errors = Array2::from_elem(shape, 0.0);
    let mut feat_count = Array2::from_elem((codebook.len(), 1), 0.0);
    for (feat, readout) in readouts {
        let feature_id = codebook.get_id(&feat);
        let encoding = codebook.record(feature_id).codeword();

        // count features
        feat_count[(feature_id, 0)] += 1.0;

        for k in 0..codebook.N as usize {
            if encoding[k] == false {
                // count 01 errors
                if readout[k] == true {
                    observed_01_errors[(feature_id, k)] += 1.0;
                }
            } else {
                // count 10 errors
                if readout[k] == false {
                    observed_10_errors[(feature_id, k)] += 1.0;
                }
            }
        }
    }

    // calculate observed (joint) error rates
    let observed_p0 = observed_01_errors / &feat_count;
    let observed_p1 = observed_10_errors / &feat_count;

    // run EM algorithm to estimate error rates
    let mut prob_no_error = Array2::from_elem(
        (codebook.len(), codebook.N as usize), LogProb::ln_one()
    );

    let mut p0 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
    let mut p1 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));

    let mut p0_last = Array1::from_elem(codebook.N as usize, 0.0);
    let mut p1_last = Array1::from_elem(codebook.N as usize, 0.0);
    for i in 0..1000 {
        // E-step: estimate probability to have no errors in rest of readout
        for feature_id in 0..codebook.len() {
            let encoding = codebook.record(feature_id).codeword();
            for k in 0..codebook.N as usize {
                let p = LogProb((0..codebook.N as usize).filter_map(|l| {
                    if l != k {
                        let p_err = if encoding[l] == false {
                            p0[k]
                        } else {
                            p1[k]
                        };
                        Some(*LogProb((p_err as f64).ln()).ln_one_minus_exp())
                    } else { None }
                }).sum());
                prob_no_error[(feature_id, k)] = p;
            }
        }

        // M-step: find p0 and p1 that maximizes the likelihood
        mem::swap(&mut p0, &mut p0_last);
        mem::swap(&mut p1, &mut p1_last);
        for k in 0..codebook.N as usize {
            // solve least squares: take mean of all estimates
            let p = |observed_p: &Array2<f64>, bit: bool| {
                let mut count = 0.0;
                let p = (0..codebook.len()).filter_map(|feature_id| {
                    let encoding = codebook.record(feature_id).codeword();
                    if feat_count[(feature_id, 0)] < 10.0 || encoding[k] != bit {
                        None
                    } else {
                        count += 1.0;
                        let p = observed_p[(feature_id, k)] * prob_no_error[(feature_id, k)].exp();
                        Some(p)
                    }
                }).sum::<f64>() / count;
                if count == 0.0 {
                    panic!("not enough counts to estimate error rate");
                }
                p
            };
            //debug!("----------- p0 ------------");
            p0[k] = p(&observed_p0, false);
            //debug!("DEBUG: p0={}", p0[k]);
            //debug!("----------- p1 ------------");
            p1[k] = p(&observed_p1, true);
            //debug!("DEBUG: p1={}", p1[k]);
        }

        // check convergence
        let abs = |d: &f64| NotNaN::new(d.abs()).unwrap();
        //debug!("{:?}", p0);
        let convergence = p0.all_close(&p0_last, max_diff) && p1.all_close(&p1_last, max_diff);

        if convergence && i >= 5 {
            debug!("convergence reached");
            debug!("{:?}", p1);
            break;
        }

        debug!("EM-algorithm step {} of {}.", i + 1, 100);
    }

    (
        p0.iter().map(|p| Prob(*p)).collect_vec(),
        p1.iter().map(|p| Prob(*p)).collect_vec()
    )
}
<commit_msg>Require at least 50 counts per feature.<commit_after>use std::mem;
use std::f64;

use itertools::Itertools;
use ndarray::prelude::*;
use bit_vec::BitVec;
use ordered_float::NotNaN;
use ndarray_rand::RandomExt;
use rand::distributions::Range;

use bio::stats::{Prob, LogProb};

use io::codebook::Codebook;

pub type Readout = BitVec;

pub fn estimate<I: Iterator<Item=(String, Readout)>>(
    codebook: &Codebook,
    readouts: I
) -> (Vec<Prob>, Vec<Prob>) {
    let max_diff = 0.001;
    let shape = (codebook.len(), codebook.N as usize);

    let mut observed_01_errors = Array2::from_elem(shape, 0.0);
    let mut observed_10_errors = Array2::from_elem(shape, 0.0);
    let mut feat_count = Array2::from_elem((codebook.len(), 1), 0.0);
    for (feat, readout) in readouts {
        let feature_id = codebook.get_id(&feat);
        let encoding = codebook.record(feature_id).codeword();

        // count features
        feat_count[(feature_id, 0)] += 1.0;

        for k in 0..codebook.N as usize {
            if encoding[k] == false {
                // count 01 errors
                if readout[k] == true {
                    observed_01_errors[(feature_id, k)] += 1.0;
                }
            } else {
                // count 10 errors
                if readout[k] == false {
                    observed_10_errors[(feature_id, k)] += 1.0;
                }
            }
        }
    }

    // calculate observed (joint) error rates
    let observed_p0 = observed_01_errors / &feat_count;
    let observed_p1 = observed_10_errors / &feat_count;

    // run EM algorithm to estimate error rates
    let mut prob_no_error = Array2::from_elem(
        (codebook.len(), codebook.N as usize), LogProb::ln_one()
    );

    let mut p0 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
    let mut p1 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));

    let mut p0_last = Array1::from_elem(codebook.N as usize, 0.0);
    let mut p1_last = Array1::from_elem(codebook.N as usize, 0.0);
    for i in 0..1000 {
        // E-step: estimate probability to have no errors in rest of readout
        for feature_id in 0..codebook.len() {
            let encoding = codebook.record(feature_id).codeword();
            for k in 0..codebook.N as usize {
                let p = LogProb((0..codebook.N as usize).filter_map(|l| {
                    if l != k {
                        let p_err = if encoding[l] == false {
                            p0[k]
                        } else {
                            p1[k]
                        };
                        Some(*LogProb((p_err as f64).ln()).ln_one_minus_exp())
                    } else { None }
                }).sum());
                prob_no_error[(feature_id, k)] = p;
            }
        }

        // M-step: find p0 and p1 that maximizes the likelihood
        mem::swap(&mut p0, &mut p0_last);
        mem::swap(&mut p1, &mut p1_last);
        for k in 0..codebook.N as usize {
            // solve least squares: take mean of all estimates
            let p = |observed_p: &Array2<f64>, bit: bool| {
                let mut count = 0.0;
                let p = (0..codebook.len()).filter_map(|feature_id| {
                    let encoding = codebook.record(feature_id).codeword();
                    if feat_count[(feature_id, 0)] < 50.0 || encoding[k] != bit {
                        None
                    } else {
                        count += 1.0;
                        let p = observed_p[(feature_id, k)] * prob_no_error[(feature_id, k)].exp();
                        Some(p)
                    }
                }).sum::<f64>() / count;
                if count == 0.0 {
                    panic!("not enough counts to estimate error rate");
                }
                p
            };
            //debug!("----------- p0 ------------");
            p0[k] = p(&observed_p0, false);
            //debug!("DEBUG: p0={}", p0[k]);
            //debug!("----------- p1 ------------");
            p1[k] = p(&observed_p1, true);
            //debug!("DEBUG: p1={}", p1[k]);
        }

        // check convergence
        let abs = |d: &f64| NotNaN::new(d.abs()).unwrap();
        //debug!("{:?}", p0);
        let convergence = p0.all_close(&p0_last, max_diff) && p1.all_close(&p1_last, max_diff);

        if convergence && i >= 5 {
            debug!("convergence reached");
            debug!("{:?}", p1);
            break;
        }

        debug!("EM-algorithm step {} of {}.", i + 1, 100);
    }

    (
        p0.iter().map(|p| Prob(*p)).collect_vec(),
        p1.iter().map(|p| Prob(*p)).collect_vec()
    )
}
<|endoftext|>


<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;
mod debug_query;
mod delete_statement;
mod distinct_clause;
#[doc(hidden)]
pub mod functions;
mod group_by_clause;
mod insert_statement;
mod limit_clause;
pub(crate) mod locking_clause;
#[doc(hidden)]
pub mod nodes;
mod offset_clause;
mod order_clause;
mod returning_clause;
mod select_clause;
mod select_statement;
mod sql_query;
mod update_statement;
#[cfg(any(feature = "sqlite", feature = "postgres"))]
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(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(crate) use self::insert_statement::ColumnList;
#[cfg(any(feature = "postgres", feature = "sqlite"))]
pub(crate) use self::insert_statement::InsertFromSelect;
#[cfg(feature = "sqlite")]
pub(crate) use self::where_clause::WhereClause;

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

    /// 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(()),
        }
    }
}

/// 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>Remove unneeded reexport<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;
mod debug_query;
mod delete_statement;
mod distinct_clause;
#[doc(hidden)]
pub mod functions;
mod group_by_clause;
mod insert_statement;
mod limit_clause;
pub(crate) mod locking_clause;
#[doc(hidden)]
pub mod nodes;
mod offset_clause;
mod order_clause;
mod returning_clause;
mod select_clause;
mod select_statement;
mod sql_query;
mod update_statement;
#[cfg(any(feature = "sqlite", feature = "postgres"))]
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(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(crate) use self::insert_statement::ColumnList;
#[cfg(any(feature = "postgres", feature = "sqlite"))]
pub(crate) use self::insert_statement::InsertFromSelect;

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

    /// 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(()),
        }
    }
}

/// 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 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#![allow(dead_code)]

use entids;
use errors::*;
use types::{Attribute, Entid, EntidMap, IdentMap, Schema, SchemaMap, TypedValue, ValueType};

/// Return `Ok(())` if `schema_map` defines a valid Mentat schema.
fn validate_schema_map(entid_map: &EntidMap, schema_map: &SchemaMap) -> Result<()> {
    for (entid, attribute) in schema_map {
        let ident = entid_map.get(entid).ok_or(ErrorKind::BadSchemaAssertion(format!("Could not get ident for entid: {}", entid)))?;

        if attribute.unique_identity && !attribute.unique_value {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/unique :db/unique_identity without :db/unique :db/unique_value for entid: {}", ident)))
        }
        if attribute.fulltext && attribute.value_type != ValueType::String {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/fulltext true without :db/valueType :db.type/string for entid: {}", ident)))
        }
        if attribute.component && attribute.value_type != ValueType::Ref {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/isComponent true without :db/valueType :db.type/ref for entid: {}", ident)))
        }
        // TODO: consider warning if we have :db/index true for :db/valueType :db.type/string,
        // since this may be inefficient.  More generally, we should try to drive complex
        // :db/valueType (string, uri, json in the future) users to opt-in to some hash-indexing
        // scheme, as discussed in https://github.com/mozilla/mentat/issues/69.
    }
    Ok(())
}

impl Schema {
    pub fn get_ident(&self, x: &Entid) -> Option<&String> {
        self.entid_map.get(x)
    }

    pub fn get_entid(&self, x: &String) -> Option<&Entid> {
        self.ident_map.get(x)
    }

    pub fn attribute_for_entid(&self, x: &Entid) -> Option<&Attribute> {
        self.schema_map.get(x)
    }

    pub fn require_ident(&self, entid: &Entid) -> Result<&String> {
        self.get_ident(&entid).ok_or(ErrorKind::UnrecognizedEntid(*entid).into())
    }

    pub fn require_entid(&self, ident: &String) -> Result<&Entid> {
        self.get_entid(&ident).ok_or(ErrorKind::UnrecognizedIdent(ident.clone()).into())
    }

    pub fn require_attribute_for_entid(&self, entid: &Entid) -> Result<&Attribute> {
        self.attribute_for_entid(entid).ok_or(ErrorKind::UnrecognizedEntid(*entid).into())
    }

    /// Create a valid `Schema` from the constituent maps.
    pub fn from(ident_map: IdentMap, schema_map: SchemaMap) -> Result<Schema> {
        let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (v.clone(), k.clone())).collect();

        validate_schema_map(&entid_map, &schema_map)?;

        Ok(Schema {
            ident_map: ident_map,
            entid_map: entid_map,
            schema_map: schema_map,
        })
    }

    /// Turn vec![(String(:ident), String(:key), TypedValue(:value)), ...] into a Mentat `Schema`.
    pub fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
        where U: IntoIterator<Item=(String, String, TypedValue)>{
        let mut schema_map = SchemaMap::new();
        for (ref symbolic_ident, ref symbolic_attr, ref value) in assertions.into_iter() {
            let ident: i64 = *ident_map.get(symbolic_ident).ok_or(ErrorKind::UnrecognizedIdent(symbolic_ident.clone()))?;
            let attr: i64 = *ident_map.get(symbolic_attr).ok_or(ErrorKind::UnrecognizedIdent(symbolic_attr.clone()))?;
            let attributes = schema_map.entry(ident).or_insert(Attribute::default());

            // TODO: improve error messages throughout.
            match attr {
                entids::DB_VALUE_TYPE => {
                    match *value {
                        TypedValue::Ref(entids::DB_TYPE_REF) => { attributes.value_type = ValueType::Ref; },
                        TypedValue::Ref(entids::DB_TYPE_BOOLEAN) => { attributes.value_type = ValueType::Boolean; },
                        TypedValue::Ref(entids::DB_TYPE_LONG) => { attributes.value_type = ValueType::Long; },
                        TypedValue::Ref(entids::DB_TYPE_STRING) => { attributes.value_type = ValueType::String; },
                        TypedValue::Ref(entids::DB_TYPE_KEYWORD) => { attributes.value_type = ValueType::Keyword; },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/valueType :db.type/*] but got [... :db/valueType {:?}] for ident '{}' and attribute '{}'", value, ident, attr)))
                    }
                },

                entids::DB_CARDINALITY => {
                    match *value {
                        TypedValue::Ref(entids::DB_CARDINALITY_MANY) => { attributes.multival = true; },
                        TypedValue::Ref(entids::DB_CARDINALITY_ONE) => { attributes.multival = false; },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/cardinality :db.cardinality/many|:db.cardinality/one] but got [... :db/cardinality {:?}]", value)))
                    }
                },

                entids::DB_UNIQUE => {
                    match *value {
                        TypedValue::Ref(entids::DB_UNIQUE_VALUE) => { attributes.unique_value = true; },
                        TypedValue::Ref(entids::DB_UNIQUE_IDENTITY) => {
                            attributes.unique_value = true;
                            attributes.unique_identity = true;
                        },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/unique :db.unique/value|:db.unique/identity] but got [... :db/unique {:?}]", value)))
                    }
                },

                entids::DB_INDEX => {
                    match *value {
                        TypedValue::Boolean(x) => { attributes.index = x },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/index true|false] but got [... :db/index {:?}]", value)))
                    }
                },

                entids::DB_FULLTEXT => {
                    match *value {
                        TypedValue::Boolean(x) => {
                            attributes.fulltext = x;
                            if attributes.fulltext {
                                attributes.index = true;
                            }
                        },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/fulltext true|false] but got [... :db/fulltext {:?}]", value)))
                    }
                },

                entids::DB_IS_COMPONENT => {
                    match *value {
                        TypedValue::Boolean(x) => { attributes.component = x },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/isComponent true|false] but got [... :db/isComponent {:?}]", value)))
                    }
                },

                entids::DB_DOC => {
                    // Nothing for now.
                },

                entids::DB_IDENT => {
                    // Nothing for now.
                },

                entids::DB_INSTALL_ATTRIBUTE => {
                    // Nothing for now.
                },

                _ => {
                    bail!(ErrorKind::BadSchemaAssertion(format!("Do not recognize attribute '{}' for ident '{}'", attr, ident)))
                }
            }
        };

        Schema::from(ident_map.clone(), schema_map)
    }
}
<commit_msg>Ensure :db/index true for :db/unique _. Fixes #254. r=nalexander (#267)<commit_after>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#![allow(dead_code)]

use entids;
use errors::*;
use types::{Attribute, Entid, EntidMap, IdentMap, Schema, SchemaMap, TypedValue, ValueType};

/// Return `Ok(())` if `schema_map` defines a valid Mentat schema.
fn validate_schema_map(entid_map: &EntidMap, schema_map: &SchemaMap) -> Result<()> {
    for (entid, attribute) in schema_map {
        let ident = entid_map.get(entid).ok_or(ErrorKind::BadSchemaAssertion(format!("Could not get ident for entid: {}", entid)))?;

        if attribute.unique_value && !attribute.index {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/unique :db/unique_value true without :db/index true for entid: {}", ident)))
        }

        if attribute.unique_identity && !attribute.unique_value {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/unique :db/unique_identity without :db/unique :db/unique_value for entid: {}", ident)))
        }
        if attribute.fulltext && attribute.value_type != ValueType::String {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/fulltext true without :db/valueType :db.type/string for entid: {}", ident)))
        }
        if attribute.component && attribute.value_type != ValueType::Ref {
            bail!(ErrorKind::BadSchemaAssertion(format!(":db/isComponent true without :db/valueType :db.type/ref for entid: {}", ident)))
        }
        // TODO: consider warning if we have :db/index true for :db/valueType :db.type/string,
        // since this may be inefficient.  More generally, we should try to drive complex
        // :db/valueType (string, uri, json in the future) users to opt-in to some hash-indexing
        // scheme, as discussed in https://github.com/mozilla/mentat/issues/69.
    }
    Ok(())
}

impl Schema {
    pub fn get_ident(&self, x: &Entid) -> Option<&String> {
        self.entid_map.get(x)
    }

    pub fn get_entid(&self, x: &String) -> Option<&Entid> {
        self.ident_map.get(x)
    }

    pub fn attribute_for_entid(&self, x: &Entid) -> Option<&Attribute> {
        self.schema_map.get(x)
    }

    pub fn require_ident(&self, entid: &Entid) -> Result<&String> {
        self.get_ident(&entid).ok_or(ErrorKind::UnrecognizedEntid(*entid).into())
    }

    pub fn require_entid(&self, ident: &String) -> Result<&Entid> {
        self.get_entid(&ident).ok_or(ErrorKind::UnrecognizedIdent(ident.clone()).into())
    }

    pub fn require_attribute_for_entid(&self, entid: &Entid) -> Result<&Attribute> {
        self.attribute_for_entid(entid).ok_or(ErrorKind::UnrecognizedEntid(*entid).into())
    }

    /// Create a valid `Schema` from the constituent maps.
    pub fn from(ident_map: IdentMap, schema_map: SchemaMap) -> Result<Schema> {
        let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (v.clone(), k.clone())).collect();

        validate_schema_map(&entid_map, &schema_map)?;

        Ok(Schema {
            ident_map: ident_map,
            entid_map: entid_map,
            schema_map: schema_map,
        })
    }

    /// Turn vec![(String(:ident), String(:key), TypedValue(:value)), ...] into a Mentat `Schema`.
    pub fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
        where U: IntoIterator<Item=(String, String, TypedValue)>{
        let mut schema_map = SchemaMap::new();
        for (ref symbolic_ident, ref symbolic_attr, ref value) in assertions.into_iter() {
            let ident: i64 = *ident_map.get(symbolic_ident).ok_or(ErrorKind::UnrecognizedIdent(symbolic_ident.clone()))?;
            let attr: i64 = *ident_map.get(symbolic_attr).ok_or(ErrorKind::UnrecognizedIdent(symbolic_attr.clone()))?;
            let attributes = schema_map.entry(ident).or_insert(Attribute::default());

            // TODO: improve error messages throughout.
            match attr {
                entids::DB_VALUE_TYPE => {
                    match *value {
                        TypedValue::Ref(entids::DB_TYPE_REF) => { attributes.value_type = ValueType::Ref; },
                        TypedValue::Ref(entids::DB_TYPE_BOOLEAN) => { attributes.value_type = ValueType::Boolean; },
                        TypedValue::Ref(entids::DB_TYPE_LONG) => { attributes.value_type = ValueType::Long; },
                        TypedValue::Ref(entids::DB_TYPE_STRING) => { attributes.value_type = ValueType::String; },
                        TypedValue::Ref(entids::DB_TYPE_KEYWORD) => { attributes.value_type = ValueType::Keyword; },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/valueType :db.type/*] but got [... :db/valueType {:?}] for ident '{}' and attribute '{}'", value, ident, attr)))
                    }
                },

                entids::DB_CARDINALITY => {
                    match *value {
                        TypedValue::Ref(entids::DB_CARDINALITY_MANY) => { attributes.multival = true; },
                        TypedValue::Ref(entids::DB_CARDINALITY_ONE) => { attributes.multival = false; },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/cardinality :db.cardinality/many|:db.cardinality/one] but got [... :db/cardinality {:?}]", value)))
                    }
                },

                entids::DB_UNIQUE => {
                    match *value {
                        TypedValue::Ref(entids::DB_UNIQUE_VALUE) => {
                            attributes.unique_value = true;
                            attributes.index = true;
                        },
                        TypedValue::Ref(entids::DB_UNIQUE_IDENTITY) => {
                            attributes.unique_value = true;
                            attributes.unique_identity = true;
                            attributes.index = true;
                        },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/unique :db.unique/value|:db.unique/identity] but got [... :db/unique {:?}]", value)))
                    }
                },

                entids::DB_INDEX => {
                    match *value {
                        TypedValue::Boolean(x) => { attributes.index = x },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/index true|false] but got [... :db/index {:?}]", value)))
                    }
                },

                entids::DB_FULLTEXT => {
                    match *value {
                        TypedValue::Boolean(x) => {
                            attributes.fulltext = x;
                            if attributes.fulltext {
                                attributes.index = true;
                            }
                        },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/fulltext true|false] but got [... :db/fulltext {:?}]", value)))
                    }
                },

                entids::DB_IS_COMPONENT => {
                    match *value {
                        TypedValue::Boolean(x) => { attributes.component = x },
                        _ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/isComponent true|false] but got [... :db/isComponent {:?}]", value)))
                    }
                },

                entids::DB_DOC => {
                    // Nothing for now.
                },

                entids::DB_IDENT => {
                    // Nothing for now.
                },

                entids::DB_INSTALL_ATTRIBUTE => {
                    // Nothing for now.
                },

                _ => {
                    bail!(ErrorKind::BadSchemaAssertion(format!("Do not recognize attribute '{}' for ident '{}'", attr, ident)))
                }
            }
        };

        Schema::from(ident_map.clone(), schema_map)
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use super::{AppError, InternalAppErrorStatic};
use crate::util::{json_response, AppResponse};

use chrono::NaiveDateTime;
use conduit::{header, StatusCode};

/// Generates a response with the provided status and description as JSON
fn json_error(detail: &str, status: StatusCode) -> AppResponse {
    let json = json!({ "errors": [{ "detail": detail }] });

    let mut response = json_response(&json);
    *response.status_mut() = status;
    response
}

// The following structs are emtpy and do not provide a custom message to the user

#[derive(Debug)]
pub(crate) struct NotFound;

// This struct has this helper impl for use as `NotFound.into()`
impl From<NotFound> for AppResponse {
    fn from(_: NotFound) -> AppResponse {
        json_error("Not Found", StatusCode::NOT_FOUND)
    }
}

impl AppError for NotFound {
    fn response(&self) -> Option<AppResponse> {
        Some(Self.into())
    }
}

impl fmt::Display for NotFound {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Not Found".fmt(f)
    }
}

#[derive(Debug)]
pub(super) struct Forbidden;
#[derive(Debug)]
pub(crate) struct ReadOnlyMode;

impl AppError for Forbidden {
    fn response(&self) -> Option<AppResponse> {
        let detail = "must be logged in to perform that action";
        Some(json_error(detail, StatusCode::FORBIDDEN))
    }
}

impl fmt::Display for Forbidden {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "must be logged in to perform that action".fmt(f)
    }
}

impl AppError for ReadOnlyMode {
    fn response(&self) -> Option<AppResponse> {
        let detail = "Crates.io is currently in read-only mode for maintenance. \
                      Please try again later.";
        Some(json_error(detail, StatusCode::SERVICE_UNAVAILABLE))
    }
}

impl fmt::Display for ReadOnlyMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Tried to write in read only mode".fmt(f)
    }
}

// The following structs wrap owned data and provide a custom message to the user

#[derive(Debug)]
pub(super) struct Ok(pub(super) String);
#[derive(Debug)]
pub(super) struct BadRequest(pub(super) String);
#[derive(Debug)]
pub(super) struct ServerError(pub(super) String);
#[derive(Debug)]
pub(crate) struct TooManyRequests {
    pub retry_after: NaiveDateTime,
}

impl AppError for Ok {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::OK))
    }
}

impl fmt::Display for Ok {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for BadRequest {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::BAD_REQUEST))
    }
}

impl fmt::Display for BadRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for ServerError {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::INTERNAL_SERVER_ERROR))
    }
}

impl fmt::Display for ServerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for TooManyRequests {
    fn response(&self) -> Option<AppResponse> {
        use std::convert::TryInto;

        const HTTP_DATE_FORMAT: &str = "%a, %d %b %Y %H:%M:%S GMT";
        let retry_after = self.retry_after.format(HTTP_DATE_FORMAT);

        let detail = format!(
            "You have published too many crates in a \
             short period of time. Please try again after {} or email \
             help@crates.io to have your limit increased.",
            retry_after
        );
        let mut response = json_error(&detail, StatusCode::TOO_MANY_REQUESTS);
        response.headers_mut().insert(
            header::RETRY_AFTER,
            retry_after
                .to_string()
                .try_into()
                .expect("HTTP_DATE_FORMAT contains invalid char"),
        );
        Some(response)
    }
}

impl fmt::Display for TooManyRequests {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Too many requests".fmt(f)
    }
}

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

impl InsecurelyGeneratedTokenRevoked {
    pub fn boxed() -> Box<dyn AppError> {
        Box::new(Self)
    }
}

impl AppError for InsecurelyGeneratedTokenRevoked {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::UNAUTHORIZED))
    }

    fn cause(&self) -> Option<&dyn AppError> {
        Some(&InternalAppErrorStatic {
            description: "insecurely generated, revoked 2020-07",
        })
    }
}

pub const TOKEN_FORMAT_ERROR: &str =
    "The given API token does not match the format used by crates.io. \
    \
    Tokens generated before 2020-07-14 were generated with an insecure \
    random number generator, and have been revoked. You can generate a \
    new token at https://crates.io/me. \
    \
    For more information please see \
    https://blog.rust-lang.org/2020/07/14/crates-io-security-advisory.html. \
    We apologize for any inconvenience.";

impl fmt::Display for InsecurelyGeneratedTokenRevoked {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(TOKEN_FORMAT_ERROR)?;
        Result::Ok(())
    }
}

#[derive(Debug)]
pub(super) struct AccountLocked {
    pub(super) reason: String,
    pub(super) until: Option<NaiveDateTime>,
}

impl AppError for AccountLocked {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::FORBIDDEN))
    }
}

impl fmt::Display for AccountLocked {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(until) = self.until {
            let until = until.format("%Y-%m-%d at %H:%M:%S UTC");
            write!(
                f,
                "This account is locked until {}. Reason: {}",
                until, self.reason
            )
        } else {
            write!(
                f,
                "This account is indefinitely locked. Reason: {}",
                self.reason
            )
        }
    }
}

#[derive(Debug)]
pub(crate) struct OwnershipInvitationExpired {
    pub(crate) crate_name: String,
}

impl AppError for OwnershipInvitationExpired {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::GONE))
    }
}

impl fmt::Display for OwnershipInvitationExpired {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "The invitation to become an owner of the {} crate expired. \
             Please reach out to an owner of the crate to request a new invitation.",
            self.crate_name
        )
    }
}

#[derive(Debug)]
pub(crate) struct MetricsDisabled;

impl AppError for MetricsDisabled {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::NOT_FOUND))
    }
}

impl fmt::Display for MetricsDisabled {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Metrics are disabled on this crates.io instance")
    }
}
<commit_msg>errors::json: Add `ServiceUnavailable` struct<commit_after>use std::fmt;

use super::{AppError, InternalAppErrorStatic};
use crate::util::{json_response, AppResponse};

use chrono::NaiveDateTime;
use conduit::{header, StatusCode};

/// Generates a response with the provided status and description as JSON
fn json_error(detail: &str, status: StatusCode) -> AppResponse {
    let json = json!({ "errors": [{ "detail": detail }] });

    let mut response = json_response(&json);
    *response.status_mut() = status;
    response
}

// The following structs are emtpy and do not provide a custom message to the user

#[derive(Debug)]
pub(crate) struct NotFound;

// This struct has this helper impl for use as `NotFound.into()`
impl From<NotFound> for AppResponse {
    fn from(_: NotFound) -> AppResponse {
        json_error("Not Found", StatusCode::NOT_FOUND)
    }
}

impl AppError for NotFound {
    fn response(&self) -> Option<AppResponse> {
        Some(Self.into())
    }
}

impl fmt::Display for NotFound {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Not Found".fmt(f)
    }
}

#[derive(Debug)]
pub(super) struct Forbidden;
#[derive(Debug)]
pub(crate) struct ReadOnlyMode;

impl AppError for Forbidden {
    fn response(&self) -> Option<AppResponse> {
        let detail = "must be logged in to perform that action";
        Some(json_error(detail, StatusCode::FORBIDDEN))
    }
}

impl fmt::Display for Forbidden {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "must be logged in to perform that action".fmt(f)
    }
}

impl AppError for ReadOnlyMode {
    fn response(&self) -> Option<AppResponse> {
        let detail = "Crates.io is currently in read-only mode for maintenance. \
                      Please try again later.";
        Some(json_error(detail, StatusCode::SERVICE_UNAVAILABLE))
    }
}

impl fmt::Display for ReadOnlyMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Tried to write in read only mode".fmt(f)
    }
}

// The following structs wrap owned data and provide a custom message to the user

#[derive(Debug)]
pub(super) struct Ok(pub(super) String);
#[derive(Debug)]
pub(super) struct BadRequest(pub(super) String);
#[derive(Debug)]
pub(super) struct ServerError(pub(super) String);
#[derive(Debug)]
pub(crate) struct ServiceUnavailable(pub(super) String);
#[derive(Debug)]
pub(crate) struct TooManyRequests {
    pub retry_after: NaiveDateTime,
}

impl AppError for Ok {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::OK))
    }
}

impl fmt::Display for Ok {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for BadRequest {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::BAD_REQUEST))
    }
}

impl fmt::Display for BadRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for ServerError {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::INTERNAL_SERVER_ERROR))
    }
}

impl fmt::Display for ServerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for ServiceUnavailable {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.0, StatusCode::SERVICE_UNAVAILABLE))
    }
}

impl fmt::Display for ServiceUnavailable {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl AppError for TooManyRequests {
    fn response(&self) -> Option<AppResponse> {
        use std::convert::TryInto;

        const HTTP_DATE_FORMAT: &str = "%a, %d %b %Y %H:%M:%S GMT";
        let retry_after = self.retry_after.format(HTTP_DATE_FORMAT);

        let detail = format!(
            "You have published too many crates in a \
             short period of time. Please try again after {} or email \
             help@crates.io to have your limit increased.",
            retry_after
        );
        let mut response = json_error(&detail, StatusCode::TOO_MANY_REQUESTS);
        response.headers_mut().insert(
            header::RETRY_AFTER,
            retry_after
                .to_string()
                .try_into()
                .expect("HTTP_DATE_FORMAT contains invalid char"),
        );
        Some(response)
    }
}

impl fmt::Display for TooManyRequests {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Too many requests".fmt(f)
    }
}

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

impl InsecurelyGeneratedTokenRevoked {
    pub fn boxed() -> Box<dyn AppError> {
        Box::new(Self)
    }
}

impl AppError for InsecurelyGeneratedTokenRevoked {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::UNAUTHORIZED))
    }

    fn cause(&self) -> Option<&dyn AppError> {
        Some(&InternalAppErrorStatic {
            description: "insecurely generated, revoked 2020-07",
        })
    }
}

pub const TOKEN_FORMAT_ERROR: &str =
    "The given API token does not match the format used by crates.io. \
    \
    Tokens generated before 2020-07-14 were generated with an insecure \
    random number generator, and have been revoked. You can generate a \
    new token at https://crates.io/me. \
    \
    For more information please see \
    https://blog.rust-lang.org/2020/07/14/crates-io-security-advisory.html. \
    We apologize for any inconvenience.";

impl fmt::Display for InsecurelyGeneratedTokenRevoked {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(TOKEN_FORMAT_ERROR)?;
        Result::Ok(())
    }
}

#[derive(Debug)]
pub(super) struct AccountLocked {
    pub(super) reason: String,
    pub(super) until: Option<NaiveDateTime>,
}

impl AppError for AccountLocked {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::FORBIDDEN))
    }
}

impl fmt::Display for AccountLocked {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(until) = self.until {
            let until = until.format("%Y-%m-%d at %H:%M:%S UTC");
            write!(
                f,
                "This account is locked until {}. Reason: {}",
                until, self.reason
            )
        } else {
            write!(
                f,
                "This account is indefinitely locked. Reason: {}",
                self.reason
            )
        }
    }
}

#[derive(Debug)]
pub(crate) struct OwnershipInvitationExpired {
    pub(crate) crate_name: String,
}

impl AppError for OwnershipInvitationExpired {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::GONE))
    }
}

impl fmt::Display for OwnershipInvitationExpired {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "The invitation to become an owner of the {} crate expired. \
             Please reach out to an owner of the crate to request a new invitation.",
            self.crate_name
        )
    }
}

#[derive(Debug)]
pub(crate) struct MetricsDisabled;

impl AppError for MetricsDisabled {
    fn response(&self) -> Option<AppResponse> {
        Some(json_error(&self.to_string(), StatusCode::NOT_FOUND))
    }
}

impl fmt::Display for MetricsDisabled {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Metrics are disabled on this crates.io instance")
    }
}
<|endoftext|>


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

//! Unix-specific extensions to general I/O primitives

#![stable(feature = "rust1", since = "1.0.0")]

use fs;
use net;
use os::raw;
use sys;
use sys_common::{self, AsInner, FromInner, IntoInner};

/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
pub type RawFd = raw::c_int;

/// A trait to extract the raw unix file descriptor from an underlying
/// object.
///
/// This is only available on unix platforms and must be imported in order
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
/// and `AsRawSocket` set of traits.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRawFd {
    /// Extracts the raw file descriptor.
    ///
    /// This method does **not** pass ownership of the raw file descriptor
    /// to the caller. The descriptor is only guaranteed to be valid while
    /// the original object has not yet been destroyed.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_raw_fd(&self) -> RawFd;
}

/// A trait to express the ability to construct an object from a raw file
/// descriptor.
#[stable(feature = "from_raw_os", since = "1.1.0")]
pub trait FromRawFd {
    /// Constructs a new instance of `Self` from the given raw file
    /// descriptor.
    ///
    /// This function **consumes ownership** of the specified file
    /// descriptor. The returned object will take responsibility for closing
    /// it when the object goes out of scope.
    ///
    /// This function is also unsafe as the primitives currently returned
    /// have the contract that they are the sole owner of the file
    /// descriptor they are wrapping. Usage of this function could
    /// accidentally allow violating this contract which can cause memory
    /// unsafety in code that relies on it being true.
    #[stable(feature = "from_raw_os", since = "1.1.0")]
    unsafe fn from_raw_fd(fd: RawFd) -> Self;
}

/// A trait to express the ability to consume an object and acquire ownership of
/// its raw file descriptor.
#[stable(feature = "into_raw_os", since = "1.4.0")]
pub trait IntoRawFd {
    /// Consumes this object, returning the raw underlying file descriptor.
    ///
    /// This function **transfers ownership** of the underlying file descriptor
    /// to the caller. Callers are then the unique owners of the file descriptor
    /// and must close the descriptor once it's no longer needed.
    #[stable(feature = "into_raw_os", since = "1.4.0")]
    fn into_raw_fd(self) -> RawFd;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for fs::File {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for fs::File {
    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
        fs::File::from_inner(sys::fs::File::from_inner(fd))
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for fs::File {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpStream {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpListener {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::UdpSocket {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}

#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpStream {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpListener {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::UdpSocket {
    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
        let socket = sys::net::Socket::from_inner(fd);
        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpStream {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpListener {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::UdpSocket {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
<commit_msg>Implement AsRawFd/IntoRawFd for RawFd<commit_after>// Copyright 2015 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.

//! Unix-specific extensions to general I/O primitives

#![stable(feature = "rust1", since = "1.0.0")]

use fs;
use net;
use os::raw;
use sys;
use sys_common::{self, AsInner, FromInner, IntoInner};

/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
pub type RawFd = raw::c_int;

/// A trait to extract the raw unix file descriptor from an underlying
/// object.
///
/// This is only available on unix platforms and must be imported in order
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
/// and `AsRawSocket` set of traits.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRawFd {
    /// Extracts the raw file descriptor.
    ///
    /// This method does **not** pass ownership of the raw file descriptor
    /// to the caller. The descriptor is only guaranteed to be valid while
    /// the original object has not yet been destroyed.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_raw_fd(&self) -> RawFd;
}

/// A trait to express the ability to construct an object from a raw file
/// descriptor.
#[stable(feature = "from_raw_os", since = "1.1.0")]
pub trait FromRawFd {
    /// Constructs a new instance of `Self` from the given raw file
    /// descriptor.
    ///
    /// This function **consumes ownership** of the specified file
    /// descriptor. The returned object will take responsibility for closing
    /// it when the object goes out of scope.
    ///
    /// This function is also unsafe as the primitives currently returned
    /// have the contract that they are the sole owner of the file
    /// descriptor they are wrapping. Usage of this function could
    /// accidentally allow violating this contract which can cause memory
    /// unsafety in code that relies on it being true.
    #[stable(feature = "from_raw_os", since = "1.1.0")]
    unsafe fn from_raw_fd(fd: RawFd) -> Self;
}

/// A trait to express the ability to consume an object and acquire ownership of
/// its raw file descriptor.
#[stable(feature = "into_raw_os", since = "1.4.0")]
pub trait IntoRawFd {
    /// Consumes this object, returning the raw underlying file descriptor.
    ///
    /// This function **transfers ownership** of the underlying file descriptor
    /// to the caller. Callers are then the unique owners of the file descriptor
    /// and must close the descriptor once it's no longer needed.
    #[stable(feature = "into_raw_os", since = "1.4.0")]
    fn into_raw_fd(self) -> RawFd;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for RawFd {
    fn as_raw_fd(&self) -> RawFd {
        *self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for fs::File {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for fs::File {
    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
        fs::File::from_inner(sys::fs::File::from_inner(fd))
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for RawFd {
    fn into_raw_fd(self) -> RawFd {
        self
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for fs::File {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpStream {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpListener {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::UdpSocket {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}

#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpStream {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpListener {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::UdpSocket {
    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
        let socket = sys::net::Socket::from_inner(fd);
        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpStream {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpListener {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::UdpSocket {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
<|endoftext|>


<commit_before>use crate::ffi::CStr;
use crate::io;
use crate::mem;
use crate::sys::{unsupported, Void};
use crate::time::Duration;

use ::wasi::wasi_unstable as wasi;

pub struct Thread(Void);

pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;

impl Thread {
    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
        -> io::Result<Thread>
    {
        unsupported()
    }

    pub fn yield_now() {
        let ret = wasi::sched_yield();
        debug_assert_eq!(ret, Ok(()));
    }

    pub fn set_name(_name: &CStr) {
        // nope
    }

    pub fn sleep(dur: Duration) {
        let nanos = dur.as_nanos();
        assert!(nanos <= u64::max_value() as u128);

        const CLOCK_ID: wasi::Userdata = 0x0123_45678;

        let clock = wasi::raw::__wasi_subscription_u_clock_t {
            identifier: CLOCK_ID,
            clock_id: wasi::CLOCK_MONOTONIC,
            timeout: nanos as u64,
            precision: 0,
            flags: 0,
        };

        let in_ = [wasi::Subscription {
            userdata: 0,
            type_: wasi::EVENTTYPE_CLOCK,
            u: wasi::raw::__wasi_subscription_u { clock: clock },
        }];
        let (res, event) = unsafe {
            let mut out: [wasi::Event; 1] = mem::zeroed();
            let res = wasi::poll_oneoff(&in_, &mut out);
            (res, out[0])
        };
        match (res, event) {
            (Ok(1), wasi::Event {
                userdata: CLOCK_ID,
                error: 0,
                type_: wasi::EVENTTYPE_CLOCK,
                ..
            }) => {}
            _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
        }
    }

    pub fn join(self) {
        match self.0 {}
    }
}

pub mod guard {
    pub type Guard = !;
    pub unsafe fn current() -> Option<Guard> { None }
    pub unsafe fn init() -> Option<Guard> { None }
}
<commit_msg>fix WASI sleep impl<commit_after>use crate::ffi::CStr;
use crate::io;
use crate::mem;
use crate::sys::{unsupported, Void};
use crate::time::Duration;

use ::wasi::wasi_unstable as wasi;

pub struct Thread(Void);

pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;

impl Thread {
    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
        -> io::Result<Thread>
    {
        unsupported()
    }

    pub fn yield_now() {
        let ret = wasi::sched_yield();
        debug_assert_eq!(ret, Ok(()));
    }

    pub fn set_name(_name: &CStr) {
        // nope
    }

    pub fn sleep(dur: Duration) {
        let nanos = dur.as_nanos();
        assert!(nanos <= u64::max_value() as u128);

        const USERDATA: wasi::Userdata = 0x0123_45678;

        let clock = wasi::raw::__wasi_subscription_u_clock_t {
            identifier: 0,
            clock_id: wasi::CLOCK_MONOTONIC,
            timeout: nanos as u64,
            precision: 0,
            flags: 0,
        };

        let in_ = [wasi::Subscription {
            userdata: USERDATA,
            type_: wasi::EVENTTYPE_CLOCK,
            u: wasi::raw::__wasi_subscription_u { clock: clock },
        }];
        let (res, event) = unsafe {
            let mut out: [wasi::Event; 1] = mem::zeroed();
            let res = wasi::poll_oneoff(&in_, &mut out);
            (res, out[0])
        };
        match (res, event) {
            (Ok(1), wasi::Event {
                userdata: USERDATA,
                error: 0,
                type_: wasi::EVENTTYPE_CLOCK,
                ..
            }) => {}
            _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
        }
    }

    pub fn join(self) {
        match self.0 {}
    }
}

pub mod guard {
    pub type Guard = !;
    pub unsafe fn current() -> Option<Guard> { None }
    pub unsafe fn init() -> Option<Guard> { None }
}
<|endoftext|>


<commit_before>use std::iter::FromIterator;
use self::super::Algorithm;
use std::path::PathBuf;

mod md5;
mod xor8;
mod crc8;
mod crc16;
mod blake;
mod blake2;
mod crc32_64;
mod sha3256_3512;
mod sha1_2256_2512;
mod md6128_256_512;

/// Hash the specified file using the specified hashing algorithm.
pub fn hash_file(path: &PathBuf, algo: Algorithm) -> String {
    match algo {
        Algorithm::SHA1 => sha1_2256_2512::sha1::hash(path),
        Algorithm::SHA2256 => sha1_2256_2512::sha2256::hash(path),
        Algorithm::SHA2512 => sha1_2256_2512::sha2512::hash(path),
        Algorithm::SHA3256 => sha3256_3512::sha3256::hash(path),
        Algorithm::SHA3512 => sha3256_3512::sha3512::hash(path),
        Algorithm::BLAKE => blake::hash(path),
        Algorithm::BLAKE2 => blake2::hash(path),
        Algorithm::CRC64 => crc32_64::crc64::hash(path),
        Algorithm::CRC32 => crc32_64::crc32::hash(path),
        Algorithm::CRC16 => crc16::hash(path),
        Algorithm::CRC8 => crc8::hash(path),
        Algorithm::MD5 => md5::hash(path),
        Algorithm::MD6128 => md6128_256_512::md6128::hash(path),
        Algorithm::MD6256 => md6128_256_512::md6256::hash(path),
        Algorithm::MD6512 => md6128_256_512::md6512::hash(path),
        Algorithm::XOR8 => xor8::hash(path),
    }
}

/// Create a hash string out of its raw bytes.
///
/// Probably very inefficient. Better way = ?
///
/// # Examples
///
/// ```
/// assert_eq!(checksums::hash_string(&[0x99, 0xAA, 0xBB, 0xCC]), "99AABBCC".to_string());
/// assert_eq!(checksums::hash_string(&[0x09, 0x0A]), "090A".to_string());
/// ```
pub fn hash_string(bytes: &[u8]) -> String {
    String::from_iter(bytes.iter().map(|&i| {
        if i <= 0xF {
            format!("0{:X}", i)
        } else {
            format!("{:X}", i)
        }
    }))
}
<commit_msg>Use a lookup table in hash_string(), improving perf<commit_after>use std::iter::FromIterator;
use self::super::Algorithm;
use std::path::PathBuf;

mod md5;
mod xor8;
mod crc8;
mod crc16;
mod blake;
mod blake2;
mod crc32_64;
mod sha3256_3512;
mod sha1_2256_2512;
mod md6128_256_512;

/// Hash the specified file using the specified hashing algorithm.
pub fn hash_file(path: &PathBuf, algo: Algorithm) -> String {
    match algo {
        Algorithm::SHA1 => sha1_2256_2512::sha1::hash(path),
        Algorithm::SHA2256 => sha1_2256_2512::sha2256::hash(path),
        Algorithm::SHA2512 => sha1_2256_2512::sha2512::hash(path),
        Algorithm::SHA3256 => sha3256_3512::sha3256::hash(path),
        Algorithm::SHA3512 => sha3256_3512::sha3512::hash(path),
        Algorithm::BLAKE => blake::hash(path),
        Algorithm::BLAKE2 => blake2::hash(path),
        Algorithm::CRC64 => crc32_64::crc64::hash(path),
        Algorithm::CRC32 => crc32_64::crc32::hash(path),
        Algorithm::CRC16 => crc16::hash(path),
        Algorithm::CRC8 => crc8::hash(path),
        Algorithm::MD5 => md5::hash(path),
        Algorithm::MD6128 => md6128_256_512::md6128::hash(path),
        Algorithm::MD6256 => md6128_256_512::md6256::hash(path),
        Algorithm::MD6512 => md6128_256_512::md6512::hash(path),
        Algorithm::XOR8 => xor8::hash(path),
    }
}

/// Create a hash string out of its raw bytes.
///
/// Probably very inefficient. Better way = ?
///
/// # Examples
///
/// ```
/// assert_eq!(checksums::hash_string(&[0x99, 0xAA, 0xBB, 0xCC]), "99AABBCC".to_string());
/// assert_eq!(checksums::hash_string(&[0x09, 0x0A]), "090A".to_string());
/// ```
pub fn hash_string(bytes: &[u8]) -> String {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    static LOOKUP_TABLE: [&'static str; 256] = [
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
        "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
        "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
        "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
        "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
        "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
        "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
        "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
        "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
        "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
        "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
        "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
        "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
        "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
        "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
    ];

    String::from_iter(bytes.iter().map(|&i| LOOKUP_TABLE[i as usize]))
}
<|endoftext|>