<commit_before>#[macro_use]
extern crate criterion;
extern crate bmemcached;

use criterion::Criterion;

use bmemcached::MemcachedClient;

fn criterion_benchmark(c: &mut Criterion) {
    let cli = MemcachedClient::new(vec!["127.0.0.1:11211"], 10).unwrap();
    c.bench_function("set/get/delete", move |b| {
        b.iter(|| {
            let key = "benchmark test";
            cli.set(key, "abc", 10_000).unwrap();
            let returned_value: String = cli.get(key).unwrap();
            assert_eq!(returned_value, "abc");
            cli.delete(key).unwrap();
        })
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<commit_msg>chore: Change regression benchmark to use protocol directly<commit_after>#[macro_use]
extern crate criterion;
extern crate bmemcached;

use criterion::Criterion;

use bmemcached::protocol::Protocol;

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("set/get/delete", |b| {
        let mut cli = Protocol::connect("127.0.0.1:11211").unwrap();
        b.iter(|| {
            let key = "benchmark test";
            cli.set(key, "abc", 10_000).unwrap();
            let returned_value: String = cli.get(key).unwrap();
            assert_eq!(returned_value, "abc");
            cli.delete(key).unwrap();
        })
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;

use criterion::Criterion;
use ion_shell::parser::Terminator;

const TEXT: &str = include_str!("test.ion");
const EOF: &str = include_str!("herestring.ion");

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("terminator", |b| {
        b.iter(|| {
            let mut bytes = TEXT.bytes().peekable();
            while bytes.peek().is_some() {
                let stmt = Terminator::new(&mut bytes).terminate();
            }
        })
    });

    c.bench_function("terminator EOF", |b| {
        b.iter(|| {
            let mut bytes = EOF.bytes().peekable();
            while bytes.peek().is_some() {
                let stmt = Terminator::new(&mut bytes).terminate();
            }
        })
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<commit_msg>Fix the benchmark<commit_after>#[macro_use]
extern crate criterion;

use criterion::*;
use ion_shell::parser::Terminator;

const TEXT: &str = include_str!("test.ion");
const EOF: &str = include_str!("herestring.ion");

fn criterion_benchmark(c: &mut Criterion) {
    c.bench(
        "terminator-throughput",
        ParameterizedBenchmark::new(
            "terminator",
            |b, script| {
                b.iter(|| {
                    let mut bytes = script.bytes().peekable();
                    while bytes.peek().is_some() {
                        let stmt = Terminator::new(&mut bytes).terminate();
                    }
                })
            },
            vec![TEXT, EOF],
        )
        .throughput(|script| Throughput::Bytes(script.len() as u32)),
    );
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>// This code is heavily inspired by hoedown.

//
// Performance observations:
//
// Note that buf.head() == Some(&ch) is much faster than buf[0] == ch.
//

extern crate extra;
use extra::test::BenchHarness;

static SP: u8 = ' ' as u8;
static NL: u8 = '\n' as u8;

/// Returns true if the line is a horizontal rule.
fn is_hrule(buf: &[u8]) -> bool {
    let mut buf = buf;

    if buf.len() < 3 { return false }

    // Skip up to three leading spaces.
    //
    // We don't need to care about tabs here as in this position they are
    // equivalent to 4 spaces, which means we would not parse this as a
    // hrule.
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }

    // We need at least 3 items
    if buf.len() < 3 { return false }

    let item = buf[0];

    if !(item == ('*' as u8) || item == ('-' as u8) || item == ('_' as u8)) {
        return false;
    }

    // The count of '*', '-' or '_'
    let mut cnt: uint = 0;

    for &ch in buf.iter() {
        if ch == item {
            cnt += 1;
        } else if ch == NL {
            break;
        } else if ch != SP {
            return false;
        }
    }

    return cnt >= 3;
}

#[test]
fn test_is_hrule() {
    // examples as given on the markdown homepage
    assert_eq!(is_hrule(bytes!("* * *\n")), true);
    assert_eq!(is_hrule(bytes!("***\n")), true);
    assert_eq!(is_hrule(bytes!("*****\n")), true);
    assert_eq!(is_hrule(bytes!("- - -\n")), true);
    assert_eq!(is_hrule(bytes!("---------------------------------------\n")), true);

    // up to three spaces ignored
    assert_eq!(is_hrule(bytes!(" ***\n")), true);
    assert_eq!(is_hrule(bytes!("  ***\n")), true);
    assert_eq!(is_hrule(bytes!("   ***\n")), true);

    // but not four, or a tab which is equivalent to four spaces
    assert_eq!(is_hrule(bytes!("    ***\n")), false);
    assert_eq!(is_hrule(bytes!("\t***\n")), false);

    // need at least three
    assert_eq!(is_hrule(bytes!("*\n")), false);
    assert_eq!(is_hrule(bytes!("**\n")), false);
    assert_eq!(is_hrule(bytes!("* *\n")), false);
    assert_eq!(is_hrule(bytes!("   * *\n")), false);

    // Also works without newline at the end
    assert_eq!(is_hrule(bytes!("* * *")), true);

    // And underscores also supported
    assert_eq!(is_hrule(bytes!("___")), true);
    assert_eq!(is_hrule(bytes!("______________")), true);
    assert_eq!(is_hrule(bytes!(" ______________")), true);
}

#[bench]
fn bench_is_hrule(b: &mut BenchHarness) {
    let s = bytes!("   * * * * * * * * * * * * * * * *\n");
    b.iter(|| is_hrule(s));
}
<commit_msg>Return an Option from is_hrule() containing the remaining buf.<commit_after>// This code is heavily inspired by hoedown.

//
// Performance observations:
//
// Note that buf.head() == Some(&ch) is much faster than buf[0] == ch.
//

extern crate extra;
use extra::test::BenchHarness;

static SP: u8 = ' ' as u8;
static NL: u8 = '\n' as u8;

/// Returns Some(rem) if the line is a horizontal rule,
/// with rest being the buf after the hrule.
/// Otherwise returns None.
fn is_hrule<'a>(buf: &'a[u8]) -> Option<&'a[u8]> {
    let mut buf = buf;

    if buf.len() < 3 { return None }

    // Skip up to three leading spaces.
    //
    // We don't need to care about tabs here as in this position they are
    // equivalent to 4 spaces, which means we would not parse this as a
    // hrule.
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }

    // We need at least 3 items
    if buf.len() < 3 { return None }

    let item = buf[0];

    if !(item == ('*' as u8) || item == ('-' as u8) || item == ('_' as u8)) {
        return None;
    }

    // The count of '*', '-' or '_'
    let mut cnt: uint = 0;

    // Counts the consumed spaces (and the final NL)
    let mut spc: uint = 0;

    for &ch in buf.iter() {
        if      ch == item { cnt += 1; }
        else if ch == NL   { spc += 1; break; }
        else if ch == SP   { spc += 1; }
        else               { return None; }
    }

    if cnt >= 3 {
        Some(buf.slice_from(cnt + spc))
    } else {
        None
    }
}

#[test]
fn test_is_hrule() {
    // examples as given on the markdown homepage
    assert!(is_hrule(bytes!("* * *\n")).is_some());
    assert!(is_hrule(bytes!("***\n")).is_some());
    assert!(is_hrule(bytes!("*****\n")).is_some());
    assert!(is_hrule(bytes!("- - -\n")).is_some());
    assert!(is_hrule(bytes!("---------------------------------------\n")).is_some());

    // up to three spaces ignored
    assert!(is_hrule(bytes!(" ***\n")).is_some());
    assert!(is_hrule(bytes!("  ***\n")).is_some());
    assert!(is_hrule(bytes!("   ***\n")).is_some());

    // but not four, or a tab which is equivalent to four spaces

    assert!(is_hrule(bytes!("    ***\n")).is_none());
    assert!(is_hrule(bytes!("\t***\n")).is_none());

    // need at least three
    assert!(is_hrule(bytes!("*\n")).is_none());
    assert!(is_hrule(bytes!("**\n")).is_none());
    assert!(is_hrule(bytes!("* *\n")).is_none());
    assert!(is_hrule(bytes!("   * *\n")).is_none());

    // Also works without newline at the end
    assert!(is_hrule(bytes!("* * *")).is_some());

    // And underscores also supported
    assert!(is_hrule(bytes!("___")).is_some());
    assert!(is_hrule(bytes!("______________")).is_some());
    assert!(is_hrule(bytes!(" ______________")).is_some());
}

#[bench]
fn bench_is_hrule(b: &mut BenchHarness) {
    let s = bytes!("   * * * * * * * * * * * * * * * *\n");
    b.iter(|| is_hrule(s));
}
<|endoftext|>


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

//! Tidy check to ensure that unstable features are all in order
//!
//! This check will ensure properties like:
//!
//! * All stability attributes look reasonably well formed
//! * The set of library features is disjoint from the set of language features
//! * Library features have at most one stability level
//! * Library features have at most one `since` value
//! * All unstable lang features have tests to ensure they are actually unstable

use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(Debug, PartialEq, Clone)]
pub enum Status {
    Stable,
    Removed,
    Unstable,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let as_str = match *self {
            Status::Stable => "stable",
            Status::Unstable => "unstable",
            Status::Removed => "removed",
        };
        fmt::Display::fmt(as_str, f)
    }
}

#[derive(Debug, Clone)]
pub struct Feature {
    pub level: Status,
    pub since: String,
    pub has_gate_test: bool,
    pub tracking_issue: Option<u32>,
}

impl Feature {
    fn check_match(&self, other: &Feature)-> Result<(), Vec<&'static str>> {
        let mut mismatches = Vec::new();
        if self.level != other.level {
            mismatches.push("stability level");
        }
        if self.level == Status::Stable || other.level == Status::Stable {
            // As long as a feature is unstable, the since field tracks
            // when the given part of the feature has been implemented.
            // Mismatches are tolerable as features evolve and functionality
            // gets added.
            // Once a feature is stable, the since field tracks the first version
            // it was part of the stable distribution, and mismatches are disallowed.
            if self.since != other.since {
                mismatches.push("since");
            }
        }
        if self.tracking_issue != other.tracking_issue {
            mismatches.push("tracking issue");
        }
        if mismatches.is_empty() {
            Ok(())
        } else {
            Err(mismatches)
        }
    }
}

pub type Features = HashMap<String, Feature>;

pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
    let mut features = collect_lang_features(path);
    assert!(!features.is_empty());

    let lib_features = get_and_check_lib_features(path, bad, &features);
    assert!(!lib_features.is_empty());

    let mut contents = String::new();

    super::walk_many(&[&path.join("test/compile-fail"),
                       &path.join("test/compile-fail-fulldeps"),
                       &path.join("test/parse-fail"),],
                     &mut |path| super::filter_dirs(path),
                     &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        let filen_underscore = filename.replace("-","_").replace(".rs","");
        let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features);

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
            };

            let gate_test_str = "gate-test-";

            if !line.contains(gate_test_str) {
                continue;
            }

            let feature_name = match line.find(gate_test_str) {
                Some(i) => {
                    &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())]
                },
                None => continue,
            };
            match features.get_mut(feature_name) {
                Some(f) => {
                    if filename_is_gate_test {
                        err(&format!("The file is already marked as gate test \
                                      through its name, no need for a \
                                      'gate-test-{}' comment",
                                     feature_name));
                    }
                    f.has_gate_test = true;
                }
                None => {
                    err(&format!("gate-test test found referencing a nonexistent feature '{}'",
                                 feature_name));
                }
            }
        }
    });

    // Only check the number of lang features.
    // Obligatory testing for library features is dumb.
    let gate_untested = features.iter()
                                .filter(|&(_, f)| f.level == Status::Unstable)
                                .filter(|&(_, f)| !f.has_gate_test)
                                .collect::<Vec<_>>();

    for &(name, _) in gate_untested.iter() {
        println!("Expected a gate test for the feature '{}'.", name);
        println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\
                \n      test suite, with its failures due to missing usage of\
                \n      #![feature({})].", name, name);
        println!("Hint: If you already have such a test and don't want to rename it,\
                \n      you can also add a // gate-test-{} line to the test file.",
                 name);
    }

    if gate_untested.len() > 0 {
        tidy_error!(bad, "Found {} features without a gate test.", gate_untested.len());
    }

    if *bad {
        return;
    }
    if quiet {
        println!("* {} features", features.len());
        return;
    }

    let mut lines = Vec::new();
    for (name, feature) in features.iter() {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lang",
                           feature.level,
                           feature.since));
    }
    for (name, feature) in lib_features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lib",
                           feature.level,
                           feature.since));
    }

    lines.sort();
    for line in lines {
        println!("* {}", line);
    }
}

fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
    line.find(attr)
        .and_then(|i| line[i..].find('"').map(|j| i + j + 1))
        .and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
        .map(|(i, j)| &line[i..j])
}

fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool {
    if filen_underscore.starts_with("feature_gate") {
        for (n, f) in features.iter_mut() {
            if filen_underscore == format!("feature_gate_{}", n) {
                f.has_gate_test = true;
                return true;
            }
        }
    }
    return false;
}

pub fn collect_lang_features(base_src_path: &Path) -> Features {
    let mut contents = String::new();
    let path = base_src_path.join("libsyntax/feature_gate.rs");
    t!(t!(File::open(path)).read_to_string(&mut contents));

    contents.lines()
        .filter_map(|line| {
            let mut parts = line.trim().split(",");
            let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) {
                Some("active") => Status::Unstable,
                Some("removed") => Status::Removed,
                Some("accepted") => Status::Stable,
                _ => return None,
            };
            let name = parts.next().unwrap().trim();
            let since = parts.next().unwrap().trim().trim_matches('"');
            let issue_str = parts.next().unwrap().trim();
            let tracking_issue = if issue_str.starts_with("None") {
                None
            } else {
                let s = issue_str.split("(").nth(1).unwrap().split(")").nth(0).unwrap();
                Some(s.parse().unwrap())
            };
            Some((name.to_owned(),
                Feature {
                    level,
                    since: since.to_owned(),
                    has_gate_test: false,
                    tracking_issue,
                }))
        })
        .collect()
}

pub fn collect_lib_features(base_src_path: &Path) -> Features {
    let mut lib_features = Features::new();

    // This library feature is defined in the `compiler_builtins` crate, which
    // has been moved out-of-tree. Now it can no longer be auto-discovered by
    // `tidy`, because we need to filter out its (submodule) directory. Manually
    // add it to the set of known library features so we can still generate docs.
    lib_features.insert("compiler_builtins_lib".to_owned(), Feature {
        level: Status::Unstable,
        since: "".to_owned(),
        has_gate_test: false,
        tracking_issue: None,
    });

    map_lib_features(base_src_path,
                     &mut |res, _, _| {
        match res {
            Ok((name, feature)) => {
                if lib_features.get(name).is_some() {
                    return;
                }
                lib_features.insert(name.to_owned(), feature);
            },
            Err(_) => (),
        }
    });
   lib_features
}

fn get_and_check_lib_features(base_src_path: &Path,
                              bad: &mut bool,
                              lang_features: &Features) -> Features {
    let mut lib_features = Features::new();
    map_lib_features(base_src_path,
                     &mut |res, file, line| {
            match res {
                Ok((name, f)) => {
                    let mut check_features = |f: &Feature, list: &Features, display: &str| {
                        if let Some(ref s) = list.get(name) {
                            if let Err(m) = (&f).check_match(s) {
                                tidy_error!(bad,
                                            "{}:{}: mismatches to {} in: {:?}",
                                            file.display(),
                                            line,
                                            display,
                                            &m);
                            }
                        }
                    };
                    check_features(&f, &lang_features, "corresponding lang feature");
                    check_features(&f, &lib_features, "previous");
                    lib_features.insert(name.to_owned(), f);
                },
                Err(msg) => {
                    tidy_error!(bad, "{}:{}: {}", file.display(), line, msg);
                },
            }

    });
    lib_features
}

fn map_lib_features(base_src_path: &Path,
                    mf: &mut FnMut(Result<(&str, Feature), &str>, &Path, usize)) {
    let mut contents = String::new();
    super::walk(base_src_path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        let mut becoming_feature: Option<(String, Feature)> = None;
        for (i, line) in contents.lines().enumerate() {
            macro_rules! err {
                ($msg:expr) => {{
                    mf(Err($msg), file, i + 1);
                    continue;
                }};
            };
            if let Some((ref name, ref mut f)) = becoming_feature {
                if f.tracking_issue.is_none() {
                    f.tracking_issue = find_attr_val(line, "issue")
                    .map(|s| s.parse().unwrap());
                }
                if line.ends_with("]") {
                    mf(Ok((name, f.clone())), file, i + 1);
                } else if !line.ends_with(",") && !line.ends_with("\\") {
                    // We need to bail here because we might have missed the
                    // end of a stability attribute above because the "]"
                    // might not have been at the end of the line.
                    // We could then get into the very unfortunate situation that
                    // we continue parsing the file assuming the current stability
                    // attribute has not ended, and ignoring possible feature
                    // attributes in the process.
                    err!("malformed stability attribute");
                } else {
                    continue;
                }
            }
            becoming_feature = None;
            if line.contains("rustc_const_unstable(") {
                // const fn features are handled specially
                let feature_name = match find_attr_val(line, "feature") {
                    Some(name) => name,
                    None => err!("malformed stability attribute"),
                };
                let feature = Feature {
                    level: Status::Unstable,
                    since: "None".to_owned(),
                    has_gate_test: false,
                    // Whether there is a common tracking issue
                    // for these feature gates remains an open question
                    // https://github.com/rust-lang/rust/issues/24111#issuecomment-340283184
                    // But we take 24111 otherwise they will be shown as
                    // "internal to the compiler" which they are not.
                    tracking_issue: Some(24111),
                };
                mf(Ok((feature_name, feature)), file, i + 1);
                continue;
            }
            let level = if line.contains("[unstable(") {
                Status::Unstable
            } else if line.contains("[stable(") {
                Status::Stable
            } else {
                continue;
            };
            let feature_name = match find_attr_val(line, "feature") {
                Some(name) => name,
                None => err!("malformed stability attribute"),
            };
            let since = match find_attr_val(line, "since") {
                Some(name) => name,
                None if level == Status::Stable => {
                    err!("malformed stability attribute");
                }
                None => "None",
            };
            let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap());

            let feature = Feature {
                level,
                since: since.to_owned(),
                has_gate_test: false,
                tracking_issue,
            };
            if line.contains("]") {
                mf(Ok((feature_name, feature)), file, i + 1);
            } else {
                becoming_feature = Some((feature_name.to_owned(), feature));
            }
        }
    });
}
<commit_msg>Tidy: allow feature-gate tests to be ui tests<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to ensure that unstable features are all in order
//!
//! This check will ensure properties like:
//!
//! * All stability attributes look reasonably well formed
//! * The set of library features is disjoint from the set of language features
//! * Library features have at most one stability level
//! * Library features have at most one `since` value
//! * All unstable lang features have tests to ensure they are actually unstable

use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(Debug, PartialEq, Clone)]
pub enum Status {
    Stable,
    Removed,
    Unstable,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let as_str = match *self {
            Status::Stable => "stable",
            Status::Unstable => "unstable",
            Status::Removed => "removed",
        };
        fmt::Display::fmt(as_str, f)
    }
}

#[derive(Debug, Clone)]
pub struct Feature {
    pub level: Status,
    pub since: String,
    pub has_gate_test: bool,
    pub tracking_issue: Option<u32>,
}

impl Feature {
    fn check_match(&self, other: &Feature)-> Result<(), Vec<&'static str>> {
        let mut mismatches = Vec::new();
        if self.level != other.level {
            mismatches.push("stability level");
        }
        if self.level == Status::Stable || other.level == Status::Stable {
            // As long as a feature is unstable, the since field tracks
            // when the given part of the feature has been implemented.
            // Mismatches are tolerable as features evolve and functionality
            // gets added.
            // Once a feature is stable, the since field tracks the first version
            // it was part of the stable distribution, and mismatches are disallowed.
            if self.since != other.since {
                mismatches.push("since");
            }
        }
        if self.tracking_issue != other.tracking_issue {
            mismatches.push("tracking issue");
        }
        if mismatches.is_empty() {
            Ok(())
        } else {
            Err(mismatches)
        }
    }
}

pub type Features = HashMap<String, Feature>;

pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
    let mut features = collect_lang_features(path);
    assert!(!features.is_empty());

    let lib_features = get_and_check_lib_features(path, bad, &features);
    assert!(!lib_features.is_empty());

    let mut contents = String::new();

    super::walk_many(&[&path.join("test/ui-fulldeps"),
                       &path.join("test/ui"),
                       &path.join("test/compile-fail"),
                       &path.join("test/compile-fail-fulldeps"),
                       &path.join("test/parse-fail"),],
                     &mut |path| super::filter_dirs(path),
                     &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        let filen_underscore = filename.replace("-","_").replace(".rs","");
        let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features);

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
            };

            let gate_test_str = "gate-test-";

            if !line.contains(gate_test_str) {
                continue;
            }

            let feature_name = match line.find(gate_test_str) {
                Some(i) => {
                    &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())]
                },
                None => continue,
            };
            match features.get_mut(feature_name) {
                Some(f) => {
                    if filename_is_gate_test {
                        err(&format!("The file is already marked as gate test \
                                      through its name, no need for a \
                                      'gate-test-{}' comment",
                                     feature_name));
                    }
                    f.has_gate_test = true;
                }
                None => {
                    err(&format!("gate-test test found referencing a nonexistent feature '{}'",
                                 feature_name));
                }
            }
        }
    });

    // Only check the number of lang features.
    // Obligatory testing for library features is dumb.
    let gate_untested = features.iter()
                                .filter(|&(_, f)| f.level == Status::Unstable)
                                .filter(|&(_, f)| !f.has_gate_test)
                                .collect::<Vec<_>>();

    for &(name, _) in gate_untested.iter() {
        println!("Expected a gate test for the feature '{}'.", name);
        println!("Hint: create a failing test file named 'feature-gate-{}.rs'\
                \n      in the 'ui' test suite, with its failures due to\
                \n      missing usage of #![feature({})].", name, name);
        println!("Hint: If you already have such a test and don't want to rename it,\
                \n      you can also add a // gate-test-{} line to the test file.",
                 name);
    }

    if gate_untested.len() > 0 {
        tidy_error!(bad, "Found {} features without a gate test.", gate_untested.len());
    }

    if *bad {
        return;
    }
    if quiet {
        println!("* {} features", features.len());
        return;
    }

    let mut lines = Vec::new();
    for (name, feature) in features.iter() {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lang",
                           feature.level,
                           feature.since));
    }
    for (name, feature) in lib_features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lib",
                           feature.level,
                           feature.since));
    }

    lines.sort();
    for line in lines {
        println!("* {}", line);
    }
}

fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
    line.find(attr)
        .and_then(|i| line[i..].find('"').map(|j| i + j + 1))
        .and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
        .map(|(i, j)| &line[i..j])
}

fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool {
    if filen_underscore.starts_with("feature_gate") {
        for (n, f) in features.iter_mut() {
            if filen_underscore == format!("feature_gate_{}", n) {
                f.has_gate_test = true;
                return true;
            }
        }
    }
    return false;
}

pub fn collect_lang_features(base_src_path: &Path) -> Features {
    let mut contents = String::new();
    let path = base_src_path.join("libsyntax/feature_gate.rs");
    t!(t!(File::open(path)).read_to_string(&mut contents));

    contents.lines()
        .filter_map(|line| {
            let mut parts = line.trim().split(",");
            let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) {
                Some("active") => Status::Unstable,
                Some("removed") => Status::Removed,
                Some("accepted") => Status::Stable,
                _ => return None,
            };
            let name = parts.next().unwrap().trim();
            let since = parts.next().unwrap().trim().trim_matches('"');
            let issue_str = parts.next().unwrap().trim();
            let tracking_issue = if issue_str.starts_with("None") {
                None
            } else {
                let s = issue_str.split("(").nth(1).unwrap().split(")").nth(0).unwrap();
                Some(s.parse().unwrap())
            };
            Some((name.to_owned(),
                Feature {
                    level,
                    since: since.to_owned(),
                    has_gate_test: false,
                    tracking_issue,
                }))
        })
        .collect()
}

pub fn collect_lib_features(base_src_path: &Path) -> Features {
    let mut lib_features = Features::new();

    // This library feature is defined in the `compiler_builtins` crate, which
    // has been moved out-of-tree. Now it can no longer be auto-discovered by
    // `tidy`, because we need to filter out its (submodule) directory. Manually
    // add it to the set of known library features so we can still generate docs.
    lib_features.insert("compiler_builtins_lib".to_owned(), Feature {
        level: Status::Unstable,
        since: "".to_owned(),
        has_gate_test: false,
        tracking_issue: None,
    });

    map_lib_features(base_src_path,
                     &mut |res, _, _| {
        match res {
            Ok((name, feature)) => {
                if lib_features.get(name).is_some() {
                    return;
                }
                lib_features.insert(name.to_owned(), feature);
            },
            Err(_) => (),
        }
    });
   lib_features
}

fn get_and_check_lib_features(base_src_path: &Path,
                              bad: &mut bool,
                              lang_features: &Features) -> Features {
    let mut lib_features = Features::new();
    map_lib_features(base_src_path,
                     &mut |res, file, line| {
            match res {
                Ok((name, f)) => {
                    let mut check_features = |f: &Feature, list: &Features, display: &str| {
                        if let Some(ref s) = list.get(name) {
                            if let Err(m) = (&f).check_match(s) {
                                tidy_error!(bad,
                                            "{}:{}: mismatches to {} in: {:?}",
                                            file.display(),
                                            line,
                                            display,
                                            &m);
                            }
                        }
                    };
                    check_features(&f, &lang_features, "corresponding lang feature");
                    check_features(&f, &lib_features, "previous");
                    lib_features.insert(name.to_owned(), f);
                },
                Err(msg) => {
                    tidy_error!(bad, "{}:{}: {}", file.display(), line, msg);
                },
            }

    });
    lib_features
}

fn map_lib_features(base_src_path: &Path,
                    mf: &mut FnMut(Result<(&str, Feature), &str>, &Path, usize)) {
    let mut contents = String::new();
    super::walk(base_src_path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        let mut becoming_feature: Option<(String, Feature)> = None;
        for (i, line) in contents.lines().enumerate() {
            macro_rules! err {
                ($msg:expr) => {{
                    mf(Err($msg), file, i + 1);
                    continue;
                }};
            };
            if let Some((ref name, ref mut f)) = becoming_feature {
                if f.tracking_issue.is_none() {
                    f.tracking_issue = find_attr_val(line, "issue")
                    .map(|s| s.parse().unwrap());
                }
                if line.ends_with("]") {
                    mf(Ok((name, f.clone())), file, i + 1);
                } else if !line.ends_with(",") && !line.ends_with("\\") {
                    // We need to bail here because we might have missed the
                    // end of a stability attribute above because the "]"
                    // might not have been at the end of the line.
                    // We could then get into the very unfortunate situation that
                    // we continue parsing the file assuming the current stability
                    // attribute has not ended, and ignoring possible feature
                    // attributes in the process.
                    err!("malformed stability attribute");
                } else {
                    continue;
                }
            }
            becoming_feature = None;
            if line.contains("rustc_const_unstable(") {
                // const fn features are handled specially
                let feature_name = match find_attr_val(line, "feature") {
                    Some(name) => name,
                    None => err!("malformed stability attribute"),
                };
                let feature = Feature {
                    level: Status::Unstable,
                    since: "None".to_owned(),
                    has_gate_test: false,
                    // Whether there is a common tracking issue
                    // for these feature gates remains an open question
                    // https://github.com/rust-lang/rust/issues/24111#issuecomment-340283184
                    // But we take 24111 otherwise they will be shown as
                    // "internal to the compiler" which they are not.
                    tracking_issue: Some(24111),
                };
                mf(Ok((feature_name, feature)), file, i + 1);
                continue;
            }
            let level = if line.contains("[unstable(") {
                Status::Unstable
            } else if line.contains("[stable(") {
                Status::Stable
            } else {
                continue;
            };
            let feature_name = match find_attr_val(line, "feature") {
                Some(name) => name,
                None => err!("malformed stability attribute"),
            };
            let since = match find_attr_val(line, "since") {
                Some(name) => name,
                None if level == Status::Stable => {
                    err!("malformed stability attribute");
                }
                None => "None",
            };
            let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap());

            let feature = Feature {
                level,
                since: since.to_owned(),
                has_gate_test: false,
                tracking_issue,
            };
            if line.contains("]") {
                mf(Ok((feature_name, feature)), file, i + 1);
            } else {
                becoming_feature = Some((feature_name.to_owned(), feature));
            }
        }
    });
}
<|endoftext|>


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

#[cfg(feature = "bytes")]
use bytes::Bytes;

use crate::clear::Clear;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::coded_output_stream::WithCodedOutputStream;
use crate::error::ProtobufError;
use crate::error::Result;
use crate::message_dyn::MessageDyn;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::MessageDescriptor;
use crate::unknown::UnknownFields;
use crate::wire_format::check_message_size;

