<commit_before>// FIXME (Issue #1984): The way this module sets up tests is a relic and more
// convoluted than it needs to be

import option;
import std::getopts;
import std::test;
import str;
import vec;
import task;

import core::result;
import result::{ok, err};

import comm::port;
import comm::chan;
import comm::send;
import comm::recv;

import common::config;
import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::mode;
import util::logv;

fn main(args: [str]) {
    let config = parse_config(args);
    log_config(config);
    run_tests(config);
}

fn parse_config(args: [str]) -> config {
    let opts =
        [getopts::reqopt("compile-lib-path"), getopts::reqopt("run-lib-path"),
         getopts::reqopt("rustc-path"), getopts::reqopt("src-base"),
         getopts::reqopt("build-base"), getopts::reqopt("aux-base"),
         getopts::reqopt("stage-id"),
         getopts::reqopt("mode"), getopts::optflag("ignored"),
         getopts::optopt("runtool"), getopts::optopt("rustcflags"),
         getopts::optflag("verbose")];

    check (vec::is_not_empty(args));
    let args_ = vec::tail(args);
    let match =
        alt getopts::getopts(args_, opts) {
          ok(m) { m }
          err(f) { fail getopts::fail_str(f) }
        };

    ret {compile_lib_path: getopts::opt_str(match, "compile-lib-path"),
         run_lib_path: getopts::opt_str(match, "run-lib-path"),
         rustc_path: getopts::opt_str(match, "rustc-path"),
         src_base: getopts::opt_str(match, "src-base"),
         build_base: getopts::opt_str(match, "build-base"),
         aux_base: getopts::opt_str(match, "aux-base"),
         stage_id: getopts::opt_str(match, "stage-id"),
         mode: str_mode(getopts::opt_str(match, "mode")),
         run_ignored: getopts::opt_present(match, "ignored"),
         filter:
             if vec::len(match.free) > 0u {
                 option::some(match.free[0])
             } else { option::none },
         runtool: getopts::opt_maybe_str(match, "runtool"),
         rustcflags: getopts::opt_maybe_str(match, "rustcflags"),
         verbose: getopts::opt_present(match, "verbose")};
}

