<commit_before>use std::cmp;

use crate::ich::StableHashingContext;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
use rustc_hir::HirId;
pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass};
use rustc_session::{DiagnosticMessageId, Session};
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
use rustc_span::{Span, Symbol};

/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
pub enum LintSource {
    /// Lint is at the default level as declared
    /// in rustc or a plugin.
    Default,

    /// Lint level was set by an attribute.
    Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */),

    /// Lint level was set by a command-line flag.
    CommandLine(Symbol),
}

pub type LevelSource = (Level, LintSource);

pub struct LintLevelSets {
    pub list: Vec<LintSet>,
    pub lint_cap: Level,
}

pub enum LintSet {
    CommandLine {
        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
        // flag.
        specs: FxHashMap<LintId, LevelSource>,
    },

    Node {
        specs: FxHashMap<LintId, LevelSource>,
        parent: u32,
    },
}

impl LintLevelSets {
    pub fn new() -> Self {
        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
    }

    pub fn get_lint_level(
        &self,
        lint: &'static Lint,
        idx: u32,
        aux: Option<&FxHashMap<LintId, LevelSource>>,
        sess: &Session,
    ) -> LevelSource {
        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);

        // If `level` is none then we actually assume the default level for this
        // lint.
        let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));

        // If we're about to issue a warning, check at the last minute for any
        // directives against the warnings "lint". If, for example, there's an
        // `allow(warnings)` in scope then we want to respect that instead.
        if level == Level::Warn {
            let (warnings_level, warnings_src) =
                self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux);
            if let Some(configured_warning_level) = warnings_level {
                if configured_warning_level != Level::Warn {
                    level = configured_warning_level;
                    src = warnings_src;
                }
            }
        }

        // Ensure that we never exceed the `--cap-lints` argument.
        level = cmp::min(level, self.lint_cap);

        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
            // Ensure that we never exceed driver level.
            level = cmp::min(*driver_level, level);
        }

        return (level, src);
    }

    pub fn get_lint_id_level(
        &self,
        id: LintId,
        mut idx: u32,
        aux: Option<&FxHashMap<LintId, LevelSource>>,
    ) -> (Option<Level>, LintSource) {
        if let Some(specs) = aux {
            if let Some(&(level, src)) = specs.get(&id) {
                return (Some(level), src);
            }
        }
        loop {
            match self.list[idx as usize] {
                LintSet::CommandLine { ref specs } => {
                    if let Some(&(level, src)) = specs.get(&id) {
                        return (Some(level), src);
                    }
                    return (None, LintSource::Default);
                }
                LintSet::Node { ref specs, parent } => {
                    if let Some(&(level, src)) = specs.get(&id) {
                        return (Some(level), src);
                    }
                    idx = parent;
                }
            }
        }
    }
}

pub struct LintLevelMap {
    pub sets: LintLevelSets,
    pub id_to_set: FxHashMap<HirId, u32>,
}

impl LintLevelMap {
    /// If the `id` was previously registered with `register_id` when building
    /// this `LintLevelMap` this returns the corresponding lint level and source
    /// of the lint level for the lint provided.
    ///
    /// If the `id` was not previously registered, returns `None`. If `None` is
    /// returned then the parent of `id` should be acquired and this function
    /// should be called again.
    pub fn level_and_source(
        &self,
        lint: &'static Lint,
        id: HirId,
        session: &Session,
    ) -> Option<LevelSource> {
        self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
    #[inline]
    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
        let LintLevelMap { ref sets, ref id_to_set } = *self;

        id_to_set.hash_stable(hcx, hasher);

        let LintLevelSets { ref list, lint_cap } = *sets;

        lint_cap.hash_stable(hcx, hasher);

        hcx.while_hashing_spans(true, |hcx| {
            list.len().hash_stable(hcx, hasher);

            // We are working under the assumption here that the list of
            // lint-sets is built in a deterministic order.
            for lint_set in list {
                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);

                match *lint_set {
                    LintSet::CommandLine { ref specs } => {
                        specs.hash_stable(hcx, hasher);
                    }
                    LintSet::Node { ref specs, parent } => {
                        specs.hash_stable(hcx, hasher);
                        parent.hash_stable(hcx, hasher);
                    }
                }
            }
        })
    }
}

pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a>);

impl<'a> LintDiagnosticBuilder<'a> {
    /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
    pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> {
        self.0.set_primary_message(msg);
        self.0
    }

    /// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder.
    pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a>{
        LintDiagnosticBuilder(err)
    }
}

pub fn struct_lint_level<'s>(
    sess: &'s Session,
    lint: &'static Lint,
    level: Level,
    src: LintSource,
    span: Option<MultiSpan>,
    decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) {

    // FIXME: Move the guts of this function into a fn which takes dyn Fn to reduce code bloat.
    let mut err = match (level, span) {
        (Level::Allow, _) => { return; },
        (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""),
        (Level::Warn, None) => sess.struct_warn(""),
        (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
        (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""),
    };

    // Check for future incompatibility lints and issue a stronger warning.
    let lint_id = LintId::of(lint);
    let future_incompatible = lint.future_incompatible;

    // If this code originates in a foreign macro, aka something that this crate
    // did not itself author, then it's likely that there's nothing this crate
    // can do about it. We probably want to skip the lint entirely.
    if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
        // Any suggestions made here are likely to be incorrect, so anything we
        // emit shouldn't be automatically fixed by rustfix.
        err.allow_suggestions(false);

        // If this is a future incompatible lint it'll become a hard error, so
        // we have to emit *something*. Also allow lints to whitelist themselves
        // on a case-by-case basis for emission in a foreign macro.
        if future_incompatible.is_none() && !lint.report_in_external_macro {
            err.cancel();
            // Don't continue further, since we don't want to have
            // `diag_span_note_once` called for a diagnostic that isn't emitted.
            return;
        }
    }

    let name = lint.name_lower();
    match src {
        LintSource::Default => {
            sess.diag_note_once(
                &mut err,
                DiagnosticMessageId::from(lint),
                &format!("`#[{}({})]` on by default", level.as_str(), name),
            );
        }
        LintSource::CommandLine(lint_flag_val) => {
            let flag = match level {
                Level::Warn => "-W",
                Level::Deny => "-D",
                Level::Forbid => "-F",
                Level::Allow => panic!(),
            };
            let hyphen_case_lint_name = name.replace("_", "-");
            if lint_flag_val.as_str() == name {
                sess.diag_note_once(
                    &mut err,
                    DiagnosticMessageId::from(lint),
                    &format!(
                        "requested on the command line with `{} {}`",
                        flag, hyphen_case_lint_name
                    ),
                );
            } else {
                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
                sess.diag_note_once(
                    &mut err,
                    DiagnosticMessageId::from(lint),
                    &format!(
                        "`{} {}` implied by `{} {}`",
                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
                    ),
                );
            }
        }
        LintSource::Node(lint_attr_name, src, reason) => {
            if let Some(rationale) = reason {
                err.note(&rationale.as_str());
            }
            sess.diag_span_note_once(
                &mut err,
                DiagnosticMessageId::from(lint),
                src,
                "the lint level is defined here",
            );
            if lint_attr_name.as_str() != name {
                let level_str = level.as_str();
                sess.diag_note_once(
                    &mut err,
                    DiagnosticMessageId::from(lint),
                    &format!(
                        "`#[{}({})]` implied by `#[{}({})]`",
                        level_str, name, level_str, lint_attr_name
                    ),
                );
            }
        }
    }

    err.code(DiagnosticId::Lint(name));

    if let Some(future_incompatible) = future_incompatible {
        const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
             it will become a hard error";

        let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
            "once this method is added to the standard library, \
             the ambiguity may cause an error or change in behavior!"
                .to_owned()
        } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
            "this borrowing pattern was not meant to be accepted, \
             and may become a hard error in the future"
                .to_owned()
        } else if let Some(edition) = future_incompatible.edition {
            format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
        } else {
            format!("{} in a future release!", STANDARD_MESSAGE)
        };
        let citation = format!("for more information, see {}", future_incompatible.reference);
        err.warn(&explanation);
        err.note(&citation);
    }

    // Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
    decorate(LintDiagnosticBuilder::new(err));
}

/// Returns whether `span` originates in a foreign crate's external macro.
///
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
    let expn_data = span.ctxt().outer_expn_data();
    match expn_data.kind {
        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
        ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
        ExpnKind::Macro(MacroKind::Bang, _) => {
            if expn_data.def_site.is_dummy() {
                // Dummy span for the `def_site` means it's an external macro.
                return true;
            }
            match sess.source_map().span_to_snippet(expn_data.def_site) {
                Ok(code) => !code.starts_with("macro_rules"),
                // No snippet means external macro or compiler-builtin expansion.
                Err(_) => true,
            }
        }
        ExpnKind::Macro(..) => true, // definitely a plugin
    }
}