/// Trait implemented for all the messages (generated and dynamic).
///
/// * Generated messages are generated from `.proto` files
/// * Dynamic messages can be created without code generation using only parsed proto files
///   (see [FileDescriptor::new_dynamic](crate::reflect::FileDescriptor::new_dynamic)).
///
///
/// Also, generated messages implement `Default + PartialEq`
///
/// This trait is sized, there's accompanying [`MessageDyn`](crate::MessageDyn) trait
/// which is implemented for all messages which can be used in functions
/// without making message a function type parameter.
///
/// ## `Display`
///
/// [`Display`](fmt::Display) implementation for messages does protobuf text format.
/// See [`text_format`](crate::text_format) for more details.
pub trait Message:
    fmt::Debug + fmt::Display + Clear + Clone + Send + Sync + Sized + 'static
{
    /// Message descriptor for this message, used for reflection.
    ///
    /// This function is rarely needed to be called directly, use
    /// [`Message::descriptor_static()`] instead.
    fn descriptor_by_instance(&self) -> MessageDescriptor {
        Self::descriptor_static()
    }

    /// Get message descriptor for message type.
    ///
    /// ```
    /// # use protobuf::Message;
    /// # fn foo<MyMessage: Message>() {
    /// let descriptor = MyMessage::descriptor_static();
    /// assert_eq!("MyMessage", descriptor.name());
    /// # }
    /// ```
    fn descriptor_static() -> MessageDescriptor {
        panic!(
            "descriptor_static is not implemented for message, \
             LITE_RUNTIME must be used"
        );
    }

    /// True iff all required fields are initialized.
    /// Always returns `true` for protobuf 3.
    fn is_initialized(&self) -> bool;

    /// Update this message object with fields read from given stream.
    fn merge_from(&mut self, is: &mut CodedInputStream) -> Result<()>;

    /// Parse message from stream.
    fn parse_from(is: &mut CodedInputStream) -> Result<Self> {
        let mut r: Self = Message::new();
        r.merge_from(is)?;
        r.check_initialized()?;
        Ok(r)
    }

    /// Write message to the stream.
    ///
    /// Sizes of this messages and nested messages must be cached
    /// by calling `compute_size` prior to this call.
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> Result<()>;

    /// Compute and cache size of this message and all nested messages.
    ///
    /// Note if the computation overflows u32, the cached size is stored truncated.
    fn compute_size(&self) -> u64;

    /// Get size previously computed by `compute_size`.
    ///
    /// Note if message size exceeds u32, the cached size is stored truncated.
    fn cached_size(&self) -> u32;

    /// Write the message to the stream.
    ///
    /// Results in error if message is not fully initialized.
    fn write_to(&self, os: &mut CodedOutputStream) -> Result<()> {
        self.check_initialized()?;

        // cache sizes
        self.compute_size();
        // TODO: reserve additional
        self.write_to_with_cached_sizes(os)?;

        Ok(())
    }

    /// Write the message to the stream prepending the message with message length
    /// encoded as varint.
    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
        let size = self.compute_size();
        let size = check_message_size(size)?;
        os.write_raw_varint32(size as u32)?;

        let written = os.total_bytes_written();

        self.write_to_with_cached_sizes(os)?;

        // Self-check.
        assert_eq!(
            written + size as u64,
            os.total_bytes_written(),
            "Expected to write {}, actually wrote {}",
            size,
            os.total_bytes_written() - written
        );

        Ok(())
    }

    /// Write the message to the vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> Result<()> {
        let mut os = CodedOutputStream::vec(vec);
        self.write_length_delimited_to(&mut os)?;
        os.flush()?;
        Ok(())
    }

    /// Update this message object with fields read from given stream.
    fn merge_from_bytes(&mut self, bytes: &[u8]) -> Result<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    fn parse_from_reader(reader: &mut dyn Read) -> Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::new(reader);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    fn parse_from_bytes(bytes: &[u8]) -> Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from `Bytes` object.
    /// Resulting message may share references to the passed bytes object.
    #[cfg(feature = "bytes")]
    fn parse_from_tokio_bytes(bytes: &Bytes) -> Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::from_tokio_bytes(bytes);
        let r = Self::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Check if all required fields of this object are initialized.
    fn check_initialized(&self) -> Result<()> {
        if !self.is_initialized() {
            Err(
                ProtobufError::MessageNotInitialized(Self::descriptor_static().name().to_owned())
                    .into(),
            )
        } else {
            Ok(())
        }
    }

    /// Write the message to the writer.
    fn write_to_writer(&self, w: &mut dyn Write) -> Result<()> {
        w.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_vec(&self, v: &mut Vec<u8>) -> Result<()> {
        v.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    ///
    /// > **Note**: You can use [`Message::parse_from_bytes`]
    /// to do the reverse.
    fn write_to_bytes(&self) -> Result<Vec<u8>> {
        self.check_initialized()?;

        let size = self.compute_size() as usize;
        let mut v = Vec::with_capacity(size);
        // skip zerofill
        unsafe {
            v.set_len(size);
        }
        {
            let mut os = CodedOutputStream::bytes(&mut v);
            self.write_to_with_cached_sizes(&mut os)?;
            os.check_eof();
        }
        Ok(v)
    }

    /// Write the message to the writer, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_writer(&self, w: &mut dyn Write) -> Result<()> {
        w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
    }

    /// Write the message to the bytes vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_bytes(&self) -> Result<Vec<u8>> {
        let mut v = Vec::new();
        v.with_coded_output_stream(|os| self.write_length_delimited_to(os))?;
        Ok(v)
    }

    /// Get a reference to unknown fields.
    fn unknown_fields(&self) -> &UnknownFields;
    /// Get a mutable reference to unknown fields.
    fn mut_unknown_fields(&mut self) -> &mut UnknownFields;

    /// Create an empty message object.
    ///
    /// ```
    /// # use protobuf::Message;
    /// # fn foo<MyMessage: Message>() {
    /// let m = MyMessage::new();
    /// # }
    /// ```
    fn new() -> Self;

    /// Return a pointer to default immutable message with static lifetime.
    ///
    /// ```
    /// # use protobuf::Message;
    /// # fn foo<MyMessage: Message>() {
    /// let m: &MyMessage = MyMessage::default_instance();
    /// # }
    /// ```
    fn default_instance() -> &'static Self;

    /// Reflective equality.
    ///
    /// # See also
    ///
    /// [`dyn Message::reflect_eq_dyn()`], `dyn` version of this function.
    fn reflect_eq(&self, other: &Self, mode: &ReflectEqMode) -> bool {
        <dyn MessageDyn>::reflect_eq_dyn(self, other, mode)
    }
}
<commit_msg>Unnecessary unsafe when serializing to vec<commit_after>use std::fmt;
use std::io::Read;
use std::io::Write;

#[cfg(feature = "bytes")]
use bytes::Bytes;

use crate::clear::Clear;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::coded_output_stream::WithCodedOutputStream;
use crate::error::ProtobufError;
use crate::error::Result;
use crate::message_dyn::MessageDyn;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::MessageDescriptor;
use crate::unknown::UnknownFields;
use crate::wire_format::check_message_size;