fn log_config(config: config) {
    let c = config;
    logv(c, #fmt["configuration:"]);
    logv(c, #fmt["compile_lib_path: %s", config.compile_lib_path]);
    logv(c, #fmt["run_lib_path: %s", config.run_lib_path]);
    logv(c, #fmt["rustc_path: %s", config.rustc_path]);
    logv(c, #fmt["src_base: %s", config.src_base]);
    logv(c, #fmt["build_base: %s", config.build_base]);
    logv(c, #fmt["stage_id: %s", config.stage_id]);
    logv(c, #fmt["mode: %s", mode_str(config.mode)]);
    logv(c, #fmt["run_ignored: %b", config.run_ignored]);
    logv(c, #fmt["filter: %s", opt_str(config.filter)]);
    logv(c, #fmt["runtool: %s", opt_str(config.runtool)]);
    logv(c, #fmt["rustcflags: %s", opt_str(config.rustcflags)]);
    logv(c, #fmt["verbose: %b", config.verbose]);
    logv(c, #fmt["\n"]);
}

fn opt_str(maybestr: option<str>) -> str {
    alt maybestr { option::some(s) { s } option::none { "(none)" } }
}

fn str_opt(maybestr: str) -> option<str> {
    if maybestr != "(none)" { option::some(maybestr) } else { option::none }
}

fn str_mode(s: str) -> mode {
    alt s {
      "compile-fail" { mode_compile_fail }
      "run-fail" { mode_run_fail }
      "run-pass" { mode_run_pass }
      "pretty" { mode_pretty }
      _ { fail "invalid mode" }
    }
}

fn mode_str(mode: mode) -> str {
    alt mode {
      mode_compile_fail { "compile-fail" }
      mode_run_fail { "run-fail" }
      mode_run_pass { "run-pass" }
      mode_pretty { "pretty" }
    }
}

fn run_tests(config: config) {
    let opts = test_opts(config);
    let tests = make_tests(config);
    let res = test::run_tests_console(opts, tests);
    if !res { fail "Some tests failed"; }
}

fn test_opts(config: config) -> test::test_opts {
    {filter:
         alt config.filter {
           option::some(s) { option::some(s) }
           option::none { option::none }
         },
     run_ignored: config.run_ignored}
}

fn make_tests(config: config) -> [test::test_desc] {
    #debug("making tests from %s", config.src_base);
    let tests = [];
    for file: str in os::list_dir(config.src_base) {
        let file = file;
        #debug("inspecting file %s", file);
        if is_test(config, file) {
            tests += [make_test(config, file)]
        }
    }
    ret tests;
}

fn is_test(config: config, testfile: str) -> bool {
    // Pretty-printer does not work with .rc files yet
    let valid_extensions =
        alt config.mode { mode_pretty { [".rs"] } _ { [".rc", ".rs"] } };
    let invalid_prefixes = [".", "#", "~"];
    let name = path::basename(testfile);

    let valid = false;

    for ext in valid_extensions {
        if str::ends_with(name, ext) { valid = true; }
    }

    for pre in invalid_prefixes {
        if str::starts_with(name, pre) { valid = false; }
    }

    ret valid;
}

fn make_test(config: config, testfile: str) ->
   test::test_desc {
    {
        name: make_test_name(config, testfile),
        fn: make_test_closure(config, testfile),
        ignore: header::is_test_ignored(config, testfile),
        should_fail: false
    }
}

fn make_test_name(config: config, testfile: str) -> str {
    #fmt["[%s] %s", mode_str(config.mode), testfile]
}

fn make_test_closure(config: config, testfile: str) -> test::test_fn {
    ret {||
        runtest::run(config, copy testfile);
    };
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>compiletest: Remove FIXME. Closes #1984<commit_after>import option;
import std::getopts;
import std::test;
import str;
import vec;
import task;

import core::result;
import result::{ok, err};

import comm::port;
import comm::chan;
import comm::send;
import comm::recv;

import common::config;
import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::mode;
import util::logv;

fn main(args: [str]) {
    let config = parse_config(args);
    log_config(config);
    run_tests(config);
}

fn parse_config(args: [str]) -> config {
    let opts =
        [getopts::reqopt("compile-lib-path"), getopts::reqopt("run-lib-path"),
         getopts::reqopt("rustc-path"), getopts::reqopt("src-base"),
         getopts::reqopt("build-base"), getopts::reqopt("aux-base"),
         getopts::reqopt("stage-id"),
         getopts::reqopt("mode"), getopts::optflag("ignored"),
         getopts::optopt("runtool"), getopts::optopt("rustcflags"),
         getopts::optflag("verbose")];

    check (vec::is_not_empty(args));
    let args_ = vec::tail(args);
    let match =
        alt getopts::getopts(args_, opts) {
          ok(m) { m }
          err(f) { fail getopts::fail_str(f) }
        };

    ret {compile_lib_path: getopts::opt_str(match, "compile-lib-path"),
         run_lib_path: getopts::opt_str(match, "run-lib-path"),
         rustc_path: getopts::opt_str(match, "rustc-path"),
         src_base: getopts::opt_str(match, "src-base"),
         build_base: getopts::opt_str(match, "build-base"),
         aux_base: getopts::opt_str(match, "aux-base"),
         stage_id: getopts::opt_str(match, "stage-id"),
         mode: str_mode(getopts::opt_str(match, "mode")),
         run_ignored: getopts::opt_present(match, "ignored"),
         filter:
             if vec::len(match.free) > 0u {
                 option::some(match.free[0])
             } else { option::none },
         runtool: getopts::opt_maybe_str(match, "runtool"),
         rustcflags: getopts::opt_maybe_str(match, "rustcflags"),
         verbose: getopts::opt_present(match, "verbose")};
}

fn log_config(config: config) {
    let c = config;
    logv(c, #fmt["configuration:"]);
    logv(c, #fmt["compile_lib_path: %s", config.compile_lib_path]);
    logv(c, #fmt["run_lib_path: %s", config.run_lib_path]);
    logv(c, #fmt["rustc_path: %s", config.rustc_path]);
    logv(c, #fmt["src_base: %s", config.src_base]);
    logv(c, #fmt["build_base: %s", config.build_base]);
    logv(c, #fmt["stage_id: %s", config.stage_id]);
    logv(c, #fmt["mode: %s", mode_str(config.mode)]);
    logv(c, #fmt["run_ignored: %b", config.run_ignored]);
    logv(c, #fmt["filter: %s", opt_str(config.filter)]);
    logv(c, #fmt["runtool: %s", opt_str(config.runtool)]);
    logv(c, #fmt["rustcflags: %s", opt_str(config.rustcflags)]);
    logv(c, #fmt["verbose: %b", config.verbose]);
    logv(c, #fmt["\n"]);
}

fn opt_str(maybestr: option<str>) -> str {
    alt maybestr { option::some(s) { s } option::none { "(none)" } }
}

fn str_opt(maybestr: str) -> option<str> {
    if maybestr != "(none)" { option::some(maybestr) } else { option::none }
}

fn str_mode(s: str) -> mode {
    alt s {
      "compile-fail" { mode_compile_fail }
      "run-fail" { mode_run_fail }
      "run-pass" { mode_run_pass }
      "pretty" { mode_pretty }
      _ { fail "invalid mode" }
    }
}

fn mode_str(mode: mode) -> str {
    alt mode {
      mode_compile_fail { "compile-fail" }
      mode_run_fail { "run-fail" }
      mode_run_pass { "run-pass" }
      mode_pretty { "pretty" }
    }
}

fn run_tests(config: config) {
    let opts = test_opts(config);
    let tests = make_tests(config);
    let res = test::run_tests_console(opts, tests);
    if !res { fail "Some tests failed"; }
}

fn test_opts(config: config) -> test::test_opts {
    {filter:
         alt config.filter {
           option::some(s) { option::some(s) }
           option::none { option::none }
         },
     run_ignored: config.run_ignored}
}

fn make_tests(config: config) -> [test::test_desc] {
    #debug("making tests from %s", config.src_base);
    let tests = [];
    for file: str in os::list_dir(config.src_base) {
        let file = file;
        #debug("inspecting file %s", file);
        if is_test(config, file) {
            tests += [make_test(config, file)]
        }
    }
    ret tests;
}

fn is_test(config: config, testfile: str) -> bool {
    // Pretty-printer does not work with .rc files yet
    let valid_extensions =
        alt config.mode { mode_pretty { [".rs"] } _ { [".rc", ".rs"] } };
    let invalid_prefixes = [".", "#", "~"];
    let name = path::basename(testfile);

    let valid = false;

    for ext in valid_extensions {
        if str::ends_with(name, ext) { valid = true; }
    }

    for pre in invalid_prefixes {
        if str::starts_with(name, pre) { valid = false; }
    }

    ret valid;
}

fn make_test(config: config, testfile: str) ->
   test::test_desc {
    {
        name: make_test_name(config, testfile),
        fn: make_test_closure(config, testfile),
        ignore: header::is_test_ignored(config, testfile),
        should_fail: false
    }
}

fn make_test_name(config: config, testfile: str) -> str {
    #fmt["[%s] %s", mode_str(config.mode), testfile]
}

fn make_test_closure(config: config, testfile: str) -> test::test_fn {
    ret {||
        runtest::run(config, copy testfile);
    };
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use ide_db::{helpers::FamousDefs, RootDatabase};
use syntax::{
    ast::{self, NameOwner},
    AstNode,
};

use crate::{
    assist_context::{AssistContext, Assists},
    utils::generate_trait_impl_text,
    AssistId, AssistKind,
};

// Assist: generate_deref
//
// Generate `Deref` impl using the given struct field.
//
// ```
// struct A;
// struct B {
//    $0a: A
// }
// ```
// ->
// ```
// struct A;
// struct B {
//    a: A
// }
//
// impl std::ops::Deref for B {
//     type Target = A;
//
//     fn deref(&self) -> &Self::Target {
//         &self.a
//     }
// }
// ```
pub(crate) fn generate_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::RecordField>()?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let field_name = field.name()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field_name),
        target,
        |edit| {
            let start_offset = strukt.syntax().text_range().end();
            let impl_code = format!(
                r#"    type Target = {0};

    fn deref(&self) -> &Self::Target {{
        &self.{1}
    }}"#,
                field_type.syntax(),
                field_name.syntax()
            );
            let strukt_adt = ast::Adt::Struct(strukt);
            // Q for reviewer: Is there a better way to specify the trait_text, e.g.
            // - can I have it auto `use std::ops::Deref`, and then just use `Deref` as the trait text?
            //   Or is there a helper that might detect if `std::ops::Deref` has been used, and pick `Deref`,
            //   otherwise, pick `std::ops::Deref` for the trait_text.
            let deref_impl = generate_trait_impl_text(&strukt_adt, "std::ops::Deref", &impl_code);
            edit.insert(start_offset, deref_impl);
        },
    )
}

fn existing_deref_impl(
    sema: &'_ hir::Semantics<'_, RootDatabase>,
    strukt: &ast::Struct,
) -> Option<()> {
    let strukt = sema.to_def(strukt)?;
    let krate = strukt.module(sema.db).krate();

    let deref_trait = FamousDefs(sema, Some(krate)).core_ops_Deref()?;
    let strukt_type = strukt.ty(sema.db);

    if strukt_type.impls_trait(sema.db, deref_trait, &[]) {
        Some(())
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_generate_deref() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B { $0a: A }"#,
            r#"struct A { }
struct B { a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        );
    }

    fn check_not_applicable(ra_fixture: &str) {
        let fixture = format!(
            "//- /main.rs crate:main deps:core,std\n{}\n{}",
            ra_fixture,
            FamousDefs::FIXTURE
        );
        check_assist_not_applicable(generate_deref, &fixture)
    }

    #[test]
    fn test_generate_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_deref_impl_already_exists);
        check_not_applicable(
            r#"struct A { }
struct B { $0a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        )
    }
}
<commit_msg>implement field stuff too<commit_after>use std::fmt::Display;

use ide_db::{helpers::FamousDefs, RootDatabase};
use syntax::{
    ast::{self, NameOwner},
    AstNode, SyntaxNode,
};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    utils::generate_trait_impl_text,
    AssistId, AssistKind,
};

// Assist: generate_deref
//
// Generate `Deref` impl using the given struct field.
//
// ```
// struct A;
// struct B {
//    $0a: A
// }
// ```
// ->
// ```
// struct A;
// struct B {
//    a: A
// }
//
// impl std::ops::Deref for B {
//     type Target = A;
//
//     fn deref(&self) -> &Self::Target {
//         &self.a
//     }
// }
// ```
pub(crate) fn generate_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    generate_record_deref(acc, ctx).or_else(|| generate_tuple_deref(acc, ctx))
}

fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::RecordField>()?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_record_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let field_name = field.name()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field_name),
        target,
        |edit| generate_edit(edit, strukt, field_type.syntax(), field_name.syntax()),
    )
}

fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::TupleField>()?;
    let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
    let field_list_index =
        field_list.syntax().children().into_iter().position(|s| &s == field.syntax())?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_field_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field.syntax()),
        target,
        |edit| generate_edit(edit, strukt, field_type.syntax(), field_list_index),
    )
}

fn generate_edit(
    edit: &mut AssistBuilder,
    strukt: ast::Struct,
    field_type_syntax: &SyntaxNode,
    field_name: impl Display,
) {
    let start_offset = strukt.syntax().text_range().end();
    let impl_code = format!(
        r#"    type Target = {0};

    fn deref(&self) -> &Self::Target {{
        &self.{1}
    }}"#,
        field_type_syntax, field_name
    );
    let strukt_adt = ast::Adt::Struct(strukt);
    let deref_impl = generate_trait_impl_text(&strukt_adt, "std::ops::Deref", &impl_code);
    edit.insert(start_offset, deref_impl);
}

fn existing_deref_impl(
    sema: &'_ hir::Semantics<'_, RootDatabase>,
    strukt: &ast::Struct,
) -> Option<()> {
    let strukt = sema.to_def(strukt)?;
    let krate = strukt.module(sema.db).krate();

    let deref_trait = FamousDefs(sema, Some(krate)).core_ops_Deref()?;
    let strukt_type = strukt.ty(sema.db);

    if strukt_type.impls_trait(sema.db, deref_trait, &[]) {
        Some(())
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_generate_record_deref() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B { $0a: A }"#,
            r#"struct A { }
struct B { a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        );
    }

    #[test]
    fn test_generate_field_deref_idx_0() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B($0A);"#,
            r#"struct A { }
struct B(A);

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}"#,
        );
    }
    #[test]
    fn test_generate_field_deref_idx_1() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B(u8, $0A);"#,
            r#"struct A { }
struct B(u8, A);

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.1
    }
}"#,
        );
    }

    fn check_not_applicable(ra_fixture: &str) {
        let fixture = format!(
            "//- /main.rs crate:main deps:core,std\n{}\n{}",
            ra_fixture,
            FamousDefs::FIXTURE
        );
        check_assist_not_applicable(generate_deref, &fixture)
    }

    #[test]
    fn test_generate_record_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_record_deref_impl_already_exists);
        check_not_applicable(
            r#"struct A { }
struct B { $0a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        )
    }

    #[test]
    fn test_generate_field_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_field_deref_impl_already_exists);
        check_not_applicable(
            r#"struct A { }
struct B($0A)

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}"#,
        )
    }
}
<|endoftext|>


<commit_before>/// This modules specifies the input to rust-analyzer. In some sense, this is
/// **the** most important module, because all other fancy stuff is strictly
/// derived from this input.
///
/// Note that neither this module, nor any other part of the analyzer's core do
/// actual IO. See `vfs` and `project_model` in `ra_lsp_server` crate for how
/// actual IO is done and lowered to input.
use std::sync::Arc;

use relative_path::RelativePathBuf;
use rustc_hash::FxHashMap;
use salsa;

use ra_syntax::SmolStr;

/// `FileId` is an integer which uniquely identifies a file. File paths are
/// messy and system-dependent, so most of the code should work directly with
/// `FileId`, without inspecting the path. The mapping between `FileId` and path
/// and `SourceRoot` is constant. File rename is represented as a pair of
/// deletion/creation.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub u32);

/// Files are grouped into source roots. A source root is a directory on the
/// file systems which is watched for changes. Typically it corresponds to a
/// Cargo package. Source roots *might* be nested: in this case, file belongs to
/// the nearest enclosing source root. Path to files are always relative to a
/// source root, and analyzer does not know the root path of the source root at
/// all. So, a file from one source root can't refere a file in another source
/// root by path.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SourceRootId(pub u32);

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct SourceRoot {
    pub files: FxHashMap<RelativePathBuf, FileId>,
}

/// `CrateGraph` is a bit of information which turns a set of text files into a
/// number of Rust crates. Each Crate is the `FileId` of it's root module, the
/// set of cfg flags (not yet implemented) and the set of dependencies. Note
/// that, due to cfg's, there might be several crates for a single `FileId`! As
/// in the rust-lang proper, a crate does not have a name. Instead, names are
/// specified on dependency edges. That is, a crate might be known under
/// different names in different dependant crates.
///
/// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust
/// langauge proper, not a concept of the build system. In practice, we get
/// `CrateGraph` by lowering `cargo metadata` output.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CrateGraph {
    arena: FxHashMap<CrateId, CrateData>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);

#[derive(Debug, Clone, PartialEq, Eq)]
struct CrateData {
    file_id: FileId,
    dependencies: Vec<Dependency>,
}

impl CrateData {
    fn new(file_id: FileId) -> CrateData {
        CrateData {
            file_id,
            dependencies: Vec::new(),
        }
    }

    fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) {
        self.dependencies.push(Dependency { name, crate_id })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dependency {
    pub crate_id: CrateId,
    pub name: SmolStr,
}

impl Dependency {
    pub fn crate_id(&self) -> CrateId {
        self.crate_id
    }
}

impl CrateGraph {
    pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
        let crate_id = CrateId(self.arena.len() as u32);
        let prev = self.arena.insert(crate_id, CrateData::new(file_id));
        assert!(prev.is_none());
        crate_id
    }
    pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) {
        if self.dfs(from, to) {
           panic!("Cycle dependencies found.")
        }
        self.arena.get_mut(&from).unwrap().add_dep(name, to)
    }
    pub fn crate_root(&self, crate_id: CrateId) -> FileId {
        self.arena[&crate_id].file_id
    }
    pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
        let (&crate_id, _) = self
            .arena
            .iter()
            .find(|(_crate_id, data)| data.file_id == file_id)?;
        Some(crate_id)
    }
    pub fn dependencies<'a>(
        &'a self,
        crate_id: CrateId,
    ) -> impl Iterator<Item=&'a Dependency> + 'a {
        self.arena[&crate_id].dependencies.iter()
    }
    fn dfs(&self, target: CrateId, from: CrateId) -> bool {
        for dep in self.dependencies(from) {
            let crate_id = dep.crate_id();
            if crate_id == target {
                return true;
            }
            if self.arena.contains_key(&crate_id) {
                if self.dfs(target, crate_id) {
                    return true;
                }
            }
        }
        return false;
    }
}

mod test {
    use super::{CrateGraph, FxHashMap, FileId, SmolStr};
    #[test]
    #[should_panic]
    fn it_should_painc_because_of_cycle_dependencies() {
        let mut graph = CrateGraph {
            arena: FxHashMap::default()
        };
        let crate1 = graph.add_crate_root(FileId(1u32));
        let crate2 = graph.add_crate_root(FileId(2u32));
        let crate3 = graph.add_crate_root(FileId(3u32));
        graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
        graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
        graph.add_dep(crate3, SmolStr::new("crate1"), crate1);
    }

    #[test]
    fn it_works() {
        let mut graph = CrateGraph {
            arena: FxHashMap::default()
        };
        let crate1 = graph.add_crate_root(FileId(1u32));
        let crate2 = graph.add_crate_root(FileId(2u32));
        let crate3 = graph.add_crate_root(FileId(3u32));
        graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
        graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
    }
}

salsa::query_group! {
    pub trait FilesDatabase: salsa::Database {
        /// Text of the file.
        fn file_text(file_id: FileId) -> Arc<String> {
            type FileTextQuery;
            storage input;
        }
        /// Path to a file, relative to the root of its source root.
        fn file_relative_path(file_id: FileId) -> RelativePathBuf {
            type FileRelativePathQuery;
            storage input;
        }
        /// Source root of the file.
        fn file_source_root(file_id: FileId) -> SourceRootId {
            type FileSourceRootQuery;
            storage input;
        }
        /// Contents of the source root.
        fn source_root(id: SourceRootId) -> Arc<SourceRoot> {
            type SourceRootQuery;
            storage input;
        }
        /// The set of "local" (that is, from the current workspace) roots.
        /// Files in local roots are assumed to change frequently.
        fn local_roots() -> Arc<Vec<SourceRootId>> {
            type LocalRootsQuery;
            storage input;
        }
        /// The set of roots for crates.io libraries.
        /// Files in libraries are assumed to never change.
        fn library_roots() -> Arc<Vec<SourceRootId>> {
            type LibraryRootsQuery;
            storage input;
        }
        /// The crate graph.
        fn crate_graph() -> Arc<CrateGraph> {
            type CrateGraphQuery;
            storage input;
        }
    }
}
<commit_msg>rename to dfs_find<commit_after>/// This modules specifies the input to rust-analyzer. In some sense, this is
/// **the** most important module, because all other fancy stuff is strictly
/// derived from this input.
///
/// Note that neither this module, nor any other part of the analyzer's core do
/// actual IO. See `vfs` and `project_model` in `ra_lsp_server` crate for how
/// actual IO is done and lowered to input.
use std::sync::Arc;

use relative_path::RelativePathBuf;
use rustc_hash::FxHashMap;
use salsa;

use ra_syntax::SmolStr;

/// `FileId` is an integer which uniquely identifies a file. File paths are
/// messy and system-dependent, so most of the code should work directly with
/// `FileId`, without inspecting the path. The mapping between `FileId` and path
/// and `SourceRoot` is constant. File rename is represented as a pair of
/// deletion/creation.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub u32);

/// Files are grouped into source roots. A source root is a directory on the
/// file systems which is watched for changes. Typically it corresponds to a
/// Cargo package. Source roots *might* be nested: in this case, file belongs to
/// the nearest enclosing source root. Path to files are always relative to a
/// source root, and analyzer does not know the root path of the source root at
/// all. So, a file from one source root can't refere a file in another source
/// root by path.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SourceRootId(pub u32);

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct SourceRoot {
    pub files: FxHashMap<RelativePathBuf, FileId>,
}

/// `CrateGraph` is a bit of information which turns a set of text files into a
/// number of Rust crates. Each Crate is the `FileId` of it's root module, the
/// set of cfg flags (not yet implemented) and the set of dependencies. Note
/// that, due to cfg's, there might be several crates for a single `FileId`! As
/// in the rust-lang proper, a crate does not have a name. Instead, names are
/// specified on dependency edges. That is, a crate might be known under
/// different names in different dependant crates.
///
/// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust
/// langauge proper, not a concept of the build system. In practice, we get
/// `CrateGraph` by lowering `cargo metadata` output.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CrateGraph {
    arena: FxHashMap<CrateId, CrateData>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);

#[derive(Debug, Clone, PartialEq, Eq)]
struct CrateData {
    file_id: FileId,
    dependencies: Vec<Dependency>,
}

impl CrateData {
    fn new(file_id: FileId) -> CrateData {
        CrateData {
            file_id,
            dependencies: Vec::new(),
        }
    }

    fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) {
        self.dependencies.push(Dependency { name, crate_id })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dependency {
    pub crate_id: CrateId,
    pub name: SmolStr,
}

impl Dependency {
    pub fn crate_id(&self) -> CrateId {
        self.crate_id
    }
}

impl CrateGraph {
    pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
        let crate_id = CrateId(self.arena.len() as u32);
        let prev = self.arena.insert(crate_id, CrateData::new(file_id));
        assert!(prev.is_none());
        crate_id
    }
    pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) {
        if self.dfs_find(from, to) {
           panic!("Cycle dependencies found.")
        }
        self.arena.get_mut(&from).unwrap().add_dep(name, to)
    }
    pub fn crate_root(&self, crate_id: CrateId) -> FileId {
        self.arena[&crate_id].file_id
    }
    pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
        let (&crate_id, _) = self
            .arena
            .iter()
            .find(|(_crate_id, data)| data.file_id == file_id)?;
        Some(crate_id)
    }
    pub fn dependencies<'a>(
        &'a self,
        crate_id: CrateId,
    ) -> impl Iterator<Item=&'a Dependency> + 'a {
        self.arena[&crate_id].dependencies.iter()
    }
    fn dfs_find(&self, target: CrateId, from: CrateId) -> bool {
        for dep in self.dependencies(from) {
            let crate_id = dep.crate_id();
            if crate_id == target {
                return true;
            }
            if self.arena.contains_key(&crate_id) {
                if self.dfs_find(target, crate_id) {
                    return true;
                }
            }
        }
        return false;
    }
}