pub fn add_elided_lifetime_in_path_suggestion(
    sess: &Session,
    db: &mut DiagnosticBuilder<'_>,
    n: usize,
    path_span: Span,
    incl_angl_brckt: bool,
    insertion_span: Span,
    anon_lts: String,
) {
    let (replace_span, suggestion) = if incl_angl_brckt {
        (insertion_span, anon_lts)
    } else {
        // When possible, prefer a suggestion that replaces the whole
        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
        // at a point (which makes for an ugly/confusing label)
        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
            // But our spans can get out of whack due to macros; if the place we think
            // we want to insert `'_` isn't even within the path expression's span, we
            // should bail out of making any suggestion rather than panicking on a
            // subtract-with-overflow or string-slice-out-out-bounds (!)
            // FIXME: can we do better?
            if insertion_span.lo().0 < path_span.lo().0 {
                return;
            }
            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
            if insertion_index > snippet.len() {
                return;
            }
            let (before, after) = snippet.split_at(insertion_index);
            (path_span, format!("{}{}{}", before, anon_lts, after))
        } else {
            (insertion_span, anon_lts)
        }
    };
    db.span_suggestion(
        replace_span,
        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
        suggestion,
        Applicability::MachineApplicable,
    );
}
<commit_msg>Box `decorate` to avoid code bloat.<commit_after>use std::cmp;

use crate::ich::StableHashingContext;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
use rustc_hir::HirId;
pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass};
use rustc_session::{DiagnosticMessageId, Session};
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
use rustc_span::{Span, Symbol};

/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
pub enum LintSource {
    /// Lint is at the default level as declared
    /// in rustc or a plugin.
    Default,

    /// Lint level was set by an attribute.
    Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */),

    /// Lint level was set by a command-line flag.
    CommandLine(Symbol),
}

pub type LevelSource = (Level, LintSource);

pub struct LintLevelSets {
    pub list: Vec<LintSet>,
    pub lint_cap: Level,
}

pub enum LintSet {
    CommandLine {
        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
        // flag.
        specs: FxHashMap<LintId, LevelSource>,
    },

    Node {
        specs: FxHashMap<LintId, LevelSource>,
        parent: u32,
    },
}

impl LintLevelSets {
    pub fn new() -> Self {
        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
    }

    pub fn get_lint_level(
        &self,
        lint: &'static Lint,
        idx: u32,
        aux: Option<&FxHashMap<LintId, LevelSource>>,
        sess: &Session,
    ) -> LevelSource {
        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);

        // If `level` is none then we actually assume the default level for this
        // lint.
        let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));

        // If we're about to issue a warning, check at the last minute for any
        // directives against the warnings "lint". If, for example, there's an
        // `allow(warnings)` in scope then we want to respect that instead.
        if level == Level::Warn {
            let (warnings_level, warnings_src) =
                self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux);
            if let Some(configured_warning_level) = warnings_level {
                if configured_warning_level != Level::Warn {
                    level = configured_warning_level;
                    src = warnings_src;
                }
            }
        }

        // Ensure that we never exceed the `--cap-lints` argument.
        level = cmp::min(level, self.lint_cap);

        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
            // Ensure that we never exceed driver level.
            level = cmp::min(*driver_level, level);
        }

        return (level, src);
    }

    pub fn get_lint_id_level(
        &self,
        id: LintId,
        mut idx: u32,
        aux: Option<&FxHashMap<LintId, LevelSource>>,
    ) -> (Option<Level>, LintSource) {
        if let Some(specs) = aux {
            if let Some(&(level, src)) = specs.get(&id) {
                return (Some(level), src);
            }
        }
        loop {
            match self.list[idx as usize] {
                LintSet::CommandLine { ref specs } => {
                    if let Some(&(level, src)) = specs.get(&id) {
                        return (Some(level), src);
                    }
                    return (None, LintSource::Default);
                }
                LintSet::Node { ref specs, parent } => {
                    if let Some(&(level, src)) = specs.get(&id) {
                        return (Some(level), src);
                    }
                    idx = parent;
                }
            }
        }
    }
}

pub struct LintLevelMap {
    pub sets: LintLevelSets,
    pub id_to_set: FxHashMap<HirId, u32>,
}

impl LintLevelMap {
    /// If the `id` was previously registered with `register_id` when building
    /// this `LintLevelMap` this returns the corresponding lint level and source
    /// of the lint level for the lint provided.
    ///
    /// If the `id` was not previously registered, returns `None`. If `None` is
    /// returned then the parent of `id` should be acquired and this function
    /// should be called again.
    pub fn level_and_source(
        &self,
        lint: &'static Lint,
        id: HirId,
        session: &Session,
    ) -> Option<LevelSource> {
        self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
    #[inline]
    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
        let LintLevelMap { ref sets, ref id_to_set } = *self;

        id_to_set.hash_stable(hcx, hasher);

        let LintLevelSets { ref list, lint_cap } = *sets;

        lint_cap.hash_stable(hcx, hasher);

        hcx.while_hashing_spans(true, |hcx| {
            list.len().hash_stable(hcx, hasher);

            // We are working under the assumption here that the list of
            // lint-sets is built in a deterministic order.
            for lint_set in list {
                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);

                match *lint_set {
                    LintSet::CommandLine { ref specs } => {
                        specs.hash_stable(hcx, hasher);
                    }
                    LintSet::Node { ref specs, parent } => {
                        specs.hash_stable(hcx, hasher);
                        parent.hash_stable(hcx, hasher);
                    }
                }
            }
        })
    }
}

pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a>);

impl<'a> LintDiagnosticBuilder<'a> {
    /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
    pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> {
        self.0.set_primary_message(msg);
        self.0
    }

    /// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder.
    pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a>{
        LintDiagnosticBuilder(err)
    }
}

pub fn struct_lint_level<'s, 'd>(
    sess: &'s Session,
    lint: &'static Lint,
    level: Level,
    src: LintSource,
    span: Option<MultiSpan>,
    decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + 'd,
) {
    // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
    // the "real" work.
    fn struct_lint_level_impl(
        sess: &'s Session,
        lint: &'static Lint,
        level: Level,
        src: LintSource,
        span: Option<MultiSpan>,
        decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>) {
        let mut err = match (level, span) {
            (Level::Allow, _) => {
                return;
            }
            (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""),
            (Level::Warn, None) => sess.struct_warn(""),
            (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
            (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""),
        };

        // Check for future incompatibility lints and issue a stronger warning.
        let lint_id = LintId::of(lint);
        let future_incompatible = lint.future_incompatible;

        // If this code originates in a foreign macro, aka something that this crate
        // did not itself author, then it's likely that there's nothing this crate
        // can do about it. We probably want to skip the lint entirely.
        if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
            // Any suggestions made here are likely to be incorrect, so anything we
            // emit shouldn't be automatically fixed by rustfix.
            err.allow_suggestions(false);

            // If this is a future incompatible lint it'll become a hard error, so
            // we have to emit *something*. Also allow lints to whitelist themselves
            // on a case-by-case basis for emission in a foreign macro.
            if future_incompatible.is_none() && !lint.report_in_external_macro {
                err.cancel();
                // Don't continue further, since we don't want to have
                // `diag_span_note_once` called for a diagnostic that isn't emitted.
                return;
            }
        }

        let name = lint.name_lower();
        match src {
            LintSource::Default => {
                sess.diag_note_once(
                    &mut err,
                    DiagnosticMessageId::from(lint),
                    &format!("`#[{}({})]` on by default", level.as_str(), name),
                );
            }
            LintSource::CommandLine(lint_flag_val) => {
                let flag = match level {
                    Level::Warn => "-W",
                    Level::Deny => "-D",
                    Level::Forbid => "-F",
                    Level::Allow => panic!(),
                };
                let hyphen_case_lint_name = name.replace("_", "-");
                if lint_flag_val.as_str() == name {
                    sess.diag_note_once(
                        &mut err,
                        DiagnosticMessageId::from(lint),
                        &format!(
                            "requested on the command line with `{} {}`",
                            flag, hyphen_case_lint_name
                        ),
                    );
                } else {
                    let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
                    sess.diag_note_once(
                        &mut err,
                        DiagnosticMessageId::from(lint),
                        &format!(
                            "`{} {}` implied by `{} {}`",
                            flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
                        ),
                    );
                }
            }
            LintSource::Node(lint_attr_name, src, reason) => {
                if let Some(rationale) = reason {
                    err.note(&rationale.as_str());
                }
                sess.diag_span_note_once(
                    &mut err,
                    DiagnosticMessageId::from(lint),
                    src,
                    "the lint level is defined here",
                );
                if lint_attr_name.as_str() != name {
                    let level_str = level.as_str();
                    sess.diag_note_once(
                        &mut err,
                        DiagnosticMessageId::from(lint),
                        &format!(
                            "`#[{}({})]` implied by `#[{}({})]`",
                            level_str, name, level_str, lint_attr_name
                        ),
                    );
                }
            }
        }

        err.code(DiagnosticId::Lint(name));

        if let Some(future_incompatible) = future_incompatible {
            const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
                 it will become a hard error";

            let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
                "once this method is added to the standard library, \
                 the ambiguity may cause an error or change in behavior!"
                    .to_owned()
            } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
                "this borrowing pattern was not meant to be accepted, \
                 and may become a hard error in the future"
                    .to_owned()
            } else if let Some(edition) = future_incompatible.edition {
                format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
            } else {
                format!("{} in a future release!", STANDARD_MESSAGE)
            };
            let citation = format!("for more information, see {}", future_incompatible.reference);
            err.warn(&explanation);
            err.note(&citation);
        }

        // Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
        decorate(LintDiagnosticBuilder::new(err));
    }
    struct_lint_level_impl(sess, lint, level, src, span, Box::new(decorate))
}

