<commit_before>use rustc_errors::DiagnosticBuilder;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_infer::infer::region_constraints::Constraint;
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
use rustc_traits::type_op_prove_predicate_with_span;

use std::fmt;
use std::rc::Rc;

use crate::borrow_check::region_infer::values::RegionElement;
use crate::borrow_check::MirBorrowckCtxt;

#[derive(Clone)]
crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);

/// What operation a universe was created for.
#[derive(Clone)]
enum UniverseInfoInner<'tcx> {
    /// Relating two types which have binders.
    RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> },
    /// Created from performing a `TypeOp`.
    TypeOp(Rc<dyn TypeOpInfo<'tcx> + 'tcx>),
    /// Any other reason.
    Other,
}

impl UniverseInfo<'tcx> {
    crate fn other() -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::Other)
    }

    crate fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::RelateTys { expected, found })
    }

    crate fn report_error(
        &self,
        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
        placeholder: ty::PlaceholderRegion,
        error_element: RegionElement,
        span: Span,
    ) {
        match self.0 {
            UniverseInfoInner::RelateTys { expected, found } => {
                let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id());
                let err = mbcx.infcx.report_mismatched_types(
                    &ObligationCause::misc(span, body_id),
                    expected,
                    found,
                    TypeError::RegionsPlaceholderMismatch,
                );
                err.buffer(&mut mbcx.errors_buffer);
            }
            UniverseInfoInner::TypeOp(ref type_op_info) => {
                type_op_info.report_error(mbcx, placeholder, error_element, span);
            }
            UniverseInfoInner::Other => {
                // FIXME: This error message isn't great, but it doesn't show
                // up in the existing UI tests. Consider investigating this
                // some more.
                mbcx.infcx
                    .tcx
                    .sess
                    .struct_span_err(span, "higher-ranked subtype error")
                    .buffer(&mut mbcx.errors_buffer);
            }
        }
    }
}

crate trait ToUniverseInfo<'tcx> {
    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
}

impl<'tcx> ToUniverseInfo<'tcx>
    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
{
    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
            canonical_query: self,
            base_universe,
        })))
    }
}

impl<'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx> ToUniverseInfo<'tcx>
    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
{
    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
            canonical_query: self,
            base_universe,
        })))
    }
}

impl<'tcx> ToUniverseInfo<'tcx>
    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
{
    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        // Ascribe user type isn't usually called on types that have different
        // bound regions.
        UniverseInfo::other()
    }
}

impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        // We can't rerun custom type ops.
        UniverseInfo::other()
    }
}

#[allow(unused_lifetimes)]
trait TypeOpInfo<'tcx> {
    /// Returns an error to be reported if rerunning the type op fails to
    /// recover the error's cause.
    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;

    fn base_universe(&self) -> ty::UniverseIndex;

    fn nice_error(
        &self,
        tcx: TyCtxt<'tcx>,
        span: Span,
        placeholder_region: ty::Region<'tcx>,
        error_region: Option<ty::Region<'tcx>>,
    ) -> Option<DiagnosticBuilder<'tcx>>;

    fn report_error(
        &self,
        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
        placeholder: ty::PlaceholderRegion,
        error_element: RegionElement,
        span: Span,
    ) {
        let tcx = mbcx.infcx.tcx;
        let base_universe = self.base_universe();

        let adjusted_universe = if let Some(adjusted) =
            placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
        {
            adjusted
        } else {
            self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
            return;
        };

        let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
            name: placeholder.name,
            universe: adjusted_universe.into(),
        }));

        let error_region =
            if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
                let adjusted_universe =
                    error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
                adjusted_universe.map(|adjusted| {
                    tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
                        name: error_placeholder.name,
                        universe: adjusted.into(),
                    }))
                })
            } else {
                None
            };

        debug!(?placeholder_region);

        let nice_error = self.nice_error(tcx, span, placeholder_region, error_region);

        if let Some(nice_error) = nice_error {
            nice_error.buffer(&mut mbcx.errors_buffer);
        } else {
            self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
        }
    }
}

struct PredicateQuery<'tcx> {
    canonical_query:
        Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>,
    base_universe: ty::UniverseIndex,
}

impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
        let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
        err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
        err
    }

    fn base_universe(&self) -> ty::UniverseIndex {
        self.base_universe
    }

    fn nice_error(
        &self,
        tcx: TyCtxt<'tcx>,
        span: Span,
        placeholder_region: ty::Region<'tcx>,
        error_region: Option<ty::Region<'tcx>>,
    ) -> Option<DiagnosticBuilder<'tcx>> {
        tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
            let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
            type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span));
            try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
        })
    }
}

struct NormalizeQuery<'tcx, T> {
    canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>,
    base_universe: ty::UniverseIndex,
}

impl<T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
where
    T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
{
    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
        let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
        err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value));
        err
    }

    fn base_universe(&self) -> ty::UniverseIndex {
        self.base_universe
    }

    fn nice_error(
        &self,
        tcx: TyCtxt<'tcx>,
        span: Span,
        placeholder_region: ty::Region<'tcx>,
        error_region: Option<ty::Region<'tcx>>,
    ) -> Option<DiagnosticBuilder<'tcx>> {
        tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
            let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);

            let mut selcx = SelectionContext::new(infcx);
            let (param_env, value) = key.into_parts();

            let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
                &mut selcx,
                param_env,
                ObligationCause::dummy_with_span(span),
                value.value,
            );
            fulfill_cx.register_predicate_obligations(infcx, obligations);

            try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
        })
    }
}

fn try_extract_error_from_fulfill_cx<'tcx>(
    mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
    infcx: &InferCtxt<'_, 'tcx>,
    placeholder_region: ty::Region<'tcx>,
    error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
    let tcx = infcx.tcx;

    // We generally shouldn't have here because the query was
    // already run, but there's no point using `delay_span_bug`
    // when we're going to emit an error here anyway.
    let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);

    let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
        debug!(?region_constraints);
        region_constraints.constraints.iter().find_map(|(constraint, cause)| {
            match *constraint {
                Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
                    Some((sub, cause.clone()))
                }
                // FIXME: Should this check the universe of the var?
                Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
                    Some((tcx.mk_region(ty::ReVar(vid)), cause.clone()))
                }
                _ => None,
            }
        })
    })?;

    debug!(?sub_region, ?cause);
    let nice_error = match (error_region, sub_region) {
        (Some(error_region), &ty::ReVar(vid)) => NiceRegionError::new(
            infcx,
            RegionResolutionError::SubSupConflict(
                vid,
                infcx.region_var_origin(vid),
                cause.clone(),
                error_region,
                cause.clone(),
                placeholder_region,
            ),
        ),
        (Some(error_region), _) => NiceRegionError::new(
            infcx,
            RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region),
        ),
        // Note universe here is wrong...
        (None, &ty::ReVar(vid)) => NiceRegionError::new(
            infcx,
            RegionResolutionError::UpperBoundUniverseConflict(
                vid,
                infcx.region_var_origin(vid),
                infcx.universe_of_region(sub_region),
                cause.clone(),
                placeholder_region,
            ),
        ),
        (None, _) => NiceRegionError::new(
            infcx,
            RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region),
        ),
    };
    nice_error.try_report_from_nll().or_else(|| {
        if let SubregionOrigin::Subtype(trace) = cause {
            Some(
                infcx.report_and_explain_type_error(*trace, &TypeError::RegionsPlaceholderMismatch),
            )
        } else {
            None
        }
    })
}
<commit_msg>fix typo in bound_region_errors.rs<commit_after>use rustc_errors::DiagnosticBuilder;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_infer::infer::region_constraints::Constraint;
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
use rustc_traits::type_op_prove_predicate_with_span;

use std::fmt;
use std::rc::Rc;

use crate::borrow_check::region_infer::values::RegionElement;
use crate::borrow_check::MirBorrowckCtxt;

#[derive(Clone)]
crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);

/// What operation a universe was created for.
#[derive(Clone)]
enum UniverseInfoInner<'tcx> {
    /// Relating two types which have binders.
    RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> },
    /// Created from performing a `TypeOp`.
    TypeOp(Rc<dyn TypeOpInfo<'tcx> + 'tcx>),
    /// Any other reason.
    Other,
}