/// Trait implemented for all the messages (generated and dynamic).
///
/// * Generated messages are generated from `.proto` files
/// * Dynamic messages can be created without code generation using only parsed proto files
///   (see [FileDescriptor::new_dynamic](crate::reflect::FileDescriptor::new_dynamic)).
///
///
/// Also, generated messages implement `Default + PartialEq`
///
/// This trait is sized, there's accompanying [`MessageDyn`](crate::MessageDyn) trait
/// which is implemented for all messages which can be used in functions
/// without making message a function type parameter.
///
/// ## `Display`
///
/// [`Display`](fmt::Display) implementation for messages does protobuf text format.
/// See [`text_format`](crate::text_format) for more details.
pub trait Message:
    fmt::Debug + fmt::Display + Clear + Clone + Send + Sync + Sized + 'static
{
    /// Message descriptor for this message, used for reflection.
    ///
    /// This function is rarely needed to be called directly, use
    /// [`Message::descriptor_static()`] instead.
    fn descriptor_by_instance(&self) -> MessageDescriptor {
        Self::descriptor_static()
    }

    /// Get message descriptor for message type.
    ///
    /// ```
    /// # use protobuf::Message;
    /// # fn foo<MyMessage: Message>() {
    /// let descriptor = MyMessage::descriptor_static();
    /// assert_eq!("MyMessage", descriptor.name());
    /// # }
    /// ```
    fn descriptor_static() -> MessageDescriptor {
        panic!(
            "descriptor_static is not implemented for message, \
             LITE_RUNTIME must be used"
        );
    }

    /// True iff all required fields are initialized.
    /// Always returns `true` for protobuf 3.
    fn is_initialized(&self) -> bool;

    /// Update this message object with fields read from given stream.
    fn merge_from(&mut self, is: &mut CodedInputStream) -> Result<()>;

    /// Parse message from stream.
    fn parse_from(is: &mut CodedInputStream) -> Result<Self> {
        let mut r: Self = Message::new();
        r.merge_from(is)?;
        r.check_initialized()?;
        Ok(r)
    }

    /// Write message to the stream.
    ///
    /// Sizes of this messages and nested messages must be cached
    /// by calling `compute_size` prior to this call.
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> Result<()>;

    /// Compute and cache size of this message and all nested messages.
    ///
    /// Note if the computation overflows u32, the cached size is stored truncated.
    fn compute_size(&self) -> u64;

    /// Get size previously computed by `compute_size`.
    ///
    /// Note if message size exceeds u32, the cached size is stored truncated.
    fn cached_size(&self) -> u32;

    /// Write the message to the stream.
    ///
    /// Results in error if message is not fully initialized.
    fn write_to(&self, os: &mut CodedOutputStream) -> Result<()> {
        self.check_initialized()?;

        // cache sizes
        self.compute_size();
        // TODO: reserve additional
        self.write_to_with_cached_sizes(os)?;

        Ok(())
    }

    /// Write the message to the stream prepending the message with message length
    /// encoded as varint.
    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
        let size = self.compute_size();
        let size = check_message_size(size)?;
        os.write_raw_varint32(size as u32)?;

        let written = os.total_bytes_written();

        self.write_to_with_cached_sizes(os)?;

        // Self-check.
        assert_eq!(
            written + size as u64,
            os.total_bytes_written(),
            "Expected to write {}, actually wrote {}",
            size,
            os.total_bytes_written() - written
        );

        Ok(())
    }

    /// Write the message to the vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> Result<()> {
        let mut os = CodedOutputStream::vec(vec);
        self.write_length_delimited_to(&mut os)?;
        os.flush()?;
        Ok(())
    }

    /// Update this message object with fields read from given stream.
    fn merge_from_bytes(&mut self, bytes: &[u8]) -> Result<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    fn parse_from_reader(reader: &mut dyn Read) -> Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::new(reader);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    fn parse_from_bytes(bytes: &[u8]) -> Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from `Bytes` object.
    /// Resulting message may share references to the passed bytes object.
    #[cfg(feature = "bytes")]
    fn parse_from_tokio_bytes(bytes: &Bytes) -> Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::from_tokio_bytes(bytes);
        let r = Self::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Check if all required fields of this object are initialized.
    fn check_initialized(&self) -> Result<()> {
        if !self.is_initialized() {
            Err(
                ProtobufError::MessageNotInitialized(Self::descriptor_static().name().to_owned())
                    .into(),
            )
        } else {
            Ok(())
        }
    }

    /// Write the message to the writer.
    fn write_to_writer(&self, w: &mut dyn Write) -> Result<()> {
        w.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_vec(&self, v: &mut Vec<u8>) -> Result<()> {
        v.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    ///
    /// > **Note**: You can use [`Message::parse_from_bytes`]
    /// to do the reverse.
    fn write_to_bytes(&self) -> Result<Vec<u8>> {
        self.check_initialized()?;

        let size = self.compute_size() as usize;
        let mut v = Vec::with_capacity(size);
        {
            let mut os = CodedOutputStream::vec(&mut v);
            self.write_to_with_cached_sizes(&mut os)?;
            os.flush()?;
        }
        Ok(v)
    }

    /// Write the message to the writer, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_writer(&self, w: &mut dyn Write) -> Result<()> {
        w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
    }

    /// Write the message to the bytes vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_bytes(&self) -> Result<Vec<u8>> {
        let mut v = Vec::new();
        v.with_coded_output_stream(|os| self.write_length_delimited_to(os))?;
        Ok(v)
    }

    /// Get a reference to unknown fields.
    fn unknown_fields(&self) -> &UnknownFields;
    /// Get a mutable reference to unknown fields.
    fn mut_unknown_fields(&mut self) -> &mut UnknownFields;

    /// Create an empty message object.
    ///
    /// ```
    /// # use protobuf::Message;
    /// # fn foo<MyMessage: Message>() {
    /// let m = MyMessage::new();
    /// # }
    /// ```
    fn new() -> Self;

    /// Return a pointer to default immutable message with static lifetime.
    ///
    /// ```
    /// # use protobuf::Message;
    /// # fn foo<MyMessage: Message>() {
    /// let m: &MyMessage = MyMessage::default_instance();
    /// # }
    /// ```
    fn default_instance() -> &'static Self;

    /// Reflective equality.
    ///
    /// # See also
    ///
    /// [`dyn Message::reflect_eq_dyn()`], `dyn` version of this function.
    fn reflect_eq(&self, other: &Self, mode: &ReflectEqMode) -> bool {
        <dyn MessageDyn>::reflect_eq_dyn(self, other, mode)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![allow(deprecated)]
use std::{ptr, os};

use spaces::immix_space::block_info::BlockInfo;

use constants::{BLOCK_SIZE, HEAP_SIZE};
use gc_object::GCObjectRef;

/// The `BlockAllocator` is the global resource for blocks for the immix
/// space.
///
/// On initialization it will allocate a memory map of `HEAP_SIZE` and align
/// it to `BLOCK_SIZE`. During normal runtime it will allocate blocks on the
/// fly from this memory map and store returned blocks in a list.
///
/// Blocks from this `BlockAllocator` are always aligned to `BLOCK_SIZE`.
///
/// The list of returned free blocks is a stack. The `BlockAllocator` will
/// first exhaust the returned free blocks and then fall back to allocating
/// new blocks from the memory map. This means it will return recently
/// returned blocks first.
pub struct BlockAllocator {
    /// The memory map of `HEAP_SIZE`.
    mmap: os::MemoryMap,

    /// The pointer to the last allocated block.
    data: *mut u8,

    /// The upper bound of the memory map as a pointer.
    data_bound: *mut u8,

    /// A list of returned (free) blocks.
    free_blocks: Vec<*mut BlockInfo>,
}

impl BlockAllocator {
    /// Create a new `BlockAllocator`.
    ///
    /// This will `panic` if no memory map of size `HEAP_SIZE` can be
    /// allocared.
    pub fn new() -> BlockAllocator {
        let mmap = os::MemoryMap::new(HEAP_SIZE + BLOCK_SIZE,
                                      &[os::MapOption::MapReadable,
                                        os::MapOption::MapWritable]).unwrap();
        let data = unsafe{ mmap.data().offset((BLOCK_SIZE - (mmap.data() as usize) % BLOCK_SIZE) as isize) };
        let data_bound = unsafe{ mmap.data().offset(mmap.len() as isize) };
        debug!("Allocated heap {:p} of size {}, usable range: {:p} - {:p} (size {}, {} blocks)",
                mmap.data(), mmap.len(), data, data_bound,
                (data_bound as usize) - (data  as usize),
                ((data_bound as usize) - (data  as usize)) / BLOCK_SIZE);
        debug_assert!((data as usize) % BLOCK_SIZE == 0,
            "Allocated mmap {:p} is not aligned (offset {})",
            data, (data as usize) % BLOCK_SIZE);
        return BlockAllocator {
            mmap: mmap,
            data: data,
            data_bound: data_bound,
            free_blocks: Vec::with_capacity(HEAP_SIZE / BLOCK_SIZE),
        };
    }

    /// Get a new block aligned to `BLOCK_SIZE`.
    pub fn get_block(&mut self) -> Option<*mut BlockInfo> {
        return self.free_blocks.pop().or_else(|| self.build_next_block());
    }

    /// Return a collection of blocks.
    pub fn return_blocks(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.free_blocks.extend(blocks.into_iter());
    }

    /// Return the number of unallocated blocks.
    pub fn available_blocks(&self) -> usize {
        return (((self.data_bound as usize) - (self.data as usize)) % BLOCK_SIZE)
            + self.free_blocks.len();
    }

    /// Return if an address is within the bounds of the memory map.
    pub fn is_in_space(&self, object: GCObjectRef) -> bool {
        return self.mmap.data() < (object as *mut u8)
            && (object as *mut u8) < self.data_bound;
    }
}

impl BlockAllocator {
    /// Build a new block from the memory map.
    ///
    /// Returns `None` if the memory map is exhausted.
    fn build_next_block(&mut self) -> Option<*mut BlockInfo> {
        let block = unsafe{ self.data.offset(BLOCK_SIZE as isize) };
        if block < self.data_bound {
            self.data = block;
            debug_assert!((block as usize) % BLOCK_SIZE == 0,
                "Allocated block {:p} is not aligned (offset {})",
                block, (block as usize) % BLOCK_SIZE);
            unsafe{ ptr::write(block as *mut BlockInfo, BlockInfo::new()); }
            return Some(block as *mut BlockInfo);
        }
        return None;
    }
}
<commit_msg>Implement MemoryMap wrapper in block_allocator<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![allow(deprecated)]
use std::{ptr, os};
use libc;

use spaces::immix_space::block_info::BlockInfo;

use constants::{BLOCK_SIZE, HEAP_SIZE, TOTAL_BLOCKS};
use gc_object::GCObjectRef;

/// A simple wrapper for a heap mmap.
struct MemoryMap{
    /// The pointer to the mmap'ed region.
    mmap: *mut libc::c_void,
}

impl MemoryMap {
    /// Create a new `MemoryMap` of `HEAP_SIZE + BLOCK_SIZE` to be aligned to
    /// `BLOCK_SIZE` boundaries.
    fn new() -> MemoryMap {
        let mmap = unsafe {
            libc::mmap(ptr::null_mut(), (HEAP_SIZE + BLOCK_SIZE) as libc::size_t,
                       libc::PROT_READ | libc::PROT_WRITE,
                      libc::MAP_PRIVATE | libc::MAP_ANON, -1, 0)
        };

        if mmap == libc::MAP_FAILED {
            panic!("Failed to allocate the heap memory map");
        }

        return MemoryMap {
            mmap: mmap,
        }
    }

    /// Return a `BLOCK_SIZE` aligned pointer to the mmap'ed region.
    fn aligned(&self) -> *mut u8 {
        let offset = BLOCK_SIZE - (self.mmap as usize) % BLOCK_SIZE;
        return unsafe{ self.mmap.offset(offset as isize) } as *mut u8;
    }

    /// Return a pointer to the start of the mmap'ed region.
    fn start(&self) -> *mut u8 {
        return self.mmap as *mut u8;
    }

    /// Return a pointer to the end of the mmap'ed region.
    fn bound(&self) -> *mut u8 {
        return unsafe{ self.mmap.offset(HEAP_SIZE as isize) } as *mut u8;
    }
}

impl Drop for MemoryMap {
    fn drop(&mut self) {
        unsafe {
            libc::munmap(self.mmap, (HEAP_SIZE + BLOCK_SIZE) as libc::size_t);
        }
    }
}

/// The `BlockAllocator` is the global resource for blocks for the immix
/// space.
///
/// On initialization it will allocate a memory map of `HEAP_SIZE` and align
/// it to `BLOCK_SIZE`. During normal runtime it will allocate blocks on the
/// fly from this memory map and store returned blocks in a list.
///
/// Blocks from this `BlockAllocator` are always aligned to `BLOCK_SIZE`.
///
/// The list of returned free blocks is a stack. The `BlockAllocator` will
/// first exhaust the returned free blocks and then fall back to allocating
/// new blocks from the memory map. This means it will return recently
/// returned blocks first.
pub struct BlockAllocator {
    /// The memory map of `HEAP_SIZE`.
    mmap: MemoryMap,

    /// The pointer to the last allocated block.
    data: *mut u8,

    /// The upper bound of the memory map as a pointer.
    data_bound: *mut u8,

    /// A list of returned (free) blocks.
    free_blocks: Vec<*mut BlockInfo>,
}

impl BlockAllocator {
    /// Create a new `BlockAllocator`.
    ///
    /// This will `panic` if no memory map of size `HEAP_SIZE` can be
    /// allocared.
    pub fn new() -> BlockAllocator {
        let mmap = MemoryMap::new();
        let data = mmap.aligned();
        let bound = mmap.bound();
        debug_assert!((data as usize) % BLOCK_SIZE == 0,
            "Allocated mmap {:p} is not aligned (offset {})",
            data, (data as usize) % BLOCK_SIZE);
        return BlockAllocator {
            mmap: mmap,
            data: data,
            data_bound: bound,
            free_blocks: Vec::with_capacity(TOTAL_BLOCKS),
        };
    }

    /// Get a new block aligned to `BLOCK_SIZE`.
    pub fn get_block(&mut self) -> Option<*mut BlockInfo> {
        return self.free_blocks.pop().or_else(|| self.build_next_block());
    }

    /// Return a collection of blocks.
    pub fn return_blocks(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.free_blocks.extend(blocks.into_iter());
    }

    /// Return the number of unallocated blocks.
    pub fn available_blocks(&self) -> usize {
        return (((self.data_bound as usize) - (self.data as usize)) % BLOCK_SIZE)
            + self.free_blocks.len();
    }

    /// Return if an address is within the bounds of the memory map.
    pub fn is_in_space(&self, object: GCObjectRef) -> bool {
        return self.mmap.start() < (object as *mut u8)
            && (object as *mut u8) < self.data_bound;
    }
}

impl BlockAllocator {
    /// Build a new block from the memory map.
    ///
    /// Returns `None` if the memory map is exhausted.
    fn build_next_block(&mut self) -> Option<*mut BlockInfo> {
        let block = unsafe{ self.data.offset(BLOCK_SIZE as isize) };
        if block < self.data_bound {
            self.data = block;
            debug_assert!((block as usize) % BLOCK_SIZE == 0,
                "Allocated block {:p} is not aligned (offset {})",
                block, (block as usize) % BLOCK_SIZE);
            unsafe{ ptr::write(block as *mut BlockInfo, BlockInfo::new()); }
            return Some(block as *mut BlockInfo);
        }
        return None;
    }
}
<|endoftext|>


<commit_before>// Issue #2263.

// Should pass region checking.
fn ok(f: fn@(x: &uint)) {
    // Here, g is a function that can accept a uint pointer with
    // lifetime r, and f is a function that can accept a uint pointer
    // with any lifetime.  The assignment g = f should be OK (i.e., f
    // should be a subtype of g), because f can be used in any context
    // that expects g's type.  But this currently fails.
    let mut g: fn@(y: &r.uint) = fn@(x: &r.uint) { };
    g = f;
}

// This version is the same as above, except that here, g's type is
// inferred.
fn ok_inferred(f: fn@(x: &uint)) {
    let mut g = fn@(x: &r.uint) { };
    g = f;
}

fn main() {
}
<commit_msg>Clarify comments in test.<commit_after>// Issue #2263.

// Should pass region checking.
fn ok(f: fn@(x: &uint)) {
    // Here, g is a function that can accept a uint pointer with
    // lifetime r, and f is a function that can accept a uint pointer
    // with any lifetime.  The assignment g = f should be OK (i.e.,
    // f's type should be a subtype of g's type), because f can be
    // used in any context that expects g's type.  But this currently
    // fails.
    let mut g: fn@(y: &r.uint) = fn@(x: &r.uint) { };
    g = f;
}

// This version is the same as above, except that here, g's type is
// inferred.
fn ok_inferred(f: fn@(x: &uint)) {
    let mut g = fn@(x: &r.uint) { };
    g = f;
}

fn main() {
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fs::{self, File};
use std::io::Write;
use std::marker;
use std::path::{Path, MAIN_SEPARATOR};

use serde_json;
use tokio_core::reactor;
use tokio_retry::strategy::FibonacciBackoff;
use tokio_retry::Retry;
use uuid::Uuid;

use failure::ResultExt;

use keychain::{self, Identifier, Keychain};
use util::secp::pedersen

use error::{Error, ErrorKind};

use libwallet;

use libwallet::types::{
	Context, OutputData, TxLogEntry, WalletBackend, WalletClient, WalletDetails, WalletOutputBatch,
};

use types::{WalletConfig, WalletSeed};

const DETAIL_FILE: &'static str = "wallet.det";
const DET_BCK_FILE: &'static str = "wallet.detbck";
const DAT_FILE: &'static str = "wallet.dat";
const BCK_FILE: &'static str = "wallet.bck";
const LOCK_FILE: &'static str = "wallet.lock";

#[derive(Debug)]
struct FileBatch<'a, K: 'a>
where
	K: Keychain,
{
	/// List of outputs
	outputs: &'a mut HashMap<String, OutputData>,
	/// Wallet Details
	details: WalletDetails,
	/// Data file path
	data_file_path: String,
	/// Details file path
	details_file_path: String,
	/// lock file path
	lock_file_path: String,
	/// PhantomData for our K: Keychain.
	_marker: marker::PhantomData<K>,
}

impl<'a, K> WalletOutputBatch<K> for FileBatch<'a, K>
where
	K: Keychain,
{
	fn keychain(&mut self) -> &mut K {
		unimplemented!();
	}

	fn save(&mut self, out: OutputData) -> Result<(), libwallet::Error> {
		let _ = self.outputs.insert(out.key_id.to_hex(), out);
		Ok(())
	}

	fn get(&self, id: &Identifier) -> Result<OutputData, libwallet::Error> {
		self.outputs
			.get(&id.to_hex())
			.map(|od| od.clone())
			.ok_or(libwallet::ErrorKind::Backend("not found".to_string()).into())
	}

	fn delete(&mut self, id: &Identifier) -> Result<(), libwallet::Error> {
		let _ = self.outputs.remove(&id.to_hex());
		Ok(())
	}

	fn save_details(&mut self, _r: Identifier, w: WalletDetails) -> Result<(), libwallet::Error> {
		self.details = w;
		Ok(())
	}

	fn next_tx_log_id(&mut self, _root_key_id: Identifier) -> Result<u32, libwallet::Error> {
		Ok(0)
	}

	fn save_tx_log_entry(&self, _t: TxLogEntry) -> Result<(), libwallet::Error> {
		// not implemented for file wallets
		Ok(())
	}

	fn lock_output(&mut self, out: &mut OutputData) -> Result<(), libwallet::Error> {
		if let Some(out_to_lock) = self.outputs.get_mut(&out.key_id.to_hex()) {
			if out_to_lock.value == out.value {
				out_to_lock.lock()
			}
		}
		Ok(())
	}

	fn iter(&self) -> Box<Iterator<Item = OutputData>> {
		unimplemented!()
	}

	fn tx_log_iter(&self) -> Box<Iterator<Item = TxLogEntry>> {
		unimplemented!()
	}

	fn save_private_context(
		&mut self,
		_slate_id: &[u8],
		_ctx: &Context,
	) -> Result<(), libwallet::Error> {
		unimplemented!()
	}

	fn delete_private_context(&mut self, _slate_id: &[u8]) -> Result<(), libwallet::Error> {
		unimplemented!()
	}

	fn commit(&self) -> Result<(), libwallet::Error> {
		let mut data_file = File::create(self.data_file_path.clone())
			.context(libwallet::ErrorKind::CallbackImpl("Could not create"))?;
		let mut details_file = File::create(self.details_file_path.clone())
			.context(libwallet::ErrorKind::CallbackImpl("Could not create"))?;
		let mut outputs = self.outputs.values().collect::<Vec<_>>();
		outputs.sort();
		let res_json = serde_json::to_vec_pretty(&outputs).context(
			libwallet::ErrorKind::CallbackImpl("Error serializing wallet output data"),
		)?;
		let details_res_json = serde_json::to_vec_pretty(&self.details).context(
			libwallet::ErrorKind::CallbackImpl("Error serializing wallet details data"),
		)?;
		data_file
			.write_all(res_json.as_slice())
			.context(libwallet::ErrorKind::CallbackImpl(
				"Error writing wallet data file",
			))?;
		details_file
			.write_all(details_res_json.as_slice())
			.context(libwallet::ErrorKind::CallbackImpl(
				"Error writing wallet details file",
			))?;
		Ok(())
	}
}

impl<'a, K> Drop for FileBatch<'a, K>
where
	K: Keychain,
{
	fn drop(&mut self) {
		// delete the lock file
		if let Err(e) = fs::remove_dir(&self.lock_file_path) {
			error!(
				"Could not remove wallet lock file. Maybe insufficient rights? {:?} ", e
			);
		}
		info!("... released wallet lock");
	}
}

/// Wallet information tracking all our outputs. Based on HD derivation and
/// avoids storing any key data, only storing output amounts and child index.
#[derive(Debug, Clone)]
pub struct FileWallet<C, K> {
	/// Keychain
	pub keychain: Option<K>,
	/// Client implementation
	pub client: C,
	/// Configuration
	pub config: WalletConfig,
	/// passphrase: TODO better ways of dealing with this other than storing
	passphrase: String,
	/// List of outputs
	pub outputs: HashMap<String, OutputData>,
	/// Tx log
	pub tx_log: Vec<TxLogEntry>,
	/// Details
	pub details: WalletDetails,
	/// Data file path
	pub data_file_path: String,
	/// Backup file path
	pub backup_file_path: String,
	/// lock file path
	pub lock_file_path: String,
	/// details file path
	pub details_file_path: String,
	/// Details backup file path
	pub details_bak_path: String,
}

impl<C, K> WalletBackend<C, K> for FileWallet<C, K>
where
	C: WalletClient,
	K: Keychain,
{
	/// Initialize with whatever stored credentials we have
	fn open_with_credentials(&mut self) -> Result<(), libwallet::Error> {
		let wallet_seed = WalletSeed::from_file(&self.config)
			.context(libwallet::ErrorKind::CallbackImpl("Error opening wallet"))?;
		let keychain = wallet_seed.derive_keychain(&self.passphrase);
		self.keychain = Some(keychain.context(libwallet::ErrorKind::CallbackImpl(
			"Error deriving keychain",
		))?);
		Ok(())
	}

	/// Close wallet and remove any stored credentials (TBD)
	fn close(&mut self) -> Result<(), libwallet::Error> {
		debug!("Closing wallet keychain");
		self.keychain = None;
		Ok(())
	}

	/// Return the keychain being used
	fn keychain(&mut self) -> &mut K {
		self.keychain.as_mut().unwrap()
	}

	/// Return the client being used
	fn client(&mut self) -> &mut C {
		&mut self.client
	}

	fn iter<'a>(&'a self) -> Box<Iterator<Item = OutputData> + 'a> {
		Box::new(self.outputs.values().cloned())
	}

	fn get_tx_log_entry(&self, _u: &Uuid) -> Result<Option<TxLogEntry>, libwallet::Error> {
		Ok(None)
	}

	fn tx_log_iter<'a>(&'a self) -> Box<Iterator<Item = TxLogEntry> + 'a> {
		Box::new(self.tx_log.iter().cloned())
	}

	fn get_private_context(&mut self, _slate_id: &[u8]) -> Result<Context, libwallet::Error> {
		unimplemented!()
	}

	fn get(&self, id: &Identifier) -> Result<OutputData, libwallet::Error> {
		self.outputs
			.get(&id.to_hex())
			.map(|o| o.clone())
			.ok_or(libwallet::ErrorKind::Backend("not found".to_string()).into())
	}

	fn get_commitment(
		&mut self,
		_id: &Identifier,
	) -> Result<pedersen::Commitment, libwallet::Error> {
		unimplemented!();
	}

	fn batch<'a>(&'a mut self) -> Result<Box<WalletOutputBatch<K> + 'a>, libwallet::Error> {
		self.lock()?;

		// We successfully acquired the lock - so do what needs to be done.
		self.read_or_create_paths()
			.context(libwallet::ErrorKind::CallbackImpl("Lock Error"))?;
		self.write(&self.backup_file_path, &self.details_bak_path)
			.context(libwallet::ErrorKind::CallbackImpl("Write Error"))?;

		Ok(Box::new(FileBatch {
			outputs: &mut self.outputs,
			details: self.details.clone(),
			data_file_path: self.data_file_path.clone(),
			details_file_path: self.details_file_path.clone(),
			lock_file_path: self.lock_file_path.clone(),
			_marker: marker::PhantomData,
		}))
	}

	/// Next child index when we want to create a new output.
	fn next_child<'a>(
		&'a mut self,
		root_key_id: keychain::Identifier,
	) -> Result<u32, libwallet::Error> {
		let mut details = self.details(root_key_id.clone())?;
		let mut max_n = 0;
		for out in self.iter() {
			if max_n < out.n_child && out.root_key_id == root_key_id {
				max_n = out.n_child;
			}
		}
		let mut batch = self.batch()?;
		if details.last_child_index <= max_n {
			details.last_child_index = max_n + 1;
		} else {
			details.last_child_index += 1;
		}
		batch.save_details(root_key_id.clone(), details.clone())?;
		batch.commit()?;
		Ok(details.last_child_index)
	}

	fn details(&mut self, _root_key_id: Identifier) -> Result<WalletDetails, libwallet::Error> {
		self.batch()?;
		Ok(self.details.clone())
	}

	/// Restore wallet contents
	fn restore(&mut self) -> Result<(), libwallet::Error> {
		libwallet::internal::restore::restore(self)
	}
}