mod test {
    use super::{CrateGraph, FxHashMap, FileId, SmolStr};
    #[test]
    #[should_panic]
    fn it_should_painc_because_of_cycle_dependencies() {
        let mut graph = CrateGraph {
            arena: FxHashMap::default()
        };
        let crate1 = graph.add_crate_root(FileId(1u32));
        let crate2 = graph.add_crate_root(FileId(2u32));
        let crate3 = graph.add_crate_root(FileId(3u32));
        graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
        graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
        graph.add_dep(crate3, SmolStr::new("crate1"), crate1);
    }

    #[test]
    fn it_works() {
        let mut graph = CrateGraph {
            arena: FxHashMap::default()
        };
        let crate1 = graph.add_crate_root(FileId(1u32));
        let crate2 = graph.add_crate_root(FileId(2u32));
        let crate3 = graph.add_crate_root(FileId(3u32));
        graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
        graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
    }
}

salsa::query_group! {
    pub trait FilesDatabase: salsa::Database {
        /// Text of the file.
        fn file_text(file_id: FileId) -> Arc<String> {
            type FileTextQuery;
            storage input;
        }
        /// Path to a file, relative to the root of its source root.
        fn file_relative_path(file_id: FileId) -> RelativePathBuf {
            type FileRelativePathQuery;
            storage input;
        }
        /// Source root of the file.
        fn file_source_root(file_id: FileId) -> SourceRootId {
            type FileSourceRootQuery;
            storage input;
        }
        /// Contents of the source root.
        fn source_root(id: SourceRootId) -> Arc<SourceRoot> {
            type SourceRootQuery;
            storage input;
        }
        /// The set of "local" (that is, from the current workspace) roots.
        /// Files in local roots are assumed to change frequently.
        fn local_roots() -> Arc<Vec<SourceRootId>> {
            type LocalRootsQuery;
            storage input;
        }
        /// The set of roots for crates.io libraries.
        /// Files in libraries are assumed to never change.
        fn library_roots() -> Arc<Vec<SourceRootId>> {
            type LibraryRootsQuery;
            storage input;
        }
        /// The crate graph.
        fn crate_graph() -> Arc<CrateGraph> {
            type CrateGraphQuery;
            storage input;
        }
    }
}
<|endoftext|>


<commit_before>use crate::{enum_map, Enum, EnumMap};
use arbitrary::{Arbitrary, Result, Unstructured};

impl<'a, K: Enum<V>, V: Arbitrary<'a>> Arbitrary<'a> for EnumMap<K, V> {
    fn arbitrary(u: &mut Unstructured<'a>) -> Result<EnumMap<K, V>> {
        Ok(enum_map! {
            _ => Arbitrary::arbitrary(u)?,
        })
    }
}
<commit_msg>Implement Arbitrary::size_hint for EnumMap<commit_after>use crate::internal::Array;
use crate::{enum_map, Enum, EnumMap};
use arbitrary::{Arbitrary, Result, Unstructured};

impl<'a, K: Enum<V>, V: Arbitrary<'a>> Arbitrary<'a> for EnumMap<K, V> {
    fn arbitrary(u: &mut Unstructured<'a>) -> Result<EnumMap<K, V>> {
        Ok(enum_map! {
            _ => Arbitrary::arbitrary(u)?,
        })
    }

    fn size_hint(depth: usize) -> (usize, Option<usize>) {
        if K::Array::LENGTH == 0 {
            (0, Some(0))
        } else {
            let (lo, hi) = V::size_hint(depth);
            (
                lo.saturating_mul(K::Array::LENGTH),
                hi.and_then(|hi| hi.checked_mul(K::Array::LENGTH)),
            )
        }
    }
}
<|endoftext|>


<commit_before>use boxcars::crc::calc_crc;
use boxcars::*;
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use serde_json;

fn bench_crc(c: &mut Criterion) {
    let data = include_bytes!("../assets/replays/good/rumble.replay");
    let mut group = c.benchmark_group("crc_throughput");
    group.throughput(Throughput::Bytes(data.len() as u64));
    group.bench_function("bench_crc", |b| {
        let data = include_bytes!("../assets/replays/good/rumble.replay");
        b.iter(|| {
            black_box(calc_crc(&data[..]));
        })
    });
    group.finish();
}

fn bench_parse_crc_body(c: &mut Criterion) {
    c.bench_function("bench_parse_crc_body", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");
        b.iter(|| {
            black_box(
                ParserBuilder::new(data)
                    .always_check_crc()
                    .must_parse_network_data()
                    .parse()
                    .is_ok(),
            )
        });
    });
}

fn bench_parse_no_crc_body(c: &mut Criterion) {
    c.bench_function("bench_parse_no_crc_body", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");
        b.iter(|| {
            black_box(
                ParserBuilder::new(data)
                    .on_error_check_crc()
                    .must_parse_network_data()
                    .parse()
                    .is_ok(),
            )
        });
    });
}

fn bench_parse_no_crc_no_body(c: &mut Criterion) {
    c.bench_function("bench_parse_no_crc_no_body", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");
        b.iter(|| {
            black_box(
                ParserBuilder::new(data)
                    .on_error_check_crc()
                    .never_parse_network_data()
                    .parse()
                    .is_ok(),
            )
        });
    });
}

fn bench_parse_crc_json(c: &mut Criterion) {
    c.bench_function("bench_parse_crc_json", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");

        // allocate a buffer big enough to hold all of the serialized data
        let mut bytes = Vec::with_capacity(2_usize.pow(25));
        b.iter(|| {
            let data = ParserBuilder::new(data).always_check_crc().parse().unwrap();
            black_box(serde_json::to_writer(&mut bytes, &data).is_ok());
            unsafe { bytes.set_len(0); }
        });
    });
}

fn bench_parse_no_crc_json(c: &mut Criterion) {
    c.bench_function("bench_parse_no_crc_json", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");

        // allocate a buffer big enough to hold all of the serialized data
        let mut bytes = Vec::with_capacity(2_usize.pow(25));
        b.iter(|| {
            let replay = ParserBuilder::new(data)
                .on_error_check_crc()
                .parse()
                .unwrap();
            black_box(serde_json::to_writer(&mut bytes, &replay).is_ok());
            unsafe { bytes.set_len(0); }
        });
    });
}