/// Returns whether `span` originates in a foreign crate's external macro.
///
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
    let expn_data = span.ctxt().outer_expn_data();
    match expn_data.kind {
        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
        ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
        ExpnKind::Macro(MacroKind::Bang, _) => {
            if expn_data.def_site.is_dummy() {
                // Dummy span for the `def_site` means it's an external macro.
                return true;
            }
            match sess.source_map().span_to_snippet(expn_data.def_site) {
                Ok(code) => !code.starts_with("macro_rules"),
                // No snippet means external macro or compiler-builtin expansion.
                Err(_) => true,
            }
        }
        ExpnKind::Macro(..) => true, // definitely a plugin
    }
}

pub fn add_elided_lifetime_in_path_suggestion(
    sess: &Session,
    db: &mut DiagnosticBuilder<'_>,
    n: usize,
    path_span: Span,
    incl_angl_brckt: bool,
    insertion_span: Span,
    anon_lts: String,
) {
    let (replace_span, suggestion) = if incl_angl_brckt {
        (insertion_span, anon_lts)
    } else {
        // When possible, prefer a suggestion that replaces the whole
        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
        // at a point (which makes for an ugly/confusing label)
        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
            // But our spans can get out of whack due to macros; if the place we think
            // we want to insert `'_` isn't even within the path expression's span, we
            // should bail out of making any suggestion rather than panicking on a
            // subtract-with-overflow or string-slice-out-out-bounds (!)
            // FIXME: can we do better?
            if insertion_span.lo().0 < path_span.lo().0 {
                return;
            }
            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
            if insertion_index > snippet.len() {
                return;
            }
            let (before, after) = snippet.split_at(insertion_index);
            (path_span, format!("{}{}{}", before, anon_lts, after))
        } else {
            (insertion_span, anon_lts)
        }
    };
    db.span_suggestion(
        replace_span,
        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
        suggestion,
        Applicability::MachineApplicable,
    );
}
<|endoftext|>


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

/*!

Operations on the ubiquitous `Option` type.

Type `Option` represents an optional value.

Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
languages you might use a nullable type, in Rust you would use an option
type.

Options are most commonly used with pattern matching to query the presence
of a value and take action, always accounting for the `None` case.

# Example

~~~
let msg = Some(~"howdy");

// Take a reference to the contained string
match msg {
    Some(ref m) => io::println(m),
    None => ()
}

// Remove the contained string, destroying the Option
let unwrapped_msg = match msg {
    Some(m) => m,
    None => ~"default message"
};
~~~

*/

use cmp::{Eq,Ord};
use ops::Add;
use kinds::Copy;
use util;
use num::Zero;
use iterator::Iterator;
use str::StrSlice;
use clone::DeepClone;

#[cfg(test)] use str;
#[cfg(test)] use iterator::IteratorUtil;

/// The option type
#[deriving(Clone, DeepClone, Eq)]
pub enum Option<T> {
    None,
    Some(T),
}

impl<T:Ord> Ord for Option<T> {
    fn lt(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => false,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a < *b
        }
    }

    fn le(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => true,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a <= *b
        }
    }

    fn ge(&self, other: &Option<T>) -> bool {
        !(self < other)
    }

    fn gt(&self, other: &Option<T>) -> bool {
        !(self <= other)
    }
}

impl<T: Copy + Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
    #[inline(always)]
    fn add(&self, other: &Option<T>) -> Option<T> {
        match (*self, *other) {
            (None, None) => None,
            (_, None) => *self,
            (None, _) => *other,
            (Some(ref lhs), Some(ref rhs)) => Some(*lhs + *rhs)
        }
    }
}

impl<T> Option<T> {
    /// Return an iterator over the possibly contained value
    #[inline]
    pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
        match *self {
            Some(ref x) => OptionIterator{opt: Some(x)},
            None => OptionIterator{opt: None}
        }
    }

    /// Return a mutable iterator over the possibly contained value
    #[inline]
    pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
        match *self {
            Some(ref mut x) => OptionMutIterator{opt: Some(x)},
            None => OptionMutIterator{opt: None}
        }
    }

    /// Returns true if the option equals `none`
    #[inline]
    pub fn is_none(&const self) -> bool {
        match *self { None => true, Some(_) => false }
    }

    /// Returns true if the option contains some value
    #[inline(always)]
    pub fn is_some(&const self) -> bool { !self.is_none() }

    /// Update an optional value by optionally running its content through a
    /// function that returns an option.
    #[inline(always)]
    pub fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> {
        match self {
            Some(t) => f(t),
            None => None
        }
    }

    /// Returns the leftmost Some() value, or None if both are None.
    #[inline(always)]
    pub fn or(self, optb: Option<T>) -> Option<T> {
        match self {
            Some(opta) => Some(opta),
            _ => optb
        }
    }

    /// Update an optional value by optionally running its content by reference
    /// through a function that returns an option.
    #[inline(always)]
    pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option<U>)
                            -> Option<U> {
        match *self {
            Some(ref x) => f(x),
            None => None
        }
    }

    /// Maps a `some` value from one type to another by reference
    #[inline(always)]
    pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option<U> {
        match *self { Some(ref x) => Some(f(x)), None => None }
    }

    /// As `map`, but consumes the option and gives `f` ownership to avoid
    /// copying.
    #[inline(always)]
    pub fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> {
        match self { None => None, Some(v) => Some(f(v)) }
    }

    /// Applies a function to the contained value or returns a default
    #[inline(always)]
    pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
        match *self { None => def, Some(ref t) => f(t) }
    }

    /// As `map_default`, but consumes the option and gives `f`
    /// ownership to avoid copying.
    #[inline(always)]
    pub fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U {
        match self { None => def, Some(v) => f(v) }
    }

    /// Apply a function to the contained value or do nothing
    pub fn mutate(&mut self, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        }
    }

    /// Apply a function to the contained value or set it to a default
    pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        } else {
            *self = Some(def);
        }
    }

    /**
    Gets an immutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline(always)]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        match *self {
          Some(ref x) => x,
          None => fail!("option::get_ref none")
        }
    }

    /**
    Gets a mutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline(always)]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        match *self {
          Some(ref mut x) => x,
          None => fail!("option::get_mut_ref none")
        }
    }

    #[inline(always)]
    pub fn unwrap(self) -> T {
        /*!
        Moves a value out of an option type and returns it.

        Useful primarily for getting strings, vectors and unique pointers out
        of option types without copying them.

        # Failure

        Fails if the value equals `None`.

        # Safety note

        In general, because this function may fail, its use is discouraged.
        Instead, prefer to use pattern matching and handle the `None`
        case explicitly.
         */
        match self {
          Some(x) => x,
          None => fail!("option::unwrap none")
        }
    }

    /**
     * The option dance. Moves a value out of an option type and returns it,
     * replacing the original with `None`.
     *
     * # Failure
     *
     * Fails if the value equals `None`.
     */
    #[inline(always)]
    pub fn swap_unwrap(&mut self) -> T {
        if self.is_none() { fail!("option::swap_unwrap none") }
        util::replace(self, None).unwrap()
    }

    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    #[inline(always)]
    pub fn expect(self, reason: &str) -> T {
        match self {
          Some(val) => val,
          None => fail!(reason.to_owned()),
        }
    }
}

impl<T:Copy> Option<T> {
    /**
    Gets the value out of an option

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
    */
    #[inline(always)]
    pub fn get(self) -> T {
        match self {
          Some(x) => return x,
          None => fail!("option::get none")
        }
    }

    /// Returns the contained value or a default
    #[inline(always)]
    pub fn get_or_default(self, def: T) -> T {
        match self { Some(x) => x, None => def }
    }

    /// Applies a function zero or more times until the result is none.
    #[inline(always)]
    pub fn while_some(self, blk: &fn(v: T) -> Option<T>) {
        let mut opt = self;
        while opt.is_some() {
            opt = blk(opt.unwrap());
        }
    }
}

impl<T:Copy + Zero> Option<T> {
    /// Returns the contained value or zero (for this type)
    #[inline(always)]
    pub fn get_or_zero(self) -> T {
        match self {
            Some(x) => x,
            None => Zero::zero()
        }
    }
}

/// Immutable iterator over an `Option<A>`
pub struct OptionIterator<'self, A> {
    priv opt: Option<&'self A>
}

impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
    fn next(&mut self) -> Option<&'self A> {
        util::replace(&mut self.opt, None)
    }
}

/// Mutable iterator over an `Option<A>`
pub struct OptionMutIterator<'self, A> {
    priv opt: Option<&'self mut A>
}

impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
    fn next(&mut self) -> Option<&'self mut A> {
        util::replace(&mut self.opt, None)
    }
}

#[test]
fn test_unwrap_ptr() {
    unsafe {
        let x = ~0;
        let addr_x: *int = ::cast::transmute(&*x);
        let opt = Some(x);
        let y = opt.unwrap();
        let addr_y: *int = ::cast::transmute(&*y);
        assert_eq!(addr_x, addr_y);
    }
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| buf);
    let opt = Some(x);
    let y = opt.unwrap();
    let addr_y = str::as_buf(y, |buf, _len| buf);
    assert_eq!(addr_x, addr_y);
}