impl<C, K> FileWallet<C, K>
where
	C: WalletClient,
	K: Keychain,
{
	/// Create a new FileWallet instance
	pub fn new(config: WalletConfig, passphrase: &str, client: C) -> Result<Self, Error> {
		let mut retval = FileWallet {
			keychain: None,
			client: client,
			config: config.clone(),
			passphrase: String::from(passphrase),
			outputs: HashMap::new(),
			tx_log: Vec::new(),
			details: WalletDetails::default(),
			data_file_path: format!("{}{}{}", config.data_file_dir, MAIN_SEPARATOR, DAT_FILE),
			backup_file_path: format!("{}{}{}", config.data_file_dir, MAIN_SEPARATOR, BCK_FILE),
			lock_file_path: format!("{}{}{}", config.data_file_dir, MAIN_SEPARATOR, LOCK_FILE),
			details_file_path: format!("{}{}{}", config.data_file_dir, MAIN_SEPARATOR, DETAIL_FILE),
			details_bak_path: format!("{}{}{}", config.data_file_dir, MAIN_SEPARATOR, DET_BCK_FILE),
		};
		match retval.read_or_create_paths() {
			Ok(_) => Ok(retval),
			Err(e) => Err(e),
		}
	}

	fn lock(&self) -> Result<(), libwallet::Error> {
		// create directory if it doesn't exist
		fs::create_dir_all(self.config.data_file_dir.clone()).unwrap_or_else(|why| {
			info!("! {:?}", why.kind());
		});

		info!("Acquiring wallet lock ...");

		let lock_file_path = self.lock_file_path.clone();
		let action = || {
			trace!("making lock file for wallet lock");
			fs::create_dir(&lock_file_path)
		};

		// use tokio_retry to cleanly define some retry logic
		let mut core = reactor::Core::new().unwrap();
		let retry_strategy = FibonacciBackoff::from_millis(1000).take(10);
		let retry_future = Retry::spawn(core.handle(), retry_strategy, action);
		let retry_result = core
			.run(retry_future)
			.context(libwallet::ErrorKind::CallbackImpl(
				"Failed to acquire lock file",
			));

		match retry_result {
			Ok(_) => Ok(()),
			Err(e) => {
				error!(
					"Failed to acquire wallet lock file (multiple retries)",
				);
				Err(e.into())
			}
		}
	}

	/// Read the wallet data or create brand files if the data
	/// files don't yet exist
	fn read_or_create_paths(&mut self) -> Result<(), Error> {
		if !Path::new(&self.config.data_file_dir.clone()).exists() {
			fs::create_dir_all(&self.config.data_file_dir.clone()).unwrap_or_else(|why| {
				info!("! {:?}", why.kind());
			});
		}
		if Path::new(&self.data_file_path.clone()).exists() {
			self.read()?;
		}
		if Path::new(&self.details_file_path.clone()).exists() {
			self.details = self.read_details()?;
		}
		Ok(())
	}

	/// Read details file from disk
	fn read_details(&self) -> Result<WalletDetails, Error> {
		let details_file = File::open(self.details_file_path.clone())
			.context(ErrorKind::FileWallet(&"Could not open wallet details file"))?;
		serde_json::from_reader(details_file)
			.context(ErrorKind::Format)
			.map_err(|e| e.into())
	}

	/// Read output_data vec from disk.
	fn read_outputs(&self) -> Result<Vec<OutputData>, Error> {
		let data_file = File::open(self.data_file_path.clone())
			.context(ErrorKind::FileWallet(&"Could not open wallet file"))?;
		serde_json::from_reader(data_file)
			.context(ErrorKind::Format)
			.map_err(|e| e.into())
	}

	/// Populate wallet_data with output_data from disk.
	fn read(&mut self) -> Result<(), Error> {
		let outputs = self.read_outputs()?;
		self.outputs = HashMap::new();
		for out in outputs {
			self.outputs.insert(out.key_id.to_hex(), out.clone());
		}
		Ok(())
	}

	/// Write the wallet and details data to disk.
	fn write(&self, data_file_path: &str, details_file_path: &str) -> Result<(), Error> {
		let mut data_file =
			File::create(data_file_path).context(ErrorKind::FileWallet(&"Could not create "))?;
		let mut outputs = self.outputs.values().collect::<Vec<_>>();
		outputs.sort();
		let res_json = serde_json::to_vec_pretty(&outputs)
			.context(ErrorKind::FileWallet("Error serializing wallet data"))?;
		data_file
			.write_all(res_json.as_slice())
			.context(ErrorKind::FileWallet(&"Error writing wallet file"))?;
		// write details file
		let mut details_file =
			File::create(details_file_path).context(ErrorKind::FileWallet(&"Could not create "))?;
		let res_json = serde_json::to_string_pretty(&self.details).context(
			ErrorKind::FileWallet("Error serializing wallet details file"),
		)?;
		details_file
			.write_all(res_json.into_bytes().as_slice())
			.context(ErrorKind::FileWallet(&"Error writing wallet details file"))
			.map_err(|e| e.into())
	}
}
<commit_msg>remove file wallet (#1824)<commit_after><|endoftext|>


<commit_before>// Chapter 4.12 - Structs
// [Chapter 4.12] https://doc.rust-lang.org/book/structs.html
pub mod structs {
    struct Point {
        x: i32,
        y: i32,
    }

    pub fn main() {
        let origin = Point{x: 10, y: 20}; // origin: Point
        println!("The origin is at ({}, {})", origin.x, origin.y);

        let mut origin = Point{x: 10, y: 20}; // origin: Point
        origin.x = 30;
        println!("The origin is at ({}, {})", origin.x, origin.y);
    }
}<commit_msg>Chapter 4.12 - Tuple Structs<commit_after>// Chapter 4.12 - Structs
// [Chapter 4.12] https://doc.rust-lang.org/book/structs.html
pub mod structs {
    struct Point {
        x: i32,
        y: i32,
    }
    struct Point3D {
        x: i32,
        y: i32,
        z: i32,
    }

    struct PointRef<'a> {
        x: &'a mut i32,
        y: &'a mut i32,
    }

    pub fn main() {
        let origin = Point{x: 10, y: 20}; // origin: Point
        println!("The origin is at ({}, {})", origin.x, origin.y);

        let mut origin = Point{y: 20, x: 10,}; // origin: Point
        origin.x = 30;
        println!("The origin is at ({}, {})", origin.x, origin.y);
        // Mutable struct
        {
            let r = PointRef{
                x: &mut origin.x,
                y: &mut origin.y,
            };
            *r.x = 5;
            *r.y = 6;
        }
        println!("The origin is at ({}, {})", origin.x, origin.y);

        let point3d_1 = Point3D {
            x:  10,
            y:  20,
            z:  30,
        };
        let point3d_2 = Point3D {
            z:  300,
            ..point3d_1
        };
        println!("The origin is at ({}, {}, {})",
                 point3d_2.x,
                 point3d_2.y,
                 point3d_2.z);
        tuple_stuct();
    }

    fn tuple_stuct() {
        struct Color(i32, i32, i32);
        let black = Color(0, 0, 0);
        let white = Color(0xFF, 0b010, 0xFF);
        println!("", black);
    }
}<|endoftext|>


