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

use util::nodemap::{FxHashMap, FxHashSet};
use ty::context::TyCtxt;
use ty::{AdtDef, VariantDef, FieldDef, TyS};
use ty::{DefId, Substs};
use ty::{AdtKind, Visibility};
use ty::TypeVariants::*;

pub use self::def_id_forest::DefIdForest;

mod def_id_forest;

// The methods in this module calculate DefIdForests of modules in which a
// AdtDef/VariantDef/FieldDef is visibly uninhabited.
//
// # Example
// ```rust
// enum Void {}
// mod a {
//     pub mod b {
//         pub struct SecretlyUninhabited {
//             _priv: !,
//         }
//     }
// }
//
// mod c {
//     pub struct AlsoSecretlyUninhabited {
//         _priv: Void,
//     }
//     mod d {
//     }
// }
//
// struct Foo {
//     x: a::b::SecretlyUninhabited,
//     y: c::AlsoSecretlyUninhabited,
// }
// ```
// In this code, the type Foo will only be visibly uninhabited inside the
// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will
// return the forest of modules {b, c->d} (represented in a DefIdForest by the
// set {b, c})
//
// We need this information for pattern-matching on Foo or types that contain
// Foo.
//
// # Example
// ```rust
// let foo_result: Result<T, Foo> = ... ;
// let Ok(t) = foo_result;
// ```
// This code should only compile in modules where the uninhabitedness of Foo is
// visible.

impl<'a, 'gcx, 'tcx> AdtDef {
    /// Calculate the forest of DefIds from which this adt is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>,
                substs: &'tcx Substs<'tcx>) -> DefIdForest
    {
        DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
            v.uninhabited_from(visited, tcx, substs, self.adt_kind())
        }))
    }
}

impl<'a, 'gcx, 'tcx> VariantDef {
    /// Calculate the forest of DefIds from which this variant is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>,
                substs: &'tcx Substs<'tcx>,
                adt_kind: AdtKind) -> DefIdForest
    {
        match adt_kind {
            AdtKind::Union => {
                DefIdForest::intersection(tcx, self.fields.iter().map(|f| {
                    f.uninhabited_from(visited, tcx, substs, false)
                }))
            },
            AdtKind::Struct => {
                DefIdForest::union(tcx, self.fields.iter().map(|f| {
                    f.uninhabited_from(visited, tcx, substs, false)
                }))
            },
            AdtKind::Enum => {
                DefIdForest::union(tcx, self.fields.iter().map(|f| {
                    f.uninhabited_from(visited, tcx, substs, true)
                }))
            },
        }
    }
}

impl<'a, 'gcx, 'tcx> FieldDef {
    /// Calculate the forest of DefIds from which this field is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>,
                substs: &'tcx Substs<'tcx>,
                is_enum: bool) -> DefIdForest
    {
        let mut data_uninhabitedness = move || {
            self.ty(tcx, substs).uninhabited_from(visited, tcx)
        };
        // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
        // Visibility::Invisible so we need to override self.vis if we're
        // dealing with an enum.
        if is_enum {
            data_uninhabitedness()
        } else {
            match self.vis {
                Visibility::Invisible => DefIdForest::empty(),
                Visibility::Restricted(from) => {
                    let forest = DefIdForest::from_id(from);
                    let iter = Some(forest).into_iter().chain(Some(data_uninhabitedness()));
                    DefIdForest::intersection(tcx, iter)
                },
                Visibility::Public => data_uninhabitedness(),
            }
        }
    }
}

impl<'a, 'gcx, 'tcx> TyS<'tcx> {
    /// Calculate the forest of DefIds from which this type is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
    {
        match tcx.lift_to_global(&self) {
            Some(global_ty) => {
                {
                    let cache = tcx.inhabitedness_cache.borrow();
                    if let Some(forest) = cache.get(&global_ty) {
                        return forest.clone();
                    }
                }
                let forest = global_ty.uninhabited_from_inner(visited, tcx);
                let mut cache = tcx.inhabitedness_cache.borrow_mut();
                cache.insert(global_ty, forest.clone());
                forest
            },
            None => {
                let forest = self.uninhabited_from_inner(visited, tcx);
                forest
            },
        }
    }

    fn uninhabited_from_inner(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
    {
        match self.sty {
            TyAdt(def, substs) => {
                {
                    let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
                    if !substs_set.insert(substs) {
                        // We are already calculating the inhabitedness of this type.
                        // The type must contain a reference to itself. Break the
                        // infinite loop.
                        return DefIdForest::empty();
                    }
                    if substs_set.len() >= tcx.sess.recursion_limit.get() / 4 {
                        // We have gone very deep, reinstantiating this ADT inside
                        // itself with different type arguments. We are probably
                        // hitting an infinite loop. For example, it's possible to write:
                        //                a type Foo<T>
                        //      which contains a Foo<(T, T)>
                        //      which contains a Foo<((T, T), (T, T))>
                        //      which contains a Foo<(((T, T), (T, T)), ((T, T), (T, T)))>
                        //      etc.
                        let error = format!("reached recursion limit while checking
                                             inhabitedness of `{}`", self);
                        tcx.sess.fatal(&error);
                    }
                }
                let ret = def.uninhabited_from(visited, tcx, substs);
                let mut substs_set = visited.get_mut(&def.did).unwrap();
                substs_set.remove(substs);
                ret
            },

            TyNever => DefIdForest::full(tcx),
            TyTuple(ref tys, _) => {
                DefIdForest::union(tcx, tys.iter().map(|ty| {
                    ty.uninhabited_from(visited, tcx)
                }))
            },
            TyArray(ty, len) => {
                if len == 0 {
                    DefIdForest::empty()
                } else {
                    ty.uninhabited_from(visited, tcx)
                }
            }
            TyRef(_, ref tm) => {
                tm.ty.uninhabited_from(visited, tcx)
            }

            _ => DefIdForest::empty(),
        }
    }
}

<commit_msg>Rollup merge of #39940 - sgrif:sg-indentation, r=alexcrichton<commit_after>// Copyright 2012-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.

use util::nodemap::{FxHashMap, FxHashSet};
use ty::context::TyCtxt;
use ty::{AdtDef, VariantDef, FieldDef, TyS};
use ty::{DefId, Substs};
use ty::{AdtKind, Visibility};
use ty::TypeVariants::*;

pub use self::def_id_forest::DefIdForest;

mod def_id_forest;

// The methods in this module calculate DefIdForests of modules in which a
// AdtDef/VariantDef/FieldDef is visibly uninhabited.
//
// # Example
// ```rust
// enum Void {}
// mod a {
//     pub mod b {
//         pub struct SecretlyUninhabited {
//             _priv: !,
//         }
//     }
// }
//
// mod c {
//     pub struct AlsoSecretlyUninhabited {
//         _priv: Void,
//     }
//     mod d {
//     }
// }
//
// struct Foo {
//     x: a::b::SecretlyUninhabited,
//     y: c::AlsoSecretlyUninhabited,
// }
// ```
// In this code, the type Foo will only be visibly uninhabited inside the
// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will
// return the forest of modules {b, c->d} (represented in a DefIdForest by the
// set {b, c})
//
// We need this information for pattern-matching on Foo or types that contain
// Foo.
//
// # Example
// ```rust
// let foo_result: Result<T, Foo> = ... ;
// let Ok(t) = foo_result;
// ```
// This code should only compile in modules where the uninhabitedness of Foo is
// visible.

impl<'a, 'gcx, 'tcx> AdtDef {
    /// Calculate the forest of DefIds from which this adt is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>,
                substs: &'tcx Substs<'tcx>) -> DefIdForest
    {
        DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
            v.uninhabited_from(visited, tcx, substs, self.adt_kind())
        }))
    }
}

impl<'a, 'gcx, 'tcx> VariantDef {
    /// Calculate the forest of DefIds from which this variant is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>,
                substs: &'tcx Substs<'tcx>,
                adt_kind: AdtKind) -> DefIdForest
    {
        match adt_kind {
            AdtKind::Union => {
                DefIdForest::intersection(tcx, self.fields.iter().map(|f| {
                    f.uninhabited_from(visited, tcx, substs, false)
                }))
            },
            AdtKind::Struct => {
                DefIdForest::union(tcx, self.fields.iter().map(|f| {
                    f.uninhabited_from(visited, tcx, substs, false)
                }))
            },
            AdtKind::Enum => {
                DefIdForest::union(tcx, self.fields.iter().map(|f| {
                    f.uninhabited_from(visited, tcx, substs, true)
                }))
            },
        }
    }
}

impl<'a, 'gcx, 'tcx> FieldDef {
    /// Calculate the forest of DefIds from which this field is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>,
                substs: &'tcx Substs<'tcx>,
                is_enum: bool) -> DefIdForest
    {
        let mut data_uninhabitedness = move || {
            self.ty(tcx, substs).uninhabited_from(visited, tcx)
        };
        // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
        // Visibility::Invisible so we need to override self.vis if we're
        // dealing with an enum.
        if is_enum {
            data_uninhabitedness()
        } else {
            match self.vis {
                Visibility::Invisible => DefIdForest::empty(),
                Visibility::Restricted(from) => {
                    let forest = DefIdForest::from_id(from);
                    let iter = Some(forest).into_iter().chain(Some(data_uninhabitedness()));
                    DefIdForest::intersection(tcx, iter)
                },
                Visibility::Public => data_uninhabitedness(),
            }
        }
    }
}

