<commit_before>use std::collections::HashMap;
use std::path::Path;

#[derive(Debug, Default)]
pub struct LanguageSpec {
    pub reserved_words: HashMap<String, String>,
    pub hash_comment: bool,
    pub c_style_comments: bool,
    pub backtick_strings: bool,
    pub regexp_literals: bool,
    pub triple_quote_literals: bool,
    pub c_preprocessor: bool,
    // Rust is mostly C-like, with a couple of differences.
    pub rust_tweaks: bool,
    pub cxx14_digit_separators: bool,
}

fn make_reserved(v: &[&str]) -> HashMap<String, String> {
    let mut reserved_words = HashMap::new();
    for word in v {
        reserved_words.insert(word.to_string(), "class=\"syn_reserved\" ".to_string());
    }
    reserved_words
}

lazy_static! {
    static ref RESERVED_WORDS_JS : Vec<&'static str> = vec![
        "abstract", "else", "instanceof", "super",
        "boolean", "enum", "int", "switch",
        "break", "export", "interface", "synchronized",
        "byte", "extends", "let", "this",
        "case", "false", "long", "throw",
        "catch", "final", "native", "throws",
        "char", "finally", "new", "transient",
        "class", "float", "null", "true",
        "const", "for", "package", "try",
        "continue", "function", "private", "typeof",
        "debugger", "goto", "protected", "var",
        "default", "if", "public", "void",
        "delete", "implements", "return", "volatile",
        "do", "import", "short", "while",
        "double", "in", "static", "with",
        "get", "set",
    ];

    static ref RESERVED_WORDS_CPP : Vec<&'static str> = vec![
        "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel",
        "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break",
        "case", "catch", "char", "char16_t", "char32_t", "class", "compl", "concept",
        "const", "constexpr", "const_cast", "continue", "decltype", "default", "delete",
        "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
        "float", "for", "friend", "goto", "if", "inline", "int", "import", "long", "module",
        "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
        // Don't mark "operator" as a keyword so that people can click
        // on it.
        //"operator",
        "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
        "requires", "return", "short", "signed", "sizeof", "static", "static_assert",
        "static_cast", "struct", "switch", "synchronized", "template", "this", "thread_local",
        "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
        "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq",
        "#if", "#ifdef", "#ifndef", "#else", "#elif", "#endif", "#define", "#undef",
        "#include", "#error", "defined",
    ];

    static ref RESERVED_WORDS_IPDL : Vec<&'static str> = vec![
        "answer", "as", "async", "both", "bridges", "call", "child", "class",
        "compress", "compressall", "__delete__", "delete", "from", "goto", "high",
        "include", "intr", "manager", "manages", "namespace", "normal", "nullable",
        "opens", "or", "parent", "prio", "protocol", "recv", "returns", "send",
        "spawns", "start", "state", "struct", "sync", "union", "upto", "urgent",
        "using",
    ];

    static ref RESERVED_WORDS_IDL : Vec<&'static str> = vec![
        "const", "interface", "in", "inout", "out", "attribute", "raises",
        "readonly", "native", "typedef",
        "array", "shared", "iid_is", "size_is", "retval",
        "boolean", "void", "octet", "short", "long", "long",
        "unsigned", "float", "double", "char", "string", "wchar", "wstring",
        "nsid", "domstring", "utf8string", "cstring", "astring", "jsval",
        "uuid", "scriptable", "builtinclass", "function", "noscript", "deprecated",
        "object", "main_process_scriptable_only",
    ];

    static ref RESERVED_WORDS_WEBIDL : Vec<&'static str> = vec![
        "module", "interface", "partial", "dictionary", "exception", "enum", "callback",
        "typedef", "implements", "const", "null", "true", "false", "serializer",
        "stringifier", "jsonifier", "unrestricted", "attribute", "readonly", "inherit",
        "static", "getter", "setter", "creator", "deleter", "legacycaller", "optional",
        "Date", "DOMString", "ByteString", "USVString", "any", "boolean", "byte",
        "double", "float", "long", "object", "octet", "Promise", "required", "sequence",
        "MozMap", "short", "unsigned", "void", "ArrayBuffer", "SharedArrayBuffer", "or",
        "maplike", "setlike", "iterable",
        "Exposed", "ChromeOnly", "ChromeConstructor", "Pref", "Func", "AvailableIn",
        "CheckAnyPermissions", "CheckAllPermissions", "JSImplementation", "HeaderFile",
        "NavigatorProperty", "AvailableIn", "Func", "CheckAnyPermissions", "CheckAllPermissions",
        "Deprecated", "NeedResolve", "OverrideBuiltins", "ChromeOnly", "Unforgeable",
        "UnsafeInPrerendering", "LegacyEventInit", "ProbablyShortLivingObject", "ArrayClass",
        "Clamp", "Constructor", "EnforceRange", "ExceptionClass", "Exposed", "ImplicitThis",
        "Global", "PrimaryGlobal", "LegacyArrayClass", "LegacyUnenumerableNamedProperties",
        "LenientSetter", "LenientThis", "NamedConstructor", "NewObject", "NoInterfaceObject",
        "OverrideBuiltins", "PutForwards", "Replaceable", "SameObject", "SecureContext",
        "Throws", "TreatNonObjectAsNull", "TreatNullAs", "Unforgeable", "Unscopable",
    ];

    static ref RESERVED_WORDS_PYTHON : Vec<&'static str> = vec![
        "and", "del", "from", "not", "while",
        "as", "elif", "global", "or", "with",
        "assert", "else", "if", "pass", "yield",
        "break", "except", "import", "print",
        "class", "exec", "in", "raise", "continue",
        "finally", "is", "return",
        "def", "for", "lambda", "try",
    ];

    // List of Rust reserved words pulled from
    // https://github.com/rust-lang/rust/blob/master/src/libsyntax/symbol.rs
    static ref RESERVED_WORDS_RUST : Vec<&'static str> = vec![
        "as", "box", "break", "const", "continue", "crate",
        "else", "enum", "extern", "false", "fn", "for", "if",
        "impl", "in", "let", "loop", "match", "mod", "move",
        "mut", "pub", "ref", "return", "self", "Self", "static",
        "struct", "super", "trait", "true", "type", "unsafe",
        "use", "where", "while",

        "abstract", "alignof", "become", "do", "final", "macro",
        "offsetof", "override", "priv", "proc", "pure", "sizeof",
        "typeof", "unsized", "virtual", "yield",

        "default", "union",
    ];

    static ref RESERVED_WORDS_JAVA : Vec<&'static str> = vec![
        "abstract", "continue", "for", "new", "switch", "assert", "default",
        "goto", "package", "synchronized", "boolean", "do", "if", "private",
        "this", "break", "double", "implements", "protected", "throw", "byte",
        "else", "import", "public", "throws", "case", "enum", "instanceof",
        "return", "transient", "catch", "extends", "int", "short", "try",
        "char", "final", "interface", "static", "void", "class", "finally",
        "long", "strictfp", "volatile", "const", "float", "native", "super",
        "while", "null", "true", "false",
    ];

    // http://kotlinlang.org/docs/reference/keyword-reference.html
    static ref RESERVED_WORDS_KOTLIN : Vec<&'static str> = vec![
        "as", "as?", "break", "class", "continue", "do", "else", "false",
        "for", "fun", "if", "in", "!in", "interface", "is", "!is", "null",
        "object", "package", "return", "super", "this", "throw", "true",
        "try", "typealias", "val", "var", "when", "while",

        "by", "catch", "constructor", "delegate", "dynamic", "field", "file",
        "finally", "get", "import", "init", "param", "property", "receiver",
        "set", "setparam", "where",

        "actual", "abstract", "annotation", "companion", "const",
        "crossinline", "data", "enum", "expect", "external", "final", "infix",
        "inline", "inner", "internal", "lateinit", "noinline", "open",
        "operator", "out", "override", "private", "protected", "public",
        "reified", "sealed", "suspend", "tailrec", "vararg",

        "field", "it",
    ];

    static ref JS_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JS),
        c_style_comments: true,
        backtick_strings: true,
        regexp_literals: true,
        .. LanguageSpec::default()
    };

    static ref CPP_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_CPP),
        c_style_comments: true,
        c_preprocessor: true,
        cxx14_digit_separators: true,
        .. LanguageSpec::default()
    };

    static ref IPDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IPDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref IDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref WEBIDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_WEBIDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref PYTHON_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_PYTHON),
        hash_comment: true,
        triple_quote_literals: true,
        .. LanguageSpec::default()
    };

    static ref RUST_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_RUST),
        hash_comment: true, // for now, for attributes
        c_style_comments: true,
        rust_tweaks: true,
        .. LanguageSpec::default()
    };

    static ref JAVA_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JAVA),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref KOTLIN_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_KOTLIN),
        c_style_comments: true,
        .. LanguageSpec::default()
    };
}

#[derive(Debug)]
pub enum DocType {
    Markdown,
    ReStructuredText,
}