impl UniverseInfo<'tcx> {
    crate fn other() -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::Other)
    }

    crate fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::RelateTys { expected, found })
    }

    crate fn report_error(
        &self,
        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
        placeholder: ty::PlaceholderRegion,
        error_element: RegionElement,
        span: Span,
    ) {
        match self.0 {
            UniverseInfoInner::RelateTys { expected, found } => {
                let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id());
                let err = mbcx.infcx.report_mismatched_types(
                    &ObligationCause::misc(span, body_id),
                    expected,
                    found,
                    TypeError::RegionsPlaceholderMismatch,
                );
                err.buffer(&mut mbcx.errors_buffer);
            }
            UniverseInfoInner::TypeOp(ref type_op_info) => {
                type_op_info.report_error(mbcx, placeholder, error_element, span);
            }
            UniverseInfoInner::Other => {
                // FIXME: This error message isn't great, but it doesn't show
                // up in the existing UI tests. Consider investigating this
                // some more.
                mbcx.infcx
                    .tcx
                    .sess
                    .struct_span_err(span, "higher-ranked subtype error")
                    .buffer(&mut mbcx.errors_buffer);
            }
        }
    }
}

crate trait ToUniverseInfo<'tcx> {
    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
}

impl<'tcx> ToUniverseInfo<'tcx>
    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
{
    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
            canonical_query: self,
            base_universe,
        })))
    }
}

impl<'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx> ToUniverseInfo<'tcx>
    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
{
    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
            canonical_query: self,
            base_universe,
        })))
    }
}

impl<'tcx> ToUniverseInfo<'tcx>
    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
{
    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        // Ascribe user type isn't usually called on types that have different
        // bound regions.
        UniverseInfo::other()
    }
}

impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        // We can't rerun custom type ops.
        UniverseInfo::other()
    }
}

#[allow(unused_lifetimes)]
trait TypeOpInfo<'tcx> {
    /// Returns an error to be reported if rerunning the type op fails to
    /// recover the error's cause.
    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;

    fn base_universe(&self) -> ty::UniverseIndex;

    fn nice_error(
        &self,
        tcx: TyCtxt<'tcx>,
        span: Span,
        placeholder_region: ty::Region<'tcx>,
        error_region: Option<ty::Region<'tcx>>,
    ) -> Option<DiagnosticBuilder<'tcx>>;

    fn report_error(
        &self,
        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
        placeholder: ty::PlaceholderRegion,
        error_element: RegionElement,
        span: Span,
    ) {
        let tcx = mbcx.infcx.tcx;
        let base_universe = self.base_universe();

        let adjusted_universe = if let Some(adjusted) =
            placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
        {
            adjusted
        } else {
            self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
            return;
        };

        let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
            name: placeholder.name,
            universe: adjusted_universe.into(),
        }));

        let error_region =
            if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
                let adjusted_universe =
                    error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
                adjusted_universe.map(|adjusted| {
                    tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
                        name: error_placeholder.name,
                        universe: adjusted.into(),
                    }))
                })
            } else {
                None
            };

        debug!(?placeholder_region);

        let nice_error = self.nice_error(tcx, span, placeholder_region, error_region);

        if let Some(nice_error) = nice_error {
            nice_error.buffer(&mut mbcx.errors_buffer);
        } else {
            self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
        }
    }
}

struct PredicateQuery<'tcx> {
    canonical_query:
        Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>,
    base_universe: ty::UniverseIndex,
}

impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
        let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
        err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
        err
    }

    fn base_universe(&self) -> ty::UniverseIndex {
        self.base_universe
    }

    fn nice_error(
        &self,
        tcx: TyCtxt<'tcx>,
        span: Span,
        placeholder_region: ty::Region<'tcx>,
        error_region: Option<ty::Region<'tcx>>,
    ) -> Option<DiagnosticBuilder<'tcx>> {
        tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
            let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
            type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span));
            try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
        })
    }
}

struct NormalizeQuery<'tcx, T> {
    canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>,
    base_universe: ty::UniverseIndex,
}

impl<T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
where
    T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
{
    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
        let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
        err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value));
        err
    }

    fn base_universe(&self) -> ty::UniverseIndex {
        self.base_universe
    }

    fn nice_error(
        &self,
        tcx: TyCtxt<'tcx>,
        span: Span,
        placeholder_region: ty::Region<'tcx>,
        error_region: Option<ty::Region<'tcx>>,
    ) -> Option<DiagnosticBuilder<'tcx>> {
        tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
            let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);

            let mut selcx = SelectionContext::new(infcx);
            let (param_env, value) = key.into_parts();

            let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
                &mut selcx,
                param_env,
                ObligationCause::dummy_with_span(span),
                value.value,
            );
            fulfill_cx.register_predicate_obligations(infcx, obligations);

            try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
        })
    }
}

fn try_extract_error_from_fulfill_cx<'tcx>(
    mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
    infcx: &InferCtxt<'_, 'tcx>,
    placeholder_region: ty::Region<'tcx>,
    error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
    let tcx = infcx.tcx;

    // We generally shouldn't have errors here because the query was
    // already run, but there's no point using `delay_span_bug`
    // when we're going to emit an error here anyway.
    let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);

    let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
        debug!(?region_constraints);
        region_constraints.constraints.iter().find_map(|(constraint, cause)| {
            match *constraint {
                Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
                    Some((sub, cause.clone()))
                }
                // FIXME: Should this check the universe of the var?
                Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
                    Some((tcx.mk_region(ty::ReVar(vid)), cause.clone()))
                }
                _ => None,
            }
        })
    })?;

    debug!(?sub_region, ?cause);
    let nice_error = match (error_region, sub_region) {
        (Some(error_region), &ty::ReVar(vid)) => NiceRegionError::new(
            infcx,
            RegionResolutionError::SubSupConflict(
                vid,
                infcx.region_var_origin(vid),
                cause.clone(),
                error_region,
                cause.clone(),
                placeholder_region,
            ),
        ),
        (Some(error_region), _) => NiceRegionError::new(
            infcx,
            RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region),
        ),
        // Note universe here is wrong...
        (None, &ty::ReVar(vid)) => NiceRegionError::new(
            infcx,
            RegionResolutionError::UpperBoundUniverseConflict(
                vid,
                infcx.region_var_origin(vid),
                infcx.universe_of_region(sub_region),
                cause.clone(),
                placeholder_region,
            ),
        ),
        (None, _) => NiceRegionError::new(
            infcx,
            RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region),
        ),
    };
    nice_error.try_report_from_nll().or_else(|| {
        if let SubregionOrigin::Subtype(trace) = cause {
            Some(
                infcx.report_and_explain_type_error(*trace, &TypeError::RegionsPlaceholderMismatch),
            )
        } else {
            None
        }
    })
}
<|endoftext|>


<commit_before>extern crate sdl2;

use super::{FONT, Color};
use super::event::*;