criterion_group!(
    benches,
    bench_crc,
    bench_parse_crc_body,
    bench_parse_no_crc_body,
    bench_parse_no_crc_no_body,
    bench_parse_crc_json,
    bench_parse_no_crc_json
);

criterion_main!(benches);
<commit_msg>Add pure json serialization benchmark<commit_after>use boxcars::crc::calc_crc;
use boxcars::*;
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};

fn bench_crc(c: &mut Criterion) {
    let data = include_bytes!("../assets/replays/good/rumble.replay");
    let mut group = c.benchmark_group("crc_throughput");
    group.throughput(Throughput::Bytes(data.len() as u64));
    group.bench_function("bench_crc", |b| {
        let data = include_bytes!("../assets/replays/good/rumble.replay");
        b.iter(|| {
            black_box(calc_crc(&data[..]));
        })
    });
    group.finish();
}

fn bench_json_serialization(c: &mut Criterion) {
    let data = include_bytes!("../assets/replays/good/3381.replay");
    let mut bytes = Vec::new();
    let replay = ParserBuilder::new(data)
        .on_error_check_crc()
        .parse()
        .unwrap();
    serde_json::to_writer(&mut bytes, &replay).unwrap();

    let mut group = c.benchmark_group("json_throughput");
    group.throughput(Throughput::Bytes(bytes.len() as u64));
    unsafe { bytes.set_len(0); };

    group.bench_function("bench_json_serialization", |b| {
        b.iter(|| {
            black_box(serde_json::to_writer(&mut bytes, &replay).is_ok());
            unsafe { bytes.set_len(0); };
        })
    });
    group.finish();
}

fn bench_parse_crc_body(c: &mut Criterion) {
    c.bench_function("bench_parse_crc_body", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");
        b.iter(|| {
            black_box(
                ParserBuilder::new(data)
                    .always_check_crc()
                    .must_parse_network_data()
                    .parse()
                    .is_ok(),
            )
        });
    });
}

fn bench_parse_no_crc_body(c: &mut Criterion) {
    c.bench_function("bench_parse_no_crc_body", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");
        b.iter(|| {
            black_box(
                ParserBuilder::new(data)
                    .on_error_check_crc()
                    .must_parse_network_data()
                    .parse()
                    .is_ok(),
            )
        });
    });
}

fn bench_parse_no_crc_no_body(c: &mut Criterion) {
    c.bench_function("bench_parse_no_crc_no_body", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");
        b.iter(|| {
            black_box(
                ParserBuilder::new(data)
                    .on_error_check_crc()
                    .never_parse_network_data()
                    .parse()
                    .is_ok(),
            )
        });
    });
}

fn bench_parse_crc_json(c: &mut Criterion) {
    c.bench_function("bench_parse_crc_json", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");

        // allocate a buffer big enough to hold all of the serialized data
        let mut bytes = Vec::with_capacity(2_usize.pow(25));
        b.iter(|| {
            let data = ParserBuilder::new(data).always_check_crc().parse().unwrap();
            black_box(serde_json::to_writer(&mut bytes, &data).is_ok());
            unsafe { bytes.set_len(0); }
        });
    });
}

fn bench_parse_no_crc_json(c: &mut Criterion) {
    c.bench_function("bench_parse_no_crc_json", |b| {
        let data = include_bytes!("../assets/replays/good/3381.replay");

        // allocate a buffer big enough to hold all of the serialized data
        let mut bytes = Vec::with_capacity(2_usize.pow(25));
        b.iter(|| {
            let replay = ParserBuilder::new(data)
                .on_error_check_crc()
                .parse()
                .unwrap();
            black_box(serde_json::to_writer(&mut bytes, &replay).is_ok());
            unsafe { bytes.set_len(0); }
        });
    });
}

criterion_group!(
    benches,
    bench_crc,
    bench_json_serialization,
    bench_parse_crc_body,
    bench_parse_no_crc_body,
    bench_parse_no_crc_no_body,
    bench_parse_crc_json,
    bench_parse_no_crc_json
);

criterion_main!(benches);
<|endoftext|>


<commit_before>use crate::core::META_FILEPATH;
use crate::directory::error::{DeleteError, OpenReadError, OpenWriteError};
use crate::directory::AntiCallToken;
use crate::directory::WatchCallbackList;
use crate::directory::{Directory, FileSlice, WatchCallback, WatchHandle};
use crate::directory::{TerminatingWrite, WritePtr};
use common::HasLen;
use fail::fail_point;
use std::collections::HashMap;
use std::fmt;
use std::io::{self, BufWriter, Cursor, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::result;
use std::sync::{Arc, RwLock};

use super::FileHandle;

/// Writer associated with the `RamDirectory`
///
/// The Writer just writes a buffer.
///
/// # Panics
///
/// On drop, if the writer was left in a *dirty* state.
/// That is, if flush was not called after the last call
/// to write.
///
struct VecWriter {
    path: PathBuf,
    shared_directory: RamDirectory,
    data: Cursor<Vec<u8>>,
    is_flushed: bool,
}

impl VecWriter {
    fn new(path_buf: PathBuf, shared_directory: RamDirectory) -> VecWriter {
        VecWriter {
            path: path_buf,
            data: Cursor::new(Vec::new()),
            shared_directory,
            is_flushed: true,
        }
    }
}

impl Drop for VecWriter {
    fn drop(&mut self) {
        if !self.is_flushed {
            panic!(
                "You forgot to flush {:?} before its writter got Drop. Do not rely on drop. This also occurs when the indexer crashed, so you may want to check the logs for the root cause.",
                self.path
            )
        }
    }
}

impl Seek for VecWriter {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.data.seek(pos)
    }
}

impl Write for VecWriter {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.is_flushed = false;
        self.data.write_all(buf)?;
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        self.is_flushed = true;
        let mut fs = self.shared_directory.fs.write().unwrap();
        fs.write(self.path.clone(), self.data.get_ref());
        Ok(())
    }
}

impl TerminatingWrite for VecWriter {
    fn terminate_ref(&mut self, _: AntiCallToken) -> io::Result<()> {
        self.flush()
    }
}

#[derive(Default)]
struct InnerDirectory {
    fs: HashMap<PathBuf, FileSlice>,
    watch_router: WatchCallbackList,
}

impl InnerDirectory {
    fn write(&mut self, path: PathBuf, data: &[u8]) -> bool {
        let data = FileSlice::from(data.to_vec());
        self.fs.insert(path, data).is_some()
    }

    fn open_read(&self, path: &Path) -> Result<FileSlice, OpenReadError> {
        self.fs
            .get(path)
            .ok_or_else(|| OpenReadError::FileDoesNotExist(PathBuf::from(path)))
            .map(Clone::clone)
    }

    fn delete(&mut self, path: &Path) -> result::Result<(), DeleteError> {
        match self.fs.remove(path) {
            Some(_) => Ok(()),
            None => Err(DeleteError::FileDoesNotExist(PathBuf::from(path))),
        }
    }

    fn exists(&self, path: &Path) -> bool {
        self.fs.contains_key(path)
    }

    fn watch(&mut self, watch_handle: WatchCallback) -> WatchHandle {
        self.watch_router.subscribe(watch_handle)
    }

    fn total_mem_usage(&self) -> usize {
        self.fs.values().map(|f| f.len()).sum()
    }
}

impl fmt::Debug for RamDirectory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "RamDirectory")
    }
}

/// A Directory storing everything in anonymous memory.
///
/// It is mainly meant for unit testing.
/// Writes are only made visible upon flushing.
///
#[derive(Clone, Default)]
pub struct RamDirectory {
    fs: Arc<RwLock<InnerDirectory>>,
}

impl RamDirectory {
    /// Constructor
    pub fn create() -> RamDirectory {
        Self::default()
    }

    /// Returns the sum of the size of the different files
    /// in the RamDirectory.
    pub fn total_mem_usage(&self) -> usize {
        self.fs.read().unwrap().total_mem_usage()
    }

    /// Write a copy of all of the files saved in the RamDirectory in the target `Directory`.
    ///
    /// Files are all written using the `Directory::write` meaning, even if they were
    /// written using the `atomic_write` api.
    ///
    /// If an error is encounterred, files may be persisted partially.
    pub fn persist(&self, dest: &dyn Directory) -> crate::Result<()> {
        let wlock = self.fs.write().unwrap();
        for (path, file) in wlock.fs.iter() {
            let mut dest_wrt = dest.open_write(path)?;
            dest_wrt.write_all(file.read_bytes()?.as_slice())?;
            dest_wrt.terminate()?;
        }
        Ok(())
    }
}

impl Directory for RamDirectory {
    fn get_file_handle(&self, path: &Path) -> Result<Box<dyn FileHandle>, OpenReadError> {
        let file_slice = self.open_read(path)?;
        Ok(Box::new(file_slice))
    }

    fn open_read(&self, path: &Path) -> result::Result<FileSlice, OpenReadError> {
        self.fs.read().unwrap().open_read(path)
    }

    fn delete(&self, path: &Path) -> result::Result<(), DeleteError> {
        fail_point!("RamDirectory::delete", |_| {
            Err(DeleteError::IoError {
                io_error: io::Error::from(io::ErrorKind::Other),
                filepath: path.to_path_buf(),
            })
        });
        self.fs.write().unwrap().delete(path)
    }

    fn exists(&self, path: &Path) -> Result<bool, OpenReadError> {
        Ok(self
            .fs
            .read()
            .map_err(|e| OpenReadError::IoError {
                io_error: io::Error::new(io::ErrorKind::Other, e.to_string()),
                filepath: path.to_path_buf(),
            })?
            .exists(path))
    }

    fn open_write(&self, path: &Path) -> Result<WritePtr, OpenWriteError> {
        let mut fs = self.fs.write().unwrap();
        let path_buf = PathBuf::from(path);
        let vec_writer = VecWriter::new(path_buf.clone(), self.clone());
        let exists = fs.write(path_buf.clone(), &[]);
        // force the creation of the file to mimic the MMap directory.
        if exists {
            Err(OpenWriteError::FileAlreadyExists(path_buf))
        } else {
            Ok(BufWriter::new(Box::new(vec_writer)))
        }
    }

    fn atomic_read(&self, path: &Path) -> Result<Vec<u8>, OpenReadError> {
        let bytes =
            self.open_read(path)?
                .read_bytes()
                .map_err(|io_error| OpenReadError::IoError {
                    io_error,
                    filepath: path.to_path_buf(),
                })?;
        Ok(bytes.as_slice().to_owned())
    }

    fn atomic_write(&self, path: &Path, data: &[u8]) -> io::Result<()> {
        fail_point!("RamDirectory::atomic_write", |msg| Err(io::Error::new(
            io::ErrorKind::Other,
            msg.unwrap_or_else(|| "Undefined".to_string())
        )));
        let path_buf = PathBuf::from(path);

        self.fs.write().unwrap().write(path_buf, data);

        if path == *META_FILEPATH {
            let _ = self.fs.write().unwrap().watch_router.broadcast();
        }
        Ok(())
    }

    fn watch(&self, watch_callback: WatchCallback) -> crate::Result<WatchHandle> {
        Ok(self.fs.write().unwrap().watch(watch_callback))
    }
}