#[derive(Debug)]
pub enum FormatAs {
    FormatCLike(&'static LanguageSpec),
    FormatTagLike(&'static LanguageSpec),
    Plain,
    Binary,
}

pub fn select_formatting(filename: &str) -> FormatAs {
    let ext = match Path::new(filename).extension() {
        Some(ext) => ext.to_str().unwrap(),
        None => "",
    };
    match ext {
        "c" | "cc" | "cpp" | "cxx" | "h" | "hh" | "hxx" | "mm" => FormatAs::FormatCLike(&*CPP_SPEC),
        "ipdl" | "ipdlh" => FormatAs::FormatCLike(&*IPDL_SPEC),
        "idl" => FormatAs::FormatCLike(&*IDL_SPEC),
        "webidl" => FormatAs::FormatCLike(&*WEBIDL_SPEC),
        "js" | "jsm" | "json" | "sjs" => FormatAs::FormatCLike(&*JS_SPEC),
        "py" | "build" | "configure" => FormatAs::FormatCLike(&*PYTHON_SPEC),
        "rs" => FormatAs::FormatCLike(&*RUST_SPEC),
        "java" => FormatAs::FormatCLike(&*JAVA_SPEC),
        "kt" => FormatAs::FormatCLike(&*KOTLIN_SPEC),

        "html" | "htm" | "xhtml" | "xht" | "xml" | "xul" => FormatAs::FormatTagLike(&*JS_SPEC),

        // Keep this list in sync with the binary types list in nginx-setup.py
        "ogg" | "ttf" | "xpi" | "png" | "bcmap" |
        "gif" | "ogv" | "jpg" | "jpeg" | "bmp" | "icns" | "ico" |
        "mp4" | "sqlite" | "jar" | "webm" | "woff" |
        "class" | "m4s" | "mgif" | "wav" | "opus" |
        "mp3" | "otf" => FormatAs::Binary,

        _ => FormatAs::Plain,
    }
}
<commit_msg>Bug 1381918 - Remove unused enum<commit_after>use std::collections::HashMap;
use std::path::Path;

#[derive(Debug, Default)]
pub struct LanguageSpec {
    pub reserved_words: HashMap<String, String>,
    pub hash_comment: bool,
    pub c_style_comments: bool,
    pub backtick_strings: bool,
    pub regexp_literals: bool,
    pub triple_quote_literals: bool,
    pub c_preprocessor: bool,
    // Rust is mostly C-like, with a couple of differences.
    pub rust_tweaks: bool,
    pub cxx14_digit_separators: bool,
}

fn make_reserved(v: &[&str]) -> HashMap<String, String> {
    let mut reserved_words = HashMap::new();
    for word in v {
        reserved_words.insert(word.to_string(), "class=\"syn_reserved\" ".to_string());
    }
    reserved_words
}

lazy_static! {
    static ref RESERVED_WORDS_JS : Vec<&'static str> = vec![
        "abstract", "else", "instanceof", "super",
        "boolean", "enum", "int", "switch",
        "break", "export", "interface", "synchronized",
        "byte", "extends", "let", "this",
        "case", "false", "long", "throw",
        "catch", "final", "native", "throws",
        "char", "finally", "new", "transient",
        "class", "float", "null", "true",
        "const", "for", "package", "try",
        "continue", "function", "private", "typeof",
        "debugger", "goto", "protected", "var",
        "default", "if", "public", "void",
        "delete", "implements", "return", "volatile",
        "do", "import", "short", "while",
        "double", "in", "static", "with",
        "get", "set",
    ];

    static ref RESERVED_WORDS_CPP : Vec<&'static str> = vec![
        "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel",
        "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break",
        "case", "catch", "char", "char16_t", "char32_t", "class", "compl", "concept",
        "const", "constexpr", "const_cast", "continue", "decltype", "default", "delete",
        "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
        "float", "for", "friend", "goto", "if", "inline", "int", "import", "long", "module",
        "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
        // Don't mark "operator" as a keyword so that people can click
        // on it.
        //"operator",
        "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
        "requires", "return", "short", "signed", "sizeof", "static", "static_assert",
        "static_cast", "struct", "switch", "synchronized", "template", "this", "thread_local",
        "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
        "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq",
        "#if", "#ifdef", "#ifndef", "#else", "#elif", "#endif", "#define", "#undef",
        "#include", "#error", "defined",
    ];

    static ref RESERVED_WORDS_IPDL : Vec<&'static str> = vec![
        "answer", "as", "async", "both", "bridges", "call", "child", "class",
        "compress", "compressall", "__delete__", "delete", "from", "goto", "high",
        "include", "intr", "manager", "manages", "namespace", "normal", "nullable",
        "opens", "or", "parent", "prio", "protocol", "recv", "returns", "send",
        "spawns", "start", "state", "struct", "sync", "union", "upto", "urgent",
        "using",
    ];

    static ref RESERVED_WORDS_IDL : Vec<&'static str> = vec![
        "const", "interface", "in", "inout", "out", "attribute", "raises",
        "readonly", "native", "typedef",
        "array", "shared", "iid_is", "size_is", "retval",
        "boolean", "void", "octet", "short", "long", "long",
        "unsigned", "float", "double", "char", "string", "wchar", "wstring",
        "nsid", "domstring", "utf8string", "cstring", "astring", "jsval",
        "uuid", "scriptable", "builtinclass", "function", "noscript", "deprecated",
        "object", "main_process_scriptable_only",
    ];

    static ref RESERVED_WORDS_WEBIDL : Vec<&'static str> = vec![
        "module", "interface", "partial", "dictionary", "exception", "enum", "callback",
        "typedef", "implements", "const", "null", "true", "false", "serializer",
        "stringifier", "jsonifier", "unrestricted", "attribute", "readonly", "inherit",
        "static", "getter", "setter", "creator", "deleter", "legacycaller", "optional",
        "Date", "DOMString", "ByteString", "USVString", "any", "boolean", "byte",
        "double", "float", "long", "object", "octet", "Promise", "required", "sequence",
        "MozMap", "short", "unsigned", "void", "ArrayBuffer", "SharedArrayBuffer", "or",
        "maplike", "setlike", "iterable",
        "Exposed", "ChromeOnly", "ChromeConstructor", "Pref", "Func", "AvailableIn",
        "CheckAnyPermissions", "CheckAllPermissions", "JSImplementation", "HeaderFile",
        "NavigatorProperty", "AvailableIn", "Func", "CheckAnyPermissions", "CheckAllPermissions",
        "Deprecated", "NeedResolve", "OverrideBuiltins", "ChromeOnly", "Unforgeable",
        "UnsafeInPrerendering", "LegacyEventInit", "ProbablyShortLivingObject", "ArrayClass",
        "Clamp", "Constructor", "EnforceRange", "ExceptionClass", "Exposed", "ImplicitThis",
        "Global", "PrimaryGlobal", "LegacyArrayClass", "LegacyUnenumerableNamedProperties",
        "LenientSetter", "LenientThis", "NamedConstructor", "NewObject", "NoInterfaceObject",
        "OverrideBuiltins", "PutForwards", "Replaceable", "SameObject", "SecureContext",
        "Throws", "TreatNonObjectAsNull", "TreatNullAs", "Unforgeable", "Unscopable",
    ];

    static ref RESERVED_WORDS_PYTHON : Vec<&'static str> = vec![
        "and", "del", "from", "not", "while",
        "as", "elif", "global", "or", "with",
        "assert", "else", "if", "pass", "yield",
        "break", "except", "import", "print",
        "class", "exec", "in", "raise", "continue",
        "finally", "is", "return",
        "def", "for", "lambda", "try",
    ];

    // List of Rust reserved words pulled from
    // https://github.com/rust-lang/rust/blob/master/src/libsyntax/symbol.rs
    static ref RESERVED_WORDS_RUST : Vec<&'static str> = vec![
        "as", "box", "break", "const", "continue", "crate",
        "else", "enum", "extern", "false", "fn", "for", "if",
        "impl", "in", "let", "loop", "match", "mod", "move",
        "mut", "pub", "ref", "return", "self", "Self", "static",
        "struct", "super", "trait", "true", "type", "unsafe",
        "use", "where", "while",

        "abstract", "alignof", "become", "do", "final", "macro",
        "offsetof", "override", "priv", "proc", "pure", "sizeof",
        "typeof", "unsized", "virtual", "yield",

        "default", "union",
    ];

    static ref RESERVED_WORDS_JAVA : Vec<&'static str> = vec![
        "abstract", "continue", "for", "new", "switch", "assert", "default",
        "goto", "package", "synchronized", "boolean", "do", "if", "private",
        "this", "break", "double", "implements", "protected", "throw", "byte",
        "else", "import", "public", "throws", "case", "enum", "instanceof",
        "return", "transient", "catch", "extends", "int", "short", "try",
        "char", "final", "interface", "static", "void", "class", "finally",
        "long", "strictfp", "volatile", "const", "float", "native", "super",
        "while", "null", "true", "false",
    ];

    // http://kotlinlang.org/docs/reference/keyword-reference.html
    static ref RESERVED_WORDS_KOTLIN : Vec<&'static str> = vec![
        "as", "as?", "break", "class", "continue", "do", "else", "false",
        "for", "fun", "if", "in", "!in", "interface", "is", "!is", "null",
        "object", "package", "return", "super", "this", "throw", "true",
        "try", "typealias", "val", "var", "when", "while",

        "by", "catch", "constructor", "delegate", "dynamic", "field", "file",
        "finally", "get", "import", "init", "param", "property", "receiver",
        "set", "setparam", "where",

        "actual", "abstract", "annotation", "companion", "const",
        "crossinline", "data", "enum", "expect", "external", "final", "infix",
        "inline", "inner", "internal", "lateinit", "noinline", "open",
        "operator", "out", "override", "private", "protected", "public",
        "reified", "sealed", "suspend", "tailrec", "vararg",

        "field", "it",
    ];

    static ref JS_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JS),
        c_style_comments: true,
        backtick_strings: true,
        regexp_literals: true,
        .. LanguageSpec::default()
    };

    static ref CPP_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_CPP),
        c_style_comments: true,
        c_preprocessor: true,
        cxx14_digit_separators: true,
        .. LanguageSpec::default()
    };

    static ref IPDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IPDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref IDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref WEBIDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_WEBIDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref PYTHON_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_PYTHON),
        hash_comment: true,
        triple_quote_literals: true,
        .. LanguageSpec::default()
    };

    static ref RUST_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_RUST),
        hash_comment: true, // for now, for attributes
        c_style_comments: true,
        rust_tweaks: true,
        .. LanguageSpec::default()
    };

    static ref JAVA_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JAVA),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref KOTLIN_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_KOTLIN),
        c_style_comments: true,
        .. LanguageSpec::default()
    };
}