/// A window
#[allow(dead_code)]
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// SDL2 Context
    ctx: sdl2::Sdl,
    /// Video Context
    video_ctx: sdl2::VideoSubsystem,
    /// Event Pump
    event_pump: sdl2::EventPump,
    /// The inner renderer
    inner: sdl2::render::Renderer<'static>,
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Box<Self>> {
        let ctx = sdl2::init().unwrap();
        let video_ctx = ctx.video().unwrap();
        let event_pump = ctx.event_pump().unwrap();

        let mut builder = video_ctx.window(title, w, h);

        if x >= 0 || y >= 0 {
            builder.position(x, y);
        }

        match builder.build() {
            Ok(window) => Some(Box::new(Window {
                x: x,
                y: y,
                w: w,
                h: h,
                t: title.to_string(),
                ctx: ctx,
                video_ctx: video_ctx,
                event_pump: event_pump,
                inner: window.renderer().build().unwrap(),
            })),
            Err(_) => None
        }
    }

    pub fn sync_path(&mut self) {
        if let Some(window) = self.inner.window() {
            self.x = window.position().0;
            self.x = window.position().1;
            self.w = window.size().0;
            self.h = window.size().1;
            self.t = window.title().to_string();
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get width
    pub fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    pub fn height(&self) -> u32 {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, _: &str) {
        // TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: i32, y: i32, color: Color) {
        self.inner.set_draw_color(sdl2::pixels::Color::RGBA((color.data >> 16) as u8, (color.data >> 8) as u8, color.data as u8, (color.data >> 24) as u8));
        self.inner.draw_point(sdl2::rect::Point::new(x, y));
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        self.inner.set_draw_color(sdl2::pixels::Color::RGBA((color.data >> 16) as u8, (color.data >> 8) as u8, color.data as u8, (color.data >> 24) as u8));

        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < FONT.len() {
                row_data = FONT[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.inner.draw_point(sdl2::rect::Point::new(x + col as i32, y + row as i32));
                }
            }
            offset += 1;
        }
    }

    // TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        let w = self.w;
        let h = self.h;
        self.rect(0, 0, w, h, color);
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, color: Color) {
        if let Some(rect) = sdl2::rect::Rect::new(start_x, start_y, w, h).unwrap_or(None) {
            self.inner.set_draw_color(sdl2::pixels::Color::RGBA((color.data >> 16) as u8, (color.data >> 8) as u8, color.data as u8, (color.data >> 24) as u8));
            self.inner.fill_rect(rect);
        }
    }

    /// Display an image
    // TODO: Improve speed
    pub fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    fn convert_keycode(&self, keycode_option: Option<sdl2::keyboard::Keycode>) -> Option<(char, u8)> {
        if let Some(keycode) = keycode_option {
            match keycode {
                sdl2::keyboard::Keycode::Return => Some(('\n', 0)),

                sdl2::keyboard::Keycode::Escape => Some(('\x1B', K_ESC)),
                sdl2::keyboard::Keycode::Backspace => Some(('\0', K_BKSP)),
                sdl2::keyboard::Keycode::Tab => Some(('\t', K_TAB)),
                sdl2::keyboard::Keycode::LCtrl => Some(('\0', K_CTRL)),
                sdl2::keyboard::Keycode::RCtrl => Some(('\0', K_CTRL)),
                sdl2::keyboard::Keycode::LAlt => Some(('\0', K_ALT)),
                sdl2::keyboard::Keycode::RAlt => Some(('\0', K_ALT)),
                sdl2::keyboard::Keycode::F1 => Some(('\0', K_F1)),
                sdl2::keyboard::Keycode::F2 => Some(('\0', K_F2)),
                sdl2::keyboard::Keycode::F3 => Some(('\0', K_F3)),
                sdl2::keyboard::Keycode::F4 => Some(('\0', K_F4)),
                sdl2::keyboard::Keycode::F5 => Some(('\0', K_F5)),
                sdl2::keyboard::Keycode::F6 => Some(('\0', K_F6)),
                sdl2::keyboard::Keycode::F7 => Some(('\0', K_F7)),
                sdl2::keyboard::Keycode::F8 => Some(('\0', K_F8)),
                sdl2::keyboard::Keycode::F9 => Some(('\0', K_F9)),
                sdl2::keyboard::Keycode::F10 => Some(('\0', K_F10)),
                sdl2::keyboard::Keycode::Home => Some(('\0', K_HOME)),
                sdl2::keyboard::Keycode::Up => Some(('\0', K_UP)),
                sdl2::keyboard::Keycode::PageUp => Some(('\0', K_PGUP)),
                sdl2::keyboard::Keycode::Left => Some(('\0', K_LEFT)),
                sdl2::keyboard::Keycode::Right => Some(('\0', K_RIGHT)),
                sdl2::keyboard::Keycode::End => Some(('\0', K_END)),
                sdl2::keyboard::Keycode::Down => Some(('\0', K_DOWN)),
                sdl2::keyboard::Keycode::PageDown => Some(('\0', K_PGDN)),
                sdl2::keyboard::Keycode::Delete => Some(('\0', K_DEL)),
                sdl2::keyboard::Keycode::F11 => Some(('\0', K_F11)),
                sdl2::keyboard::Keycode::F12 => Some(('\0', K_F12)),
                sdl2::keyboard::Keycode::LShift => Some(('\0', K_LEFT_SHIFT)),
                sdl2::keyboard::Keycode::RShift => Some(('\0', K_RIGHT_SHIFT)),
                _ => None
            }
        } else {
            None
        }
    }

    fn convert_event(&self, event: sdl2::event::Event) -> Vec<Event> {
        let mut events = Vec::new();

        let mouse_event = || -> Event {
            let mouse = self.ctx.mouse().mouse_state();
            MouseEvent {
                x: mouse.1,
                y: mouse.2,
                left_button: mouse.0.left(),
                middle_button: mouse.0.middle(),
                right_button: mouse.0.right()
            }.to_event()
        };

        match event {
            sdl2::event::Event::MouseMotion { .. } => events.push(mouse_event()),
            sdl2::event::Event::MouseButtonDown { .. } => events.push(mouse_event()),
            sdl2::event::Event::MouseButtonUp { .. } => events.push(mouse_event()),
            sdl2::event::Event::KeyDown { keycode, .. } => if let Some(code) = self.convert_keycode(keycode) {
                events.push(KeyEvent {
                    character: code.0,
                    scancode: code.1,
                    pressed: true
                }.to_event());
            },
            sdl2::event::Event::KeyUp { keycode, .. } => if let Some(code) = self.convert_keycode(keycode) {
                events.push(KeyEvent {
                    character: code.0,
                    scancode: code.1,
                    pressed: false
                }.to_event());
            },
            sdl2::event::Event::TextInput { text, .. } => for c in text.chars() {
                events.push(KeyEvent {
                    character: c,
                    scancode: 0,
                    pressed: true
                }.to_event());
                events.push(KeyEvent {
                    character: c,
                    scancode: 0,
                    pressed: false
                }.to_event());
            },
            sdl2::event::Event::Quit { .. } => events.push(QuitEvent.to_event()),
            _ => (),
        }

        events
    }

    /// Return a iterator over events
    fn events_inner(&mut self, wait: bool) -> EventIter {
        let mut iter = EventIter {
            events: [Event::new(); 128],
            i: 0,
            count: 0,
        };

        if wait {
            let event = self.event_pump.wait_event();
            for converted_event in self.convert_event(event) {
                if iter.count < iter.events.len() {
                    iter.events[iter.count] = converted_event;
                    iter.count += 1;
                } else {
                    break;
                }
            }
        }

        while let Some(event) = self.event_pump.poll_event() {
            for converted_event in self.convert_event(event) {
                if iter.count < iter.events.len() {
                    iter.events[iter.count] = converted_event;
                    iter.count += 1;
                } else {
                    break;
                }
            }
            if iter.count + 2 < iter.events.len() {
                break;
            }
        }

        iter
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        self.events_inner(true)
    }

    /// Nonblocking iterator over events
    pub fn events_no_wait(&mut self) -> EventIter {
        self.events_inner(false)
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.inner.present();
        true
    }
}

/// Event iterator
pub struct EventIter {
    events: [Event; 128],
    i: usize,
    count: usize,
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        if self.i < self.count {
            if let Some(event) = self.events.get(self.i) {
                self.i += 1;
                Some(*event)
            } else {
                None
            }
        } else {
            None
        }
    }
}
<commit_msg>Add functions to create left, right, top and bottom borders<commit_after>extern crate sdl2;

use super::{FONT, Color};
use super::event::*;