#[test]
fn test_unwrap_resource() {
    struct R {
       i: @mut int,
    }

    #[unsafe_destructor]
    impl ::ops::Drop for R {
       fn finalize(&self) { *(self.i) += 1; }
    }

    fn R(i: @mut int) -> R {
        R {
            i: i
        }
    }

    let i = @mut 0;
    {
        let x = R(i);
        let opt = Some(x);
        let _y = opt.unwrap();
    }
    assert_eq!(*i, 1);
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    for x.iter().advance |_x| {
        y2 = y.swap_unwrap();
    }
    assert_eq!(y2, 5);
    assert!(y.is_none());
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable::new());
    let _y2 = y.swap_unwrap();
    let _y3 = y.swap_unwrap();
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert_eq!(i, 11);
}

#[test]
fn test_get_or_zero() {
    let some_stuff = Some(42);
    assert_eq!(some_stuff.get_or_zero(), 42);
    let no_stuff: Option<int> = None;
    assert_eq!(no_stuff.get_or_zero(), 0);
}
<commit_msg>Added filtered method for Option type<commit_after>// Copyright 2012-2013 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.

/*!

Operations on the ubiquitous `Option` type.

Type `Option` represents an optional value.

Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
languages you might use a nullable type, in Rust you would use an option
type.

Options are most commonly used with pattern matching to query the presence
of a value and take action, always accounting for the `None` case.

# Example

~~~
let msg = Some(~"howdy");

// Take a reference to the contained string
match msg {
    Some(ref m) => io::println(m),
    None => ()
}

// Remove the contained string, destroying the Option
let unwrapped_msg = match msg {
    Some(m) => m,
    None => ~"default message"
};
~~~

*/

use cmp::{Eq,Ord};
use ops::Add;
use kinds::Copy;
use util;
use num::Zero;
use iterator::Iterator;
use str::StrSlice;
use clone::DeepClone;

#[cfg(test)] use str;
#[cfg(test)] use iterator::IteratorUtil;

/// The option type
#[deriving(Clone, DeepClone, Eq)]
pub enum Option<T> {
    None,
    Some(T),
}

impl<T:Ord> Ord for Option<T> {
    fn lt(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => false,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a < *b
        }
    }

    fn le(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => true,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a <= *b
        }
    }

    fn ge(&self, other: &Option<T>) -> bool {
        !(self < other)
    }

    fn gt(&self, other: &Option<T>) -> bool {
        !(self <= other)
    }
}

impl<T: Copy + Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
    #[inline(always)]
    fn add(&self, other: &Option<T>) -> Option<T> {
        match (*self, *other) {
            (None, None) => None,
            (_, None) => *self,
            (None, _) => *other,
            (Some(ref lhs), Some(ref rhs)) => Some(*lhs + *rhs)
        }
    }
}

impl<T> Option<T> {
    /// Return an iterator over the possibly contained value
    #[inline]
    pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
        match *self {
            Some(ref x) => OptionIterator{opt: Some(x)},
            None => OptionIterator{opt: None}
        }
    }

    /// Return a mutable iterator over the possibly contained value
    #[inline]
    pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
        match *self {
            Some(ref mut x) => OptionMutIterator{opt: Some(x)},
            None => OptionMutIterator{opt: None}
        }
    }

    /// Returns true if the option equals `none`
    #[inline]
    pub fn is_none(&const self) -> bool {
        match *self { None => true, Some(_) => false }
    }

    /// Returns true if the option contains some value
    #[inline(always)]
    pub fn is_some(&const self) -> bool { !self.is_none() }

    /// Update an optional value by optionally running its content through a
    /// function that returns an option.
    #[inline(always)]
    pub fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> {
        match self {
            Some(t) => f(t),
            None => None
        }
    }

    /// Returns the leftmost Some() value, or None if both are None.
    #[inline(always)]
    pub fn or(self, optb: Option<T>) -> Option<T> {
        match self {
            Some(opta) => Some(opta),
            _ => optb
        }
    }

    /// Update an optional value by optionally running its content by reference
    /// through a function that returns an option.
    #[inline(always)]
    pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option<U>)
                            -> Option<U> {
        match *self {
            Some(ref x) => f(x),
            None => None
        }
    }

    /// Filters an optional value using given function.
    #[inline(always)]
    pub fn filtered<'a>(self, f: &fn(t: &'a T) -> bool) -> Option<T> {
        match self {
            Some(x) => if(f(&x)) {Some(x)} else {None},
            None => None
        }
    }

    /// Maps a `some` value from one type to another by reference
    #[inline(always)]
    pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option<U> {
        match *self { Some(ref x) => Some(f(x)), None => None }
    }

    /// As `map`, but consumes the option and gives `f` ownership to avoid
    /// copying.
    #[inline(always)]
    pub fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> {
        match self { None => None, Some(v) => Some(f(v)) }
    }

    /// Applies a function to the contained value or returns a default
    #[inline(always)]
    pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
        match *self { None => def, Some(ref t) => f(t) }
    }

    /// As `map_default`, but consumes the option and gives `f`
    /// ownership to avoid copying.
    #[inline(always)]
    pub fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U {
        match self { None => def, Some(v) => f(v) }
    }

    /// Apply a function to the contained value or do nothing
    pub fn mutate(&mut self, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        }
    }

    /// Apply a function to the contained value or set it to a default
    pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        } else {
            *self = Some(def);
        }
    }

    /**
    Gets an immutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline(always)]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        match *self {
          Some(ref x) => x,
          None => fail!("option::get_ref none")
        }
    }

    /**
    Gets a mutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline(always)]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        match *self {
          Some(ref mut x) => x,
          None => fail!("option::get_mut_ref none")
        }
    }

    #[inline(always)]
    pub fn unwrap(self) -> T {
        /*!
        Moves a value out of an option type and returns it.

        Useful primarily for getting strings, vectors and unique pointers out
        of option types without copying them.

        # Failure

        Fails if the value equals `None`.

        # Safety note

        In general, because this function may fail, its use is discouraged.
        Instead, prefer to use pattern matching and handle the `None`
        case explicitly.
         */
        match self {
          Some(x) => x,
          None => fail!("option::unwrap none")
        }
    }

    /**
     * The option dance. Moves a value out of an option type and returns it,
     * replacing the original with `None`.
     *
     * # Failure
     *
     * Fails if the value equals `None`.
     */
    #[inline(always)]
    pub fn swap_unwrap(&mut self) -> T {
        if self.is_none() { fail!("option::swap_unwrap none") }
        util::replace(self, None).unwrap()
    }

    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    #[inline(always)]
    pub fn expect(self, reason: &str) -> T {
        match self {
          Some(val) => val,
          None => fail!(reason.to_owned()),
        }
    }
}

impl<T:Copy> Option<T> {
    /**
    Gets the value out of an option

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
    */
    #[inline(always)]
    pub fn get(self) -> T {
        match self {
          Some(x) => return x,
          None => fail!("option::get none")
        }
    }

    /// Returns the contained value or a default
    #[inline(always)]
    pub fn get_or_default(self, def: T) -> T {
        match self { Some(x) => x, None => def }
    }

    /// Applies a function zero or more times until the result is none.
    #[inline(always)]
    pub fn while_some(self, blk: &fn(v: T) -> Option<T>) {
        let mut opt = self;
        while opt.is_some() {
            opt = blk(opt.unwrap());
        }
    }
}

impl<T:Copy + Zero> Option<T> {
    /// Returns the contained value or zero (for this type)
    #[inline(always)]
    pub fn get_or_zero(self) -> T {
        match self {
            Some(x) => x,
            None => Zero::zero()
        }
    }
}

/// Immutable iterator over an `Option<A>`
pub struct OptionIterator<'self, A> {
    priv opt: Option<&'self A>
}

impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
    fn next(&mut self) -> Option<&'self A> {
        util::replace(&mut self.opt, None)
    }
}

/// Mutable iterator over an `Option<A>`
pub struct OptionMutIterator<'self, A> {
    priv opt: Option<&'self mut A>
}

impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
    fn next(&mut self) -> Option<&'self mut A> {
        util::replace(&mut self.opt, None)
    }
}

#[test]
fn test_unwrap_ptr() {
    unsafe {
        let x = ~0;
        let addr_x: *int = ::cast::transmute(&*x);
        let opt = Some(x);
        let y = opt.unwrap();
        let addr_y: *int = ::cast::transmute(&*y);
        assert_eq!(addr_x, addr_y);
    }
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| buf);
    let opt = Some(x);
    let y = opt.unwrap();
    let addr_y = str::as_buf(y, |buf, _len| buf);
    assert_eq!(addr_x, addr_y);
}

#[test]
fn test_unwrap_resource() {
    struct R {
       i: @mut int,
    }

    #[unsafe_destructor]
    impl ::ops::Drop for R {
       fn finalize(&self) { *(self.i) += 1; }
    }

    fn R(i: @mut int) -> R {
        R {
            i: i
        }
    }

    let i = @mut 0;
    {
        let x = R(i);
        let opt = Some(x);
        let _y = opt.unwrap();
    }
    assert_eq!(*i, 1);
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    for x.iter().advance |_x| {
        y2 = y.swap_unwrap();
    }
    assert_eq!(y2, 5);
    assert!(y.is_none());
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable::new());
    let _y2 = y.swap_unwrap();
    let _y3 = y.swap_unwrap();
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert_eq!(i, 11);
}

