<commit_before>use crate::check::regionck::RegionCtxt;

use crate::hir;
use crate::hir::def_id::DefId;
use crate::util::common::ErrorReported;
use rustc::infer::outlives::env::OutlivesEnvironment;
use rustc::infer::{InferOk, SuppressRegionErrors};
use rustc::middle::region;
use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt};
use rustc::ty::error::TypeError;
use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc::ty::subst::{Subst, SubstsRef};
use rustc::ty::{self, Predicate, Ty, TyCtxt};

use syntax_pos::Span;

/// This function confirms that the `Drop` implementation identified by
/// `drop_impl_did` is not any more specialized than the type it is
/// attached to (Issue #8142).
///
/// This means:
///
/// 1. The self type must be nominal (this is already checked during
///    coherence),
///
/// 2. The generic region/type parameters of the impl's self type must
///    all be parameters of the Drop impl itself (i.e., no
///    specialization like `impl Drop for Foo<i32>`), and,
///
/// 3. Any bounds on the generic parameters must be reflected in the
///    struct/enum definition for the nominal type itself (i.e.
///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
    let dtor_self_type = tcx.type_of(drop_impl_did);
    let dtor_predicates = tcx.predicates_of(drop_impl_did);
    match dtor_self_type.kind {
        ty::Adt(adt_def, self_to_impl_substs) => {
            ensure_drop_params_and_item_params_correspond(
                tcx,
                drop_impl_did,
                dtor_self_type,
                adt_def.did,
            )?;

            ensure_drop_predicates_are_implied_by_item_defn(
                tcx,
                drop_impl_did,
                dtor_predicates,
                adt_def.did,
                self_to_impl_substs,
            )
        }
        _ => {
            // Destructors only work on nominal types.  This was
            // already checked by coherence, but compilation may
            // not have been terminated.
            let span = tcx.def_span(drop_impl_did);
            tcx.sess.delay_span_bug(span,
                &format!("should have been rejected by coherence check: {}", dtor_self_type));
            Err(ErrorReported)
        }
    }
}

fn ensure_drop_params_and_item_params_correspond<'tcx>(
    tcx: TyCtxt<'tcx>,
    drop_impl_did: DefId,
    drop_impl_ty: Ty<'tcx>,
    self_type_did: DefId,
) -> Result<(), ErrorReported> {
    let drop_impl_hir_id = tcx.hir().as_local_hir_id(drop_impl_did).unwrap();

    // check that the impl type can be made to match the trait type.

    tcx.infer_ctxt().enter(|ref infcx| {
        let impl_param_env = tcx.param_env(self_type_did);
        let tcx = infcx.tcx;
        let mut fulfillment_cx = TraitEngine::new(tcx);

        let named_type = tcx.type_of(self_type_did);

        let drop_impl_span = tcx.def_span(drop_impl_did);
        let fresh_impl_substs = infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
        let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);

        let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
        match infcx
            .at(cause, impl_param_env)
            .eq(named_type, fresh_impl_self_ty)
        {
            Ok(InferOk { obligations, .. }) => {
                fulfillment_cx.register_predicate_obligations(infcx, obligations);
            }
            Err(_) => {
                let item_span = tcx.def_span(self_type_did);
                struct_span_err!(
                    tcx.sess,
                    drop_impl_span,
                    E0366,
                    "Implementations of Drop cannot be specialized"
                ).span_note(
                    item_span,
                    "Use same sequence of generic type and region \
                     parameters that is on the struct/enum definition",
                )
                    .emit();
                return Err(ErrorReported);
            }
        }

        if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
            // this could be reached when we get lazy normalization
            infcx.report_fulfillment_errors(errors, None, false);
            return Err(ErrorReported);
        }

        let region_scope_tree = region::ScopeTree::default();

        // NB. It seems a bit... suspicious to use an empty param-env
        // here. The correct thing, I imagine, would be
        // `OutlivesEnvironment::new(impl_param_env)`, which would
        // allow region solving to take any `a: 'b` relations on the
        // impl into account. But I could not create a test case where
        // it did the wrong thing, so I chose to preserve existing
        // behavior, since it ought to be simply more
        // conservative. -nmatsakis
        let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());

        infcx.resolve_regions_and_report_errors(
            drop_impl_did,
            &region_scope_tree,
            &outlives_env,
            SuppressRegionErrors::default(),
        );
        Ok(())
    })
}

/// Confirms that every predicate imposed by dtor_predicates is
/// implied by assuming the predicates attached to self_type_did.
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
    tcx: TyCtxt<'tcx>,
    drop_impl_did: DefId,
    dtor_predicates: ty::GenericPredicates<'tcx>,
    self_type_did: DefId,
    self_to_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorReported> {
    let mut result = Ok(());

    // Here is an example, analogous to that from
    // `compare_impl_method`.
    //
    // Consider a struct type:
    //
    //     struct Type<'c, 'b:'c, 'a> {
    //         x: &'a Contents            // (contents are irrelevant;
    //         y: &'c Cell<&'b Contents>, //  only the bounds matter for our purposes.)
    //     }
    //
    // and a Drop impl:
    //
    //     impl<'z, 'y:'z, 'x:'y> Drop for P<'z, 'y, 'x> {
    //         fn drop(&mut self) { self.y.set(self.x); } // (only legal if 'x: 'y)
    //     }
    //
    // We start out with self_to_impl_substs, that maps the generic
    // parameters of Type to that of the Drop impl.
    //
    //     self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x}
    //
    // Applying this to the predicates (i.e., assumptions) provided by the item
    // definition yields the instantiated assumptions:
    //
    //     ['y : 'z]
    //
    // We then check all of the predicates of the Drop impl:
    //
    //     ['y:'z, 'x:'y]
    //
    // and ensure each is in the list of instantiated
    // assumptions. Here, `'y:'z` is present, but `'x:'y` is
    // absent. So we report an error that the Drop impl injected a
    // predicate that is not present on the struct definition.

    let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did).unwrap();

    let drop_impl_span = tcx.def_span(drop_impl_did);

    // We can assume the predicates attached to struct/enum definition
    // hold.
    let generic_assumptions = tcx.predicates_of(self_type_did);

    let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
    let assumptions_in_impl_context = assumptions_in_impl_context.predicates;

    let self_param_env = tcx.param_env(self_type_did);

    // An earlier version of this code attempted to do this checking
    // via the traits::fulfill machinery. However, it ran into trouble
    // since the fulfill machinery merely turns outlives-predicates
    // 'a:'b and T:'b into region inference constraints. It is simpler
    // just to look for all the predicates directly.

    assert_eq!(dtor_predicates.parent, None);
    for (predicate, _) in dtor_predicates.predicates {
        // (We do not need to worry about deep analysis of type
        // expressions etc because the Drop impls are already forced
        // to take on a structure that is roughly an alpha-renaming of
        // the generic parameters of the item definition.)

        // This path now just checks *all* predicates via an instantiation of
        // the `SimpleEqRelation`, which simply forwards to the `relate` machinery
        // after taking care of anonymizing late bound regions.
        //
        // However, it may be more efficient in the future to batch
        // the analysis together via the fulfill (see comment above regarding
        // the usage of the fulfill machinery), rather than the
        // repeated `.iter().any(..)` calls.

        // This closure is a more robust way to check `Predicate` equality
        // than simple `==` checks (which were the previous implementation).
        // It relies on `ty::relate` for `TraitPredicate` and `ProjectionPredicate`
        // (which implement the Relate trait), while delegating on simple equality
        // for the other `Predicate`.
        // This implementation solves (Issue #59497) and (Issue #58311).
        // It is unclear to me at the moment whether the approach based on `relate`
        // could be extended easily also to the other `Predicate`.
        let predicate_matches_closure = |p: &'_ Predicate<'tcx>| {
            let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
            match (predicate, p) {
                (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(),
                (Predicate::Projection(a), Predicate::Projection(b)) => {
                    relator.relate(a, b).is_ok()
                }
                _ => predicate == p,
            }
        };

        if !assumptions_in_impl_context.iter().any(predicate_matches_closure) {
            let item_span = tcx.hir().span(self_type_hir_id);
            struct_span_err!(
                tcx.sess,
                drop_impl_span,
                E0367,
                "The requirement `{}` is added only by the Drop impl.",
                predicate
            ).span_note(
                item_span,
                "The same requirement must be part of \
                 the struct/enum definition",
            )
                .emit();
            result = Err(ErrorReported);
        }
    }

    result
}

/// This function is not only checking that the dropck obligations are met for
/// the given type, but it's also currently preventing non-regular recursion in
/// types from causing stack overflows (dropck_no_diverge_on_nonregular_*.rs).
crate fn check_drop_obligations<'a, 'tcx>(
    rcx: &mut RegionCtxt<'a, 'tcx>,
    ty: Ty<'tcx>,
    span: Span,
    body_id: hir::HirId,
) -> Result<(), ErrorReported> {
    debug!("check_drop_obligations typ: {:?}", ty);

    let cause = &ObligationCause::misc(span, body_id);
    let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty);
    debug!("dropck_outlives = {:#?}", infer_ok);
    rcx.fcx.register_infer_ok_obligations(infer_ok);

    Ok(())
}

// This is an implementation of the TypeRelation trait with the
// aim of simply comparing for equality (without side-effects).
// It is not intended to be used anywhere else other than here.
crate struct SimpleEqRelation<'tcx> {
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'tcx> SimpleEqRelation<'tcx> {
    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> SimpleEqRelation<'tcx> {
        SimpleEqRelation { tcx, param_env }
    }
}

impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn param_env(&self) -> ty::ParamEnv<'tcx> {
        self.param_env
    }

    fn tag(&self) -> &'static str {
        "dropck::SimpleEqRelation"
    }

    fn a_is_expected(&self) -> bool {
        true
    }

    fn relate_with_variance<T: Relate<'tcx>>(
        &mut self,
        _: ty::Variance,
        a: &T,
        b: &T,
    ) -> RelateResult<'tcx, T> {
        // Here we ignore variance because we require drop impl's types
        // to be *exactly* the same as to the ones in the struct definition.
        self.relate(a, b)
    }

    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
        debug!("SimpleEqRelation::tys(a={:?}, b={:?})", a, b);
        ty::relate::super_relate_tys(self, a, b)
    }

    fn regions(
        &mut self,
        a: ty::Region<'tcx>,
        b: ty::Region<'tcx>,
    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
        debug!("SimpleEqRelation::regions(a={:?}, b={:?})", a, b);

        // We can just equate the regions because LBRs have been
        // already anonymized.
        if a == b {
            Ok(a)
        } else {
            // I'm not sure is this `TypeError` is the right one, but
            // it should not matter as it won't be checked (the dropck
            // will emit its own, more informative and higher-level errors
            // in case anything goes wrong).
            Err(TypeError::RegionsPlaceholderMismatch)
        }
    }

    fn consts(
        &mut self,
        a: &'tcx ty::Const<'tcx>,
        b: &'tcx ty::Const<'tcx>,
    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
        debug!("SimpleEqRelation::consts(a={:?}, b={:?})", a, b);
        ty::relate::super_relate_consts(self, a, b)
    }

    fn binders<T>(
        &mut self,
        a: &ty::Binder<T>,
        b: &ty::Binder<T>,
    ) -> RelateResult<'tcx, ty::Binder<T>>
    where
        T: Relate<'tcx>,
    {
        debug!("SimpleEqRelation::binders({:?}: {:?}", a, b);

        // Anonymizing the LBRs is necessary to solve (Issue #59497).
        // After we do so, it should be totally fine to skip the binders.
        let anon_a = self.tcx.anonymize_late_bound_regions(a);
        let anon_b = self.tcx.anonymize_late_bound_regions(b);
        self.relate(anon_a.skip_binder(), anon_b.skip_binder())?;

        Ok(a.clone())
    }
}
<commit_msg>Formatting fixes<commit_after>use crate::check::regionck::RegionCtxt;