/// A window
#[allow(dead_code)]
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// SDL2 Context
    ctx: sdl2::Sdl,
    /// Video Context
    video_ctx: sdl2::VideoSubsystem,
    /// Event Pump
    event_pump: sdl2::EventPump,
    /// The inner renderer
    inner: sdl2::render::Renderer<'static>,
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Box<Self>> {
        let ctx = sdl2::init().unwrap();
        let video_ctx = ctx.video().unwrap();
        let event_pump = ctx.event_pump().unwrap();

        let mut builder = video_ctx.window(title, w, h);

        if x >= 0 || y >= 0 {
            builder.position(x, y);
        }

        match builder.build() {
            Ok(window) => Some(Box::new(Window {
                x: x,
                y: y,
                w: w,
                h: h,
                t: title.to_string(),
                ctx: ctx,
                video_ctx: video_ctx,
                event_pump: event_pump,
                inner: window.renderer().build().unwrap(),
            })),
            Err(_) => None
        }
    }

    pub fn sync_path(&mut self) {
        if let Some(window) = self.inner.window() {
            self.x = window.position().0;
            self.x = window.position().1;
            self.w = window.size().0;
            self.h = window.size().1;
            self.t = window.title().to_string();
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get width
    pub fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    pub fn height(&self) -> u32 {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, _: &str) {
        // TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: i32, y: i32, color: Color) {
        self.inner.set_draw_color(sdl2::pixels::Color::RGBA((color.data >> 16) as u8, (color.data >> 8) as u8, color.data as u8, (color.data >> 24) as u8));
        self.inner.draw_point(sdl2::rect::Point::new(x, y));
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        self.inner.set_draw_color(sdl2::pixels::Color::RGBA((color.data >> 16) as u8, (color.data >> 8) as u8, color.data as u8, (color.data >> 24) as u8));

        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < FONT.len() {
                row_data = FONT[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.inner.draw_point(sdl2::rect::Point::new(x + col as i32, y + row as i32));
                }
            }
            offset += 1;
        }
    }

    // TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        let w = self.w;
        let h = self.h;
        self.rect(0, 0, w, h, color);
    }

    // Allows to draw a left border in the window
    // x_limit is the left limit of the border!!!
    pub fn set_border_left(&mut self, x_limit: i32, color: Color, density: i32) {
        for y in 0..self.h {
            for x in x_limit..(x_limit + density) {
                self.pixel(x, y as i32, color);
            }
        }
    }

    // Allows to draw a right border in the window
    // x_limit is the left limit of the border!!!
    pub fn set_border_right(&mut self, x_limit: i32, color: Color, density: i32) {
        for y in 0..self.h {
            for x in x_limit..(x_limit + density) {
                let new_x : i32 = self.w as i32;
                self.pixel((new_x - x), y as i32, color);
            }
        }
    }

    // Allows to draw a top border in the window
    // x_limit is the top limit of the border!!!
    pub fn set_border_top(&mut self, y_limit: i32, color: Color, density: i32) {
        for x in 0..self.w {
            for y in y_limit..(y_limit + density) {
                self.pixel(x as i32, y, color);
            }
        }
    }

    // Allows to draw a bottom border in the window
    // x_limit is the top limit of the border!!!
    pub fn set_border_bottom(&mut self, y_limit: i32, color: Color, density: i32) {
        for x in 0..self.w {
            for y in y_limit..(y_limit + density) {
                let new_y : i32 = self.h as i32;
                self.pixel(x as i32, (new_y - y), color);
            }
        }
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, color: Color) {
        if let Some(rect) = sdl2::rect::Rect::new(start_x, start_y, w, h).unwrap_or(None) {
            self.inner.set_draw_color(sdl2::pixels::Color::RGBA((color.data >> 16) as u8, (color.data >> 8) as u8, color.data as u8, (color.data >> 24) as u8));
            self.inner.fill_rect(rect);
        }
    }

    /// Display an image
    // TODO: Improve speed
    pub fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    fn convert_keycode(&self, keycode_option: Option<sdl2::keyboard::Keycode>) -> Option<(char, u8)> {
        if let Some(keycode) = keycode_option {
            match keycode {
                sdl2::keyboard::Keycode::Return => Some(('\n', 0)),

                sdl2::keyboard::Keycode::Escape => Some(('\x1B', K_ESC)),
                sdl2::keyboard::Keycode::Backspace => Some(('\0', K_BKSP)),
                sdl2::keyboard::Keycode::Tab => Some(('\t', K_TAB)),
                sdl2::keyboard::Keycode::LCtrl => Some(('\0', K_CTRL)),
                sdl2::keyboard::Keycode::RCtrl => Some(('\0', K_CTRL)),
                sdl2::keyboard::Keycode::LAlt => Some(('\0', K_ALT)),
                sdl2::keyboard::Keycode::RAlt => Some(('\0', K_ALT)),
                sdl2::keyboard::Keycode::F1 => Some(('\0', K_F1)),
                sdl2::keyboard::Keycode::F2 => Some(('\0', K_F2)),
                sdl2::keyboard::Keycode::F3 => Some(('\0', K_F3)),
                sdl2::keyboard::Keycode::F4 => Some(('\0', K_F4)),
                sdl2::keyboard::Keycode::F5 => Some(('\0', K_F5)),
                sdl2::keyboard::Keycode::F6 => Some(('\0', K_F6)),
                sdl2::keyboard::Keycode::F7 => Some(('\0', K_F7)),
                sdl2::keyboard::Keycode::F8 => Some(('\0', K_F8)),
                sdl2::keyboard::Keycode::F9 => Some(('\0', K_F9)),
                sdl2::keyboard::Keycode::F10 => Some(('\0', K_F10)),
                sdl2::keyboard::Keycode::Home => Some(('\0', K_HOME)),
                sdl2::keyboard::Keycode::Up => Some(('\0', K_UP)),
                sdl2::keyboard::Keycode::PageUp => Some(('\0', K_PGUP)),
                sdl2::keyboard::Keycode::Left => Some(('\0', K_LEFT)),
                sdl2::keyboard::Keycode::Right => Some(('\0', K_RIGHT)),
                sdl2::keyboard::Keycode::End => Some(('\0', K_END)),
                sdl2::keyboard::Keycode::Down => Some(('\0', K_DOWN)),
                sdl2::keyboard::Keycode::PageDown => Some(('\0', K_PGDN)),
                sdl2::keyboard::Keycode::Delete => Some(('\0', K_DEL)),
                sdl2::keyboard::Keycode::F11 => Some(('\0', K_F11)),
                sdl2::keyboard::Keycode::F12 => Some(('\0', K_F12)),
                sdl2::keyboard::Keycode::LShift => Some(('\0', K_LEFT_SHIFT)),
                sdl2::keyboard::Keycode::RShift => Some(('\0', K_RIGHT_SHIFT)),
                _ => None
            }
        } else {
            None
        }
    }

    fn convert_event(&self, event: sdl2::event::Event) -> Vec<Event> {
        let mut events = Vec::new();

        let mouse_event = || -> Event {
            let mouse = self.ctx.mouse().mouse_state();
            MouseEvent {
                x: mouse.1,
                y: mouse.2,
                left_button: mouse.0.left(),
                middle_button: mouse.0.middle(),
                right_button: mouse.0.right()
            }.to_event()
        };

        match event {
            sdl2::event::Event::MouseMotion { .. } => events.push(mouse_event()),
            sdl2::event::Event::MouseButtonDown { .. } => events.push(mouse_event()),
            sdl2::event::Event::MouseButtonUp { .. } => events.push(mouse_event()),
            sdl2::event::Event::KeyDown { keycode, .. } => if let Some(code) = self.convert_keycode(keycode) {
                events.push(KeyEvent {
                    character: code.0,
                    scancode: code.1,
                    pressed: true
                }.to_event());
            },
            sdl2::event::Event::KeyUp { keycode, .. } => if let Some(code) = self.convert_keycode(keycode) {
                events.push(KeyEvent {
                    character: code.0,
                    scancode: code.1,
                    pressed: false
                }.to_event());
            },
            sdl2::event::Event::TextInput { text, .. } => for c in text.chars() {
                events.push(KeyEvent {
                    character: c,
                    scancode: 0,
                    pressed: true
                }.to_event());
                events.push(KeyEvent {
                    character: c,
                    scancode: 0,
                    pressed: false
                }.to_event());
            },
            sdl2::event::Event::Quit { .. } => events.push(QuitEvent.to_event()),
            _ => (),
        }

        events
    }

    /// Return a iterator over events
    fn events_inner(&mut self, wait: bool) -> EventIter {
        let mut iter = EventIter {
            events: [Event::new(); 128],
            i: 0,
            count: 0,
        };

        if wait {
            let event = self.event_pump.wait_event();
            for converted_event in self.convert_event(event) {
                if iter.count < iter.events.len() {
                    iter.events[iter.count] = converted_event;
                    iter.count += 1;
                } else {
                    break;
                }
            }
        }

        while let Some(event) = self.event_pump.poll_event() {
            for converted_event in self.convert_event(event) {
                if iter.count < iter.events.len() {
                    iter.events[iter.count] = converted_event;
                    iter.count += 1;
                } else {
                    break;
                }
            }
            if iter.count + 2 < iter.events.len() {
                break;
            }
        }

        iter
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        self.events_inner(true)
    }

    /// Nonblocking iterator over events
    pub fn events_no_wait(&mut self) -> EventIter {
        self.events_inner(false)
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.inner.present();
        true
    }
}