<commit_before>// Copyright 2015 Jauhien Piatlicki.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// LLVM Support
// LLVM-C header Support.h

use std;
use libc::{c_char, c_void};

mod wrappers;

pub fn add_symbol<T>(name: &str, reference: &T) {
    let name = std::ffi::CString::new(name).unwrap();
    let addr = & *reference as *const _ as *const c_void;
    unsafe {
        wrappers::LLVM_AddSymbol(name.as_ptr() as *const c_char, addr)
    }
}
<commit_msg>[support] make add_symbol accept *const ()<commit_after>// Copyright 2015 Jauhien Piatlicki.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// LLVM Support
// LLVM-C header Support.h

use std;
use libc::{c_char, c_void};

mod wrappers;

// function is marked as unsafe as user can trigger execution of an
// arbitrary memory address using it
pub unsafe fn add_symbol(name: &str, ptr: *const ()) {
    let name = std::ffi::CString::new(name).unwrap();
    let addr = ptr as *const c_void;
    wrappers::LLVM_AddSymbol(name.as_ptr() as *const c_char, addr)
}
<|endoftext|>


<commit_before>use std::mem;
use std::cmp::{Ord, Eq};
use std::ops::{Add, Mul};
use std::num::{Zero, One, Bounded};

pub trait Monoid {
    fn mempty() -> Self;
    fn mappend(&self, other: &Self) -> Self;
}

impl<T: Clone> Monoid for Vec<T> {
    #[inline]
    fn mempty() -> Vec<T> { Vec::new() }
    #[inline]
    fn mappend(&self, other: &Vec<T>) -> Vec<T> { self + *other }
}

impl Monoid for String {
    #[inline]
    fn mempty() -> String { "".to_string() }
    #[inline]
    fn mappend(&self, other: &String) -> String { format!("{}{}", self, other) }
}

pub trait Wrap<T> {
    fn wrap(T) -> Self;
    fn unwrap(self) -> T;
    fn unwrap_ref<'a>(&'a self) -> &'a T;
}

pub trait WrapMonoid<T>: Wrap<T> + Monoid {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Sum<T> { repr: T }

impl<T> Sum<T> {
    #[inline]
    pub fn new(val: T) -> Sum<T> { Sum { repr: val }}
}

impl<T: Zero + Add<T, T>> Monoid for Sum<T> {
    #[inline]
    fn mempty() -> Sum<T> { Sum::new(Zero::zero()) }
    #[inline]
    fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum::new(self.repr + other.repr) }
}