use crate::hir;
use crate::hir::def_id::DefId;
use crate::util::common::ErrorReported;
use rustc::infer::outlives::env::OutlivesEnvironment;
use rustc::infer::{InferOk, SuppressRegionErrors};
use rustc::middle::region;
use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt};
use rustc::ty::error::TypeError;
use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc::ty::subst::{Subst, SubstsRef};
use rustc::ty::{self, Predicate, Ty, TyCtxt};

use syntax_pos::Span;

/// This function confirms that the `Drop` implementation identified by
/// `drop_impl_did` is not any more specialized than the type it is
/// attached to (Issue #8142).
///
/// This means:
///
/// 1. The self type must be nominal (this is already checked during
///    coherence),
///
/// 2. The generic region/type parameters of the impl's self type must
///    all be parameters of the Drop impl itself (i.e., no
///    specialization like `impl Drop for Foo<i32>`), and,
///
/// 3. Any bounds on the generic parameters must be reflected in the
///    struct/enum definition for the nominal type itself (i.e.
///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
    let dtor_self_type = tcx.type_of(drop_impl_did);
    let dtor_predicates = tcx.predicates_of(drop_impl_did);
    match dtor_self_type.kind {
        ty::Adt(adt_def, self_to_impl_substs) => {
            ensure_drop_params_and_item_params_correspond(
                tcx,
                drop_impl_did,
                dtor_self_type,
                adt_def.did,
            )?;

            ensure_drop_predicates_are_implied_by_item_defn(
                tcx,
                drop_impl_did,
                dtor_predicates,
                adt_def.did,
                self_to_impl_substs,
            )
        }
        _ => {
            // Destructors only work on nominal types.  This was
            // already checked by coherence, but compilation may
            // not have been terminated.
            let span = tcx.def_span(drop_impl_did);
            tcx.sess.delay_span_bug(
                span,
                &format!("should have been rejected by coherence check: {}", dtor_self_type),
            );
            Err(ErrorReported)
        }
    }
}

fn ensure_drop_params_and_item_params_correspond<'tcx>(
    tcx: TyCtxt<'tcx>,
    drop_impl_did: DefId,
    drop_impl_ty: Ty<'tcx>,
    self_type_did: DefId,
) -> Result<(), ErrorReported> {
    let drop_impl_hir_id = tcx.hir().as_local_hir_id(drop_impl_did).unwrap();

    // check that the impl type can be made to match the trait type.

    tcx.infer_ctxt().enter(|ref infcx| {
        let impl_param_env = tcx.param_env(self_type_did);
        let tcx = infcx.tcx;
        let mut fulfillment_cx = TraitEngine::new(tcx);

        let named_type = tcx.type_of(self_type_did);

        let drop_impl_span = tcx.def_span(drop_impl_did);
        let fresh_impl_substs = infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
        let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);

        let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
        match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) {
            Ok(InferOk { obligations, .. }) => {
                fulfillment_cx.register_predicate_obligations(infcx, obligations);
            }
            Err(_) => {
                let item_span = tcx.def_span(self_type_did);
                struct_span_err!(
                    tcx.sess,
                    drop_impl_span,
                    E0366,
                    "Implementations of Drop cannot be specialized"
                )
                .span_note(
                    item_span,
                    "Use same sequence of generic type and region \
                     parameters that is on the struct/enum definition",
                )
                .emit();
                return Err(ErrorReported);
            }
        }

        if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
            // this could be reached when we get lazy normalization
            infcx.report_fulfillment_errors(errors, None, false);
            return Err(ErrorReported);
        }

        let region_scope_tree = region::ScopeTree::default();

        // NB. It seems a bit... suspicious to use an empty param-env
        // here. The correct thing, I imagine, would be
        // `OutlivesEnvironment::new(impl_param_env)`, which would
        // allow region solving to take any `a: 'b` relations on the
        // impl into account. But I could not create a test case where
        // it did the wrong thing, so I chose to preserve existing
        // behavior, since it ought to be simply more
        // conservative. -nmatsakis
        let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());

        infcx.resolve_regions_and_report_errors(
            drop_impl_did,
            &region_scope_tree,
            &outlives_env,
            SuppressRegionErrors::default(),
        );
        Ok(())
    })
}

/// Confirms that every predicate imposed by dtor_predicates is
/// implied by assuming the predicates attached to self_type_did.
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
    tcx: TyCtxt<'tcx>,
    drop_impl_did: DefId,
    dtor_predicates: ty::GenericPredicates<'tcx>,
    self_type_did: DefId,
    self_to_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorReported> {
    let mut result = Ok(());

    // Here is an example, analogous to that from
    // `compare_impl_method`.
    //
    // Consider a struct type:
    //
    //     struct Type<'c, 'b:'c, 'a> {
    //         x: &'a Contents            // (contents are irrelevant;
    //         y: &'c Cell<&'b Contents>, //  only the bounds matter for our purposes.)
    //     }
    //
    // and a Drop impl:
    //
    //     impl<'z, 'y:'z, 'x:'y> Drop for P<'z, 'y, 'x> {
    //         fn drop(&mut self) { self.y.set(self.x); } // (only legal if 'x: 'y)
    //     }
    //
    // We start out with self_to_impl_substs, that maps the generic
    // parameters of Type to that of the Drop impl.
    //
    //     self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x}
    //
    // Applying this to the predicates (i.e., assumptions) provided by the item
    // definition yields the instantiated assumptions:
    //
    //     ['y : 'z]
    //
    // We then check all of the predicates of the Drop impl:
    //
    //     ['y:'z, 'x:'y]
    //
    // and ensure each is in the list of instantiated
    // assumptions. Here, `'y:'z` is present, but `'x:'y` is
    // absent. So we report an error that the Drop impl injected a
    // predicate that is not present on the struct definition.

    let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did).unwrap();

    let drop_impl_span = tcx.def_span(drop_impl_did);

    // We can assume the predicates attached to struct/enum definition
    // hold.
    let generic_assumptions = tcx.predicates_of(self_type_did);

    let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
    let assumptions_in_impl_context = assumptions_in_impl_context.predicates;

    let self_param_env = tcx.param_env(self_type_did);

    // An earlier version of this code attempted to do this checking
    // via the traits::fulfill machinery. However, it ran into trouble
    // since the fulfill machinery merely turns outlives-predicates
    // 'a:'b and T:'b into region inference constraints. It is simpler
    // just to look for all the predicates directly.

    assert_eq!(dtor_predicates.parent, None);
    for (predicate, _) in dtor_predicates.predicates {
        // (We do not need to worry about deep analysis of type
        // expressions etc because the Drop impls are already forced
        // to take on a structure that is roughly an alpha-renaming of
        // the generic parameters of the item definition.)

        // This path now just checks *all* predicates via an instantiation of
        // the `SimpleEqRelation`, which simply forwards to the `relate` machinery
        // after taking care of anonymizing late bound regions.
        //
        // However, it may be more efficient in the future to batch
        // the analysis together via the fulfill (see comment above regarding
        // the usage of the fulfill machinery), rather than the
        // repeated `.iter().any(..)` calls.

        // This closure is a more robust way to check `Predicate` equality
        // than simple `==` checks (which were the previous implementation).
        // It relies on `ty::relate` for `TraitPredicate` and `ProjectionPredicate`
        // (which implement the Relate trait), while delegating on simple equality
        // for the other `Predicate`.
        // This implementation solves (Issue #59497) and (Issue #58311).
        // It is unclear to me at the moment whether the approach based on `relate`
        // could be extended easily also to the other `Predicate`.
        let predicate_matches_closure = |p: &'_ Predicate<'tcx>| {
            let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
            match (predicate, p) {
                (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(),
                (Predicate::Projection(a), Predicate::Projection(b)) => {
                    relator.relate(a, b).is_ok()
                }
                _ => predicate == p,
            }
        };

        if !assumptions_in_impl_context.iter().any(predicate_matches_closure) {
            let item_span = tcx.hir().span(self_type_hir_id);
            struct_span_err!(
                tcx.sess,
                drop_impl_span,
                E0367,
                "The requirement `{}` is added only by the Drop impl.",
                predicate
            )
            .span_note(
                item_span,
                "The same requirement must be part of \
                 the struct/enum definition",
            )
            .emit();
            result = Err(ErrorReported);
        }
    }

    result
}

/// This function is not only checking that the dropck obligations are met for
/// the given type, but it's also currently preventing non-regular recursion in
/// types from causing stack overflows (dropck_no_diverge_on_nonregular_*.rs).
crate fn check_drop_obligations<'a, 'tcx>(
    rcx: &mut RegionCtxt<'a, 'tcx>,
    ty: Ty<'tcx>,
    span: Span,
    body_id: hir::HirId,
) -> Result<(), ErrorReported> {
    debug!("check_drop_obligations typ: {:?}", ty);

    let cause = &ObligationCause::misc(span, body_id);
    let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty);
    debug!("dropck_outlives = {:#?}", infer_ok);
    rcx.fcx.register_infer_ok_obligations(infer_ok);

    Ok(())
}

// This is an implementation of the TypeRelation trait with the
// aim of simply comparing for equality (without side-effects).
// It is not intended to be used anywhere else other than here.
crate struct SimpleEqRelation<'tcx> {
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'tcx> SimpleEqRelation<'tcx> {
    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> SimpleEqRelation<'tcx> {
        SimpleEqRelation { tcx, param_env }
    }
}

impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn param_env(&self) -> ty::ParamEnv<'tcx> {
        self.param_env
    }

    fn tag(&self) -> &'static str {
        "dropck::SimpleEqRelation"
    }

    fn a_is_expected(&self) -> bool {
        true
    }

    fn relate_with_variance<T: Relate<'tcx>>(
        &mut self,
        _: ty::Variance,
        a: &T,
        b: &T,
    ) -> RelateResult<'tcx, T> {
        // Here we ignore variance because we require drop impl's types
        // to be *exactly* the same as to the ones in the struct definition.
        self.relate(a, b)
    }

    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
        debug!("SimpleEqRelation::tys(a={:?}, b={:?})", a, b);
        ty::relate::super_relate_tys(self, a, b)
    }

    fn regions(
        &mut self,
        a: ty::Region<'tcx>,
        b: ty::Region<'tcx>,
    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
        debug!("SimpleEqRelation::regions(a={:?}, b={:?})", a, b);

        // We can just equate the regions because LBRs have been
        // already anonymized.
        if a == b {
            Ok(a)
        } else {
            // I'm not sure is this `TypeError` is the right one, but
            // it should not matter as it won't be checked (the dropck
            // will emit its own, more informative and higher-level errors
            // in case anything goes wrong).
            Err(TypeError::RegionsPlaceholderMismatch)
        }
    }

    fn consts(
        &mut self,
        a: &'tcx ty::Const<'tcx>,
        b: &'tcx ty::Const<'tcx>,
    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
        debug!("SimpleEqRelation::consts(a={:?}, b={:?})", a, b);
        ty::relate::super_relate_consts(self, a, b)
    }

    fn binders<T>(
        &mut self,
        a: &ty::Binder<T>,
        b: &ty::Binder<T>,
    ) -> RelateResult<'tcx, ty::Binder<T>>
    where
        T: Relate<'tcx>,
    {
        debug!("SimpleEqRelation::binders({:?}: {:?}", a, b);

        // Anonymizing the LBRs is necessary to solve (Issue #59497).
        // After we do so, it should be totally fine to skip the binders.
        let anon_a = self.tcx.anonymize_late_bound_regions(a);
        let anon_b = self.tcx.anonymize_late_bound_regions(b);
        self.relate(anon_a.skip_binder(), anon_b.skip_binder())?;

        Ok(a.clone())
    }
}
<|endoftext|>


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

use std::cell::RefCell;
use std::collections::BTreeMap;

use ast;
use ast::{Ident, Name, TokenTree};
use codemap::Span;
use ext::base::{ExtCtxt, MacEager, MacResult};
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
use util::small_vector::SmallVector;

// Maximum width of any line in an extended error description (inclusive).
const MAX_DESCRIPTION_WIDTH: usize = 80;

thread_local! {
    static REGISTERED_DIAGNOSTICS: RefCell<ErrorMap> = {
        RefCell::new(BTreeMap::new())
    }
}

/// Error information type.
pub struct ErrorInfo {
    pub description: Option<Name>,
    pub use_site: Option
}

/// Mapping from error codes to metadata.
pub type ErrorMap = BTreeMap<Name, ErrorInfo>;

fn with_registered_diagnostics<T, F>(f: F) -> T where
    F: FnOnce(&mut ErrorMap) -> T,
{
    REGISTERED_DIAGNOSTICS.with(move |slot| {
        f(&mut *slot.borrow_mut())
    })
}

pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt,
                                   span: Span,
                                   token_tree: &[TokenTree])
                                   -> Box<MacResult+'cx> {
    let code = match (token_tree.len(), token_tree.get(0)) {
        (1, Some(&ast::TtToken(_, token::Ident(code, _)))) => code,
        _ => unreachable!()
    };

    with_registered_diagnostics(|diagnostics| {
        match diagnostics.get_mut(&code.name) {
            // Previously used errors.
            Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => {
                ecx.span_warn(span, &format!(
                    "diagnostic code {} already used", &token::get_ident(code)
                ));
                ecx.span_note(previous_span, "previous invocation");
            }
            // Newly used errors.
            Some(ref mut info) => {
                info.use_site = Some(span);
            }
            // Unregistered errors.
            None => {
                ecx.span_err(span, &format!(
                    "used diagnostic code {} not registered", &token::get_ident(code)
                ));
            }
        }
    });
    MacEager::expr(ecx.expr_tuple(span, Vec::new()))
}

pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
                                       span: Span,
                                       token_tree: &[TokenTree])
                                       -> Box<MacResult+'cx> {
    let (code, description) = match (
        token_tree.len(),
        token_tree.get(0),
        token_tree.get(1),
        token_tree.get(2)
    ) {
        (1, Some(&ast::TtToken(_, token::Ident(ref code, _))), None, None) => {
            (code, None)
        },
        (3, Some(&ast::TtToken(_, token::Ident(ref code, _))),
            Some(&ast::TtToken(_, token::Comma)),
            Some(&ast::TtToken(_, token::Literal(token::StrRaw(description, _), None)))) => {
            (code, Some(description))
        }
        _ => unreachable!()
    };
    // Check that the description starts and ends with a newline and doesn't
    // overflow the maximum line width.
    description.map(|raw_msg| {
        let msg = raw_msg.as_str();
        if !msg.starts_with("\n") || !msg.ends_with("\n") {
            ecx.span_err(span, &format!(
                "description for error code {} doesn't start and end with a newline",
                token::get_ident(*code)
            ));
        }
        if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH) {
            ecx.span_err(span, &format!(
                "description for error code {} contains a line longer than {} characters",
                token::get_ident(*code), MAX_DESCRIPTION_WIDTH
            ));
        }
    });
    // Add the error to the map.
    with_registered_diagnostics(|diagnostics| {
        let info = ErrorInfo {
            description: description,
            use_site: None
        };
        if diagnostics.insert(code.name, info).is_some() {
            ecx.span_err(span, &format!(
                "diagnostic code {} already registered", &token::get_ident(*code)
            ));
        }
    });
    let sym = Ident::new(token::gensym(&(
        "__register_diagnostic_".to_string() + &token::get_ident(*code)
    )));
    MacEager::items(SmallVector::many(vec![
        ecx.item_mod(
            span,
            span,
            sym,
            Vec::new(),
            Vec::new()
        )
    ]))
}

pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                                          span: Span,
                                          token_tree: &[TokenTree])
                                          -> Box<MacResult+'cx> {
    assert_eq!(token_tree.len(), 3);
    let (_crate_name, name) = match (&token_tree[0], &token_tree[2]) {
        (
            // Crate name.
            &ast::TtToken(_, token::Ident(ref crate_name, _)),
            // DIAGNOSTICS ident.
            &ast::TtToken(_, token::Ident(ref name, _))
        ) => (crate_name.as_str(), name),
        _ => unreachable!()
    };

    // FIXME (#25705): we used to ensure error code uniqueness and
    // output error description JSON metadata here, but the approach
    // employed was too brittle.

    // Construct the output expression.
    let (count, expr) =
        with_registered_diagnostics(|diagnostics| {
            let descriptions: Vec<P<ast::Expr>> =
                diagnostics.iter().filter_map(|(code, info)| {
                    info.description.map(|description| {
                        ecx.expr_tuple(span, vec![
                            ecx.expr_str(span, token::get_name(*code)),
                            ecx.expr_str(span, token::get_name(description))
                        ])
                    })
                }).collect();
            (descriptions.len(), ecx.expr_vec(span, descriptions))
        });

    let static_ = ecx.lifetime(span, ecx.name_of("'static"));
    let ty_str = ecx.ty_rptr(
        span,
        ecx.ty_ident(span, ecx.ident_of("str")),
        Some(static_),
        ast::MutImmutable,
    );

    let ty = ecx.ty(
        span,
        ast::TyFixedLengthVec(
            ecx.ty(
                span,
                ast::TyTup(vec![ty_str.clone(), ty_str])
            ),
            ecx.expr_usize(span, count),
        ),
    );

    MacEager::items(SmallVector::many(vec![
        P(ast::Item {
            ident: name.clone(),
            attrs: Vec::new(),
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemConst(
                ty,
                expr,
            ),
            vis: ast::Public,
            span: span,
        })
    ]))
}
<commit_msg>Auto merge of #26290 - michaelsproul:url-line-limit, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cell::RefCell;
use std::collections::BTreeMap;

use ast;
use ast::{Ident, Name, TokenTree};
use codemap::Span;
use ext::base::{ExtCtxt, MacEager, MacResult};
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
use util::small_vector::SmallVector;

// Maximum width of any line in an extended error description (inclusive).
const MAX_DESCRIPTION_WIDTH: usize = 80;

thread_local! {
    static REGISTERED_DIAGNOSTICS: RefCell<ErrorMap> = {
        RefCell::new(BTreeMap::new())
    }
}

/// Error information type.
pub struct ErrorInfo {
    pub description: Option<Name>,
    pub use_site: Option
}

/// Mapping from error codes to metadata.
pub type ErrorMap = BTreeMap<Name, ErrorInfo>;

fn with_registered_diagnostics<T, F>(f: F) -> T where
    F: FnOnce(&mut ErrorMap) -> T,
{
    REGISTERED_DIAGNOSTICS.with(move |slot| {
        f(&mut *slot.borrow_mut())
    })
}

pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt,
                                   span: Span,
                                   token_tree: &[TokenTree])
                                   -> Box<MacResult+'cx> {
    let code = match (token_tree.len(), token_tree.get(0)) {
        (1, Some(&ast::TtToken(_, token::Ident(code, _)))) => code,
        _ => unreachable!()
    };

    with_registered_diagnostics(|diagnostics| {
        match diagnostics.get_mut(&code.name) {
            // Previously used errors.
            Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => {
                ecx.span_warn(span, &format!(
                    "diagnostic code {} already used", &token::get_ident(code)
                ));
                ecx.span_note(previous_span, "previous invocation");
            }
            // Newly used errors.
            Some(ref mut info) => {
                info.use_site = Some(span);
            }
            // Unregistered errors.
            None => {
                ecx.span_err(span, &format!(
                    "used diagnostic code {} not registered", &token::get_ident(code)
                ));
            }
        }
    });
    MacEager::expr(ecx.expr_tuple(span, Vec::new()))
}

pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
                                       span: Span,
                                       token_tree: &[TokenTree])
                                       -> Box<MacResult+'cx> {
    let (code, description) = match (
        token_tree.len(),
        token_tree.get(0),
        token_tree.get(1),
        token_tree.get(2)
    ) {
        (1, Some(&ast::TtToken(_, token::Ident(ref code, _))), None, None) => {
            (code, None)
        },
        (3, Some(&ast::TtToken(_, token::Ident(ref code, _))),
            Some(&ast::TtToken(_, token::Comma)),
            Some(&ast::TtToken(_, token::Literal(token::StrRaw(description, _), None)))) => {
            (code, Some(description))
        }
        _ => unreachable!()
    };

    // Check that the description starts and ends with a newline and doesn't
    // overflow the maximum line width.
    description.map(|raw_msg| {
        let msg = raw_msg.as_str();
        if !msg.starts_with("\n") || !msg.ends_with("\n") {
            ecx.span_err(span, &format!(
                "description for error code {} doesn't start and end with a newline",
                token::get_ident(*code)
            ));
        }

        // URLs can be unavoidably longer than the line limit, so we allow them.
        // Allowed format is: `[name]: http://rust-lang.org/`
        let is_url = |l: &str| l.starts_with('[') && l.contains("]:") && l.contains("http");

        if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) {
            ecx.span_err(span, &format!(
                "description for error code {} contains a line longer than {} characters.\n\
                 if you're inserting a long URL use the footnote style to bypass this check.",
                token::get_ident(*code), MAX_DESCRIPTION_WIDTH
            ));
        }
    });
    // Add the error to the map.
    with_registered_diagnostics(|diagnostics| {
        let info = ErrorInfo {
            description: description,
            use_site: None
        };
        if diagnostics.insert(code.name, info).is_some() {
            ecx.span_err(span, &format!(
                "diagnostic code {} already registered", &token::get_ident(*code)
            ));
        }
    });
    let sym = Ident::new(token::gensym(&(
        "__register_diagnostic_".to_string() + &token::get_ident(*code)
    )));
    MacEager::items(SmallVector::many(vec![
        ecx.item_mod(
            span,
            span,
            sym,
            Vec::new(),
            Vec::new()
        )
    ]))
}

pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                                          span: Span,
                                          token_tree: &[TokenTree])
                                          -> Box<MacResult+'cx> {
    assert_eq!(token_tree.len(), 3);
    let (_crate_name, name) = match (&token_tree[0], &token_tree[2]) {
        (
            // Crate name.
            &ast::TtToken(_, token::Ident(ref crate_name, _)),
            // DIAGNOSTICS ident.
            &ast::TtToken(_, token::Ident(ref name, _))
        ) => (crate_name.as_str(), name),
        _ => unreachable!()
    };

    // FIXME (#25705): we used to ensure error code uniqueness and
    // output error description JSON metadata here, but the approach
    // employed was too brittle.

    // Construct the output expression.
    let (count, expr) =
        with_registered_diagnostics(|diagnostics| {
            let descriptions: Vec<P<ast::Expr>> =
                diagnostics.iter().filter_map(|(code, info)| {
                    info.description.map(|description| {
                        ecx.expr_tuple(span, vec![
                            ecx.expr_str(span, token::get_name(*code)),
                            ecx.expr_str(span, token::get_name(description))
                        ])
                    })
                }).collect();
            (descriptions.len(), ecx.expr_vec(span, descriptions))
        });

    let static_ = ecx.lifetime(span, ecx.name_of("'static"));
    let ty_str = ecx.ty_rptr(
        span,
        ecx.ty_ident(span, ecx.ident_of("str")),
        Some(static_),
        ast::MutImmutable,
    );

    let ty = ecx.ty(
        span,
        ast::TyFixedLengthVec(
            ecx.ty(
                span,
                ast::TyTup(vec![ty_str.clone(), ty_str])
            ),
            ecx.expr_usize(span, count),
        ),
    );

    MacEager::items(SmallVector::many(vec![
        P(ast::Item {
            ident: name.clone(),
            attrs: Vec::new(),
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemConst(
                ty,
                expr,
            ),
            vis: ast::Public,
            span: span,
        })
    ]))
}
<|endoftext|>


<commit_before>/*!
A binding for SDL2_gfx.
 */

#![crate_id="sdl2_gfx#sdl2_gfx:0.1"]
#![crate_type = "lib"]
#![desc = "SDL2_gfx bindings and wrappers"]
#![comment = "SDL2_gfx bindings and wrappers"]
#![license = "MIT"]

#![feature(globs, macro_rules)]

extern crate libc;
extern crate sdl2;

use libc::{c_int, c_long};
use std::ptr;
use std::fmt;
use std::c_str::CString;
use std::num::FromPrimitive;
use sdl2::surface::Surface;
use sdl2::get_error;
use sdl2::pixels;
use sdl2::pixels::Color;
use sdl2::pixels::ll::SDL_Color;
use sdl2::rwops::RWops;

// Setup linking for all targets.
#[link(kind="framework", name="SDL2_gfx")]
extern {}

//#[allow(non_camel_case_types, dead_code)]

pub mod primitives;
pub mod rotozoom;
pub mod framerate;
pub mod imagefilter;
<commit_msg>fix link args<commit_after>/*!
A binding for SDL2_gfx.
 */

#![crate_id="sdl2_gfx#sdl2_gfx:0.1"]
#![crate_type = "lib"]
#![desc = "SDL2_gfx bindings and wrappers"]
#![comment = "SDL2_gfx bindings and wrappers"]
#![license = "MIT"]

#![feature(globs, macro_rules)]

extern crate libc;
extern crate sdl2;

use libc::{c_int, c_long};
use std::ptr;
use std::fmt;
use std::c_str::CString;
use std::num::FromPrimitive;
use sdl2::surface::Surface;
use sdl2::get_error;
use sdl2::pixels;
use sdl2::pixels::Color;
use sdl2::pixels::ll::SDL_Color;
use sdl2::rwops::RWops;

// Setup linking for all targets.
#[link(name="SDL2_gfx")]
extern {}

//#[allow(non_camel_case_types, dead_code)]

pub mod primitives;
pub mod rotozoom;
pub mod framerate;
pub mod imagefilter;
<|endoftext|>


<commit_before>use futures_01::executor::{
    spawn as spawn01, Notify as Notify01, NotifyHandle as NotifyHandle01,
    Spawn as Spawn01, UnsafeNotify as UnsafeNotify01,
};
use futures_01::{
    Async as Async01, AsyncSink as AsyncSink01, Future as Future01,
    Sink as Sink01, Stream as Stream01,
};
use futures_core::{task as task03, Future as Future03, Stream as Stream03};
use std::pin::Pin;
use std::task::Waker;
use futures_sink::Sink as Sink03;

/// Converts a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite
/// object to a futures 0.3-compatible version,
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct Compat01As03<T> {
    pub(crate) inner: Spawn01<T>,
}

impl<T> Unpin for Compat01As03<T> {}

impl<T> Compat01As03<T> {
    /// Wraps a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite
    /// object in a futures 0.3-compatible wrapper.
    pub fn new(object: T) -> Compat01As03<T> {
        Compat01As03 {
            inner: spawn01(object),
        }
    }

    fn in_notify<R>(&mut self, waker: &Waker, f: impl FnOnce(&mut T) -> R) -> R {
        let notify = &WakerToHandle(waker);
        self.inner.poll_fn_notify(notify, 0, f)
    }
}

/// Extension trait for futures 0.1 [`Future`](futures::future::Future)
pub trait Future01CompatExt: Future01 {
    /// Converts a futures 0.1
    /// [`Future<Item = T, Error = E>`](futures::future::Future)
    /// into a futures 0.3
    /// [`Future<Output = Result<T, E>>`](futures_core::future::Future).
    fn compat(self) -> Compat01As03<Self>
    where
        Self: Sized,
    {
        Compat01As03::new(self)
    }
}
impl<Fut: Future01> Future01CompatExt for Fut {}

/// Extension trait for futures 0.1 [`Stream`](futures::stream::Stream)
pub trait Stream01CompatExt: Stream01 {
    /// Converts a futures 0.1
    /// [`Stream<Item = T, Error = E>`](futures::stream::Stream)
    /// into a futures 0.3
    /// [`Stream<Item = Result<T, E>>`](futures_core::stream::Stream).
    fn compat(self) -> Compat01As03<Self>
    where
        Self: Sized,
    {
        Compat01As03::new(self)
    }
}
impl<St: Stream01> Stream01CompatExt for St {}

/// Extension trait for futures 0.1 [`Sink`](futures::sink::Sink)
pub trait Sink01CompatExt: Sink01 {
    /// Converts a futures 0.1
    /// [`Sink<SinkItem = T, SinkError = E>`](futures::sink::Sink)
    /// into a futures 0.3
    /// [`Sink<SinkItem = T, SinkError = E>`](futures_sink::sink::Sink).
    fn sink_compat(self) -> Compat01As03Sink<Self, Self::SinkItem>
    where
        Self: Sized,
    {
        Compat01As03Sink::new(self)
    }
}
impl<Si: Sink01> Sink01CompatExt for Si {}

fn poll_01_to_03<T, E>(x: Result<Async01<T>, E>) -> task03::Poll<Result<T, E>> {
    match x {
        Ok(Async01::Ready(t)) => task03::Poll::Ready(Ok(t)),
        Ok(Async01::NotReady) => task03::Poll::Pending,
        Err(e) => task03::Poll::Ready(Err(e)),
    }
}

impl<Fut: Future01> Future03 for Compat01As03<Fut> {
    type Output = Result<Fut::Item, Fut::Error>;

    fn poll(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Self::Output> {
        poll_01_to_03(self.in_notify(waker, Future01::poll))
    }
}

impl<St: Stream01> Stream03 for Compat01As03<St> {
    type Item = Result<St::Item, St::Error>;

    fn poll_next(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Option<Self::Item>> {
        match self.in_notify(waker, Stream01::poll) {
            Ok(Async01::Ready(Some(t))) => task03::Poll::Ready(Some(Ok(t))),
            Ok(Async01::Ready(None)) => task03::Poll::Ready(None),
            Ok(Async01::NotReady) => task03::Poll::Pending,
            Err(e) => task03::Poll::Ready(Some(Err(e))),
        }
    }
}

/// Converts a futures 0.1 Sink object to a futures 0.3-compatible version
#[derive(Debug)]
#[must_use = "sinks do nothing unless polled"]
pub struct Compat01As03Sink<S, SinkItem> {
    pub(crate) inner: Spawn01<S>,
    pub(crate) buffer: Option<SinkItem>,
    pub(crate) close_started: bool,
}

impl<S, SinkItem> Unpin for Compat01As03Sink<S, SinkItem> {}

impl<S, SinkItem> Compat01As03Sink<S, SinkItem> {
    /// Wraps a futures 0.1 Sink object in a futures 0.3-compatible wrapper.
    pub fn new(inner: S) -> Compat01As03Sink<S, SinkItem> {
        Compat01As03Sink {
            inner: spawn01(inner),
            buffer: None,
            close_started: false
        }
    }

