<commit_before>extern crate regex;
#[macro_use]
extern crate lazy_static;
extern crate itertools;

use regex::Regex;
use itertools::Itertools;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::prelude::*;

lazy_static! {
    static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"(?x)
        declare_clippy_lint!\s*[\{(]\s*
        pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
        (?P<cat>[a-z_]+)\s*,\s*
        "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
    "#).unwrap();
    static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"(?x)
        declare_deprecated_lint!\s*[{(]\s*
        pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
        "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
    "#).unwrap();
    static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap();
    pub static ref DOCS_LINK: String = "https://rust-lang-nursery.github.io/rust-clippy/master/index.html".to_string();
}

#[derive(Clone, PartialEq, Debug)]
pub struct Lint {
    pub name: String,
    pub group: String,
    pub desc: String,
    pub deprecation: Option<String>,
    pub module: String,
}

impl Lint {
    pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Lint {
        Lint {
            name: name.to_lowercase(),
            group: group.to_string(),
            desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(),
            deprecation: deprecation.map(|d| d.to_string()),
            module: module.to_string(),
        }
    }

    /// Returns all non-deprecated lints
    pub fn active_lints(lints: &[Lint]) -> impl Iterator<Item=&Lint> {
        lints.iter().filter(|l| l.deprecation.is_none())
    }

    /// Returns the lints in a HashMap, grouped by the different lint groups
    pub fn by_lint_group(lints: &[Lint]) -> HashMap<String, Vec<Lint>> {
        lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map()
    }
}

pub fn gather_all() -> impl Iterator<Item=Lint> {
    let mut lints = vec![];
    for dir_entry in lint_files() {
        lints.append(&mut gather_from_file(&dir_entry).collect());
    }
    lints.into_iter()
}

fn gather_from_file(dir_entry: &fs::DirEntry) -> impl Iterator<Item=Lint> {
    let mut file = fs::File::open(dir_entry.path()).unwrap();
    let mut content = String::new();
    file.read_to_string(&mut content).unwrap();
    parse_contents(&content, dir_entry.path().file_stem().unwrap().to_str().unwrap())
}

fn parse_contents(content: &str, filename: &str) -> impl Iterator<Item=Lint> {
    let mut lints: Vec<Lint> = DEC_CLIPPY_LINT_RE
        .captures_iter(&content)
        .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename))
        .collect();
    let mut deprecated = DEC_DEPRECATED_LINT_RE
        .captures_iter(&content)
        .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename))
        .collect();
    lints.append(&mut deprecated);
    lints.into_iter()
}

/// Collects all .rs files in the `clippy_lints/src` directory
fn lint_files() -> impl Iterator<Item=fs::DirEntry> {
    let paths = fs::read_dir("../clippy_lints/src").unwrap();
    paths
        .filter_map(|f| f.ok())
        .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
}

#[test]
fn test_parse_contents() {
    let result: Vec<Lint> = parse_contents(
        r#"
declare_clippy_lint! {
    pub PTR_ARG,
    style,
    "really long \
     text"
}

declare_clippy_lint!{
    pub DOC_MARKDOWN,
    pedantic,
    "single line"
}

/// some doc comment
declare_deprecated_lint! {
    pub SHOULD_ASSERT_EQ,
    "`assert!()` will be more flexible with RFC 2011"
}
    "#,
    "module_name").collect();

    let expected = vec![
        Lint::new("ptr_arg", "style", "really long text", None, "module_name"),
        Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"),
        Lint::new(
            "should_assert_eq",
            "Deprecated",
            "`assert!()` will be more flexible with RFC 2011",
            Some("`assert!()` will be more flexible with RFC 2011"),
            "module_name"
        ),
    ];
    assert_eq!(expected, result);
}

#[test]
fn test_active_lints() {
    let lints = vec![
        Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"),
        Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name")
    ];
    let expected = vec![
        Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name")
    ];
    assert_eq!(expected, Lint::active_lints(&lints).cloned().collect::<Vec<Lint>>());
}

#[test]
fn test_by_lint_group() {
    let lints = vec![
        Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
        Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
        Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
    ];
    let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
    expected.insert("group1".to_string(), vec![
        Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
        Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
    ]);
    expected.insert("group2".to_string(), vec![
        Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")
    ]);
    assert_eq!(expected, Lint::by_lint_group(&lints));
}
<commit_msg>More refactoring<commit_after>extern crate regex;
#[macro_use]
extern crate lazy_static;
extern crate itertools;

use regex::Regex;
use itertools::Itertools;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::prelude::*;

lazy_static! {
    static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"(?x)
        declare_clippy_lint!\s*[\{(]\s*
        pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
        (?P<cat>[a-z_]+)\s*,\s*
        "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
    "#).unwrap();
    static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"(?x)
        declare_deprecated_lint!\s*[{(]\s*
        pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
        "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
    "#).unwrap();
    static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap();
    pub static ref DOCS_LINK: String = "https://rust-lang-nursery.github.io/rust-clippy/master/index.html".to_string();
}

#[derive(Clone, PartialEq, Debug)]
pub struct Lint {
    pub name: String,
    pub group: String,
    pub desc: String,
    pub deprecation: Option<String>,
    pub module: String,
}

impl Lint {
    pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Lint {
        Lint {
            name: name.to_lowercase(),
            group: group.to_string(),
            desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(),
            deprecation: deprecation.map(|d| d.to_string()),
            module: module.to_string(),
        }
    }

    /// Returns all non-deprecated lints
    pub fn active_lints(lints: &[Lint]) -> impl Iterator<Item=&Lint> {
        lints.iter().filter(|l| l.deprecation.is_none())
    }

    /// Returns the lints in a HashMap, grouped by the different lint groups
    pub fn by_lint_group(lints: &[Lint]) -> HashMap<String, Vec<Lint>> {
        lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map()
    }
}

pub fn gather_all() -> impl Iterator<Item=Lint> {
    lint_files().flat_map(gather_from_file)
}

fn gather_from_file(dir_entry: fs::DirEntry) -> impl Iterator<Item=Lint> {
    let mut file = fs::File::open(dir_entry.path()).unwrap();
    let mut content = String::new();
    file.read_to_string(&mut content).unwrap();
    parse_contents(&content, dir_entry.path().file_stem().unwrap().to_str().unwrap())
}

fn parse_contents(content: &str, filename: &str) -> impl Iterator<Item=Lint> {
    let lints = DEC_CLIPPY_LINT_RE
        .captures_iter(content)
        .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename));
    let deprecated = DEC_DEPRECATED_LINT_RE
        .captures_iter(content)
        .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename));
    // Removing the `.collect::<Vec<Lint>>().into_iter()` causes some lifetime issues due to the map
    lints.chain(deprecated).collect::<Vec<Lint>>().into_iter()
}

/// Collects all .rs files in the `clippy_lints/src` directory
fn lint_files() -> impl Iterator<Item=fs::DirEntry> {
    fs::read_dir("../clippy_lints/src")
        .unwrap()
        .filter_map(|f| f.ok())
        .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
}

#[test]
fn test_parse_contents() {
    let result: Vec<Lint> = parse_contents(
        r#"
declare_clippy_lint! {
    pub PTR_ARG,
    style,
    "really long \
     text"
}

declare_clippy_lint!{
    pub DOC_MARKDOWN,
    pedantic,
    "single line"
}

/// some doc comment
declare_deprecated_lint! {
    pub SHOULD_ASSERT_EQ,
    "`assert!()` will be more flexible with RFC 2011"
}
    "#,
    "module_name").collect();

    let expected = vec![
        Lint::new("ptr_arg", "style", "really long text", None, "module_name"),
        Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"),
        Lint::new(
            "should_assert_eq",
            "Deprecated",
            "`assert!()` will be more flexible with RFC 2011",
            Some("`assert!()` will be more flexible with RFC 2011"),
            "module_name"
        ),
    ];
    assert_eq!(expected, result);
}

#[test]
fn test_active_lints() {
    let lints = vec![
        Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"),
        Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name")
    ];
    let expected = vec![
        Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name")
    ];
    assert_eq!(expected, Lint::active_lints(&lints).cloned().collect::<Vec<Lint>>());
}

#[test]
fn test_by_lint_group() {
    let lints = vec![
        Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
        Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
        Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
    ];
    let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
    expected.insert("group1".to_string(), vec![
        Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
        Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
    ]);
    expected.insert("group2".to_string(), vec![
        Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")
    ]);
    assert_eq!(expected, Lint::by_lint_group(&lints));
}
<|endoftext|>


<commit_before>extern mod r5;

use r5::runtime::{Runtime};
use r5::parser::Parser;

fn prompt() {
    print("repl > ")
}

fn main() {
    let mut runtime = Runtime::new_std();

    prompt();
    for io::stdin().each_line |line| {
        do io::with_str_reader(line) |rdr| {
            let mut parser = Parser(rdr);
            match parser.parse() {
                Ok(datum) => {
                    match runtime.eval(@datum) {
                        Ok(result) => {
                            result.write(io::stdout());
                            print("\n");
                        },
                        Err(e) => println(fmt!("Error: %s", e.to_str())),
                    }
                }
                Err(e) => {
                    let (line, col) = parser.pos();
                    println(fmt!("Parse Error: %u:%u:%s", line, col, e))
                },
            }
        }
        prompt();
    }
    println("^D");
}
<commit_msg>update repl to rust 0.7<commit_after>extern mod r5;