#[cfg(test)]
mod tests {
    use super::RamDirectory;
    use crate::Directory;
    use std::io::Write;
    use std::path::Path;

    #[test]
    fn test_persist() {
        let msg_atomic: &'static [u8] = b"atomic is the way";
        let msg_seq: &'static [u8] = b"sequential is the way";
        let path_atomic: &'static Path = Path::new("atomic");
        let path_seq: &'static Path = Path::new("seq");
        let directory = RamDirectory::create();
        assert!(directory.atomic_write(path_atomic, msg_atomic).is_ok());
        let mut wrt = directory.open_write(path_seq).unwrap();
        assert!(wrt.write_all(msg_seq).is_ok());
        assert!(wrt.flush().is_ok());
        let directory_copy = RamDirectory::create();
        assert!(directory.persist(&directory_copy).is_ok());
        assert_eq!(directory_copy.atomic_read(path_atomic).unwrap(), msg_atomic);
        assert_eq!(directory_copy.atomic_read(path_seq).unwrap(), msg_seq);
    }
}
<commit_msg>Replacing the panic check in the RAM Directory on lack of flush.<commit_after>use crate::core::META_FILEPATH;
use crate::directory::error::{DeleteError, OpenReadError, OpenWriteError};
use crate::directory::AntiCallToken;
use crate::directory::WatchCallbackList;
use crate::directory::{Directory, FileSlice, WatchCallback, WatchHandle};
use crate::directory::{TerminatingWrite, WritePtr};
use common::HasLen;
use fail::fail_point;
use std::collections::HashMap;
use std::fmt;
use std::io::{self, BufWriter, Cursor, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::result;
use std::sync::{Arc, RwLock};

use super::FileHandle;

/// Writer associated with the `RamDirectory`
///
/// The Writer just writes a buffer.
///
/// # Panics
///
/// On drop, if the writer was left in a *dirty* state.
/// That is, if flush was not called after the last call
/// to write.
///
struct VecWriter {
    path: PathBuf,
    shared_directory: RamDirectory,
    data: Cursor<Vec<u8>>,
    is_flushed: bool,
}

impl VecWriter {
    fn new(path_buf: PathBuf, shared_directory: RamDirectory) -> VecWriter {
        VecWriter {
            path: path_buf,
            data: Cursor::new(Vec::new()),
            shared_directory,
            is_flushed: true,
        }
    }
}

impl Drop for VecWriter {
    fn drop(&mut self) {
        if !self.is_flushed {
            warn!(
                "You forgot to flush {:?} before its writter got Drop. Do not rely on drop. This also occurs when the indexer crashed, so you may want to check the logs for the root cause.",
                self.path
            )
        }
    }
}

impl Seek for VecWriter {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.data.seek(pos)
    }
}

impl Write for VecWriter {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.is_flushed = false;
        self.data.write_all(buf)?;
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        self.is_flushed = true;
        let mut fs = self.shared_directory.fs.write().unwrap();
        fs.write(self.path.clone(), self.data.get_ref());
        Ok(())
    }
}

impl TerminatingWrite for VecWriter {
    fn terminate_ref(&mut self, _: AntiCallToken) -> io::Result<()> {
        self.flush()
    }
}

#[derive(Default)]
struct InnerDirectory {
    fs: HashMap<PathBuf, FileSlice>,
    watch_router: WatchCallbackList,
}

impl InnerDirectory {
    fn write(&mut self, path: PathBuf, data: &[u8]) -> bool {
        let data = FileSlice::from(data.to_vec());
        self.fs.insert(path, data).is_some()
    }

    fn open_read(&self, path: &Path) -> Result<FileSlice, OpenReadError> {
        self.fs
            .get(path)
            .ok_or_else(|| OpenReadError::FileDoesNotExist(PathBuf::from(path)))
            .map(Clone::clone)
    }

    fn delete(&mut self, path: &Path) -> result::Result<(), DeleteError> {
        match self.fs.remove(path) {
            Some(_) => Ok(()),
            None => Err(DeleteError::FileDoesNotExist(PathBuf::from(path))),
        }
    }

    fn exists(&self, path: &Path) -> bool {
        self.fs.contains_key(path)
    }

    fn watch(&mut self, watch_handle: WatchCallback) -> WatchHandle {
        self.watch_router.subscribe(watch_handle)
    }

    fn total_mem_usage(&self) -> usize {
        self.fs.values().map(|f| f.len()).sum()
    }
}

impl fmt::Debug for RamDirectory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "RamDirectory")
    }
}

/// A Directory storing everything in anonymous memory.
///
/// It is mainly meant for unit testing.
/// Writes are only made visible upon flushing.
///
#[derive(Clone, Default)]
pub struct RamDirectory {
    fs: Arc<RwLock<InnerDirectory>>,
}

impl RamDirectory {
    /// Constructor
    pub fn create() -> RamDirectory {
        Self::default()
    }

    /// Returns the sum of the size of the different files
    /// in the RamDirectory.
    pub fn total_mem_usage(&self) -> usize {
        self.fs.read().unwrap().total_mem_usage()
    }

    /// Write a copy of all of the files saved in the RamDirectory in the target `Directory`.
    ///
    /// Files are all written using the `Directory::write` meaning, even if they were
    /// written using the `atomic_write` api.
    ///
    /// If an error is encounterred, files may be persisted partially.
    pub fn persist(&self, dest: &dyn Directory) -> crate::Result<()> {
        let wlock = self.fs.write().unwrap();
        for (path, file) in wlock.fs.iter() {
            let mut dest_wrt = dest.open_write(path)?;
            dest_wrt.write_all(file.read_bytes()?.as_slice())?;
            dest_wrt.terminate()?;
        }
        Ok(())
    }
}

impl Directory for RamDirectory {
    fn get_file_handle(&self, path: &Path) -> Result<Box<dyn FileHandle>, OpenReadError> {
        let file_slice = self.open_read(path)?;
        Ok(Box::new(file_slice))
    }

    fn open_read(&self, path: &Path) -> result::Result<FileSlice, OpenReadError> {
        self.fs.read().unwrap().open_read(path)
    }

    fn delete(&self, path: &Path) -> result::Result<(), DeleteError> {
        fail_point!("RamDirectory::delete", |_| {
            Err(DeleteError::IoError {
                io_error: io::Error::from(io::ErrorKind::Other),
                filepath: path.to_path_buf(),
            })
        });
        self.fs.write().unwrap().delete(path)
    }

    fn exists(&self, path: &Path) -> Result<bool, OpenReadError> {
        Ok(self
            .fs
            .read()
            .map_err(|e| OpenReadError::IoError {
                io_error: io::Error::new(io::ErrorKind::Other, e.to_string()),
                filepath: path.to_path_buf(),
            })?
            .exists(path))
    }

    fn open_write(&self, path: &Path) -> Result<WritePtr, OpenWriteError> {
        let mut fs = self.fs.write().unwrap();
        let path_buf = PathBuf::from(path);
        let vec_writer = VecWriter::new(path_buf.clone(), self.clone());
        let exists = fs.write(path_buf.clone(), &[]);
        // force the creation of the file to mimic the MMap directory.
        if exists {
            Err(OpenWriteError::FileAlreadyExists(path_buf))
        } else {
            Ok(BufWriter::new(Box::new(vec_writer)))
        }
    }

    fn atomic_read(&self, path: &Path) -> Result<Vec<u8>, OpenReadError> {
        let bytes =
            self.open_read(path)?
                .read_bytes()
                .map_err(|io_error| OpenReadError::IoError {
                    io_error,
                    filepath: path.to_path_buf(),
                })?;
        Ok(bytes.as_slice().to_owned())
    }

    fn atomic_write(&self, path: &Path, data: &[u8]) -> io::Result<()> {
        fail_point!("RamDirectory::atomic_write", |msg| Err(io::Error::new(
            io::ErrorKind::Other,
            msg.unwrap_or_else(|| "Undefined".to_string())
        )));
        let path_buf = PathBuf::from(path);

        self.fs.write().unwrap().write(path_buf, data);

        if path == *META_FILEPATH {
            let _ = self.fs.write().unwrap().watch_router.broadcast();
        }
        Ok(())
    }

    fn watch(&self, watch_callback: WatchCallback) -> crate::Result<WatchHandle> {
        Ok(self.fs.write().unwrap().watch(watch_callback))
    }
}

#[cfg(test)]
mod tests {
    use super::RamDirectory;
    use crate::Directory;
    use std::io::Write;
    use std::path::Path;

    #[test]
    fn test_persist() {
        let msg_atomic: &'static [u8] = b"atomic is the way";
        let msg_seq: &'static [u8] = b"sequential is the way";
        let path_atomic: &'static Path = Path::new("atomic");
        let path_seq: &'static Path = Path::new("seq");
        let directory = RamDirectory::create();
        assert!(directory.atomic_write(path_atomic, msg_atomic).is_ok());
        let mut wrt = directory.open_write(path_seq).unwrap();
        assert!(wrt.write_all(msg_seq).is_ok());
        assert!(wrt.flush().is_ok());
        let directory_copy = RamDirectory::create();
        assert!(directory.persist(&directory_copy).is_ok());
        assert_eq!(directory_copy.atomic_read(path_atomic).unwrap(), msg_atomic);
        assert_eq!(directory_copy.atomic_read(path_seq).unwrap(), msg_seq);
    }
}
<|endoftext|>


<commit_before>use {Distribution, Generator};

/// A Bernoulli distribution.
#[derive(Clone, Copy)]
pub struct Bernoulli {
    /// The probability of success.
    pub p: f64,
    /// The probability of failure.
    pub q: f64,
}

impl Bernoulli {
    /// Create a Bernoulli distribution with success probability `p`.
    ///
    /// # Panics
    ///
    /// Panics if `p < 0` or `p > 1`.
    #[inline]
    pub fn new(p: f64) -> Bernoulli {
        debug_assert!(0. < p && p < 1., "Bernoulli::new() is called with p < 0 or p > 1");
        Bernoulli { p: p, q: 1. - p }
    }

    /// Create a Bernoulli distribution with failure probability `q`.
    ///
    /// # Panics
    ///
    /// Panics if `q < 0` or `q > 1`.
    #[inline]
    pub fn new_failprob(q: f64) -> Bernoulli {
        debug_assert!(0. < q && q < 1., "Bernoulli::new_failprob() is called with q < 0 or q > 1");
        Bernoulli { p: 1. - q, q: q }
    }

}

impl Distribution for Bernoulli {
    type Value = u8;

    #[inline]
    fn mean(&self) -> f64 { self.p }

    #[inline]
    fn var(&self) -> f64 { self.p * self.q }

    #[inline]
    fn skewness(&self) -> f64 { (1. - 2. * self.p) / (self.p * self.q).sqrt() }

    #[inline]
    fn kurtosis(&self) -> f64 { (1. - 6. * self.p * self.q) / (self.p * self.q) }

    #[inline]
    fn median(&self) -> f64 {
        use std::cmp::Ordering::*;
        match self.p.partial_cmp(&self.q) {
            Some(Less) => 0.0,
            Some(Equal) => 0.5,
            Some(Greater) => 1.0,
            None => unreachable!(),
        }
    }