    fn in_notify<R>(
        &mut self,
        lw: &LocalWaker,
        f: impl FnOnce(&mut S) -> R,
    ) -> R {
        let notify = &WakerToHandle(lw.as_waker());
        self.inner.poll_fn_notify(notify, 0, f)
    }
}

impl<S, SinkItem> Stream03 for Compat01As03Sink<S, SinkItem>
where
    S: Stream01,
{
    type Item = Result<S::Item, S::Error>;

    fn poll_next(
        mut self: Pin<&mut Self>,
        lw: &LocalWaker,
    ) -> task03::Poll<Option<Self::Item>> {
        match self.in_notify(lw, |f| f.poll()) {
            Ok(Async01::Ready(Some(t))) => task03::Poll::Ready(Some(Ok(t))),
            Ok(Async01::Ready(None)) => task03::Poll::Ready(None),
            Ok(Async01::NotReady) => task03::Poll::Pending,
            Err(e) => task03::Poll::Ready(Some(Err(e))),
        }
    }
}

impl<S, SinkItem> Sink03 for Compat01As03Sink<S, SinkItem>
where
    S: Sink01<SinkItem = SinkItem>,
{
    type SinkItem = SinkItem;
    type SinkError = S::SinkError;

    fn start_send(
        mut self: Pin<&mut Self>,
        item: Self::SinkItem,
    ) -> Result<(), Self::SinkError> {
        debug_assert!(self.buffer.is_none());
        self.buffer = Some(item);
        Ok(())
    }

    fn poll_ready(
        mut self: Pin<&mut Self>,
        lw: &LocalWaker,
    ) -> task03::Poll<Result<(), Self::SinkError>> {
        match self.buffer.take() {
            Some(item) => match self.in_notify(lw, |f| f.start_send(item)) {
                Ok(AsyncSink01::Ready) => task03::Poll::Ready(Ok(())),
                Ok(AsyncSink01::NotReady(i)) => {
                    self.buffer = Some(i);
                    task03::Poll::Pending
                }
                Err(e) => task03::Poll::Ready(Err(e)),
            },
            None => task03::Poll::Ready(Ok(())),
        }
    }

    fn poll_flush(
        mut self: Pin<&mut Self>,
        lw: &LocalWaker,
    ) -> task03::Poll<Result<(), Self::SinkError>> {
        let item = self.buffer.take();
        match self.in_notify(lw, |f| match item {
            Some(i) => match f.start_send(i) {
                Ok(AsyncSink01::Ready) => f.poll_complete().map(|i| (i, None)),
                Ok(AsyncSink01::NotReady(t)) => {
                    Ok((Async01::NotReady, Some(t)))
                }
                Err(e) => Err(e),
            },
            None => f.poll_complete().map(|i| (i, None)),
        }) {
            Ok((Async01::Ready(_), _)) => task03::Poll::Ready(Ok(())),
            Ok((Async01::NotReady, item)) => {
                self.buffer = item;
                task03::Poll::Pending
            }
            Err(e) => task03::Poll::Ready(Err(e)),
        }
    }

    fn poll_close(
        mut self: Pin<&mut Self>,
        lw: &LocalWaker,
    ) -> task03::Poll<Result<(), Self::SinkError>> {
        let item = self.buffer.take();
        let close_started = self.close_started;

        let result = self.in_notify(lw, |f| {
            if !close_started {
                if let Some(item) = item {
                    if let AsyncSink01::NotReady(item) = f.start_send(item)? {
                        return Ok((Async01::NotReady, Some(item), false));
                    }
                }

                if let Async01::NotReady = f.poll_complete()? {
                    return Ok((Async01::NotReady, None, false));
                }
            }

            Ok((<S as Sink01>::close(f)?, None, true))
        });

        match result {
            Ok((Async01::Ready(_), _, _)) => task03::Poll::Ready(Ok(())),
            Ok((Async01::NotReady, item, close_started)) => {
                self.buffer = item;
                self.close_started = close_started;
                task03::Poll::Pending
            }
            Err(e) => task03::Poll::Ready(Err(e)),
        }
    }
}

struct NotifyWaker(task03::Waker);

#[derive(Clone)]
struct WakerToHandle<'a>(&'a task03::Waker);

impl<'a> From<WakerToHandle<'a>> for NotifyHandle01 {
    fn from(handle: WakerToHandle<'a>) -> NotifyHandle01 {
        let ptr = Box::new(NotifyWaker(handle.0.clone()));

        unsafe { NotifyHandle01::new(Box::into_raw(ptr)) }
    }
}

impl Notify01 for NotifyWaker {
    fn notify(&self, _: usize) {
        self.0.wake();
    }
}

unsafe impl UnsafeNotify01 for NotifyWaker {
    unsafe fn clone_raw(&self) -> NotifyHandle01 {
        WakerToHandle(&self.0).into()
    }

    unsafe fn drop_raw(&self) {
        let ptr: *const dyn UnsafeNotify01 = self;
        drop(Box::from_raw(ptr as *mut dyn UnsafeNotify01));
    }
}

#[cfg(feature = "io-compat")]
mod io {
    use super::*;
    use futures_io::{
        AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03, Initializer,
    };
    use std::io::Error;
    use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01};

    impl<R: AsyncRead01> AsyncRead03 for Compat01As03<R> {
        unsafe fn initializer(&self) -> Initializer {
            // check if `prepare_uninitialized_buffer` needs zeroing
            if self.inner.get_ref().prepare_uninitialized_buffer(&mut [1]) {
                Initializer::zeroing()
            } else {
                Initializer::nop()
            }
        }

        fn poll_read(&mut self, waker: &task03::Waker, buf: &mut [u8])
            -> task03::Poll<Result<usize, Error>>
        {
            poll_01_to_03(self.in_notify(waker, |x| x.poll_read(buf)))
        }
    }

    impl<W: AsyncWrite01> AsyncWrite03 for Compat01As03<W> {
        fn poll_write(&mut self, waker: &task03::Waker, buf: &[u8])
            -> task03::Poll<Result<usize, Error>>
        {
            poll_01_to_03(self.in_notify(waker, |x| x.poll_write(buf)))
        }

        fn poll_flush(&mut self, waker: &task03::Waker)
            -> task03::Poll<Result<(), Error>>
        {
            poll_01_to_03(self.in_notify(waker, AsyncWrite01::poll_flush))
        }

        fn poll_close(&mut self, waker: &task03::Waker)
            -> task03::Poll<Result<(), Error>>
        {
            poll_01_to_03(self.in_notify(waker, AsyncWrite01::shutdown))
        }
    }
}
<commit_msg>Fix last remaining localwaker references<commit_after>use futures_01::executor::{
    spawn as spawn01, Notify as Notify01, NotifyHandle as NotifyHandle01,
    Spawn as Spawn01, UnsafeNotify as UnsafeNotify01,
};
use futures_01::{
    Async as Async01, AsyncSink as AsyncSink01, Future as Future01,
    Sink as Sink01, Stream as Stream01,
};
use futures_core::{task as task03, Future as Future03, Stream as Stream03};
use std::pin::Pin;
use std::task::Waker;
use futures_sink::Sink as Sink03;

/// Converts a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite
/// object to a futures 0.3-compatible version,
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct Compat01As03<T> {
    pub(crate) inner: Spawn01<T>,
}

impl<T> Unpin for Compat01As03<T> {}

impl<T> Compat01As03<T> {
    /// Wraps a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite
    /// object in a futures 0.3-compatible wrapper.
    pub fn new(object: T) -> Compat01As03<T> {
        Compat01As03 {
            inner: spawn01(object),
        }
    }

    fn in_notify<R>(&mut self, waker: &Waker, f: impl FnOnce(&mut T) -> R) -> R {
        let notify = &WakerToHandle(waker);
        self.inner.poll_fn_notify(notify, 0, f)
    }
}

/// Extension trait for futures 0.1 [`Future`](futures::future::Future)
pub trait Future01CompatExt: Future01 {
    /// Converts a futures 0.1
    /// [`Future<Item = T, Error = E>`](futures::future::Future)
    /// into a futures 0.3
    /// [`Future<Output = Result<T, E>>`](futures_core::future::Future).
    fn compat(self) -> Compat01As03<Self>
    where
        Self: Sized,
    {
        Compat01As03::new(self)
    }
}
impl<Fut: Future01> Future01CompatExt for Fut {}

/// Extension trait for futures 0.1 [`Stream`](futures::stream::Stream)
pub trait Stream01CompatExt: Stream01 {
    /// Converts a futures 0.1
    /// [`Stream<Item = T, Error = E>`](futures::stream::Stream)
    /// into a futures 0.3
    /// [`Stream<Item = Result<T, E>>`](futures_core::stream::Stream).
    fn compat(self) -> Compat01As03<Self>
    where
        Self: Sized,
    {
        Compat01As03::new(self)
    }
}
impl<St: Stream01> Stream01CompatExt for St {}

/// Extension trait for futures 0.1 [`Sink`](futures::sink::Sink)
pub trait Sink01CompatExt: Sink01 {
    /// Converts a futures 0.1
    /// [`Sink<SinkItem = T, SinkError = E>`](futures::sink::Sink)
    /// into a futures 0.3
    /// [`Sink<SinkItem = T, SinkError = E>`](futures_sink::sink::Sink).
    fn sink_compat(self) -> Compat01As03Sink<Self, Self::SinkItem>
    where
        Self: Sized,
    {
        Compat01As03Sink::new(self)
    }
}
impl<Si: Sink01> Sink01CompatExt for Si {}

fn poll_01_to_03<T, E>(x: Result<Async01<T>, E>) -> task03::Poll<Result<T, E>> {
    match x {
        Ok(Async01::Ready(t)) => task03::Poll::Ready(Ok(t)),
        Ok(Async01::NotReady) => task03::Poll::Pending,
        Err(e) => task03::Poll::Ready(Err(e)),
    }
}

impl<Fut: Future01> Future03 for Compat01As03<Fut> {
    type Output = Result<Fut::Item, Fut::Error>;

    fn poll(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Self::Output> {
        poll_01_to_03(self.in_notify(waker, Future01::poll))
    }
}

impl<St: Stream01> Stream03 for Compat01As03<St> {
    type Item = Result<St::Item, St::Error>;

    fn poll_next(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Option<Self::Item>> {
        match self.in_notify(waker, Stream01::poll) {
            Ok(Async01::Ready(Some(t))) => task03::Poll::Ready(Some(Ok(t))),
            Ok(Async01::Ready(None)) => task03::Poll::Ready(None),
            Ok(Async01::NotReady) => task03::Poll::Pending,
            Err(e) => task03::Poll::Ready(Some(Err(e))),
        }
    }
}

/// Converts a futures 0.1 Sink object to a futures 0.3-compatible version
#[derive(Debug)]
#[must_use = "sinks do nothing unless polled"]
pub struct Compat01As03Sink<S, SinkItem> {
    pub(crate) inner: Spawn01<S>,
    pub(crate) buffer: Option<SinkItem>,
    pub(crate) close_started: bool,
}

impl<S, SinkItem> Unpin for Compat01As03Sink<S, SinkItem> {}

impl<S, SinkItem> Compat01As03Sink<S, SinkItem> {
    /// Wraps a futures 0.1 Sink object in a futures 0.3-compatible wrapper.
    pub fn new(inner: S) -> Compat01As03Sink<S, SinkItem> {
        Compat01As03Sink {
            inner: spawn01(inner),
            buffer: None,
            close_started: false
        }
    }