impl<'a, 'gcx, 'tcx> TyS<'tcx> {
    /// Calculate the forest of DefIds from which this type is visibly uninhabited.
    pub fn uninhabited_from(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
    {
        match tcx.lift_to_global(&self) {
            Some(global_ty) => {
                {
                    let cache = tcx.inhabitedness_cache.borrow();
                    if let Some(forest) = cache.get(&global_ty) {
                        return forest.clone();
                    }
                }
                let forest = global_ty.uninhabited_from_inner(visited, tcx);
                let mut cache = tcx.inhabitedness_cache.borrow_mut();
                cache.insert(global_ty, forest.clone());
                forest
            },
            None => {
                let forest = self.uninhabited_from_inner(visited, tcx);
                forest
            },
        }
    }

    fn uninhabited_from_inner(
                &self,
                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
    {
        match self.sty {
            TyAdt(def, substs) => {
                {
                    let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
                    if !substs_set.insert(substs) {
                        // We are already calculating the inhabitedness of this type.
                        // The type must contain a reference to itself. Break the
                        // infinite loop.
                        return DefIdForest::empty();
                    }
                    if substs_set.len() >= tcx.sess.recursion_limit.get() / 4 {
                        // We have gone very deep, reinstantiating this ADT inside
                        // itself with different type arguments. We are probably
                        // hitting an infinite loop. For example, it's possible to write:
                        //                a type Foo<T>
                        //      which contains a Foo<(T, T)>
                        //      which contains a Foo<((T, T), (T, T))>
                        //      which contains a Foo<(((T, T), (T, T)), ((T, T), (T, T)))>
                        //      etc.
                        let error = format!("reached recursion limit while checking \
                                             inhabitedness of `{}`", self);
                        tcx.sess.fatal(&error);
                    }
                }
                let ret = def.uninhabited_from(visited, tcx, substs);
                let mut substs_set = visited.get_mut(&def.did).unwrap();
                substs_set.remove(substs);
                ret
            },

            TyNever => DefIdForest::full(tcx),
            TyTuple(ref tys, _) => {
                DefIdForest::union(tcx, tys.iter().map(|ty| {
                    ty.uninhabited_from(visited, tcx)
                }))
            },
            TyArray(ty, len) => {
                if len == 0 {
                    DefIdForest::empty()
                } else {
                    ty.uninhabited_from(visited, tcx)
                }
            }
            TyRef(_, ref tm) => {
                tm.ty.uninhabited_from(visited, tcx)
            }

            _ => DefIdForest::empty(),
        }
    }
}

<|endoftext|>


<commit_before>// Coherence phase
//
// The job of the coherence phase of typechecking is to ensure that
// each trait has at most one implementation for each type. This is
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.

use rustc::traits;
use rustc::ty::query::Providers;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc_errors::struct_span_err;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};

mod builtin;
mod inherent_impls;
mod inherent_impls_overlap;
mod orphan;
mod unsafety;

fn check_impl(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_ref: ty::TraitRef<'_>) {
    debug!(
        "(checking implementation) adding impl for trait '{:?}', item '{}'",
        trait_ref,
        tcx.def_path_str(impl_def_id)
    );

    // Skip impls where one of the self type is an error type.
    // This occurs with e.g., resolve failures (#30589).
    if trait_ref.references_error() {
        return;
    }

    enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
    enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id);
}

fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_def_id: DefId) {
    let did = Some(trait_def_id);
    let li = tcx.lang_items();
    let span = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());

    // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
    if did == li.sized_trait() {
        struct_span_err!(
            tcx.sess,
            span,
            E0322,
            "explicit impls for the `Sized` trait are not permitted"
        )
        .span_label(span, "impl of 'Sized' not allowed")
        .emit();
        return;
    }

    if did == li.unsize_trait() {
        struct_span_err!(
            tcx.sess,
            span,
            E0328,
            "explicit impls for the `Unsize` trait are not permitted"
        )
        .span_label(span, "impl of `Unsize` not allowed")
        .emit();
        return;
    }

    if tcx.features().unboxed_closures {
        // the feature gate allows all Fn traits
        return;
    }

    let trait_name = if did == li.fn_trait() {
        "Fn"
    } else if did == li.fn_mut_trait() {
        "FnMut"
    } else if did == li.fn_once_trait() {
        "FnOnce"
    } else {
        return; // everything OK
    };
    struct_span_err!(
        tcx.sess,
        span,
        E0183,
        "manual implementations of `{}` are experimental",
        trait_name
    )
    .span_label(span, format!("manual implementations of `{}` are experimental", trait_name))
    .help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")
    .emit();
}

/// We allow impls of marker traits to overlap, so they can't override impls
/// as that could make it ambiguous which associated item to use.
fn enforce_empty_impls_for_marker_traits(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_def_id: DefId) {
    if !tcx.trait_def(trait_def_id).is_marker {
        return;
    }

    if tcx.associated_item_def_ids(trait_def_id).is_empty() {
        return;
    }

    let span = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
    struct_span_err!(tcx.sess, span, E0715, "impls for marker traits cannot contain items").emit();
}

pub fn provide(providers: &mut Providers<'_>) {
    use self::builtin::coerce_unsized_info;
    use self::inherent_impls::{crate_inherent_impls, inherent_impls};
    use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;

    *providers = Providers {
        coherent_trait,
        crate_inherent_impls,
        inherent_impls,
        crate_inherent_impls_overlap_check,
        coerce_unsized_info,
        ..*providers
    };
}

fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
    // Trigger building the specialization graph for the trait. This will detect and report any
    // overlap errors.
    tcx.specialization_graph_of(def_id);

    let impls = tcx.hir().trait_impls(def_id);
    for &hir_id in impls {
        let impl_def_id = tcx.hir().local_def_id(hir_id);
        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();

        check_impl(tcx, impl_def_id, trait_ref);
        check_object_overlap(tcx, impl_def_id, trait_ref);
    }
    builtin::check_trait(tcx, def_id);
}

pub fn check_coherence(tcx: TyCtxt<'_>) {
    for &trait_def_id in tcx.hir().krate().trait_impls.keys() {
        tcx.ensure().coherent_trait(trait_def_id);
    }

    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
    tcx.sess.time("orphan_checking", || orphan::check(tcx));

    // these queries are executed for side-effects (error reporting):
    tcx.ensure().crate_inherent_impls(LOCAL_CRATE);
    tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE);
}

/// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
fn check_object_overlap<'tcx>(
    tcx: TyCtxt<'tcx>,
    impl_def_id: DefId,
    trait_ref: ty::TraitRef<'tcx>,
) {
    let trait_def_id = trait_ref.def_id;

    if trait_ref.references_error() {
        debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref);
        return;
    }

    // check for overlap with the automatic `impl Trait for dyn Trait`
    if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().kind {
        // This is something like impl Trait1 for Trait2. Illegal
        // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.

        let component_def_ids = data.iter().flat_map(|predicate| {
            match predicate.skip_binder() {
                ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
                ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id),
                // An associated type projection necessarily comes with
                // an additional `Trait` requirement.
                ty::ExistentialPredicate::Projection(..) => None,
            }
        });

        for component_def_id in component_def_ids {
            if !tcx.is_object_safe(component_def_id) {
                // Without the 'object_safe_for_dispatch' feature this is an error
                // which will be reported by wfcheck.  Ignore it here.
                // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
                // With the feature enabled, the trait is not implemented automatically,
                // so this is valid.
            } else {
                let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id);
                if supertrait_def_ids.any(|d| d == trait_def_id) {
                    let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
                    struct_span_err!(
                        tcx.sess,
                        sp,
                        E0371,
                        "the object type `{}` automatically implements the trait `{}`",
                        trait_ref.self_ty(),
                        tcx.def_path_str(trait_def_id)
                    )
                    .span_label(
                        sp,
                        format!(
                            "`{}` automatically implements trait `{}`",
                            trait_ref.self_ty(),
                            tcx.def_path_str(trait_def_id)
                        ),
                    )
                    .emit();
                }
            }
        }
    }
}
<commit_msg>Defer error span calculation until needed<commit_after>// Coherence phase
//
// The job of the coherence phase of typechecking is to ensure that
// each trait has at most one implementation for each type. This is
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.

use rustc::traits;
use rustc::ty::query::Providers;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc_errors::struct_span_err;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_span::Span;

mod builtin;
mod inherent_impls;
mod inherent_impls_overlap;
mod orphan;
mod unsafety;

/// Obtains the span of just the impl header of `impl_def_id`.
fn impl_header_span(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Span {
    tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap())
}

fn check_impl(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_ref: ty::TraitRef<'_>) {
    debug!(
        "(checking implementation) adding impl for trait '{:?}', item '{}'",
        trait_ref,
        tcx.def_path_str(impl_def_id)
    );

    // Skip impls where one of the self type is an error type.
    // This occurs with e.g., resolve failures (#30589).
    if trait_ref.references_error() {
        return;
    }

    enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
    enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id);
}

fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_def_id: DefId) {
    let did = Some(trait_def_id);
    let li = tcx.lang_items();

    // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
    if did == li.sized_trait() {
        let span = impl_header_span(tcx, impl_def_id);
        struct_span_err!(
            tcx.sess,
            span,
            E0322,
            "explicit impls for the `Sized` trait are not permitted"
        )
        .span_label(span, "impl of 'Sized' not allowed")
        .emit();
        return;
    }

    if did == li.unsize_trait() {
        let span = impl_header_span(tcx, impl_def_id);
        struct_span_err!(
            tcx.sess,
            span,
            E0328,
            "explicit impls for the `Unsize` trait are not permitted"
        )
        .span_label(span, "impl of `Unsize` not allowed")
        .emit();
        return;
    }

    if tcx.features().unboxed_closures {
        // the feature gate allows all Fn traits
        return;
    }

    let trait_name = if did == li.fn_trait() {
        "Fn"
    } else if did == li.fn_mut_trait() {
        "FnMut"
    } else if did == li.fn_once_trait() {
        "FnOnce"
    } else {
        return; // everything OK
    };

    let span = impl_header_span(tcx, impl_def_id);
    struct_span_err!(
        tcx.sess,
        span,
        E0183,
        "manual implementations of `{}` are experimental",
        trait_name
    )
    .span_label(span, format!("manual implementations of `{}` are experimental", trait_name))
    .help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")
    .emit();
}

/// We allow impls of marker traits to overlap, so they can't override impls
/// as that could make it ambiguous which associated item to use.
fn enforce_empty_impls_for_marker_traits(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_def_id: DefId) {
    if !tcx.trait_def(trait_def_id).is_marker {
        return;
    }

    if tcx.associated_item_def_ids(trait_def_id).is_empty() {
        return;
    }

    let span = impl_header_span(tcx, impl_def_id);
    struct_span_err!(tcx.sess, span, E0715, "impls for marker traits cannot contain items").emit();
}

pub fn provide(providers: &mut Providers<'_>) {
    use self::builtin::coerce_unsized_info;
    use self::inherent_impls::{crate_inherent_impls, inherent_impls};
    use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;

    *providers = Providers {
        coherent_trait,
        crate_inherent_impls,
        inherent_impls,
        crate_inherent_impls_overlap_check,
        coerce_unsized_info,
        ..*providers
    };
}

fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
    // Trigger building the specialization graph for the trait. This will detect and report any
    // overlap errors.
    tcx.specialization_graph_of(def_id);

    let impls = tcx.hir().trait_impls(def_id);
    for &hir_id in impls {
        let impl_def_id = tcx.hir().local_def_id(hir_id);
        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();

        check_impl(tcx, impl_def_id, trait_ref);
        check_object_overlap(tcx, impl_def_id, trait_ref);
    }
    builtin::check_trait(tcx, def_id);
}

pub fn check_coherence(tcx: TyCtxt<'_>) {
    for &trait_def_id in tcx.hir().krate().trait_impls.keys() {
        tcx.ensure().coherent_trait(trait_def_id);
    }

    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
    tcx.sess.time("orphan_checking", || orphan::check(tcx));

    // these queries are executed for side-effects (error reporting):
    tcx.ensure().crate_inherent_impls(LOCAL_CRATE);
    tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE);
}

/// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
fn check_object_overlap<'tcx>(
    tcx: TyCtxt<'tcx>,
    impl_def_id: DefId,
    trait_ref: ty::TraitRef<'tcx>,
) {
    let trait_def_id = trait_ref.def_id;

    if trait_ref.references_error() {
        debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref);
        return;
    }

    // check for overlap with the automatic `impl Trait for dyn Trait`
    if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().kind {
        // This is something like impl Trait1 for Trait2. Illegal
        // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.

        let component_def_ids = data.iter().flat_map(|predicate| {
            match predicate.skip_binder() {
                ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
                ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id),
                // An associated type projection necessarily comes with
                // an additional `Trait` requirement.
                ty::ExistentialPredicate::Projection(..) => None,
            }
        });

        for component_def_id in component_def_ids {
            if !tcx.is_object_safe(component_def_id) {
                // Without the 'object_safe_for_dispatch' feature this is an error
                // which will be reported by wfcheck.  Ignore it here.
                // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
                // With the feature enabled, the trait is not implemented automatically,
                // so this is valid.
            } else {
                let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id);
                if supertrait_def_ids.any(|d| d == trait_def_id) {
                    let span = impl_header_span(tcx, impl_def_id);
                    struct_span_err!(
                        tcx.sess,
                        span,
                        E0371,
                        "the object type `{}` automatically implements the trait `{}`",
                        trait_ref.self_ty(),
                        tcx.def_path_str(trait_def_id)
                    )
                    .span_label(
                        span,
                        format!(
                            "`{}` automatically implements trait `{}`",
                            trait_ref.self_ty(),
                            tcx.def_path_str(trait_def_id)
                        ),
                    )
                    .emit();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::net::IpAddr;
use std::io::{Write, ErrorKind};
use std::io::Read;

use mio::*;
use mio::tcp::TcpStream;
use mio::unix::UnixReady;
use network::ClientResult;
use network::Readiness;
use network::BackendConnectionStatus;
use network::protocol::ProtocolResult;
use network::socket::{SocketHandler,SocketResult,server_bind};
use network::protocol::pipe::Pipe;
use network::buffer_queue::BufferQueue;
use pool::Checkout;

use super::header::*;

pub struct SendProxyProtocol<Front:SocketHandler> {
  pub header:         Option<Vec<u8>>,
  pub frontend:       Front,
  pub backend:        Option<TcpStream>,
  pub frontend_token: Token,
  pub backend_token:  Option<Token>,
  pub readiness:      Readiness,
  cursor_header:      usize,
}

impl <Front:SocketHandler + Read> SendProxyProtocol<Front> {
  pub fn new(frontend: Front, frontend_token: Token, backend: Option<TcpStream>) -> Self {
    SendProxyProtocol {
      header: None,
      frontend,
      backend,
      frontend_token,
      backend_token:  None,
      readiness: Readiness {
        front_interest:  UnixReady::hup() | UnixReady::error(),
        back_interest:   UnixReady::from(Ready::writable()) | UnixReady::hup() | UnixReady::error(),
        front_readiness: UnixReady::from(Ready::empty()),
        back_readiness:  UnixReady::from(Ready::empty()),
      },
      cursor_header: 0,
    }
  }

  // The header is send immediately at once upon the connection is establish
  // and prepended before any data.
  pub fn back_writable(&mut self) -> (ProtocolResult, ClientResult) {
    debug!("Writing proxy protocol header");

    if let Some(ref mut socket) = self.backend {
      if let Some(ref mut header) = self.header {
        loop {
          match socket.write(&mut header[self.cursor_header..]) {
            Ok(sz) => {
              self.cursor_header += sz;

              if self.cursor_header == header.len() {
                debug!("Proxy protocol sent, upgrading");
                return (ProtocolResult::Upgrade, ClientResult::Continue)
              }
            },
            Err(e) => {
              debug!("PROXY PROTOCOL {}", e);
              break;
            },
          }
        }
      }
    }
    (ProtocolResult::Continue, ClientResult::Continue)
  }

  pub fn front_socket(&self) -> &TcpStream {
    self.frontend.socket_ref()
  }

  pub fn back_socket(&self) -> Option<&TcpStream> {
    self.backend.as_ref()
  }

  pub fn set_back_socket(&mut self, socket: TcpStream) {
    self.backend = Some(socket);
  }

  pub fn back_token(&self) -> Option<Token> {
    self.backend_token
  }

  pub fn set_back_token(&mut self, token: Token) {
    self.backend_token = Some(token);
  }

  pub fn set_back_connected(&mut self, status: BackendConnectionStatus) {
    if status == BackendConnectionStatus::Connected {
      self.gen_proxy_protocol_header();
    }
  }

  pub fn readiness(&mut self) -> &mut Readiness {
    &mut self.readiness
  }

  fn gen_proxy_protocol_header(&mut self) {
    let addr_frontend = self.frontend.socket_ref().peer_addr().expect("frontend address should be available");

    let addr_backend = self.backend.as_ref().and_then(|socket| {
      socket.peer_addr().map_err(|e| error!("cannot get backend address: {:?}", e)).ok()
    });

    let addr_backend = match addr_backend {
      Some(addr) => addr,
      None       => return,
    };

    // PROXY command hardcoded for now, but we'll use LOCAL when we implement health checks
    let protocol_header = ProxyProtocolHeader::V2(HeaderV2::new(Command::Proxy, addr_frontend, addr_backend));
    self.header = Some(protocol_header.into_bytes());
  }

  pub fn into_pipe(mut self, front_buf: Checkout<BufferQueue>, back_buf: Checkout<BufferQueue>) -> Pipe<Front> {
    let backend_socket = self.backend.take().unwrap();
    let addr = backend_socket.peer_addr().map(|s| s.ip()).ok();

    let mut pipe = Pipe::new(
      self.frontend,
      self.frontend_token,
      Some(backend_socket),
      front_buf,
      back_buf,
      addr,
    );

    pipe.readiness.front_readiness = self.readiness.front_readiness;
    pipe.readiness.back_readiness  = self.readiness.back_readiness;

    if let Some(back_token) = self.backend_token {
      pipe.set_back_token(back_token);
    }

    pipe
  }
}
<commit_msg>Add a unit test for proxy protocol in send mode<commit_after>use std::net::IpAddr;
use std::io::{Write, ErrorKind};
use std::io::Read;

use mio::*;
use mio::tcp::TcpStream;
use mio::unix::UnixReady;
use network::ClientResult;
use network::Readiness;
use network::BackendConnectionStatus;
use network::protocol::ProtocolResult;
use network::socket::{SocketHandler,SocketResult,server_bind};
use network::protocol::pipe::Pipe;
use network::buffer_queue::BufferQueue;
use pool::Checkout;

use super::header::*;

pub struct SendProxyProtocol<Front:SocketHandler> {
  pub header:         Option<Vec<u8>>,
  pub frontend:       Front,
  pub backend:        Option<TcpStream>,
  pub frontend_token: Token,
  pub backend_token:  Option<Token>,
  pub readiness:      Readiness,
  cursor_header:      usize,
}

impl <Front:SocketHandler + Read> SendProxyProtocol<Front> {
  pub fn new(frontend: Front, frontend_token: Token, backend: Option<TcpStream>) -> Self {
    SendProxyProtocol {
      header: None,
      frontend,
      backend,
      frontend_token,
      backend_token:  None,
      readiness: Readiness {
        front_interest:  UnixReady::hup() | UnixReady::error(),
        back_interest:   UnixReady::from(Ready::writable()) | UnixReady::hup() | UnixReady::error(),
        front_readiness: UnixReady::from(Ready::empty()),
        back_readiness:  UnixReady::from(Ready::empty()),
      },
      cursor_header: 0,
    }
  }

  // The header is send immediately at once upon the connection is establish
  // and prepended before any data.
  pub fn back_writable(&mut self) -> (ProtocolResult, ClientResult) {
    debug!("Writing proxy protocol header");

    if let Some(ref mut socket) = self.backend {
      if let Some(ref mut header) = self.header {
        loop {
          match socket.write(&mut header[self.cursor_header..]) {
            Ok(sz) => {
              self.cursor_header += sz;

              if self.cursor_header == header.len() {
                debug!("Proxy protocol sent, upgrading");
                return (ProtocolResult::Upgrade, ClientResult::Continue)
              }
            },
            Err(e) => {
              debug!("PROXY PROTOCOL {}", e);
              break;
            },
          }
        }
      }
    }
    (ProtocolResult::Continue, ClientResult::Continue)
  }

  pub fn front_socket(&self) -> &TcpStream {
    self.frontend.socket_ref()
  }

  pub fn back_socket(&self) -> Option<&TcpStream> {
    self.backend.as_ref()
  }

  pub fn set_back_socket(&mut self, socket: TcpStream) {
    self.backend = Some(socket);
  }

  pub fn back_token(&self) -> Option<Token> {
    self.backend_token
  }

  pub fn set_back_token(&mut self, token: Token) {
    self.backend_token = Some(token);
  }

  pub fn set_back_connected(&mut self, status: BackendConnectionStatus) {
    if status == BackendConnectionStatus::Connected {
      self.gen_proxy_protocol_header();
    }
  }

  pub fn readiness(&mut self) -> &mut Readiness {
    &mut self.readiness
  }

  fn gen_proxy_protocol_header(&mut self) {
    let addr_frontend = self.frontend.socket_ref().peer_addr().expect("frontend address should be available");

    let addr_backend = self.backend.as_ref().and_then(|socket| {
      socket.peer_addr().map_err(|e| error!("cannot get backend address: {:?}", e)).ok()
    });

    let addr_backend = match addr_backend {
      Some(addr) => addr,
      None       => return,
    };

    // PROXY command hardcoded for now, but we'll use LOCAL when we implement health checks
    let protocol_header = ProxyProtocolHeader::V2(HeaderV2::new(Command::Proxy, addr_frontend, addr_backend));
    self.header = Some(protocol_header.into_bytes());
  }

  pub fn into_pipe(mut self, front_buf: Checkout<BufferQueue>, back_buf: Checkout<BufferQueue>) -> Pipe<Front> {
    let backend_socket = self.backend.take().unwrap();
    let addr = backend_socket.peer_addr().map(|s| s.ip()).ok();

    let mut pipe = Pipe::new(
      self.frontend,
      self.frontend_token,
      Some(backend_socket),
      front_buf,
      back_buf,
      addr,
    );

    pipe.readiness.front_readiness = self.readiness.front_readiness;
    pipe.readiness.back_readiness  = self.readiness.back_readiness;

    if let Some(back_token) = self.backend_token {
      pipe.set_back_token(back_token);
    }

    pipe
  }
}

#[cfg(test)]
mod send_test {

  use super::*;

  use parser::proxy_protocol::parse_v2_header;
  use nom::IResult::Done;

  use std::{thread, thread::JoinHandle, time::Duration, net::SocketAddr};
  use mio::net::{TcpListener, TcpStream};
  use std::net::{TcpListener as StdTcpListener, TcpStream as StdTcpStream};

  #[test]
  fn it_should_shend_a_proxy_protocol_header_to_the_upstream_backend() {
    setup_test_logger!();
    let addr_client: SocketAddr = "127.0.0.1:6666".parse().expect("parse address error");
    let addr_backend: SocketAddr = "127.0.0.1:2001".parse().expect("parse address error");

    start_client(addr_client.clone());
    let backend = start_backend(addr_backend.clone());
    start_middleware(addr_client, addr_backend);

    backend.join().expect("Couldn't join on the associated backend");
  }

  // Get connection from the client and connect to the backend
  // When connections are etablish we send the proxy protocol header
  fn start_middleware(addr_client: SocketAddr, addr_backend: SocketAddr) {
    let backend_stream = TcpStream::connect(&addr_backend).expect("could not connect to the backend");
    let client_listener = TcpListener::bind(&addr_client).expect("could not accept client connection");

    let mut client_stream = None;

    loop {
      if let Ok((stream, _addr)) = client_listener.accept() {
        client_stream = Some(stream);
        break;
      }
    }

    let mut send_pp = SendProxyProtocol::new(client_stream.expect("dazdaz"), Token(0), Some(backend_stream));

    send_pp.set_back_connected(BackendConnectionStatus::Connected);

    while (ProtocolResult::Upgrade, ClientResult::Continue) != send_pp.back_writable() {};
  }

  // Only connect to the middleware
  fn start_client(addr: SocketAddr) {
    thread::spawn(move|| {
      loop {
        match StdTcpStream::connect(&addr) {
          Ok(stream) => break,
          Err(_) => {},
        }
      };
    });
  }

  // Get connection from the middleware read on the socket stream.
  // We check if we receive a valid proxy protocol header
  fn start_backend(addr: SocketAddr) -> JoinHandle<()> {
    let listener = StdTcpListener::bind(&addr).expect("could not start backend");

    thread::spawn(move|| {
      let mut buf: [u8; 28] = [0; 28];
      let (mut conn, _) = listener.accept().expect("could not accept connection from light middleware");
      println!("backend get a connection from the middleware");

      conn.set_read_timeout(Some(Duration::from_millis(50)));

      let res = conn.read(&mut buf);

      if let Done(rest, header) =  parse_v2_header(&buf) {
        println!("complete header received");
      } else {
        panic!("incorrect proxy protocol header received");
      }
    })
  }
}
<|endoftext|>


<commit_before>use EventLoopHandle;
use std::cell::RefCell;
use std::io::Error as IoError;
use std::io::Write;
use std::os::raw::{c_int, c_void};
use std::os::unix::io::RawFd;
use std::rc::Rc;
use wayland_sys::server::*;

/// fd_event_source
///
/// A handle to a registered FD event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct FdEventSource<ID> {
    ptr: *mut wl_event_source,
    data: *mut (FdEventSourceImpl<ID>, *mut EventLoopHandle, ID),
}

bitflags!{
    /// Flags to register interest on a file descriptor
    pub struct FdInterest: u32 {
        /// Interest to be notified when the file descriptor is readable
        const READ  = 0x01;
        /// Interest to be notified when the file descriptor is writable
        const WRITE = 0x02;
    }
}

pub fn make_fd_event_source<ID: 'static>(ptr: *mut wl_event_source,
                                         data: Box<(FdEventSourceImpl<ID>, *mut EventLoopHandle, ID)>)
                                         -> FdEventSource<ID> {
    FdEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl<ID> FdEventSource<ID> {
    /// Change the registered interest for this FD
    pub fn update_mask(&mut self, mask: FdInterest) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_fd_update,
                self.ptr,
                mask.bits()
            );
        }
    }

    /// Remove this event source from its event loop
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let data = Box::from_raw(self.data);
            data.2
        }
    }
}

/// Implementation for FD events
pub struct FdEventSourceImpl<ID> {
    /// The FD is ready to be read/written
    ///
    /// Details of the capability state are given as argument.
    pub ready: fn(evlh: &mut EventLoopHandle, idata: &mut ID, fd: RawFd, mask: FdInterest),
    /// An error occured with this FD
    ///
    /// Most likely it won't be usable any longer
    pub error: fn(evlh: &mut EventLoopHandle, idata: &mut ID, fd: RawFd, mask: IoError),
}

pub unsafe extern "C" fn event_source_fd_dispatcher<ID>(fd: c_int, mask: u32, data: *mut c_void) -> c_int
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &mut *(data as *mut (FdEventSourceImpl<ID>, *mut EventLoopHandle, ID));
        let implem = &data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        if mask & 0x08 > 0 {
            // EPOLLERR
            use nix::sys::socket;
            let err = match socket::getsockopt(fd, socket::sockopt::SocketError) {
                Ok(err) => err,
                Err(_) => {
                    // error while retrieving the error code ???
                    let _ = write!(
                        ::std::io::stderr(),
                        "[wayland-server error] Error while retrieving error code on socket {}, aborting.",
                        fd
                    );
                    ::libc::abort();
                }
            };
            (implem.error)(evlh, idata, fd, IoError::from_raw_os_error(err));
        } else if mask & 0x04 > 0 {
            // EPOLLHUP
            (implem.error)(
                evlh,
                idata,
                fd,
                IoError::new(::std::io::ErrorKind::ConnectionAborted, ""),
            )
        } else {
            let mut bits = FdInterest::empty();
            if mask & 0x02 > 0 {
                bits = bits | FdInterest::WRITE;
            }
            if mask & 0x01 > 0 {
                bits = bits | FdInterest::READ;
            }
            (implem.ready)(evlh, idata, fd, bits)
        }
    });
    match ret {
        Ok(()) => return 0, // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for fd {} event source panicked, aborting.",
                fd
            );
            ::libc::abort();
        }
    }
}