    #[inline]
    fn modes(&self) -> Vec<Self::Value> {
        use std::cmp::Ordering::*;
        match self.p.partial_cmp(&self.q) {
            Some(Less) => vec![0],
            Some(Equal) => vec![0, 1],
            Some(Greater) => vec![1],
            None => unreachable!(),
        }
    }

    #[inline]
    fn entropy(&self) -> f64 {
        -self.q * self.q.ln() - self.p * self.p.ln()
    }

    #[inline]
    fn cdf(&self, x: Self::Value) -> f64 {
        if x == 0 { self.q }
        else { 1. }
    }

    #[inline]
    fn inv_cdf(&self, p: f64) -> Self::Value {
        debug_assert!(0.0 <= p && p <= 1.0, "inv_cdf is called with p outside of [0, 1]");
        if p <= self.q { 0 }
        else { 1 }
    }

    #[inline]
    fn pdf(&self, x: Self::Value) -> f64 {
        if x == 0 { self.q }
        else if x == 1 { self.p }
        else { 0.0 }
    }

    #[inline]
    fn sample<G: Generator>(&self, generator: &mut G) -> Self::Value {
        if generator.gen::<f64>() < self.q { 0 } else { 1 }
    }
}

#[cfg(test)]
mod tests {
    use assert;

    use {Distribution, Sampler};
    use distributions::Bernoulli;

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn invalid_succprob() {
        let _ = Bernoulli::new(2.0);
        let _ = Bernoulli::new(-0.5);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn invalid_failprob() {
        let _ = Bernoulli::new_failprob(2.0);
        let _ = Bernoulli::new_failprob(-0.5);
    }

    #[test]
    fn new_failprob() {
        let _ = Bernoulli::new_failprob(1e-24);
    }

    #[test]
    fn mean() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.mean(), 0.5);
    }

    #[test]
    fn var() {
        let d = Bernoulli::new(0.25);
        assert_eq!(d.var(), 0.1875);
    }

    #[test]
    fn sd() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.sd(), 0.5);
    }

    #[test]
    fn skewness() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.skewness(), 0.0);
    }

    #[test]
    fn kurtosis() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.kurtosis(), -2.0);
    }

    #[test]
    fn median() {
        let d1 = Bernoulli::new(0.25);
        let d2 = Bernoulli::new(0.5);
        let d3 = Bernoulli::new(0.75);
        assert_eq!(d1.median(), 0.0);
        assert_eq!(d2.median(), 0.5);
        assert_eq!(d3.median(), 1.0);
    }

    #[test]
    fn modes() {
        let d1 = Bernoulli::new(0.25);
        let d2 = Bernoulli::new(0.5);
        let d3 = Bernoulli::new(0.75);
        assert_eq!(d1.modes(), vec![0]);
        assert_eq!(d2.modes(), vec![0, 1]);
        assert_eq!(d3.modes(), vec![1]);
    }

    #[test]
    fn entropy() {
        let dists = vec![
            Bernoulli::new(0.25),
            Bernoulli::new(0.5),
            Bernoulli::new(0.75),
        ];
        assert::within(&dists.iter().map(|d| d.entropy()).collect::<Vec<_>>(),
                       &vec![0.5623351446188083, 0.6931471805599453, 0.5623351446188083], 1e-16);
    }

    #[test]
    fn pdf() {
        let bernoulli = Bernoulli::new(0.25);
        let x = 0..3;
        let p = vec![0.75, 0.25, 0.0];

        assert::equal(&x.map(|x| bernoulli.pdf(x)).collect::<Vec<_>>(), &p);
    }

    #[test]
    fn cdf() {
        let bernoulli = Bernoulli::new(0.25);
        let x = 0..3;
        let p = vec![0.75, 1., 1.];

        assert::equal(&x.map(|x| bernoulli.cdf(x)).collect::<Vec<_>>(), &p);
    }

    #[test]
    fn inv_cdf() {
        let bernoulli = Bernoulli::new(0.25);
        let p = vec![0.0, 0.25, 0.5, 0.75, 0.75000000001, 1.0];
        let x = vec![0, 0, 0, 0, 1, 1];

        assert::equal(&p.iter().map(|&p| bernoulli.inv_cdf(p)).collect::<Vec<_>>(), &x);
    }

    #[test]
    fn sample() {
        let mut generator = ::generator();
        let bernoulli = Bernoulli::new(0.25);

        let sum = Sampler(&bernoulli, &mut generator)
            .take(100)
            .fold(0, |a, b| a + b);

        assert!(sum <= 100);
    }
}
<commit_msg>Saved repeted calculations for bernoulli<commit_after>use {Distribution, Generator};

/// A Bernoulli distribution.
#[derive(Clone, Copy)]
pub struct Bernoulli {
    /// The probability of success.
    pub p: f64,
    /// The probability of failure.
    pub q: f64,
    // The variance
    pq: f64,
}

impl Bernoulli {
    /// Create a Bernoulli distribution with success probability `p`.
    ///
    /// # Panics
    ///
    /// Panics if `p < 0` or `p > 1`.
    #[inline]
    pub fn new(p: f64) -> Bernoulli {
        debug_assert!(0. < p && p < 1., "Bernoulli::new() is called with p < 0 or p > 1");
        let q = 1. - p;
        Bernoulli { p: p, q: q, pq: p * q }
    }

    /// Create a Bernoulli distribution with failure probability `q`.
    ///
    /// # Panics
    ///
    /// Panics if `q < 0` or `q > 1`.
    #[inline]
    pub fn new_failprob(q: f64) -> Bernoulli {
        debug_assert!(0. < q && q < 1., "Bernoulli::new_failprob() is called with q < 0 or q > 1");
        let p = 1. - q;
        Bernoulli { p: p, q: q, pq: p * q }
    }

}

impl Distribution for Bernoulli {
    type Value = u8;

    #[inline]
    fn mean(&self) -> f64 { self.p }

    #[inline]
    fn var(&self) -> f64 { self.pq }

    #[inline]
    fn skewness(&self) -> f64 { (1. - 2. * self.p) / (self.pq).sqrt() }

    #[inline]
    fn kurtosis(&self) -> f64 { (1. - 6. * self.pq) / (self.pq) }

    #[inline]
    fn median(&self) -> f64 {
        use std::cmp::Ordering::*;
        match self.p.partial_cmp(&self.q) {
            Some(Less) => 0.0,
            Some(Equal) => 0.5,
            Some(Greater) => 1.0,
            None => unreachable!(),
        }
    }

    #[inline]
    fn modes(&self) -> Vec<Self::Value> {
        use std::cmp::Ordering::*;
        match self.p.partial_cmp(&self.q) {
            Some(Less) => vec![0],
            Some(Equal) => vec![0, 1],
            Some(Greater) => vec![1],
            None => unreachable!(),
        }
    }

    #[inline]
    fn entropy(&self) -> f64 {
        -self.q * self.q.ln() - self.p * self.p.ln()
    }

    #[inline]
    fn cdf(&self, x: Self::Value) -> f64 {
        if x == 0 { self.q }
        else { 1. }
    }

    #[inline]
    fn inv_cdf(&self, p: f64) -> Self::Value {
        debug_assert!(0.0 <= p && p <= 1.0, "inv_cdf is called with p outside of [0, 1]");
        if p <= self.q { 0 }
        else { 1 }
    }

    #[inline]
    fn pdf(&self, x: Self::Value) -> f64 {
        if x == 0 { self.q }
        else if x == 1 { self.p }
        else { 0.0 }
    }

    #[inline]
    fn sample<G: Generator>(&self, generator: &mut G) -> Self::Value {
        if generator.gen::<f64>() < self.q { 0 } else { 1 }
    }
}

#[cfg(test)]
mod tests {
    use assert;

    use {Distribution, Sampler};
    use distributions::Bernoulli;

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn invalid_succprob() {
        let _ = Bernoulli::new(2.0);
        let _ = Bernoulli::new(-0.5);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn invalid_failprob() {
        let _ = Bernoulli::new_failprob(2.0);
        let _ = Bernoulli::new_failprob(-0.5);
    }

    #[test]
    fn new_failprob() {
        let _ = Bernoulli::new_failprob(1e-24);
    }

    #[test]
    fn mean() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.mean(), 0.5);
    }

    #[test]
    fn var() {
        let d = Bernoulli::new(0.25);
        assert_eq!(d.var(), 0.1875);
    }

    #[test]
    fn sd() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.sd(), 0.5);
    }

    #[test]
    fn skewness() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.skewness(), 0.0);
    }

    #[test]
    fn kurtosis() {
        let d = Bernoulli::new(0.5);
        assert_eq!(d.kurtosis(), -2.0);
    }

    #[test]
    fn median() {
        let d1 = Bernoulli::new(0.25);
        let d2 = Bernoulli::new(0.5);
        let d3 = Bernoulli::new(0.75);
        assert_eq!(d1.median(), 0.0);
        assert_eq!(d2.median(), 0.5);
        assert_eq!(d3.median(), 1.0);
    }

    #[test]
    fn modes() {
        let d1 = Bernoulli::new(0.25);
        let d2 = Bernoulli::new(0.5);
        let d3 = Bernoulli::new(0.75);
        assert_eq!(d1.modes(), vec![0]);
        assert_eq!(d2.modes(), vec![0, 1]);
        assert_eq!(d3.modes(), vec![1]);
    }

    #[test]
    fn entropy() {
        let dists = vec![
            Bernoulli::new(0.25),
            Bernoulli::new(0.5),
            Bernoulli::new(0.75),
        ];
        assert::within(&dists.iter().map(|d| d.entropy()).collect::<Vec<_>>(),
                       &vec![0.5623351446188083, 0.6931471805599453, 0.5623351446188083], 1e-16);
    }

    #[test]
    fn pdf() {
        let bernoulli = Bernoulli::new(0.25);
        let x = 0..3;
        let p = vec![0.75, 0.25, 0.0];

        assert::equal(&x.map(|x| bernoulli.pdf(x)).collect::<Vec<_>>(), &p);
    }

    #[test]
    fn cdf() {
        let bernoulli = Bernoulli::new(0.25);
        let x = 0..3;
        let p = vec![0.75, 1., 1.];

        assert::equal(&x.map(|x| bernoulli.cdf(x)).collect::<Vec<_>>(), &p);
    }

    #[test]
    fn inv_cdf() {
        let bernoulli = Bernoulli::new(0.25);
        let p = vec![0.0, 0.25, 0.5, 0.75, 0.75000000001, 1.0];
        let x = vec![0, 0, 0, 0, 1, 1];

        assert::equal(&p.iter().map(|&p| bernoulli.inv_cdf(p)).collect::<Vec<_>>(), &x);
    }

    #[test]
    fn sample() {
        let mut generator = ::generator();
        let bernoulli = Bernoulli::new(0.25);

        let sum = Sampler(&bernoulli, &mut generator)
            .take(100)
            .fold(0, |a, b| a + b);

        assert!(sum <= 100);
    }
}
<|endoftext|>


<commit_before>//! This example shows how to transmit a request with a custom HTTP header.

extern crate xmlrpc;
extern crate reqwest;

use xmlrpc::{Request, Transport};
use xmlrpc::http::{build_headers, check_response};

use reqwest::{Client, RequestBuilder};
use reqwest::header::COOKIE;