use std::io;
use r5::runtime::{Runtime};
use r5::parser::Parser;

fn prompt() {
    print("repl > ")
}

fn main() {
    let mut runtime = Runtime::new_std();

    prompt();
    for io::stdin().each_line |line| {
        do io::with_str_reader(line) |rdr| {
            let mut parser = Parser(rdr);
            match parser.parse() {
                Ok(datum) => {
                    match runtime.eval(@datum) {
                        Ok(result) => {
                            result.write(io::stdout());
                            print("\n");
                        },
                        Err(e) => println(fmt!("Error: %s", e.to_str())),
                    }
                }
                Err(e) => {
                    let (line, col) = parser.pos();
                    println(fmt!("Parse Error: %u:%u:%s", line, col, e))
                },
            }
        }
        prompt();
    }
    println("^D");
}
<|endoftext|>


<commit_before>#![crate_name = "docopt_macros"]
#![crate_type = "dylib"]

#![feature(plugin_registrar, quote, rustc_private)]

//! This crate defines the `docopt!` macro. It is documented in the
//! documentation of the `docopt` crate.

extern crate syntax;
extern crate rustc;
extern crate docopt;

use std::borrow::Borrow;
use std::collections::HashMap;

use rustc::plugin::Registry;
use syntax::{ast, codemap};
use syntax::diagnostic::FatalError;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::common::SeqSep;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;

use docopt::{Docopt, ArgvMap};
use docopt::parse::{Options, Atom, Positional, Zero, One};

type PResult<T> = Result<T, FatalError>;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("docopt", expand);
}

fn expand(cx: &mut ExtCtxt, span: codemap::Span, tts: &[ast::TokenTree])
         -> Box<MacResult+'static> {
    let parsed = match MacParser::new(cx, tts).parse() {
        Ok(parsed) => parsed,
        Err(_) => return DummyResult::any(span),
    };
    parsed.items(cx)
}

/// Parsed corresponds to the result of parsing a `docopt` macro call.
/// It can be used to write a corresponding struct.
struct Parsed {
    struct_info: StructInfo,
    doc: Docopt,
    /// Overrided type annotations for struct members. May be empty.
    /// When a type annotation for an atom doesn't exist, then one is
    /// inferred automatically. It is one of: `bool`, `usize`, `String` or
    /// `Vec<String>`.
    types: HashMap<Atom, P<ast::Ty>>,
}

impl Parsed {
    /// Returns a macro result suitable for expansion.
    /// Contains two items: one for the struct and one for the struct impls.
    fn items(&self, cx: &ExtCtxt) -> Box<MacResult+'static> {
        let mut its = vec!();
        its.push(self.struct_decl(cx));

        let struct_name = self.struct_info.name;
        let full_doc = &*self.doc.parser().full_doc;
        its.push(quote_item!(cx,
            impl $struct_name {
                #[allow(dead_code)]
                fn docopt() -> docopt::Docopt {
                    // The unwrap is justified here because this code
                    // gen only happens if the Docopt usage string is valid.
                    docopt::Docopt::new($full_doc).unwrap()
                }
            }
        ).unwrap());
        MacEager::items(SmallVector::many(its))
    }

    /// Returns an item for the struct definition.
    fn struct_decl(&self, cx: &ExtCtxt) -> P<ast::Item> {
        let name = self.struct_info.name.clone();
        let vis = if self.struct_info.public { ast::Public }
                  else { ast::Inherited };
        let def = ast::VariantData::Struct(
            self.struct_fields(cx), ast::DUMMY_NODE_ID);

        let mut traits = vec!["RustcDecodable".to_string()];
        traits.extend(self.struct_info.deriving.iter().cloned());
        let attrs = vec![attribute(cx, "allow", vec!["non_snake_case"]),
                         attribute(cx, "derive", traits)];

        let st = cx.item_struct(codemap::DUMMY_SP, name.clone(), def);
        cx.item(codemap::DUMMY_SP, name, attrs, st.node.clone()).map(|mut it| {
            it.vis = vis;
            it
        })
    }

    /// Returns a list of fields for the struct definition.
    /// Handles type annotations.
    fn struct_fields(&self, cx: &ExtCtxt) -> Vec<ast::StructField> {
        let mut fields: Vec<ast::StructField> = vec!();
        for (atom, opts) in self.doc.parser().descs.iter() {
            let name = ArgvMap::key_to_struct_field(&*atom.to_string());
            let ty = match self.types.get(atom) {
                None => self.pat_type(cx, atom, opts),
                Some(ty) => ty.clone(),
            };
            fields.push(self.mk_struct_field(&*name, ty));
        }
        fields
    }

    /// Returns an inferred type for a usage pattern.
    /// This is only invoked when a type annotation is not present.
    fn pat_type(&self, cx: &ExtCtxt, atom: &Atom, opts: &Options) -> P<ast::Ty> {
        let sp = codemap::DUMMY_SP;
        match (opts.repeats, &opts.arg) {
            (false, &Zero) => {
                match atom {
                    &Positional(_) => cx.ty_ident(sp, ident("String")),
                    _ => cx.ty_ident(sp, ident("bool")),
                }
            }
            (true, &Zero) => {
                match atom {
                    &Positional(_) => ty_vec_string(cx),
                    _ => cx.ty_ident(sp, ident("usize")),
                }
            }
            (false, &One(_)) => cx.ty_ident(sp, ident("String")),
            (true, &One(_)) => ty_vec_string(cx),
        }
    }

    /// Creates a struct field from a member name and type.
    fn mk_struct_field(&self, name: &str, ty: P<ast::Ty>) -> ast::StructField {
        codemap::dummy_spanned(ast::StructField_ {
            kind: ast::NamedField(ident(name), ast::Public),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: vec!(),
        })
    }
}

/// State for parsing a `docopt` macro invocation.
struct MacParser<'a, 'b:'a> {
    cx: &'a mut ExtCtxt<'b>,
    p: Parser<'b>,
}

impl<'a, 'b> MacParser<'a, 'b> {
    fn new(cx: &'a mut ExtCtxt<'b>, tts: &[ast::TokenTree]) -> MacParser<'a, 'b> {
        let p = cx.new_parser_from_tts(tts);
        MacParser { cx: cx, p: p }
    }

    /// Main entry point for parsing arguments to `docopt` macro.
    /// First looks for an identifier for the struct name.
    /// Second, a string containing the docopt usage patterns.
    /// Third, an optional list of type annotations.
    fn parse(&mut self) -> PResult<Parsed> {
        if self.p.token == token::Eof {
            self.cx.span_err(self.cx.call_site(), "macro expects arguments");
            return Err(FatalError);
        }
        let struct_info = try!(self.parse_struct_info());
        let docstr = try!(self.parse_str());

        let sep = SeqSep {
            sep: Some(token::Comma),
            trailing_sep_allowed: true,
        };
        let types = try!(self.p.parse_seq_to_end(
            &token::Eof, sep, |p| MacParser::parse_type_annotation(p)
        )).into_iter()
          .map(|(ident, ty)| {
              let field_name = ident.to_string();
              let key = ArgvMap::struct_field_to_key(&*field_name);
              (Atom::new(&*key), ty)
           })
          .collect::<HashMap<Atom, P<ast::Ty>>>();
        try!(self.p.expect(&token::Eof));

        // This config does not matter because we're only asking for the
        // usage patterns in the Docopt string. The configuration does not
        // affect the retrieval of usage patterns.
        let doc = match Docopt::new(docstr) {
            Ok(doc) => doc,
            Err(err) => {
                self.cx.span_err(self.cx.call_site(),
                                 &*format!("Invalid Docopt usage: {}", err));
                return Err(FatalError);
            }
        };
        Ok(Parsed {
            struct_info: struct_info,
            doc: doc,
            types: types,
        })
    }