#[derive(Debug)]
pub enum FormatAs {
    FormatCLike(&'static LanguageSpec),
    FormatTagLike(&'static LanguageSpec),
    Plain,
    Binary,
}

pub fn select_formatting(filename: &str) -> FormatAs {
    let ext = match Path::new(filename).extension() {
        Some(ext) => ext.to_str().unwrap(),
        None => "",
    };
    match ext {
        "c" | "cc" | "cpp" | "cxx" | "h" | "hh" | "hxx" | "mm" => FormatAs::FormatCLike(&*CPP_SPEC),
        "ipdl" | "ipdlh" => FormatAs::FormatCLike(&*IPDL_SPEC),
        "idl" => FormatAs::FormatCLike(&*IDL_SPEC),
        "webidl" => FormatAs::FormatCLike(&*WEBIDL_SPEC),
        "js" | "jsm" | "json" | "sjs" => FormatAs::FormatCLike(&*JS_SPEC),
        "py" | "build" | "configure" => FormatAs::FormatCLike(&*PYTHON_SPEC),
        "rs" => FormatAs::FormatCLike(&*RUST_SPEC),
        "java" => FormatAs::FormatCLike(&*JAVA_SPEC),
        "kt" => FormatAs::FormatCLike(&*KOTLIN_SPEC),

        "html" | "htm" | "xhtml" | "xht" | "xml" | "xul" => FormatAs::FormatTagLike(&*JS_SPEC),

        // Keep this list in sync with the binary types list in nginx-setup.py
        "ogg" | "ttf" | "xpi" | "png" | "bcmap" |
        "gif" | "ogv" | "jpg" | "jpeg" | "bmp" | "icns" | "ico" |
        "mp4" | "sqlite" | "jar" | "webm" | "woff" |
        "class" | "m4s" | "mgif" | "wav" | "opus" |
        "mp3" | "otf" => FormatAs::Binary,

        _ => FormatAs::Plain,
    }
}
<|endoftext|>


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

/*!
 * Unicode-intensive `char` methods.
 *
 * These methods implement functionality for `char` that requires knowledge of
 * Unicode definitions, including normalization, categorization, and display information.
 */

use core::option::Option;
use tables::{derived_property, property, general_category, conversions, charwidth};

/// Returns whether the specified `char` is considered a Unicode alphabetic
/// code point
#[deprecated = "use UnicodeChar::is_alphabetic"]
pub fn is_alphabetic(c: char) -> bool {
    c.is_alphabetic()
}

/// Returns whether the specified `char` satisfies the 'XID_Start' Unicode property
///
/// 'XID_Start' is a Unicode Derived Property specified in
/// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
/// mostly similar to ID_Start but modified for closure under NFKx.
#[allow(non_snake_case)]
#[deprecated = "use UnicodeChar::is_XID_start"]
pub fn is_XID_start(c: char) -> bool    { derived_property::XID_Start(c) }

/// Returns whether the specified `char` satisfies the 'XID_Continue' Unicode property
///
/// 'XID_Continue' is a Unicode Derived Property specified in
/// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
/// mostly similar to 'ID_Continue' but modified for closure under NFKx.
#[allow(non_snake_case)]
#[deprecated = "use UnicodeChar::is_XID_continue"]
pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) }

///
/// Indicates whether a `char` is in lower case
///
/// This is defined according to the terms of the Unicode Derived Core Property 'Lowercase'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_lowercase"]
pub fn is_lowercase(c: char) -> bool {
    c.is_lowercase()
}

///
/// Indicates whether a `char` is in upper case
///
/// This is defined according to the terms of the Unicode Derived Core Property 'Uppercase'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_uppercase"]
pub fn is_uppercase(c: char) -> bool {
    c.is_uppercase()
}

///
/// Indicates whether a `char` is whitespace
///
/// Whitespace is defined in terms of the Unicode Property 'White_Space'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_whitespace"]
pub fn is_whitespace(c: char) -> bool {
    c.is_whitespace()
}

///
/// Indicates whether a `char` is alphanumeric
///
/// Alphanumericness is defined in terms of the Unicode General Categories
/// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_alphanumeric"]
pub fn is_alphanumeric(c: char) -> bool {
    c.is_alphanumeric()
}

///
/// Indicates whether a `char` is a control code point
///
/// Control code points are defined in terms of the Unicode General Category
/// 'Cc'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_control"]
pub fn is_control(c: char) -> bool { general_category::Cc(c) }

/// Indicates whether the `char` is numeric (Nd, Nl, or No)
#[inline]
#[deprecated = "use UnicodeChar::is_numeric"]
pub fn is_digit(c: char) -> bool {
    c.is_numeric()
}

/// Convert a char to its uppercase equivalent
///
/// The case-folding performed is the common or simple mapping:
/// it maps one Unicode codepoint (one char in Rust) to its uppercase equivalent according
/// to the Unicode database at ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
/// The additional SpecialCasing.txt is not considered here, as it expands to multiple
/// codepoints in some cases.
///
/// A full reference can be found here
/// http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
///
/// # Return value
///
/// Returns the char itself if no conversion was made
#[inline]
#[deprecated = "use UnicodeChar::to_uppercase"]
pub fn to_uppercase(c: char) -> char {
    conversions::to_upper(c)
}

/// Convert a char to its lowercase equivalent
///
/// The case-folding performed is the common or simple mapping
/// see `to_uppercase` for references and more information
///
/// # Return value
///
/// Returns the char itself if no conversion if possible
#[inline]
#[deprecated = "use UnicodeChar::to_lowercase"]
pub fn to_lowercase(c: char) -> char {
    conversions::to_lower(c)
}

/// Returns this character's displayed width in columns, or `None` if it is a
/// control character other than `'\x00'`.
///
/// `is_cjk` determines behavior for characters in the Ambiguous category:
/// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
/// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
/// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
/// recommends that these characters be treated as 1 column (i.e.,
/// `is_cjk` = `false`) if the context cannot be reliably determined.
#[deprecated = "use UnicodeChar::width"]
pub fn width(c: char, is_cjk: bool) -> Option<uint> {
    charwidth::width(c, is_cjk)
}

/// Useful functions for Unicode characters.
#[experimental = "pending prelude organization"]
pub trait UnicodeChar {
    /// Returns whether the specified character is considered a Unicode
    /// alphabetic code point.
    fn is_alphabetic(self) -> bool;

    /// Returns whether the specified character satisfies the 'XID_Start'
    /// Unicode property.
    ///
    /// 'XID_Start' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to ID_Start but modified for closure under NFKx.
    #[allow(non_snake_case)]
    #[deprecated = "use is_xid_start"]
    fn is_XID_start(self) -> bool;

    /// Returns whether the specified character satisfies the 'XID_Start'
    /// Unicode property.
    ///
    /// 'XID_Start' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to ID_Start but modified for closure under NFKx.
    #[allow(non_snake_case)]
    fn is_xid_start(self) -> bool;

    /// Returns whether the specified `char` satisfies the 'XID_Continue'
    /// Unicode property.
    ///
    /// 'XID_Continue' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
    #[allow(non_snake_case)]
    #[deprecated = "use is_xid_continue"]
    fn is_XID_continue(self) -> bool;

    /// Returns whether the specified `char` satisfies the 'XID_Continue'
    /// Unicode property.
    ///
    /// 'XID_Continue' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
    #[allow(non_snake_case)]
    fn is_xid_continue(self) -> bool;

    /// Indicates whether a character is in lowercase.
    ///
    /// This is defined according to the terms of the Unicode Derived Core
    /// Property `Lowercase`.
    fn is_lowercase(self) -> bool;

    /// Indicates whether a character is in uppercase.
    ///
    /// This is defined according to the terms of the Unicode Derived Core
    /// Property `Uppercase`.
    fn is_uppercase(self) -> bool;

    /// Indicates whether a character is whitespace.
    ///
    /// Whitespace is defined in terms of the Unicode Property `White_Space`.
    fn is_whitespace(self) -> bool;

    /// Indicates whether a character is alphanumeric.
    ///
    /// Alphanumericness is defined in terms of the Unicode General Categories
    /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
    fn is_alphanumeric(self) -> bool;

    /// Indicates whether a character is a control code point.
    ///
    /// Control code points are defined in terms of the Unicode General
    /// Category `Cc`.
    fn is_control(self) -> bool;

    /// Indicates whether the character is numeric (Nd, Nl, or No).
    fn is_numeric(self) -> bool;

    /// Converts a character to its lowercase equivalent.
    ///
    /// The case-folding performed is the common or simple mapping. See
    /// `to_uppercase()` for references and more information.
    ///
    /// # Return value
    ///
    /// Returns the lowercase equivalent of the character, or the character
    /// itself if no conversion is possible.
    fn to_lowercase(self) -> char;

    /// Converts a character to its uppercase equivalent.
    ///
    /// The case-folding performed is the common or simple mapping: it maps
    /// one Unicode codepoint (one character in Rust) to its uppercase
    /// equivalent according to the Unicode database [1]. The additional
    /// [`SpecialCasing.txt`] is not considered here, as it expands to multiple
    /// codepoints in some cases.
    ///
    /// A full reference can be found here [2].
    ///
    /// # Return value
    ///
    /// Returns the uppercase equivalent of the character, or the character
    /// itself if no conversion was made.
    ///
    /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
    ///
    /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
    ///
    /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
    fn to_uppercase(self) -> char;

    /// Returns this character's displayed width in columns, or `None` if it is a
    /// control character other than `'\x00'`.
    ///
    /// `is_cjk` determines behavior for characters in the Ambiguous category:
    /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
    /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
    /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
    /// recommends that these characters be treated as 1 column (i.e.,
    /// `is_cjk` = `false`) if the context cannot be reliably determined.
    #[experimental = "needs expert opinion. is_cjk flag stands out as ugly"]
    fn width(self, is_cjk: bool) -> Option<uint>;
}