use std::error::Error;

/// Custom transport that adds a cookie header.
struct MyTransport(RequestBuilder);

impl Transport for MyTransport {
    type Stream = reqwest::Response;

    fn transmit(self, request: &Request) -> Result<Self::Stream, Box<Error + Send + Sync>> {
        let mut body = Vec::new();
        request.write_as_xml(&mut body).expect("could not write request to buffer (this should never happen)");

        let response = build_headers(self.0, body.len() as u64)
            .header(COOKIE, "SESSION=123abc")  // Our custom header will be a `Cookie` header
            .body(body)
            .send()?;

        check_response(&response)?;

        Ok(response)
    }
}

fn main() {
    let request = Request::new("pow").arg(2).arg(8);

    let tp = MyTransport(Client::new().post("http://localhost/target"));
    let result = request.call(tp);

    println!("Result: {:?}", result);
}
<commit_msg>Remove remaining bare trait object<commit_after>//! This example shows how to transmit a request with a custom HTTP header.

extern crate xmlrpc;
extern crate reqwest;

use xmlrpc::{Request, Transport};
use xmlrpc::http::{build_headers, check_response};

use reqwest::{Client, RequestBuilder};
use reqwest::header::COOKIE;

use std::error::Error;

/// Custom transport that adds a cookie header.
struct MyTransport(RequestBuilder);

impl Transport for MyTransport {
    type Stream = reqwest::Response;

    fn transmit(self, request: &Request) -> Result<Self::Stream, Box<dyn Error + Send + Sync>> {
        let mut body = Vec::new();
        request.write_as_xml(&mut body).expect("could not write request to buffer (this should never happen)");

        let response = build_headers(self.0, body.len() as u64)
            .header(COOKIE, "SESSION=123abc")  // Our custom header will be a `Cookie` header
            .body(body)
            .send()?;

        check_response(&response)?;

        Ok(response)
    }
}

fn main() {
    let request = Request::new("pow").arg(2).arg(8);

    let tp = MyTransport(Client::new().post("http://localhost/target"));
    let result = request.call(tp);

    println!("Result: {:?}", result);
}
<|endoftext|>


<commit_before>// 定义一个函数，可以接受一个由 `Fn` 限定的泛型 `F` 参数并调用它。
fn call_me<F: Fn()>(f: F) {
    f()
}

// 定义一个满足 `Fn` 限定的装包函数（wrapper function）。
fn function() {
    println!("I'm a function!")
}

fn main() {
    // 定义一个满足 `Fn` 限定的闭包。
    let closure = || println!("I'm a closure!");

    call_me(closure);
    call_me(function);
}
<commit_msg>Explicit return value<commit_after>// 定义一个函数，可以接受一个由 `Fn` 限定的泛型 `F` 参数并调用它。
fn call_me<F: Fn()>(f: F) {
    f()
}

// 定义一个满足 `Fn` 限定的装包函数（wrapper function）。
fn function() {
    println!("I'm a function!");
}

fn main() {
    // 定义一个满足 `Fn` 限定的闭包。
    let closure = || println!("I'm a closure!");

    call_me(closure);
    call_me(function);
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(dynasm)]

use std::io::{self, Write};

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    stdout.write_all(dynasm_opmap!().as_bytes()).unwrap();
}
<commit_msg>Port the instruction reference documentation project to proc_macro as well<commit_after>#![feature(proc_macro_hygiene)]

use std::io::{self, Write};

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    stdout.write_all(dynasm::dynasm_opmap!().as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>use super::gi_docgen;
use crate::{nameutil, Env};
use once_cell::sync::Lazy;
use regex::{Captures, Regex};

const LANGUAGE_SEP_BEGIN: &str = "<!-- language=\"";
const LANGUAGE_SEP_END: &str = "\" -->";
const LANGUAGE_BLOCK_BEGIN: &str = "|[";
const LANGUAGE_BLOCK_END: &str = "\n]|";

pub fn reformat_doc(input: &str, env: &Env, in_type: &str) -> String {
    code_blocks_transformation(input, env, in_type)
}

fn try_split<'a>(src: &'a str, needle: &str) -> (&'a str, Option<&'a str>) {
    match src.find(needle) {
        Some(pos) => (&src[..pos], Some(&src[pos + needle.len()..])),
        None => (src, None),
    }
}

fn code_blocks_transformation(mut input: &str, env: &Env, in_type: &str) -> String {
    let mut out = String::with_capacity(input.len());

    loop {
        input = match try_split(input, LANGUAGE_BLOCK_BEGIN) {
            (before, Some(after)) => {
                out.push_str(&format(before, env, in_type));
                if let (before, Some(after)) =
                    try_split(get_language(after, &mut out), LANGUAGE_BLOCK_END)
                {
                    out.push_str(before);
                    out.push_str("\n```");
                    after
                } else {
                    after
                }
            }
            (before, None) => {
                out.push_str(&format(before, env, in_type));
                return out;
            }
        };
    }
}

fn get_language<'a>(entry: &'a str, out: &mut String) -> &'a str {
    if let (_, Some(after)) = try_split(entry, LANGUAGE_SEP_BEGIN) {
        if let (before, Some(after)) = try_split(after, LANGUAGE_SEP_END) {
            out.push_str(&format!("\n```{}", before));
            return after;
        }
    }
    out.push_str("\n```text");
    entry
}

fn format(input: &str, env: &Env, in_type: &str) -> String {
    let mut ret = String::with_capacity(input.len());
    // We run gi_docgen first because it's super picky about the types it replaces
    let out = replace_c_types(input, env, in_type);
    let out = gi_docgen::replace_c_types(&out, env, in_type);
    // this has to be done after gi_docgen replaced the various types it knows as it uses `@` in it's linking format
    let out = PARAM_SYMBOL.replace_all(&out, |caps: &Captures<'_>| format!("`{}`", &caps[2]));
    ret.push_str(&out);
    ret
}

static SYMBOL: Lazy<Regex> = Lazy::new(|| Regex::new(r"([#%])(\w+\b)([:.]+[\w-]+\b)?").unwrap());
static PARAM_SYMBOL: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"([@])(\w+\b)([:.]+[\w-]+\b)?").unwrap());
static FUNCTION: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"([@#%])?(\w+\b[:.]+)?(\b[a-z0-9_]+)\(\)").unwrap());
// **note**
// The optional . at the end is to make the regex more relaxed for some weird broken cases on gtk3's docs
// it doesn't hurt other docs so please don't drop it
static GDK_GTK: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"`([^\(:])?((G[dts]k|Pango)\w+\b)(\.)?`").unwrap());
static TAGS: Lazy<Regex> = Lazy::new(|| Regex::new(r"<[\w/-]+>").unwrap());
static SPACES: Lazy<Regex> = Lazy::new(|| Regex::new(r"[ ]{2,}").unwrap());

fn replace_c_types(entry: &str, env: &Env, _in_type: &str) -> String {
    let out = FUNCTION.replace_all(entry, |caps: &Captures<'_>| {
        let name = &caps[3];
        find_function(name, env)
    });

    let out = SYMBOL.replace_all(&out, |caps: &Captures<'_>| {
        match &caps[2] {
            "TRUE" => "[`true`]".to_string(),
            "FALSE" => "[`false`]".to_string(),
            "NULL" => "[`None`]".to_string(),
            symbol_name => {
                if &caps[1] == "%" {
                    find_constant_or_variant(symbol_name, env)
                } else {
                    let method_name = caps.get(3).map(|m| m.as_str().trim_start_matches('.'));
                    // would be #
                    find_type_by_name(symbol_name, method_name, env)
                }
            }
        }
    });
    let out = GDK_GTK.replace_all(&out, |caps: &Captures<'_>| find_type(&caps[2], env));
    let out = TAGS.replace_all(&out, "`$0`");
    SPACES.replace_all(&out, " ").into_owned()
}

fn find_type_by_name(symbol: &str, method_name: Option<&str>, env: &Env) -> String {
    let symbols = env.symbols.borrow();
    if let Some(method) = method_name {
        if let Some((obj_info, fn_info)) = env.analysis.find_object_by_function(
            env,
            |o| o.full_name == symbol,
            |f| f.name == method,
        ) {
            let sym = symbols.by_tid(obj_info.type_id).unwrap(); // we are sure the object exists
            let (type_name, visible_type_name) = obj_info.generate_doc_link_info(fn_info);
            let name = sym.full_rust_name().replace(&obj_info.name, &type_name);

            fn_info.doc_link(Some(&name), Some(&visible_type_name))
        } else if let Some((record_info, fn_info)) = env.analysis.find_record_by_function(
            env,
            |r| r.type_(&env.library).c_type == symbol,
            |f| f.name == method,
        ) {
            let sym_name = symbols
                .by_tid(record_info.type_id)
                .unwrap()
                .full_rust_name(); // we are sure the object exists
            fn_info.doc_link(Some(&sym_name), None)
        } else {
            format!("`{}::{}`", symbol, method)
        }
    } else {
        find_type(symbol, env)
    }
}

fn find_constant_or_variant(symbol: &str, env: &Env) -> String {
    let symbols = env.symbols.borrow();
    if let Some(const_info) = env
        .analysis
        .constants
        .iter()
        .find(|c| c.glib_name == symbol)
    {
        // for whatever reason constants are not part of the symbols list
        format!("[`{n}`][crate::{n}]", n = const_info.name)
    } else if let Some((flag_info, member_info)) = env.analysis.flags.iter().find_map(|f| {
        f.type_(&env.library)
            .members
            .iter()
            .find(|m| m.c_identifier == symbol)
            .map(|m| (f, m))
    }) {
        let sym = symbols.by_tid(flag_info.type_id).unwrap();
        format!(
            "[`{p}::{m}`][crate::{p}::{m}]",
            m = nameutil::bitfield_member_name(&member_info.name),
            p = sym.full_rust_name()
        )
    } else if let Some((enum_info, member_info)) = env.analysis.enumerations.iter().find_map(|e| {
        e.type_(&env.library)
            .members
            .iter()
            .find(|m| m.c_identifier == symbol)
            .map(|m| (e, m))
    }) {
        let sym = symbols.by_tid(enum_info.type_id).unwrap();
        format!(
            "[`{e}::{m}`][crate::{e}::{m}]",
            m = nameutil::enum_member_name(&member_info.name),
            e = sym.full_rust_name()
        )
    } else {
        format!("`{}`", symbol)
    }
}

/// either an object/interface, record, enum or a flag
fn find_type(name: &str, env: &Env) -> String {
    let symbols = env.symbols.borrow();

    let symbol = if let Some(obj) = env.analysis.objects.values().find(|o| o.c_type == name) {
        symbols.by_tid(obj.type_id)
    } else if let Some(record) = env
        .analysis
        .records
        .values()
        .find(|r| r.type_(&env.library).c_type == name)
    {
        symbols.by_tid(record.type_id)
    } else if let Some(enum_) = env
        .analysis
        .enumerations
        .iter()
        .find(|e| e.type_(&env.library).c_type == name)
    {
        symbols.by_tid(enum_.type_id)
    } else if let Some(flag) = env
        .analysis
        .flags
        .iter()
        .find(|f| f.type_(&env.library).c_type == name)
    {
        symbols.by_tid(flag.type_id)
    } else {
        None
    };
    symbol
        .map(|sym| format!("[`{n}`][crate::{n}]", n = sym.full_rust_name()))
        .unwrap_or_else(|| format!("`{}`", name))
}