    /// Parses a single string literal. On failure, an error is logged and
    /// unit is returned.
    fn parse_str(&mut self) -> PResult<String> {
        fn lit_is_str(lit: &ast::Lit) -> bool {
            match lit.node {
                ast::LitStr(_, _) => true,
                _ => false,
            }
        }
        fn lit_to_string(lit: &ast::Lit) -> String {
            match lit.node {
                ast::LitStr(ref s, _) => s.to_string(),
                _ => panic!("BUG: expected string literal"),
            }
        }
        let exp = self.cx.expander().fold_expr(self.p.parse_expr_panic());
        let s = match exp.node {
            ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
                lit_to_string(&**lit)
            }
            _ => {
                let err = format!("Expected string literal but got {}",
                                  pprust::expr_to_string(&*exp));
                self.cx.span_err(exp.span, &*err);
                return Err(FatalError);
            }
        };
        try!(self.p.bump());
        Ok(s)
    }

    /// Parses a type annotation in a `docopt` invocation of the form
    /// `ident: Ty`.
    /// Note that this is a static method as it is used as a HOF.
    fn parse_type_annotation(p: &mut Parser)
                            -> PResult<(ast::Ident, P<ast::Ty>)> {
        let ident = try!(p.parse_ident());
        try!(p.expect(&token::Colon));
        let ty = p.parse_ty_panic();
        Ok((ident, ty))
    }

    /// Parses struct information, like visibility, name and deriving.
    fn parse_struct_info(&mut self) -> PResult<StructInfo> {
        let public = try!(self.p.eat_keyword(token::keywords::Pub));
        let mut info = StructInfo {
            name: try!(self.p.parse_ident()),
            public: public,
            deriving: vec![],
        };
        if try!(self.p.eat(&token::Comma)) { return Ok(info); }
        let deriving = try!(self.p.parse_ident());
        if deriving.name.as_str() != "derive" {
            let err = format!("Expected 'derive' keyword but got '{}'",
                              deriving);
            self.cx.span_err(self.cx.call_site(), &*err);
            return Err(FatalError);
        }
        while !try!(self.p.eat(&token::Comma)) {
            info.deriving.push(
                try!(self.p.parse_ident()).name.to_string());
        }
        Ok(info)
    }
}

struct StructInfo {
    name: ast::Ident,
    public: bool,
    deriving: Vec<String>,
}

// Convenience functions for building intermediate values.

fn ident(s: &str) -> ast::Ident {
    ast::Ident::with_empty_ctxt(token::intern(s))
}

fn attribute<S, T>(cx: &ExtCtxt, name: S, items: Vec<T>) -> ast::Attribute
            where S: Borrow<str>, T: Borrow<str> {
    let sp = codemap::DUMMY_SP;
    let its = items.into_iter().map(|s| meta_item(cx, s.borrow())).collect();
    let mi = cx.meta_list(sp, intern(name.borrow()), its);
    cx.attribute(sp, mi)
}

fn meta_item(cx: &ExtCtxt, s: &str) -> P<ast::MetaItem> {
    cx.meta_word(codemap::DUMMY_SP, intern(s))
}

fn intern(s: &str) -> token::InternedString {
    token::intern_and_get_ident(s)
}

fn ty_vec_string(cx: &ExtCtxt) -> P<ast::Ty> {
    let sp = codemap::DUMMY_SP;
    let tystr = ast::AngleBracketedParameterData {
        lifetimes: vec![],
        types: OwnedSlice::from_vec(vec![cx.ty_ident(sp, ident("String"))]),
        bindings: OwnedSlice::empty(),
    };
    cx.ty_path(ast::Path {
        span: sp,
        global: false,
        segments: vec![ast::PathSegment {
            identifier: ident("Vec"),
            parameters: ast::PathParameters::AngleBracketedParameters(tystr),
        }]
    })
}
<commit_msg>Fix #148<commit_after>#![crate_name = "docopt_macros"]
#![crate_type = "dylib"]

#![feature(plugin_registrar, quote, rustc_private)]

//! This crate defines the `docopt!` macro. It is documented in the
//! documentation of the `docopt` crate.

extern crate syntax;
extern crate rustc;
extern crate docopt;

use std::borrow::Borrow;
use std::collections::HashMap;

use rustc::plugin::Registry;
use syntax::{ast, codemap};
use syntax::diagnostic::FatalError;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::common::SeqSep;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;

use docopt::{Docopt, ArgvMap};
use docopt::parse::{Options, Atom, Positional, Zero, One};

type PResult<T> = Result<T, FatalError>;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("docopt", expand);
}

fn expand(cx: &mut ExtCtxt, span: codemap::Span, tts: &[ast::TokenTree])
         -> Box<MacResult+'static> {
    let parsed = match MacParser::new(cx, tts).parse() {
        Ok(parsed) => parsed,
        Err(_) => return DummyResult::any(span),
    };
    parsed.items(cx)
}

/// Parsed corresponds to the result of parsing a `docopt` macro call.
/// It can be used to write a corresponding struct.
struct Parsed {
    struct_info: StructInfo,
    doc: Docopt,
    /// Overrided type annotations for struct members. May be empty.
    /// When a type annotation for an atom doesn't exist, then one is
    /// inferred automatically. It is one of: `bool`, `usize`, `String` or
    /// `Vec<String>`.
    types: HashMap<Atom, P<ast::Ty>>,
}

impl Parsed {
    /// Returns a macro result suitable for expansion.
    /// Contains two items: one for the struct and one for the struct impls.
    fn items(&self, cx: &ExtCtxt) -> Box<MacResult+'static> {
        let mut its = vec!();
        its.push(self.struct_decl(cx));

        let struct_name = self.struct_info.name;
        let full_doc = &*self.doc.parser().full_doc;
        its.push(quote_item!(cx,
            impl $struct_name {
                #[allow(dead_code)]
                fn docopt() -> docopt::Docopt {
                    // The unwrap is justified here because this code
                    // gen only happens if the Docopt usage string is valid.
                    docopt::Docopt::new($full_doc).unwrap()
                }
            }
        ).unwrap());
        MacEager::items(SmallVector::many(its))
    }

    /// Returns an item for the struct definition.
    fn struct_decl(&self, cx: &ExtCtxt) -> P<ast::Item> {
        let name = self.struct_info.name.clone();
        let vis = if self.struct_info.public { ast::Public }
                  else { ast::Inherited };
        let def = ast::VariantData::Struct(
            self.struct_fields(cx), ast::DUMMY_NODE_ID);

        let mut traits = vec!["RustcDecodable".to_string()];
        traits.extend(self.struct_info.deriving.iter().cloned());
        let attrs = vec![attribute(cx, "allow", vec!["non_snake_case"]),
                         attribute(cx, "derive", traits)];

        let st = cx.item_struct(codemap::DUMMY_SP, name.clone(), def);
        cx.item(codemap::DUMMY_SP, name, attrs, st.node.clone()).map(|mut it| {
            it.vis = vis;
            it
        })
    }

    /// Returns a list of fields for the struct definition.
    /// Handles type annotations.
    fn struct_fields(&self, cx: &ExtCtxt) -> Vec<ast::StructField> {
        let mut fields: Vec<ast::StructField> = vec!();
        for (atom, opts) in self.doc.parser().descs.iter() {
            let name = ArgvMap::key_to_struct_field(&*atom.to_string());
            let ty = match self.types.get(atom) {
                None => self.pat_type(cx, atom, opts),
                Some(ty) => ty.clone(),
            };
            fields.push(self.mk_struct_field(&*name, ty));
        }
        fields
    }

    /// Returns an inferred type for a usage pattern.
    /// This is only invoked when a type annotation is not present.
    fn pat_type(&self, cx: &ExtCtxt, atom: &Atom, opts: &Options) -> P<ast::Ty> {
        let sp = codemap::DUMMY_SP;
        match (opts.repeats, &opts.arg) {
            (false, &Zero) => {
                match atom {
                    &Positional(_) => cx.ty_ident(sp, ident("String")),
                    _ => cx.ty_ident(sp, ident("bool")),
                }
            }
            (true, &Zero) => {
                match atom {
                    &Positional(_) => ty_vec_string(cx),
                    _ => cx.ty_ident(sp, ident("usize")),
                }
            }
            (false, &One(_)) => cx.ty_ident(sp, ident("String")),
            (true, &One(_)) => ty_vec_string(cx),
        }
    }

    /// Creates a struct field from a member name and type.
    fn mk_struct_field(&self, name: &str, ty: P<ast::Ty>) -> ast::StructField {
        codemap::dummy_spanned(ast::StructField_ {
            kind: ast::NamedField(ident(name), ast::Public),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: vec!(),
        })
    }
}

/// State for parsing a `docopt` macro invocation.
struct MacParser<'a, 'b:'a> {
    cx: &'a mut ExtCtxt<'b>,
    p: Parser<'b>,
}

impl<'a, 'b> MacParser<'a, 'b> {
    fn new(cx: &'a mut ExtCtxt<'b>, tts: &[ast::TokenTree]) -> MacParser<'a, 'b> {
        let p = cx.new_parser_from_tts(tts);
        MacParser { cx: cx, p: p }
    }

    /// Main entry point for parsing arguments to `docopt` macro.
    /// First looks for an identifier for the struct name.
    /// Second, a string containing the docopt usage patterns.
    /// Third, an optional list of type annotations.
    fn parse(&mut self) -> PResult<Parsed> {
        if self.p.token == token::Eof {
            self.cx.span_err(self.cx.call_site(), "macro expects arguments");
            return Err(FatalError);
        }
        let struct_info = try!(self.parse_struct_info());
        let docstr = try!(self.parse_str());

        let sep = SeqSep {
            sep: Some(token::Comma),
            trailing_sep_allowed: true,
        };
        let types = try!(self.p.parse_seq_to_end(
            &token::Eof, sep, |p| MacParser::parse_type_annotation(p)
        )).into_iter()
          .map(|(ident, ty)| {
              let field_name = ident.to_string();
              let key = ArgvMap::struct_field_to_key(&*field_name);
              (Atom::new(&*key), ty)
           })
          .collect::<HashMap<Atom, P<ast::Ty>>>();
        try!(self.p.expect(&token::Eof));

        // This config does not matter because we're only asking for the
        // usage patterns in the Docopt string. The configuration does not
        // affect the retrieval of usage patterns.
        let doc = match Docopt::new(docstr) {
            Ok(doc) => doc,
            Err(err) => {
                self.cx.span_err(self.cx.call_site(),
                                 &*format!("Invalid Docopt usage: {}", err));
                return Err(FatalError);
            }
        };
        Ok(Parsed {
            struct_info: struct_info,
            doc: doc,
            types: types,
        })
    }