#[test]
fn test_get_or_zero() {
    let some_stuff = Some(42);
    assert_eq!(some_stuff.get_or_zero(), 42);
    let no_stuff: Option<int> = None;
    assert_eq!(no_stuff.get_or_zero(), 0);
}

#[test]
fn test_filtered() {
    let some_stuff = Some(42);
    let modified_stuff = some_stuff.filtered(|&x| {x < 10});
    assert_eq!(some_stuff.get(), 42);
    assert!(modified_stuff.is_none());
}<|endoftext|>


<commit_before>use crate::frame::Ax25Frame;
use crate::kiss;
use crate::linux;
use snafu::{ensure, ResultExt, Snafu};
use std::str::FromStr;
use std::sync::Arc;

/// Errors that can occur when interacting with a `Tnc`.
#[derive(Debug, Snafu)]
pub enum TncError {
    #[snafu(display("Unable to connect to TNC: {}", source))]
    OpenTnc { source: std::io::Error },
    #[snafu(display("Interface with specified callsign '{}' does not exist", callsign))]
    InterfaceNotFound { callsign: String },
    #[snafu(display("Unable to send frame: {}", source))]
    SendFrame { source: std::io::Error },
    #[snafu(display("Unable to receive frame: {}", source))]
    ReceiveFrame { source: std::io::Error },
    #[snafu(display("Unable to make configuration change: {}", source))]
    ConfigFailed { source: std::io::Error },
}

/// Errors that can occur when parsing a `TncAddress` from a string.
#[derive(Debug, Snafu, PartialEq)]
pub enum ParseError {
    #[snafu(display("TNC address '{}' is invalid - it should begin with 'tnc:'", string))]
    NoTncPrefix { string: String },
    #[snafu(display("Unknown TNC type {}", tnc_type))]
    UnknownType { tnc_type: String },
    #[snafu(display(
        "TNC type '{}' expects {} parameters to follow but there are {}",
        tnc_type,
        expected,
        actual
    ))]
    WrongParameterCount {
        tnc_type: String,
        expected: usize,
        actual: usize,
    },
    #[snafu(display("Supplied port '{}' should be a number from 0 to 65535", input))]
    InvalidPort {
        input: String,
        source: std::num::ParseIntError,
    },
}

/// Configuration details for a TCP KISS TNC. This structure can be created directly
/// or indirectly by parsing a string into a `TncAddress`.
#[derive(PartialEq, Debug)]
pub struct TcpKissConfig {
    // Use a String to accept domain names. Even for IP addresses we will typically
    // receive this in a textual format from a parameter or config file.
    host: String,
    port: u16,
}

/// Configuration details for a TNC attached as a Linux network interface using
/// `kissattach`. This structure can be created directly or indirectly by parsing
/// a string into a `TncAddress`.
#[derive(PartialEq, Debug)]
pub struct LinuxIfConfig {
    callsign: String, // e.g. "VK7NTK-2"
}

#[derive(PartialEq, Debug)]
pub(crate) enum ConnectConfig {
    TcpKiss(TcpKissConfig),
    LinuxIf(LinuxIfConfig),
}

/// A parsed TNC address that can be used to open a `Tnc`.
#[derive(PartialEq, Debug)]
pub struct TncAddress {
    pub(crate) config: ConnectConfig,
}

impl TncAddress {
    /// Programmatically create a `TncAddress` pointing to a Linux network interface.
    pub fn new_linuxif(linuxif: LinuxIfConfig) -> Self {
        TncAddress {
            config: ConnectConfig::LinuxIf(linuxif),
        }
    }

    /// Porgrammatically create a `TncAddress` pointing to a KISS TCP service.
    pub fn new_tcpkiss(tcpkiss: TcpKissConfig) -> Self {
        TncAddress {
            config: ConnectConfig::TcpKiss(tcpkiss),
        }
    }
}

impl FromStr for TncAddress {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        ensure!(
            s.starts_with("tnc:"),
            NoTncPrefix {
                string: s.to_string()
            }
        );
        let components: Vec<&str> = s.split(':').collect();
        let len = components.len();
        Ok(match components[1] {
            "tcpkiss" => {
                ensure!(
                    len == 4,
                    WrongParameterCount {
                        tnc_type: components[1],
                        expected: 2usize,
                        actual: len - 2
                    }
                );
                TncAddress {
                    config: ConnectConfig::TcpKiss(TcpKissConfig {
                        host: components[2].to_string(),
                        port: components[3].parse().context(InvalidPort {
                            input: components[3].to_string(),
                        })?,
                    }),
                }
            }
            "linuxif" => {
                ensure!(
                    len == 3,
                    WrongParameterCount {
                        tnc_type: components[1],
                        expected: 1usize,
                        actual: len - 2
                    }
                );
                TncAddress {
                    config: ConnectConfig::LinuxIf(LinuxIfConfig {
                        callsign: components[2].to_string(),
                    }),
                }
            }
            unknown => UnknownType {
                tnc_type: unknown.to_string(),
            }
            .fail()?,
        })
    }
}

trait TncImpl: Send + Sync {
    fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError>;
    fn receive_frame(&self) -> Result<Ax25Frame, TncError>;
    fn clone(&self) -> Box<dyn TncImpl>;
}

/// A local or remote TNC attached to a radio, which can send and receive frames.
pub struct Tnc {
    imp: Box<dyn TncImpl>,
}

impl Tnc {
    /// Attempt to obtain a `Tnc` connection using the provided address.
    pub fn open(address: &TncAddress) -> Result<Self, TncError> {
        let imp: Box<dyn TncImpl> = match &address.config {
            ConnectConfig::TcpKiss(config) => Box::new(TcpKissTnc::open(&config)?),
            ConnectConfig::LinuxIf(config) => Box::new(LinuxIfTnc::open(&config)?),
        };
        Ok(Self { imp })
    }

    /// Transmit a frame on the radio. Transmission is not guaranteed even if a
    /// `Ok` result is returned.
    pub fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError> {
        self.imp.send_frame(frame)
    }

    /// Block to receive a frame from the radio. If you want to do this on
    /// a separate thread from sending, clone the `Tnc`.
    pub fn receive_frame(&self) -> Result<Ax25Frame, TncError> {
        self.imp.receive_frame()
    }
}

impl Clone for Tnc {
    fn clone(&self) -> Self {
        Tnc {
            imp: self.imp.clone()
        }
    }
}

struct LinuxIfTnc {
    socket: Arc<linux::Ax25RawSocket>,
    ifindex: i32,
}

impl LinuxIfTnc {
    fn open(config: &LinuxIfConfig) -> Result<Self, TncError> {
        let socket = linux::Ax25RawSocket::new().context(OpenTnc)?;
        let ifindex = match socket
            .list_ax25_interfaces()
            .context(OpenTnc)?
            .iter()
            .find(|nd| nd.name.to_uppercase() == config.callsign.to_uppercase())
        {
            Some(nd) => nd.ifindex,
            None => InterfaceNotFound {
                callsign: config.callsign.clone(),
            }
            .fail()?,
        };
        Ok(Self {
            socket: Arc::new(socket),
            ifindex,
        })
    }
}

impl TncImpl for LinuxIfTnc {
    fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError> {
        self.socket
            .send_frame(&frame.to_bytes(), self.ifindex)
            .context(SendFrame)
    }

    fn receive_frame(&self) -> Result<Ax25Frame, TncError> {
        loop {
            let bytes = self.socket.receive_frame().context(ReceiveFrame)?;
            if let Ok(parsed) = Ax25Frame::from_bytes(&bytes) {
                return Ok(parsed);
            }
        }
    }

    fn clone(&self) -> Box<dyn TncImpl> {
        Box::new(LinuxIfTnc {
            socket: self.socket.clone(),
            ifindex: self.ifindex
        })
    }
}

struct TcpKissTnc {
    iface: Arc<kiss::TcpKissInterface>,
}

impl TcpKissTnc {
    fn open(config: &TcpKissConfig) -> Result<Self, TncError> {
        Ok(Self {
            iface: Arc::new(
                kiss::TcpKissInterface::new(format!("{}:{}", config.host, config.port))
                    .context(OpenTnc)?,
            ),
        })
    }
}

impl TncImpl for TcpKissTnc {
    fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError> {
        self.iface.send_frame(&frame.to_bytes()).context(SendFrame)
    }

    fn receive_frame(&self) -> Result<Ax25Frame, TncError> {
        loop {
            let bytes = self.iface.receive_frame().context(ReceiveFrame)?;
            if let Ok(parsed) = Ax25Frame::from_bytes(&bytes) {
                return Ok(parsed);
            }
        }
    }

