<commit_before>/// This list represents the default file types that ripgrep ships with. In
/// general, any file format is fair game, although it should generally be
/// limited to reasonably popular open formats. For other cases, you can add
/// types to each invocation of ripgrep with the '--type-add' flag.
///
/// If you would like to add or improve this list, please file a PR:
/// https://github.com/BurntSushi/ripgrep
///
/// Please try to keep this list sorted lexicographically and wrapped to 79
/// columns (inclusive).
#[rustfmt::skip]
pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
    ("agda", &["*.agda", "*.lagda"]),
    ("aidl", &["*.aidl"]),
    ("amake", &["*.mk", "*.bp"]),
    ("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
    ("asm", &["*.asm", "*.s", "*.S"]),
    ("asp", &[
        "*.aspx", "*.aspx.cs", "*.aspx.cs", "*.ascx", "*.ascx.cs", "*.ascx.vb",
    ]),
    ("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]),
    ("avro", &["*.avdl", "*.avpr", "*.avsc"]),
    ("awk", &["*.awk"]),
    ("bazel", &["*.bzl", "WORKSPACE", "BUILD", "BUILD.bazel"]),
    ("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
    ("brotli", &["*.br"]),
    ("buildstream", &["*.bst"]),
    ("bzip2", &["*.bz2", "*.tbz2"]),
    ("c", &["*.[chH]", "*.[chH].in", "*.cats"]),
    ("cabal", &["*.cabal"]),
    ("cbor", &["*.cbor"]),
    ("ceylon", &["*.ceylon"]),
    ("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
    ("cmake", &["*.cmake", "CMakeLists.txt"]),
    ("coffeescript", &["*.coffee"]),
    ("config", &["*.cfg", "*.conf", "*.config", "*.ini"]),
    ("coq", &["*.v"]),
    ("cpp", &[
        "*.[ChH]", "*.cc", "*.[ch]pp", "*.[ch]xx", "*.hh",  "*.inl",
        "*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in",
    ]),
    ("creole", &["*.creole"]),
    ("crystal", &["Projectfile", "*.cr"]),
    ("cs", &["*.cs"]),
    ("csharp", &["*.cs"]),
    ("cshtml", &["*.cshtml"]),
    ("css", &["*.css", "*.scss"]),
    ("csv", &["*.csv"]),
    ("cython", &["*.pyx", "*.pxi", "*.pxd"]),
    ("d", &["*.d"]),
    ("dart", &["*.dart"]),
    ("dhall", &["*.dhall"]),
    ("diff", &["*.patch", "*.diff"]),
    ("docker", &["*Dockerfile*"]),
    ("dvc", &["Dvcfile", "*.dvc"]),
    ("ebuild", &["*.ebuild"]),
    ("edn", &["*.edn"]),
    ("elisp", &["*.el"]),
    ("elixir", &["*.ex", "*.eex", "*.exs"]),
    ("elm", &["*.elm"]),
    ("erb", &["*.erb"]),
    ("erlang", &["*.erl", "*.hrl"]),
    ("fidl", &["*.fidl"]),
    ("fish", &["*.fish"]),
    ("flatbuffers", &["*.fbs"]),
    ("fortran", &[
        "*.f", "*.F", "*.f77", "*.F77", "*.pfo",
        "*.f90", "*.F90", "*.f95", "*.F95",
    ]),
    ("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
    ("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
    ("gn", &["*.gn", "*.gni"]),
    ("go", &["*.go"]),
    ("gradle", &["*.gradle"]),
    ("groovy", &["*.groovy", "*.gradle"]),
    ("gzip", &["*.gz", "*.tgz"]),
    ("h", &["*.h", "*.hpp"]),
    ("haml", &["*.haml"]),
    ("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]),
    ("hbs", &["*.hbs"]),
    ("hs", &["*.hs", "*.lhs"]),
    ("html", &["*.htm", "*.html", "*.ejs"]),
    ("idris", &["*.idr", "*.lidr"]),
    ("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]),
    ("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
    ("jl", &["*.jl"]),
    ("js", &["*.js", "*.jsx", "*.vue"]),
    ("json", &["*.json", "composer.lock"]),
    ("jsonl", &["*.jsonl"]),
    ("julia", &["*.jl"]),
    ("jupyter", &["*.ipynb", "*.jpynb"]),
    ("k", &["*.k"]),
    ("kotlin", &["*.kt", "*.kts"]),
    ("less", &["*.less"]),
    ("license", &[
        // General
        "COPYING", "COPYING[.-]*",
        "COPYRIGHT", "COPYRIGHT[.-]*",
        "EULA", "EULA[.-]*",
        "licen[cs]e", "licen[cs]e.*",
        "LICEN[CS]E", "LICEN[CS]E[.-]*", "*[.-]LICEN[CS]E*",
        "NOTICE", "NOTICE[.-]*",
        "PATENTS", "PATENTS[.-]*",
        "UNLICEN[CS]E", "UNLICEN[CS]E[.-]*",
        // GPL (gpl.txt, etc.)
        "agpl[.-]*",
        "gpl[.-]*",
        "lgpl[.-]*",
        // Other license-specific (APACHE-2.0.txt, etc.)
        "AGPL-*[0-9]*",
        "APACHE-*[0-9]*",
        "BSD-*[0-9]*",
        "CC-BY-*",
        "GFDL-*[0-9]*",
        "GNU-*[0-9]*",
        "GPL-*[0-9]*",
        "LGPL-*[0-9]*",
        "MIT-*[0-9]*",
        "MPL-*[0-9]*",
        "OFL-*[0-9]*",
    ]),
    ("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
    ("lock", &["*.lock", "package-lock.json"]),
    ("log", &["*.log"]),
    ("lua", &["*.lua"]),
    ("lz4", &["*.lz4"]),
    ("lzma", &["*.lzma"]),
    ("m4", &["*.ac", "*.m4"]),
    ("make", &[
        "[Gg][Nn][Uu]makefile", "[Mm]akefile",
        "[Gg][Nn][Uu]makefile.am", "[Mm]akefile.am",
        "[Gg][Nn][Uu]makefile.in", "[Mm]akefile.in",
        "*.mk", "*.mak"
    ]),
    ("mako", &["*.mako", "*.mao"]),
    ("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]),
    ("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
    ("matlab", &["*.m"]),
    ("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
    ("meson", &["meson.build", "meson_options.txt"]),
    ("mk", &["mkfile"]),
    ("ml", &["*.ml"]),
    ("msbuild", &[
        "*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets",
    ]),
    ("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]),
    ("nix", &["*.nix"]),
    ("objc", &["*.h", "*.m"]),
    ("objcpp", &["*.h", "*.mm"]),
    ("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
    ("org", &["*.org", "*.org_archive"]),
    ("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]),
    ("pdf", &["*.pdf"]),
    ("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]),
    ("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
    ("pod", &["*.pod"]),
    ("postscript", &["*.eps", "*.ps"]),
    ("protobuf", &["*.proto"]),
    ("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
    ("puppet", &["*.erb", "*.pp", "*.rb"]),
    ("purs", &["*.purs"]),
    ("py", &["*.py"]),
    ("qmake", &["*.pro", "*.pri", "*.prf"]),
    ("qml", &["*.qml"]),
    ("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
    ("racket", &["*.rkt"]),
    ("rdoc", &["*.rdoc"]),
    ("readme", &["README*", "*README"]),
    ("robot", &["*.robot"]),
    ("rst", &["*.rst"]),
    ("ruby", &["Gemfile", "*.gemspec", ".irbrc", "Rakefile", "*.rb"]),
    ("rust", &["*.rs"]),
    ("sass", &["*.sass", "*.scss"]),
    ("scala", &["*.scala", "*.sbt"]),
    ("sh", &[
        // Portable/misc. init files
        ".login", ".logout", ".profile", "profile",
        // bash-specific init files
        ".bash_login", "bash_login",
        ".bash_logout", "bash_logout",
        ".bash_profile", "bash_profile",
        ".bashrc", "bashrc", "*.bashrc",
        // csh-specific init files
        ".cshrc", "*.cshrc",
        // ksh-specific init files
        ".kshrc", "*.kshrc",
        // tcsh-specific init files
        ".tcshrc",
        // zsh-specific init files
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        // Extensions
        "*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh", "*.zsh",
    ]),
    ("slim", &["*.skim", "*.slim", "*.slime"]),
    ("smarty", &["*.tpl"]),
    ("sml", &["*.sml", "*.sig"]),
    ("soy", &["*.soy"]),
    ("spark", &["*.spark"]),
    ("spec", &["*.spec"]),
    ("sql", &["*.sql", "*.psql"]),
    ("stylus", &["*.styl"]),
    ("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
    ("svg", &["*.svg"]),
    ("swift", &["*.swift"]),
    ("swig", &["*.def", "*.i"]),
    ("systemd", &[
        "*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path",
        "*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target",
        "*.timer",
    ]),
    ("taskpaper", &["*.taskpaper"]),
    ("tcl", &["*.tcl"]),
    ("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]),
    ("textile", &["*.textile"]),
    ("tf", &["*.tf"]),
    ("thrift", &["*.thrift"]),
    ("toml", &["*.toml", "Cargo.lock"]),
    ("ts", &["*.ts", "*.tsx"]),
    ("twig", &["*.twig"]),
    ("txt", &["*.txt"]),
    ("typoscript", &["*.typoscript", "*.ts"]),
    ("vala", &["*.vala"]),
    ("vb", &["*.vb"]),
    ("vcl", &["*.vcl"]),
    ("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]),
    ("vhdl", &["*.vhd", "*.vhdl"]),
    ("vim", &["*.vim"]),
    ("vimscript", &["*.vim"]),
    ("webidl", &["*.idl", "*.webidl", "*.widl"]),
    ("wiki", &["*.mediawiki", "*.wiki"]),
    ("xml", &[
        "*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb",
        "*.rng", "*.sch", "*.xhtml",
    ]),
    ("xz", &["*.xz", "*.txz"]),
    ("yacc", &["*.y"]),
    ("yaml", &["*.yaml", "*.yml"]),
    ("z", &["*.Z"]),
    ("zig", &["*.zig"]),
    ("zsh", &[
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        "*.zsh",
    ]),
    ("zstd", &["*.zst", "*.zstd"]),
];
<commit_msg>ignore/types: add a type for minified files<commit_after>/// This list represents the default file types that ripgrep ships with. In
/// general, any file format is fair game, although it should generally be
/// limited to reasonably popular open formats. For other cases, you can add
/// types to each invocation of ripgrep with the '--type-add' flag.
///
/// If you would like to add or improve this list, please file a PR:
/// https://github.com/BurntSushi/ripgrep
///
/// Please try to keep this list sorted lexicographically and wrapped to 79
/// columns (inclusive).
#[rustfmt::skip]
pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
    ("agda", &["*.agda", "*.lagda"]),
    ("aidl", &["*.aidl"]),
    ("amake", &["*.mk", "*.bp"]),
    ("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
    ("asm", &["*.asm", "*.s", "*.S"]),
    ("asp", &[
        "*.aspx", "*.aspx.cs", "*.aspx.cs", "*.ascx", "*.ascx.cs", "*.ascx.vb",
    ]),
    ("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]),
    ("avro", &["*.avdl", "*.avpr", "*.avsc"]),
    ("awk", &["*.awk"]),
    ("bazel", &["*.bzl", "WORKSPACE", "BUILD", "BUILD.bazel"]),
    ("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
    ("brotli", &["*.br"]),
    ("buildstream", &["*.bst"]),
    ("bzip2", &["*.bz2", "*.tbz2"]),
    ("c", &["*.[chH]", "*.[chH].in", "*.cats"]),
    ("cabal", &["*.cabal"]),
    ("cbor", &["*.cbor"]),
    ("ceylon", &["*.ceylon"]),
    ("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
    ("cmake", &["*.cmake", "CMakeLists.txt"]),
    ("coffeescript", &["*.coffee"]),
    ("config", &["*.cfg", "*.conf", "*.config", "*.ini"]),
    ("coq", &["*.v"]),
    ("cpp", &[
        "*.[ChH]", "*.cc", "*.[ch]pp", "*.[ch]xx", "*.hh",  "*.inl",
        "*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in",
    ]),
    ("creole", &["*.creole"]),
    ("crystal", &["Projectfile", "*.cr"]),
    ("cs", &["*.cs"]),
    ("csharp", &["*.cs"]),
    ("cshtml", &["*.cshtml"]),
    ("css", &["*.css", "*.scss"]),
    ("csv", &["*.csv"]),
    ("cython", &["*.pyx", "*.pxi", "*.pxd"]),
    ("d", &["*.d"]),
    ("dart", &["*.dart"]),
    ("dhall", &["*.dhall"]),
    ("diff", &["*.patch", "*.diff"]),
    ("docker", &["*Dockerfile*"]),
    ("dvc", &["Dvcfile", "*.dvc"]),
    ("ebuild", &["*.ebuild"]),
    ("edn", &["*.edn"]),
    ("elisp", &["*.el"]),
    ("elixir", &["*.ex", "*.eex", "*.exs"]),
    ("elm", &["*.elm"]),
    ("erb", &["*.erb"]),
    ("erlang", &["*.erl", "*.hrl"]),
    ("fidl", &["*.fidl"]),
    ("fish", &["*.fish"]),
    ("flatbuffers", &["*.fbs"]),
    ("fortran", &[
        "*.f", "*.F", "*.f77", "*.F77", "*.pfo",
        "*.f90", "*.F90", "*.f95", "*.F95",
    ]),
    ("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
    ("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
    ("gn", &["*.gn", "*.gni"]),
    ("go", &["*.go"]),
    ("gradle", &["*.gradle"]),
    ("groovy", &["*.groovy", "*.gradle"]),
    ("gzip", &["*.gz", "*.tgz"]),
    ("h", &["*.h", "*.hpp"]),
    ("haml", &["*.haml"]),
    ("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]),
    ("hbs", &["*.hbs"]),
    ("hs", &["*.hs", "*.lhs"]),
    ("html", &["*.htm", "*.html", "*.ejs"]),
    ("idris", &["*.idr", "*.lidr"]),
    ("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]),
    ("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
    ("jl", &["*.jl"]),
    ("js", &["*.js", "*.jsx", "*.vue"]),
    ("json", &["*.json", "composer.lock"]),
    ("jsonl", &["*.jsonl"]),
    ("julia", &["*.jl"]),
    ("jupyter", &["*.ipynb", "*.jpynb"]),
    ("k", &["*.k"]),
    ("kotlin", &["*.kt", "*.kts"]),
    ("less", &["*.less"]),
    ("license", &[
        // General
        "COPYING", "COPYING[.-]*",
        "COPYRIGHT", "COPYRIGHT[.-]*",
        "EULA", "EULA[.-]*",
        "licen[cs]e", "licen[cs]e.*",
        "LICEN[CS]E", "LICEN[CS]E[.-]*", "*[.-]LICEN[CS]E*",
        "NOTICE", "NOTICE[.-]*",
        "PATENTS", "PATENTS[.-]*",
        "UNLICEN[CS]E", "UNLICEN[CS]E[.-]*",
        // GPL (gpl.txt, etc.)
        "agpl[.-]*",
        "gpl[.-]*",
        "lgpl[.-]*",
        // Other license-specific (APACHE-2.0.txt, etc.)
        "AGPL-*[0-9]*",
        "APACHE-*[0-9]*",
        "BSD-*[0-9]*",
        "CC-BY-*",
        "GFDL-*[0-9]*",
        "GNU-*[0-9]*",
        "GPL-*[0-9]*",
        "LGPL-*[0-9]*",
        "MIT-*[0-9]*",
        "MPL-*[0-9]*",
        "OFL-*[0-9]*",
    ]),
    ("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
    ("lock", &["*.lock", "package-lock.json"]),
    ("log", &["*.log"]),
    ("lua", &["*.lua"]),
    ("lz4", &["*.lz4"]),
    ("lzma", &["*.lzma"]),
    ("m4", &["*.ac", "*.m4"]),
    ("make", &[
        "[Gg][Nn][Uu]makefile", "[Mm]akefile",
        "[Gg][Nn][Uu]makefile.am", "[Mm]akefile.am",
        "[Gg][Nn][Uu]makefile.in", "[Mm]akefile.in",
        "*.mk", "*.mak"
    ]),
    ("mako", &["*.mako", "*.mao"]),
    ("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]),
    ("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
    ("matlab", &["*.m"]),
    ("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
    ("meson", &["meson.build", "meson_options.txt"]),
    ("minified", &["*.min.html", "*.min.css", "*.min.js"]),
    ("mk", &["mkfile"]),
    ("ml", &["*.ml"]),
    ("msbuild", &[
        "*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets",
    ]),
    ("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]),
    ("nix", &["*.nix"]),
    ("objc", &["*.h", "*.m"]),
    ("objcpp", &["*.h", "*.mm"]),
    ("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
    ("org", &["*.org", "*.org_archive"]),
    ("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]),
    ("pdf", &["*.pdf"]),
    ("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]),
    ("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
    ("pod", &["*.pod"]),
    ("postscript", &["*.eps", "*.ps"]),
    ("protobuf", &["*.proto"]),
    ("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
    ("puppet", &["*.erb", "*.pp", "*.rb"]),
    ("purs", &["*.purs"]),
    ("py", &["*.py"]),
    ("qmake", &["*.pro", "*.pri", "*.prf"]),
    ("qml", &["*.qml"]),
    ("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
    ("racket", &["*.rkt"]),
    ("rdoc", &["*.rdoc"]),
    ("readme", &["README*", "*README"]),
    ("robot", &["*.robot"]),
    ("rst", &["*.rst"]),
    ("ruby", &["Gemfile", "*.gemspec", ".irbrc", "Rakefile", "*.rb"]),
    ("rust", &["*.rs"]),
    ("sass", &["*.sass", "*.scss"]),
    ("scala", &["*.scala", "*.sbt"]),
    ("sh", &[
        // Portable/misc. init files
        ".login", ".logout", ".profile", "profile",
        // bash-specific init files
        ".bash_login", "bash_login",
        ".bash_logout", "bash_logout",
        ".bash_profile", "bash_profile",
        ".bashrc", "bashrc", "*.bashrc",
        // csh-specific init files
        ".cshrc", "*.cshrc",
        // ksh-specific init files
        ".kshrc", "*.kshrc",
        // tcsh-specific init files
        ".tcshrc",
        // zsh-specific init files
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        // Extensions
        "*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh", "*.zsh",
    ]),
    ("slim", &["*.skim", "*.slim", "*.slime"]),
    ("smarty", &["*.tpl"]),
    ("sml", &["*.sml", "*.sig"]),
    ("soy", &["*.soy"]),
    ("spark", &["*.spark"]),
    ("spec", &["*.spec"]),
    ("sql", &["*.sql", "*.psql"]),
    ("stylus", &["*.styl"]),
    ("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
    ("svg", &["*.svg"]),
    ("swift", &["*.swift"]),
    ("swig", &["*.def", "*.i"]),
    ("systemd", &[
        "*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path",
        "*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target",
        "*.timer",
    ]),
    ("taskpaper", &["*.taskpaper"]),
    ("tcl", &["*.tcl"]),
    ("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]),
    ("textile", &["*.textile"]),
    ("tf", &["*.tf"]),
    ("thrift", &["*.thrift"]),
    ("toml", &["*.toml", "Cargo.lock"]),
    ("ts", &["*.ts", "*.tsx"]),
    ("twig", &["*.twig"]),
    ("txt", &["*.txt"]),
    ("typoscript", &["*.typoscript", "*.ts"]),
    ("vala", &["*.vala"]),
    ("vb", &["*.vb"]),
    ("vcl", &["*.vcl"]),
    ("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]),
    ("vhdl", &["*.vhd", "*.vhdl"]),
    ("vim", &["*.vim"]),
    ("vimscript", &["*.vim"]),
    ("webidl", &["*.idl", "*.webidl", "*.widl"]),
    ("wiki", &["*.mediawiki", "*.wiki"]),
    ("xml", &[
        "*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb",
        "*.rng", "*.sch", "*.xhtml",
    ]),
    ("xz", &["*.xz", "*.txz"]),
    ("yacc", &["*.y"]),
    ("yaml", &["*.yaml", "*.yml"]),
    ("z", &["*.Z"]),
    ("zig", &["*.zig"]),
    ("zsh", &[
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        "*.zsh",
    ]),
    ("zstd", &["*.zst", "*.zstd"]),
];
<|endoftext|>


<commit_before>use cap::{CPoolHalf, Cap, CPool, CapWriteObject, CapReadObject};
use util::{SharedReadGuard, SharedWriteGuard, RefGuard, RefMutGuard, IndexedSharedReadGuard, IndexedSharedWriteGuard, Streamer};
use core::ops::{Deref, DerefMut};
use core::marker::{PhantomData};

pub struct CapFull<Half, M> {
    half: Half,
    mdbs: M,
    deleted: bool,
}

impl<Half, M> CapFull<Half, M> {
    pub fn new(half: Half, mdbs: M) -> Self {
        CapFull {
            half: half,
            mdbs: mdbs,
            deleted: false,
        }
    }

    pub fn mark_deleted(&mut self) {
        self.deleted = true;
    }
}

impl<Half, M> Deref for CapFull<Half, M> {
    type Target = Half;
    fn deref(&self) -> &Half {
        &self.half
    }
}

impl<Half, M> DerefMut for CapFull<Half, M> {
    fn deref_mut(&mut self) -> &mut Half {
        &mut self.half
    }
}

impl<Half, M> Drop for CapFull<Half, M> {
    fn drop(&mut self) {
        assert!(self.deleted, "attempt to drop unmarked CapFull.");
    }
}

#[derive(Clone)]
pub struct MDBAddr {
    cpool: CPoolHalf,
    cpool_index: u8,
    mdb_index: usize,
}

pub struct MDB<'a> {
    this: Option<MDBAddr>,
    first_child: Option<MDBAddr>,
    parent: Option<MDBAddr>,
    prev: Option<MDBAddr>,
    next: Option<MDBAddr>,
    holding_parent: Option<&'a mut MDB<'a>>
}

impl<'a> MDB<'a> {
    pub fn derive(&'a mut self) -> MDB<'a> {
        MDB {
            this: None,
            first_child: None,
            parent: None,
            next: None,
            prev: None,
            holding_parent: Some(self),
        }
    }

    fn match_mdbs<'b>(cap: &'b mut Cap<'a>) -> &'b mut [MDB<'a>] {
        match cap {
            &mut Cap::CPool(ref mut cpool) => {
                &mut cpool.mdbs
            }
        }
    }

    pub unsafe fn set(&mut self, addr: MDBAddr) {
        self.this = Some(addr.clone());

        // Update prev
        if self.prev.is_some() {
            let mut prev = self.prev.clone().unwrap();
            let mut full_option = prev.cpool.write(prev.cpool_index);
            let full = full_option.as_mut().unwrap();
            let ref mut mdbs = Self::match_mdbs(full);
            mdbs[prev.mdb_index].next = Some(addr.clone());
        }

        // Update children
        let mut current_child_option = self.first_child.clone();
        while current_child_option.is_some() {
            let mut current_child = current_child_option.clone().unwrap();
            let mut full_option = current_child.cpool.write(current_child.cpool_index);
            let full = full_option.as_mut().unwrap();
            let ref mut mdbs = Self::match_mdbs(full);
            mdbs[current_child.mdb_index].parent = Some(addr.clone());
            current_child_option = mdbs[current_child.mdb_index].next.clone();
        }

        // Update next
        if self.next.is_some() {
            let mut next = self.next.clone().unwrap();
            let mut full_option = next.cpool.write(next.cpool_index);
            let full = full_option.as_mut().unwrap();
            let ref mut mdbs = Self::match_mdbs(full);
            mdbs[next.mdb_index].prev = Some(addr.clone());
        }

        // If holding_parent exists, then insert this to holding parent.
        if self.holding_parent.is_some() {
            let holding_parent = self.holding_parent.take().unwrap();
            if holding_parent.first_child.is_some() {
                let mut first_child = holding_parent.first_child.clone().unwrap();
                let mut full_option = first_child.cpool.write(first_child.cpool_index);
                let full = full_option.as_mut().unwrap();
                let ref mut mdbs = Self::match_mdbs(full);
                mdbs[first_child.mdb_index].prev = Some(addr.clone());
            }
            self.next = holding_parent.first_child.clone();
            self.parent = holding_parent.this.clone();
            holding_parent.first_child = Some(addr.clone());
        }
    }
}

// pub struct MDBChildIter<'a> {
//     next_child: Option<MDBAddr>,
//     current_cpool: &'a CPool<'a>,
//     current_cpool_half: CPoolHalf,
// }

// impl<'a> Streamer<'a> for MDBChildIter<'a> {
//     type Item = RefGuard<'a, Option<Cap<'a>>, IndexedSharedReadGuard<'a, Option<Cap<'a>>, usize, CPool<'a>>>;

//     fn next(&'a mut self) -> Option<Self::Item> {
//         if self.next_child.is_some() {
//             let next_child = self.next_child.take().unwrap();
//             if next_child.cpool == self.current_cpool_half {
//                 {
//                     let cpool = self.current_cpool;
//                     let ref mdb = cpool[next_child.cpool_index as usize].as_ref().unwrap().mdbs()[next_child.mdb_index];
//                     self.next_child = mdb.next.clone();
//                 }
//                 Some(RefGuard::Ref(&self.current_cpool[next_child.cpool_index as usize]))
//             } else {
//                 {
//                     let cpool = next_child.cpool.read();
//                     let ref mdb = cpool[next_child.cpool_index as usize].as_ref().unwrap().mdbs()[next_child.mdb_index];
//                     self.next_child = mdb.next.clone();
//                 }
//                 Some(RefGuard::Guard(IndexedSharedReadGuard::new(
//                     next_child.cpool.read(),
//                     next_child.cpool_index as usize
//                 )))
//             }
//         } else {
//             None
//         }
//     }
// }

// pub struct MDBChildIterMut<'a> {
//     next_child: Option<MDBAddr>,
//     current_cpool: &'a mut CPool<'a>,
//     current_cpool_half: CPoolHalf,
// }

// impl<'a> Streamer<'a> for MDBChildIterMut<'a> {
//     type Item = RefMutGuard<'a, Option<Cap<'a>>, IndexedSharedWriteGuard<'a, Option<Cap<'a>>, usize, CPool<'a>>>;

//     fn next(&'a mut self) -> Option<Self::Item> {
//         if self.next_child.is_some() {
//             let mut next_child = self.next_child.take().unwrap();
//             if next_child.cpool == self.current_cpool_half {
//                 {
//                     let ref cpool = self.current_cpool;
//                     let ref mdb = cpool[next_child.cpool_index as usize].as_ref().unwrap().mdbs()[next_child.mdb_index];
//                     self.next_child = mdb.next.clone();
//                 }
//                 let full = &mut self.current_cpool[next_child.cpool_index as usize];
//                 Some(RefMutGuard::Ref(full))
//             } else {
//                 {
//                     let cpool = next_child.cpool.read();
//                     let ref mdb = cpool[next_child.cpool_index as usize].as_ref().unwrap().mdbs()[next_child.mdb_index];
//                     self.next_child = mdb.next.clone();
//                 }
//                 Some(RefMutGuard::Guard(IndexedSharedWriteGuard::new(
//                     next_child.cpool.write(),
//                     next_child.cpool_index as usize
//                 )))
//             }
//         } else {
//             None
//         }
//     }
// }
<commit_msg>WIP: Finish MDB Iterators<commit_after>use cap::{CPoolHalf, Cap, CPool, CapWriteObject, CapReadObject};
use util::{SharedReadGuard, SharedWriteGuard, RefGuard, RefMutGuard, IndexedSharedReadGuard, IndexedSharedWriteGuard};
use core::ops::{Deref, DerefMut};
use core::marker::{PhantomData};

pub struct CapFull<Half, M> {
    half: Half,
    mdbs: M,
    deleted: bool,
}

impl<Half, M> CapFull<Half, M> {
    pub fn new(half: Half, mdbs: M) -> Self {
        CapFull {
            half: half,
            mdbs: mdbs,
            deleted: false,
        }
    }

    pub fn mark_deleted(&mut self) {
        self.deleted = true;
    }
}

impl<Half, M> Deref for CapFull<Half, M> {
    type Target = Half;
    fn deref(&self) -> &Half {
        &self.half
    }
}

impl<Half, M> DerefMut for CapFull<Half, M> {
    fn deref_mut(&mut self) -> &mut Half {
        &mut self.half
    }
}

impl<Half, M> Drop for CapFull<Half, M> {
    fn drop(&mut self) {
        assert!(self.deleted, "attempt to drop unmarked CapFull.");
    }
}

#[derive(Clone)]
pub struct MDBAddr {
    cpool: CPoolHalf,
    cpool_index: u8,
    mdb_index: usize,
}

pub struct MDB<'a> {
    this: Option<MDBAddr>,
    first_child: Option<MDBAddr>,
    parent: Option<MDBAddr>,
    prev: Option<MDBAddr>,
    next: Option<MDBAddr>,
    holding_parent: Option<&'a mut MDB<'a>>
}

fn match_mdbs_mut<'a, 'b>(cap: &'b mut Cap<'a>) -> &'b mut [MDB<'a>] {
    match cap {
        &mut Cap::CPool(ref mut cpool) => {
            &mut cpool.mdbs
        }
    }
}

fn match_mdbs<'a, 'b>(cap: &'b Cap<'a>) -> &'b [MDB<'a>] {
    match cap {
        &Cap::CPool(ref cpool) => {
            &cpool.mdbs
        }
    }
}

impl<'a> MDB<'a> {
    pub fn derive(&'a mut self) -> MDB<'a> {
        MDB {
            this: None,
            first_child: None,
            parent: None,
            next: None,
            prev: None,
            holding_parent: Some(self),
        }
    }

    pub unsafe fn set(&mut self, addr: MDBAddr) {
        self.this = Some(addr.clone());

        // Update prev
        if self.prev.is_some() {
            let mut prev = self.prev.clone().unwrap();
            let mut full_option = prev.cpool.write(prev.cpool_index);
            let full = full_option.as_mut().unwrap();
            let ref mut mdbs = match_mdbs_mut(full);
            mdbs[prev.mdb_index].next = Some(addr.clone());
        }

        // Update children
        let mut current_child_option = self.first_child.clone();
        while current_child_option.is_some() {
            let mut current_child = current_child_option.clone().unwrap();
            let mut full_option = current_child.cpool.write(current_child.cpool_index);
            let full = full_option.as_mut().unwrap();
            let ref mut mdbs = match_mdbs_mut(full);
            mdbs[current_child.mdb_index].parent = Some(addr.clone());
            current_child_option = mdbs[current_child.mdb_index].next.clone();
        }

        // Update next
        if self.next.is_some() {
            let mut next = self.next.clone().unwrap();
            let mut full_option = next.cpool.write(next.cpool_index);
            let full = full_option.as_mut().unwrap();
            let ref mut mdbs = match_mdbs_mut(full);
            mdbs[next.mdb_index].prev = Some(addr.clone());
        }

        // If holding_parent exists, then insert this to holding parent.
        if self.holding_parent.is_some() {
            let holding_parent = self.holding_parent.take().unwrap();
            if holding_parent.first_child.is_some() {
                let mut first_child = holding_parent.first_child.clone().unwrap();
                let mut full_option = first_child.cpool.write(first_child.cpool_index);
                let full = full_option.as_mut().unwrap();
                let ref mut mdbs = match_mdbs_mut(full);
                mdbs[first_child.mdb_index].prev = Some(addr.clone());
            }
            self.next = holding_parent.first_child.clone();
            self.parent = holding_parent.this.clone();
            holding_parent.first_child = Some(addr.clone());
        }
    }
}

pub struct MDBChildIter<'a> {
    next_child: Option<MDBAddr>,
    _marker: PhantomData<Option<Cap<'a>>>
}

impl<'a> Iterator for MDBChildIter<'a> {
    type Item = SharedReadGuard<'a, Option<Cap<'a>>>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_child.is_some() {
            let next_child = self.next_child.take().unwrap();
            let full_option = next_child.cpool.read(next_child.cpool_index);
            {
                let full = full_option.as_ref().unwrap();
                let ref mdbs = match_mdbs(full);
                self.next_child = mdbs[next_child.mdb_index].next.clone();
            }
            Some(full_option)
        } else {
            None
        }
    }
}

pub struct MDBChildIterMut<'a> {
    next_child: Option<MDBAddr>,
    _marker: PhantomData<Option<Cap<'a>>>
}

impl<'a> Iterator for MDBChildIterMut<'a> {
    type Item = SharedWriteGuard<'a, Option<Cap<'a>>>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_child.is_some() {
            let mut next_child = self.next_child.take().unwrap();
            let full_option = next_child.cpool.write(next_child.cpool_index);
            {
                let full = full_option.as_ref().unwrap();
                let ref mdbs = match_mdbs(full);
                self.next_child = mdbs[next_child.mdb_index].next.clone();
            }
            Some(full_option)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use radio::song::Song;
use serde_json;
use std::collections::HashMap;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};
use util::logger::log;

/// A map containing songs and their times played,
/// Inserting a song already known will increase its counter
#[derive(Debug)]
pub struct SongMap(HashMap<Song, u8>);

impl SongMap {
    /// Creates a new empty songmap
    fn new() -> Self {
        SongMap(HashMap::new())
    }

    /// Inserts a song into the map
    fn insert(&mut self, key: Song, value: u8) {
        self.0.insert(key, value);
    }

    /// Inserts a song into the map
    /// If known increases its counter instead
    pub fn insert_song(&mut self, song: Song) {
        let counter = self.0.entry(song).or_insert(0);
        *counter += 1;
    }

    /// Saves a map to json
    pub fn save_to_file(&self, dir: &str, name: &str) {
        /// Logs possible errors
        fn save_error(dir: &str, name: &str) {
            log(&format!("ERROR: Could not save {}\\{}.json",dir, name));
        }

        // Create file and directory
        let _ = fs::create_dir_all(dir);
        let to = match File::create(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                save_error(dir, name);
                return
            }
        };
        let mut to = BufWriter::new(to);
        // Since the map contains a non-string key we cannot save it to json
        // straight away, convert it to a save-able format
        let mut string_vec: Vec<SongMapHelper> = Vec::new();
        for (key, value) in self.0.iter() {
            string_vec.push(
                SongMapHelper {
                    artist: key.artist.clone(),
                    title: key.title.clone(),
                    count: *value,
                }
            );
        }
        // Write json to file
        match serde_json::to_writer_pretty(&mut to, &string_vec) {
            Err(_) => {
                save_error(dir, name);
                return
            }
            _ => {},
        }
        // Add a newline, otherwise the json might be invalid
        let _ = to.write(b"\n");
        let _ = to.flush();
    }

    /// Loads a map from json
    pub fn load_from_file(dir: &str, name: &'static str) -> Self {
        /// Logs possible errors
        fn load_error(dir: &str, name: &'static str) {
            log(&format!("ERROR: Could not load {}\\{}.json",dir, name));
        }

        // Create an empty map
        let mut song_map = SongMap::new();
        // Try to open
        let from = match File::open(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                load_error(dir, name);
                return song_map
            }
        };
        let from = BufReader::new(from);
        // Save into a vector of helper
        let string_vec: Vec<SongMapHelper> = match serde_json::from_reader(from) {
            Ok(vec) => vec,
            Err(_) => {
                load_error(dir, name);
                return song_map
            }
        };
        // Convert helper to the actual songmap
        for song_helper in string_vec {
            song_map.insert( Song {
                artist: song_helper.artist,
                title: song_helper.title
            }, song_helper.count);
        }
        song_map
    }
}

/// This is a helper so that the songmap may be saved to json with serde
#[derive(Debug, Serialize, Deserialize)]
struct SongMapHelper {
    artist: String,
    title: String,
    count: u8
}
<commit_msg>Change songmap count from u8 to u16<commit_after>use radio::song::Song;
use serde_json;
use std::collections::HashMap;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};
use util::logger::log;

/// A map containing songs and their times played,
/// Inserting a song already known will increase its counter
#[derive(Debug)]
pub struct SongMap(HashMap<Song, u16>);

impl SongMap {
    /// Creates a new empty songmap
    fn new() -> Self {
        SongMap(HashMap::new())
    }

    /// Inserts a song into the map
    fn insert(&mut self, key: Song, value: u16) {
        self.0.insert(key, value);
    }

    /// Inserts a song into the map
    /// If known increases its counter instead
    pub fn insert_song(&mut self, song: Song) {
        let counter = self.0.entry(song).or_insert(0);
        *counter += 1;
    }

    /// Saves a map to json
    pub fn save_to_file(&self, dir: &str, name: &str) {
        /// Logs possible errors
        fn save_error(dir: &str, name: &str) {
            log(&format!("ERROR: Could not save {}\\{}.json",dir, name));
        }

        // Create file and directory
        let _ = fs::create_dir_all(dir);
        let to = match File::create(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                save_error(dir, name);
                return
            }
        };
        let mut to = BufWriter::new(to);
        // Since the map contains a non-string key we cannot save it to json
        // straight away, convert it to a save-able format
        let mut string_vec: Vec<SongMapHelper> = Vec::new();
        for (key, value) in self.0.iter() {
            string_vec.push(
                SongMapHelper {
                    artist: key.artist.clone(),
                    title: key.title.clone(),
                    count: *value,
                }
            );
        }
        // Write json to file
        match serde_json::to_writer_pretty(&mut to, &string_vec) {
            Err(_) => {
                save_error(dir, name);
                return
            }
            _ => {},
        }
        // Add a newline, otherwise the json might be invalid
        let _ = to.write(b"\n");
        let _ = to.flush();
    }

    /// Loads a map from json
    pub fn load_from_file(dir: &str, name: &'static str) -> Self {
        /// Logs possible errors
        fn load_error(dir: &str, name: &'static str) {
            log(&format!("ERROR: Could not load {}\\{}.json",dir, name));
        }

        // Create an empty map
        let mut song_map = SongMap::new();
        // Try to open
        let from = match File::open(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                load_error(dir, name);
                return song_map
            }
        };
        let from = BufReader::new(from);
        // Save into a vector of helper
        let string_vec: Vec<SongMapHelper> = match serde_json::from_reader(from) {
            Ok(vec) => vec,
            Err(_) => {
                load_error(dir, name);
                return song_map
            }
        };
        // Convert helper to the actual songmap
        for song_helper in string_vec {
            song_map.insert( Song {
                artist: song_helper.artist,
                title: song_helper.title
            }, song_helper.count);
        }
        song_map
    }
}

/// This is a helper so that the songmap may be saved to json with serde
#[derive(Debug, Serialize, Deserialize)]
struct SongMapHelper {
    artist: String,
    title: String,
    count: u16,
}
<|endoftext|>


<commit_before>extern crate time;
extern crate regex;

use std::env;
use std::process;
use regex::Regex;
use std::io::Read;
use std::fs::File;
use time::precise_time_ns;

fn measure(data: String, pattern: String) {
    let mut count = 0;
    let start = precise_time_ns();

    let regex = Regex::new(&pattern).unwrap();
    for captures in regex.captures_iter(&data) {
        count += captures.len();
    }

    let elapse = precise_time_ns() - start;

    println!("{} - {}", elapse as f64 / 1000000.0, count);
}

fn main() {
    if env::args().len() != 2 {
        println!("Usage: benchmark <filename>");
        process::exit(1);
    }

    let mut file = File::open(env::args().nth(1).unwrap()).unwrap();
    let mut data = String::new();

    file.read_to_string(&mut data).unwrap();

    // Email
    measure(data.clone(), r"[\w\.+-]+@[\w\.-]+\.[\w\.-]+".to_string());

    // URI
    measure(data.clone(), r"[\w]+://[^/\s?#]+[^\s?#]+(?:\?[^\s#]*)?(?:#[^\s]*)?".to_string());

    // IP
    measure(data.clone(), r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])".to_string());
}
<commit_msg>Improve Rust benchmark<commit_after>extern crate time;
extern crate regex;

use std::env;
use std::process;
use regex::Regex;
use std::io::Read;
use std::fs::File;
use time::precise_time_ns;

fn measure(data: String, pattern: String) {
    let start = precise_time_ns();

    let regex = Regex::new(&pattern).unwrap();
    let count = regex.find_iter(&data).count();

    let elapse = precise_time_ns() - start;

    println!("{} - {}", elapse as f64 / 1e6, count);
}

fn main() {
    if env::args().len() != 2 {
        println!("Usage: benchmark <filename>");
        process::exit(1);
    }

    let mut file = File::open(env::args().nth(1).unwrap()).unwrap();
    let mut data = String::new();

    file.read_to_string(&mut data).unwrap();

    // Email
    measure(data.clone(), r"[\w\.+-]+@[\w\.-]+\.[\w\.-]+".to_string());

    // URI
    measure(data.clone(), r"[\w]+://[^/\s?#]+[^\s?#]+(?:\?[^\s#]*)?(?:#[^\s]*)?".to_string());

    // IP
    measure(data.clone(), r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])".to_string());
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::index_data::{IndexData, IndexDatum};
use super::buffer::{Buffer, BufferBinding,
                    ArrayBufferBinding, ElementArrayBufferBinding};
use super::types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }

    pub fn draw_arrays_range(&self,
                             mode: DrawingMode,
                             start: u32,
                             length: usize)
    {
        debug_assert!((start as usize) + length <= self.vbo.count);

        unsafe {
            self.gl_buffer.draw_arrays_range(mode, start, length);
        }
    }

    pub fn draw_arrays(&self, mode: DrawingMode) {
        unsafe {
            self.gl_buffer.draw_arrays_range(mode, 0, self.vbo.count);
        }
    }

    pub fn draw_n_elements<I>(&self,
                              mode: DrawingMode,
                              count: usize,
                              indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.gl_buffer.draw_n_elements(mode, count, indicies);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            let ibo = $ibo;

            let gl_buffer = bind_element_array_buffer!($gl, ibo.buffer_mut());
            $crate::IndexBufferBinding::new(gl_buffer, ibo)
        }
    }
}
<commit_msg>Add `VertexBufferBinding.draw_elements()`<commit_after>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::index_data::{IndexData, IndexDatum};
use super::buffer::{Buffer, BufferBinding,
                    ArrayBufferBinding, ElementArrayBufferBinding};
use super::types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }

    pub fn draw_arrays_range(&self,
                             mode: DrawingMode,
                             start: u32,
                             length: usize)
    {
        debug_assert!((start as usize) + length <= self.vbo.count);

        unsafe {
            self.gl_buffer.draw_arrays_range(mode, start, length);
        }
    }

    pub fn draw_arrays(&self, mode: DrawingMode) {
        unsafe {
            self.gl_buffer.draw_arrays_range(mode, 0, self.vbo.count);
        }
    }

    pub fn draw_n_elements<I>(&self,
                              mode: DrawingMode,
                              count: usize,
                              indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.gl_buffer.draw_n_elements(mode, count, indicies);
        }
    }

    pub fn draw_elements<I>(&self,
                            mode: DrawingMode,
                            indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.gl_buffer.draw_elements(mode, indicies);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            let ibo = $ibo;

            let gl_buffer = bind_element_array_buffer!($gl, ibo.buffer_mut());
            $crate::IndexBufferBinding::new(gl_buffer, ibo)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Data structures that represent video format information in virtio video devices.

use std::convert::{From, Into, TryFrom};
use std::fmt::{self, Display};
use std::io;

use base::error;
use data_model::Le32;
use enumn::N;

use crate::virtio::video::command::ReadCmdError;
use crate::virtio::video::protocol::*;
use crate::virtio::video::response::Response;
use crate::virtio::Writer;

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum Profile {
    H264Baseline = VIRTIO_VIDEO_PROFILE_H264_BASELINE,
    H264Main = VIRTIO_VIDEO_PROFILE_H264_MAIN,
    H264Extended = VIRTIO_VIDEO_PROFILE_H264_EXTENDED,
    H264High = VIRTIO_VIDEO_PROFILE_H264_HIGH,
    H264High10 = VIRTIO_VIDEO_PROFILE_H264_HIGH10PROFILE,
    H264High422 = VIRTIO_VIDEO_PROFILE_H264_HIGH422PROFILE,
    H264High444PredictiveProfile = VIRTIO_VIDEO_PROFILE_H264_HIGH444PREDICTIVEPROFILE,
    H264ScalableBaseline = VIRTIO_VIDEO_PROFILE_H264_SCALABLEBASELINE,
    H264ScalableHigh = VIRTIO_VIDEO_PROFILE_H264_SCALABLEHIGH,
    H264StereoHigh = VIRTIO_VIDEO_PROFILE_H264_STEREOHIGH,
    H264MultiviewHigh = VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH,
    HevcMain = VIRTIO_VIDEO_PROFILE_HEVC_MAIN,
    HevcMain10 = VIRTIO_VIDEO_PROFILE_HEVC_MAIN10,
    HevcMainStillPicture = VIRTIO_VIDEO_PROFILE_HEVC_MAIN_STILL_PICTURE,
    VP8Profile0 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE0,
    VP8Profile1 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE1,
    VP8Profile2 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE2,
    VP8Profile3 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE3,
    VP9Profile0 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE0,
    VP9Profile1 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE1,
    VP9Profile2 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE2,
    VP9Profile3 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE3,
}
impl_try_from_le32_for_enumn!(Profile, "profile");

impl Profile {
    pub fn to_format(&self) -> Format {
        use Profile::*;
        match self {
            H264Baseline
            | H264Main
            | H264Extended
            | H264High
            | H264High10
            | H264High422
            | H264High444PredictiveProfile
            | H264ScalableBaseline
            | H264ScalableHigh
            | H264StereoHigh
            | H264MultiviewHigh => Format::H264,
            HevcMain | HevcMain10 | HevcMainStillPicture => Format::HEVC,
            VP8Profile0 | VP8Profile1 | VP8Profile2 | VP8Profile3 => Format::VP8,
            VP9Profile0 | VP9Profile1 | VP9Profile2 | VP9Profile3 => Format::VP9,
        }
    }
}

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum Level {
    H264_1_0 = VIRTIO_VIDEO_LEVEL_H264_1_0,
    H264_1_1 = VIRTIO_VIDEO_LEVEL_H264_1_1,
    H264_1_2 = VIRTIO_VIDEO_LEVEL_H264_1_2,
    H264_1_3 = VIRTIO_VIDEO_LEVEL_H264_1_3,
    H264_2_0 = VIRTIO_VIDEO_LEVEL_H264_2_0,
    H264_2_1 = VIRTIO_VIDEO_LEVEL_H264_2_1,
    H264_2_2 = VIRTIO_VIDEO_LEVEL_H264_2_2,
    H264_3_0 = VIRTIO_VIDEO_LEVEL_H264_3_0,
    H264_3_1 = VIRTIO_VIDEO_LEVEL_H264_3_1,
    H264_3_2 = VIRTIO_VIDEO_LEVEL_H264_3_2,
    H264_4_0 = VIRTIO_VIDEO_LEVEL_H264_4_0,
    H264_4_1 = VIRTIO_VIDEO_LEVEL_H264_4_1,
    H264_4_2 = VIRTIO_VIDEO_LEVEL_H264_4_2,
    H264_5_0 = VIRTIO_VIDEO_LEVEL_H264_5_0,
    H264_5_1 = VIRTIO_VIDEO_LEVEL_H264_5_1,
}
impl_try_from_le32_for_enumn!(Level, "level");

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum Format {
    // Raw formats
    NV12 = VIRTIO_VIDEO_FORMAT_NV12,
    YUV420 = VIRTIO_VIDEO_FORMAT_YUV420,

    // Bitstream formats
    H264 = VIRTIO_VIDEO_FORMAT_H264,
    HEVC = VIRTIO_VIDEO_FORMAT_HEVC,
    VP8 = VIRTIO_VIDEO_FORMAT_VP8,
    VP9 = VIRTIO_VIDEO_FORMAT_VP9,
}
impl_try_from_le32_for_enumn!(Format, "format");

impl Display for Format {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Format::*;
        match self {
            NV12 => write!(f, "NV12"),
            YUV420 => write!(f, "YUV420"),
            H264 => write!(f, "H264"),
            HEVC => write!(f, "HEVC"),
            VP8 => write!(f, "VP8"),
            VP9 => write!(f, "VP9"),
        }
    }
}

#[derive(Debug, Default, Copy, Clone)]
pub struct Crop {
    pub left: u32,
    pub top: u32,
    pub width: u32,
    pub height: u32,
}
impl_from_for_interconvertible_structs!(virtio_video_crop, Crop, left, top, width, height);

#[derive(Debug, Default, Clone, Copy)]
pub struct PlaneFormat {
    pub plane_size: u32,
    pub stride: u32,
}
impl_from_for_interconvertible_structs!(virtio_video_plane_format, PlaneFormat, plane_size, stride);

#[derive(Debug, Default, Clone, Copy)]
pub struct FormatRange {
    pub min: u32,
    pub max: u32,
    pub step: u32,
}
impl_from_for_interconvertible_structs!(virtio_video_format_range, FormatRange, min, max, step);

#[derive(Debug, Default, Clone)]
pub struct FrameFormat {
    pub width: FormatRange,
    pub height: FormatRange,
    pub bitrates: Vec<FormatRange>,
}

impl Response for FrameFormat {
    fn write(&self, w: &mut Writer) -> Result<(), io::Error> {
        w.write_obj(virtio_video_format_frame {
            width: self.width.into(),
            height: self.height.into(),
            num_rates: Le32::from(self.bitrates.len() as u32),
            ..Default::default()
        })?;
        w.write_iter(
            self.bitrates
                .iter()
                .map(|r| Into::<virtio_video_format_range>::into(*r)),
        )
    }
}

#[derive(Debug, Clone)]
pub struct FormatDesc {
    pub mask: u64,
    pub format: Format,
    pub frame_formats: Vec<FrameFormat>,
}

impl Response for FormatDesc {
    fn write(&self, w: &mut Writer) -> Result<(), io::Error> {
        w.write_obj(virtio_video_format_desc {
            mask: self.mask.into(),
            format: Le32::from(self.format as u32),
            // ChromeOS only supports single-buffer mode.
            planes_layout: Le32::from(VIRTIO_VIDEO_PLANES_LAYOUT_SINGLE_BUFFER),
            // No alignment is required on boards that we currently support.
            plane_align: Le32::from(0),
            num_frames: Le32::from(self.frame_formats.len() as u32),
        })?;
        self.frame_formats.iter().try_for_each(|ff| ff.write(w))
    }
}

fn clamp_size(size: u32, min: u32, step: u32) -> u32 {
    match step {
        0 | 1 => size,
        _ => {
            let step_mod = (size - min) % step;
            if step_mod == 0 {
                size
            } else {
                size - step_mod + step
            }
        }
    }
}

/// Parses a slice of valid frame formats and the desired resolution
/// and returns the closest available resolution.
pub fn find_closest_resolution(
    frame_formats: &[FrameFormat],
    desired_width: u32,
    desired_height: u32,
) -> (u32, u32) {
    for FrameFormat { width, height, .. } in frame_formats.iter() {
        if desired_width < width.min || desired_width > width.max {
            continue;
        }
        if desired_height < height.min || desired_height > height.max {
            continue;
        }
        let allowed_width = clamp_size(desired_width, width.min, width.step);
        let allowed_height = clamp_size(desired_height, height.min, height.step);
        return (allowed_width, allowed_height);
    }

    // Return the resolution with maximum surface if nothing better is found.
    match frame_formats
        .iter()
        .max_by_key(|format| format.width.max * format.height.max)
    {
        None => (0, 0),
        Some(format) => (format.width.max, format.height.max),
    }
}

/// A rectangle used to describe portions of a frame.
#[derive(Debug)]
pub struct Rect {
    pub left: i32,
    pub top: i32,
    pub right: i32,
    pub bottom: i32,
}

/// Description of the layout for a single plane.
#[derive(Debug, Clone)]
pub struct FramePlane {
    pub offset: usize,
    pub stride: usize,
}
<commit_msg>virtio: video: make Rect struct comparable<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Data structures that represent video format information in virtio video devices.

use std::convert::{From, Into, TryFrom};
use std::fmt::{self, Display};
use std::io;

use base::error;
use data_model::Le32;
use enumn::N;

use crate::virtio::video::command::ReadCmdError;
use crate::virtio::video::protocol::*;
use crate::virtio::video::response::Response;
use crate::virtio::Writer;

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum Profile {
    H264Baseline = VIRTIO_VIDEO_PROFILE_H264_BASELINE,
    H264Main = VIRTIO_VIDEO_PROFILE_H264_MAIN,
    H264Extended = VIRTIO_VIDEO_PROFILE_H264_EXTENDED,
    H264High = VIRTIO_VIDEO_PROFILE_H264_HIGH,
    H264High10 = VIRTIO_VIDEO_PROFILE_H264_HIGH10PROFILE,
    H264High422 = VIRTIO_VIDEO_PROFILE_H264_HIGH422PROFILE,
    H264High444PredictiveProfile = VIRTIO_VIDEO_PROFILE_H264_HIGH444PREDICTIVEPROFILE,
    H264ScalableBaseline = VIRTIO_VIDEO_PROFILE_H264_SCALABLEBASELINE,
    H264ScalableHigh = VIRTIO_VIDEO_PROFILE_H264_SCALABLEHIGH,
    H264StereoHigh = VIRTIO_VIDEO_PROFILE_H264_STEREOHIGH,
    H264MultiviewHigh = VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH,
    HevcMain = VIRTIO_VIDEO_PROFILE_HEVC_MAIN,
    HevcMain10 = VIRTIO_VIDEO_PROFILE_HEVC_MAIN10,
    HevcMainStillPicture = VIRTIO_VIDEO_PROFILE_HEVC_MAIN_STILL_PICTURE,
    VP8Profile0 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE0,
    VP8Profile1 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE1,
    VP8Profile2 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE2,
    VP8Profile3 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE3,
    VP9Profile0 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE0,
    VP9Profile1 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE1,
    VP9Profile2 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE2,
    VP9Profile3 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE3,
}
impl_try_from_le32_for_enumn!(Profile, "profile");

impl Profile {
    pub fn to_format(&self) -> Format {
        use Profile::*;
        match self {
            H264Baseline
            | H264Main
            | H264Extended
            | H264High
            | H264High10
            | H264High422
            | H264High444PredictiveProfile
            | H264ScalableBaseline
            | H264ScalableHigh
            | H264StereoHigh
            | H264MultiviewHigh => Format::H264,
            HevcMain | HevcMain10 | HevcMainStillPicture => Format::HEVC,
            VP8Profile0 | VP8Profile1 | VP8Profile2 | VP8Profile3 => Format::VP8,
            VP9Profile0 | VP9Profile1 | VP9Profile2 | VP9Profile3 => Format::VP9,
        }
    }
}

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum Level {
    H264_1_0 = VIRTIO_VIDEO_LEVEL_H264_1_0,
    H264_1_1 = VIRTIO_VIDEO_LEVEL_H264_1_1,
    H264_1_2 = VIRTIO_VIDEO_LEVEL_H264_1_2,
    H264_1_3 = VIRTIO_VIDEO_LEVEL_H264_1_3,
    H264_2_0 = VIRTIO_VIDEO_LEVEL_H264_2_0,
    H264_2_1 = VIRTIO_VIDEO_LEVEL_H264_2_1,
    H264_2_2 = VIRTIO_VIDEO_LEVEL_H264_2_2,
    H264_3_0 = VIRTIO_VIDEO_LEVEL_H264_3_0,
    H264_3_1 = VIRTIO_VIDEO_LEVEL_H264_3_1,
    H264_3_2 = VIRTIO_VIDEO_LEVEL_H264_3_2,
    H264_4_0 = VIRTIO_VIDEO_LEVEL_H264_4_0,
    H264_4_1 = VIRTIO_VIDEO_LEVEL_H264_4_1,
    H264_4_2 = VIRTIO_VIDEO_LEVEL_H264_4_2,
    H264_5_0 = VIRTIO_VIDEO_LEVEL_H264_5_0,
    H264_5_1 = VIRTIO_VIDEO_LEVEL_H264_5_1,
}
impl_try_from_le32_for_enumn!(Level, "level");

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum Format {
    // Raw formats
    NV12 = VIRTIO_VIDEO_FORMAT_NV12,
    YUV420 = VIRTIO_VIDEO_FORMAT_YUV420,

    // Bitstream formats
    H264 = VIRTIO_VIDEO_FORMAT_H264,
    HEVC = VIRTIO_VIDEO_FORMAT_HEVC,
    VP8 = VIRTIO_VIDEO_FORMAT_VP8,
    VP9 = VIRTIO_VIDEO_FORMAT_VP9,
}
impl_try_from_le32_for_enumn!(Format, "format");

impl Display for Format {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Format::*;
        match self {
            NV12 => write!(f, "NV12"),
            YUV420 => write!(f, "YUV420"),
            H264 => write!(f, "H264"),
            HEVC => write!(f, "HEVC"),
            VP8 => write!(f, "VP8"),
            VP9 => write!(f, "VP9"),
        }
    }
}

#[derive(Debug, Default, Copy, Clone)]
pub struct Crop {
    pub left: u32,
    pub top: u32,
    pub width: u32,
    pub height: u32,
}
impl_from_for_interconvertible_structs!(virtio_video_crop, Crop, left, top, width, height);

#[derive(Debug, Default, Clone, Copy)]
pub struct PlaneFormat {
    pub plane_size: u32,
    pub stride: u32,
}
impl_from_for_interconvertible_structs!(virtio_video_plane_format, PlaneFormat, plane_size, stride);

#[derive(Debug, Default, Clone, Copy)]
pub struct FormatRange {
    pub min: u32,
    pub max: u32,
    pub step: u32,
}
impl_from_for_interconvertible_structs!(virtio_video_format_range, FormatRange, min, max, step);

#[derive(Debug, Default, Clone)]
pub struct FrameFormat {
    pub width: FormatRange,
    pub height: FormatRange,
    pub bitrates: Vec<FormatRange>,
}

impl Response for FrameFormat {
    fn write(&self, w: &mut Writer) -> Result<(), io::Error> {
        w.write_obj(virtio_video_format_frame {
            width: self.width.into(),
            height: self.height.into(),
            num_rates: Le32::from(self.bitrates.len() as u32),
            ..Default::default()
        })?;
        w.write_iter(
            self.bitrates
                .iter()
                .map(|r| Into::<virtio_video_format_range>::into(*r)),
        )
    }
}

#[derive(Debug, Clone)]
pub struct FormatDesc {
    pub mask: u64,
    pub format: Format,
    pub frame_formats: Vec<FrameFormat>,
}

impl Response for FormatDesc {
    fn write(&self, w: &mut Writer) -> Result<(), io::Error> {
        w.write_obj(virtio_video_format_desc {
            mask: self.mask.into(),
            format: Le32::from(self.format as u32),
            // ChromeOS only supports single-buffer mode.
            planes_layout: Le32::from(VIRTIO_VIDEO_PLANES_LAYOUT_SINGLE_BUFFER),
            // No alignment is required on boards that we currently support.
            plane_align: Le32::from(0),
            num_frames: Le32::from(self.frame_formats.len() as u32),
        })?;
        self.frame_formats.iter().try_for_each(|ff| ff.write(w))
    }
}

fn clamp_size(size: u32, min: u32, step: u32) -> u32 {
    match step {
        0 | 1 => size,
        _ => {
            let step_mod = (size - min) % step;
            if step_mod == 0 {
                size
            } else {
                size - step_mod + step
            }
        }
    }
}

/// Parses a slice of valid frame formats and the desired resolution
/// and returns the closest available resolution.
pub fn find_closest_resolution(
    frame_formats: &[FrameFormat],
    desired_width: u32,
    desired_height: u32,
) -> (u32, u32) {
    for FrameFormat { width, height, .. } in frame_formats.iter() {
        if desired_width < width.min || desired_width > width.max {
            continue;
        }
        if desired_height < height.min || desired_height > height.max {
            continue;
        }
        let allowed_width = clamp_size(desired_width, width.min, width.step);
        let allowed_height = clamp_size(desired_height, height.min, height.step);
        return (allowed_width, allowed_height);
    }

    // Return the resolution with maximum surface if nothing better is found.
    match frame_formats
        .iter()
        .max_by_key(|format| format.width.max * format.height.max)
    {
        None => (0, 0),
        Some(format) => (format.width.max, format.height.max),
    }
}

/// A rectangle used to describe portions of a frame.
#[derive(Debug, Eq, PartialEq)]
pub struct Rect {
    pub left: i32,
    pub top: i32,
    pub right: i32,
    pub bottom: i32,
}

/// Description of the layout for a single plane.
#[derive(Debug, Clone)]
pub struct FramePlane {
    pub offset: usize,
    pub stride: usize,
}
<|endoftext|>


<commit_before>//! `pagecache` is a lock-free pagecache and log for building high-performance databases.
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", allow(inline_always))]

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate crossbeam_epoch as epoch;
extern crate bincode;
extern crate historian;
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "env_logger")]
extern crate env_logger;
#[macro_use]
extern crate log as _log;
#[cfg(feature = "rayon")]
extern crate rayon;
#[cfg(feature = "zstd")]
extern crate zstd;
#[cfg(feature = "cpuprofiler")]
extern crate cpuprofiler;
#[cfg(any(test, feature = "lock_free_delays"))]
extern crate rand;
#[cfg(unix)]
extern crate libc;

#[doc(hidden)]
pub use ds::{Radix, Stack};

/// general-purpose configuration
pub use config::{Config, FinalConfig};
pub use io::*;

macro_rules! rep_no_copy {
    ($e:expr; $n:expr) => {
        {
            let mut v = Vec::with_capacity($n);
            for _ in 0..$n {
                v.push($e);
            }
            v
        }
    };
}

mod io;
mod config;
mod hash;
mod ds;
mod metrics;

// use log::{Iter, MessageHeader, SegmentHeader, SegmentTrailer};
use metrics::Metrics;
use ds::*;
use hash::{crc16_arr, crc64};

/// An offset for a storage file segment.
pub type SegmentID = usize;

/// A log file offset.
pub type LogID = u64;

/// A logical sequence number.
pub type Lsn = isize;

/// A page identifier.
pub type PageID = usize;

type HPtr<'g, P> = epoch::Shared<'g, ds::stack::Node<io::CacheEntry<P>>>;

lazy_static! {
    /// A metric collector for all sled instances running in this
    /// process.
    pub static ref M: Metrics = Metrics::default();
}

fn clock() -> f64 {
    let u = uptime();
    (u.as_secs() * 1_000_000_000) as f64 + f64::from(u.subsec_nanos())
}

// not correct, since it starts counting at the first observance...
fn uptime() -> std::time::Duration {
    lazy_static! {
        static ref START: std::time::Instant = std::time::Instant::now();
    }

    START.elapsed()
}

// This function is useful for inducing random jitter into our atomic
// operations, shaking out more possible interleavings quickly. It gets
// fully elliminated by the compiler in non-test code.
#[inline(always)]
pub fn debug_delay() {
    #[cfg(any(test, feature = "lock_free_delays"))]
    {
        use rand::{Rng, thread_rng};

        if thread_rng().gen_weighted_bool(1000) {
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }
}

// initialize env_logger and/or cpuprofiler if configured to do so.
fn global_init() {
    use std::sync::{ONCE_INIT, Once};

    static ONCE: Once = ONCE_INIT;

    ONCE.call_once(|| {
        #[cfg(feature = "env_logger")]
        {
            let format = |record: &_log::LogRecord| {
                format!(
                    "{:05} {:10} {:10} {}",
                    record.level(),
                    tn(),
                    record.location().module_path().split("::").last().unwrap(),
                    record.args()
                )
            };

            let mut builder = env_logger::LogBuilder::new();
            builder.format(format).filter(
                None,
                _log::LogLevelFilter::Info,
            );

            if std::env::var("RUST_LOG").is_ok() {
                builder.parse(&std::env::var("RUST_LOG").unwrap());
            }

            let _r = builder.init();
        }

        #[cfg(feature = "cpuprofiler")]
        {
            use std::env;

            let key = "CPUPROFILE";
            let path = match env::var(key) {
                Ok(val) => val,
                Err(_) => "sled.profile".to_owned(),
            };
            cpuprofiler::PROFILER.lock().unwrap().start(path).expect(
                "could not start cpu profiler!",
            );
        }
    });
}
<commit_msg>add docs to debug_delay<commit_after>//! `pagecache` is a lock-free pagecache and log for building high-performance databases.
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", allow(inline_always))]

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate crossbeam_epoch as epoch;
extern crate bincode;
extern crate historian;
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "env_logger")]
extern crate env_logger;
#[macro_use]
extern crate log as _log;
#[cfg(feature = "rayon")]
extern crate rayon;
#[cfg(feature = "zstd")]
extern crate zstd;
#[cfg(feature = "cpuprofiler")]
extern crate cpuprofiler;
#[cfg(any(test, feature = "lock_free_delays"))]
extern crate rand;
#[cfg(unix)]
extern crate libc;

#[doc(hidden)]
pub use ds::{Radix, Stack};

/// general-purpose configuration
pub use config::{Config, FinalConfig};
pub use io::*;

macro_rules! rep_no_copy {
    ($e:expr; $n:expr) => {
        {
            let mut v = Vec::with_capacity($n);
            for _ in 0..$n {
                v.push($e);
            }
            v
        }
    };
}

mod io;
mod config;
mod hash;
mod ds;
mod metrics;

// use log::{Iter, MessageHeader, SegmentHeader, SegmentTrailer};
use metrics::Metrics;
use ds::*;
use hash::{crc16_arr, crc64};

/// An offset for a storage file segment.
pub type SegmentID = usize;

/// A log file offset.
pub type LogID = u64;

/// A logical sequence number.
pub type Lsn = isize;

/// A page identifier.
pub type PageID = usize;

type HPtr<'g, P> = epoch::Shared<'g, ds::stack::Node<io::CacheEntry<P>>>;

lazy_static! {
    /// A metric collector for all sled instances running in this
    /// process.
    pub static ref M: Metrics = Metrics::default();
}

fn clock() -> f64 {
    let u = uptime();
    (u.as_secs() * 1_000_000_000) as f64 + f64::from(u.subsec_nanos())
}

// not correct, since it starts counting at the first observance...
fn uptime() -> std::time::Duration {
    lazy_static! {
        static ref START: std::time::Instant = std::time::Instant::now();
    }

    START.elapsed()
}

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully elliminated by the compiler in non-test code.
#[inline(always)]
pub fn debug_delay() {
    #[cfg(any(test, feature = "lock_free_delays"))]
    {
        use rand::{Rng, thread_rng};

        if thread_rng().gen_weighted_bool(1000) {
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }
}

// initialize env_logger and/or cpuprofiler if configured to do so.
fn global_init() {
    use std::sync::{ONCE_INIT, Once};

    static ONCE: Once = ONCE_INIT;

    ONCE.call_once(|| {
        #[cfg(feature = "env_logger")]
        {
            let format = |record: &_log::LogRecord| {
                format!(
                    "{:05} {:10} {:10} {}",
                    record.level(),
                    tn(),
                    record.location().module_path().split("::").last().unwrap(),
                    record.args()
                )
            };

            let mut builder = env_logger::LogBuilder::new();
            builder.format(format).filter(
                None,
                _log::LogLevelFilter::Info,
            );

            if std::env::var("RUST_LOG").is_ok() {
                builder.parse(&std::env::var("RUST_LOG").unwrap());
            }

            let _r = builder.init();
        }

        #[cfg(feature = "cpuprofiler")]
        {
            use std::env;

            let key = "CPUPROFILE";
            let path = match env::var(key) {
                Ok(val) => val,
                Err(_) => "sled.profile".to_owned(),
            };
            cpuprofiler::PROFILER.lock().unwrap().start(path).expect(
                "could not start cpu profiler!",
            );
        }
    });
}
<|endoftext|>


<commit_before>//! The `expressionparser` module parse every expression
//! to an ast (abstract syntaxtree)
//! the idea is explained here: http://programmers.stackexchange.com/questions/254074/

use frontend::ast::{ASTNode, NodeDefault};
use frontend::lexer::Token;
use frontend::lexer::Token::*;

pub struct ExpressionParser {
    expr_stack: Vec<ASTNode>,
    oper_stack: Vec<Token>,
}

impl ExpressionParser {
    pub fn parse(node: &mut NodeDefault) {
        let mut expr_parser = ExpressionParser {
            expr_stack: Vec::new(),
            oper_stack: Vec::new(),
        };
        expr_parser.parse_expressions(node);
    }

    /// parse the expression node and creates mutliple ast nodes
    fn parse_expressions(&mut self, node: &mut NodeDefault) {

        node.childs.reverse();
        while let Some(top) = node.childs.pop() {
            match top.category() {
                tok @ TokInt      { .. } |
                tok @ TokFunction { .. } |
                tok @ TokVariable { .. } => {
                    let childs_copy = top.as_default().childs.to_vec();
                    self.expr_stack.push( ASTNode::Default(NodeDefault { category: tok.clone(), childs: childs_copy }) );
                },
                tok @ TokNumOp  { .. } |
                tok @ TokCompOp { .. } => {
                    let length = self.oper_stack.len();

                    // cycle through the oper_stack stack backwards
                    // if the rank of the current operator is <= the top of the
                    // stack, we create a new node
                    for i in 0..length {
                        let i_rev = length - i - 1;
                        let token: Token = self.oper_stack.get(i_rev).unwrap().clone();
                        if is_ranking_not_higher(token, tok.clone()) {
                            self.new_operator_node();
                        }
                    }

                    self.oper_stack.push(tok.clone());
                },
                _ => ()
            }
        }

        // parse the last elements of the stack
        // to avoid endless loop we try max expr_stack.len()
        for _ in 0..self.expr_stack.len() {
            if self.expr_stack.len() > 0 {
                self.new_operator_node();
            }
        }

        // finished. so add the root of the expressions as child.
        assert!{self.expr_stack.len() == 1, "Only one expression can be the root. But there are {:?}.", self.expr_stack.len()};
        if let Some(root) = self.expr_stack.pop() {
            node.childs.push(root);
        }
    }

    /// creates a node with an operator on top
    fn new_operator_node(&mut self) {
        if let Some(top_op) = self.oper_stack.pop() {
            let e2: ASTNode = self.expr_stack.pop().unwrap();
            let e1: ASTNode = self.expr_stack.pop().unwrap();

            let new_node = ASTNode::Default(NodeDefault { category: top_op.clone(), childs: vec![e1, e2] });
            self.expr_stack.push( new_node );
        }
    }
}

/// checks the operatores of two tokens returns true if operator of token1
/// is more important then operator of token2
/// the ranking is set in "operator_precedence"
fn is_ranking_not_higher(token1: Token, token2: Token) -> bool {
    let mut op1: String = "".to_string();
    let mut op2: String = "".to_string();
    match token1 {
        TokNumOp  { op_name, .. } |
        TokCompOp { op_name, .. } => {
            op1 = op_name.clone();
        },
        _ => ()
    }
    match token2 {
        TokNumOp  { op_name, .. } |
        TokCompOp { op_name, .. } => {
            op2 = op_name.clone();
        },
        _ => ()
    }

    if operator_rank(op1) >= operator_rank(op2) {
        return true
    }

    false
}

/// ranking of the operators
fn operator_rank(op: String) -> u8 {
    match op.as_ref() {
        "is" | "==" | "eq" | "neq" | ">" | "gt" | ">=" | "gte" | "<" | "lt" | "<=" | "lte"
                    => 2,
        "+" | "-"   => 3,
        "*" | "/"   => 4,
        "%"         => 5,
        _           => panic!{"This operator is not implemented"}
    }
}
<commit_msg>Add boolean to expression parser<commit_after>//! The `expressionparser` module parse every expression
//! to an ast (abstract syntaxtree)
//! the idea is explained here: http://programmers.stackexchange.com/questions/254074/

use frontend::ast::{ASTNode, NodeDefault};
use frontend::lexer::Token;
use frontend::lexer::Token::*;

pub struct ExpressionParser {
    expr_stack: Vec<ASTNode>,
    oper_stack: Vec<Token>,
}

impl ExpressionParser {
    pub fn parse(node: &mut NodeDefault) {
        let mut expr_parser = ExpressionParser {
            expr_stack: Vec::new(),
            oper_stack: Vec::new(),
        };
        expr_parser.parse_expressions(node);
    }

    /// parse the expression node and creates mutliple ast nodes
    fn parse_expressions(&mut self, node: &mut NodeDefault) {

        node.childs.reverse();
        while let Some(top) = node.childs.pop() {
            match top.category() {
                tok @ TokBoolean  { .. } |
                tok @ TokInt      { .. } |
                tok @ TokFunction { .. } |
                tok @ TokVariable { .. } => {
                    let childs_copy = top.as_default().childs.to_vec();
                    self.expr_stack.push( ASTNode::Default(NodeDefault { category: tok.clone(), childs: childs_copy }) );
                },
                tok @ TokNumOp  { .. } |
                tok @ TokCompOp { .. } => {
                    let length = self.oper_stack.len();

                    // cycle through the oper_stack stack backwards
                    // if the rank of the current operator is <= the top of the
                    // stack, we create a new node
                    for i in 0..length {
                        let i_rev = length - i - 1;
                        let token: Token = self.oper_stack.get(i_rev).unwrap().clone();
                        if is_ranking_not_higher(token, tok.clone()) {
                            self.new_operator_node();
                        }
                    }

                    self.oper_stack.push(tok.clone());
                },
                _ => ()
            }
        }

        // parse the last elements of the stack
        // to avoid endless loop we try max expr_stack.len()
        for _ in 0..self.expr_stack.len() {
            if self.expr_stack.len() > 0 {
                self.new_operator_node();
            }
        }

        // finished. so add the root of the expressions as child.
        assert!{self.expr_stack.len() == 1, "Only one expression can be the root. But there are {:?}.", self.expr_stack.len()};
        if let Some(root) = self.expr_stack.pop() {
            node.childs.push(root);
        }
    }

    /// creates a node with an operator on top
    fn new_operator_node(&mut self) {
        if let Some(top_op) = self.oper_stack.pop() {
            let e2: ASTNode = self.expr_stack.pop().unwrap();
            let e1: ASTNode = self.expr_stack.pop().unwrap();

            let new_node = ASTNode::Default(NodeDefault { category: top_op.clone(), childs: vec![e1, e2] });
            self.expr_stack.push( new_node );
        }
    }
}

/// checks the operatores of two tokens returns true if operator of token1
/// is more important then operator of token2
/// the ranking is set in "operator_precedence"
fn is_ranking_not_higher(token1: Token, token2: Token) -> bool {
    let mut op1: String = "".to_string();
    let mut op2: String = "".to_string();
    match token1 {
        TokNumOp  { op_name, .. } |
        TokCompOp { op_name, .. } => {
            op1 = op_name.clone();
        },
        _ => ()
    }
    match token2 {
        TokNumOp  { op_name, .. } |
        TokCompOp { op_name, .. } => {
            op2 = op_name.clone();
        },
        _ => ()
    }

    if operator_rank(op1) >= operator_rank(op2) {
        return true
    }

    false
}

/// ranking of the operators
fn operator_rank(op: String) -> u8 {
    match op.as_ref() {
        "is" | "==" | "eq" | "neq" | ">" | "gt" | ">=" | "gte" | "<" | "lt" | "<=" | "lte"
                    => 2,
        "+" | "-"   => 3,
        "*" | "/"   => 4,
        "%"         => 5,
        _           => panic!{"This operator is not implemented"}
    }
}
<|endoftext|>


<commit_before>#![feature(try_trait)]

use serde::Deserialize;

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}

#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}

#[derive(Deserialize)]
struct BottleStable {
    rebuild: u64,
    files: serde_json::Value,
}

#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn d(f: &Formula) -> Option<()> {
    if f.versions.bottle {
        let name = &f.name;
        let ver = f.versions.stable.as_ref()?;
        let bs = f.bottle.stable.as_ref()?;
        let rebuild = bs.rebuild;
        for (platform, v) in bs.files.as_object()?.iter() {
            if let Ok(bi) = serde_json::from_value::<BottleInfo>(v.clone()) {
                if rebuild == 0 {
                    println!("{} {} {}-{}.{}.bottle.tar.gz", bi.sha256, bi.url, name, ver, platform);
                } else {
                    println!("{} {} {}-{}.{}.bottle.{}.tar.gz", bi.sha256, bi.url, name, ver, platform, rebuild);
                }
            }
        }
    }
    Some(())
}

fn main() {
    let f: Formulae = serde_json::from_reader(std::io::stdin()).unwrap();
    for f in f.0 {
        d(&f);
    }
}
<commit_msg>homebrew-bottles: fix filename with revision attribute<commit_after>#![feature(try_trait)]

use serde::Deserialize;

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}

#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}

#[derive(Deserialize)]
struct BottleStable {
    rebuild: u64,
    files: serde_json::Value,
}

#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
    revision: u64,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn d(f: &Formula) -> Option<()> {
    let revision = f.revision;
    let revision = if revision == 0 { "".to_string() } else { format!("_{}", revision) };
    if f.versions.bottle {
        let name = &f.name;
        let version = f.versions.stable.as_ref()?;
        let bs = f.bottle.stable.as_ref()?;
        let rebuild = bs.rebuild;
        let rebuild = if rebuild == 0 { "".to_string() } else { format!(".{}", rebuild) };
        for (platform, v) in bs.files.as_object()?.iter() {
            if let Ok(bi) = serde_json::from_value::<BottleInfo>(v.clone()) {
                println!(
                    "{} {} {}-{}{}.{}.bottle{}.tar.gz",
                    bi.sha256, bi.url, name, version, revision, platform, rebuild
                );
            }
        }
    }
    Some(())
}

fn main() {
    let f: Formulae = serde_json::from_reader(std::io::stdin()).unwrap();
    for f in f.0 {
        d(&f);
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Arithmetic/Integer
// not_tested

fn main() {
    let input = std::io::stdin().read_line().unwrap();
    let words = input.as_slice().words().take(2)
                            .map(from_str)
                            .collect::<Vec<Option<int>>>();

    let (a, b) = match words.as_slice() {
            [Some(x), Some(y)] => (x, y),
            _                  => fail!("Please enter 2 integers")
    };

    println!("a + b = {}", a + b);
    println!("a - b = {}", a - b);
    println!("a * b = {}", a * b);
    println!("a / b = {}", a / b);
    println!("a % b = {}", a % b);
}
<commit_msg>arithmetic integers: style<commit_after>// Implements http://rosettacode.org/wiki/Arithmetic/Integer
// not_tested
use std::io::stdin;

fn main() {
    let input = stdin().read_line().unwrap();
    let words = input.as_slice().words().take(2)
                                        .map(from_str)
                                        .collect::<Vec<Option<int>>>();

    let (a, b) = match words.as_slice() {
            [Some(x), Some(y)] => (x, y),
            _ => fail!("Please enter 2 integers")
    };

    println!("a + b = {}", a + b);
    println!("a - b = {}", a - b);
    println!("a * b = {}", a * b);
    println!("a / b = {}", a / b);
    println!("a % b = {}", a % b);
}
<|endoftext|>


<commit_before>use std::cmp;

use matches::matches;
use rustc::hir::*;
use rustc::hir::map::*;
use rustc::hir::intravisit::FnKind;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::TypeVariants;
use rustc::session::config::Config as SessionConfig;
use rustc_target::spec::abi::Abi;
use rustc_target::abi::LayoutOf;
use syntax::ast::NodeId;
use syntax_pos::Span;
use crate::utils::{in_macro, is_copy, is_self, span_lint_and_sugg, snippet};

/// **What it does:** Checks for functions taking arguments by reference, where
/// the argument type is `Copy` and small enough to be more efficient to always
/// pass by value.
///
/// **Why is this bad?** In many calling conventions instances of structs will
/// be passed through registers if they fit into two or less general purpose
/// registers.
///
/// **Known problems:** This lint is target register size dependent, it is
/// limited to 32-bit to try and reduce portability problems between 32 and
/// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit
/// will be different.
///
/// The configuration option `trivial_copy_size_limit` can be set to override
/// this limit for a project.
///
/// This lint attempts to allow passing arguments by reference if a reference
/// to that argument is returned. This is implemented by comparing the lifetime
/// of the argument and return value for equality. However, this can cause
/// false positives in cases involving multiple lifetimes that are bounded by
/// each other.
///
/// **Example:**
/// ```rust
/// fn foo(v: &u32) {
///     assert_eq!(v, 42);
/// }
/// // should be
/// fn foo(v: u32) {
///     assert_eq!(v, 42);
/// }
/// ```
declare_clippy_lint! {
    pub TRIVIALLY_COPY_PASS_BY_REF,
    perf,
    "functions taking small copyable arguments by reference"
}

pub struct TriviallyCopyPassByRef {
    limit: u64,
}

impl TriviallyCopyPassByRef {
    pub fn new(limit: Option<u64>, target: &SessionConfig) -> Self {
        let limit = limit.unwrap_or_else(|| {
            let bit_width = target.usize_ty.bit_width().expect("usize should have a width") as u64;
            // Cap the calculated bit width at 32-bits to reduce
            // portability problems between 32 and 64-bit targets
            let bit_width = cmp::min(bit_width, 32);
            let byte_width = bit_width / 8;
            // Use a limit of 2 times the register bit width
            byte_width * 2
        });
        Self { limit }
    }
}

impl LintPass for TriviallyCopyPassByRef {
    fn get_lints(&self) -> LintArray {
        lint_array![TRIVIALLY_COPY_PASS_BY_REF]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        kind: FnKind<'tcx>,
        decl: &'tcx FnDecl,
        body: &'tcx Body,
        span: Span,
        node_id: NodeId,
    ) {
        if in_macro(span) {
            return;
        }

        match kind {
            FnKind::ItemFn(.., header, _, attrs) => {
                if header.abi != Abi::Rust {
                    return;
                }
                for a in attrs {
                    if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" {
                        return;
                    }
                }
            },
            FnKind::Method(..) => (),
            _ => return,
        }

        // Exclude non-inherent impls
        if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) {
            if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) |
                ItemKind::Trait(..))
            {
                return;
            }
        }

        let fn_def_id = cx.tcx.hir.local_def_id(node_id);

        let fn_sig = cx.tcx.fn_sig(fn_def_id);
        let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig);

        // Use lifetimes to determine if we're returning a reference to the argument. In that case
        // we can't switch to pass-by-value as the argument will not live long enough.
        let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty {
            Some(output_lt)
        } else {
            None
        };

        for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) {
            // All spans generated from a proc-macro invocation are the same...
            if span == input.span {
                return;
            }

            if_chain! {
                if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty;
                if Some(input_lt) != output_lt;
                if is_copy(cx, ty);
                if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
                if size <= self.limit;
                if let TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node;
                then {
                    let value_type = if is_self(arg) {
                        "self".into()
                    } else {
                        snippet(cx, decl_ty.span, "_").into()
                    };
                    span_lint_and_sugg(
                        cx,
                        TRIVIALLY_COPY_PASS_BY_REF,
                        input.span,
                        "this argument is passed by reference, but would be more efficient if passed by value",
                        "consider passing by value instead",
                        value_type);
                }
            }
        }
    }
}
<commit_msg>Wrap comment at 80 columns<commit_after>use std::cmp;

use matches::matches;
use rustc::hir::*;
use rustc::hir::map::*;
use rustc::hir::intravisit::FnKind;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::TypeVariants;
use rustc::session::config::Config as SessionConfig;
use rustc_target::spec::abi::Abi;
use rustc_target::abi::LayoutOf;
use syntax::ast::NodeId;
use syntax_pos::Span;
use crate::utils::{in_macro, is_copy, is_self, span_lint_and_sugg, snippet};

/// **What it does:** Checks for functions taking arguments by reference, where
/// the argument type is `Copy` and small enough to be more efficient to always
/// pass by value.
///
/// **Why is this bad?** In many calling conventions instances of structs will
/// be passed through registers if they fit into two or less general purpose
/// registers.
///
/// **Known problems:** This lint is target register size dependent, it is
/// limited to 32-bit to try and reduce portability problems between 32 and
/// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit
/// will be different.
///
/// The configuration option `trivial_copy_size_limit` can be set to override
/// this limit for a project.
///
/// This lint attempts to allow passing arguments by reference if a reference
/// to that argument is returned. This is implemented by comparing the lifetime
/// of the argument and return value for equality. However, this can cause
/// false positives in cases involving multiple lifetimes that are bounded by
/// each other.
///
/// **Example:**
/// ```rust
/// fn foo(v: &u32) {
///     assert_eq!(v, 42);
/// }
/// // should be
/// fn foo(v: u32) {
///     assert_eq!(v, 42);
/// }
/// ```
declare_clippy_lint! {
    pub TRIVIALLY_COPY_PASS_BY_REF,
    perf,
    "functions taking small copyable arguments by reference"
}

pub struct TriviallyCopyPassByRef {
    limit: u64,
}

impl TriviallyCopyPassByRef {
    pub fn new(limit: Option<u64>, target: &SessionConfig) -> Self {
        let limit = limit.unwrap_or_else(|| {
            let bit_width = target.usize_ty.bit_width().expect("usize should have a width") as u64;
            // Cap the calculated bit width at 32-bits to reduce
            // portability problems between 32 and 64-bit targets
            let bit_width = cmp::min(bit_width, 32);
            let byte_width = bit_width / 8;
            // Use a limit of 2 times the register bit width
            byte_width * 2
        });
        Self { limit }
    }
}

impl LintPass for TriviallyCopyPassByRef {
    fn get_lints(&self) -> LintArray {
        lint_array![TRIVIALLY_COPY_PASS_BY_REF]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        kind: FnKind<'tcx>,
        decl: &'tcx FnDecl,
        body: &'tcx Body,
        span: Span,
        node_id: NodeId,
    ) {
        if in_macro(span) {
            return;
        }

        match kind {
            FnKind::ItemFn(.., header, _, attrs) => {
                if header.abi != Abi::Rust {
                    return;
                }
                for a in attrs {
                    if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" {
                        return;
                    }
                }
            },
            FnKind::Method(..) => (),
            _ => return,
        }

        // Exclude non-inherent impls
        if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) {
            if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) |
                ItemKind::Trait(..))
            {
                return;
            }
        }

        let fn_def_id = cx.tcx.hir.local_def_id(node_id);

        let fn_sig = cx.tcx.fn_sig(fn_def_id);
        let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig);

        // Use lifetimes to determine if we're returning a reference to the
        // argument. In that case we can't switch to pass-by-value as the
        // argument will not live long enough.
        let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty {
            Some(output_lt)
        } else {
            None
        };

        for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) {
            // All spans generated from a proc-macro invocation are the same...
            if span == input.span {
                return;
            }

            if_chain! {
                if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty;
                if Some(input_lt) != output_lt;
                if is_copy(cx, ty);
                if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
                if size <= self.limit;
                if let TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node;
                then {
                    let value_type = if is_self(arg) {
                        "self".into()
                    } else {
                        snippet(cx, decl_ty.span, "_").into()
                    };
                    span_lint_and_sugg(
                        cx,
                        TRIVIALLY_COPY_PASS_BY_REF,
                        input.span,
                        "this argument is passed by reference, but would be more efficient if passed by value",
                        "consider passing by value instead",
                        value_type);
                }
            }
        }
    }
}
<|endoftext|>