    /// Parses a single string literal. On failure, an error is logged and
    /// unit is returned.
    fn parse_str(&mut self) -> PResult<String> {
        fn lit_is_str(lit: &ast::Lit) -> bool {
            match lit.node {
                ast::LitStr(_, _) => true,
                _ => false,
            }
        }
        fn lit_to_string(lit: &ast::Lit) -> String {
            match lit.node {
                ast::LitStr(ref s, _) => s.to_string(),
                _ => panic!("BUG: expected string literal"),
            }
        }
        let exp = self.cx.expander().fold_expr(self.p.parse_expr().unwrap());
        let s = match exp.node {
            ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
                lit_to_string(&**lit)
            }
            _ => {
                let err = format!("Expected string literal but got {}",
                                  pprust::expr_to_string(&*exp));
                self.cx.span_err(exp.span, &*err);
                return Err(FatalError);
            }
        };
        try!(self.p.bump());
        Ok(s)
    }

    /// Parses a type annotation in a `docopt` invocation of the form
    /// `ident: Ty`.
    /// Note that this is a static method as it is used as a HOF.
    fn parse_type_annotation(p: &mut Parser)
                            -> PResult<(ast::Ident, P<ast::Ty>)> {
        let ident = try!(p.parse_ident());
        try!(p.expect(&token::Colon));
        let ty = p.parse_ty().unwrap();
        Ok((ident, ty))
    }

    /// Parses struct information, like visibility, name and deriving.
    fn parse_struct_info(&mut self) -> PResult<StructInfo> {
        let public = try!(self.p.eat_keyword(token::keywords::Pub));
        let mut info = StructInfo {
            name: try!(self.p.parse_ident()),
            public: public,
            deriving: vec![],
        };
        if try!(self.p.eat(&token::Comma)) { return Ok(info); }
        let deriving = try!(self.p.parse_ident());
        if deriving.name.as_str() != "derive" {
            let err = format!("Expected 'derive' keyword but got '{}'",
                              deriving);
            self.cx.span_err(self.cx.call_site(), &*err);
            return Err(FatalError);
        }
        while !try!(self.p.eat(&token::Comma)) {
            info.deriving.push(
                try!(self.p.parse_ident()).name.to_string());
        }
        Ok(info)
    }
}

struct StructInfo {
    name: ast::Ident,
    public: bool,
    deriving: Vec<String>,
}

// Convenience functions for building intermediate values.

fn ident(s: &str) -> ast::Ident {
    ast::Ident::with_empty_ctxt(token::intern(s))
}

fn attribute<S, T>(cx: &ExtCtxt, name: S, items: Vec<T>) -> ast::Attribute
            where S: Borrow<str>, T: Borrow<str> {
    let sp = codemap::DUMMY_SP;
    let its = items.into_iter().map(|s| meta_item(cx, s.borrow())).collect();
    let mi = cx.meta_list(sp, intern(name.borrow()), its);
    cx.attribute(sp, mi)
}

fn meta_item(cx: &ExtCtxt, s: &str) -> P<ast::MetaItem> {
    cx.meta_word(codemap::DUMMY_SP, intern(s))
}

fn intern(s: &str) -> token::InternedString {
    token::intern_and_get_ident(s)
}

fn ty_vec_string(cx: &ExtCtxt) -> P<ast::Ty> {
    let sp = codemap::DUMMY_SP;
    let tystr = ast::AngleBracketedParameterData {
        lifetimes: vec![],
        types: OwnedSlice::from_vec(vec![cx.ty_ident(sp, ident("String"))]),
        bindings: OwnedSlice::empty(),
    };
    cx.ty_path(ast::Path {
        span: sp,
        global: false,
        segments: vec![ast::PathSegment {
            identifier: ident("Vec"),
            parameters: ast::PathParameters::AngleBracketedParameters(tystr),
        }]
    })
}
<|endoftext|>


<commit_before>//! All the individual event types that can be sent out by the
//! Supervisor.
//!
//! A key aspect of the current design is that all events are
//! collections of *references*, rather than owned types. This means
//! less unnecessary allocations and copying in order to create
//! events.

use super::EventCore;
use crate::manager::service::{HealthCheckResult as DomainHealthCheckResult,
                              Service,
                              UpdateStrategy as DomainUpdateStrategy};
use prost::{Enumeration,
            Message};

include!(concat!(env!("OUT_DIR"), "/chef.habitat.supervisor.event.rs"));

// Note: `UpdateStrategy` here is the protobuf-generated type for the
// event we're sending out; `DomainUpdateStrategy` is the one we use
// elsewhere in the Supervisor.
impl Into<UpdateStrategy> for DomainUpdateStrategy {
    fn into(self) -> UpdateStrategy {
        match self {
            DomainUpdateStrategy::None => UpdateStrategy::None,
            DomainUpdateStrategy::AtOnce => UpdateStrategy::AtOnce,
            DomainUpdateStrategy::Rolling => UpdateStrategy::Rolling,
        }
    }
}

// Note: `HealthCheck` here is the protobuf-generated type for the
// event we're sending out; `DomainHealthCheckResult` is the one we use
// elsewhere in the Supervisor.
impl Into<HealthCheck> for DomainHealthCheckResult {
    fn into(self) -> HealthCheck {
        match self {
            DomainHealthCheckResult::Ok => HealthCheck::Ok,
            DomainHealthCheckResult::Warning => HealthCheck::Warning,
            DomainHealthCheckResult::Critical => HealthCheck::Critical,
            DomainHealthCheckResult::Unknown => HealthCheck::Unknown,
        }
    }
}

impl Service {
    /// Create a protobuf metadata struct for Service-related event
    /// messages.
    // NOTE This was originally `pub(super)`, but it's `pub` for now
    // because it seems better to be able to generate this when we
    // kick off the health checking future for a service, rather than
    // cloning the entire service for eventing.
    pub fn to_service_metadata(&self) -> ServiceMetadata {
        ServiceMetadata { package_ident:   self.pkg.ident.to_string(),
                          spec_ident:      self.spec_ident.to_string(),
                          service_group:   self.service_group.to_string(),
                          update_channel:  self.channel.to_string(),
                          update_strategy: self.update_strategy.into(), }
    }
}

impl EventCore {
    /// Create a protobuf metadata struct for all event messages.
    pub(super) fn to_event_metadata(&self) -> EventMetadata {
        EventMetadata { supervisor_id: self.supervisor_id.clone(),
                        ip_address:    self.ip_address.to_string(),
                        application:   self.application.clone(),
                        environment:   self.environment.clone(),
                        timestamp:     None,
                        meta:          self.meta.clone().into(), }
    }
}

pub trait EventMessage: Message + Sized {
    /// All messages will have some top-level metadata about the
    /// Supervisor they come from. This function allows us to set it
    /// generically when we send the message out.
    fn event_metadata(&mut self, event_metadata: EventMetadata);

    /// Convert a message to bytes for sending to NATS.
    fn to_bytes(&self) -> Vec<u8> {
        let mut buf = bytes::BytesMut::with_capacity(self.encoded_len());
        // The only way this can fail is if the buffer doesn't have
        // enough room. We just set that, though, so something would
        // have to be seriously wrong in Prost for this to fail.
        self.encode(&mut buf)
            .expect("UNEXPECTED PROST ERROR: encoded_len() was not long enough!");
        buf.to_vec()
    }
}

// TODO (CM): these are repetitive, and will only get more so as we
// add events. Consider implementing via macro instead.

impl EventMessage for ServiceStartedEvent {
    fn event_metadata(&mut self, event_metadata: EventMetadata) {
        self.event_metadata = Some(event_metadata);
    }
}

impl EventMessage for ServiceStoppedEvent {
    fn event_metadata(&mut self, event_metadata: EventMetadata) {
        self.event_metadata = Some(event_metadata);
    }
}

impl EventMessage for HealthCheckEvent {
    fn event_metadata(&mut self, event_metadata: EventMetadata) {
        self.event_metadata = Some(event_metadata);
    }
}
<commit_msg>Remove old comment<commit_after>//! All the individual event types that can be sent out by the
//! Supervisor.

use super::EventCore;
use crate::manager::service::{HealthCheckResult as DomainHealthCheckResult,
                              Service,
                              UpdateStrategy as DomainUpdateStrategy};
use prost::{Enumeration,
            Message};

include!(concat!(env!("OUT_DIR"), "/chef.habitat.supervisor.event.rs"));