    fn clone(&self) -> Box<dyn TncImpl> {
        Box::new(TcpKissTnc {
            iface: self.iface.clone()
        })
    }
}

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

    #[test]
    fn parse_tnc_addresses() {
        assert_eq!(
            "tnc:tcpkiss:192.168.0.1:8001".parse::<TncAddress>(),
            Ok(TncAddress {
                config: ConnectConfig::TcpKiss(TcpKissConfig {
                    host: "192.168.0.1".to_string(),
                    port: 8001_u16,
                })
            })
        );
        assert_eq!(
            "tnc:linuxif:VK7NTK-2".parse::<TncAddress>(),
            Ok(TncAddress {
                config: ConnectConfig::LinuxIf(LinuxIfConfig {
                    callsign: "VK7NTK-2".to_string(),
                })
            })
        );
        assert!(match "fish".parse::<TncAddress>() {
            Err(ParseError::NoTncPrefix { .. }) => true,
            _ => false,
        });
        assert!(match "tnc:".parse::<TncAddress>() {
            Err(ParseError::UnknownType { tnc_type }) => tnc_type == "",
            _ => false,
        });
        assert!(match "tnc:fish".parse::<TncAddress>() {
            Err(ParseError::UnknownType { tnc_type }) => tnc_type == "fish",
            _ => false,
        });
        assert!(match "tnc:tcpkiss".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 0
            }
            _ => false,
        });
        assert!(match "tnc:tcpkiss:".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 1
            }
            _ => false,
        });
        assert!(match "tnc:tcpkiss:a:b:c".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 3
            }
            _ => false,
        });
        assert!(match "tnc:tcpkiss:192.168.0.1".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 1
            }
            _ => false,
        });
        assert!(
            match "tnc:tcpkiss:192.168.0.1:hello".parse::<TncAddress>() {
                Err(ParseError::InvalidPort { input, .. }) => input == "hello",
                _ => false,
            }
        );
    }
}
<commit_msg>Make TNC config fields public so they can be used<commit_after>use crate::frame::Ax25Frame;
use crate::kiss;
use crate::linux;
use snafu::{ensure, ResultExt, Snafu};
use std::str::FromStr;
use std::sync::Arc;

/// Errors that can occur when interacting with a `Tnc`.
#[derive(Debug, Snafu)]
pub enum TncError {
    #[snafu(display("Unable to connect to TNC: {}", source))]
    OpenTnc { source: std::io::Error },
    #[snafu(display("Interface with specified callsign '{}' does not exist", callsign))]
    InterfaceNotFound { callsign: String },
    #[snafu(display("Unable to send frame: {}", source))]
    SendFrame { source: std::io::Error },
    #[snafu(display("Unable to receive frame: {}", source))]
    ReceiveFrame { source: std::io::Error },
    #[snafu(display("Unable to make configuration change: {}", source))]
    ConfigFailed { source: std::io::Error },
}

/// Errors that can occur when parsing a `TncAddress` from a string.
#[derive(Debug, Snafu, PartialEq)]
pub enum ParseError {
    #[snafu(display("TNC address '{}' is invalid - it should begin with 'tnc:'", string))]
    NoTncPrefix { string: String },
    #[snafu(display("Unknown TNC type {}", tnc_type))]
    UnknownType { tnc_type: String },
    #[snafu(display(
        "TNC type '{}' expects {} parameters to follow but there are {}",
        tnc_type,
        expected,
        actual
    ))]
    WrongParameterCount {
        tnc_type: String,
        expected: usize,
        actual: usize,
    },
    #[snafu(display("Supplied port '{}' should be a number from 0 to 65535", input))]
    InvalidPort {
        input: String,
        source: std::num::ParseIntError,
    },
}

/// Configuration details for a TCP KISS TNC. This structure can be created directly
/// or indirectly by parsing a string into a `TncAddress`.
#[derive(PartialEq, Debug)]
pub struct TcpKissConfig {
    /// Hostname or IP address of the computer with the TNC
    pub host: String,
    /// Port number
    pub port: u16,
}

/// Configuration details for a TNC attached as a Linux network interface using
/// `kissattach`. This structure can be created directly or indirectly by parsing
/// a string into a `TncAddress`.
#[derive(PartialEq, Debug)]
pub struct LinuxIfConfig {
    /// The hardware address associated with the interface, e.g. "VK7NTK-2"
    pub callsign: String,
}

#[derive(PartialEq, Debug)]
pub(crate) enum ConnectConfig {
    TcpKiss(TcpKissConfig),
    LinuxIf(LinuxIfConfig),
}

/// A parsed TNC address that can be used to open a `Tnc`.
#[derive(PartialEq, Debug)]
pub struct TncAddress {
    pub(crate) config: ConnectConfig,
}

impl TncAddress {
    /// Programmatically create a `TncAddress` pointing to a Linux network interface.
    pub fn new_linuxif(linuxif: LinuxIfConfig) -> Self {
        TncAddress {
            config: ConnectConfig::LinuxIf(linuxif),
        }
    }

    /// Porgrammatically create a `TncAddress` pointing to a KISS TCP service.
    pub fn new_tcpkiss(tcpkiss: TcpKissConfig) -> Self {
        TncAddress {
            config: ConnectConfig::TcpKiss(tcpkiss),
        }
    }
}

impl FromStr for TncAddress {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        ensure!(
            s.starts_with("tnc:"),
            NoTncPrefix {
                string: s.to_string()
            }
        );
        let components: Vec<&str> = s.split(':').collect();
        let len = components.len();
        Ok(match components[1] {
            "tcpkiss" => {
                ensure!(
                    len == 4,
                    WrongParameterCount {
                        tnc_type: components[1],
                        expected: 2usize,
                        actual: len - 2
                    }
                );
                TncAddress {
                    config: ConnectConfig::TcpKiss(TcpKissConfig {
                        host: components[2].to_string(),
                        port: components[3].parse().context(InvalidPort {
                            input: components[3].to_string(),
                        })?,
                    }),
                }
            }
            "linuxif" => {
                ensure!(
                    len == 3,
                    WrongParameterCount {
                        tnc_type: components[1],
                        expected: 1usize,
                        actual: len - 2
                    }
                );
                TncAddress {
                    config: ConnectConfig::LinuxIf(LinuxIfConfig {
                        callsign: components[2].to_string(),
                    }),
                }
            }
            unknown => UnknownType {
                tnc_type: unknown.to_string(),
            }
            .fail()?,
        })
    }
}

trait TncImpl: Send + Sync {
    fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError>;
    fn receive_frame(&self) -> Result<Ax25Frame, TncError>;
    fn clone(&self) -> Box<dyn TncImpl>;
}

/// A local or remote TNC attached to a radio, which can send and receive frames.
pub struct Tnc {
    imp: Box<dyn TncImpl>,
}

impl Tnc {
    /// Attempt to obtain a `Tnc` connection using the provided address.
    pub fn open(address: &TncAddress) -> Result<Self, TncError> {
        let imp: Box<dyn TncImpl> = match &address.config {
            ConnectConfig::TcpKiss(config) => Box::new(TcpKissTnc::open(&config)?),
            ConnectConfig::LinuxIf(config) => Box::new(LinuxIfTnc::open(&config)?),
        };
        Ok(Self { imp })
    }

    /// Transmit a frame on the radio. Transmission is not guaranteed even if a
    /// `Ok` result is returned.
    pub fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError> {
        self.imp.send_frame(frame)
    }

    /// Block to receive a frame from the radio. If you want to do this on
    /// a separate thread from sending, clone the `Tnc`.
    pub fn receive_frame(&self) -> Result<Ax25Frame, TncError> {
        self.imp.receive_frame()
    }
}

impl Clone for Tnc {
    fn clone(&self) -> Self {
        Tnc {
            imp: self.imp.clone()
        }
    }
}

struct LinuxIfTnc {
    socket: Arc<linux::Ax25RawSocket>,
    ifindex: i32,
}

impl LinuxIfTnc {
    fn open(config: &LinuxIfConfig) -> Result<Self, TncError> {
        let socket = linux::Ax25RawSocket::new().context(OpenTnc)?;
        let ifindex = match socket
            .list_ax25_interfaces()
            .context(OpenTnc)?
            .iter()
            .find(|nd| nd.name.to_uppercase() == config.callsign.to_uppercase())
        {
            Some(nd) => nd.ifindex,
            None => InterfaceNotFound {
                callsign: config.callsign.clone(),
            }
            .fail()?,
        };
        Ok(Self {
            socket: Arc::new(socket),
            ifindex,
        })
    }
}

impl TncImpl for LinuxIfTnc {
    fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError> {
        self.socket
            .send_frame(&frame.to_bytes(), self.ifindex)
            .context(SendFrame)
    }

    fn receive_frame(&self) -> Result<Ax25Frame, TncError> {
        loop {
            let bytes = self.socket.receive_frame().context(ReceiveFrame)?;
            if let Ok(parsed) = Ax25Frame::from_bytes(&bytes) {
                return Ok(parsed);
            }
        }
    }

    fn clone(&self) -> Box<dyn TncImpl> {
        Box::new(LinuxIfTnc {
            socket: self.socket.clone(),
            ifindex: self.ifindex
        })
    }
}

struct TcpKissTnc {
    iface: Arc<kiss::TcpKissInterface>,
}

impl TcpKissTnc {
    fn open(config: &TcpKissConfig) -> Result<Self, TncError> {
        Ok(Self {
            iface: Arc::new(
                kiss::TcpKissInterface::new(format!("{}:{}", config.host, config.port))
                    .context(OpenTnc)?,
            ),
        })
    }
}