/// Event iterator
pub struct EventIter {
    events: [Event; 128],
    i: usize,
    count: usize,
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        if self.i < self.count {
            if let Some(event) = self.events.get(self.i) {
                self.i += 1;
                Some(*event)
            } else {
                None
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write, BufWriter};

use terminal::Terminal;

pub struct Interface {
    lines: Vec<String>,
    terminal: Terminal,
}

impl Interface {
    pub fn new(lines: Vec<String>) -> Interface {
        Interface {
            lines: lines,
            terminal: Terminal::from("/dev/tty").unwrap(),
        }
    }

    pub fn run(&mut self) -> Result<String, io::Error> {
        let mut term = BufWriter::new(&mut self.terminal);
        let mut search = String::new();

        for line in &self.lines {
            write!(term, "{}\n", line)?;
        }

        return Ok(search)
    }
}
<commit_msg>Add custom, centralized Error for Interface<commit_after>use std::io::{self, Write, BufWriter};

use terminal::{self, Terminal};

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Interface {
    lines: Vec<String>,
    terminal: Terminal,
}

impl Interface {
    pub fn new(lines: Vec<String>) -> Interface {
        Interface {
            lines: lines,
            terminal: Terminal::from("/dev/tty").unwrap(),
        }
    }

    pub fn run(&mut self) -> Result<String, Error> {
        let mut term = BufWriter::new(&mut self.terminal);
        let mut search = String::new();

        for line in &self.lines {
            write!(term, "{}\n", line)?;
        }

        return Ok(search)
    }
}
<|endoftext|>


<commit_before>use std::io::Write;

// TODO: should not use wire_format here
use wire_format;

pub enum Visibility {
    Public,
    Default,
}

pub struct CodeWriter<'a> {
    writer: &'a mut (Write + 'a),
    indent: String,
}

impl<'a> CodeWriter<'a> {
    pub fn new(writer: &'a mut Write) -> CodeWriter<'a> {
        CodeWriter {
            writer: writer,
            indent: "".to_string(),
        }
    }

    pub fn write_line<S : AsRef<str>>(&mut self, line: S) {
        (if line.as_ref().is_empty() {
             self.writer.write_all("\n".as_bytes())
         } else {
             let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat();
             self.writer.write_all(s.as_bytes())
         }).unwrap();
    }

    pub fn write_generated(&mut self) {
        self.write_line("// This file is generated. Do not edit");

        // https://secure.phabricator.com/T784
        self.write_line("// @generated");

        self.write_line("");
        self.comment("https://github.com/Manishearth/rust-clippy/issues/702");
        self.write_line("#![allow(unknown_lints)]");
        self.write_line("#![allow(clippy)]");
        self.write_line("");
        self.write_line("#![cfg_attr(rustfmt, rustfmt_skip)]");
        self.write_line("");
        self.write_line("#![allow(box_pointers)]");
        self.write_line("#![allow(dead_code)]");
        self.write_line("#![allow(missing_docs)]");
        self.write_line("#![allow(non_camel_case_types)]");
        self.write_line("#![allow(non_snake_case)]");
        self.write_line("#![allow(non_upper_case_globals)]");
        self.write_line("#![allow(trivial_casts)]");
        self.write_line("#![allow(unsafe_code)]");
        self.write_line("#![allow(unused_imports)]");
        self.write_line("#![allow(unused_results)]");
    }

    pub fn todo(&mut self, message: &str) {
        self.write_line(format!("panic!(\"TODO: {}\");", message));
    }

    pub fn unimplemented(&mut self) {
        self.write_line(format!("unimplemented!();"));
    }

    pub fn indented<F>(&mut self, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("{}    ", self.indent),
        });
    }

    #[allow(dead_code)]
    pub fn commented<F>(&mut self, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("// {}", self.indent),
        });
    }

    pub fn pub_const(&mut self, name: &str, field_type: &str, init: &str) {
        self.write_line(&format!("pub const {}: {} = {};", name, field_type, init));
    }

    pub fn lazy_static(&mut self, name: &str, ty: &str) {
        self.stmt_block(
            &format!(
                "static mut {}: ::protobuf::lazy::Lazy<{}> = ::protobuf::lazy::Lazy",
                name,
                ty
            ),
            |w| {
                w.field_entry("lock", "::protobuf::lazy::ONCE_INIT");
                w.field_entry("ptr", &format!("0 as *const {}", ty));
            },
        );
    }

    pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.lazy_static(name, ty);
        self.unsafe_expr(|w| {
            w.write_line(&format!("{}.get(|| {{", name));
            w.indented(|w| init(w));
            w.write_line(&format!("}})"));
        });
    }

    pub fn lazy_static_decl_get_simple(&mut self, name: &str, ty: &str, init: &str) {
        self.lazy_static(name, ty);
        self.unsafe_expr(|w| { w.write_line(&format!("{}.get({})", name, init)); });
    }

    pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.write_line(first_line);
        self.indented(cb);
        self.write_line(last_line);
    }

    pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.block(&format!("{} {{", prefix), "}", cb);
    }

    pub fn stmt_block<S : AsRef<str>, F>(&mut self, prefix: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.block(&format!("{} {{", prefix.as_ref()), "};", cb);
    }

    pub fn unsafe_expr<F>(&mut self, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block("unsafe", cb);
    }

    pub fn impl_self_block<S : AsRef<str>, F>(&mut self, name: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("impl {}", name.as_ref()), cb);
    }

    pub fn impl_for_block<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("impl {} for {}", tr.as_ref(), ty.as_ref()), cb);
    }

    pub fn unsafe_impl(&mut self, what: &str, for_what: &str) {
        self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what));
    }

    pub fn pub_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
    }

    pub fn def_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("struct {}", name.as_ref()), cb);
    }

    pub fn pub_enum<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub enum {}", name), cb);
    }

    pub fn pub_trait<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub trait {}", name), cb);
    }

    pub fn field_entry(&mut self, name: &str, value: &str) {
        self.write_line(&format!("{}: {},", name, value));
    }

    pub fn field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("{}: {},", name, field_type));
    }

    pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("pub {}: {},", name, field_type));
    }

    pub fn field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str) {
        match vis {
            Visibility::Public => self.pub_field_decl(name, field_type),
            Visibility::Default => self.field_decl(name, field_type),
        }
    }

    pub fn derive(&mut self, derive: &[&str]) {
        let v: Vec<String> = derive.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[derive({})]", v.join(",")));
    }

    pub fn allow(&mut self, what: &[&str]) {
        let v: Vec<String> = what.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[allow({})]", v.join(",")));
    }

    pub fn comment(&mut self, comment: &str) {
        if comment.is_empty() {
            self.write_line("//");
        } else {
            self.write_line(&format!("// {}", comment));
        }
    }

    pub fn fn_def(&mut self, sig: &str) {
        self.write_line(&format!("fn {};", sig));
    }

    pub fn fn_block<F>(&mut self, public: bool, sig: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        if public {
            self.expr_block(&format!("pub fn {}", sig), cb);
        } else {
            self.expr_block(&format!("fn {}", sig), cb);
        }
    }

    pub fn pub_fn<F>(&mut self, sig: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.fn_block(true, sig, cb);
    }

    pub fn def_fn<F>(&mut self, sig: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.fn_block(false, sig, cb);
    }

    pub fn def_mod<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("mod {}", name), cb)
    }

    pub fn pub_mod<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub mod {}", name), cb)
    }

    pub fn while_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("while {}", cond.as_ref()), cb);
    }

    // if ... { ... }
    pub fn if_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("if {}", cond.as_ref()), cb);
    }

    // if ... {} else { ... }
    pub fn if_else_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.write_line(&format!("if {} {{", cond.as_ref()));
        self.write_line("} else {");
        self.indented(cb);
        self.write_line("}");
    }

    // if let ... = ... { ... }
    pub fn if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.if_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    // if let ... = ... { } else { ... }
    pub fn if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.if_else_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    pub fn for_stmt<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb)
    }

    pub fn match_block<S : AsRef<str>, F>(&mut self, value: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.stmt_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn match_expr<S : AsRef<str>, F>(&mut self, value: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn case_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.block(&format!("{} => {{", cond.as_ref()), "},", cb);
    }

    pub fn case_expr<S1 : AsRef<str>, S2 : AsRef<str>>(&mut self, cond: S1, body: S2) {
        self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref()));
    }

    pub fn error_unexpected_wire_type(&mut self, wire_type: &str) {
        self.write_line(&format!(
            "return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type({}));",
            wire_type
        ));
    }

    pub fn assert_wire_type(&mut self, wire_type: wire_format::WireType) {
        self.if_stmt(&format!("wire_type != ::protobuf::wire_format::{:?}", wire_type), |w| {
            w.error_unexpected_wire_type("wire_type");
        });
    }
}
<commit_msg>pub_trait_extend utility<commit_after>use std::io::Write;

// TODO: should not use wire_format here
use wire_format;