#[experimental = "pending prelude organization"]
impl UnicodeChar for char {
    fn is_alphabetic(self) -> bool {
        match self {
            'a' ... 'z' | 'A' ... 'Z' => true,
            c if c > '\x7f' => derived_property::Alphabetic(c),
            _ => false
        }
    }

    #[deprecated = "use is_xid_start"]
    fn is_XID_start(self) -> bool { derived_property::XID_Start(self) }

    #[deprecated = "use is_xid_continue"]
    fn is_XID_continue(self) -> bool { derived_property::XID_Continue(self) }

    fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }

    fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }

    fn is_lowercase(self) -> bool {
        match self {
            'a' ... 'z' => true,
            c if c > '\x7f' => derived_property::Lowercase(c),
            _ => false
        }
    }

    fn is_uppercase(self) -> bool {
        match self {
            'A' ... 'Z' => true,
            c if c > '\x7f' => derived_property::Uppercase(c),
            _ => false
        }
    }

    fn is_whitespace(self) -> bool {
        match self {
            ' ' | '\x09' ... '\x0d' => true,
            c if c > '\x7f' => property::White_Space(c),
            _ => false
        }
    }

    fn is_alphanumeric(self) -> bool {
        self.is_alphabetic() || self.is_numeric()
    }

    fn is_control(self) -> bool { general_category::Cc(self) }

    fn is_numeric(self) -> bool {
        match self {
            '0' ... '9' => true,
            c if c > '\x7f' => general_category::N(c),
            _ => false
        }
    }

    fn to_lowercase(self) -> char { conversions::to_lower(self) }

    fn to_uppercase(self) -> char { conversions::to_upper(self) }

    #[experimental = "needs expert opinion. is_cjk flag stands out as ugly"]
    fn width(self, is_cjk: bool) -> Option<uint> { charwidth::width(self, is_cjk) }
}
<commit_msg>unicode: Remove unused `non_snake_case` allows.<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Unicode-intensive `char` methods.
 *
 * These methods implement functionality for `char` that requires knowledge of
 * Unicode definitions, including normalization, categorization, and display information.
 */

use core::option::Option;
use tables::{derived_property, property, general_category, conversions, charwidth};

/// Returns whether the specified `char` is considered a Unicode alphabetic
/// code point
#[deprecated = "use UnicodeChar::is_alphabetic"]
pub fn is_alphabetic(c: char) -> bool {
    c.is_alphabetic()
}

/// Returns whether the specified `char` satisfies the 'XID_Start' Unicode property
///
/// 'XID_Start' is a Unicode Derived Property specified in
/// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
/// mostly similar to ID_Start but modified for closure under NFKx.
#[allow(non_snake_case)]
#[deprecated = "use UnicodeChar::is_XID_start"]
pub fn is_XID_start(c: char) -> bool    { derived_property::XID_Start(c) }

/// Returns whether the specified `char` satisfies the 'XID_Continue' Unicode property
///
/// 'XID_Continue' is a Unicode Derived Property specified in
/// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
/// mostly similar to 'ID_Continue' but modified for closure under NFKx.
#[allow(non_snake_case)]
#[deprecated = "use UnicodeChar::is_XID_continue"]
pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) }

///
/// Indicates whether a `char` is in lower case
///
/// This is defined according to the terms of the Unicode Derived Core Property 'Lowercase'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_lowercase"]
pub fn is_lowercase(c: char) -> bool {
    c.is_lowercase()
}

///
/// Indicates whether a `char` is in upper case
///
/// This is defined according to the terms of the Unicode Derived Core Property 'Uppercase'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_uppercase"]
pub fn is_uppercase(c: char) -> bool {
    c.is_uppercase()
}

///
/// Indicates whether a `char` is whitespace
///
/// Whitespace is defined in terms of the Unicode Property 'White_Space'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_whitespace"]
pub fn is_whitespace(c: char) -> bool {
    c.is_whitespace()
}

///
/// Indicates whether a `char` is alphanumeric
///
/// Alphanumericness is defined in terms of the Unicode General Categories
/// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_alphanumeric"]
pub fn is_alphanumeric(c: char) -> bool {
    c.is_alphanumeric()
}

///
/// Indicates whether a `char` is a control code point
///
/// Control code points are defined in terms of the Unicode General Category
/// 'Cc'.
///
#[inline]
#[deprecated = "use UnicodeChar::is_control"]
pub fn is_control(c: char) -> bool { general_category::Cc(c) }

/// Indicates whether the `char` is numeric (Nd, Nl, or No)
#[inline]
#[deprecated = "use UnicodeChar::is_numeric"]
pub fn is_digit(c: char) -> bool {
    c.is_numeric()
}

/// Convert a char to its uppercase equivalent
///
/// The case-folding performed is the common or simple mapping:
/// it maps one Unicode codepoint (one char in Rust) to its uppercase equivalent according
/// to the Unicode database at ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
/// The additional SpecialCasing.txt is not considered here, as it expands to multiple
/// codepoints in some cases.
///
/// A full reference can be found here
/// http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
///
/// # Return value
///
/// Returns the char itself if no conversion was made
#[inline]
#[deprecated = "use UnicodeChar::to_uppercase"]
pub fn to_uppercase(c: char) -> char {
    conversions::to_upper(c)
}

/// Convert a char to its lowercase equivalent
///
/// The case-folding performed is the common or simple mapping
/// see `to_uppercase` for references and more information
///
/// # Return value
///
/// Returns the char itself if no conversion if possible
#[inline]
#[deprecated = "use UnicodeChar::to_lowercase"]
pub fn to_lowercase(c: char) -> char {
    conversions::to_lower(c)
}

/// Returns this character's displayed width in columns, or `None` if it is a
/// control character other than `'\x00'`.
///
/// `is_cjk` determines behavior for characters in the Ambiguous category:
/// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
/// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
/// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
/// recommends that these characters be treated as 1 column (i.e.,
/// `is_cjk` = `false`) if the context cannot be reliably determined.
#[deprecated = "use UnicodeChar::width"]
pub fn width(c: char, is_cjk: bool) -> Option<uint> {
    charwidth::width(c, is_cjk)
}

/// Useful functions for Unicode characters.
#[experimental = "pending prelude organization"]
pub trait UnicodeChar {
    /// Returns whether the specified character is considered a Unicode
    /// alphabetic code point.
    fn is_alphabetic(self) -> bool;

    /// Returns whether the specified character satisfies the 'XID_Start'
    /// Unicode property.
    ///
    /// 'XID_Start' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to ID_Start but modified for closure under NFKx.
    #[allow(non_snake_case)]
    #[deprecated = "use is_xid_start"]
    fn is_XID_start(self) -> bool;

    /// Returns whether the specified character satisfies the 'XID_Start'
    /// Unicode property.
    ///
    /// 'XID_Start' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to ID_Start but modified for closure under NFKx.
    fn is_xid_start(self) -> bool;

    /// Returns whether the specified `char` satisfies the 'XID_Continue'
    /// Unicode property.
    ///
    /// 'XID_Continue' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
    #[allow(non_snake_case)]
    #[deprecated = "use is_xid_continue"]
    fn is_XID_continue(self) -> bool;

    /// Returns whether the specified `char` satisfies the 'XID_Continue'
    /// Unicode property.
    ///
    /// 'XID_Continue' is a Unicode Derived Property specified in
    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
    /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
    fn is_xid_continue(self) -> bool;

    /// Indicates whether a character is in lowercase.
    ///
    /// This is defined according to the terms of the Unicode Derived Core
    /// Property `Lowercase`.
    fn is_lowercase(self) -> bool;

    /// Indicates whether a character is in uppercase.
    ///
    /// This is defined according to the terms of the Unicode Derived Core
    /// Property `Uppercase`.
    fn is_uppercase(self) -> bool;

    /// Indicates whether a character is whitespace.
    ///
    /// Whitespace is defined in terms of the Unicode Property `White_Space`.
    fn is_whitespace(self) -> bool;

    /// Indicates whether a character is alphanumeric.
    ///
    /// Alphanumericness is defined in terms of the Unicode General Categories
    /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
    fn is_alphanumeric(self) -> bool;

    /// Indicates whether a character is a control code point.
    ///
    /// Control code points are defined in terms of the Unicode General
    /// Category `Cc`.
    fn is_control(self) -> bool;

    /// Indicates whether the character is numeric (Nd, Nl, or No).
    fn is_numeric(self) -> bool;

    /// Converts a character to its lowercase equivalent.
    ///
    /// The case-folding performed is the common or simple mapping. See
    /// `to_uppercase()` for references and more information.
    ///
    /// # Return value
    ///
    /// Returns the lowercase equivalent of the character, or the character
    /// itself if no conversion is possible.
    fn to_lowercase(self) -> char;

    /// Converts a character to its uppercase equivalent.
    ///
    /// The case-folding performed is the common or simple mapping: it maps
    /// one Unicode codepoint (one character in Rust) to its uppercase
    /// equivalent according to the Unicode database [1]. The additional
    /// [`SpecialCasing.txt`] is not considered here, as it expands to multiple
    /// codepoints in some cases.
    ///
    /// A full reference can be found here [2].
    ///
    /// # Return value
    ///
    /// Returns the uppercase equivalent of the character, or the character
    /// itself if no conversion was made.
    ///
    /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
    ///
    /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
    ///
    /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
    fn to_uppercase(self) -> char;

    /// Returns this character's displayed width in columns, or `None` if it is a
    /// control character other than `'\x00'`.
    ///
    /// `is_cjk` determines behavior for characters in the Ambiguous category:
    /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
    /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
    /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
    /// recommends that these characters be treated as 1 column (i.e.,
    /// `is_cjk` = `false`) if the context cannot be reliably determined.
    #[experimental = "needs expert opinion. is_cjk flag stands out as ugly"]
    fn width(self, is_cjk: bool) -> Option<uint>;
}