impl TncImpl for TcpKissTnc {
    fn send_frame(&self, frame: &Ax25Frame) -> Result<(), TncError> {
        self.iface.send_frame(&frame.to_bytes()).context(SendFrame)
    }

    fn receive_frame(&self) -> Result<Ax25Frame, TncError> {
        loop {
            let bytes = self.iface.receive_frame().context(ReceiveFrame)?;
            if let Ok(parsed) = Ax25Frame::from_bytes(&bytes) {
                return Ok(parsed);
            }
        }
    }

    fn clone(&self) -> Box<dyn TncImpl> {
        Box::new(TcpKissTnc {
            iface: self.iface.clone()
        })
    }
}

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

    #[test]
    fn parse_tnc_addresses() {
        assert_eq!(
            "tnc:tcpkiss:192.168.0.1:8001".parse::<TncAddress>(),
            Ok(TncAddress {
                config: ConnectConfig::TcpKiss(TcpKissConfig {
                    host: "192.168.0.1".to_string(),
                    port: 8001_u16,
                })
            })
        );
        assert_eq!(
            "tnc:linuxif:VK7NTK-2".parse::<TncAddress>(),
            Ok(TncAddress {
                config: ConnectConfig::LinuxIf(LinuxIfConfig {
                    callsign: "VK7NTK-2".to_string(),
                })
            })
        );
        assert!(match "fish".parse::<TncAddress>() {
            Err(ParseError::NoTncPrefix { .. }) => true,
            _ => false,
        });
        assert!(match "tnc:".parse::<TncAddress>() {
            Err(ParseError::UnknownType { tnc_type }) => tnc_type == "",
            _ => false,
        });
        assert!(match "tnc:fish".parse::<TncAddress>() {
            Err(ParseError::UnknownType { tnc_type }) => tnc_type == "fish",
            _ => false,
        });
        assert!(match "tnc:tcpkiss".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 0
            }
            _ => false,
        });
        assert!(match "tnc:tcpkiss:".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 1
            }
            _ => false,
        });
        assert!(match "tnc:tcpkiss:a:b:c".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 3
            }
            _ => false,
        });
        assert!(match "tnc:tcpkiss:192.168.0.1".parse::<TncAddress>() {
            Err(ParseError::WrongParameterCount {
                tnc_type,
                expected,
                actual,
            }) => {
                tnc_type == "tcpkiss" && expected == 2 && actual == 1
            }
            _ => false,
        });
        assert!(
            match "tnc:tcpkiss:192.168.0.1:hello".parse::<TncAddress>() {
                Err(ParseError::InvalidPort { input, .. }) => input == "hello",
                _ => false,
            }
        );
    }
}
<|endoftext|>


<commit_before>use core::cmp::Eq;

use std::cmp::FuzzyEq;

use numeric::types::angle::Radians;
use numeric::types::number::Number;

pub mod vec2;
pub mod vec3;
pub mod vec4;

pub use self::vec2::Vec2;
pub use self::vec3::Vec3;
pub use self::vec4::Vec4;

/**
 * The base generic vector trait.
 *
 * # Type parameters
 *
 * * `T` - The type of the components. This is intended to support boolean,
 *         integer, unsigned integer, and floating point types.
 */
pub trait Vector<T>: Index<uint, T> Eq {
    /**
     * Construct the vector from a single value, copying it to each component
     */
    static pure fn from_value(value: T) -> self;

    /**
     * # Return value
     *
     * A pointer to the first component of the vector
     */
    pure fn to_ptr(&self) -> *T;
}

pub trait MutableVector<T>: Vector<T> {
    /**
     * Get a mutable reference to the component at `i`
     */
    fn index_mut(&mut self, i: uint) -> &self/mut T;

    /**
     * Swap two components of the vector in place
     */
    fn swap(&mut self, a: uint, b: uint);
}

/**
 * A generic 2-dimensional vector
 */
pub trait Vector2<T>: Vector<T> {
    // static pure fn new(x: T, y: T) -> self;
}

/**
 * A generic 3-dimensional vector
 */
pub trait Vector3<T>: Vector<T> {
    // static pure fn new(x: T, y: T, z: T) -> self;
}

/**
 * A generic 4-dimensional vector
 */
pub trait Vector4<T>: Vector<T> {
    // static pure fn new(x: T, y: T, z: T, w: T) -> self;
}

/**
 * A vector with numeric components
 */
pub trait NumericVector<T>: Vector<T> Neg<self> {
    /**
     * The standard basis vector
     *
     * # Return value
     *
     * A vector with each component set to one
     */
    static pure fn identity() -> self;

    /**
     * The null vector
     *
     * # Return value
     *
     * A vector with each component set to zero
     */
    static pure fn zero() -> self;