pub enum Visibility {
    Public,
    Default,
}

pub struct CodeWriter<'a> {
    writer: &'a mut (Write + 'a),
    indent: String,
}

impl<'a> CodeWriter<'a> {
    pub fn new(writer: &'a mut Write) -> CodeWriter<'a> {
        CodeWriter {
            writer: writer,
            indent: "".to_string(),
        }
    }

    pub fn write_line<S : AsRef<str>>(&mut self, line: S) {
        (if line.as_ref().is_empty() {
             self.writer.write_all("\n".as_bytes())
         } else {
             let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat();
             self.writer.write_all(s.as_bytes())
         }).unwrap();
    }

    pub fn write_generated(&mut self) {
        self.write_line("// This file is generated. Do not edit");

        // https://secure.phabricator.com/T784
        self.write_line("// @generated");

        self.write_line("");
        self.comment("https://github.com/Manishearth/rust-clippy/issues/702");
        self.write_line("#![allow(unknown_lints)]");
        self.write_line("#![allow(clippy)]");
        self.write_line("");
        self.write_line("#![cfg_attr(rustfmt, rustfmt_skip)]");
        self.write_line("");
        self.write_line("#![allow(box_pointers)]");
        self.write_line("#![allow(dead_code)]");
        self.write_line("#![allow(missing_docs)]");
        self.write_line("#![allow(non_camel_case_types)]");
        self.write_line("#![allow(non_snake_case)]");
        self.write_line("#![allow(non_upper_case_globals)]");
        self.write_line("#![allow(trivial_casts)]");
        self.write_line("#![allow(unsafe_code)]");
        self.write_line("#![allow(unused_imports)]");
        self.write_line("#![allow(unused_results)]");
    }

    pub fn todo(&mut self, message: &str) {
        self.write_line(format!("panic!(\"TODO: {}\");", message));
    }

    pub fn unimplemented(&mut self) {
        self.write_line(format!("unimplemented!();"));
    }

    pub fn indented<F>(&mut self, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("{}    ", self.indent),
        });
    }

    #[allow(dead_code)]
    pub fn commented<F>(&mut self, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("// {}", self.indent),
        });
    }

    pub fn pub_const(&mut self, name: &str, field_type: &str, init: &str) {
        self.write_line(&format!("pub const {}: {} = {};", name, field_type, init));
    }

    pub fn lazy_static(&mut self, name: &str, ty: &str) {
        self.stmt_block(
            &format!(
                "static mut {}: ::protobuf::lazy::Lazy<{}> = ::protobuf::lazy::Lazy",
                name,
                ty
            ),
            |w| {
                w.field_entry("lock", "::protobuf::lazy::ONCE_INIT");
                w.field_entry("ptr", &format!("0 as *const {}", ty));
            },
        );
    }

    pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.lazy_static(name, ty);
        self.unsafe_expr(|w| {
            w.write_line(&format!("{}.get(|| {{", name));
            w.indented(|w| init(w));
            w.write_line(&format!("}})"));
        });
    }

    pub fn lazy_static_decl_get_simple(&mut self, name: &str, ty: &str, init: &str) {
        self.lazy_static(name, ty);
        self.unsafe_expr(|w| { w.write_line(&format!("{}.get({})", name, init)); });
    }

    pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.write_line(first_line);
        self.indented(cb);
        self.write_line(last_line);
    }

    pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.block(&format!("{} {{", prefix), "}", cb);
    }

    pub fn stmt_block<S : AsRef<str>, F>(&mut self, prefix: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.block(&format!("{} {{", prefix.as_ref()), "};", cb);
    }

    pub fn unsafe_expr<F>(&mut self, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block("unsafe", cb);
    }

    pub fn impl_self_block<S : AsRef<str>, F>(&mut self, name: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("impl {}", name.as_ref()), cb);
    }

    pub fn impl_for_block<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("impl {} for {}", tr.as_ref(), ty.as_ref()), cb);
    }

    pub fn unsafe_impl(&mut self, what: &str, for_what: &str) {
        self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what));
    }

    pub fn pub_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
    }

    pub fn def_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("struct {}", name.as_ref()), cb);
    }

    pub fn pub_enum<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub enum {}", name), cb);
    }

    pub fn pub_trait<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub trait {}", name), cb);
    }

    pub fn pub_trait_extend<F>(&mut self, name: &str, extend: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub trait {} : {}", name, extend), cb);
    }

    pub fn field_entry(&mut self, name: &str, value: &str) {
        self.write_line(&format!("{}: {},", name, value));
    }

    pub fn field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("{}: {},", name, field_type));
    }

    pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("pub {}: {},", name, field_type));
    }

    pub fn field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str) {
        match vis {
            Visibility::Public => self.pub_field_decl(name, field_type),
            Visibility::Default => self.field_decl(name, field_type),
        }
    }

    pub fn derive(&mut self, derive: &[&str]) {
        let v: Vec<String> = derive.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[derive({})]", v.join(",")));
    }

    pub fn allow(&mut self, what: &[&str]) {
        let v: Vec<String> = what.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[allow({})]", v.join(",")));
    }

    pub fn comment(&mut self, comment: &str) {
        if comment.is_empty() {
            self.write_line("//");
        } else {
            self.write_line(&format!("// {}", comment));
        }
    }

    pub fn fn_def(&mut self, sig: &str) {
        self.write_line(&format!("fn {};", sig));
    }

    pub fn fn_block<F>(&mut self, public: bool, sig: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        if public {
            self.expr_block(&format!("pub fn {}", sig), cb);
        } else {
            self.expr_block(&format!("fn {}", sig), cb);
        }
    }

    pub fn pub_fn<F>(&mut self, sig: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.fn_block(true, sig, cb);
    }

    pub fn def_fn<F>(&mut self, sig: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.fn_block(false, sig, cb);
    }

    pub fn def_mod<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("mod {}", name), cb)
    }

    pub fn pub_mod<F>(&mut self, name: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("pub mod {}", name), cb)
    }

    pub fn while_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("while {}", cond.as_ref()), cb);
    }

    // if ... { ... }
    pub fn if_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("if {}", cond.as_ref()), cb);
    }

    // if ... {} else { ... }
    pub fn if_else_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.write_line(&format!("if {} {{", cond.as_ref()));
        self.write_line("} else {");
        self.indented(cb);
        self.write_line("}");
    }

    // if let ... = ... { ... }
    pub fn if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.if_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    // if let ... = ... { } else { ... }
    pub fn if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.if_else_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    pub fn for_stmt<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb)
    }

    pub fn match_block<S : AsRef<str>, F>(&mut self, value: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.stmt_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn match_expr<S : AsRef<str>, F>(&mut self, value: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.expr_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn case_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
    where
        F : Fn(&mut CodeWriter),
    {
        self.block(&format!("{} => {{", cond.as_ref()), "},", cb);
    }

    pub fn case_expr<S1 : AsRef<str>, S2 : AsRef<str>>(&mut self, cond: S1, body: S2) {
        self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref()));
    }

    pub fn error_unexpected_wire_type(&mut self, wire_type: &str) {
        self.write_line(&format!(
            "return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type({}));",
            wire_type
        ));
    }

    pub fn assert_wire_type(&mut self, wire_type: wire_format::WireType) {
        self.if_stmt(&format!("wire_type != ::protobuf::wire_format::{:?}", wire_type), |w| {
            w.error_unexpected_wire_type("wire_type");
        });
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/// General actor system infrastructure.

use std::any::{Any, AnyRefExt, AnyMutRefExt};
use std::collections::HashMap;
use std::cell::{Cell, RefCell};
use std::intrinsics::TypeId;
use std::io::TcpStream;
use std::mem::{transmute, transmute_copy, replace};
use std::raw::TraitObject;
use serialize::json;

/// A common trait for all devtools actors that encompasses an immutable name
/// and the ability to process messages that are directed to particular actors.
/// TODO: ensure the name is immutable
pub trait Actor {
    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &String,
                      msg: &json::JsonObject,
                      stream: &mut TcpStream) -> bool;
    fn name(&self) -> String;
}

impl<'a> AnyMutRefExt<'a> for &'a mut Actor + 'a {
    fn downcast_mut<T: 'static>(self) -> Option<&'a mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

impl<'a> AnyRefExt<'a> for &'a Actor + 'a {
    fn is<T: 'static>(self) -> bool {
        // This implementation is only needed so long as there's a Rust bug that
        // prevents downcast_ref from giving realistic return values.
        unsafe {
            let t = TypeId::of::<T>();
            let this: &Actor = transmute(self);
            let boxed: TypeId = this.get_type_id();
            t == boxed
        }
    }

    fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

/// A list of known, owned actors.
pub struct ActorRegistry {
    actors: HashMap<String, Box<Actor+Send+Sized>>,
    new_actors: RefCell<Vec<Box<Actor+Send+Sized>>>,
    script_actors: RefCell<HashMap<String, String>>,
    next: Cell<u32>,
}

impl ActorRegistry {
    /// Create an empty registry.
    pub fn new() -> ActorRegistry {
        ActorRegistry {
            actors: HashMap::new(),
            new_actors: RefCell::new(vec!()),
            script_actors: RefCell::new(HashMap::new()),
            next: Cell::new(0),
        }
    }

    pub fn register_script_actor(&self, script_id: String, actor: String) {
        println!("registering {:s} ({:s})", actor.as_slice(), script_id.as_slice());
        let mut script_actors = self.script_actors.borrow_mut();
        script_actors.insert(script_id, actor);
    }

    pub fn script_to_actor(&self, script_id: String) -> String {
        if script_id.as_slice() == "" {
            return "".to_string();
        }
        self.script_actors.borrow().get(&script_id).unwrap().to_string()
    }

    pub fn script_actor_registered(&self, script_id: String) -> bool {
        self.script_actors.borrow().contains_key(&script_id)
    }

    pub fn actor_to_script(&self, actor: String) -> String {
        for (key, value) in self.script_actors.borrow().iter() {
            println!("checking {:s}", value.as_slice());
            if value.as_slice() == actor.as_slice() {
                return key.to_string();
            }
        }
        panic!("couldn't find actor named {:s}", actor)
    }

    /// Create a unique name based on a monotonically increasing suffix
    pub fn new_name(&self, prefix: &str) -> String {
        let suffix = self.next.get();
        self.next.set(suffix + 1);
        format!("{:s}{:u}", prefix, suffix)
    }

    /// Add an actor to the registry of known actors that can receive messages.
    pub fn register(&mut self, actor: Box<Actor+Send+Sized>) {
        self.actors.insert(actor.name().to_string(), actor);
    }

    pub fn register_later(&self, actor: Box<Actor+Send+Sized>) {
        let mut actors = self.new_actors.borrow_mut();
        actors.push(actor);
    }

    /// Find an actor by registered name
    pub fn find<'a, T: 'static>(&'a self, name: &str) -> &'a T {
        //FIXME: Rust bug forces us to implement bogus Any for Actor since downcast_ref currently
        //       fails for unknown reasons.
        /*let actor: &Actor+Send+Sized = *self.actors.find(&name.to_string()).unwrap();
        (actor as &Any).downcast_ref::<T>().unwrap()*/
        self.actors.get(&name.to_string()).unwrap().downcast_ref::<T>().unwrap()
    }

    /// Find an actor by registered name
    pub fn find_mut<'a, T: 'static>(&'a mut self, name: &str) -> &'a mut T {
        //FIXME: Rust bug forces us to implement bogus Any for Actor since downcast_ref currently
        //       fails for unknown reasons.
        /*let actor: &mut Actor+Send+Sized = *self.actors.find_mut(&name.to_string()).unwrap();
        (actor as &mut Any).downcast_mut::<T>().unwrap()*/
        self.actors.get_mut(&name.to_string()).unwrap().downcast_mut::<T>().unwrap()
    }

    /// Attempt to process a message as directed by its `to` property. If the actor is not
    /// found or does not indicate that it knew how to process the message, ignore the failure.
    pub fn handle_message(&mut self, msg: &json::JsonObject, stream: &mut TcpStream) {
        let to = msg.get(&"to".to_string()).unwrap().as_string().unwrap();
        match self.actors.get(&to.to_string()) {
            None => println!("message received for unknown actor \"{:s}\"", to),
            Some(actor) => {
                let msg_type = msg.get(&"type".to_string()).unwrap().as_string().unwrap();
                if !actor.handle_message(self, &msg_type.to_string(), msg, stream) {
                    println!("unexpected message type \"{:s}\" found for actor \"{:s}\"",
                             msg_type, to);
                }
            }
        }
        let new_actors = replace(&mut *self.new_actors.borrow_mut(), vec!());
        for actor in new_actors.into_iter() {
            self.actors.insert(actor.name().to_string(), actor);
        }
    }
}
<commit_msg>auto merge of #4147 : jdm/servo/devtoolspanic, r=Manishearth<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/// General actor system infrastructure.

use std::any::{Any, AnyRefExt, AnyMutRefExt};
use std::collections::HashMap;
use std::cell::{Cell, RefCell};
use std::intrinsics::TypeId;
use std::io::TcpStream;
use std::mem::{transmute, transmute_copy, replace};
use std::raw::TraitObject;
use serialize::json;

/// A common trait for all devtools actors that encompasses an immutable name
/// and the ability to process messages that are directed to particular actors.
/// TODO: ensure the name is immutable
pub trait Actor : Any {
    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &String,
                      msg: &json::JsonObject,
                      stream: &mut TcpStream) -> bool;
    fn name(&self) -> String;
}

impl<'a> AnyMutRefExt<'a> for &'a mut Actor + 'a {
    fn downcast_mut<T: 'static>(self) -> Option<&'a mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

impl<'a> AnyRefExt<'a> for &'a Actor + 'a {
    fn is<T: 'static>(self) -> bool {
        // This implementation is only needed so long as there's a Rust bug that
        // prevents downcast_ref from giving realistic return values.
        let t = TypeId::of::<T>();
        let boxed: TypeId = (*self).get_type_id();
        t == boxed
    }

    fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

/// A list of known, owned actors.
pub struct ActorRegistry {
    actors: HashMap<String, Box<Actor+Send+Sized>>,
    new_actors: RefCell<Vec<Box<Actor+Send+Sized>>>,
    script_actors: RefCell<HashMap<String, String>>,
    next: Cell<u32>,
}

impl ActorRegistry {
    /// Create an empty registry.
    pub fn new() -> ActorRegistry {
        ActorRegistry {
            actors: HashMap::new(),
            new_actors: RefCell::new(vec!()),
            script_actors: RefCell::new(HashMap::new()),
            next: Cell::new(0),
        }
    }

    pub fn register_script_actor(&self, script_id: String, actor: String) {
        println!("registering {:s} ({:s})", actor.as_slice(), script_id.as_slice());
        let mut script_actors = self.script_actors.borrow_mut();
        script_actors.insert(script_id, actor);
    }

    pub fn script_to_actor(&self, script_id: String) -> String {
        if script_id.as_slice() == "" {
            return "".to_string();
        }
        self.script_actors.borrow().get(&script_id).unwrap().to_string()
    }

    pub fn script_actor_registered(&self, script_id: String) -> bool {
        self.script_actors.borrow().contains_key(&script_id)
    }

    pub fn actor_to_script(&self, actor: String) -> String {
        for (key, value) in self.script_actors.borrow().iter() {
            println!("checking {:s}", value.as_slice());
            if value.as_slice() == actor.as_slice() {
                return key.to_string();
            }
        }
        panic!("couldn't find actor named {:s}", actor)
    }

    /// Create a unique name based on a monotonically increasing suffix
    pub fn new_name(&self, prefix: &str) -> String {
        let suffix = self.next.get();
        self.next.set(suffix + 1);
        format!("{:s}{:u}", prefix, suffix)
    }

    /// Add an actor to the registry of known actors that can receive messages.
    pub fn register(&mut self, actor: Box<Actor+Send+Sized>) {
        self.actors.insert(actor.name().to_string(), actor);
    }

    pub fn register_later(&self, actor: Box<Actor+Send+Sized>) {
        let mut actors = self.new_actors.borrow_mut();
        actors.push(actor);
    }