/// timer_event_source
///
/// A handle to a registered timer event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct TimerEventSource<ID> {
    ptr: *mut wl_event_source,
    data: *mut (TimerEventSourceImpl<ID>, *mut EventLoopHandle, ID),
}

pub fn make_timer_event_source<ID>(ptr: *mut wl_event_source,
                                   data: Box<(TimerEventSourceImpl<ID>, *mut EventLoopHandle, ID)>)
                                   -> TimerEventSource<ID> {
    TimerEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl<ID> TimerEventSource<ID> {
    /// Set the delay of this timer
    ///
    /// The callback will be called during the next dispatch of the
    /// event loop after this time (in milliseconds) is elapsed.
    ///
    /// Manually the delay to 0 stops the timer (the callback won't be
    /// called).
    pub fn set_delay_ms(&mut self, delay: i32) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_timer_update,
                self.ptr,
                delay
            );
        }
    }

    /// Remove this event source from its event loop
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let data = Box::from_raw(self.data);
            data.2
        }
    }
}

/// Called when the countdown reaches 0
pub type TimerEventSourceImpl<ID> = fn(&mut EventLoopHandle, idata: &mut ID);

pub unsafe extern "C" fn event_source_timer_dispatcher<ID>(data: *mut c_void) -> c_int
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &mut *(data as *mut (TimerEventSourceImpl<ID>, *mut EventLoopHandle, ID));
        let cb = data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        cb(evlh, idata);
    });
    match ret {
        Ok(()) => return 0, // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

/// signal_event_source
///
/// A handle to a registered signal event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct SignalEventSource<ID> {
    ptr: *mut wl_event_source,
    data: *mut (SignalEventSourceImpl<ID>, *mut EventLoopHandle, ID),
}

pub fn make_signal_event_source<ID: 'static>(ptr: *mut wl_event_source,
                                             data: Box<
    (SignalEventSourceImpl<ID>, *mut EventLoopHandle, ID),
>)
                                             -> SignalEventSource<ID> {
    SignalEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl<ID> SignalEventSource<ID> {
    /// Remove this event source from its event loop
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let data = Box::from_raw(self.data);
            data.2
        }
    }
}

/// A signal has been received
///
/// The signal number is given has argument
pub type SignalEventSourceImpl<ID> = fn(
                                      &mut EventLoopHandle,
                                      idata: &mut ID,
                                      signal: ::nix::sys::signal::Signal,
);

pub unsafe extern "C" fn event_source_signal_dispatcher<ID>(signal: c_int, data: *mut c_void) -> c_int
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &mut *(data as *mut (SignalEventSourceImpl<ID>, *mut EventLoopHandle, ID));
        let cb = data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        let sig = match ::nix::sys::signal::Signal::from_c_int(signal) {
            Ok(sig) => sig,
            Err(_) => {
                // Actually, this cannot happen, as we cannot register an event source for
                // an unknown signal...
                let _ = write!(
                    ::std::io::stderr(),
                    "[wayland-server error] Unknown signal in signal event source: {}, aborting.",
                    signal
                );
                ::libc::abort();
            }
        };
        cb(evlh, idata, sig);
    });
    match ret {
        Ok(()) => return 0, // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

/// Idle event source
///
/// A handle to an idle event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct IdleEventSource<ID> {
    ptr: *mut wl_event_source,
    data: Rc<RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>>,
}

pub fn make_idle_event_source<ID>(ptr: *mut wl_event_source,
                                  data: Rc<
    RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>,
>)
                                  -> IdleEventSource<ID> {
    IdleEventSource {
        ptr: ptr,
        data: data,
    }
}

/// The idle-throttled callback
pub type IdleEventSourceImpl<ID> = fn(&mut EventLoopHandle, idata: &mut ID);

impl<ID> IdleEventSource<ID> {
    /// Remove this event source from its event loop
    ///
    /// If this idle callback was not yet dispatched, cancel it.
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        let dispatched = self.data.borrow().3;
        if !dispatched {
            unsafe {
                // unregister this event source
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
                // recreate the outstanding reference that was not consumed
                let _ = Rc::from_raw(&*self.data);
            }
        }
        // we are now the only oustanding reference
        let data = Rc::try_unwrap(self.data)
            .unwrap_or_else(|_| panic!("Idle Rc was not singly owned."))
            .into_inner();
        data.2
    }
}

pub unsafe extern "C" fn event_source_idle_dispatcher<ID>(data: *mut c_void)
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &*(data as *mut RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>);
        let mut data = data.borrow_mut();
        let cb = data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        cb(evlh, idata);
    });
    match ret {
        Ok(()) => {
            // all went well
            // free the refence to the idata, as this event source cannot be called again
            let data =
                Rc::from_raw(data as *mut RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>);
            // store that the dispatching occured
            data.borrow_mut().3 = true;
        }
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}
<commit_msg>Add with_idata to EventSources<commit_after>use EventLoopHandle;
use std::cell::RefCell;
use std::io::Error as IoError;
use std::io::Write;
use std::os::raw::{c_int, c_void};
use std::os::unix::io::RawFd;
use std::rc::Rc;
use wayland_sys::server::*;

/// fd_event_source
///
/// A handle to a registered FD event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct FdEventSource<ID> {
    ptr: *mut wl_event_source,
    data: *mut (FdEventSourceImpl<ID>, *mut EventLoopHandle, ID),
}

bitflags!{
    /// Flags to register interest on a file descriptor
    pub struct FdInterest: u32 {
        /// Interest to be notified when the file descriptor is readable
        const READ  = 0x01;
        /// Interest to be notified when the file descriptor is writable
        const WRITE = 0x02;
    }
}

pub fn make_fd_event_source<ID: 'static>(ptr: *mut wl_event_source,
                                         data: Box<(FdEventSourceImpl<ID>, *mut EventLoopHandle, ID)>)
                                         -> FdEventSource<ID> {
    FdEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl<ID> FdEventSource<ID> {
    /// Change the registered interest for this FD
    pub fn update_mask(&mut self, mask: FdInterest) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_fd_update,
                self.ptr,
                mask.bits()
            );
        }
    }

    /// Access the implementation data without removing it from the `EventLoop`
    pub fn with_idata<F, R>(&mut self, evlh: &mut EventLoopHandle, f: F) -> R
    where
        F: FnOnce(&mut ID, &mut EventLoopHandle) -> R,
    {
        let mut data = unsafe { Box::from_raw(self.data) };
        let res = f(&mut data.2, evlh);
        self.data = Box::into_raw(data);
        res
    }

    /// Remove this event source from its event loop
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let data = Box::from_raw(self.data);
            data.2
        }
    }
}

/// Implementation for FD events
pub struct FdEventSourceImpl<ID> {
    /// The FD is ready to be read/written
    ///
    /// Details of the capability state are given as argument.
    pub ready: fn(evlh: &mut EventLoopHandle, idata: &mut ID, fd: RawFd, mask: FdInterest),
    /// An error occured with this FD
    ///
    /// Most likely it won't be usable any longer
    pub error: fn(evlh: &mut EventLoopHandle, idata: &mut ID, fd: RawFd, mask: IoError),
}

pub unsafe extern "C" fn event_source_fd_dispatcher<ID>(fd: c_int, mask: u32, data: *mut c_void) -> c_int
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &mut *(data as *mut (FdEventSourceImpl<ID>, *mut EventLoopHandle, ID));
        let implem = &data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        if mask & 0x08 > 0 {
            // EPOLLERR
            use nix::sys::socket;
            let err = match socket::getsockopt(fd, socket::sockopt::SocketError) {
                Ok(err) => err,
                Err(_) => {
                    // error while retrieving the error code ???
                    let _ = write!(
                        ::std::io::stderr(),
                        "[wayland-server error] Error while retrieving error code on socket {}, aborting.",
                        fd
                    );
                    ::libc::abort();
                }
            };
            (implem.error)(evlh, idata, fd, IoError::from_raw_os_error(err));
        } else if mask & 0x04 > 0 {
            // EPOLLHUP
            (implem.error)(
                evlh,
                idata,
                fd,
                IoError::new(::std::io::ErrorKind::ConnectionAborted, ""),
            )
        } else {
            let mut bits = FdInterest::empty();
            if mask & 0x02 > 0 {
                bits = bits | FdInterest::WRITE;
            }
            if mask & 0x01 > 0 {
                bits = bits | FdInterest::READ;
            }
            (implem.ready)(evlh, idata, fd, bits)
        }
    });
    match ret {
        Ok(()) => return 0, // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for fd {} event source panicked, aborting.",
                fd
            );
            ::libc::abort();
        }
    }
}

/// timer_event_source
///
/// A handle to a registered timer event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct TimerEventSource<ID> {
    ptr: *mut wl_event_source,
    data: *mut (TimerEventSourceImpl<ID>, *mut EventLoopHandle, ID),
}