    /**
     * # Return value
     *
     * The scalar multiplication of the vector and `value`
     */
    pure fn mul_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The scalar division of the vector and `value`
     */
    pure fn div_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The sum of the vector and `other`
     */
    pure fn add_v(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The difference between the vector and `other`
     */
    pure fn sub_v(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The dot product of the vector and `other`
     */
    pure fn dot(&self, other: &self) -> T;
}

/**
 * A mutable vector with numeric components
 */
pub trait MutableNumericVector<T>: MutableVector<&self/T>
                                   NumericVector<T> {
    /**
     * Negate the vector
     */
    fn neg_self(&mut self);

    /**
     * Multiply the vector by a scalar
     */
    fn mul_self_t(&mut self, value: T);

    /**
     * Divide the vector by a scalar
     */
    fn div_self_t(&mut self, value: T);

    /**
     * Set to the sum of the vector and `other`
     */
    fn add_self_v(&mut self, other: &self);

    /**
     * Set to the difference between the vector and `other`
     */
    fn sub_self_v(&mut self, other: &self);
}

/**
 * A 2-dimensional vector with numeric components
 */
pub trait NumericVector2<T>: NumericVector<T> {
    // static pure fn unit_x() -> self;
    // static pure fn unit_y() -> self;

    /**
     * # Return value
     *
     * The perp dot product of the vector and `other`
     */
    pure fn perp_dot(&self, other: &self) -> T;
}

/**
 * A 3-dimensional vector with numeric components
 */
pub trait NumericVector3<T>: NumericVector<T> {
    // static pure fn unit_x() -> self;
    // static pure fn unit_y() -> self;
    // static pure fn unit_z() -> self;

    /**
     * # Return value
     *
     * The cross product of the vector and `other`
     */
    pure fn cross(&self, other: &self) -> self;
}

/**
 * A mutable 3-dimensional vector with numeric components
 */
pub trait MutableNumericVector3<T>: MutableNumericVector<&self/T> {
    /**
     * Set to the cross product of the vector and `other`
     */
    fn cross_self(&mut self, other: &self);
}

/**
 * A 4-dimensional vector with numeric components
 */
pub trait NumericVector4<T>: NumericVector<T> {
    // static pure fn unit_x() -> self;
    // static pure fn unit_y() -> self;
    // static pure fn unit_z() -> self;
    // static pure fn unit_w() -> self;
}

/**
 * A Euclidean (or Affine) vector
 *
 * # Type parameters
 *
 * * `T` - The type of the components. This should be a floating point type.
 */
pub trait EuclideanVector<T>: NumericVector<T> {
    /**
     * # Return value
     *
     * The squared length of the vector. This is useful for comparisons where
     * the exact length does not need to be calculated.
     */
    pure fn length2(&self) -> T;

    /**
     * # Return value
     *
     * The length of the vector
     *
     * # Performance notes
     *
     * For instances where the exact length of the vector does not need to be
     * known, for example for quaternion-quaternion length comparisons,
     * it is advisable to use the `length2` method instead.
     */
    pure fn length(&self) -> T;

    /**
     * # Return value
     *
     * The squared distance between the vector and `other`.
     */
    pure fn distance2(&self, other: &self) -> T;

    /**
     * # Return value
     *
     * The distance between the vector and `other`
     */
    pure fn distance(&self, other: &self) -> T;

    /**
     * # Return value
     *
     * The angle between the vector and `other`
     */
    pure fn angle(&self, other: &self) -> Radians<T>;

    /**
     * # Return value
     *
     * The normalized vector
     */
    pure fn normalize(&self) -> self;

    /**
     * Set the length of the vector whilst preserving the direction
     */
    pure fn normalize_to(&self, length: T) -> self;

    /**
     * Linearly intoperlate between the vector and `other`
     *
     * # Return value
     *
     * The intoperlated vector
     */
    pure fn lerp(&self, other: &self, amount: T) -> self;
}

/**
 * A mutable Euclidean (or Affine) vector
 *
 * # Type parameters
 *
 * * `T` - The type of the components. This should be a floating point type.
 */
pub trait MutableEuclideanVector<T>: MutableNumericVector<&self/T>
                                     EuclideanVector<T> {
    /**
     * Normalize the vector
     */
    fn normalize_self(&mut self);

    /**
     * Set the vector to a specified length whilst preserving the direction
     */
    fn normalize_self_to(&mut self, length: T);

    /**
     * Linearly intoperlate the vector towards `other`
     */
    fn lerp_self(&mut self, other: &self, amount: T);
}

/**
 * Component-wise vector comparison methods
 */
pub trait OrdinalVector<T, BoolVec>: Vector<T> {
    /**
     * Component-wise compare of `self < other`
     */
    pure fn less_than(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self <= other`
     */
    pure fn less_than_equal(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self > other`
     */
    pure fn greater_than(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self >= other`
     */
    pure fn greater_than_equal(&self, other: &self) -> BoolVec;
}

/**
 * Component-wise equality comparison methods
 */
pub trait EquableVector<T, BoolVec>: Vector<T> {
    /**
     * Component-wise compare of `self == other`
     */
    pure fn equal(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self != other`
     */
    pure fn not_equal(&self, other: &self) -> BoolVec;
}

/**
 * A vector with boolean components
 */
pub trait BooleanVector: Vector<bool> {
    /**
     * # Return value
     *
     * `true` if of any component is `true`
     */
    pure fn any(&self) -> bool;

    /**
     * # Return value
     *
     * `true` only if all components are `true`
     */
    pure fn all(&self) -> bool;

    /**
     * # Return value
     *
     * the component-wise logical complement
     */
    pure fn not(&self) -> self;
}<commit_msg>Comments<commit_after>use core::cmp::Eq;

use std::cmp::FuzzyEq;

use numeric::types::angle::Radians;
use numeric::types::number::Number;

pub mod vec2;
pub mod vec3;
pub mod vec4;

pub use self::vec2::Vec2;
pub use self::vec3::Vec3;
pub use self::vec4::Vec4;

/**
 * The base generic vector trait.
 *
 * # Type parameters
 *
 * * `T` - The type of the components. This is intended to support boolean,
 *         integer, unsigned integer, and floating point types.
 */
pub trait Vector<T>: Index<uint, T> Eq {
    /**
     * Construct the vector from a single value, copying it to each component
     */
    static pure fn from_value(value: T) -> self;

    /**
     * # Return value
     *
     * A pointer to the first component of the vector
     */
    pure fn to_ptr(&self) -> *T;
}

pub trait MutableVector<T>: Vector<T> {
    /**
     * Get a mutable reference to the component at `i`
     */
    fn index_mut(&mut self, i: uint) -> &self/mut T;

    /**
     * Swap two components of the vector in place
     */
    fn swap(&mut self, a: uint, b: uint);
}

/**
 * A generic 2-dimensional vector
 */
pub trait Vector2<T>: Vector<T> {
    // static pure fn new(x: T, y: T) -> self;
}

/**
 * A generic 3-dimensional vector
 */
pub trait Vector3<T>: Vector<T> {
    // static pure fn new(x: T, y: T, z: T) -> self;
}

/**
 * A generic 4-dimensional vector
 */
pub trait Vector4<T>: Vector<T> {
    // static pure fn new(x: T, y: T, z: T, w: T) -> self;
}

/**
 * A vector with numeric components
 */
pub trait NumericVector<T>: Vector<T> Neg<self> {
    /**
     * The standard basis vector
     *
     * # Return value
     *
     * A vector with each component set to one
     */
    static pure fn identity() -> self;

    /**
     * The null vector
     *
     * # Return value
     *
     * A vector with each component set to zero
     */
    static pure fn zero() -> self;

    /**
     * # Return value
     *
     * The scalar multiplication of the vector and `value`
     */
    pure fn mul_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The scalar division of the vector and `value`
     */
    pure fn div_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The sum of the vector and `other`
     */
    pure fn add_v(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The difference between the vector and `other`
     */
    pure fn sub_v(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The dot product of the vector and `other`
     */
    pure fn dot(&self, other: &self) -> T;
}

/**
 * A mutable vector with numeric components
 */
pub trait MutableNumericVector<T>: MutableVector<&self/T>
                                   NumericVector<T> {
    /**
     * Negate the vector
     */
    fn neg_self(&mut self);

    /**
     * Multiply the vector by a scalar
     */
    fn mul_self_t(&mut self, value: T);

    /**
     * Divide the vector by a scalar
     */
    fn div_self_t(&mut self, value: T);

    /**
     * Set to the sum of the vector and `other`
     */
    fn add_self_v(&mut self, other: &self);

    /**
     * Set to the difference between the vector and `other`
     */
    fn sub_self_v(&mut self, other: &self);
}

/**
 * A 2-dimensional vector with numeric components
 */
pub trait NumericVector2<T>: NumericVector<T> {
    // static pure fn unit_x() -> self;
    // static pure fn unit_y() -> self;

    /**
     * # Return value
     *
     * The perp dot product of the vector and `other`
     */
    pure fn perp_dot(&self, other: &self) -> T;
}

/**
 * A 3-dimensional vector with numeric components
 */
pub trait NumericVector3<T>: NumericVector<T> {
    // static pure fn unit_x() -> self;
    // static pure fn unit_y() -> self;
    // static pure fn unit_z() -> self;

    /**
     * # Return value
     *
     * The cross product of the vector and `other`
     */
    pure fn cross(&self, other: &self) -> self;
}

/**
 * A mutable 3-dimensional vector with numeric components
 */
pub trait MutableNumericVector3<T>: MutableNumericVector<&self/T> {
    /**
     * Set to the cross product of the vector and `other`
     */
    fn cross_self(&mut self, other: &self);
}

/**
 * A 4-dimensional vector with numeric components
 */
pub trait NumericVector4<T>: NumericVector<T> {
    // static pure fn unit_x() -> self;
    // static pure fn unit_y() -> self;
    // static pure fn unit_z() -> self;
    // static pure fn unit_w() -> self;
}

/**
 * A Euclidean (or Affine) vector
 *
 * # Type parameters
 *
 * * `T` - The type of the components. This should be a floating point type.
 */
pub trait EuclideanVector<T>: NumericVector<T> {
    /**
     * # Return value
     *
     * The squared length of the vector. This is useful for comparisons where
     * the exact length does not need to be calculated.
     */
    pure fn length2(&self) -> T;

    /**
     * # Return value
     *
     * The length of the vector
     *
     * # Performance notes
     *
     * For instances where the exact length of the vector does not need to be
     * known, for example for quaternion-quaternion length comparisons,
     * it is advisable to use the `length2` method instead.
     */
    pure fn length(&self) -> T;

    /**
     * # Return value
     *
     * The squared distance between the vector and `other`.
     */
    pure fn distance2(&self, other: &self) -> T;

    /**
     * # Return value
     *
     * The distance between the vector and `other`
     */
    pure fn distance(&self, other: &self) -> T;

    /**
     * # Return value
     *
     * The angle between the vector and `other`
     */
    pure fn angle(&self, other: &self) -> Radians<T>;

    /**
     * # Return value
     *
     * The normalized vector
     */
    pure fn normalize(&self) -> self;

    /**
     * Set the length of the vector whilst preserving the direction
     */
    pure fn normalize_to(&self, length: T) -> self;

    /**
     * Linearly intoperlate between the vector and `other`
     *
     * # Return value
     *
     * The intoperlated vector
     */
    pure fn lerp(&self, other: &self, amount: T) -> self;
}

/**
 * A mutable Euclidean (or Affine) vector
 *
 * # Type parameters
 *
 * * `T` - The type of the components. This should be a floating point type.
 */
pub trait MutableEuclideanVector<T>: MutableNumericVector<&self/T>
                                     EuclideanVector<T> {
    /**
     * Normalize the vector
     */
    fn normalize_self(&mut self);

    /**
     * Set the vector to a specified length whilst preserving the direction
     */
    fn normalize_self_to(&mut self, length: T);

    /**
     * Linearly intoperlate the vector towards `other`
     */
    fn lerp_self(&mut self, other: &self, amount: T);
}

/**
 * Component-wise vector comparison methods
 *
 * The methods contained in this trait correspond to the relational functions
 * mentioned in Section 8.7 of the [GLSL 4.30.6 specification]
 * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
 */
pub trait OrdinalVector<T, BoolVec>: Vector<T> {
    /**
     * Component-wise compare of `self < other`
     */
    pure fn less_than(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self <= other`
     */
    pure fn less_than_equal(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self > other`
     */
    pure fn greater_than(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self >= other`
     */
    pure fn greater_than_equal(&self, other: &self) -> BoolVec;
}

/**
 * Component-wise equality comparison methods
 *
 * The methods contained in this trait correspond to the relational functions
 * mentioned in Section 8.7 of the [GLSL 4.30.6 specification]
 * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
 */
pub trait EquableVector<T, BoolVec>: Vector<T> {
    /**
     * Component-wise compare of `self == other`
     */
    pure fn equal(&self, other: &self) -> BoolVec;

    /**
     * Component-wise compare of `self != other`
     */
    pure fn not_equal(&self, other: &self) -> BoolVec;
}

/**
 * A vector with boolean components
 *
 * The methods contained in this trait correspond to the relational functions
 * mentioned in Section 8.7 of the [GLSL 4.30.6 specification]
 * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
 */
pub trait BooleanVector: Vector<bool> {
    /**
     * # Return value
     *
     * `true` if of any component is `true`
     */
    pure fn any(&self) -> bool;

    /**
     * # Return value
     *
     * `true` only if all components are `true`
     */
    pure fn all(&self) -> bool;

    /**
     * # Return value
     *
     * the component-wise logical complement
     */
    pure fn not(&self) -> self;
}<|endoftext|>