impl<T> Wrap<T> for Sum<T> {
    #[inline]
    fn wrap(val: T) -> Sum<T> { Sum::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Sum { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: Zero + Add<T, T>> WrapMonoid<T> for Sum<T> {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Prod<T> { repr: T }

impl<T> Prod<T> {
    #[inline]
    pub fn new(val: T) -> Prod<T> { Prod { repr: val }}
}

impl<T: One + Mul<T, T>> Monoid for Prod<T> {
    #[inline]
    fn mempty() -> Prod<T> { Prod::new(One::one()) }
    #[inline]
    fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod::new(self.repr * other.repr) }
}

impl<T> Wrap<T> for Prod<T> {
    #[inline]
    fn wrap(val: T) -> Prod<T> { Prod::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Prod { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: One + Mul<T, T>> WrapMonoid<T> for Prod<T> {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Max<T> { repr: T }

impl<T> Max<T> {
    #[inline]
    pub fn new(val: T) -> Max<T> { Max { repr: val } }
}

impl<T: Clone + Bounded + Ord> Monoid for Max<T> {
    #[inline]
    fn mempty() -> Max<T> { Max::new(Bounded::min_value()) }
    #[inline]
    fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr > other.repr { self.clone() } else { other.clone() }
    }
}

impl<T> Wrap<T> for Max<T> {
    #[inline]
    fn wrap(val: T) -> Max<T> { Max::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Max { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: Clone + Bounded + Ord> WrapMonoid<T> for Max<T> {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Min<T> { repr: T }

impl<T> Min<T> {
    #[inline]
    pub fn new(val: T) -> Min<T> { Min { repr: val } }
}

impl<T: Clone + Bounded + Ord> Monoid for Min<T> {
    #[inline]
    fn mempty() -> Min<T> { Min::new(Bounded::max_value()) }
    #[inline]
    fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr < other.repr { self.clone() } else { other.clone() }
    }
}

impl<T> Wrap<T> for Min<T> {
    #[inline]
    fn wrap(val: T) -> Min<T> { Min::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Min { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: Clone + Bounded + Ord> WrapMonoid<T> for Min<T> {}

#[inline]
pub fn mconcat<T: Monoid>(v: &[T]) -> T {
    v.iter().fold(Monoid::mempty(), |accum: T, elem| { accum.mappend(elem) })
}

pub struct MergeMonoidIterator<V, T, U> {
    iter1: T,
    value1: Option<V>,
    iter2: U,
    value2: Option<V>
}

impl<V, T: Iterator<V>, U: Iterator<V>> MergeMonoidIterator<V, T, U> {
    #[inline]
    pub fn new(iter1: T, iter2: U) -> MergeMonoidIterator<V, T, U> {
        MergeMonoidIterator { iter1: iter1, value1: None, iter2: iter2, value2: None }
    }
}

impl<K: TotalOrd, V: Monoid, T: Iterator<(K, V)>, U: Iterator<(K, V)>>
    Iterator<(K, V)> for MergeMonoidIterator<(K, V), T, U> {
    fn next(&mut self) -> Option<(K, V)> {
        fn return_val<V>(opt: &mut Option<V>) -> Option<V> {
            let mut result = None;
            mem::swap(opt, &mut result);
            return result;
        }

        // Fill value if empty (if iter ends, set None)
        if self.value1.is_none() { self.value1 = self.iter1.next(); }
        if self.value2.is_none() { self.value2 = self.iter2.next(); }

        // If one value is None, returns anogher value (with setting None)
        if self.value1.is_none() { return return_val(&mut self.value2); }
        if self.value2.is_none() { return return_val(&mut self.value1); }

        // Returns smaller value
        let cmp = self.value1.get_ref().ref0().cmp(self.value2.get_ref().ref0());
        match cmp {
            Less    => { return return_val(&mut self.value1); }
            Greater => { return return_val(&mut self.value2); },
            Equal   => {
                let mut r1 = None;
                let mut r2 = None;
                mem::swap(&mut self.value1, &mut r1);
                mem::swap(&mut self.value2, &mut r2);
                let ((k, v1), (_, v2)) = (r1.unwrap(), r2.unwrap());
                return Some((k, v1.mappend(&v2)));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Monoid, Wrap, Sum, Prod, Max, Min,
                MergeMonoidIterator};
    use std::fmt::Show;

    #[test]
    fn test_mconcat() {
        fn check_wrap<T: TotalEq + Clone + Show, M: Monoid + Wrap<T>>(v: &[T], f: |T| -> M, result: T) {
            let ms = v.to_owned().move_iter().map(f).collect::<Vec<M>>();
            assert_eq!(super::mconcat(ms.as_slice()).unwrap(), result);
        }

        let v1 = [1, 2, 3, 4];
        let v2 = [0, 1, 2, 3, 4];
        let v3 = [0, 0, 0, 0];
        let v4 = [];

        check_wrap(v1, Sum::new, 10);
        check_wrap(v2, Sum::new, 10);
        check_wrap(v3, Sum::new, 0);
        check_wrap(v4, Sum::new, 0);

        check_wrap(v1, Prod::new, 24);
        check_wrap(v2, Prod::new, 0);
        check_wrap(v3, Prod::new, 0);
        check_wrap(v4, Prod::new, 1);

        check_wrap(v1, Max::new, 4);
        check_wrap(v2, Max::new, 4);
        check_wrap(v3, Max::new, 0);

        check_wrap(v1, Min::new, 1);
        check_wrap(v2, Min::new, 0);
        check_wrap(v3, Min::new, 0);

        assert_eq!(super::mconcat([vec![], vec![1, 2, 3], vec![4], vec![5]]), vec![1, 2, 3, 4, 5]);
        assert_eq!(super::mconcat(["".to_string(), "abc".to_string(), "d".to_string(), "e".to_string()]),
                   "abcde".to_string());
    }

    #[test]
    fn test_merge_monoid_iterator() {
        fn check<M: Monoid + Wrap<int> + TotalEq + Show>(v1: &[(int, int)],
                                                    v2: &[(int, int)],
                                                    f: fn(int) -> M,
                                                    result: &[(int, int)]) {
            let merged = MergeMonoidIterator::new(
                v1.iter().map(|&(x, y)| (x, f(y))),
                v2.iter().map(|&(x, y)| (x, f(y)))
            ).collect::<Vec<(int, M)>>();
            assert_eq!(merged, result.iter().map(|&(x, y)| (x, f(y))).collect());

            let merged = MergeMonoidIterator::new(
                v2.iter().map(|&(x, y)| (x, f(y))),
                v1.iter().map(|&(x, y)| (x, f(y)))
            ).collect::<Vec<(int, M)>>();
            assert_eq!(merged, result.iter().map(|&(x, y)| (x, f(y))).collect());
        }

        let v1 = [(1, 1), (3, 1), (4, 3), (6, 1)];
        let v2 = [(1, 2), (2, 1), (4, 2), (7, 2)];

        check(v1, v2, Sum::new, [(1, 3), (2, 1), (3, 1), (4, 5), (6, 1), (7, 2)]);
        check(v1, v2, Prod::new, [(1, 2), (2, 1), (3, 1), (4, 6), (6, 1), (7, 2)]);
        check(v1, v2, Max::new, [(1, 2), (2, 1), (3, 1), (4, 3), (6, 1), (7, 2)]);
        check(v1, v2, Min::new, [(1, 1), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)]);

        check(v1, [], Sum::new, v1);
        check([], [], Sum::new, []);
        check(v1, [], Prod::new, v1);
        check([], [], Prod::new, []);
        check(v1, [], Max::new, v1);
        check([], [], Max::new, []);
        check(v1, [], Min::new, v1);
        check([], [], Min::new, []);
    }
}
<commit_msg>remove MergeMonoidIterator<commit_after>use std::cmp::{Ord, Eq};
use std::ops::{Add, Mul};
use std::num::{Zero, One, Bounded};

pub trait Monoid {
    fn mempty() -> Self;
    fn mappend(&self, other: &Self) -> Self;
}

impl<T: Clone> Monoid for Vec<T> {
    #[inline]
    fn mempty() -> Vec<T> { Vec::new() }
    #[inline]
    fn mappend(&self, other: &Vec<T>) -> Vec<T> { self + *other }
}

impl Monoid for String {
    #[inline]
    fn mempty() -> String { "".to_string() }
    #[inline]
    fn mappend(&self, other: &String) -> String { format!("{}{}", self, other) }
}

pub trait Wrap<T> {
    fn wrap(T) -> Self;
    fn unwrap(self) -> T;
    fn unwrap_ref<'a>(&'a self) -> &'a T;
}

pub trait WrapMonoid<T>: Wrap<T> + Monoid {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Sum<T> { repr: T }

impl<T> Sum<T> {
    #[inline]
    pub fn new(val: T) -> Sum<T> { Sum { repr: val }}
}

impl<T: Zero + Add<T, T>> Monoid for Sum<T> {
    #[inline]
    fn mempty() -> Sum<T> { Sum::new(Zero::zero()) }
    #[inline]
    fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum::new(self.repr + other.repr) }
}

impl<T> Wrap<T> for Sum<T> {
    #[inline]
    fn wrap(val: T) -> Sum<T> { Sum::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Sum { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: Zero + Add<T, T>> WrapMonoid<T> for Sum<T> {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Prod<T> { repr: T }

impl<T> Prod<T> {
    #[inline]
    pub fn new(val: T) -> Prod<T> { Prod { repr: val }}
}

impl<T: One + Mul<T, T>> Monoid for Prod<T> {
    #[inline]
    fn mempty() -> Prod<T> { Prod::new(One::one()) }
    #[inline]
    fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod::new(self.repr * other.repr) }
}

impl<T> Wrap<T> for Prod<T> {
    #[inline]
    fn wrap(val: T) -> Prod<T> { Prod::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Prod { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: One + Mul<T, T>> WrapMonoid<T> for Prod<T> {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Max<T> { repr: T }

impl<T> Max<T> {
    #[inline]
    pub fn new(val: T) -> Max<T> { Max { repr: val } }
}

impl<T: Clone + Bounded + Ord> Monoid for Max<T> {
    #[inline]
    fn mempty() -> Max<T> { Max::new(Bounded::min_value()) }
    #[inline]
    fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr > other.repr { self.clone() } else { other.clone() }
    }
}

impl<T> Wrap<T> for Max<T> {
    #[inline]
    fn wrap(val: T) -> Max<T> { Max::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Max { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: Clone + Bounded + Ord> WrapMonoid<T> for Max<T> {}

#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Min<T> { repr: T }

impl<T> Min<T> {
    #[inline]
    pub fn new(val: T) -> Min<T> { Min { repr: val } }
}

impl<T: Clone + Bounded + Ord> Monoid for Min<T> {
    #[inline]
    fn mempty() -> Min<T> { Min::new(Bounded::max_value()) }
    #[inline]
    fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr < other.repr { self.clone() } else { other.clone() }
    }
}

impl<T> Wrap<T> for Min<T> {
    #[inline]
    fn wrap(val: T) -> Min<T> { Min::new(val) }
    #[inline]
    fn unwrap(self) -> T { match self { Min { repr: repr } => repr } }
    #[inline]
    fn unwrap_ref<'a>(&'a self) -> &'a T { &self.repr}
}

impl<T: Clone + Bounded + Ord> WrapMonoid<T> for Min<T> {}

#[inline]
pub fn mconcat<T: Monoid>(v: &[T]) -> T {
    v.iter().fold(Monoid::mempty(), |accum: T, elem| { accum.mappend(elem) })
}

#[cfg(test)]
mod tests {
    use super::{Monoid, Wrap, Sum, Prod, Max, Min};
    use std::fmt::Show;

    #[test]
    fn test_mconcat() {
        fn check_wrap<T: TotalEq + Clone + Show, M: Monoid + Wrap<T>>(v: &[T], f: |T| -> M, result: T) {
            let ms = v.to_owned().move_iter().map(f).collect::<Vec<M>>();
            assert_eq!(super::mconcat(ms.as_slice()).unwrap(), result);
        }

        let v1 = [1, 2, 3, 4];
        let v2 = [0, 1, 2, 3, 4];
        let v3 = [0, 0, 0, 0];
        let v4 = [];

        check_wrap(v1, Sum::new, 10);
        check_wrap(v2, Sum::new, 10);
        check_wrap(v3, Sum::new, 0);
        check_wrap(v4, Sum::new, 0);

        check_wrap(v1, Prod::new, 24);
        check_wrap(v2, Prod::new, 0);
        check_wrap(v3, Prod::new, 0);
        check_wrap(v4, Prod::new, 1);

        check_wrap(v1, Max::new, 4);
        check_wrap(v2, Max::new, 4);
        check_wrap(v3, Max::new, 0);

        check_wrap(v1, Min::new, 1);
        check_wrap(v2, Min::new, 0);
        check_wrap(v3, Min::new, 0);

        assert_eq!(super::mconcat([vec![], vec![1, 2, 3], vec![4], vec![5]]), vec![1, 2, 3, 4, 5]);
        assert_eq!(super::mconcat(["".to_string(), "abc".to_string(), "d".to_string(), "e".to_string()]),
                   "abcde".to_string());
    }
}
<|endoftext|>