    fn in_notify<R>(
        &mut self,
        waker: &Waker,
        f: impl FnOnce(&mut S) -> R,
    ) -> R {
        let notify = &WakerToHandle(waker);
        self.inner.poll_fn_notify(notify, 0, f)
    }
}

impl<S, SinkItem> Stream03 for Compat01As03Sink<S, SinkItem>
where
    S: Stream01,
{
    type Item = Result<S::Item, S::Error>;

    fn poll_next(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Option<Self::Item>> {
        match self.in_notify(waker, |f| f.poll()) {
            Ok(Async01::Ready(Some(t))) => task03::Poll::Ready(Some(Ok(t))),
            Ok(Async01::Ready(None)) => task03::Poll::Ready(None),
            Ok(Async01::NotReady) => task03::Poll::Pending,
            Err(e) => task03::Poll::Ready(Some(Err(e))),
        }
    }
}

impl<S, SinkItem> Sink03 for Compat01As03Sink<S, SinkItem>
where
    S: Sink01<SinkItem = SinkItem>,
{
    type SinkItem = SinkItem;
    type SinkError = S::SinkError;

    fn start_send(
        mut self: Pin<&mut Self>,
        item: Self::SinkItem,
    ) -> Result<(), Self::SinkError> {
        debug_assert!(self.buffer.is_none());
        self.buffer = Some(item);
        Ok(())
    }

    fn poll_ready(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Result<(), Self::SinkError>> {
        match self.buffer.take() {
            Some(item) => match self.in_notify(waker, |f| f.start_send(item)) {
                Ok(AsyncSink01::Ready) => task03::Poll::Ready(Ok(())),
                Ok(AsyncSink01::NotReady(i)) => {
                    self.buffer = Some(i);
                    task03::Poll::Pending
                }
                Err(e) => task03::Poll::Ready(Err(e)),
            },
            None => task03::Poll::Ready(Ok(())),
        }
    }

    fn poll_flush(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Result<(), Self::SinkError>> {
        let item = self.buffer.take();
        match self.in_notify(waker, |f| match item {
            Some(i) => match f.start_send(i) {
                Ok(AsyncSink01::Ready) => f.poll_complete().map(|i| (i, None)),
                Ok(AsyncSink01::NotReady(t)) => {
                    Ok((Async01::NotReady, Some(t)))
                }
                Err(e) => Err(e),
            },
            None => f.poll_complete().map(|i| (i, None)),
        }) {
            Ok((Async01::Ready(_), _)) => task03::Poll::Ready(Ok(())),
            Ok((Async01::NotReady, item)) => {
                self.buffer = item;
                task03::Poll::Pending
            }
            Err(e) => task03::Poll::Ready(Err(e)),
        }
    }

    fn poll_close(
        mut self: Pin<&mut Self>,
        waker: &Waker,
    ) -> task03::Poll<Result<(), Self::SinkError>> {
        let item = self.buffer.take();
        let close_started = self.close_started;

        let result = self.in_notify(waker, |f| {
            if !close_started {
                if let Some(item) = item {
                    if let AsyncSink01::NotReady(item) = f.start_send(item)? {
                        return Ok((Async01::NotReady, Some(item), false));
                    }
                }

                if let Async01::NotReady = f.poll_complete()? {
                    return Ok((Async01::NotReady, None, false));
                }
            }

            Ok((<S as Sink01>::close(f)?, None, true))
        });

        match result {
            Ok((Async01::Ready(_), _, _)) => task03::Poll::Ready(Ok(())),
            Ok((Async01::NotReady, item, close_started)) => {
                self.buffer = item;
                self.close_started = close_started;
                task03::Poll::Pending
            }
            Err(e) => task03::Poll::Ready(Err(e)),
        }
    }
}

struct NotifyWaker(task03::Waker);

#[derive(Clone)]
struct WakerToHandle<'a>(&'a task03::Waker);

impl<'a> From<WakerToHandle<'a>> for NotifyHandle01 {
    fn from(handle: WakerToHandle<'a>) -> NotifyHandle01 {
        let ptr = Box::new(NotifyWaker(handle.0.clone()));

        unsafe { NotifyHandle01::new(Box::into_raw(ptr)) }
    }
}

impl Notify01 for NotifyWaker {
    fn notify(&self, _: usize) {
        self.0.wake();
    }
}

unsafe impl UnsafeNotify01 for NotifyWaker {
    unsafe fn clone_raw(&self) -> NotifyHandle01 {
        WakerToHandle(&self.0).into()
    }

    unsafe fn drop_raw(&self) {
        let ptr: *const dyn UnsafeNotify01 = self;
        drop(Box::from_raw(ptr as *mut dyn UnsafeNotify01));
    }
}

#[cfg(feature = "io-compat")]
mod io {
    use super::*;
    use futures_io::{
        AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03, Initializer,
    };
    use std::io::Error;
    use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01};

    impl<R: AsyncRead01> AsyncRead03 for Compat01As03<R> {
        unsafe fn initializer(&self) -> Initializer {
            // check if `prepare_uninitialized_buffer` needs zeroing
            if self.inner.get_ref().prepare_uninitialized_buffer(&mut [1]) {
                Initializer::zeroing()
            } else {
                Initializer::nop()
            }
        }

        fn poll_read(&mut self, waker: &task03::Waker, buf: &mut [u8])
            -> task03::Poll<Result<usize, Error>>
        {
            poll_01_to_03(self.in_notify(waker, |x| x.poll_read(buf)))
        }
    }

    impl<W: AsyncWrite01> AsyncWrite03 for Compat01As03<W> {
        fn poll_write(&mut self, waker: &task03::Waker, buf: &[u8])
            -> task03::Poll<Result<usize, Error>>
        {
            poll_01_to_03(self.in_notify(waker, |x| x.poll_write(buf)))
        }

        fn poll_flush(&mut self, waker: &task03::Waker)
            -> task03::Poll<Result<(), Error>>
        {
            poll_01_to_03(self.in_notify(waker, AsyncWrite01::poll_flush))
        }

        fn poll_close(&mut self, waker: &task03::Waker)
            -> task03::Poll<Result<(), Error>>
        {
            poll_01_to_03(self.in_notify(waker, AsyncWrite01::shutdown))
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;

use clap::{Arg, App, AppSettings};
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::fs::File;

fn main() {
    let matches = App::new("updatefw_rs")
        .version("1.0")
        .author("guiglin & nicolattuso")
        .about("implementation of cat in Rust!")
        .setting(AppSettings::TrailingVarArg)
        .arg(Arg::with_name("number")
             .short("n")
             .long("number")
             .help("number all output lines"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .required(true))
        .get_matches();
    let files = matches.values_of("files").unwrap();
    let file_list: Vec<&str> = files.collect();
    println!("{}", file_list.join(" "));

    let f = File::open(file_list[0]);
    let f = BufReader::new(f);

    for line in f.lines() {
        println!("{}", line.unwrap);
    }
}
<commit_msg>remove clap because it's too heavy and fix compilation<commit_after>use std::error::Error;
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::fs::File;
use std::env;

fn main() {

    let tab: Vec<_> = env::args().collect();

    println!("{:?}", &tab[1..]);
    if tab.len() > 1 {
        println!("arg tab[1] = {}", tab[1]);
    }

    assert_ne!(tab.len(), 1);
    let path;
    path = &tab[1];

    let f = File::open(&path).unwrap();
    let f = BufReader::new(f);

    for line in f.lines() {
        println!("{}", line.unwrap());
    }
}
<|endoftext|>


<commit_before><commit_msg>Expand deprecation note for capnp_rpc::Server.<commit_after><|endoftext|>


<commit_before>extern crate curl;

#[cfg(feature = "pi")]
extern crate wiringpi;

use std::path::Path;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::io::stdout;
use std::{thread, time};
use std::str;

use curl::easy::Easy;

static CONFIG_FILE_NAME: &'static str = "doorstate.config";

struct API {
    url: String,
    rate_ms: i64,
    pre_shared_key: String
}

struct GPIO {
    pin: i8
}

fn config() -> (API, GPIO)
{
    let path = Path::new(CONFIG_FILE_NAME);
    let path_display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!(
            "Couldn't open {}: {}",
            path_display,
            why.description()),
        Ok(file) => file,
    };

    let mut config = String::new();

    match file.read_to_string(&mut config) {
        Err(why) => panic!(
            "Couldn't read {}: {}",
            path_display,
            why.description()),
        //Ok(_) => print!("{} contains:\n{}", path_display, config),
        Ok(_) => {},
    };

    let mut api = API {
        url: String::new(),
        pre_shared_key: String::new(),
        rate_ms: -1
    };

    let mut gpio = GPIO {
        pin: -1
    };

    for line in config.lines() {
        // Ignore comments (lines starting with '#')
        if !line.trim().starts_with("#") {
            //println!("{}", line);
            let tokens: Vec<&str> = line.splitn(2, "=").collect();

            let key = tokens[0].trim();
            let value = tokens[1].trim();

            match key {
                "api.url" => api.url = value.to_string(),
                "api.rate-ms" => api.rate_ms = value.parse::<i64>().unwrap(),
                "api.pre-shared-key" => api.pre_shared_key = value.to_string(),
                "gpio.pin" => gpio.pin = value.parse::<i8>().unwrap(),
                _ => {},
            }
        }
    }

    (api, gpio)
}

#[cfg(feature = "pi")]
fn read_doorstate() {
}

fn send_doorstate(url: String, data: String) {
    let mut easy = Easy::new();
    let mut dst = Vec::new();

    easy.url(&url).unwrap();

    // This scope is required to end the borrow of dst
    {
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            dst.extend_from_slice(data);
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }

    let mut clone = &dst.clone();
    let challenge = str::from_utf8(&clone).unwrap();

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

#[cfg(feature = "pi")]
fn setup_gpio(pin: i8) -> WiringPi {
    let pi = wiringpi::setup();
    let pin = pi.input_pin(pin);

    pi
}

#[allow(unused_variables)]
fn setup_gpio(pin: i8) {
}

fn main() {
    let (api, gpio) = config();
    let duration;

    let pi = setup_gpio(gpio.pin);

    if api.rate_ms > -1 {
        duration = time::Duration::from_millis(api.rate_ms as u64);
    } else {
        duration = time::Duration::from_millis(0);
    }

    send_doorstate(api.url, "".to_string());

    /*
    loop {
        println!("Test");

        if pi != () {
            println!("pi is not equal to unit type");
        }

        if duration > time::Duration::from_millis(0) {
            thread::sleep(duration);
        }
    }
    */
}
<commit_msg>Implemet sending of status including digest auth<commit_after>extern crate curl;
extern crate crypto_hash;

#[cfg(feature = "pi")]
extern crate wiringpi;

use std::path::Path;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::{thread, time};
use std::str;

use curl::easy::Easy;

use crypto_hash::{Algorithm, hex_digest};

static CONFIG_FILE_NAME: &'static str = "doorstate.config";

struct API {
    url: String,
    rate_ms: i64,
    pre_shared_key: String
}

struct GPIO {
    pin: i8
}

fn config() -> (API, GPIO)
{
    let path = Path::new(CONFIG_FILE_NAME);
    let path_display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!(
            "Couldn't open {}: {}",
            path_display,
            why.description()),
        Ok(file) => file,
    };

    let mut config = String::new();

    match file.read_to_string(&mut config) {
        Err(why) => panic!(
            "Couldn't read {}: {}",
            path_display,
            why.description()),
        //Ok(_) => print!("{} contains:\n{}", path_display, config),
        Ok(_) => {},
    };

    let mut api = API {
        url: String::new(),
        pre_shared_key: String::new(),
        rate_ms: -1
    };

    let mut gpio = GPIO {
        pin: -1
    };

    for line in config.lines() {
        // Ignore comments (lines starting with '#')
        if !line.trim().starts_with("#") {
            //println!("{}", line);
            let tokens: Vec<&str> = line.splitn(2, "=").collect();

            let key = tokens[0].trim();
            let value = tokens[1].trim();

            match key {
                "api.url" => api.url = value.to_string(),
                "api.rate-ms" => api.rate_ms = value.parse::<i64>().unwrap(),
                "api.pre-shared-key" => api.pre_shared_key = value.to_string(),
                "gpio.pin" => gpio.pin = value.parse::<i8>().unwrap(),
                _ => {},
            }
        }
    }

    (api, gpio)
}

#[cfg(feature = "pi")]
fn read_doorstate() {
}

fn send_doorstate(baseurl: String, pre_shared_key: String, status: String) {
    let mut easy = Easy::new();
    let mut dst = Vec::new();

    easy.url(&baseurl).unwrap();

    // This scope is required to end the borrow of dst
    {
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            dst.extend_from_slice(data);
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }

    let challenge = str::from_utf8(&dst).unwrap();
    let mut response = dst.to_vec();

    response.extend_from_slice(pre_shared_key.as_bytes());

    let response_hashed = hex_digest(Algorithm::SHA256, response);
    let url: String = baseurl + "?" +
        "challenge=" + challenge + "&" +
        "response=" + &response_hashed + "&" +
        "status=" + &status;

    println!("{}", url);

    easy.url(&url).unwrap();

    let transfer = easy.transfer();

    transfer.perform().unwrap();
}

#[cfg(feature = "pi")]
fn setup_gpio(pin: i8) -> WiringPi {
    let pi = wiringpi::setup();
    let pin = pi.input_pin(pin);

    pi
}

#[allow(unused_variables)]
fn setup_gpio(pin: i8) {
}

fn main() {
    let (api, gpio) = config();
    let duration;

    let pi = setup_gpio(gpio.pin);

    if api.rate_ms > -1 {
        duration = time::Duration::from_millis(api.rate_ms as u64);
    } else {
        duration = time::Duration::from_millis(0);
    }

    send_doorstate(api.url, api.pre_shared_key, "offen".to_string());

    /*
    loop {
        println!("Test");

        if pi != () {
            println!("pi is not equal to unit type");
        }

        if duration > time::Duration::from_millis(0) {
            thread::sleep(duration);
        }
    }
    */
}
<|endoftext|>


<commit_before>use {time, node};
use hash::SubotaiHash;
use std::collections::HashMap;
use std::sync::RwLock;
use std::cmp;
use std::mem;

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum StorageEntry {
   Value(SubotaiHash),
   Blob(Vec<u8>),
}

type KeyGroup = Vec<(time::Tm, StorageEntry)>; // expiration/entry pair

pub struct Storage {
   key_groups    : RwLock<HashMap<SubotaiHash, KeyGroup> >,
   parent_id     : SubotaiHash,
   configuration : node::Configuration,
}

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum StoreResult {
   Success,
   StorageFull,
   BlobTooBig,
}

impl Storage {
   pub fn new(parent_id: SubotaiHash, configuration: node::Configuration) -> Storage {
      Storage {
         key_groups    : RwLock::new(HashMap::with_capacity(configuration.max_storage)),
         parent_id     : parent_id,
         configuration : configuration,
      }
   }

   /// Returns number of entries.
   pub fn len(&self) -> usize {
      self.key_groups.read().unwrap().values().flat_map(|group| group.iter()).count()
   }

   pub fn is_empty(&self) -> bool {
      self.len() == 0
   }

   /// Retrieves all entries in a key_group.
   pub fn retrieve(&self, key: &SubotaiHash) -> Option<Vec<StorageEntry>> {
      if let Some(key_group) = self.key_groups.read().unwrap().get(key) {
         Some(key_group.iter().cloned().map(|pair| pair.1).collect())
      } else {
         None
      }
   }

   /// Stores an entry in a key_group, with an expiration date, if it wasn't present already.
   /// If it was present, it keeps the latest expiration time.
   pub fn store(&self, key: &SubotaiHash, entry: &StorageEntry, expiration: &time::Tm) -> StoreResult {
      if self.is_big_blob(entry) {
         return StoreResult::BlobTooBig;
      }

      // Expiration time is clamped to a reasonable value.
      let expiration = cmp::min(*expiration, time::now() + time::Duration::hours(self.configuration.base_expiration_time_hrs));

      let mut key_groups = self.key_groups.write().unwrap();
      if key_groups.contains_key(key) {
         let key_group = key_groups.get_mut(key).unwrap();
         let already_existed = if let Some(preexisting_pair) = key_group.iter_mut().find(|stored_pair| stored_pair.1 == *entry) {
            preexisting_pair.0 = cmp::max(preexisting_pair.0, expiration); // Take the latest expiration time.
            true
         } else {
            false
         };
         if !already_existed {
            if self.len() > self.configuration.max_storage {
               return StoreResult::StorageFull;
            }
            key_group.push((expiration.clone(), entry.clone()));
         }
      } else {
         if self.len() > self.configuration.max_storage {
            return StoreResult::StorageFull;
         }
         let mut key_group = KeyGroup::new();
         key_group.push((expiration.clone(), entry.clone()));
         key_groups.insert(key.clone(), key_group);
      }
      StoreResult::Success
   }

   fn is_big_blob(&self, entry: &StorageEntry) -> bool {
      match entry {
         &StorageEntry::Blob(ref vec) => vec.len() > self.configuration.max_storage_blob_size,
         _ => false,
      }
   }

   pub fn clear_expired_entries(&self) {
      let now = time::now();
      let mut key_groups = self.key_groups.write().unwrap();
      for mut key_group in key_groups.values_mut() {
         key_group.retain(|&(time, _)| now < time);
      }

      // We clear the keygroups that have run out of entries.
      let empty_keys: Vec<_> = key_groups
         .iter()
         .filter_map(|(key, group)| if group.is_empty() { Some(key) } else { None })
         .cloned()
         .collect();

      for key in empty_keys {
         key_groups.remove(&key);
      }
   }

   ///// Marks all key-entry pairs as ready for republishing.
   //pub fn mark_all_as_ready(&self) {
   //   for (_, &mut ExtendedEntry {ref mut republish_ready, ..})  in self.extended_entries.write().unwrap().iter_mut() {
   //      *republish_ready = true;
   //   }
   //}

   ///// Marks a particular key-entry pair as not ready for republishing.
   //pub fn mark_as_not_ready(&self, key: &SubotaiHash) {
   //   if let Some( &mut ExtendedEntry {ref mut republish_ready, ..}) = self.extended_entries.write().unwrap().get_mut(key) {
   //      *republish_ready = false;
   //   }
   //}

   ///// Retrieves all key-entry pairs ready for republishing, together with their current expiration date
   //pub fn get_all_ready_entries(&self) -> Vec<(SubotaiHash, StorageEntry, time::Tm)>  {
   //   self.extended_entries.read().unwrap().iter()
   //      .filter(|&(_, &ExtendedEntry{ republish_ready, ..})| republish_ready)
   //      .map(|(key, &ExtendedEntry{ ref entry, ref expiration, ..})| (key.clone(), entry.clone(), expiration.clone()))
   //      .collect()
   //}
}

#[cfg(test)]
mod tests {
   use super::*;
   use {hash, time, node};
}
<commit_msg>More expressive extended storage type<commit_after>use {time, node};
use hash::SubotaiHash;
use std::collections::HashMap;
use std::sync::RwLock;
use std::cmp;
use std::mem;

/// User facing storage entry. This is the data type that can be stored and retrieved
/// in the Subotai network, consisting of either another hash (Value) or a binary blob.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum StorageEntry {
   Value(SubotaiHash),
   Blob(Vec<u8>),
}

/// Storage entry wrapper that includes management information.
#[derive(Debug, Clone)]
struct ExtendedEntry {
   entry           : StorageEntry,
   expiration      : time::Tm,
   republish_ready : bool,
}

/// Groups of extended entries classified by key.
type KeyGroup = Vec<ExtendedEntry>;

pub struct Storage {
   key_groups    : RwLock<HashMap<SubotaiHash, KeyGroup> >,
   parent_id     : SubotaiHash,
   configuration : node::Configuration,
}

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum StoreResult {
   Success,
   StorageFull,
   BlobTooBig,
}

impl Storage {
   pub fn new(parent_id: SubotaiHash, configuration: node::Configuration) -> Storage {
      Storage {
         key_groups    : RwLock::new(HashMap::with_capacity(configuration.max_storage)),
         parent_id     : parent_id,
         configuration : configuration,
      }
   }

   /// Returns number of entries.
   pub fn len(&self) -> usize {
      self.key_groups.read().unwrap().values().flat_map(|group| group.iter()).count()
   }

   pub fn is_empty(&self) -> bool {
      self.len() == 0
   }

   /// Retrieves all entries in a key_group.
   pub fn retrieve(&self, key: &SubotaiHash) -> Option<Vec<StorageEntry>> {
      if let Some(key_group) = self.key_groups.read().unwrap().get(key) {
         Some(key_group.iter().cloned().map(|extended| extended.entry).collect())
      } else {
         None
      }
   }

   /// Stores an entry in a key_group, with an expiration date, if it wasn't present already.
   /// If it was present, it keeps the latest expiration time.
   pub fn store(&self, key: &SubotaiHash, entry: &StorageEntry, expiration: &time::Tm) -> StoreResult {
      if self.is_big_blob(entry) {
         return StoreResult::BlobTooBig;
      }

      // Expiration time is clamped to a reasonable value.
      let expiration = cmp::min(*expiration, time::now() + time::Duration::hours(self.configuration.base_expiration_time_hrs));

      let mut key_groups = self.key_groups.write().unwrap();
      if key_groups.contains_key(key) {
         let key_group = key_groups.get_mut(key).unwrap();
         let already_existed = if let Some(preexisting_pair) = key_group.iter_mut().find(|stored_pair| stored_pair.entry == *entry) {
            preexisting_pair.expiration = cmp::max(preexisting_pair.expiration, expiration); // Take the latest expiration time.
            preexisting_pair.republish_ready = false;
            true
         } else {
            false
         };
         if !already_existed {
            if self.len() > self.configuration.max_storage {
               return StoreResult::StorageFull;
            }
            let new_entry = ExtendedEntry {
               entry           : entry.clone(),
               expiration      : expiration.clone(),
               republish_ready : false,
            };
            key_group.push(new_entry);
         }
      } else {
         if self.len() > self.configuration.max_storage {
            return StoreResult::StorageFull;
         }
         let mut key_group = KeyGroup::new();
         let new_entry = ExtendedEntry {
               entry           : entry.clone(),
               expiration      : expiration.clone(),
               republish_ready : false,
         };
         key_group.push(new_entry);
         key_groups.insert(key.clone(), key_group);
      }
      StoreResult::Success
   }

   fn is_big_blob(&self, entry: &StorageEntry) -> bool {
      match entry {
         &StorageEntry::Blob(ref vec) => vec.len() > self.configuration.max_storage_blob_size,
         _ => false,
      }
   }

   pub fn clear_expired_entries(&self) {
      let now = time::now();
      let mut key_groups = self.key_groups.write().unwrap();
      for mut key_group in key_groups.values_mut() {
         key_group.retain(|&ExtendedEntry{ expiration, .. }| now < expiration);
      }

      // We clear the keygroups that have run out of entries.
      let empty_keys: Vec<_> = key_groups
         .iter()
         .filter_map(|(key, group)| if group.is_empty() { Some(key) } else { None })
         .cloned()
         .collect();

      for key in empty_keys {
         key_groups.remove(&key);
      }
   }

   // Marks all key-entry pairs as ready for republishing.
   //pub fn mark_all_as_ready(&self) {
   //   for (_, &mut ExtendedEntry {ref mut republish_ready, ..})  in self.extended_entries.write().unwrap().iter_mut() {
   //      *republish_ready = true;
   //   }
   //}

   ///// Marks a particular key-entry pair as not ready for republishing.
   //pub fn mark_as_not_ready(&self, key: &SubotaiHash) {
   //   if let Some( &mut ExtendedEntry {ref mut republish_ready, ..}) = self.extended_entries.write().unwrap().get_mut(key) {
   //      *republish_ready = false;
   //   }
   //}

   ///// Retrieves all key-entry pairs ready for republishing, together with their current expiration date
   //pub fn get_all_ready_entries(&self) -> Vec<(SubotaiHash, StorageEntry, time::Tm)>  {
   //   self.extended_entries.read().unwrap().iter()
   //      .filter(|&(_, &ExtendedEntry{ republish_ready, ..})| republish_ready)
   //      .map(|(key, &ExtendedEntry{ ref entry, ref expiration, ..})| (key.clone(), entry.clone(), expiration.clone()))
   //      .collect()
   //}
}

#[cfg(test)]
mod tests {
   use super::*;
   use {hash, time, node};
}
<|endoftext|>


<commit_before>use cocoa;

export QuartzNativeFont, with_test_native_font, create;

import libc::size_t;
import ptr::null;
import unsafe::reinterpret_cast;
import result::{Result, Ok};
import glyph::GlyphIndex;
import cocoa::cg::{
    CGDataProviderRef,
    CGFontRef
};
import cocoa::cg::cg::{
    CGDataProviderCreateWithData,
    CGDataProviderRelease,
    CGFontCreateWithDataProvider,
    CGFontRelease
};

struct QuartzNativeFont/& {
    let fontprov: CGDataProviderRef;
    let cgfont: CGFontRef;

    new (fontprov: CGDataProviderRef, cgfont: CGFontRef) {
        assert fontprov.is_not_null();
        assert cgfont.is_not_null();

        self.fontprov = fontprov;
        self.cgfont = cgfont;
    }

    drop {
        assert self.cgfont.is_not_null();
        assert self.fontprov.is_not_null();

        CGFontRelease(self.cgfont);
        CGDataProviderRelease(self.fontprov);
    }

    fn glyph_index(_codepoint: char) -> Option<GlyphIndex> {
        // FIXME
        Some(40u)
    }

    // FIXME: What unit is this returning? Let's have a custom type
    fn glyph_h_advance(_glyph: GlyphIndex) -> Option<int> {
        // FIXME
        Some(15)
    }
}

fn create(buf: &~[u8]) -> Result<QuartzNativeFont, ()> {
    let fontprov = vec::as_buf(*buf, |cbuf, len| {
        CGDataProviderCreateWithData(
            null(),
            unsafe { reinterpret_cast(&cbuf) },
            len as size_t,
            null())
    });
    // FIXME: Error handling
    assert fontprov.is_not_null();
    let cgfont = CGFontCreateWithDataProvider(fontprov);
    // FIXME: Error handling
    assert cgfont.is_not_null();

    return Ok(QuartzNativeFont(fontprov, cgfont));
}

fn with_test_native_font(f: fn@(nf: &NativeFont)) {
    import font::test_font_bin;
    import unwrap_result = result::unwrap;

    let buf = test_font_bin();
    let res = create(&buf);
    let font = unwrap_result(res);
    f(&font);
}
<commit_msg>Get the correct glyph index/advance on mac<commit_after>use cocoa;

export QuartzNativeFont, with_test_native_font, create;

import libc::size_t;
import ptr::null;
import unsafe::reinterpret_cast;
import glyph::GlyphIndex;
import cocoa::cg::{
    CGDataProviderRef,
    CGFontRef
};
import cocoa::cg::cg::{
    CGDataProviderCreateWithData,
    CGDataProviderRelease,
    CGFontCreateWithDataProvider,
    CGFontRelease
};

mod coretext {

    type CTFontRef = *u8;
    type UniChar = libc::c_ushort;
    type CGGlyph = libc::c_ushort;
    type CFIndex = libc::c_long;

    type CTFontOrientation = u32;
    const kCTFontDefaultOrientation: CTFontOrientation = 0;
    const kCTFontHorizontalOrientation: CTFontOrientation = 1;
    const kCTFontVerticalOrientation: CTFontOrientation = 2;

    type CGFloat = libc::c_double;

    struct CGSize {
        width: CGFloat;
        height: CGFloat;
    }

    type CGAffineTransform = ();
    type CTFontDescriptorRef = *u8;

    #[nolink]
    #[link_args = "-framework ApplicationServices"]
    extern mod coretext {
        fn CTFontCreateWithGraphicsFont(graphicsFont: CGFontRef, size: CGFloat, matrix: *CGAffineTransform, attributes: CTFontDescriptorRef) -> CTFontRef;
        fn CTFontGetGlyphsForCharacters(font: CTFontRef, characters: *UniChar, glyphs: *CGGlyph, count: CFIndex) -> bool;
        fn CTFontGetAdvancesForGlyphs(font: CTFontRef, orientation: CTFontOrientation, glyphs: *CGGlyph, advances: *CGSize, count: CFIndex) -> libc::c_double;
        fn CFRelease(font: CTFontRef);
    }
}

struct QuartzNativeFont/& {
    let fontprov: CGDataProviderRef;
    let cgfont: CGFontRef;

    new (fontprov: CGDataProviderRef, cgfont: CGFontRef) {
        assert fontprov.is_not_null();
        assert cgfont.is_not_null();

        self.fontprov = fontprov;
        self.cgfont = cgfont;
    }

    drop {
        assert self.cgfont.is_not_null();
        assert self.fontprov.is_not_null();

        CGFontRelease(self.cgfont);
        CGDataProviderRelease(self.fontprov);
    }

    fn glyph_index(codepoint: char) -> Option<GlyphIndex> {

        import coretext::{UniChar, CGGlyph, CFIndex};
        import coretext::coretext::{CFRelease, CTFontGetGlyphsForCharacters};

        let ctfont = ctfont_from_cgfont(self.cgfont);
        assert ctfont.is_not_null();
        let characters: ~[UniChar] = ~[codepoint as UniChar];
        let glyphs: ~[mut CGGlyph] = ~[mut 0 as CGGlyph];
        let count: CFIndex = 1;

        let result = do vec::as_buf(characters) |character_buf, _l| {
            do vec::as_buf(glyphs) |glyph_buf, _l| {
                CTFontGetGlyphsForCharacters(ctfont, character_buf, glyph_buf, count)
            }
        };

        assert result != false; // FIXME: error handling

        CFRelease(ctfont);

        assert glyphs[0] != 0; // FIXME: error handling
        return Some(glyphs[0] as GlyphIndex);
    }

    // FIXME: What unit is this returning? Let's have a custom type
    fn glyph_h_advance(glyph: GlyphIndex) -> Option<int> {
        import coretext::{CGGlyph, kCTFontDefaultOrientation};
        import coretext::coretext::{CFRelease, CTFontGetAdvancesForGlyphs};

        let ctfont = ctfont_from_cgfont(self.cgfont);
        assert ctfont.is_not_null();
        let glyphs = ~[glyph as CGGlyph];
        let advance = do vec::as_buf(glyphs) |glyph_buf, _l| {
            CTFontGetAdvancesForGlyphs(ctfont, kCTFontDefaultOrientation, glyph_buf, null(), 1)
        };

        CFRelease(ctfont);

        return Some(advance as int);
    }
}

fn ctfont_from_cgfont(+cgfont: CGFontRef) -> coretext::CTFontRef unsafe {
    import coretext::CGFloat;
    import coretext::coretext::CTFontCreateWithGraphicsFont;

    assert cgfont.is_not_null();
    CTFontCreateWithGraphicsFont(cgfont, 21f as CGFloat, null(), null())
}

fn create(buf: &~[u8]) -> Result<QuartzNativeFont, ()> {
    let fontprov = vec::as_buf(*buf, |cbuf, len| {
        CGDataProviderCreateWithData(
            null(),
            unsafe { reinterpret_cast(&cbuf) },
            len as size_t,
            null())
    });
    // FIXME: Error handling
    assert fontprov.is_not_null();
    let cgfont = CGFontCreateWithDataProvider(fontprov);
    // FIXME: Error handling
    assert cgfont.is_not_null();

    return Ok(QuartzNativeFont(fontprov, cgfont));
}

fn with_test_native_font(f: fn@(nf: &NativeFont)) {
    import font::test_font_bin;
    import unwrap_result = result::unwrap;

    let buf = test_font_bin();
    let res = create(&buf);
    let font = unwrap_result(res);
    f(&font);
}
<|endoftext|>


<commit_before><commit_msg>Review: Consistently format macro parameters.<commit_after><|endoftext|>