pub fn make_timer_event_source<ID>(ptr: *mut wl_event_source,
                                   data: Box<(TimerEventSourceImpl<ID>, *mut EventLoopHandle, ID)>)
                                   -> TimerEventSource<ID> {
    TimerEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl<ID> TimerEventSource<ID> {
    /// Set the delay of this timer
    ///
    /// The callback will be called during the next dispatch of the
    /// event loop after this time (in milliseconds) is elapsed.
    ///
    /// Manually the delay to 0 stops the timer (the callback won't be
    /// called).
    pub fn set_delay_ms(&mut self, delay: i32) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_timer_update,
                self.ptr,
                delay
            );
        }
    }

    /// Access with the implementation data without removing it from the `EventLoop`
    pub fn with_idata<F, R>(&mut self, evlh: &mut EventLoopHandle, f: F) -> R
    where
        F: FnOnce(&mut ID, &mut EventLoopHandle) -> R,
    {
        let mut data = unsafe { Box::from_raw(self.data) };
        let res = f(&mut data.2, evlh);
        self.data = Box::into_raw(data);
        res
    }
    /// Remove this event source from its event loop
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let data = Box::from_raw(self.data);
            data.2
        }
    }
}

/// Called when the countdown reaches 0
pub type TimerEventSourceImpl<ID> = fn(&mut EventLoopHandle, idata: &mut ID);

pub unsafe extern "C" fn event_source_timer_dispatcher<ID>(data: *mut c_void) -> c_int
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &mut *(data as *mut (TimerEventSourceImpl<ID>, *mut EventLoopHandle, ID));
        let cb = data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        cb(evlh, idata);
    });
    match ret {
        Ok(()) => return 0, // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

/// signal_event_source
///
/// A handle to a registered signal event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct SignalEventSource<ID> {
    ptr: *mut wl_event_source,
    data: *mut (SignalEventSourceImpl<ID>, *mut EventLoopHandle, ID),
}

pub fn make_signal_event_source<ID: 'static>(ptr: *mut wl_event_source,
                                             data: Box<
    (SignalEventSourceImpl<ID>, *mut EventLoopHandle, ID),
>)
                                             -> SignalEventSource<ID> {
    SignalEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl<ID> SignalEventSource<ID> {
    /// Access with the implementation data without removing it from the `EventLoop`
    pub fn with_idata<F, R>(&mut self, evlh: &mut EventLoopHandle, f: F) -> R
    where
        F: FnOnce(&mut ID, &mut EventLoopHandle) -> R,
    {
        let mut data = unsafe { Box::from_raw(self.data) };
        let res = f(&mut data.2, evlh);
        self.data = Box::into_raw(data);
        res
    }

    /// Remove this event source from its event loop
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let data = Box::from_raw(self.data);
            data.2
        }
    }
}

/// A signal has been received
///
/// The signal number is given has argument
pub type SignalEventSourceImpl<ID> = fn(
                                      &mut EventLoopHandle,
                                      idata: &mut ID,
                                      signal: ::nix::sys::signal::Signal,
);

pub unsafe extern "C" fn event_source_signal_dispatcher<ID>(signal: c_int, data: *mut c_void) -> c_int
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &mut *(data as *mut (SignalEventSourceImpl<ID>, *mut EventLoopHandle, ID));
        let cb = data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        let sig = match ::nix::sys::signal::Signal::from_c_int(signal) {
            Ok(sig) => sig,
            Err(_) => {
                // Actually, this cannot happen, as we cannot register an event source for
                // an unknown signal...
                let _ = write!(
                    ::std::io::stderr(),
                    "[wayland-server error] Unknown signal in signal event source: {}, aborting.",
                    signal
                );
                ::libc::abort();
            }
        };
        cb(evlh, idata, sig);
    });
    match ret {
        Ok(()) => return 0, // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

/// Idle event source
///
/// A handle to an idle event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct IdleEventSource<ID> {
    ptr: *mut wl_event_source,
    data: Rc<RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>>,
}

pub fn make_idle_event_source<ID>(ptr: *mut wl_event_source,
                                  data: Rc<
    RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>,
>)
                                  -> IdleEventSource<ID> {
    IdleEventSource {
        ptr: ptr,
        data: data,
    }
}

/// The idle-throttled callback
pub type IdleEventSourceImpl<ID> = fn(&mut EventLoopHandle, idata: &mut ID);

impl<ID> IdleEventSource<ID> {
    /// Access with the implementation data without removing it from the `EventLoop`
    pub fn with_idata<F, R>(&mut self, evlh: &mut EventLoopHandle, f: F) -> R
    where
        F: FnOnce(&mut ID, &mut EventLoopHandle) -> R,
    {
        f(&mut self.data.borrow_mut().2, evlh)
    }

    /// Remove this event source from its event loop
    ///
    /// If this idle callback was not yet dispatched, cancel it.
    ///
    /// Returns the implementation data in case you have something to do with it.
    pub fn remove(self) -> ID {
        let dispatched = self.data.borrow().3;
        if !dispatched {
            unsafe {
                // unregister this event source
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
                // recreate the outstanding reference that was not consumed
                let _ = Rc::from_raw(&*self.data);
            }
        }
        // we are now the only oustanding reference
        let data = Rc::try_unwrap(self.data)
            .unwrap_or_else(|_| panic!("Idle Rc was not singly owned."))
            .into_inner();
        data.2
    }
}

pub unsafe extern "C" fn event_source_idle_dispatcher<ID>(data: *mut c_void)
where
    ID: 'static,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let data = &*(data as *mut RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>);
        let mut data = data.borrow_mut();
        let cb = data.0;
        let evlh = &mut *(data.1);
        let idata = &mut data.2;
        cb(evlh, idata);
    });
    match ret {
        Ok(()) => {
            // all went well
            // free the refence to the idata, as this event source cannot be called again
            let data =
                Rc::from_raw(data as *mut RefCell<(IdleEventSourceImpl<ID>, *mut EventLoopHandle, ID, bool)>);
            // store that the dispatching occured
            data.borrow_mut().3 = true;
        }
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}
<|endoftext|>


<commit_before>extern crate regex;

use std::ascii::AsciiExt;
use std::error::Error;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
use std::collections::HashMap;
use std::collections::HashSet;
use regex::Regex;

fn load_dictionary(dictionary_path: &Path) -> (
        HashMap<(char, usize, usize), HashSet<String>>,
        HashMap<usize, HashSet<String>>) {
    let display = dictionary_path.display();

    let file = match File::open(dictionary_path) {
        Err(why) => panic!("couldn't open {}: {}",
                           display,
                           Error::description(&why)),
        Ok(file) => file,
    };

    let mut ch_position_length_map = HashMap::new();
    let mut length_map = HashMap::new();
    let reader = BufReader::new(file);

    for readline in reader.lines() {
        let line = match readline {
            Err(why) => panic!("couldn't read from {}: {}",
                                display,
                                Error::description(&why)),
            Ok(readline) => readline,
        };

        let word = line.trim();
        for (index, ch) in word.to_ascii_lowercase().chars().enumerate() {
            let key = (ch, index, word.len());

            ch_position_length_map.entry(key).or_insert(
                HashSet::new()).insert(word.to_string());
            length_map.entry(word.len()).or_insert(
                HashSet::new()).insert(word.to_string());
        }
    }
    (ch_position_length_map, length_map)
}

fn match_pattern(pattern : &str,
         ch_position_length_map : &HashMap<(char, usize, usize), HashSet<String>>,
         length_map : &HashMap<usize, HashSet<String>>) -> Vec<String> {
    let pattern_parser = Regex::new(
        r"(?P<number>\d+)|(?P<letter>[A-Za-z])").unwrap();

    let mut pattern_length: usize = 0;
    let mut ch_and_index = Vec::new();

    for number_or_letter in pattern_parser.captures_iter(
            &pattern.to_ascii_lowercase()) {
        if number_or_letter.name("number").is_some() {
            let number_as_string = number_or_letter.name("number").unwrap();
            let number: usize = number_as_string.parse().unwrap();
            pattern_length += number;
        } else {
            let match_word = number_or_letter.name("letter").unwrap();
            let ch = match_word.char_indices().next().unwrap().1;
            ch_and_index.push((ch, pattern_length));
            pattern_length += 1;
        }
    }

    if ch_and_index.is_empty() {
        if length_map.contains_key(&pattern_length) {
            return length_map.get(
                &pattern_length).unwrap().iter().cloned().collect();
        } else {
            return Vec::new();
        }
    }

    let mut word_sets = Vec::new();
    for &(ch, index) in ch_and_index.iter() {
        let key = (ch, index as usize, pattern_length as usize);
        if ch_position_length_map.contains_key(&key) {
            word_sets.push(ch_position_length_map.get(&key).unwrap());
        } else {
            // There are no words of pattern_length that ch at index.
            return Vec::new();
        }
    }

    assert!(!word_sets.is_empty());
    if word_sets.len() == 1 {
        return word_sets.get(0).unwrap().iter().cloned().collect();
    }

    word_sets.sort_by(|a, b| a.len().cmp(&b.len()));
    let mut refined_word_set : HashSet<String> =
        word_sets.get(0).unwrap().intersection(
            word_sets.get(1).unwrap()).cloned().collect();

    for word_set in word_sets.iter().skip(2) {
        refined_word_set = refined_word_set.intersection(
            word_set).cloned().collect();
    }

    return refined_word_set.iter().cloned().collect();
}

fn print_matches(words : Vec<String>) {
    if words.is_empty() {
        println!("\t<No Results>");
    } else {
        let mut sorted_words : Vec<String> = words.into_iter().collect();
        sorted_words.sort();
        for word in sorted_words {
            println!("\t{}", word);
        }
    }
}