#[experimental = "pending prelude organization"]
impl UnicodeChar for char {
    fn is_alphabetic(self) -> bool {
        match self {
            'a' ... 'z' | 'A' ... 'Z' => true,
            c if c > '\x7f' => derived_property::Alphabetic(c),
            _ => false
        }
    }

    #[deprecated = "use is_xid_start"]
    fn is_XID_start(self) -> bool { derived_property::XID_Start(self) }

    #[deprecated = "use is_xid_continue"]
    fn is_XID_continue(self) -> bool { derived_property::XID_Continue(self) }

    fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }

    fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }

    fn is_lowercase(self) -> bool {
        match self {
            'a' ... 'z' => true,
            c if c > '\x7f' => derived_property::Lowercase(c),
            _ => false
        }
    }

    fn is_uppercase(self) -> bool {
        match self {
            'A' ... 'Z' => true,
            c if c > '\x7f' => derived_property::Uppercase(c),
            _ => false
        }
    }

    fn is_whitespace(self) -> bool {
        match self {
            ' ' | '\x09' ... '\x0d' => true,
            c if c > '\x7f' => property::White_Space(c),
            _ => false
        }
    }

    fn is_alphanumeric(self) -> bool {
        self.is_alphabetic() || self.is_numeric()
    }

    fn is_control(self) -> bool { general_category::Cc(self) }

    fn is_numeric(self) -> bool {
        match self {
            '0' ... '9' => true,
            c if c > '\x7f' => general_category::N(c),
            _ => false
        }
    }

    fn to_lowercase(self) -> char { conversions::to_lower(self) }

    fn to_uppercase(self) -> char { conversions::to_upper(self) }

    #[experimental = "needs expert opinion. is_cjk flag stands out as ugly"]
    fn width(self, is_cjk: bool) -> Option<uint> { charwidth::width(self, is_cjk) }
}
<|endoftext|>


<commit_before>use std::rand::StdRng;
use std::rand::Rng;
use std::rand::SeedableRng;
use std::iter;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::HashMap;
use terrain::TerrainType;
use location::Location;
use mapgen;
use {AreaSpec};
use components::{Category};
use spawn::Spawn;

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values.

#[derive(Copy, Clone, RustcDecodable, RustcEncodable)]
struct AreaSeed {
    pub rng_seed: u32,
    pub spec: AreaSpec,
}

#[derive(Clone)]
/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    /// Random number generator seed. Must uniquely define the Area contents.
    pub seed: AreaSeed,
    /// Stored terrain.
    pub terrain: HashMap<Location, TerrainType>,
    /// Valid slots to spawn things in, basically open floor and connected to
    /// areas the player can reach. (Does not handle stuff like monsters that
    /// spawn in water for now.)
    _open_slots: Vec<Location>,
    /// Where the player should enter the area.
    player_entrance: Location,
    /// Non-player entities to create when first initializing the map.
    spawns: Vec<(Spawn, Location)>,
}

impl Decodable for Area {
    fn decode<D: Decoder>(d: &mut D) -> Result<Area, D::Error> {
        let seed: AreaSeed = try!(Decodable::decode(d));
        Ok(Area::new(seed.rng_seed, seed.spec))
    }
}

impl Encodable for Area {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.seed.encode(s)
    }
}

impl Area {
    pub fn new(rng_seed: u32, spec: AreaSpec) -> Area {
        let num_mobs = 32;
        let num_items = 24;

        let mut terrain = HashMap::new();
        let mut rng: StdRng = SeedableRng::from_seed([rng_seed as usize + spec.depth as usize].as_slice());
        mapgen::gen_herringbone(
            &mut rng,
            &spec,
            |x, y, z, t| {terrain.insert(Location::new(x as i8, y as i8, z as i8), t);});

        // Generate open slots that can be used to spawn stuff.
        let mut opens = Vec::new();
        for (&loc, t) in terrain.iter() {
            // No connectivity analysis yet, trusting that herringbone map has
            // total connectivity. Later on, use Dijkstra map that spreads
            // from entrance/exit as a reachability floodfill to do something
            // cleverer here.
            if loc.z == 0 && !t.blocks_walk() &&
                terrain.get(&loc.below()).map_or(false, |t| t.is_solid()) {
                opens.push(loc);
            }
        }
        rng.shuffle(opens.as_mut_slice());

        let entrance = opens.pop().unwrap();

        let mut spawns = vec![];

        // XXX: copy-pasting the space-finding code.
        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Mob], vec![spec.biome]))
            .take(num_mobs)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Item], vec![spec.biome]))
            .take(num_items)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        Area {
            seed: AreaSeed { rng_seed: rng_seed, spec: spec },
            terrain: terrain,
            _open_slots: opens,
            player_entrance: entrance,
            spawns: spawns,
        }
    }

    /// Return terrain at given location.
    pub fn terrain(&self, loc: Location) -> TerrainType {
        match self.terrain.get(&loc) {
            Some(&t) => t,
            None => self.default_terrain(loc)
        }
    }

    /// List the objects that should be hatched in the world during init. This
    /// is tied to map generation, so it goes in the area module.
    pub fn get_spawns(&self) -> Vec<(Spawn, Location)> { self.spawns.clone() }

    pub fn player_entrance(&self) -> Location {
        self.player_entrance
    }

    fn default_terrain(&self, _loc: Location) -> TerrainType {
        self.seed.spec.biome.default_terrain()
    }
}
<commit_msg>Don't spawn in doorways<commit_after>use std::rand::StdRng;
use std::rand::Rng;
use std::rand::SeedableRng;
use std::iter;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::HashMap;
use terrain::TerrainType;
use location::Location;
use mapgen;
use {AreaSpec};
use components::{Category};
use spawn::Spawn;

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values.

#[derive(Copy, Clone, RustcDecodable, RustcEncodable)]
struct AreaSeed {
    pub rng_seed: u32,
    pub spec: AreaSpec,
}

#[derive(Clone)]
/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    /// Random number generator seed. Must uniquely define the Area contents.
    pub seed: AreaSeed,
    /// Stored terrain.
    pub terrain: HashMap<Location, TerrainType>,
    /// Valid slots to spawn things in, basically open floor and connected to
    /// areas the player can reach. (Does not handle stuff like monsters that
    /// spawn in water for now.)
    _open_slots: Vec<Location>,
    /// Where the player should enter the area.
    player_entrance: Location,
    /// Non-player entities to create when first initializing the map.
    spawns: Vec<(Spawn, Location)>,
}

impl Decodable for Area {
    fn decode<D: Decoder>(d: &mut D) -> Result<Area, D::Error> {
        let seed: AreaSeed = try!(Decodable::decode(d));
        Ok(Area::new(seed.rng_seed, seed.spec))
    }
}

impl Encodable for Area {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.seed.encode(s)
    }
}

impl Area {
    pub fn new(rng_seed: u32, spec: AreaSpec) -> Area {
        let num_mobs = 32;
        let num_items = 24;

        let mut terrain = HashMap::new();
        let mut rng: StdRng = SeedableRng::from_seed([rng_seed as usize + spec.depth as usize].as_slice());
        mapgen::gen_herringbone(
            &mut rng,
            &spec,
            |x, y, z, t| {terrain.insert(Location::new(x as i8, y as i8, z as i8), t);});

        // Generate open slots that can be used to spawn stuff.
        //
        // No connectivity analysis yet, trusting that herringbone map has
        // total connectivity. Later on, use Dijkstra map that spreads from
        // entrance/exit as a reachability floodfill to do something cleverer
        // here.
        let mut opens: Vec<Location> = terrain.iter()
            .filter_map(|(&loc, t)|
                if !t.blocks_walk() && !t.is_door() &&
                    terrain.get(&loc.below())
                        .unwrap_or(&spec.biome.default_terrain()).is_solid() {
                    Some(loc)
                } else { None })
            .collect();

        rng.shuffle(opens.as_mut_slice());

        let entrance = opens.pop().unwrap();

        let mut spawns = vec![];

        // XXX: copy-pasting the space-finding code.
        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Mob], vec![spec.biome]))
            .take(num_mobs)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Item], vec![spec.biome]))
            .take(num_items)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        Area {
            seed: AreaSeed { rng_seed: rng_seed, spec: spec },
            terrain: terrain,
            _open_slots: opens,
            player_entrance: entrance,
            spawns: spawns,
        }
    }

    /// Return terrain at given location.
    pub fn terrain(&self, loc: Location) -> TerrainType {
        match self.terrain.get(&loc) {
            Some(&t) => t,
            None => self.default_terrain(loc)
        }
    }

    /// List the objects that should be hatched in the world during init. This
    /// is tied to map generation, so it goes in the area module.
    pub fn get_spawns(&self) -> Vec<(Spawn, Location)> { self.spawns.clone() }

    pub fn player_entrance(&self) -> Location {
        self.player_entrance
    }

    fn default_terrain(&self, _loc: Location) -> TerrainType {
        self.seed.spec.biome.default_terrain()
    }
}
<|endoftext|>


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

// Verifies that the types and values of static items
// are safe. The rules enforced by this module are:
//
// - For each *mutable* static item, it checks that its **type**:
//     - doesn't have a destructor
//     - doesn't own an owned pointer
//
// - For each *immutable* static item, it checks that its **value**:
//       - doesn't own owned, managed pointers
//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
//           - the type of the struct/enum has a dtor
//
// Rules Enforced Elsewhere:
// - It's not possible to take the address of a static item with unsafe interior. This is enforced
// by borrowck::gather_loans

use middle::ty;
use middle::def;
use middle::typeck;
use middle::traits;
use middle::mem_categorization as mc;
use middle::expr_use_visitor as euv;
use util::nodemap::NodeSet;