// Note: `UpdateStrategy` here is the protobuf-generated type for the
// event we're sending out; `DomainUpdateStrategy` is the one we use
// elsewhere in the Supervisor.
impl Into<UpdateStrategy> for DomainUpdateStrategy {
    fn into(self) -> UpdateStrategy {
        match self {
            DomainUpdateStrategy::None => UpdateStrategy::None,
            DomainUpdateStrategy::AtOnce => UpdateStrategy::AtOnce,
            DomainUpdateStrategy::Rolling => UpdateStrategy::Rolling,
        }
    }
}

// Note: `HealthCheck` here is the protobuf-generated type for the
// event we're sending out; `DomainHealthCheckResult` is the one we use
// elsewhere in the Supervisor.
impl Into<HealthCheck> for DomainHealthCheckResult {
    fn into(self) -> HealthCheck {
        match self {
            DomainHealthCheckResult::Ok => HealthCheck::Ok,
            DomainHealthCheckResult::Warning => HealthCheck::Warning,
            DomainHealthCheckResult::Critical => HealthCheck::Critical,
            DomainHealthCheckResult::Unknown => HealthCheck::Unknown,
        }
    }
}

impl Service {
    /// Create a protobuf metadata struct for Service-related event
    /// messages.
    // NOTE This was originally `pub(super)`, but it's `pub` for now
    // because it seems better to be able to generate this when we
    // kick off the health checking future for a service, rather than
    // cloning the entire service for eventing.
    pub fn to_service_metadata(&self) -> ServiceMetadata {
        ServiceMetadata { package_ident:   self.pkg.ident.to_string(),
                          spec_ident:      self.spec_ident.to_string(),
                          service_group:   self.service_group.to_string(),
                          update_channel:  self.channel.to_string(),
                          update_strategy: self.update_strategy.into(), }
    }
}

impl EventCore {
    /// Create a protobuf metadata struct for all event messages.
    pub(super) fn to_event_metadata(&self) -> EventMetadata {
        EventMetadata { supervisor_id: self.supervisor_id.clone(),
                        ip_address:    self.ip_address.to_string(),
                        application:   self.application.clone(),
                        environment:   self.environment.clone(),
                        timestamp:     None,
                        meta:          self.meta.clone().into(), }
    }
}

pub trait EventMessage: Message + Sized {
    /// All messages will have some top-level metadata about the
    /// Supervisor they come from. This function allows us to set it
    /// generically when we send the message out.
    fn event_metadata(&mut self, event_metadata: EventMetadata);

    /// Convert a message to bytes for sending to NATS.
    fn to_bytes(&self) -> Vec<u8> {
        let mut buf = bytes::BytesMut::with_capacity(self.encoded_len());
        // The only way this can fail is if the buffer doesn't have
        // enough room. We just set that, though, so something would
        // have to be seriously wrong in Prost for this to fail.
        self.encode(&mut buf)
            .expect("UNEXPECTED PROST ERROR: encoded_len() was not long enough!");
        buf.to_vec()
    }
}

// TODO (CM): these are repetitive, and will only get more so as we
// add events. Consider implementing via macro instead.

impl EventMessage for ServiceStartedEvent {
    fn event_metadata(&mut self, event_metadata: EventMetadata) {
        self.event_metadata = Some(event_metadata);
    }
}

impl EventMessage for ServiceStoppedEvent {
    fn event_metadata(&mut self, event_metadata: EventMetadata) {
        self.event_metadata = Some(event_metadata);
    }
}

impl EventMessage for HealthCheckEvent {
    fn event_metadata(&mut self, event_metadata: EventMetadata) {
        self.event_metadata = Some(event_metadata);
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use super::helpers::{
    TestRig,
    setup_attestation_validation_test,
};
use super::validation::attestation_validation::{
    AttestationValidationError,
};
use super::types::AttesterMap;
use super::bls::{
    AggregateSignature,
};
use super::types::{
    Hash256,
};

fn generic_rig() -> TestRig {
    let shard_id = 10;
    let validator_count = 2;
    setup_attestation_validation_test(shard_id, validator_count)
}

#[test]
fn test_attestation_validation_valid() {
    let rig = generic_rig();

    let result = rig.context.validate_attestation(&rig.attestation);

    let voter_map = result.unwrap();
    assert_eq!(voter_map.len(), 2);
}

#[test]
fn test_attestation_validation_invalid_slot_too_high() {
    let mut rig = generic_rig();

    rig.attestation.slot = rig.context.block_slot + 1;

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::SlotTooHigh));
}

#[test]
fn test_attestation_validation_invalid_slot_too_low() {
    let mut rig = generic_rig();

    rig.attestation.slot = rig.context.block_slot - u64::from(rig.context.cycle_length) - 2;
    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::SlotTooLow));
}

#[test]
fn test_attestation_validation_invalid_justified_slot_incorrect() {
    let mut rig = generic_rig();

    let original = rig.attestation.justified_slot;
    rig.attestation.justified_slot = original - 1;
    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::JustifiedSlotIncorrect));

    rig.attestation.justified_slot = original + 1;
    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::JustifiedSlotIncorrect));
}

#[test]
fn test_attestation_validation_invalid_too_many_oblique() {
    let mut rig = generic_rig();

    let obliques: Vec<Hash256> = (0..(rig.context.cycle_length + 1))
        .map(|i| Hash256::from((i * 2) as u64))
        .collect();

    rig.attestation.oblique_parent_hashes = obliques;

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::TooManyObliqueHashes));
}

#[test]
fn test_attestation_validation_invalid_bad_attester_map() {
    let mut rig = generic_rig();

    rig.context.attester_map = Arc::new(AttesterMap::new());

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::BadAttesterMap));
}

#[test]
fn test_attestation_validation_invalid_bad_bitfield_length() {
    let mut rig = generic_rig();

    /*
     * Extend the bitfield by one byte
     *
     * This is a little hacky and makes assumptions about the internals
     * of the bitfield.
     */
    let one_byte_higher = rig.attester_count + 8;
    rig.attestation.attester_bitfield.set_bit(one_byte_higher, true);
    rig.attestation.attester_bitfield.set_bit(one_byte_higher, false);

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::BadBitfieldLength));
}

#[test]
fn test_attestation_validation_invalid_unknown_justfied_block_hash() {
    let mut rig = generic_rig();

    rig.attestation.justified_block_hash = Hash256::from("unknown block hash".as_bytes());

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::UnknownJustifiedBlock));
}

#[test]
fn test_attestation_validation_invalid_empty_signature() {
    let mut rig = generic_rig();

    rig.attestation.aggregate_sig = AggregateSignature::new();

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::BadAggregateSignature));
}
<commit_msg>Add InvalidBitfieldEndBits tests<commit_after>use std::sync::Arc;

use super::helpers::{
    TestRig,
    setup_attestation_validation_test,
};
use super::validation::attestation_validation::{
    AttestationValidationError,
};
use super::types::AttesterMap;
use super::bls::{
    AggregateSignature,
};
use super::types::{
    Hash256,
};

fn generic_rig() -> TestRig {
    let shard_id = 10;
    let validator_count = 2;
    setup_attestation_validation_test(shard_id, validator_count)
}

#[test]
fn test_attestation_validation_valid() {
    let rig = generic_rig();

    let result = rig.context.validate_attestation(&rig.attestation);

    let voter_map = result.unwrap();
    assert_eq!(voter_map.len(), 2);
}

#[test]
fn test_attestation_validation_invalid_slot_too_high() {
    let mut rig = generic_rig();

    rig.attestation.slot = rig.context.block_slot + 1;

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::SlotTooHigh));
}

#[test]
fn test_attestation_validation_invalid_slot_too_low() {
    let mut rig = generic_rig();

    rig.attestation.slot = rig.context.block_slot - u64::from(rig.context.cycle_length) - 2;
    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::SlotTooLow));
}

#[test]
fn test_attestation_validation_invalid_justified_slot_incorrect() {
    let mut rig = generic_rig();

    let original = rig.attestation.justified_slot;
    rig.attestation.justified_slot = original - 1;
    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::JustifiedSlotIncorrect));

    rig.attestation.justified_slot = original + 1;
    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::JustifiedSlotIncorrect));
}

#[test]
fn test_attestation_validation_invalid_too_many_oblique() {
    let mut rig = generic_rig();

    let obliques: Vec<Hash256> = (0..(rig.context.cycle_length + 1))
        .map(|i| Hash256::from((i * 2) as u64))
        .collect();

    rig.attestation.oblique_parent_hashes = obliques;

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::TooManyObliqueHashes));
}

#[test]
fn test_attestation_validation_invalid_bad_attester_map() {
    let mut rig = generic_rig();

    rig.context.attester_map = Arc::new(AttesterMap::new());

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::BadAttesterMap));
}

#[test]
fn test_attestation_validation_invalid_bad_bitfield_length() {
    let mut rig = generic_rig();

    /*
     * Extend the bitfield by one byte
     *
     * This is a little hacky and makes assumptions about the internals
     * of the bitfield.
     */
    let one_byte_higher = rig.attester_count + 8;
    rig.attestation.attester_bitfield.set_bit(one_byte_higher, true);
    rig.attestation.attester_bitfield.set_bit(one_byte_higher, false);

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::BadBitfieldLength));
}