fn main() {
    let dictionary_path = Path::new("/usr/share/dict/words");
    let (ch_position_length_map, length_map) = load_dictionary(
        &dictionary_path);

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let matches = match_pattern(&line.unwrap(),
                                    &ch_position_length_map,
                                    &length_map);
        print_matches(matches);
    }
}<commit_msg>Work it terms of &str when possible.<commit_after>extern crate regex;

use std::ascii::AsciiExt;
use std::error::Error;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
use std::collections::HashMap;
use std::collections::HashSet;
use regex::Regex;

fn load_dictionary(dictionary_path: &Path) -> Vec<String> {
    let display = dictionary_path.display();

    let file = match File::open(dictionary_path) {
        Err(why) => panic!("couldn't open {}: {}",
                           display,
                           Error::description(&why)),
        Ok(file) => file,
    };
    let reader = BufReader::new(file);
    let mut words = Vec::new();

    for readline in reader.lines() {
        let line = match readline {
            Err(why) => panic!("couldn't read from {}: {}",
                                display,
                                Error::description(&why)),
            Ok(readline) => readline,
        };

        words.push(line.trim().to_string());
    }
    return words;
}

fn build_maps(words: &Vec<String>) -> (
        HashMap<(char, usize, usize), HashSet<&str>>,
        HashMap<usize, HashSet<&str>>) {
    let mut ch_position_length_map :
        HashMap<(char, usize, usize), HashSet<&str>> = HashMap::new();
    let mut length_map : HashMap<usize, HashSet<&str>> = HashMap::new();

    for word in words.iter() {
        for (index, ch) in word.to_ascii_lowercase().chars().enumerate() {
            let key = (ch, index, word.len());

            ch_position_length_map.entry(key).or_insert(
                HashSet::new()).insert(word);
            length_map.entry(word.len()).or_insert(
                HashSet::new()).insert(word);
        }
    }
    (ch_position_length_map, length_map)
}

fn match_pattern<'a>(pattern : &str,
         ch_position_length_map : &HashMap<(char, usize, usize), HashSet<&'a str>>,
         length_map : &HashMap<usize, HashSet<&'a str>>) -> Vec<&'a str> {
    let pattern_parser = Regex::new(
        r"(?P<number>\d+)|(?P<letter>[A-Za-z])").unwrap();

    let mut pattern_length: usize = 0;
    let mut ch_and_index = Vec::new();

    for number_or_letter in pattern_parser.captures_iter(
            &pattern.to_ascii_lowercase()) {
        if number_or_letter.name("number").is_some() {
            let number_as_string = number_or_letter.name("number").unwrap();
            let number: usize = number_as_string.parse().unwrap();
            pattern_length += number;
        } else {
            let match_word = number_or_letter.name("letter").unwrap();
            let ch = match_word.char_indices().next().unwrap().1;
            ch_and_index.push((ch, pattern_length));
            pattern_length += 1;
        }
    }

    if ch_and_index.is_empty() {
        if length_map.contains_key(&pattern_length) {
            return length_map.get(
                &pattern_length).unwrap().iter().cloned().collect();
        } else {
            return Vec::new();
        }
    }

    let mut word_sets : Vec<&HashSet<&str>> = Vec::new();
    for &(ch, index) in ch_and_index.iter() {
        let key = (ch, index as usize, pattern_length as usize);
        if ch_position_length_map.contains_key(&key) {
            word_sets.push(ch_position_length_map.get(&key).unwrap());
        } else {
            // There are no words of pattern_length that ch at index.
            return Vec::new();
        }
    }

    assert!(!word_sets.is_empty());
    if word_sets.len() == 1 {
        return word_sets.get(0).unwrap().iter().cloned().collect();
    }

    word_sets.sort_by(|a, b| a.len().cmp(&b.len()));
    let mut refined_word_set : HashSet<&str> =
        word_sets.get(0).unwrap().intersection(
            word_sets.get(1).unwrap()).cloned().collect();

    for word_set in word_sets.iter().skip(2) {
        refined_word_set = refined_word_set.intersection(
            word_set).cloned().collect();
    }

    return refined_word_set.iter().cloned().collect();
}

fn print_matches(words : Vec<&str>) {
    if words.is_empty() {
        println!("\t<No Results>");
    } else {
        let mut sorted_words : Vec<&str> = words.into_iter().collect();
        sorted_words.sort();
        for word in sorted_words {
            println!("\t{}", word);
        }
    }
}

fn main() {
    let dictionary_path = Path::new("/usr/share/dict/words");
    let words = load_dictionary(&dictionary_path);
    let (ch_position_length_map, length_map) = build_maps(&words);

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let matches = match_pattern(&line.unwrap(),
                                    &ch_position_length_map,
                                    &length_map);
        print_matches(matches);
    }
}<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!
//!  + [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  + The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  + The [ELF Format Specification](elfspec)
//!
//! [elfspec]: http://www.skyfree.org/linux/references/ELF_Format.pdf
#![feature(core_intrinsics)]
#![feature(try_from)]
#![no_std]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate macro_attr;

extern crate memory;

use core::{ convert, ops, mem, slice };
use core::convert::TryFrom;

macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty:ty; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty:ty; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}

pub mod section;
pub mod file;
pub mod program;

/// An ELF section header.
pub type Section<'a> = section::Header<'a>;
/// An ELF header file.
pub type FileHeader<W> = file::HeaderRepr<W>;

/// TODO: should ELF have its own error type?
pub type ElfResult<T> = Result<T, &'static str>;

pub trait ElfWord: Sized + Copy + Clone
                         + ops::Add<Self> + ops::Sub<Self>
                         + ops::Mul<Self> + ops::Div<Self>
                         + ops::Shl<Self> + ops::Shr<Self> { }
impl ElfWord for u64 { }
impl ElfWord for u32 { }

#[cfg(target_pointer_width = "32")]
type DefaultWord = u32;
#[cfg(target_pointer_width = "64")]
type DefaultWord = u64;

/// Hack to make the type-system let me do what I want
trait ValidatesWord<Word: ElfWord> {
    fn check(&self) -> ElfResult<()>;
}

/// A handle on a parsed ELF binary
///  TODO: do we want this to own a HashMap of section names to section headers,
///        to speed up section lookup?
//          - eliza, 03/08/2017
#[derive(Debug)]
pub struct Image< 'a
                , Word = DefaultWord
                , ProgHeader = program::Header<Word = Word>
                , Header = FileHeader<Word>
                >
where Word: ElfWord + 'a
    , ProgHeader: program::Header<Word = Word> + Sized +'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// the binary's [file header](file/trait.Header.html)
    pub header: &'a Header
  , /// references to each [section header](section/struct.Header.html)
    pub sections: &'a [section::Header<'a>]
  , /// references to each [program header](program/trait.Header.html)
    pub program_headers: &'a [ProgHeader]
  , /// the raw binary contents of the ELF binary.
    /// note that this includes the _entire_ binary contents of the file,
    /// so the file header and each section header is included in this slice.
    binary: &'a [u8]
}

impl<'a, Word, ProgHeader, Header> Image<'a, Word, ProgHeader, Header>
where Word: ElfWord + 'a
    , ProgHeader: program::Header<Word = Word> + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// Returns the section header [string table].
    ///
    /// [string table]: section/struct.StrTable.html
    pub fn sh_str_table(&'a self) -> section::StrTable<'a> {
        // TODO: do we want to validate that the string table index is
        //       reasonable (e.g. it's not longer than the binary)?
        //          - eliza, 03/08/2017
        // TODO: do we want to cache a ref to the string table?
        //          - eliza, 03/08/2017
        section::StrTable::from(&self.binary[self.header.sh_str_idx()..])
    }

}

impl<'a, Word, PH, H> TryFrom<&'a [u8]> for Image<'a, Word, PH, H>
where Word: ElfWord + 'a
    , PH: program::Header<Word = Word> + 'a
    , H: file::Header<Word = Word> + 'a
    , &'a H: convert::TryFrom<&'a [u8], Err = &'static str>
    {

    type Err = &'static str;

    fn try_from(bytes: &'a [u8]) -> ElfResult<Self> {
        let header: &'a H = <&'a H>::try_from(bytes)?;

        // TODO: this won't actually work; need to rewrite section headers to
        //       work the same as program headers.
        //          - eliza, 03/14/2017
        let sections = unsafe { extract_from_slice::<Section<'a>>(
            &bytes[header.sh_range()]
          , 0
          , header.sh_count()
        )? };
        let prog_headers = unsafe { extract_from_slice::<PH>(
            &bytes[header.ph_range()]
          , 0
          , header.ph_count()
        )? };
        Ok(Image { header: header
              , sections: sections
              , program_headers: prog_headers
              , binary: bytes
        })
    }
}