/// Find a function in all the possible items, if not found return the original name surrounded with backsticks
/// A function can either be a struct/interface/record method, a global function or maybe a virtual function
fn find_function(name: &str, env: &Env) -> String {
    let symbols = env.symbols.borrow();
    // if we can find the function in an object
    if let Some((obj_info, fn_info)) =
        env.analysis
            .find_object_by_function(env, |_| true, |f| f.glib_name == name)
    {
        let sym = symbols.by_tid(obj_info.type_id).unwrap(); // we are sure the object exists
        let (type_name, visible_type_name) = obj_info.generate_doc_link_info(fn_info);

        let name = sym.full_rust_name().replace(&obj_info.name, &type_name);
        fn_info.doc_link(Some(&name), Some(&visible_type_name))
    // or in a record
    } else if let Some((record_info, fn_info)) =
        env.analysis
            .find_record_by_function(env, |_| true, |f| f.glib_name == name)
    {
        let sym_name = symbols
            .by_tid(record_info.type_id)
            .unwrap()
            .full_rust_name(); // we are sure the object exists
        fn_info.doc_link(Some(&sym_name), None)
    // or as a global function
    } else if let Some(fn_info) = env
        .analysis
        .find_global_function(env, |f| f.glib_name == name)
    {
        fn_info.doc_link(None, None)
    } else {
        format!("`{}()`", name)
    }
}
<commit_msg>docs: don't generate links for ignored enum members/flags variants<commit_after>use super::gi_docgen;
use crate::{nameutil, Env};
use once_cell::sync::Lazy;
use regex::{Captures, Regex};

const LANGUAGE_SEP_BEGIN: &str = "<!-- language=\"";
const LANGUAGE_SEP_END: &str = "\" -->";
const LANGUAGE_BLOCK_BEGIN: &str = "|[";
const LANGUAGE_BLOCK_END: &str = "\n]|";

pub fn reformat_doc(input: &str, env: &Env, in_type: &str) -> String {
    code_blocks_transformation(input, env, in_type)
}

fn try_split<'a>(src: &'a str, needle: &str) -> (&'a str, Option<&'a str>) {
    match src.find(needle) {
        Some(pos) => (&src[..pos], Some(&src[pos + needle.len()..])),
        None => (src, None),
    }
}

fn code_blocks_transformation(mut input: &str, env: &Env, in_type: &str) -> String {
    let mut out = String::with_capacity(input.len());

    loop {
        input = match try_split(input, LANGUAGE_BLOCK_BEGIN) {
            (before, Some(after)) => {
                out.push_str(&format(before, env, in_type));
                if let (before, Some(after)) =
                    try_split(get_language(after, &mut out), LANGUAGE_BLOCK_END)
                {
                    out.push_str(before);
                    out.push_str("\n```");
                    after
                } else {
                    after
                }
            }
            (before, None) => {
                out.push_str(&format(before, env, in_type));
                return out;
            }
        };
    }
}

fn get_language<'a>(entry: &'a str, out: &mut String) -> &'a str {
    if let (_, Some(after)) = try_split(entry, LANGUAGE_SEP_BEGIN) {
        if let (before, Some(after)) = try_split(after, LANGUAGE_SEP_END) {
            out.push_str(&format!("\n```{}", before));
            return after;
        }
    }
    out.push_str("\n```text");
    entry
}

fn format(input: &str, env: &Env, in_type: &str) -> String {
    let mut ret = String::with_capacity(input.len());
    // We run gi_docgen first because it's super picky about the types it replaces
    let out = replace_c_types(input, env, in_type);
    let out = gi_docgen::replace_c_types(&out, env, in_type);
    // this has to be done after gi_docgen replaced the various types it knows as it uses `@` in it's linking format
    let out = PARAM_SYMBOL.replace_all(&out, |caps: &Captures<'_>| format!("`{}`", &caps[2]));
    ret.push_str(&out);
    ret
}

static SYMBOL: Lazy<Regex> = Lazy::new(|| Regex::new(r"([#%])(\w+\b)([:.]+[\w-]+\b)?").unwrap());
static PARAM_SYMBOL: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"([@])(\w+\b)([:.]+[\w-]+\b)?").unwrap());
static FUNCTION: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"([@#%])?(\w+\b[:.]+)?(\b[a-z0-9_]+)\(\)").unwrap());
// **note**
// The optional . at the end is to make the regex more relaxed for some weird broken cases on gtk3's docs
// it doesn't hurt other docs so please don't drop it
static GDK_GTK: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"`([^\(:])?((G[dts]k|Pango)\w+\b)(\.)?`").unwrap());
static TAGS: Lazy<Regex> = Lazy::new(|| Regex::new(r"<[\w/-]+>").unwrap());
static SPACES: Lazy<Regex> = Lazy::new(|| Regex::new(r"[ ]{2,}").unwrap());

fn replace_c_types(entry: &str, env: &Env, _in_type: &str) -> String {
    let out = FUNCTION.replace_all(entry, |caps: &Captures<'_>| {
        let name = &caps[3];
        find_function(name, env)
    });

    let out = SYMBOL.replace_all(&out, |caps: &Captures<'_>| {
        match &caps[2] {
            "TRUE" => "[`true`]".to_string(),
            "FALSE" => "[`false`]".to_string(),
            "NULL" => "[`None`]".to_string(),
            symbol_name => {
                if &caps[1] == "%" {
                    find_constant_or_variant(symbol_name, env)
                } else {
                    let method_name = caps.get(3).map(|m| m.as_str().trim_start_matches('.'));
                    // would be #
                    find_type_by_name(symbol_name, method_name, env)
                }
            }
        }
    });
    let out = GDK_GTK.replace_all(&out, |caps: &Captures<'_>| find_type(&caps[2], env));
    let out = TAGS.replace_all(&out, "`$0`");
    SPACES.replace_all(&out, " ").into_owned()
}

fn find_type_by_name(symbol: &str, method_name: Option<&str>, env: &Env) -> String {
    let symbols = env.symbols.borrow();
    if let Some(method) = method_name {
        if let Some((obj_info, fn_info)) = env.analysis.find_object_by_function(
            env,
            |o| o.full_name == symbol,
            |f| f.name == method,
        ) {
            let sym = symbols.by_tid(obj_info.type_id).unwrap(); // we are sure the object exists
            let (type_name, visible_type_name) = obj_info.generate_doc_link_info(fn_info);
            let name = sym.full_rust_name().replace(&obj_info.name, &type_name);

            fn_info.doc_link(Some(&name), Some(&visible_type_name))
        } else if let Some((record_info, fn_info)) = env.analysis.find_record_by_function(
            env,
            |r| r.type_(&env.library).c_type == symbol,
            |f| f.name == method,
        ) {
            let sym_name = symbols
                .by_tid(record_info.type_id)
                .unwrap()
                .full_rust_name(); // we are sure the object exists
            fn_info.doc_link(Some(&sym_name), None)
        } else {
            format!("`{}::{}`", symbol, method)
        }
    } else {
        find_type(symbol, env)
    }
}

fn find_constant_or_variant(symbol: &str, env: &Env) -> String {
    let symbols = env.symbols.borrow();
    if let Some(const_info) = env
        .analysis
        .constants
        .iter()
        .find(|c| c.glib_name == symbol)
    {
        // for whatever reason constants are not part of the symbols list
        format!("[`{n}`][crate::{n}]", n = const_info.name)
    } else if let Some((flag_info, member_info)) = env.analysis.flags.iter().find_map(|f| {
        f.type_(&env.library)
            .members
            .iter()
            .find(|m| m.c_identifier == symbol && !m.status.ignored())
            .map(|m| (f, m))
    }) {
        let sym = symbols.by_tid(flag_info.type_id).unwrap();
        format!(
            "[`{p}::{m}`][crate::{p}::{m}]",
            m = nameutil::bitfield_member_name(&member_info.name),
            p = sym.full_rust_name()
        )
    } else if let Some((enum_info, member_info)) = env.analysis.enumerations.iter().find_map(|e| {
        e.type_(&env.library)
            .members
            .iter()
            .find(|m| m.c_identifier == symbol && !m.status.ignored())
            .map(|m| (e, m))
    }) {
        let sym = symbols.by_tid(enum_info.type_id).unwrap();
        format!(
            "[`{e}::{m}`][crate::{e}::{m}]",
            m = nameutil::enum_member_name(&member_info.name),
            e = sym.full_rust_name()
        )
    } else {
        format!("`{}`", symbol)
    }
}

/// either an object/interface, record, enum or a flag
fn find_type(name: &str, env: &Env) -> String {
    let symbols = env.symbols.borrow();

    let symbol = if let Some(obj) = env.analysis.objects.values().find(|o| o.c_type == name) {
        symbols.by_tid(obj.type_id)
    } else if let Some(record) = env
        .analysis
        .records
        .values()
        .find(|r| r.type_(&env.library).c_type == name)
    {
        symbols.by_tid(record.type_id)
    } else if let Some(enum_) = env
        .analysis
        .enumerations
        .iter()
        .find(|e| e.type_(&env.library).c_type == name)
    {
        symbols.by_tid(enum_.type_id)
    } else if let Some(flag) = env
        .analysis
        .flags
        .iter()
        .find(|f| f.type_(&env.library).c_type == name)
    {
        symbols.by_tid(flag.type_id)
    } else {
        None
    };
    symbol
        .map(|sym| format!("[`{n}`][crate::{n}]", n = sym.full_rust_name()))
        .unwrap_or_else(|| format!("`{}`", name))
}

/// Find a function in all the possible items, if not found return the original name surrounded with backsticks
/// A function can either be a struct/interface/record method, a global function or maybe a virtual function
fn find_function(name: &str, env: &Env) -> String {
    let symbols = env.symbols.borrow();
    // if we can find the function in an object
    if let Some((obj_info, fn_info)) =
        env.analysis
            .find_object_by_function(env, |_| true, |f| f.glib_name == name)
    {
        let sym = symbols.by_tid(obj_info.type_id).unwrap(); // we are sure the object exists
        let (type_name, visible_type_name) = obj_info.generate_doc_link_info(fn_info);

        let name = sym.full_rust_name().replace(&obj_info.name, &type_name);
        fn_info.doc_link(Some(&name), Some(&visible_type_name))
    // or in a record
    } else if let Some((record_info, fn_info)) =
        env.analysis
            .find_record_by_function(env, |_| true, |f| f.glib_name == name)
    {
        let sym_name = symbols
            .by_tid(record_info.type_id)
            .unwrap()
            .full_rust_name(); // we are sure the object exists
        fn_info.doc_link(Some(&sym_name), None)
    // or as a global function
    } else if let Some(fn_info) = env
        .analysis
        .find_global_function(env, |f| f.glib_name == name)
    {
        fn_info.doc_link(None, None)
    } else {
        format!("`{}()`", name)
    }
}
<|endoftext|>


<commit_before><commit_msg>PaintServer: use a Fragment for the iri case, not a String<commit_after><|endoftext|>