use syntax::ast;
use syntax::print::pprust;
use syntax::visit::Visitor;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::visit;

#[deriving(Eq, PartialEq)]
enum Mode {
    InConstant,
    InStatic,
    InStaticMut,
    InNothing,
}

struct CheckStaticVisitor<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    mode: Mode,
    checker: &'a mut GlobalChecker,
}

struct GlobalVisitor<'a, 'b, 't: 'b>(euv::ExprUseVisitor<'a, 'b, ty::ctxt<'t>>);
struct GlobalChecker {
    static_consumptions: NodeSet,
    const_borrows: NodeSet,
    static_interior_borrows: NodeSet,
}

pub fn check_crate(tcx: &ty::ctxt) {
    let mut checker = GlobalChecker {
        static_consumptions: NodeSet::new(),
        const_borrows: NodeSet::new(),
        static_interior_borrows: NodeSet::new(),
    };
    {
        let visitor = euv::ExprUseVisitor::new(&mut checker, tcx);
        visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate());
    }
    visit::walk_crate(&mut CheckStaticVisitor {
        tcx: tcx,
        mode: InNothing,
        checker: &mut checker,
    }, tcx.map.krate());
}

impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
    fn with_mode(&mut self, mode: Mode, f: |&mut CheckStaticVisitor<'a, 'tcx>|) {
        let old = self.mode;
        self.mode = mode;
        f(self);
        self.mode = old;
    }

    fn msg(&self) -> &'static str {
        match self.mode {
            InConstant => "constants",
            InStaticMut | InStatic => "statics",
            InNothing => unreachable!(),
        }
    }

    fn check_static_mut_type(&self, e: &ast::Expr) {
        let node_ty = ty::node_id_to_type(self.tcx, e.id);
        let tcontents = ty::type_contents(self.tcx, node_ty);

        let suffix = if tcontents.has_dtor() {
            "destructors"
        } else if tcontents.owns_owned() {
            "owned pointers"
        } else {
            return
        };

        self.tcx.sess.span_err(e.span, format!("mutable statics are not allowed \
                                                to have {}", suffix).as_slice());
    }

    fn check_static_type(&self, e: &ast::Expr) {
        let ty = ty::node_id_to_type(self.tcx, e.id);
        let infcx = typeck::infer::new_infer_ctxt(self.tcx);
        let mut fulfill_cx = traits::FulfillmentContext::new();
        let cause = traits::ObligationCause::misc(DUMMY_SP);
        let obligation = traits::obligation_for_builtin_bound(self.tcx, cause, ty,
                                                              ty::BoundSync);
        fulfill_cx.register_obligation(self.tcx, obligation.unwrap());
        let env = ty::empty_parameter_environment();
        let result = fulfill_cx.select_all_or_error(&infcx, &env, self.tcx).is_ok();
        if !result {
            self.tcx.sess.span_err(e.span, "shared static items must have a \
                                            type which implements Sync");
        }
    }
}

impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &ast::Item) {
        debug!("visit_item(item={})", pprust::item_to_string(i));
        match i.node {
            ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
                self.check_static_type(&**expr);
                self.with_mode(InStatic, |v| v.visit_expr(&**expr));
            }
            ast::ItemStatic(_, ast::MutMutable, ref expr) => {
                self.check_static_mut_type(&**expr);
                self.with_mode(InStaticMut, |v| v.visit_expr(&**expr));
            }
            ast::ItemConst(_, ref expr) => {
                self.with_mode(InConstant, |v| v.visit_expr(&**expr));
            }
            _ => {
                self.with_mode(InNothing, |v| visit::walk_item(v, i));
            }
        }
    }

    /// This method is used to enforce the constraints on
    /// immutable static items. It walks through the *value*
    /// of the item walking down the expression and evaluating
    /// every nested expression. if the expression is not part
    /// of a static item, this method does nothing but walking
    /// down through it.
    fn visit_expr(&mut self, e: &ast::Expr) {
        if self.mode == InNothing {
            return visit::walk_expr(self, e);
        }

        let node_ty = ty::node_id_to_type(self.tcx, e.id);

        match ty::get(node_ty).sty {
            ty::ty_struct(did, _) |
            ty::ty_enum(did, _) if ty::has_dtor(self.tcx, did) => {
                self.tcx.sess.span_err(e.span,
                                       format!("{} are not allowed to have \
                                                destructors", self.msg()).as_slice())
            }
            _ => {}
        }

        // statics cannot be consumed by value at any time, that would imply
        // that they're an initializer (what a const is for) or kept in sync
        // over time (not feasible), so deny it outright.
        if self.checker.static_consumptions.remove(&e.id) {
            self.tcx.sess.span_err(e.span, "cannot refer to other statics by \
                                            value, use the address-of operator \
                                            or a constant instead");
        }

        // Borrowed statics can specifically *only* have their address taken,
        // not any number of other borrows such as borrowing fields, reading
        // elements of an array, etc.
        if self.checker.static_interior_borrows.remove(&e.id) {
            self.tcx.sess.span_err(e.span, "cannot refer to the interior of \
                                            another static, use a constant \
                                            instead");
        }

        // constants cannot be borrowed if they contain interior mutability as
        // it means that our "silent insertion of statics" could change
        // initializer values (very bad).
        if self.checker.const_borrows.remove(&e.id) {
            let node_ty = ty::node_id_to_type(self.tcx, e.id);
            let tcontents = ty::type_contents(self.tcx, node_ty);
            if tcontents.interior_unsafe() {
                self.tcx.sess.span_err(e.span, "cannot borrow a constant which \
                                                contains interior mutability, \
                                                create a static instead");
            }
        }

        match e.node {
            ast::ExprAddrOf(ast::MutMutable, _) => {
                if self.mode != InStaticMut {
                    span_err!(self.tcx.sess, e.span, E0020,
                              "{} are not allowed to have mutable references",
                              self.msg());
                }
            },
            ast::ExprBox(..) |
            ast::ExprUnary(ast::UnUniq, _) => {
                span_err!(self.tcx.sess, e.span, E0022,
                          "{} are not allowed to have custom pointers",
                          self.msg());
            }
            ast::ExprPath(..) => {
                match ty::resolve_expr(self.tcx, e) {
                    def::DefStatic(..) if self.mode == InConstant => {
                        let msg = "constants cannot refer to other statics, \
                                   insert an intermediate constant \
                                   instead";
                        self.tcx.sess.span_err(e.span, msg.as_slice());
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        visit::walk_expr(self, e);
    }
}

impl<'a, 'b, 't, 'v> Visitor<'v> for GlobalVisitor<'a, 'b, 't> {
    fn visit_item(&mut self, item: &ast::Item) {
        match item.node {
            ast::ItemConst(_, ref e) |
            ast::ItemStatic(_, _, ref e) => {
                let GlobalVisitor(ref mut v) = *self;
                v.consume_expr(&**e);
            }
            _ => {}
        }
        visit::walk_item(self, item);
    }
}

impl euv::Delegate for GlobalChecker {
    fn consume(&mut self,
               consume_id: ast::NodeId,
               _consume_span: Span,
               cmt: mc::cmt,
               _mode: euv::ConsumeMode) {
        let mut cur = &cmt;
        loop {
            match cur.cat {
                mc::cat_static_item => {
                    self.static_consumptions.insert(consume_id);
                    break
                }
                mc::cat_deref(ref cmt, _, _) |
                mc::cat_discr(ref cmt, _) |
                mc::cat_downcast(ref cmt) |
                mc::cat_interior(ref cmt, _) => cur = cmt,

                mc::cat_rvalue(..) |
                mc::cat_upvar(..) |
                mc::cat_local(..) => break,
            }
        }
    }
    fn borrow(&mut self,
              borrow_id: ast::NodeId,
              _borrow_span: Span,
              cmt: mc::cmt,
              _loan_region: ty::Region,
              _bk: ty::BorrowKind,
              _loan_cause: euv::LoanCause) {
        let mut cur = &cmt;
        let mut is_interior = false;
        loop {
            match cur.cat {
                mc::cat_rvalue(..) => {
                    self.const_borrows.insert(borrow_id);
                    break
                }
                mc::cat_static_item => {
                    if is_interior {
                        self.static_interior_borrows.insert(borrow_id);
                    }
                    break
                }
                mc::cat_deref(ref cmt, _, _) |
                mc::cat_interior(ref cmt, _) => {
                    is_interior = true;
                    cur = cmt;
                }

                mc::cat_downcast(..) |
                mc::cat_discr(..) |
                mc::cat_upvar(..) |
                mc::cat_local(..) => unreachable!(),
            }
        }
    }

    fn decl_without_init(&mut self,
                         _id: ast::NodeId,
                         _span: Span) {}
    fn mutate(&mut self,
              _assignment_id: ast::NodeId,
              _assignment_span: Span,
              _assignee_cmt: mc::cmt,
              _mode: euv::MutateMode) {}
    fn consume_pat(&mut self,
                   _consume_pat: &ast::Pat,
                   _cmt: mc::cmt,
                   _mode: euv::ConsumeMode) {}
}

<commit_msg>auto merge of #18124 : pnkfelix/rust/fsk-add-check-of-borrow-local-static, r=thestinger<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Verifies that the types and values of static items
// are safe. The rules enforced by this module are:
//
// - For each *mutable* static item, it checks that its **type**:
//     - doesn't have a destructor
//     - doesn't own an owned pointer
//
// - For each *immutable* static item, it checks that its **value**:
//       - doesn't own owned, managed pointers
//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
//           - the type of the struct/enum has a dtor
//
// Rules Enforced Elsewhere:
// - It's not possible to take the address of a static item with unsafe interior. This is enforced
// by borrowck::gather_loans

use middle::ty;
use middle::def;
use middle::typeck;
use middle::traits;
use middle::mem_categorization as mc;
use middle::expr_use_visitor as euv;
use util::nodemap::NodeSet;

use syntax::ast;
use syntax::print::pprust;
use syntax::visit::Visitor;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::visit;

#[deriving(Eq, PartialEq)]
enum Mode {
    InConstant,
    InStatic,
    InStaticMut,
    InNothing,
}

struct CheckStaticVisitor<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    mode: Mode,
    checker: &'a mut GlobalChecker,
}

struct GlobalVisitor<'a, 'b, 't: 'b>(euv::ExprUseVisitor<'a, 'b, ty::ctxt<'t>>);
struct GlobalChecker {
    static_consumptions: NodeSet,
    const_borrows: NodeSet,
    static_interior_borrows: NodeSet,
    static_local_borrows: NodeSet,
}

pub fn check_crate(tcx: &ty::ctxt) {
    let mut checker = GlobalChecker {
        static_consumptions: NodeSet::new(),
        const_borrows: NodeSet::new(),
        static_interior_borrows: NodeSet::new(),
        static_local_borrows: NodeSet::new(),
    };
    {
        let visitor = euv::ExprUseVisitor::new(&mut checker, tcx);
        visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate());
    }
    visit::walk_crate(&mut CheckStaticVisitor {
        tcx: tcx,
        mode: InNothing,
        checker: &mut checker,
    }, tcx.map.krate());
}

impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
    fn with_mode(&mut self, mode: Mode, f: |&mut CheckStaticVisitor<'a, 'tcx>|) {
        let old = self.mode;
        self.mode = mode;
        f(self);
        self.mode = old;
    }

    fn msg(&self) -> &'static str {
        match self.mode {
            InConstant => "constants",
            InStaticMut | InStatic => "statics",
            InNothing => unreachable!(),
        }
    }

    fn check_static_mut_type(&self, e: &ast::Expr) {
        let node_ty = ty::node_id_to_type(self.tcx, e.id);
        let tcontents = ty::type_contents(self.tcx, node_ty);

        let suffix = if tcontents.has_dtor() {
            "destructors"
        } else if tcontents.owns_owned() {
            "owned pointers"
        } else {
            return
        };

        self.tcx.sess.span_err(e.span, format!("mutable statics are not allowed \
                                                to have {}", suffix).as_slice());
    }

    fn check_static_type(&self, e: &ast::Expr) {
        let ty = ty::node_id_to_type(self.tcx, e.id);
        let infcx = typeck::infer::new_infer_ctxt(self.tcx);
        let mut fulfill_cx = traits::FulfillmentContext::new();
        let cause = traits::ObligationCause::misc(DUMMY_SP);
        let obligation = traits::obligation_for_builtin_bound(self.tcx, cause, ty,
                                                              ty::BoundSync);
        fulfill_cx.register_obligation(self.tcx, obligation.unwrap());
        let env = ty::empty_parameter_environment();
        let result = fulfill_cx.select_all_or_error(&infcx, &env, self.tcx).is_ok();
        if !result {
            self.tcx.sess.span_err(e.span, "shared static items must have a \
                                            type which implements Sync");
        }
    }
}

impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &ast::Item) {
        debug!("visit_item(item={})", pprust::item_to_string(i));
        match i.node {
            ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
                self.check_static_type(&**expr);
                self.with_mode(InStatic, |v| v.visit_expr(&**expr));
            }
            ast::ItemStatic(_, ast::MutMutable, ref expr) => {
                self.check_static_mut_type(&**expr);
                self.with_mode(InStaticMut, |v| v.visit_expr(&**expr));
            }
            ast::ItemConst(_, ref expr) => {
                self.with_mode(InConstant, |v| v.visit_expr(&**expr));
            }
            _ => {
                self.with_mode(InNothing, |v| visit::walk_item(v, i));
            }
        }
    }

    /// This method is used to enforce the constraints on
    /// immutable static items. It walks through the *value*
    /// of the item walking down the expression and evaluating
    /// every nested expression. if the expression is not part
    /// of a static item, this method does nothing but walking
    /// down through it.
    fn visit_expr(&mut self, e: &ast::Expr) {
        if self.mode == InNothing {
            return visit::walk_expr(self, e);
        }

        let node_ty = ty::node_id_to_type(self.tcx, e.id);

        match ty::get(node_ty).sty {
            ty::ty_struct(did, _) |
            ty::ty_enum(did, _) if ty::has_dtor(self.tcx, did) => {
                self.tcx.sess.span_err(e.span,
                                       format!("{} are not allowed to have \
                                                destructors", self.msg()).as_slice())
            }
            _ => {}
        }

        // statics cannot be consumed by value at any time, that would imply
        // that they're an initializer (what a const is for) or kept in sync
        // over time (not feasible), so deny it outright.
        if self.checker.static_consumptions.remove(&e.id) {
            self.tcx.sess.span_err(e.span, "cannot refer to other statics by \
                                            value, use the address-of operator \
                                            or a constant instead");
        }

        // Borrowed statics can specifically *only* have their address taken,
        // not any number of other borrows such as borrowing fields, reading
        // elements of an array, etc.
        if self.checker.static_interior_borrows.remove(&e.id) {
            self.tcx.sess.span_err(e.span, "cannot refer to the interior of \
                                            another static, use a constant \
                                            instead");
        }

        // constants cannot be borrowed if they contain interior mutability as
        // it means that our "silent insertion of statics" could change
        // initializer values (very bad).
        if self.checker.const_borrows.remove(&e.id) {
            let node_ty = ty::node_id_to_type(self.tcx, e.id);
            let tcontents = ty::type_contents(self.tcx, node_ty);
            if tcontents.interior_unsafe() {
                self.tcx.sess.span_err(e.span, "cannot borrow a constant which \
                                                contains interior mutability, \
                                                create a static instead");
            }
        }

        // local variables in a block expression in a static context (i.e. being
        // assigned to a static variable) cannot be borrowed.
        if self.checker.static_local_borrows.remove(&e.id) {
            self.tcx.sess.span_err(e.span, "cannot borrow a local variable inside \
                                            a static block, define a separate static \
                                            instead");
        }

        match e.node {
            ast::ExprAddrOf(ast::MutMutable, _) => {
                if self.mode != InStaticMut {
                    span_err!(self.tcx.sess, e.span, E0020,
                              "{} are not allowed to have mutable references",
                              self.msg());
                }
            },
            ast::ExprBox(..) |
            ast::ExprUnary(ast::UnUniq, _) => {
                span_err!(self.tcx.sess, e.span, E0022,
                          "{} are not allowed to have custom pointers",
                          self.msg());
            }
            ast::ExprPath(..) => {
                match ty::resolve_expr(self.tcx, e) {
                    def::DefStatic(..) if self.mode == InConstant => {
                        let msg = "constants cannot refer to other statics, \
                                   insert an intermediate constant \
                                   instead";
                        self.tcx.sess.span_err(e.span, msg.as_slice());
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        visit::walk_expr(self, e);
    }
}

impl<'a, 'b, 't, 'v> Visitor<'v> for GlobalVisitor<'a, 'b, 't> {
    fn visit_item(&mut self, item: &ast::Item) {
        match item.node {
            ast::ItemConst(_, ref e) |
            ast::ItemStatic(_, _, ref e) => {
                let GlobalVisitor(ref mut v) = *self;
                v.consume_expr(&**e);
            }
            _ => {}
        }
        visit::walk_item(self, item);
    }
}

impl euv::Delegate for GlobalChecker {
    fn consume(&mut self,
               consume_id: ast::NodeId,
               _consume_span: Span,
               cmt: mc::cmt,
               _mode: euv::ConsumeMode) {
        let mut cur = &cmt;
        loop {
            match cur.cat {
                mc::cat_static_item => {
                    self.static_consumptions.insert(consume_id);
                    break
                }
                mc::cat_deref(ref cmt, _, _) |
                mc::cat_discr(ref cmt, _) |
                mc::cat_downcast(ref cmt) |
                mc::cat_interior(ref cmt, _) => cur = cmt,

                mc::cat_rvalue(..) |
                mc::cat_upvar(..) |
                mc::cat_local(..) => break,
            }
        }
    }
    fn borrow(&mut self,
              borrow_id: ast::NodeId,
              _borrow_span: Span,
              cmt: mc::cmt,
              _loan_region: ty::Region,
              _bk: ty::BorrowKind,
              _loan_cause: euv::LoanCause) {
        let mut cur = &cmt;
        let mut is_interior = false;
        loop {
            match cur.cat {
                mc::cat_rvalue(..) => {
                    self.const_borrows.insert(borrow_id);
                    break
                }
                mc::cat_static_item => {
                    if is_interior {
                        self.static_interior_borrows.insert(borrow_id);
                    }
                    break
                }
                mc::cat_deref(ref cmt, _, _) |
                mc::cat_interior(ref cmt, _) => {
                    is_interior = true;
                    cur = cmt;
                }

                mc::cat_downcast(..) |
                mc::cat_discr(..) |
                mc::cat_upvar(..) => unreachable!(),

                mc::cat_local(..) => {
                    self.static_local_borrows.insert(borrow_id);
                    break
                }
            }
        }
    }

    fn decl_without_init(&mut self,
                         _id: ast::NodeId,
                         _span: Span) {}
    fn mutate(&mut self,
              _assignment_id: ast::NodeId,
              _assignment_span: Span,
              _assignee_cmt: mc::cmt,
              _mode: euv::MutateMode) {}
    fn consume_pat(&mut self,
                   _consume_pat: &ast::Pat,
                   _cmt: mc::cmt,
                   _mode: euv::ConsumeMode) {}
}

<|endoftext|>


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

#![allow(non_snake_case)]

// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {

E0154: r##"
Imports (`use` statements) are not allowed after non-item statements, such as
variable declarations and expression statements.

Here is an example that demonstrates the error:

```
fn f() {
    // Variable declaration before import
    let x = 0;
    use std::io::Read;
    ...
}
```

The solution is to declare the imports at the top of the block, function, or
file.

Here is the previous example again, with the correct order:

```
fn f() {
    use std::io::Read;
    let x = 0;
    ...
}
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0251: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::*; // error, do `use foo::baz as quux` instead on the previous line

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0252: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::baz; // error, do `use bar::baz as quux` instead

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0255: r##"
You can't import a value whose name is the same as another value defined in the
module.

An example of this error:

```
use foo::FOO; // error, do `use foo::FOO as BAR` instead

fn FOO() {}

mod foo {
    pub const FOO: bool = true;
}

fn main() {}
```
"##,

E0256: r##"
You can't import a type or module when the name of the item being imported is
the same as another type or submodule defined in the module.

An example of this error:

```
use foo::Bar; // error

struct Bar;

mod foo {
    pub mod Bar { }
}

fn main() {}
```
"##,

E0259: r##"
The name chosen for an external crate conflicts with another external crate that
has been imported into the current module.

Wrong example:

```
extern crate a;
extern crate crate_a as a;
```

The solution is to choose a different name that doesn't conflict with any
external crate imported into the current module.

Correct example:

```
extern crate a;
extern crate crate_a as other_name;
```
"##,

E0260: r##"
The name for an item declaration conflicts with an external crate's name.

For instance,

```
extern crate abc;

struct abc;
```

There are two possible solutions:

Solution #1: Rename the item.

```
extern crate abc;

struct xyz;
```

Solution #2: Import the crate with a different name.

```
extern crate abc as xyz;

struct abc;
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0317: r##"
User-defined types or type parameters cannot shadow the primitive types.
This error indicates you tried to define a type, struct or enum with the same
name as an existing primitive type.

See the Types section of the reference for more information about the primitive
types:

http://doc.rust-lang.org/reference.html#types
"##

}

register_diagnostics! {
    E0157,
    E0153,
    E0253, // not directly importable
    E0254, // import conflicts with imported crate in this module
    E0257,
    E0258,
    E0364, // item is private
    E0365  // item is private
}
<commit_msg>Improve examples in the E0255/E0256 error explanations.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {

E0154: r##"
Imports (`use` statements) are not allowed after non-item statements, such as
variable declarations and expression statements.

Here is an example that demonstrates the error:

```
fn f() {
    // Variable declaration before import
    let x = 0;
    use std::io::Read;
    ...
}
```

The solution is to declare the imports at the top of the block, function, or
file.

Here is the previous example again, with the correct order:

```
fn f() {
    use std::io::Read;
    let x = 0;
    ...
}
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0251: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::*; // error, do `use foo::baz as quux` instead on the previous line

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0252: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::baz; // error, do `use bar::baz as quux` instead

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0255: r##"
You can't import a value whose name is the same as another value defined in the
module.

An example of this error:

```
use bar::foo; // error, do `use bar::foo as baz` instead

fn foo() {}

mod bar {
     pub fn foo() {}
}

fn main() {}
```
"##,

E0256: r##"
You can't import a type or module when the name of the item being imported is
the same as another type or submodule defined in the module.

An example of this error:

```
use foo::Bar; // error

type Bar = u32;

mod foo {
    pub mod Bar { }
}

fn main() {}
```
"##,

E0259: r##"
The name chosen for an external crate conflicts with another external crate that
has been imported into the current module.

Wrong example:

```
extern crate a;
extern crate crate_a as a;
```

The solution is to choose a different name that doesn't conflict with any
external crate imported into the current module.

Correct example:

```
extern crate a;
extern crate crate_a as other_name;
```
"##,

E0260: r##"
The name for an item declaration conflicts with an external crate's name.

For instance,

```
extern crate abc;

struct abc;
```

There are two possible solutions:

Solution #1: Rename the item.

```
extern crate abc;

struct xyz;
```

Solution #2: Import the crate with a different name.

```
extern crate abc as xyz;

struct abc;
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0317: r##"
User-defined types or type parameters cannot shadow the primitive types.
This error indicates you tried to define a type, struct or enum with the same
name as an existing primitive type.

See the Types section of the reference for more information about the primitive
types:

http://doc.rust-lang.org/reference.html#types
"##

}

register_diagnostics! {
    E0157,
    E0153,
    E0253, // not directly importable
    E0254, // import conflicts with imported crate in this module
    E0257,
    E0258,
    E0364, // item is private
    E0365  // item is private
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use attribute::Symmetry;
use matrix::{BlasMatrix};
use matrix_vector;
use pointer::CPtr;
use scalar::Scalar;
use vector::BlasVector;

pub trait Gemv {
    fn gemv(alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! gemv_impl(
    ($t: ty, $gemv_fn: ident) => (
        impl Gemv for $t {
            fn gemv(alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$gemv_fn(a.order(), a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

gemv_impl!(f32,       cblas_sgemv)
gemv_impl!(f64,       cblas_dgemv)
gemv_impl!(Complex32, cblas_cgemv)
gemv_impl!(Complex64, cblas_zgemv)

pub trait Symv {
    fn symv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

pub trait Hemv {
    fn hemv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! symv_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symv_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$symv_fn(a.order(), symmetry,
                        a.rows(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

symv_impl!(Symv, symv, f32,       cblas_ssymv)
symv_impl!(Symv, symv, f64,       cblas_dsymv)
symv_impl!(Symv, symv, Complex32, cblas_csymv)
symv_impl!(Symv, symv, Complex64, cblas_zsymv)

symv_impl!(Hemv, hemv, Complex32, cblas_chemv)
symv_impl!(Hemv, hemv, Complex64, cblas_zhemv)

pub trait Ger {
    fn ger(alpha: Self, x: &BlasVector<Self>, y: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

pub trait Gerc {
    fn gerc(alpha: Self, x: &BlasVector<Self>, y: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

macro_rules! ger_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $ger_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(alpha: $t, x: &BlasVector<$t>, y: &BlasVector<$t>, a: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix_vector::ll::$ger_fn(a.order(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_ptr().as_c_ptr(), y.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

ger_impl!(Ger, ger, f32,       cblas_sger)
ger_impl!(Ger, ger, f64,       cblas_dger)
ger_impl!(Ger, ger, Complex32, cblas_cgeru)
ger_impl!(Ger, ger, Complex64, cblas_zgeru)

ger_impl!(Gerc, gerc, Complex32, cblas_cgerc)
ger_impl!(Gerc, gerc, Complex64, cblas_zgerc)

pub trait Her {
    fn her(symmetry: Symmetry, alpha: Self, x: &BlasVector<Complex<Self>>, a: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! her_impl(
    ($t: ty, $her_fn: ident) => (
        impl Her for $t {
            fn her(symmetry: Symmetry, alpha: $t, x: &BlasVector<Complex<$t>>, a: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix_vector::ll::$her_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

her_impl!(f32, cblas_cher)
her_impl!(f64, cblas_zher)
<commit_msg>Add Syr trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use attribute::Symmetry;
use matrix::{BlasMatrix};
use matrix_vector;
use pointer::CPtr;
use scalar::Scalar;
use vector::BlasVector;

pub trait Gemv {
    fn gemv(alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! gemv_impl(
    ($t: ty, $gemv_fn: ident) => (
        impl Gemv for $t {
            fn gemv(alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$gemv_fn(a.order(), a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

gemv_impl!(f32,       cblas_sgemv)
gemv_impl!(f64,       cblas_dgemv)
gemv_impl!(Complex32, cblas_cgemv)
gemv_impl!(Complex64, cblas_zgemv)

pub trait Symv {
    fn symv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

pub trait Hemv {
    fn hemv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! symv_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symv_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$symv_fn(a.order(), symmetry,
                        a.rows(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

symv_impl!(Symv, symv, f32,       cblas_ssymv)
symv_impl!(Symv, symv, f64,       cblas_dsymv)
symv_impl!(Symv, symv, Complex32, cblas_csymv)
symv_impl!(Symv, symv, Complex64, cblas_zsymv)

symv_impl!(Hemv, hemv, Complex32, cblas_chemv)
symv_impl!(Hemv, hemv, Complex64, cblas_zhemv)

pub trait Ger {
    fn ger(alpha: Self, x: &BlasVector<Self>, y: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

pub trait Gerc {
    fn gerc(alpha: Self, x: &BlasVector<Self>, y: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

macro_rules! ger_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $ger_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(alpha: $t, x: &BlasVector<$t>, y: &BlasVector<$t>, a: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix_vector::ll::$ger_fn(a.order(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_ptr().as_c_ptr(), y.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

ger_impl!(Ger, ger, f32,       cblas_sger)
ger_impl!(Ger, ger, f64,       cblas_dger)
ger_impl!(Ger, ger, Complex32, cblas_cgeru)
ger_impl!(Ger, ger, Complex64, cblas_zgeru)

ger_impl!(Gerc, gerc, Complex32, cblas_cgerc)
ger_impl!(Gerc, gerc, Complex64, cblas_zgerc)

pub trait Her {
    fn her(symmetry: Symmetry, alpha: Self, x: &BlasVector<Complex<Self>>, a: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! her_impl(
    ($t: ty, $her_fn: ident) => (
        impl Her for $t {
            fn her(symmetry: Symmetry, alpha: $t, x: &BlasVector<Complex<$t>>, a: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix_vector::ll::$her_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

her_impl!(f32, cblas_cher)
her_impl!(f64, cblas_zher)

pub trait Syr {
    fn syr(symmetry: Symmetry, alpha: Self, x: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

macro_rules! syr_impl(
    ($t: ty, $syr_fn: ident) => (
        impl Syr for $t {
            fn syr(symmetry: Symmetry, alpha: $t, x: &BlasVector<$t>, a: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix_vector::ll::$syr_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

syr_impl!(f32, cblas_ssyr)
syr_impl!(f64, cblas_dsyr)
<|endoftext|>