/// Extract `n` instances of type `T` from a byte slice.
///
/// This is essentially just a _slightly_ safer wrapper around
/// [`slice::from_raw_parts`]. Unlike `from_raw_parts`, this function takes
/// a valid byte slice, rather than a pointer. Therefore, some of the safety
/// issues with `from_raw_parts` are avoided:
///
/// + the lifetime (`'slice`) of the returned slice should be the same as the
///   lifetime of the input slice (`data`), rather than inferred arbitrarily.
/// + this function will panic rather than reading past the end of the slice.
///
/// # Arguments
///
/// + `data`: the byte slice to extract a slice of `&[T]`s from
/// + `offset`: a start offset into `data`
/// + `n`: the number of instances of `T` which should be contained
///        in `data[offset..]`
///
/// # Safety
///
/// While this function is safer than [`slice::from_raw_parts`],
/// it is still unsafe for the following reasons:
///
/// + The contents of `data` may not be able to be interpreted as instances of
///   type `T`.
///
/// # Caveats
///
/// + If `n` == 0, this will give you an `&[]`. Just a warning.
//    thanks to Max for making  me figure this out.
/// + `offset` must be aligned on a `T`-sized boundary.
///
/// # Panics
///
/// + If the index `offset` is longer than `T`
///
/// TODO: rewrite this as a `TryFrom` implementation (see issue #85)
//          - eliza, 03/09/2017
///       wait, possibly we should NOT do that. actually we should
///       almost certainly not do that. since this function is unsafe,
///       but `TryFrom` is not, and because this would be WAY generic.
//          - eliza, 03/09/2017
/// TODO: is this general enough to move into util?
//          - eliza, 03/09/2017
/// TODO: refactor this to take a `RangeArgument`?
//          - eliza, 03/13/2017
///       or, we could just remove the offset and expect the caller to
///       offset the slice?
//          - eliza, 03/14/2017
///
/// [`slice::from_raw_parts`]: https://doc.rust-lang.org/stable/std/slice/fn.from_raw_parts.html
unsafe fn extract_from_slice<'slice, T: Sized>( data: &'slice [u8]
                                              , offset: usize
                                              , n: usize)
                                              -> ElfResult<&'slice [T]> {
    use core::intrinsics::type_name;
    if offset % mem::align_of::<T>() != 0 {
        // TODO: these error messages don't contain as much information as they
        //       used to, since the return type is `&'static str` that can't be
        //       dynamically formatted as the panic was. refactor this?
        //       (e.g. should ELF get its own error type?)
        //        - eliza, 03/15/2017
        Err("extract_from_slice: Offset not aligned on type T sized boundary!")
        // assert!(
        //        , "Offset {} not aligned on a {}-sized boundary (must be \
        //           divisible by {})."
        //        , offset, type_name::<T>(), mem::align_of::<T>()
        //        );
    } else if data.len() - offset < mem::size_of::<T>() * n {
        Err("extract_from_slice: Slice too short to contain n instances of T!")
        // assert!(
        //        , "Slice too short to contain {} objects of type {}"
        //        , n, type_name::<T>()
        //        );
    } else {
        Ok(slice::from_raw_parts(data[offset..].as_ptr() as *const T, n))
    }
}
<commit_msg>docs(elf): add some comments in elf::Image<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!
//!  + [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  + The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  + The [ELF Format Specification](elfspec)
//!
//! [elfspec]: http://www.skyfree.org/linux/references/ELF_Format.pdf
#![feature(core_intrinsics)]
#![feature(try_from)]
#![no_std]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate macro_attr;

extern crate memory;

use core::{ convert, ops, mem, slice };
use core::convert::TryFrom;

macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty:ty; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty:ty; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}

pub mod section;
pub mod file;
pub mod program;

/// An ELF section header.
pub type Section<'a> = section::Header<'a>;
/// An ELF header file.
pub type FileHeader<W> = file::HeaderRepr<W>;

/// TODO: should ELF have its own error type?
pub type ElfResult<T> = Result<T, &'static str>;

pub trait ElfWord: Sized + Copy + Clone
                         + ops::Add<Self> + ops::Sub<Self>
                         + ops::Mul<Self> + ops::Div<Self>
                         + ops::Shl<Self> + ops::Shr<Self> { }
impl ElfWord for u64 { }
impl ElfWord for u32 { }

#[cfg(target_pointer_width = "32")]
type DefaultWord = u32;
#[cfg(target_pointer_width = "64")]
type DefaultWord = u64;

/// Hack to make the type-system let me do what I want
trait ValidatesWord<Word: ElfWord> {
    fn check(&self) -> ElfResult<()>;
}

/// A handle on a parsed ELF binary
///  TODO: do we want this to own a HashMap of section names to section headers,
///        to speed up section lookup?
//          - eliza, 03/08/2017
#[derive(Debug)]
pub struct Image< 'a
                , Word = DefaultWord
                , ProgHeader = program::Header<Word = Word>
                , Header = FileHeader<Word>
                > // jesus christ
where Word: ElfWord + 'a
    , ProgHeader: program::Header<Word = Word> + Sized + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// the binary's [file header](file/trait.Header.html)
    pub header: &'a Header
  , /// references to each [section header](section/struct.Header.html)
    pub sections: &'a [section::Header<'a>]
  , /// references to each [program header](program/trait.Header.html)
    pub program_headers: &'a [ProgHeader]
  , /// the raw binary contents of the ELF binary.
    /// note that this includes the _entire_ binary contents of the file,
    /// so the file header and each section header is included in this slice.
    binary: &'a [u8]
}

impl<'a, Word, ProgHeader, Header> Image<'a, Word, ProgHeader, Header>
where Word: ElfWord + 'a
    , ProgHeader: program::Header<Word = Word> + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// Returns the section header [string table].
    ///
    /// [string table]: section/struct.StrTable.html
    pub fn sh_str_table(&'a self) -> section::StrTable<'a> {
        // TODO: do we want to validate that the string table index is
        //       reasonable (e.g. it's not longer than the binary)?
        //          - eliza, 03/08/2017
        // TODO: do we want to cache a ref to the string table?
        //          - eliza, 03/08/2017
        section::StrTable::from(&self.binary[self.header.sh_str_idx()..])
    }

}

impl<'a, Word, PH, H> TryFrom<&'a [u8]> for Image<'a, Word, PH, H>
where Word: ElfWord + 'a
    , PH: program::Header<Word = Word> + 'a
    , H: file::Header<Word = Word> + 'a
    , &'a H: convert::TryFrom<&'a [u8], Err = &'static str>
    {

    type Err = &'static str;

    fn try_from(bytes: &'a [u8]) -> ElfResult<Self> {
        let header: &'a H = <&'a H>::try_from(bytes)?;

        // TODO: this won't actually work; need to rewrite section headers to
        //       work the same as program headers.
        //          - eliza, 03/14/2017
        let sections = unsafe { extract_from_slice::<Section<'a>>(
            &bytes[header.sh_range()]
          , 0
          , header.sh_count()
        )? };
        let prog_headers = unsafe { extract_from_slice::<PH>(
            &bytes[header.ph_range()]
          , 0
          , header.ph_count()
        )? };
        Ok(Image { header: header
              , sections: sections
              , program_headers: prog_headers
              , binary: bytes
        })
    }
}

/// Extract `n` instances of type `T` from a byte slice.
///
/// This is essentially just a _slightly_ safer wrapper around
/// [`slice::from_raw_parts`]. Unlike `from_raw_parts`, this function takes
/// a valid byte slice, rather than a pointer. Therefore, some of the safety
/// issues with `from_raw_parts` are avoided:
///
/// + the lifetime (`'slice`) of the returned slice should be the same as the
///   lifetime of the input slice (`data`), rather than inferred arbitrarily.
/// + this function will panic rather than reading past the end of the slice.
///
/// # Arguments
///
/// + `data`: the byte slice to extract a slice of `&[T]`s from
/// + `offset`: a start offset into `data`
/// + `n`: the number of instances of `T` which should be contained
///        in `data[offset..]`
///
/// # Safety
///
/// While this function is safer than [`slice::from_raw_parts`],
/// it is still unsafe for the following reasons:
///
/// + The contents of `data` may not be able to be interpreted as instances of
///   type `T`.
///
/// # Caveats
///
/// + If `n` == 0, this will give you an `&[]`. Just a warning.
//    thanks to Max for making  me figure this out.
/// + `offset` must be aligned on a `T`-sized boundary.
///
/// # Panics
///
/// + If the index `offset` is longer than `T`
///
/// TODO: rewrite this as a `TryFrom` implementation (see issue #85)
//          - eliza, 03/09/2017
///       wait, possibly we should NOT do that. actually we should
///       almost certainly not do that. since this function is unsafe,
///       but `TryFrom` is not, and because this would be WAY generic.
//          - eliza, 03/09/2017
/// TODO: is this general enough to move into util?
//          - eliza, 03/09/2017
/// TODO: refactor this to take a `RangeArgument`?
//          - eliza, 03/13/2017
///       or, we could just remove the offset and expect the caller to
///       offset the slice?
//          - eliza, 03/14/2017
///
/// [`slice::from_raw_parts`]: https://doc.rust-lang.org/stable/std/slice/fn.from_raw_parts.html
unsafe fn extract_from_slice<'slice, T: Sized>( data: &'slice [u8]
                                              , offset: usize
                                              , n: usize)
                                              -> ElfResult<&'slice [T]> {
    use core::intrinsics::type_name;
    if offset % mem::align_of::<T>() != 0 {
        // TODO: these error messages don't contain as much information as they
        //       used to, since the return type is `&'static str` that can't be
        //       dynamically formatted as the panic was. refactor this?
        //       (e.g. should ELF get its own error type?)
        //        - eliza, 03/15/2017
        Err("extract_from_slice: Offset not aligned on type T sized boundary!")
        // assert!(
        //        , "Offset {} not aligned on a {}-sized boundary (must be \
        //           divisible by {})."
        //        , offset, type_name::<T>(), mem::align_of::<T>()
        //        );
    } else if data.len() - offset < mem::size_of::<T>() * n {
        Err("extract_from_slice: Slice too short to contain n instances of T!")
        // assert!(
        //        , "Slice too short to contain {} objects of type {}"
        //        , n, type_name::<T>()
        //        );
    } else {
        Ok(slice::from_raw_parts(data[offset..].as_ptr() as *const T, n))
    }
}
<|endoftext|>