#[test]
fn test_attestation_validation_invalid_invalid_bitfield_end_bit() {
    let mut rig = generic_rig();

    let one_bit_high = rig.attester_count + 1;
    rig.attestation.attester_bitfield.set_bit(one_bit_high, true);

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::InvalidBitfieldEndBits));
}

#[test]
fn test_attestation_validation_invalid_invalid_bitfield_end_bit_with_irreguar_bitfield_len() {
    let mut rig = generic_rig();

    /*
     * This test ensure that if the number of attesters is "irregular" (with respect to the
     * bitfield), and there is a invalid bit is set, validation will still fail.
     *
     * "Irregular" here means that number of validators + 1 is not a clean multiple of eight.
     *
     * This test exists to ensure that the application can distinguish between the highest set
     * bit in a bitfield and the byte length of that bitfield
     */
    let one_bit_high = rig.attester_count + 1;
    assert!(one_bit_high % 8 != 0, "the test is ineffective in this case.");
    rig.attestation.attester_bitfield.set_bit(one_bit_high, true);

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::InvalidBitfieldEndBits));
}

#[test]
fn test_attestation_validation_invalid_unknown_justfied_block_hash() {
    let mut rig = generic_rig();

    rig.attestation.justified_block_hash = Hash256::from("unknown block hash".as_bytes());

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::UnknownJustifiedBlock));
}

#[test]
fn test_attestation_validation_invalid_empty_signature() {
    let mut rig = generic_rig();

    rig.attestation.aggregate_sig = AggregateSignature::new();

    let result = rig.context.validate_attestation(&rig.attestation);
    assert_eq!(result, Err(AttestationValidationError::BadAggregateSignature));
}
<|endoftext|>