    /// Find an actor by registered name
    pub fn find<'a, T: 'static>(&'a self, name: &str) -> &'a T {
        //FIXME: Rust bug forces us to implement bogus Any for Actor since downcast_ref currently
        //       fails for unknown reasons.
        /*let actor: &Actor+Send+Sized = *self.actors.find(&name.to_string()).unwrap();
        (actor as &Any).downcast_ref::<T>().unwrap()*/
        self.actors.get(&name.to_string()).unwrap().downcast_ref::<T>().unwrap()
    }

    /// Find an actor by registered name
    pub fn find_mut<'a, T: 'static>(&'a mut self, name: &str) -> &'a mut T {
        //FIXME: Rust bug forces us to implement bogus Any for Actor since downcast_ref currently
        //       fails for unknown reasons.
        /*let actor: &mut Actor+Send+Sized = *self.actors.find_mut(&name.to_string()).unwrap();
        (actor as &mut Any).downcast_mut::<T>().unwrap()*/
        self.actors.get_mut(&name.to_string()).unwrap().downcast_mut::<T>().unwrap()
    }

    /// Attempt to process a message as directed by its `to` property. If the actor is not
    /// found or does not indicate that it knew how to process the message, ignore the failure.
    pub fn handle_message(&mut self, msg: &json::JsonObject, stream: &mut TcpStream) {
        let to = msg.get(&"to".to_string()).unwrap().as_string().unwrap();
        match self.actors.get(&to.to_string()) {
            None => println!("message received for unknown actor \"{:s}\"", to),
            Some(actor) => {
                let msg_type = msg.get(&"type".to_string()).unwrap().as_string().unwrap();
                if !actor.handle_message(self, &msg_type.to_string(), msg, stream) {
                    println!("unexpected message type \"{:s}\" found for actor \"{:s}\"",
                             msg_type, to);
                }
            }
        }
        let new_actors = replace(&mut *self.new_actors.borrow_mut(), vec!());
        for actor in new_actors.into_iter() {
            self.actors.insert(actor.name().to_string(), actor);
        }
    }
}
<|endoftext|>


<commit_before>use crate::{error::{Error as HabError,
                    Result},
            hcore::fs::{am_i_root,
                        FS_ROOT_PATH},
            CTL_SECRET_ENVVAR};
use habitat_core::{env as henv,
                   origin::Origin};
use habitat_sup_client::SrvClient;
use std::{fs::{self,
               File},
          io::{self,
               Write},
          path::{Path,
                 PathBuf}};

const CLI_CONFIG_PATH_POSTFIX: &str = "hab/etc/cli.toml";

lazy_static::lazy_static! {
    pub static ref CLI_CONFIG_PATH: PathBuf = cli_config_path();

    /// A cached reading of the config file. This avoids the need to continually read from disk.
    /// However, it also means changes to the file will not be picked up after the program has
    /// started. Ideally, we would repopulate this struct on file change or on some configured
    /// interval.
    /// https://github.com/habitat-sh/habitat/issues/7243
    pub static ref CACHED: Config = load().unwrap_or_default();
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("reading '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    File(#[from] io::Error),
    #[error("parsing '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    Toml(#[from] toml::de::Error),
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Config {
    pub auth_token: Option<String>,
    pub origin:     Option<Origin>,
    pub ctl_secret: Option<String>,
    pub bldr_url:   Option<String>,
}

impl Config {
    fn from_file<T: AsRef<Path>>(path: T) -> std::result::Result<Self, Error> {
        let raw = fs::read_to_string(path)?;
        Ok(toml::from_str(&raw)?)
    }
}

impl Default for Config {
    fn default() -> Self {
        Config { auth_token: None,
                 origin:     None,
                 ctl_secret: None,
                 bldr_url:   None, }
    }
}

pub fn load() -> std::result::Result<Config, Error> {
    let cli_config_path = cli_config_path();
    if cli_config_path.exists() {
        debug!("Loading CLI config from {}", cli_config_path.display());
        Ok(Config::from_file(&cli_config_path)?)
    } else {
        debug!("No CLI config found, loading defaults");
        Ok(Config::default())
    }
}

pub fn save(config: &Config) -> Result<()> {
    let config_path = cli_config_path();
    let parent_path = match config_path.parent() {
        Some(p) => p,
        None => {
            return Err(HabError::FileNotFound(config_path.to_string_lossy().into_owned()));
        }
    };
    fs::create_dir_all(&parent_path)?;
    let raw = toml::ser::to_string(config)?;
    debug!("Raw config toml:\n---\n{}\n---", &raw);
    let mut file = File::create(&config_path)?;
    file.write_all(raw.as_bytes())?;
    Ok(())
}

/// Check if the HAB_CTL_SECRET env var. If not, check the CLI config to see if there is a ctl
/// secret set and return a copy of that value.
pub fn ctl_secret_key(config: &Config) -> Result<String> {
    match henv::var(CTL_SECRET_ENVVAR) {
        Ok(v) => Ok(v),
        Err(_) => {
            match config.ctl_secret {
                Some(ref v) => Ok(v.to_string()),
                None => SrvClient::read_secret_key().map_err(HabError::from),
            }
        }
    }
}

fn cli_config_path() -> PathBuf {
    if !am_i_root() {
        if let Some(home) = dirs::home_dir() {
            return home.join(format!(".{}", CLI_CONFIG_PATH_POSTFIX));
        }
    }
    PathBuf::from(&*FS_ROOT_PATH).join(CLI_CONFIG_PATH_POSTFIX)
}
<commit_msg>[Refactor] Use static cli config path<commit_after>use crate::{error::{Error as HabError,
                    Result},
            hcore::fs::{am_i_root,
                        FS_ROOT_PATH},
            CTL_SECRET_ENVVAR};
use habitat_core::{env as henv,
                   origin::Origin};
use habitat_sup_client::SrvClient;
use std::{fs::{self,
               File},
          io::{self,
               Write},
          path::{Path,
                 PathBuf}};

const CLI_CONFIG_PATH_POSTFIX: &str = "hab/etc/cli.toml";

lazy_static::lazy_static! {
    pub static ref CLI_CONFIG_PATH: PathBuf = cli_config_path();

    /// A cached reading of the config file. This avoids the need to continually read from disk.
    /// However, it also means changes to the file will not be picked up after the program has
    /// started. Ideally, we would repopulate this struct on file change or on some configured
    /// interval.
    /// https://github.com/habitat-sh/habitat/issues/7243
    pub static ref CACHED: Config = load().unwrap_or_default();
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("reading '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    File(#[from] io::Error),
    #[error("parsing '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    Toml(#[from] toml::de::Error),
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Config {
    pub auth_token: Option<String>,
    pub origin:     Option<Origin>,
    pub ctl_secret: Option<String>,
    pub bldr_url:   Option<String>,
}

impl Config {
    fn from_file<T: AsRef<Path>>(path: T) -> std::result::Result<Self, Error> {
        let raw = fs::read_to_string(path)?;
        Ok(toml::from_str(&raw)?)
    }
}

impl Default for Config {
    fn default() -> Self {
        Config { auth_token: None,
                 origin:     None,
                 ctl_secret: None,
                 bldr_url:   None, }
    }
}

pub fn load() -> std::result::Result<Config, Error> {
    if CLI_CONFIG_PATH.exists() {
        debug!("Loading CLI config from {}", CLI_CONFIG_PATH.display());
        Ok(Config::from_file(&*CLI_CONFIG_PATH)?)
    } else {
        debug!("No CLI config found, loading defaults");
        Ok(Config::default())
    }
}

pub fn save(config: &Config) -> Result<()> {
    let parent_path = match CLI_CONFIG_PATH.parent() {
        Some(p) => p,
        None => {
            return Err(HabError::FileNotFound(CLI_CONFIG_PATH.display().to_string()));
        }
    };
    fs::create_dir_all(&parent_path)?;
    let raw = toml::ser::to_string(config)?;
    debug!("Raw config toml:\n---\n{}\n---", &raw);
    let mut file = File::create(&*CLI_CONFIG_PATH)?;
    file.write_all(raw.as_bytes())?;
    Ok(())
}

/// Check if the HAB_CTL_SECRET env var. If not, check the CLI config to see if there is a ctl
/// secret set and return a copy of that value.
pub fn ctl_secret_key(config: &Config) -> Result<String> {
    match henv::var(CTL_SECRET_ENVVAR) {
        Ok(v) => Ok(v),
        Err(_) => {
            match config.ctl_secret {
                Some(ref v) => Ok(v.to_string()),
                None => SrvClient::read_secret_key().map_err(HabError::from),
            }
        }
    }
}

fn cli_config_path() -> PathBuf {
    if !am_i_root() {
        if let Some(home) = dirs::home_dir() {
            return home.join(format!(".{}", CLI_CONFIG_PATH_POSTFIX));
        }
    }
    PathBuf::from(&*FS_ROOT_PATH).join(CLI_CONFIG_PATH_POSTFIX)
}
<|endoftext|>