<commit_before>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::{IoResult, IoError};
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    let msg = format!("WARNING: Battery critically low!");
                    match show_warning(msg, true) {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    let msg = format!("WARNING: Battery low!");
                    match show_warning(msg, false) {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

fn show_warning(msg: String, critical: bool) -> Result<Process, IoError> {
    let warning_level = match critical {
        false => "warning",
        true => "error",
    };
    Command::new("i3-nagbar")
        .arg("-t")
        .arg(warning_level)
        .arg(format!("-m {}", msg))
        .spawn()
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<commit_msg>crank up time<commit_after>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::{IoResult, IoError};
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    let poll_delay: Duration = Duration::minutes(5);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    let msg = format!("WARNING: Battery critically low!");
                    match show_warning(msg, true) {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    let msg = format!("WARNING: Battery low!");
                    match show_warning(msg, false) {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

fn show_warning(msg: String, critical: bool) -> Result<Process, IoError> {
    let warning_level = match critical {
        false => "warning",
        true => "error",
    };
    Command::new("i3-nagbar")
        .arg("-t")
        .arg(warning_level)
        .arg(format!("-m {}", msg))
        .spawn()
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<|endoftext|>


<commit_before>use std::{fmt, ops::Deref, result::Result as StdResult, sync::Arc};

use serde::{
    Deserialize, Serialize,
    {de::Deserializer, ser::Serializer},
};

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
}

impl Serialize for IVec {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serde_bytes::serialize(self.as_ref(), serializer)
    }
}

impl<'de> Deserialize<'de> for IVec {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> StdResult<Self, D::Error> {
        let bytes: StdResult<Box<[u8]>, D::Error> =
            serde_bytes::deserialize(deserializer);
        bytes.map(IVec::from)
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    fn inline(slice: &[u8]) -> IVec {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        IVec(IVecInner::Inline(slice.len() as u8, data))
    }

    fn remote(arc: Arc<[u8]>) -> IVec {
        IVec(IVecInner::Remote(arc))
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if let IVecInner::Inline(..) = self.0 {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> IVec {
        if is_inline_candidate(b.len()) {
            IVec::inline(&b)
        } else {
            // rely on the Arc From specialization
            // for Box<T>, which may improve
            // over time
            IVec::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> IVec {
        if is_inline_candidate(slice.len()) {
            IVec::inline(slice)
        } else {
            IVec::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> IVec {
        IVec::remote(arc)
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> IVec {
        IVec::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &IVec) -> IVec {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        if is_inline_candidate(v.len()) {
            IVec::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            IVec::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> IVec {
                    IVec::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &IVec) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &IVec) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}
<commit_msg>Implement Hash for IVec<commit_after>use std::{
    collections::hash_map::DefaultHasher,
    fmt,
    hash::{Hash, Hasher},
    ops::Deref,
    result::Result as StdResult,
    sync::Arc,
};

use serde::{
    Deserialize, Serialize,
    {de::Deserializer, ser::Serializer},
};

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

impl Serialize for IVec {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serde_bytes::serialize(self.as_ref(), serializer)
    }
}

impl<'de> Deserialize<'de> for IVec {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> StdResult<Self, D::Error> {
        let bytes: StdResult<Box<[u8]>, D::Error> =
            serde_bytes::deserialize(deserializer);
        bytes.map(IVec::from)
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    fn inline(slice: &[u8]) -> IVec {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        IVec(IVecInner::Inline(slice.len() as u8, data))
    }

    fn remote(arc: Arc<[u8]>) -> IVec {
        IVec(IVecInner::Remote(arc))
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if let IVecInner::Inline(..) = self.0 {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> IVec {
        if is_inline_candidate(b.len()) {
            IVec::inline(&b)
        } else {
            // rely on the Arc From specialization
            // for Box<T>, which may improve
            // over time
            IVec::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> IVec {
        if is_inline_candidate(slice.len()) {
            IVec::inline(slice)
        } else {
            IVec::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> IVec {
        IVec::remote(arc)
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> IVec {
        IVec::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &IVec) -> IVec {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        if is_inline_candidate(v.len()) {
            IVec::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            IVec::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> IVec {
                    IVec::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &IVec) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &IVec) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}
<|endoftext|>


<commit_before>
//==============================================================================
struct Complex {
    real : f32,
    imag : f32
}

impl Complex {
    fn new(real: f32, imag: f32) -> Complex {
        Complex { real: real, imag: imag }
    }

    fn to_string(&self) -> String {
        format!("{}{:+}i", self.real, self.imag)
    }

    fn add(&self, v: Complex) -> Complex {
        Complex { real: self.real + v.real, imag: self.imag + v.imag }
    }

    fn times_ten(&mut self) {
        self.real *= 10.0;
        self.imag *= 10.0;
    }

    fn abs(&self) -> f32 {
        (self.real * self.real + self.imag * self.imag).sqrt()
    }
}

fn ex_5_1() {
    println!("\n#### ex_5_1() ####");

    let a = Complex::new(1.0, 2.0);
    println!("a = {}", a.to_string());

    let b = Complex::new(2.0, 4.0);
    println!("b = {}", b.to_string());

    let mut c = a.add(b);
    println!("c = {}", c.to_string());

    c.times_ten();
    println!("c*10 = {}", c.to_string());

    let d = Complex::new(-3.0, -4.0);
    println!("d = {}", d.to_string());
    println!("abs(d) = {}", d.abs());
}

//==============================================================================
trait Draw {
    fn draw(&self);
}

struct S1 {
    val : u32
}

struct S2 {
    val : f32
}

impl Draw for S1 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

impl Draw for S2 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

fn draw_object(obj : &Draw) {
    obj.draw();
}

fn ex_5_2() {
    println!("\n#### ex_5_2 ####");
    let s1 = S1 { val : 10 };
    draw_object(&s1);

    let s2 = S2 { val : 3.14 };
    draw_object(&s2);
}

//==============================================================================
// Eq and Ord trait example

#[derive(Eq)]
struct Position {
    x : u32,
    y : u32
}

impl PartialEq for Position {
    fn eq(&self, other: &Position) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl std::cmp::Ord for Position {
    fn cmp(&self, other: &Position) -> std::cmp::Ordering {
        let abs = self.x * self.x + self.y * self.y;
        let abs_other = other.x * other.x + other.y * other.y;

        abs.cmp(&abs_other)
    }
}

impl std::cmp::PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

fn ex_5_3() {
    println!("\n#### ex_5_3 (Eq, PartialEq traits) ####");
    let pos1 = Position { x: 10, y: 20 };
    let pos2 = Position { x: 10, y: 20 };
    let pos3 = Position { x: 20, y: 40 };
    let pos4 = Position { x: 20, y: 10 };

    println!("pos1 == pos2 : {}", pos1 == pos2);
    println!("pos1 == pos3 : {}", pos1 == pos3);
    println!("pos1 != pos3 : {}", pos1 != pos3);
    println!("pos1 == pos4 : {}", pos1 == pos4);
    println!("pos1 < pos3 : {}", pos1 < pos3);
    println!("pos1 > pos3 : {}", pos1 > pos3);
}

//==============================================================================
// Default, Debug trait

enum ButtonState {
    CLICKED,
    RELEASED
}

impl Default for ButtonState {
    fn default() -> ButtonState {
        ButtonState::CLICKED
    }
}

impl std::fmt::Debug for ButtonState {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let state = match *self {
            ButtonState::CLICKED => "CLICKED",
            ButtonState::RELEASED => "RELEASED",
        };
        write!(f, "{}", state)
    }
}

fn ex_5_4() {
    let mut btn : ButtonState = Default::default();
    println!("btn = {:?}", btn);

    btn = ButtonState::RELEASED;
    println!("btn = {:?}", btn);
}

//==============================================================================
fn main() {
    ex_5_1();
    ex_5_2();
    ex_5_3();
    ex_5_4();
}
<commit_msg>Rust_EssentialNoteBook: add Clone and Add traits example<commit_after>
//==============================================================================
struct Complex {
    real : f32,
    imag : f32
}

impl Complex {
    fn new(real: f32, imag: f32) -> Complex {
        Complex { real: real, imag: imag }
    }

    fn to_string(&self) -> String {
        format!("{}{:+}i", self.real, self.imag)
    }

    fn add(&self, v: Complex) -> Complex {
        Complex { real: self.real + v.real, imag: self.imag + v.imag }
    }

    fn times_ten(&mut self) {
        self.real *= 10.0;
        self.imag *= 10.0;
    }

    fn abs(&self) -> f32 {
        (self.real * self.real + self.imag * self.imag).sqrt()
    }
}

fn ex_5_1() {
    println!("\n#### ex_5_1() ####");

    let a = Complex::new(1.0, 2.0);
    println!("a = {}", a.to_string());

    let b = Complex::new(2.0, 4.0);
    println!("b = {}", b.to_string());

    let mut c = a.add(b);
    println!("c = {}", c.to_string());

    c.times_ten();
    println!("c*10 = {}", c.to_string());

    let d = Complex::new(-3.0, -4.0);
    println!("d = {}", d.to_string());
    println!("abs(d) = {}", d.abs());
}

//==============================================================================
trait Draw {
    fn draw(&self);
}

struct S1 {
    val : u32
}

struct S2 {
    val : f32
}

impl Draw for S1 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

impl Draw for S2 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

fn draw_object(obj : &Draw) {
    obj.draw();
}

fn ex_5_2() {
    println!("\n#### ex_5_2 ####");
    let s1 = S1 { val : 10 };
    draw_object(&s1);

    let s2 = S2 { val : 3.14 };
    draw_object(&s2);
}

//==============================================================================
// Eq, Ord, Clone, Debug, Default and Add traits for struct

#[derive(Eq)]
#[derive(Default)]
struct Position {
    x : u32,
    y : u32
}

impl PartialEq for Position {
    fn eq(&self, other: &Position) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl std::cmp::Ord for Position {
    fn cmp(&self, other: &Position) -> std::cmp::Ordering {
        let abs = self.x * self.x + self.y * self.y;
        let abs_other = other.x * other.x + other.y * other.y;

        abs.cmp(&abs_other)
    }
}

impl std::cmp::PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl std::clone::Clone for Position {
    fn clone(&self) -> Position {
        Position { x : self.x, y: self.y }
        // Or, derive Copy at Position and return *self here.
    }
}

impl std::ops::Add for Position {
    type Output = Position;

    fn add(self, other: Position) -> Position {
        Position { x: self.x + other.x, y: self.y + other.y }
    }
}

impl std::fmt::Debug for Position {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Position{{ x:{}, y:{} }}", self.x, self.y)
    }
}

fn ex_5_3() {
    println!("\n#### ex_5_3 (Eq, PartialEq traits) ####");
    let pos1 = Position { x: 10, y: 20 };
    let pos2 = Position { x: 10, y: 20 };
    let pos3 = Position { x: 20, y: 40 };
    let pos4 = Position { x: 20, y: 10 };

    println!("pos1 == pos2 : {}", pos1 == pos2);
    println!("pos1 == pos3 : {}", pos1 == pos3);
    println!("pos1 != pos3 : {}", pos1 != pos3);
    println!("pos1 == pos4 : {}", pos1 == pos4);
    println!("pos1 < pos3 : {}", pos1 < pos3);
    println!("pos1 > pos3 : {}", pos1 > pos3);

    let pos5 = pos4.clone();
    println!("pos4 == pos5 : {}", pos4 > pos5);

    println!("pos1 + pos2 : {:?}", pos1 + pos2);

    let pos0 : Position = Default::default();
    println!("pos0 : {:?}", pos0);
}

//==============================================================================
// Default and Debug traits for enum

enum ButtonState {
    CLICKED,
    RELEASED
}

impl Default for ButtonState {
    fn default() -> ButtonState {
        ButtonState::CLICKED
    }
}

impl std::fmt::Debug for ButtonState {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let state = match *self {
            ButtonState::CLICKED => "CLICKED",
            ButtonState::RELEASED => "RELEASED",
        };
        write!(f, "{}", state)
    }
}

fn ex_5_4() {
    let mut btn : ButtonState = Default::default();
    println!("btn = {:?}", btn);

    btn = ButtonState::RELEASED;
    println!("btn = {:?}", btn);
}

//==============================================================================
fn main() {
    ex_5_1();
    ex_5_2();
    ex_5_3();
    ex_5_4();
}
<|endoftext|>


<commit_before>use crate::providers::aliyun;
use crate::providers::MetadataProvider;
use mockito;

#[test]
fn basic_hostname() {
    let ep = "/hostname";
    let hostname = "test-hostname";

    let mut provider = aliyun::AliyunProvider::try_new().unwrap();
    provider.client = provider.client.max_attempts(1);

    provider.hostname().unwrap_err();

    let _m = mockito::mock("GET", ep).with_status(503).create();
    provider.hostname().unwrap_err();

    let _m = mockito::mock("GET", ep)
        .with_status(200)
        .with_body(hostname)
        .create();
    let v = provider.hostname().unwrap();
    assert_eq!(v, Some(hostname.to_string()));

    let _m = mockito::mock("GET", ep).with_status(404).create();
    let v = provider.hostname().unwrap();
    assert_eq!(v, None);

    let _m = mockito::mock("GET", ep)
        .with_status(200)
        .with_body("")
        .create();
    let v = provider.hostname().unwrap();
    assert_eq!(v, None);
}

#[test]
fn basic_pubkeys() {
    let mut provider = aliyun::AliyunProvider::try_new().unwrap();
    provider.client = provider.client.max_attempts(1);

    // Setup two entries with identical content, in order to test de-dup.
    let _m_keys = mockito::mock("GET", "/public-keys/")
        .with_status(200)
        .with_body("0/\ntest/\n")
        .create();
    let _m_key0 = mockito::mock("GET", "/public-keys/0/openssh-key")
        .with_status(200)
        .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment")
        .create();
    let _m_keytest = mockito::mock("GET", "/public-keys/test/openssh-key")
        .with_status(200)
        .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment")
        .create();

    let keys = provider.ssh_keys().unwrap();
    assert_ne!(keys, vec![]);
    assert_eq!(keys.len(), 1);

    assert_eq!(keys[0].options, None);
    assert_eq!(keys[0].comment, Some("test-comment".to_string()));
}
<commit_msg>fixup! providers: add Alibaba Cloud (aliyun)<commit_after>use crate::providers::aliyun;
use crate::providers::MetadataProvider;
use mockito;

#[test]
fn basic_hostname() {
    let ep = "/hostname";
    let hostname = "test-hostname";

    let mut provider = aliyun::AliyunProvider::try_new().unwrap();
    provider.client = provider.client.max_attempts(1);

    let _m = mockito::mock("GET", ep).with_status(503).create();
    provider.hostname().unwrap_err();

    let _m = mockito::mock("GET", ep)
        .with_status(200)
        .with_body(hostname)
        .create();
    let v = provider.hostname().unwrap();
    assert_eq!(v, Some(hostname.to_string()));

    let _m = mockito::mock("GET", ep).with_status(404).create();
    let v = provider.hostname().unwrap();
    assert_eq!(v, None);

    let _m = mockito::mock("GET", ep)
        .with_status(200)
        .with_body("")
        .create();
    let v = provider.hostname().unwrap();
    assert_eq!(v, None);

    mockito::reset();
    provider.hostname().unwrap_err();
}

#[test]
fn basic_pubkeys() {
    let mut provider = aliyun::AliyunProvider::try_new().unwrap();
    provider.client = provider.client.max_attempts(1);

    // Setup two entries with identical content, in order to test de-dup.
    let _m_keys = mockito::mock("GET", "/public-keys/")
        .with_status(200)
        .with_body("0/\ntest/\n")
        .create();
    let _m_key0 = mockito::mock("GET", "/public-keys/0/openssh-key")
        .with_status(200)
        .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment")
        .create();
    let _m_keytest = mockito::mock("GET", "/public-keys/test/openssh-key")
        .with_status(200)
        .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment")
        .create();

    let keys = provider.ssh_keys().unwrap();
    assert_ne!(keys, vec![]);
    assert_eq!(keys.len(), 1);

    assert_eq!(keys[0].options, None);
    assert_eq!(keys[0].comment, Some("test-comment".to_string()));

    mockito::reset();
    provider.ssh_keys().unwrap_err();
}

#[test]
fn basic_attributes() {
    let eipv4 = "test-eipv4";
    let hostname = "test-hostname";
    let image_id = "test-image-id";
    let instance_id = "test-instance-id";
    let instance_type = "test-instance-type";
    let private_ipv4 = "test-private-ipv4";
    let public_ipv4 = "test-public-ipv4";
    let region_id = "test-region-id";
    let vpc_id = "test-vpc-id";
    let zone_id = "test-zone-id";

    let endpoints = maplit::btreemap! {
        "/eipv4" => eipv4,
        "/hostname" => hostname,
        "/image-id" => image_id,
        "/instance-id" => instance_id,
        "/instance/instance-type" => instance_type,
        "/private-ipv4" => private_ipv4,
        "/public-ipv4" => public_ipv4,
        "/region-id" => region_id,
        "/vpc-id" => vpc_id,
        "/zone-id" => zone_id,
    };
    let mut mocks = Vec::with_capacity(endpoints.len());
    for (endpoint, body) in endpoints {
        let m = mockito::mock("GET", endpoint)
            .with_status(200)
            .with_body(body)
            .create();
        mocks.push(m);
    }

    let attributes = maplit::hashmap! {
        "ALIYUN_EIPV4".to_string() => eipv4.to_string(),
        "ALIYUN_HOSTNAME".to_string() => hostname.to_string(),
        "ALIYUN_IMAGE_ID".to_string() => image_id.to_string(),
        "ALIYUN_INSTANCE_ID".to_string() => instance_id.to_string(),
        "ALIYUN_INSTANCE_TYPE".to_string() => instance_type.to_string(),
        "ALIYUN_IPV4_PRIVATE".to_string() => private_ipv4.to_string(),
        "ALIYUN_IPV4_PUBLIC".to_string() => public_ipv4.to_string(),
        "ALIYUN_REGION_ID".to_string()=> region_id.to_string(),
        "ALIYUN_VPC_ID".to_string() => vpc_id.to_string(),
        "ALIYUN_ZONE_ID".to_string() => zone_id.to_string(),
    };

    let client = crate::retry::Client::try_new()
        .unwrap()
        .max_attempts(1)
        .return_on_404(true);
    let provider = aliyun::AliyunProvider { client };

    let v = provider.attributes().unwrap();
    assert_eq!(v, attributes);

    mockito::reset();
    provider.attributes().unwrap_err();
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! Convenience structs and functions for generating a random set of Libra ndoes without the
//! genesis.blob.

use crate::{
    config::{
        NodeConfig, OnDiskStorageConfig, SafetyRulesBackend, SafetyRulesService, SeedPeersConfig,
        TestConfig,
    },
    utils,
};
use libra_types::{
    discovery_info::DiscoveryInfo, discovery_set::DiscoverySet, on_chain_config::ValidatorSet,
    transaction::authenticator::AuthenticationKey, validator_info::ValidatorInfo,
};
use rand::{rngs::StdRng, SeedableRng};

pub struct ValidatorSwarm {
    pub nodes: Vec<NodeConfig>,
    pub validator_set: ValidatorSet,
    pub discovery_set: DiscoverySet,
}

impl ValidatorSwarm {
    pub fn auth_keys(&self) -> Vec<AuthenticationKey> {
        self.nodes
            .iter()
            .map(|n| {
                let test_config = n.test.as_ref().unwrap();
                let key = test_config.account_keypair.as_ref().unwrap().public_key();
                AuthenticationKey::ed25519(&key)
            })
            .collect::<Vec<_>>()
    }
}

pub fn validator_swarm(
    template: &NodeConfig,
    count: usize,
    seed: [u8; 32],
    randomize_service_ports: bool,
    randomize_libranet_ports: bool,
) -> ValidatorSwarm {
    let mut rng = StdRng::from_seed(seed);
    let mut validator_keys = Vec::new();
    let mut discovery_infos = Vec::new();
    let mut nodes = Vec::new();

    for _index in 0..count {
        let mut node = NodeConfig::random_with_template(template, &mut rng);
        if randomize_service_ports {
            node.randomize_ports();
        }

        let mut storage_config = OnDiskStorageConfig::default();
        storage_config.default = true;
        node.consensus.safety_rules.service = SafetyRulesService::Thread;
        node.consensus.safety_rules.backend = SafetyRulesBackend::OnDiskStorage(storage_config);

        let network = node.validator_network.as_mut().unwrap();
        if randomize_libranet_ports {
            network.listen_address = utils::get_available_port_in_multiaddr(true);
            network.advertised_address = network.listen_address.clone();
        }

        let test = node.test.as_ref().unwrap();
        let consensus_pubkey = test
            .consensus_keypair
            .as_ref()
            .unwrap()
            .public_key()
            .clone();
        let network_keypairs = network
            .network_keypairs
            .as_ref()
            .expect("Network keypairs are not defined");

        validator_keys.push(ValidatorInfo::new(
            network.peer_id,
            consensus_pubkey,
            1, // @TODO: Add support for dynamic weights
            network_keypairs.signing_keypair.public_key(),
            network_keypairs.identity_keypair.public_key(),
        ));

        // TODO(philiphayes): as a temporary hack, we'll just duplicate the
        // validator info into the fullnode info until we can handle deserializing
        // empty fullnode info.
        discovery_infos.push(DiscoveryInfo {
            account_address: network.peer_id,
            validator_network_identity_pubkey: network_keypairs.identity_keypair.public_key(),
            validator_network_address: network.advertised_address.clone(),
            fullnodes_network_identity_pubkey: network_keypairs.identity_keypair.public_key(),
            fullnodes_network_address: network.advertised_address.clone(),
        });

        // set UpstreamConfig
        // For a validator node, any of its validator peers are considered an upstream peer
        node.upstream.primary_networks.push(network.peer_id);

        nodes.push(node);
    }

    let mut seed_peers = SeedPeersConfig::default();
    let network = nodes[0].validator_network.as_ref().unwrap();
    seed_peers
        .seed_peers
        .insert(network.peer_id, vec![network.listen_address.clone()]);

    for node in &mut nodes {
        let network = node.validator_network.as_mut().unwrap();
        network.seed_peers = seed_peers.clone();
    }

    ValidatorSwarm {
        nodes,
        validator_set: ValidatorSet::new(validator_keys),
        discovery_set: DiscoverySet::new(discovery_infos),
    }
}

pub fn validator_swarm_for_testing(nodes: usize) -> ValidatorSwarm {
    let mut config = NodeConfig::default();
    config.test = Some(TestConfig::open_module());
    validator_swarm(&NodeConfig::default(), nodes, [1u8; 32], true, true)
}
<commit_msg>[config] Remove validator and discovery set from config-generator<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! Convenience structs and functions for generating a random set of Libra ndoes without the
//! genesis.blob.

use crate::{
    config::{
        NodeConfig, OnDiskStorageConfig, SafetyRulesBackend, SafetyRulesService, SeedPeersConfig,
        TestConfig,
    },
    utils,
};
use rand::{rngs::StdRng, SeedableRng};

pub struct ValidatorSwarm {
    pub nodes: Vec<NodeConfig>,
}

pub fn validator_swarm(
    template: &NodeConfig,
    count: usize,
    seed: [u8; 32],
    randomize_service_ports: bool,
    randomize_libranet_ports: bool,
) -> ValidatorSwarm {
    let mut rng = StdRng::from_seed(seed);
    let mut nodes = Vec::new();

    for _index in 0..count {
        let mut node = NodeConfig::random_with_template(template, &mut rng);
        if randomize_service_ports {
            node.randomize_ports();
        }

        let mut storage_config = OnDiskStorageConfig::default();
        storage_config.default = true;
        node.consensus.safety_rules.service = SafetyRulesService::Thread;
        node.consensus.safety_rules.backend = SafetyRulesBackend::OnDiskStorage(storage_config);

        let network = node.validator_network.as_mut().unwrap();
        if randomize_libranet_ports {
            network.listen_address = utils::get_available_port_in_multiaddr(true);
            network.advertised_address = network.listen_address.clone();
        }

        // For a validator node, any of its validator peers are considered an upstream peer
        node.upstream.primary_networks.push(network.peer_id);

        nodes.push(node);
    }

    let mut seed_peers = SeedPeersConfig::default();
    let network = nodes[0].validator_network.as_ref().unwrap();
    seed_peers
        .seed_peers
        .insert(network.peer_id, vec![network.listen_address.clone()]);

    for node in &mut nodes {
        let network = node.validator_network.as_mut().unwrap();
        network.seed_peers = seed_peers.clone();
    }

    ValidatorSwarm { nodes }
}

pub fn validator_swarm_for_testing(nodes: usize) -> ValidatorSwarm {
    let mut config = NodeConfig::default();
    config.test = Some(TestConfig::open_module());
    validator_swarm(&NodeConfig::default(), nodes, [1u8; 32], true, true)
}
<|endoftext|>