<commit_before>// http://dev.w3.org/csswg/css3-syntax/#tokenization
//
// The output of the tokenization step is a series of zero or more
// of the following tokens:
// ident, function, at-keyword, hash, string, bad-string, url, bad-url,
// delim, number, percentage, dimension, unicode-range, whitespace, comment,
// cdo, cdc, colon, semicolon, [, ], (, ), {, }.
//
// ident, function, at-keyword, hash, string, and url tokens
// have a value composed of zero or more characters.
// Delim tokens have a value composed of a single character.
// Number, percentage, and dimension tokens have a representation
// composed of 1 or more character, a numeric value,
// and a type flag set to either "integer" or "number".
// The type flag defaults to "integer" if not otherwise set.
// Dimension tokens additionally have a unit
// composed of one or more characters.
// Unicode-range tokens have a range of characters.

use cssparser;

const MAX_UNICODE: uint = 0x10FFFF;

#[deriving_eq]
enum NumericValue {
    Integer(int),
    // The spec calls this "number".
    // Use "float" instead to reduce term overloading with "number token".
    Float(float),
}
// TODO: add a NumberValue.as_float() method.

#[deriving_eq]
enum Token {
    Ident(~str),
    Function(~str),
    AtKeyword(~str),
    Hash(~str),
    String(~str),
    BadString,
    URL(~str),
    BadURL,
    Delim(char),
    Number(NumericValue, ~str),  // value, representation
    Percentage(NumericValue, ~str),  // value, representation
    Dimension(NumericValue, ~str, ~str),  // value, representation, unit
    UnicodeRange(char, char),  // start, end. XXX what about empty ranges?
    WhiteSpace,
    Comment,
    CDO,  // <!--
    CDC,  // -->
    Colon,  // ,
    Semicolon,  // ;
    OpenBraket, // [
    OpenParen, // (
    OpenBrace, // {
    CloseBraket, // ]
    CloseParen, // )
    CloseBrace, // }
}

struct State {
    input: ~str,
    length: uint,
    transform_function_whitespace: bool,
    quirks_mode: bool,
    mut position: uint,
    mut errors: ~[~str]
}

fn is_eof(state: &State) -> bool {
    state.position >= state.length
}

fn current_char(state: &State) -> char {
    str::char_at(state.input, state.position)
}

fn consume_char(state: &State) -> char {
    let range = str::char_range_at(state.input, state.position);
    state.position = range.next;
    range.ch
}

fn consume_whitespace(state: &State) -> Token {
    while !is_eof(state) {
        match current_char(state) {
            '\t' | '\n' | '\x0C' | ' ' => state.position += 1,
            _ => break,
        }
    }
    WhiteSpace
}

fn char_from_hex(hex: &[char]) -> char {
    let mut value = 0u;
    for hex.each |cc| {
        let c = *cc;
        value = value * 16 + c as uint - match c {
            '0'..'9' => '0' as uint,
            'A'..'F' => 'A' as uint - 10,
            'a'..'f' => 'a' as uint - 10,
            _ => fail
        }
    }
    if value == 0 || value > MAX_UNICODE {
        '\uFFFD'  // Replacement character
    } else {
        value as char
    }
}

// 3.3.27. Consume an escaped character
// Assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed
// and that the next input character has already been verified
// to not be a newline or EOF.
fn consume_escape(state: &State) -> char {
    let c = consume_char(state);
    match c {
        '0'..'9' | 'A'..'F' | 'a'..'f' => {
            let mut hex = ~[c];
            while hex.len() < 6 && !is_eof(state) {
                let c = current_char(state);
                match c {
                    '0'..'9' | 'A'..'F' | 'a'..'f' => {
                        hex.push(c); state.position += 1 },
                    _ => break
                }
            }
            if !is_eof(state) {
                match current_char(state) {
                    '\t' | '\n' | '\x0C' | ' ' => state.position += 1,
                    _ => ()
                }
            }
            char_from_hex(hex)
        },
        c => c
    }
}

// 3.3.5. Double-quote-string state
// 3.3.6. Single-quote-string state
fn consume_quoted_string(state: &State, single_quote: bool) -> Token {
    let mut string: ~str = ~"";
    loop {
        if is_eof(state) {
            state.errors.push(~"EOF in quoted string");
            return String(string);
        }
        match consume_char(state) {
            '"' if !single_quote => return String(string),
            '\'' if single_quote => return String(string),
            '\n' | '\x0C' => {
                state.errors.push(~"Newline in quoted string");
                return BadString
            },
            '\\' => {
                if is_eof(state) {
                    state.errors.push(~"EOF in quoted string");
                    return BadString
                }
                match current_char(state) {
                    // Consume quoted newline
                    '\n' | '\x0C' => state.position += 1,
                    _ =>  str::push_char(&mut string, consume_escape(state))
                }
            }
            c => str::push_char(&mut string, c),
        }
    }
}

// 3.3.9. Comment state
fn consume_comment(state: &State) -> Token {
    state.position += 1;  // consume the * in /*
    match str::find_str_from(state.input, "*/", state.position) {
        Some(end_position) => state.position = end_position + 2,
        None => {
            state.errors.push(~"EOF in comment");
            state.position = state.input.len();
        }
    }
    Comment
}

// 3.3.12. Ident state
// 3.3.13. Ident-rest state
fn consume_ident(state: &State, initial_char: char) -> Token {
    let mut string = str::from_char(initial_char);
    while !is_eof(state) {
        let c = current_char(state);
        let cc = match c {
            'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '-'  => {
                state.position += 1; c },
            _ if c >= '\xA0' => consume_char(state),  // Non-ASCII
            '\\' => {
                state.position += 1;
                if is_eof(state) { state.position -= 1; break }
                match current_char(state) {
                    '\n' | '\x0C' => { state.position -= 1; break },
                    _ => consume_escape(state)
                }
            },
            '\t' | '\n' | '\x0C' | ' ' if state.transform_function_whitespace
            => {
                state.position += 1;
                return handle_transform_function_whitespace(state, string)
            }
            '(' => {
                state.position += 1;
                // TODO: URLs
                return Function(string)
            },
            _ => break
        };
        str::push_char(&mut string, cc)
    }
    Ident(string)
}

// 3.3.14. Transform-function-whitespace state
fn handle_transform_function_whitespace(state: &State, string: ~str) -> Token {
    while !is_eof(state) {
        match current_char(state) {
            '\t' | '\n' | '\x0C' | ' ' => state.position += 1,
            '(' => { state.position += 1; return Function(string) }
            _ => break,
        }
    }
    // XXX I think the spec is wrong here.
    // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0266.html
    // Go back for one whitespace character.
    state.position -= 1;
    return Ident(string)
}

// http://dev.w3.org/csswg/css3-syntax/#tokenization
fn tokenize(input: &str, transform_function_whitespace: bool,
            quirks_mode: bool) -> {tokens: ~[Token], parse_errors: ~[~str]} {
    let input = cssparser::preprocess(input);
    let state = &State {
        input: input, length: input.len(), quirks_mode: quirks_mode,
        transform_function_whitespace: transform_function_whitespace,
        position: 0, errors: ~[] };
    let mut tokens: ~[Token] = ~[];

    // 3.3.4. Data state
    while !is_eof(state) {
        let c = consume_char(state);
        tokens.push(match c {
            '\t' | '\n' | '\x0C' | ' ' => consume_whitespace(state),
            '"' => consume_quoted_string(state, false),
            '\'' => consume_quoted_string(state, true),
            '/' if !is_eof(state) && current_char(state) == '*'
                => consume_comment(state),
            ',' => Colon,
            ';' => Semicolon,
            '[' => OpenBraket,
            '(' => OpenParen,
            '{' => OpenBrace,
            ']' => CloseBraket,
            ')' => CloseParen,
            '}' => CloseBrace,
            'a'..'z' | 'A'..'Z' | '_' => consume_ident(state, c),
            c if c >= '\xA0' => consume_ident(state, c),  // Non-ASCII
            _ => Delim(c),
        })
    }

    // Work around `error: moving out of mutable field`
    // TODO: find a cleaner way.
    let mut errors: ~[~str] = ~[];
    errors <-> state.errors;
    {tokens: tokens, parse_errors: errors}
}

#[test]
fn test_tokenizer() {

    fn assert_tokens(input: &str, expected_tokens: &[Token],
                     expected_errors: &[~str]) {
        assert_tokens_flags(
            input, false, false, expected_tokens, expected_errors)
    }

    fn assert_tokens_flags(
            input: &str,
            transform_function_whitespace: bool, quirks_mode: bool,
            expected_tokens: &[Token], expected_errors: &[~str]) {
        let result = tokenize(
            input, transform_function_whitespace, quirks_mode);
        let tokens: &[Token] = result.tokens;
        let parse_errors: &[~str] = result.parse_errors;
        if tokens != expected_tokens {
            fail fmt!("%? != %?", tokens, expected_tokens);
        }
        if parse_errors != expected_errors {
            fail fmt!("%? != %?", parse_errors, expected_errors);
        }
    }
    assert_tokens("", [], []);
    assert_tokens("?/", [Delim('?'), Delim('/')], []);
    assert_tokens("?/* Li/*psum… */", [Delim('?'), Comment], []);
    assert_tokens("?/* Li/*psum… *//", [Delim('?'), Comment, Delim('/')], []);
    assert_tokens("?/* Lipsum", [Delim('?'), Comment], [~"EOF in comment"]);
    assert_tokens("?/*", [Delim('?'), Comment], [~"EOF in comment"]);
    assert_tokens("[?}{)",
        [OpenBraket, Delim('?'), CloseBrace, OpenBrace, CloseParen], []);

    assert_tokens("(\n \t'Lore\\6d \"ipsu\\6D'",
        [OpenParen, WhiteSpace, String(~"Lorem\"ipsum")], []);
    assert_tokens("'\\''", [String(~"'")], []);
    assert_tokens("\"\\\"\"", [String(~"\"")], []);
    assert_tokens("\"\\\"", [String(~"\"")], [~"EOF in quoted string"]);
    assert_tokens("'\\", [BadString], [~"EOF in quoted string"]);
    assert_tokens("\"0\\0000000\"", [String(~"0\uFFFD0")], []);
    assert_tokens("\"0\\000000 0\"", [String(~"0\uFFFD0")], []);
    assert_tokens("'z\n'a", [BadString, String(~"a")],
        [~"Newline in quoted string", ~"EOF in quoted string"]);

    assert_tokens("Lorem\\ ipsu\\6D dolor sit",
        [Ident(~"Lorem ipsumdolor"), WhiteSpace, Ident(~"sit")], []);
    assert_tokens("foo\\", [Ident(~"foo"), Delim('\\')], []);
    assert_tokens("foo\\\nbar",
        [Ident(~"foo"), Delim('\\'), WhiteSpace, Ident(~"bar")], []);
    assert_tokens("func()", [Function(~"func"), CloseParen], []);
    assert_tokens("func ()",
        [Ident(~"func"), WhiteSpace, OpenParen, CloseParen], []);
    assert_tokens_flags("func ()", true, false,
        [Function(~"func"), CloseParen], []);
}
<commit_msg>Move stuff around.<commit_after>// http://dev.w3.org/csswg/css3-syntax/#tokenization
//
// The output of the tokenization step is a series of zero or more
// of the following tokens:
// ident, function, at-keyword, hash, string, bad-string, url, bad-url,
// delim, number, percentage, dimension, unicode-range, whitespace, comment,
// cdo, cdc, colon, semicolon, [, ], (, ), {, }.
//
// ident, function, at-keyword, hash, string, and url tokens
// have a value composed of zero or more characters.
// Delim tokens have a value composed of a single character.
// Number, percentage, and dimension tokens have a representation
// composed of 1 or more character, a numeric value,
// and a type flag set to either "integer" or "number".
// The type flag defaults to "integer" if not otherwise set.
// Dimension tokens additionally have a unit
// composed of one or more characters.
// Unicode-range tokens have a range of characters.

use cssparser;

const MAX_UNICODE: uint = 0x10FFFF;

#[deriving_eq]
enum NumericValue {
    Integer(int),
    // The spec calls this "number".
    // Use "float" instead to reduce term overloading with "number token".
    Float(float),
}
// TODO: add a NumberValue.as_float() method.

#[deriving_eq]
enum Token {
    Ident(~str),
    Function(~str),
    AtKeyword(~str),
    Hash(~str),
    String(~str),
    BadString,
    URL(~str),
    BadURL,
    Delim(char),
    Number(NumericValue, ~str),  // value, representation
    Percentage(NumericValue, ~str),  // value, representation
    Dimension(NumericValue, ~str, ~str),  // value, representation, unit
    UnicodeRange(char, char),  // start, end. XXX what about empty ranges?
    WhiteSpace,
    Comment,
    CDO,  // <!--
    CDC,  // -->
    Colon,  // ,
    Semicolon,  // ;
    OpenBraket, // [
    OpenParen, // (
    OpenBrace, // {
    CloseBraket, // ]
    CloseParen, // )
    CloseBrace, // }
}

struct State {
    input: ~str,
    length: uint,
    transform_function_whitespace: bool,
    quirks_mode: bool,
    mut position: uint,
    mut errors: ~[~str]
}

fn is_eof(state: &State) -> bool {
    state.position >= state.length
}

fn current_char(state: &State) -> char {
    str::char_at(state.input, state.position)
}

fn consume_char(state: &State) -> char {
    let range = str::char_range_at(state.input, state.position);
    state.position = range.next;
    range.ch
}

// http://dev.w3.org/csswg/css3-syntax/#tokenization
pub fn tokenize(input: &str, transform_function_whitespace: bool,
            quirks_mode: bool) -> {tokens: ~[Token], parse_errors: ~[~str]} {
    let input = cssparser::preprocess(input);
    let state = &State {
        input: input, length: input.len(), quirks_mode: quirks_mode,
        transform_function_whitespace: transform_function_whitespace,
        position: 0, errors: ~[] };
    let mut tokens: ~[Token] = ~[];

    while !is_eof(state) {
        tokens.push(consume_token(state))
    }

    // Work around `error: moving out of mutable field`
    // TODO: find a cleaner way.
    let mut errors: ~[~str] = ~[];
    errors <-> state.errors;
    {tokens: tokens, parse_errors: errors}
}

// 3.3.4. Data state
fn consume_token(state: &State) -> Token {
    let c = consume_char(state);
    match c {
        '\t' | '\n' | '\x0C' | ' ' => {
            while !is_eof(state) {
                match current_char(state) {
                    '\t' | '\n' | '\x0C' | ' ' => state.position += 1,
                    _ => break,
                }
            }
            WhiteSpace
        },
        '"' => consume_quoted_string(state, false),
        '\'' => consume_quoted_string(state, true),
        '/' if !is_eof(state) && current_char(state) == '*'
            => consume_comment(state),
        ',' => Colon,
        ';' => Semicolon,
        '[' => OpenBraket,
        '(' => OpenParen,
        '{' => OpenBrace,
        ']' => CloseBraket,
        ')' => CloseParen,
        '}' => CloseBrace,
        'a'..'z' | 'A'..'Z' | '_' => consume_ident(state, c),
        c if c >= '\xA0' => consume_ident(state, c),  // Non-ASCII
        _ => Delim(c),
    }
}

// 3.3.5. Double-quote-string state
// 3.3.6. Single-quote-string state
fn consume_quoted_string(state: &State, single_quote: bool) -> Token {
    let mut string: ~str = ~"";
    loop {
        if is_eof(state) {
            state.errors.push(~"EOF in quoted string");
            return String(string);
        }
        match consume_char(state) {
            '"' if !single_quote => return String(string),
            '\'' if single_quote => return String(string),
            '\n' | '\x0C' => {
                state.errors.push(~"Newline in quoted string");
                return BadString
            },
            '\\' => {
                if is_eof(state) {
                    state.errors.push(~"EOF in quoted string");
                    return BadString
                }
                match current_char(state) {
                    // Consume quoted newline
                    '\n' | '\x0C' => state.position += 1,
                    _ =>  str::push_char(&mut string, consume_escape(state))
                }
            }
            c => str::push_char(&mut string, c),
        }
    }
}

// 3.3.9. Comment state
fn consume_comment(state: &State) -> Token {
    state.position += 1;  // consume the * in /*
    match str::find_str_from(state.input, "*/", state.position) {
        Some(end_position) => state.position = end_position + 2,
        None => {
            state.errors.push(~"EOF in comment");
            state.position = state.input.len();
        }
    }
    Comment
}

// 3.3.12. Ident state
// 3.3.13. Ident-rest state
fn consume_ident(state: &State, initial_char: char) -> Token {
    let mut string = str::from_char(initial_char);
    while !is_eof(state) {
        let c = current_char(state);
        let cc = match c {
            'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '-'  => {
                state.position += 1; c },
            _ if c >= '\xA0' => consume_char(state),  // Non-ASCII
            '\\' => {
                state.position += 1;
                if is_eof(state) { state.position -= 1; break }
                match current_char(state) {
                    '\n' | '\x0C' => { state.position -= 1; break },
                    _ => consume_escape(state)
                }
            },
            '\t' | '\n' | '\x0C' | ' ' if state.transform_function_whitespace
            => {
                state.position += 1;
                return handle_transform_function_whitespace(state, string)
            }
            '(' => {
                state.position += 1;
                // TODO: URLs
                return Function(string)
            },
            _ => break
        };
        str::push_char(&mut string, cc)
    }
    Ident(string)
}

// 3.3.14. Transform-function-whitespace state
fn handle_transform_function_whitespace(state: &State, string: ~str) -> Token {
    while !is_eof(state) {
        match current_char(state) {
            '\t' | '\n' | '\x0C' | ' ' => state.position += 1,
            '(' => { state.position += 1; return Function(string) }
            _ => break,
        }
    }
    // XXX I think the spec is wrong here.
    // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0266.html
    // Go back for one whitespace character.
    state.position -= 1;
    return Ident(string)
}

// 3.3.27. Consume an escaped character
// Assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed
// and that the next input character has already been verified
// to not be a newline or EOF.
fn consume_escape(state: &State) -> char {
    let c = consume_char(state);
    match c {
        '0'..'9' | 'A'..'F' | 'a'..'f' => {
            let mut hex = ~[c];
            while hex.len() < 6 && !is_eof(state) {
                let c = current_char(state);
                match c {
                    '0'..'9' | 'A'..'F' | 'a'..'f' => {
                        hex.push(c); state.position += 1 },
                    _ => break
                }
            }
            if !is_eof(state) {
                match current_char(state) {
                    '\t' | '\n' | '\x0C' | ' ' => state.position += 1,
                    _ => ()
                }
            }
            char_from_hex(hex)
        },
        c => c
    }
}

fn char_from_hex(hex: &[char]) -> char {
    let mut value = 0u;
    for hex.each |cc| {
        let c = *cc;
        value = value * 16 + c as uint - match c {
            '0'..'9' => '0' as uint,
            'A'..'F' => 'A' as uint - 10,
            'a'..'f' => 'a' as uint - 10,
            _ => fail
        }
    }
    if value == 0 || value > MAX_UNICODE {
        '\uFFFD'  // Replacement character
    } else {
        value as char
    }
}

#[test]
fn test_tokenizer() {

    fn assert_tokens(input: &str, expected_tokens: &[Token],
                     expected_errors: &[~str]) {
        assert_tokens_flags(
            input, false, false, expected_tokens, expected_errors)
    }

    fn assert_tokens_flags(
            input: &str,
            transform_function_whitespace: bool, quirks_mode: bool,
            expected_tokens: &[Token], expected_errors: &[~str]) {
        let result = tokenize(
            input, transform_function_whitespace, quirks_mode);
        let tokens: &[Token] = result.tokens;
        let parse_errors: &[~str] = result.parse_errors;
        if tokens != expected_tokens {
            fail fmt!("%? != %?", tokens, expected_tokens);
        }
        if parse_errors != expected_errors {
            fail fmt!("%? != %?", parse_errors, expected_errors);
        }
    }
    assert_tokens("", [], []);
    assert_tokens("?/", [Delim('?'), Delim('/')], []);
    assert_tokens("?/* Li/*psum… */", [Delim('?'), Comment], []);
    assert_tokens("?/* Li/*psum… *//", [Delim('?'), Comment, Delim('/')], []);
    assert_tokens("?/* Lipsum", [Delim('?'), Comment], [~"EOF in comment"]);
    assert_tokens("?/*", [Delim('?'), Comment], [~"EOF in comment"]);
    assert_tokens("[?}{)",
        [OpenBraket, Delim('?'), CloseBrace, OpenBrace, CloseParen], []);

    assert_tokens("(\n \t'Lore\\6d \"ipsu\\6D'",
        [OpenParen, WhiteSpace, String(~"Lorem\"ipsum")], []);
    assert_tokens("'\\''", [String(~"'")], []);
    assert_tokens("\"\\\"\"", [String(~"\"")], []);
    assert_tokens("\"\\\"", [String(~"\"")], [~"EOF in quoted string"]);
    assert_tokens("'\\", [BadString], [~"EOF in quoted string"]);
    assert_tokens("\"0\\0000000\"", [String(~"0\uFFFD0")], []);
    assert_tokens("\"0\\000000 0\"", [String(~"0\uFFFD0")], []);
    assert_tokens("'z\n'a", [BadString, String(~"a")],
        [~"Newline in quoted string", ~"EOF in quoted string"]);

    assert_tokens("Lorem\\ ipsu\\6D dolor sit",
        [Ident(~"Lorem ipsumdolor"), WhiteSpace, Ident(~"sit")], []);
    assert_tokens("foo\\", [Ident(~"foo"), Delim('\\')], []);
    assert_tokens("foo\\\nbar",
        [Ident(~"foo"), Delim('\\'), WhiteSpace, Ident(~"bar")], []);
    assert_tokens("func()", [Function(~"func"), CloseParen], []);
    assert_tokens("func ()",
        [Ident(~"func"), WhiteSpace, OpenParen, CloseParen], []);
    assert_tokens_flags("func ()", true, false,
        [Function(~"func"), CloseParen], []);
}
<|endoftext|>


<commit_before>use std::fs::{create_dir_all, File};
use std::io::Write;

use clap::ArgMatches;

use error::Result;

pub struct Repository<'a> {
    name: &'a str,
    terraform_source: &'a str,
}

impl<'a> Repository<'a> {
    pub fn new(matches: &'a ArgMatches) -> Self {
        Repository {
            name: matches.value_of("name").expect("clap should have required name"),
            terraform_source: matches.value_of("terraform-source").unwrap_or(
                concat!("github.com/InQuicker/kaws//terraform?ref=v", env!("CARGO_PKG_VERSION")),
            ),
        }
    }

    pub fn create(&self) -> Result {
        try!(create_dir_all(format!("{}/clusters", self.name)));
        try!(create_dir_all(format!("{}/pubkeys", self.name)));
        try!(create_dir_all(format!("{}/terraform", self.name)));

        let mut gitignore = try!(File::create(format!("{}/.gitignore", self.name)));
        try!(writeln!(&mut gitignore, ".terraform"));

        let mut main_tf = try!(File::create(format!("{}/terraform/main.tf", self.name)));
        try!(write!(
            &mut main_tf,
r#"module "kaws" {{
    source = "{}"

    domain = "${{var.domain}}"
    coreos_ami = "${{var.coreos_ami}}"
    cluster = "${{var.cluster}}"
    etcd_01_initial_cluster_state = "${{var.etcd_01_initial_cluster_state}}"
    etcd_02_initial_cluster_state = "${{var.etcd_02_initial_cluster_state}}"
    etcd_03_initial_cluster_state = "${{var.etcd_03_initial_cluster_state}}"
    instance_size = "${{var.instance_size}}"
    ssh_key = "${{var.ssh_key}}"
    version = "${{var.version}}"
    zone_id = "${{var.zone_id}}"
}}

variable "coreos_ami" {{
  description = "The AMI ID for the CoreOS image to use for servers, e.g. `ami-1234abcd`"
}}

variable "cluster" {{
  description = "The target cluster's name"
}}

variable "domain" {{
  description = "The domain name for the cluster"
}}

variable "etcd_01_initial_cluster_state" {{
  description = "The initial cluster state for the first etcd node. One of `new` or `existing`"
}}

variable "etcd_02_initial_cluster_state" {{
  description = "The initial cluster state for the second etcd node. One of `new` or `existing`"
}}

variable "etcd_03_initial_cluster_state" {{
  description = "The initial cluster state for the third etcd node. One of `new` or `existing`"
}}

variable "instance_size" {{
  description = "The EC2 instance size"
}}

variable "ssh_key" {{
  description = "Name of the SSH key in AWS that should have acccess to EC2 instances"
}}

variable "version" {{
  description = "Version of Kubernetes to use, e.g. 1.0.0"
}}

variable "zone_id" {{
  description = "Zone ID of the Route 53 hosted zone"
}}
"#,
            self.terraform_source,
        ));

        Ok(Some(format!("New repository \"{}\" created!", self.name)))
    }
}
<commit_msg>Don't create pubkeys directory.<commit_after>use std::fs::{create_dir_all, File};
use std::io::Write;

use clap::ArgMatches;

use error::Result;

pub struct Repository<'a> {
    name: &'a str,
    terraform_source: &'a str,
}

impl<'a> Repository<'a> {
    pub fn new(matches: &'a ArgMatches) -> Self {
        Repository {
            name: matches.value_of("name").expect("clap should have required name"),
            terraform_source: matches.value_of("terraform-source").unwrap_or(
                concat!("github.com/InQuicker/kaws//terraform?ref=v", env!("CARGO_PKG_VERSION")),
            ),
        }
    }

    pub fn create(&self) -> Result {
        try!(create_dir_all(format!("{}/clusters", self.name)));
        try!(create_dir_all(format!("{}/terraform", self.name)));

        let mut gitignore = try!(File::create(format!("{}/.gitignore", self.name)));
        try!(writeln!(&mut gitignore, ".terraform"));

        let mut main_tf = try!(File::create(format!("{}/terraform/main.tf", self.name)));
        try!(write!(
            &mut main_tf,
r#"module "kaws" {{
    source = "{}"

    domain = "${{var.domain}}"
    coreos_ami = "${{var.coreos_ami}}"
    cluster = "${{var.cluster}}"
    etcd_01_initial_cluster_state = "${{var.etcd_01_initial_cluster_state}}"
    etcd_02_initial_cluster_state = "${{var.etcd_02_initial_cluster_state}}"
    etcd_03_initial_cluster_state = "${{var.etcd_03_initial_cluster_state}}"
    instance_size = "${{var.instance_size}}"
    ssh_key = "${{var.ssh_key}}"
    version = "${{var.version}}"
    zone_id = "${{var.zone_id}}"
}}

variable "coreos_ami" {{
  description = "The AMI ID for the CoreOS image to use for servers, e.g. `ami-1234abcd`"
}}

variable "cluster" {{
  description = "The target cluster's name"
}}

variable "domain" {{
  description = "The domain name for the cluster"
}}

variable "etcd_01_initial_cluster_state" {{
  description = "The initial cluster state for the first etcd node. One of `new` or `existing`"
}}

variable "etcd_02_initial_cluster_state" {{
  description = "The initial cluster state for the second etcd node. One of `new` or `existing`"
}}

variable "etcd_03_initial_cluster_state" {{
  description = "The initial cluster state for the third etcd node. One of `new` or `existing`"
}}

variable "instance_size" {{
  description = "The EC2 instance size"
}}

variable "ssh_key" {{
  description = "Name of the SSH key in AWS that should have acccess to EC2 instances"
}}

variable "version" {{
  description = "Version of Kubernetes to use, e.g. 1.0.0"
}}

variable "zone_id" {{
  description = "Zone ID of the Route 53 hosted zone"
}}
"#,
            self.terraform_source,
        ));

        Ok(Some(format!("New repository \"{}\" created!", self.name)))
    }
}
<|endoftext|>


<commit_before>
use std::str;
use std::collections::HashMap;
use std::collections::VecDeque;

use key_builder::KeyBuilder;
use json_value::JsonValue;
use query::OrderInfo;
use snapshot::JsonFetcher;
use aggregates::AggregateFun;

#[derive(Clone)]
pub enum PathSegment {
    ObjectKey(String),
    Array(u64),
    ArrayAll,
}

#[derive(Clone)]
pub struct ReturnPath {
    path: Vec<PathSegment>,
}

impl ReturnPath {
    pub fn new() -> ReturnPath {
        ReturnPath { path: Vec::new() }
    }

    pub fn push_object_key(&mut self, key: String) {
        self.path.push(PathSegment::ObjectKey(key));
    }

    pub fn push_array(&mut self, index: u64) {
        self.path.push(PathSegment::Array(index));
    }

    pub fn push_array_all(&mut self) {
        self.path.push(PathSegment::ArrayAll);
    }

    pub fn to_key(&self) -> String {
        let mut key = String::new();
        for seg in self.path.iter() {
            match seg {
                &PathSegment::ObjectKey(ref str) => {
                    key.push('.');
                    for cc in str.chars() {
                        // Escape chars that conflict with delimiters
                        if "\\$.".contains(cc) {
                            key.push('\\');
                        }
                        key.push(cc);
                    }
                }
                &PathSegment::Array(ref i) => {
                    key.push('$');
                    key.push_str(&i.to_string());
                }
                &PathSegment::ArrayAll => {
                    key.push_str("$*");
                }
            }
        }
        key
    }

    pub fn nth(&self, i: usize) -> Option<&PathSegment> {
        if self.path.len() <= i {
            None
        } else {
            Some(&self.path[i])
        }
    }
}

/// Returnables are created from parsing the return statement in queries.
/// They nest inside of each other, with the outermost typically being a RetObject or RetArray.
pub trait Returnable {
    /// When a match is found, information about the match is passed to outer most Returnable
    /// and then each nested Returnable will fetch information about the document (fields or
    /// scores or bind variables etc) and convert them to JsonValues and add them to the result
    /// VecDeque.
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>);

    /// If aggregates are used each Returnable needs to return information about the
    /// aggregate function it's using and the default value.
    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>);

    /// If a query has a order clause then we want to match the fields being ordered with
    /// fields being returned. We pass the ordering info by the path of the ordered fields
    /// or scores and Returnables that have the same path will take the order
    /// information. Any fields not matching a returnable are then added to special hidden
    /// Returnable (RetHidden) which fetches those fields for ordering but not rendered or
    /// returned.
    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>);

    /// Each Returnable will return the ordering direction in the same slot as the returnable
    /// so that later after fetching they will be ordered by QueryResults after fetching but
    /// converting to the final json result.
    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>);

    /// This is the final step of a Returnable. The previous fetched JsonValues are now
    /// rendered with other ornamental json elements.
    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue;
}

/// A static Json Object the can contain another number of fields and nested returnables.
pub struct RetObject {
    pub fields: Vec<(String, Box<Returnable>)>,
}

impl Returnable for RetObject {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        for &(ref _key, ref field) in self.fields.iter() {
            field.fetch_result(fetcher, seq, score, bind_var_keys, result);
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        for &(ref _key, ref field) in self.fields.iter() {
            field.get_aggregate_funs(funs);
        }
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        for &mut (ref _key, ref mut field) in self.fields.iter_mut() {
            field.take_order_for_matching_fields(map);
        }
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        for &mut (ref mut _key, ref mut field) in self.fields.iter_mut() {
            field.get_ordering(orders);
        }
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        let mut vec = Vec::with_capacity(self.fields.len());
        for &(ref key, ref returnable) in self.fields.iter() {
            vec.push((key.clone(), returnable.json_result(results)));
        }
        JsonValue::Object(vec)
    }
}

/// A static Json array the can contain another number of nested Returnables.
pub struct RetArray {
    pub slots: Vec<Box<Returnable>>,
}

impl Returnable for RetArray {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        for ref slot in self.slots.iter() {
            slot.fetch_result(fetcher, seq, score, bind_var_keys, result);
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        for ref slot in self.slots.iter() {
            slot.get_aggregate_funs(funs);
        }
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        for slot in self.slots.iter_mut() {
            slot.take_order_for_matching_fields(map);
        }
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        for ref mut slot in self.slots.iter_mut() {
            slot.get_ordering(orders);
        }
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        let mut vec = Vec::with_capacity(self.slots.len());
        for slot in self.slots.iter() {
            vec.push(slot.json_result(results));
        }
        JsonValue::Array(vec)
    }
}

/// A special returnable that only fetches values for later ordering but never renders
/// them back to the caller.
pub struct RetHidden {
    pub unrendered: Vec<Box<Returnable>>,
    pub visible: Box<Returnable>,
}

impl Returnable for RetHidden {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        for ref unrendered in self.unrendered.iter() {
            unrendered.fetch_result(fetcher, seq, score, bind_var_keys, result);
        }

        self.visible
            .fetch_result(fetcher, seq, score, bind_var_keys, result);
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        self.visible.get_aggregate_funs(funs);
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.visible.take_order_for_matching_fields(map);
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        for ref mut unrendered in self.unrendered.iter_mut() {
            unrendered.get_ordering(orders);
        }

        self.visible.get_ordering(orders);
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        for _n in 0..self.unrendered.len() {
            // we already ordered at this point, now discard the values
            results.pop_front();
        }
        self.visible.json_result(results)
    }
}

/// A literal JsonValue. Number, String, Null, True or False. Just in case the query
/// wants to return something that doesn't come from a document.
pub struct RetLiteral {
    pub json: JsonValue,
}

impl Returnable for RetLiteral {
    fn fetch_result(&self,
                    _fetcher: &mut JsonFetcher,
                    _seq: u64,
                    _score: f32,
                    _bind_var_keys: &HashMap<String, Vec<String>>,
                    _result: &mut VecDeque<JsonValue>) {
    }

    fn get_aggregate_funs(&self, _funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        //noop
    }

    fn take_order_for_matching_fields(&mut self, _map: &mut HashMap<String, OrderInfo>) {
        //noop
    }

    fn get_ordering(&mut self, _orders: &mut Vec<Option<OrderInfo>>) {
        //noop
    }

    fn json_result(&self, _results: &mut VecDeque<JsonValue>) -> JsonValue {
        self.json.clone()
    }
}

/// A value from a document. It knows the path it wants to fetch and loads the value from the
/// stored original document.
pub struct RetValue {
    pub rp: ReturnPath,
    pub ag: Option<(AggregateFun, JsonValue)>,
    pub default: JsonValue,
    pub order_info: Option<OrderInfo>,
}

impl Returnable for RetValue {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    _score: f32,
                    _bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        if Some((AggregateFun::Count, JsonValue::Null)) == self.ag {
            //don't fetch anything for count(). just stick in a null
            result.push_back(JsonValue::Null);
        }
        let mut kb = KeyBuilder::new();
        if let Some(json) = fetcher.fetch(seq, &mut kb, &self.rp) {
            result.push_back(json);
        } else {
            result.push_back(self.default.clone());
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        funs.push(self.ag.clone());
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.order_info = map.remove(&self.rp.to_key());
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        orders.push(self.order_info.take());
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        if let Some(json) = results.pop_front() {
            json
        } else {
            panic!("missing result!");
        }
    }
}

/// A bind variable. If a bind variable was matched it will be fetched then it's path is
/// added to the bind_var_keys passed into fetch_result(). This will load the values from the
/// original document and return it.
pub struct RetBind {
    pub bind_name: String,
    pub extra_rp: ReturnPath,
    pub ag: Option<(AggregateFun, JsonValue)>,
    pub default: JsonValue,
    pub order_info: Option<OrderInfo>,
}

impl Returnable for RetBind {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    _score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {

        if let Some(value_keys) = bind_var_keys.get(&self.bind_name) {
            let mut array = Vec::with_capacity(value_keys.len());
            for base_key in value_keys {
                let mut kb = KeyBuilder::new();
                kb.parse_value_key_path_only(KeyBuilder::value_key_path_only_from_str(&base_key));

                if let Some(json) = fetcher.fetch(seq, &mut kb, &self.extra_rp) {
                    array.push(json);
                } else {
                    array.push(self.default.clone());
                }
            }
            result.push_back(JsonValue::Array(array));
        } else {
            result.push_back(JsonValue::Array(vec![self.default.clone()]));
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        funs.push(self.ag.clone());
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.order_info = map.remove(&(self.bind_name.to_string() + &self.extra_rp.to_key()));
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        orders.push(self.order_info.take());
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        if let Some(json) = results.pop_front() {
            json
        } else {
            panic!("missing bind result!");
        }
    }
}

/// Returns a relevency score for a match.
pub struct RetScore {
    pub order_info: Option<OrderInfo>,
}

impl Returnable for RetScore {
    fn fetch_result(&self,
                    _fetcher: &mut JsonFetcher,
                    _seq: u64,
                    score: f32,
                    _bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        result.push_back(JsonValue::Number(score as f64));
    }

    fn get_aggregate_funs(&self, _funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        // noop
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.order_info = map.remove("score()");
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        orders.push(self.order_info.take());
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        if let Some(json) = results.pop_front() {
            json
        } else {
            panic!("missing score result!");
        }
    }
}
<commit_msg>Fix serious performance problem with count()<commit_after>
use std::str;
use std::collections::HashMap;
use std::collections::VecDeque;

use key_builder::KeyBuilder;
use json_value::JsonValue;
use query::OrderInfo;
use snapshot::JsonFetcher;
use aggregates::AggregateFun;

#[derive(Clone)]
pub enum PathSegment {
    ObjectKey(String),
    Array(u64),
    ArrayAll,
}

#[derive(Clone)]
pub struct ReturnPath {
    path: Vec<PathSegment>,
}

impl ReturnPath {
    pub fn new() -> ReturnPath {
        ReturnPath { path: Vec::new() }
    }

    pub fn push_object_key(&mut self, key: String) {
        self.path.push(PathSegment::ObjectKey(key));
    }

    pub fn push_array(&mut self, index: u64) {
        self.path.push(PathSegment::Array(index));
    }

    pub fn push_array_all(&mut self) {
        self.path.push(PathSegment::ArrayAll);
    }

    pub fn to_key(&self) -> String {
        let mut key = String::new();
        for seg in self.path.iter() {
            match seg {
                &PathSegment::ObjectKey(ref str) => {
                    key.push('.');
                    for cc in str.chars() {
                        // Escape chars that conflict with delimiters
                        if "\\$.".contains(cc) {
                            key.push('\\');
                        }
                        key.push(cc);
                    }
                }
                &PathSegment::Array(ref i) => {
                    key.push('$');
                    key.push_str(&i.to_string());
                }
                &PathSegment::ArrayAll => {
                    key.push_str("$*");
                }
            }
        }
        key
    }

    pub fn nth(&self, i: usize) -> Option<&PathSegment> {
        if self.path.len() <= i {
            None
        } else {
            Some(&self.path[i])
        }
    }
}

/// Returnables are created from parsing the return statement in queries.
/// They nest inside of each other, with the outermost typically being a RetObject or RetArray.
pub trait Returnable {
    /// When a match is found, information about the match is passed to outer most Returnable
    /// and then each nested Returnable will fetch information about the document (fields or
    /// scores or bind variables etc) and convert them to JsonValues and add them to the result
    /// VecDeque.
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>);

    /// If aggregates are used each Returnable needs to return information about the
    /// aggregate function it's using and the default value.
    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>);

    /// If a query has a order clause then we want to match the fields being ordered with
    /// fields being returned. We pass the ordering info by the path of the ordered fields
    /// or scores and Returnables that have the same path will take the order
    /// information. Any fields not matching a returnable are then added to special hidden
    /// Returnable (RetHidden) which fetches those fields for ordering but not rendered or
    /// returned.
    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>);

    /// Each Returnable will return the ordering direction in the same slot as the returnable
    /// so that later after fetching they will be ordered by QueryResults after fetching but
    /// converting to the final json result.
    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>);

    /// This is the final step of a Returnable. The previous fetched JsonValues are now
    /// rendered with other ornamental json elements.
    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue;
}

/// A static Json Object the can contain another number of fields and nested returnables.
pub struct RetObject {
    pub fields: Vec<(String, Box<Returnable>)>,
}

impl Returnable for RetObject {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        for &(ref _key, ref field) in self.fields.iter() {
            field.fetch_result(fetcher, seq, score, bind_var_keys, result);
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        for &(ref _key, ref field) in self.fields.iter() {
            field.get_aggregate_funs(funs);
        }
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        for &mut (ref _key, ref mut field) in self.fields.iter_mut() {
            field.take_order_for_matching_fields(map);
        }
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        for &mut (ref mut _key, ref mut field) in self.fields.iter_mut() {
            field.get_ordering(orders);
        }
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        let mut vec = Vec::with_capacity(self.fields.len());
        for &(ref key, ref returnable) in self.fields.iter() {
            vec.push((key.clone(), returnable.json_result(results)));
        }
        JsonValue::Object(vec)
    }
}

/// A static Json array the can contain another number of nested Returnables.
pub struct RetArray {
    pub slots: Vec<Box<Returnable>>,
}

impl Returnable for RetArray {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        for ref slot in self.slots.iter() {
            slot.fetch_result(fetcher, seq, score, bind_var_keys, result);
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        for ref slot in self.slots.iter() {
            slot.get_aggregate_funs(funs);
        }
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        for slot in self.slots.iter_mut() {
            slot.take_order_for_matching_fields(map);
        }
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        for ref mut slot in self.slots.iter_mut() {
            slot.get_ordering(orders);
        }
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        let mut vec = Vec::with_capacity(self.slots.len());
        for slot in self.slots.iter() {
            vec.push(slot.json_result(results));
        }
        JsonValue::Array(vec)
    }
}

/// A special returnable that only fetches values for later ordering but never renders
/// them back to the caller.
pub struct RetHidden {
    pub unrendered: Vec<Box<Returnable>>,
    pub visible: Box<Returnable>,
}

impl Returnable for RetHidden {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        for ref unrendered in self.unrendered.iter() {
            unrendered.fetch_result(fetcher, seq, score, bind_var_keys, result);
        }

        self.visible
            .fetch_result(fetcher, seq, score, bind_var_keys, result);
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        self.visible.get_aggregate_funs(funs);
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.visible.take_order_for_matching_fields(map);
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        for ref mut unrendered in self.unrendered.iter_mut() {
            unrendered.get_ordering(orders);
        }

        self.visible.get_ordering(orders);
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        for _n in 0..self.unrendered.len() {
            // we already ordered at this point, now discard the values
            results.pop_front();
        }
        self.visible.json_result(results)
    }
}

/// A literal JsonValue. Number, String, Null, True or False. Just in case the query
/// wants to return something that doesn't come from a document.
pub struct RetLiteral {
    pub json: JsonValue,
}

impl Returnable for RetLiteral {
    fn fetch_result(&self,
                    _fetcher: &mut JsonFetcher,
                    _seq: u64,
                    _score: f32,
                    _bind_var_keys: &HashMap<String, Vec<String>>,
                    _result: &mut VecDeque<JsonValue>) {
    }

    fn get_aggregate_funs(&self, _funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        //noop
    }

    fn take_order_for_matching_fields(&mut self, _map: &mut HashMap<String, OrderInfo>) {
        //noop
    }

    fn get_ordering(&mut self, _orders: &mut Vec<Option<OrderInfo>>) {
        //noop
    }

    fn json_result(&self, _results: &mut VecDeque<JsonValue>) -> JsonValue {
        self.json.clone()
    }
}

/// A value from a document. It knows the path it wants to fetch and loads the value from the
/// stored original document.
pub struct RetValue {
    pub rp: ReturnPath,
    pub ag: Option<(AggregateFun, JsonValue)>,
    pub default: JsonValue,
    pub order_info: Option<OrderInfo>,
}

impl Returnable for RetValue {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    _score: f32,
                    _bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        if Some((AggregateFun::Count, JsonValue::Null)) == self.ag {
            //don't fetch anything for count(). just stick in a null
            result.push_back(JsonValue::Null);
            return;
        }
        let mut kb = KeyBuilder::new();
        if let Some(json) = fetcher.fetch(seq, &mut kb, &self.rp) {
            result.push_back(json);
        } else {
            result.push_back(self.default.clone());
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        funs.push(self.ag.clone());
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.order_info = map.remove(&self.rp.to_key());
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        orders.push(self.order_info.take());
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        if let Some(json) = results.pop_front() {
            json
        } else {
            panic!("missing result!");
        }
    }
}

/// A bind variable. If a bind variable was matched it will be fetched then it's path is
/// added to the bind_var_keys passed into fetch_result(). This will load the values from the
/// original document and return it.
pub struct RetBind {
    pub bind_name: String,
    pub extra_rp: ReturnPath,
    pub ag: Option<(AggregateFun, JsonValue)>,
    pub default: JsonValue,
    pub order_info: Option<OrderInfo>,
}

impl Returnable for RetBind {
    fn fetch_result(&self,
                    fetcher: &mut JsonFetcher,
                    seq: u64,
                    _score: f32,
                    bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {

        if let Some(value_keys) = bind_var_keys.get(&self.bind_name) {
            let mut array = Vec::with_capacity(value_keys.len());
            for base_key in value_keys {
                let mut kb = KeyBuilder::new();
                kb.parse_value_key_path_only(KeyBuilder::value_key_path_only_from_str(&base_key));

                if let Some(json) = fetcher.fetch(seq, &mut kb, &self.extra_rp) {
                    array.push(json);
                } else {
                    array.push(self.default.clone());
                }
            }
            result.push_back(JsonValue::Array(array));
        } else {
            result.push_back(JsonValue::Array(vec![self.default.clone()]));
        }
    }

    fn get_aggregate_funs(&self, funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        funs.push(self.ag.clone());
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.order_info = map.remove(&(self.bind_name.to_string() + &self.extra_rp.to_key()));
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        orders.push(self.order_info.take());
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        if let Some(json) = results.pop_front() {
            json
        } else {
            panic!("missing bind result!");
        }
    }
}

/// Returns a relevency score for a match.
pub struct RetScore {
    pub order_info: Option<OrderInfo>,
}

impl Returnable for RetScore {
    fn fetch_result(&self,
                    _fetcher: &mut JsonFetcher,
                    _seq: u64,
                    score: f32,
                    _bind_var_keys: &HashMap<String, Vec<String>>,
                    result: &mut VecDeque<JsonValue>) {
        result.push_back(JsonValue::Number(score as f64));
    }

    fn get_aggregate_funs(&self, _funs: &mut Vec<Option<(AggregateFun, JsonValue)>>) {
        // noop
    }

    fn take_order_for_matching_fields(&mut self, map: &mut HashMap<String, OrderInfo>) {
        self.order_info = map.remove("score()");
    }

    fn get_ordering(&mut self, orders: &mut Vec<Option<OrderInfo>>) {
        orders.push(self.order_info.take());
    }

    fn json_result(&self, results: &mut VecDeque<JsonValue>) -> JsonValue {
        if let Some(json) = results.pop_front() {
            json
        } else {
            panic!("missing score result!");
        }
    }
}
<|endoftext|>


<commit_before>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # RPC Server
//!
//! Functions and data to handle RPC calls

use std::io::IoResult;
use serialize::json;

use bitcoin::network::serialize::Serializable;
use bitcoin::util::hash::Sha256dHash;
use jsonrpc;
use jsonrpc::error::{standard_error, InvalidParams, MethodNotFound};
use phf::PhfOrderedMap;

use bitcoind::IdleState;

pub type JsonResult = jsonrpc::JsonResult<json::Json>;

/// A single RPC command
pub struct RpcCall {
  name: &'static str,
  desc: &'static str,
  usage: &'static str,
  call: fn(&RpcCall, &mut IdleState, Vec<json::Json>) -> JsonResult
}

// Forget you saw this macro...just forget it.
macro_rules! rpc_calls(
  ( $( #[doc=$doc:tt]
       #[usage=$usage:tt]
       pub fn $name:ident($($param:tt: $paramty:ty),+) $code:expr),+ ) => (
    $(
      // `tt` token trees can only be passed to a macro. On the other hand,
      // there is no other type which will accept a doccomment as a token.
      // So we accept a tt and hand it to the macro_rules! macro ;)
      //
      // Notice that we are using the same name as the outer macro...this
      // means that the macro can only be called once, since we effectively
      // overwrite it here.
      macro_rules! rpc_calls( () => (
        // I don't really want these to be public, but they don't show up
        // in the output of `cargo doc` otherwise.
        #[doc=$doc]
        pub fn $name($($param: $paramty),+) -> JsonResult { $code }
      ))
      rpc_calls!()
    )+
    // Let's do it again!
    macro_rules! rpc_calls( () => (
      static RPC_CALLS: PhfOrderedMap<&'static str, RpcCall> = phf_ordered_map! {
        $(stringify!($name) => RpcCall {
            name: stringify!($name),
            desc: $doc,
            usage: $usage,
            call: $name
          }
        ),+
      };
    ))
    rpc_calls!()
    // Erase the dummy macro, to avoid confusing errors in case somebody
    // tries to use it outside of this macro.
    macro_rules! rpc_calls(
      () => (Sorry, you can only call rpc_calls! once.)
    )
  )
)

// Main RPC call list
rpc_calls!{
  #[doc="Fetches a list of commands"]
  #[usage=""]
  pub fn help(_: &RpcCall, _: &mut IdleState, _: Vec<json::Json>) {
    use std::collections::TreeMap;

    let mut ret = TreeMap::new();
    for call in RPC_CALLS.values() {
      let mut obj = TreeMap::new();
      obj.insert("description".to_string(), json::String(call.desc.to_string()));
      obj.insert("usage".to_string(), json::String(call.usage.to_string()));
      ret.insert(call.name.to_string(), json::Object(obj));
    }
    Ok(json::Object(ret))
  },

  #[doc="Gets the current number of unspent outputs on the blockchain."]
  #[usage=""]
  pub fn getutxocount(_: &RpcCall, idle_state: &mut IdleState, _: Vec<json::Json>) {
    Ok(json::Number(idle_state.utxo_set.read().n_utxos() as f64))
  },

  #[doc="Gets the length of the longest chain."]
  #[usage="[start hash]"]
  pub fn getblockcount(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      0 => {
        let blockchain = idle_state.blockchain.read();
        // Subtract 1 from the hash since the genesis counts as block 0
        Ok(json::Number(blockchain.iter(blockchain.genesis_hash()).count() as f64 - 1))
      }
      1 => {
        use serialize::hex::FromHex;

        let blockchain = idle_state.blockchain.read();
        let hex_hash = try!(jsonrpc::decode::json_decode_string(&params[0]));
        match hex_hash.as_slice().from_hex() {
          Ok(hash) => {
            // We reverse the iterator since the user will give us a big-endian string,
            // while everything internal is little endian.
            let hash: IoResult<Sha256dHash> = Serializable::deserialize(hash.iter().rev().map(|n| *n));
            match hash {
              // Subtract 1 from the hash since the genesis counts as block 0
              Ok(hash) => Ok(json::Number(blockchain.iter(hash).count() as f64 - 1)),
              Err(_) => Err(standard_error(InvalidParams,
                                           Some(json::String(format!("Hash must be 64-character hex string, not {}", hex_hash)))))
            }
          }
          Err(_) => Err(standard_error(InvalidParams,
                                       Some(json::String(format!("Hash must be 64-character hex string, not {}", hex_hash)))))
        }
      }
      _ => usage_error(rpc)
    }
  }
}

/// Generates a `usage` error message
fn usage_error(rpc: &RpcCall) -> JsonResult {
  Err(standard_error(InvalidParams,
                     Some(json::String(format!("Usage: {} {}", rpc.name, rpc.usage)))))
}

/// Handles a JSON-RPC request, returning a result to be given back to the peer
pub fn handle_rpc(request: jsonrpc::Request, idle_state: &mut IdleState) -> JsonResult {
  let method = request.method.as_slice();
  match RPC_CALLS.find_equiv(&method) {
    Some(rpc) => (rpc.call)(rpc, idle_state, request.params),
    None => Err(standard_error(MethodNotFound,
                               Some(json::String(request.method.clone()))))
  }
}

<commit_msg>Fix off-by-1 error in getblockcount<commit_after>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # RPC Server
//!
//! Functions and data to handle RPC calls

use std::io::IoResult;
use serialize::json;

use bitcoin::network::serialize::Serializable;
use bitcoin::util::hash::Sha256dHash;
use jsonrpc;
use jsonrpc::error::{standard_error, InvalidParams, MethodNotFound};
use phf::PhfOrderedMap;

use bitcoind::IdleState;

pub type JsonResult = jsonrpc::JsonResult<json::Json>;

/// A single RPC command
pub struct RpcCall {
  name: &'static str,
  desc: &'static str,
  usage: &'static str,
  call: fn(&RpcCall, &mut IdleState, Vec<json::Json>) -> JsonResult
}

// Forget you saw this macro...just forget it.
macro_rules! rpc_calls(
  ( $( #[doc=$doc:tt]
       #[usage=$usage:tt]
       pub fn $name:ident($($param:tt: $paramty:ty),+) $code:expr),+ ) => (
    $(
      // `tt` token trees can only be passed to a macro. On the other hand,
      // there is no other type which will accept a doccomment as a token.
      // So we accept a tt and hand it to the macro_rules! macro ;)
      //
      // Notice that we are using the same name as the outer macro...this
      // means that the macro can only be called once, since we effectively
      // overwrite it here.
      macro_rules! rpc_calls( () => (
        // I don't really want these to be public, but they don't show up
        // in the output of `cargo doc` otherwise.
        #[doc=$doc]
        pub fn $name($($param: $paramty),+) -> JsonResult { $code }
      ))
      rpc_calls!()
    )+
    // Let's do it again!
    macro_rules! rpc_calls( () => (
      static RPC_CALLS: PhfOrderedMap<&'static str, RpcCall> = phf_ordered_map! {
        $(stringify!($name) => RpcCall {
            name: stringify!($name),
            desc: $doc,
            usage: $usage,
            call: $name
          }
        ),+
      };
    ))
    rpc_calls!()
    // Erase the dummy macro, to avoid confusing errors in case somebody
    // tries to use it outside of this macro.
    macro_rules! rpc_calls(
      () => (Sorry, you can only call rpc_calls! once.)
    )
  )
)

// Main RPC call list
rpc_calls!{
  #[doc="Fetches a list of commands"]
  #[usage=""]
  pub fn help(_: &RpcCall, _: &mut IdleState, _: Vec<json::Json>) {
    use std::collections::TreeMap;

    let mut ret = TreeMap::new();
    for call in RPC_CALLS.values() {
      let mut obj = TreeMap::new();
      obj.insert("description".to_string(), json::String(call.desc.to_string()));
      obj.insert("usage".to_string(), json::String(call.usage.to_string()));
      ret.insert(call.name.to_string(), json::Object(obj));
    }
    Ok(json::Object(ret))
  },

  #[doc="Gets the current number of unspent outputs on the blockchain."]
  #[usage=""]
  pub fn getutxocount(_: &RpcCall, idle_state: &mut IdleState, _: Vec<json::Json>) {
    Ok(json::Number(idle_state.utxo_set.read().n_utxos() as f64))
  },

  #[doc="Gets the length of the longest chain."]
  #[usage="[start hash]"]
  pub fn getblockcount(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      0 => {
        let blockchain = idle_state.blockchain.read();
        // Subtract 1 from the hash since the genesis counts as block 0
        Ok(json::Number(blockchain.iter(blockchain.genesis_hash()).count() as f64 - 1.0))
      }
      1 => {
        use serialize::hex::FromHex;

        let blockchain = idle_state.blockchain.read();
        let hex_hash = try!(jsonrpc::decode::json_decode_string(&params[0]));
        match hex_hash.as_slice().from_hex() {
          Ok(hash) => {
            // We reverse the iterator since the user will give us a big-endian string,
            // while everything internal is little endian.
            let hash: IoResult<Sha256dHash> = Serializable::deserialize(hash.iter().rev().map(|n| *n));
            match hash {
              // Subtract 1 from the hash since the genesis counts as block 0
              Ok(hash) => Ok(json::Number(blockchain.iter(hash).count() as f64 - 1.0)),
              Err(_) => Err(standard_error(InvalidParams,
                                           Some(json::String(format!("Hash must be 64-character hex string, not {}", hex_hash)))))
            }
          }
          Err(_) => Err(standard_error(InvalidParams,
                                       Some(json::String(format!("Hash must be 64-character hex string, not {}", hex_hash)))))
        }
      }
      _ => usage_error(rpc)
    }
  }
}

/// Generates a `usage` error message
fn usage_error(rpc: &RpcCall) -> JsonResult {
  Err(standard_error(InvalidParams,
                     Some(json::String(format!("Usage: {} {}", rpc.name, rpc.usage)))))
}

/// Handles a JSON-RPC request, returning a result to be given back to the peer
pub fn handle_rpc(request: jsonrpc::Request, idle_state: &mut IdleState) -> JsonResult {
  let method = request.method.as_slice();
  match RPC_CALLS.find_equiv(&method) {
    Some(rpc) => (rpc.call)(rpc, idle_state, request.params),
    None => Err(standard_error(MethodNotFound,
                               Some(json::String(request.method.clone()))))
  }
}

<|endoftext|>


<commit_before>use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};

use {Num, NumCast};
use bounds::Bounded;
use ops::checked::*;
use ops::saturating::Saturating;

pub trait PrimInt
    : Sized
    + Copy
    + Num + NumCast
    + Bounded
    + PartialOrd + Ord + Eq
    + Not<Output=Self>
    + BitAnd<Output=Self>
    + BitOr<Output=Self>
    + BitXor<Output=Self>
    + Shl<usize, Output=Self>
    + Shr<usize, Output=Self>
    + CheckedAdd<Output=Self>
    + CheckedSub<Output=Self>
    + CheckedMul<Output=Self>
    + CheckedDiv<Output=Self>
    + Saturating
{
    /// Returns the number of ones in the binary representation of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b01001100u8;
    ///
    /// assert_eq!(n.count_ones(), 3);
    /// ```
    fn count_ones(self) -> u32;

    /// Returns the number of zeros in the binary representation of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b01001100u8;
    ///
    /// assert_eq!(n.count_zeros(), 5);
    /// ```
    fn count_zeros(self) -> u32;

    /// Returns the number of leading zeros in the binary representation
    /// of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b0101000u16;
    ///
    /// assert_eq!(n.leading_zeros(), 10);
    /// ```
    fn leading_zeros(self) -> u32;

    /// Returns the number of trailing zeros in the binary representation
    /// of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b0101000u16;
    ///
    /// assert_eq!(n.trailing_zeros(), 3);
    /// ```
    fn trailing_zeros(self) -> u32;

    /// Shifts the bits to the left by a specified amount amount, `n`, wrapping
    /// the truncated bits to the end of the resulting integer.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0x3456789ABCDEF012u64;
    ///
    /// assert_eq!(n.rotate_left(12), m);
    /// ```
    fn rotate_left(self, n: u32) -> Self;

    /// Shifts the bits to the right by a specified amount amount, `n`, wrapping
    /// the truncated bits to the beginning of the resulting integer.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0xDEF0123456789ABCu64;
    ///
    /// assert_eq!(n.rotate_right(12), m);
    /// ```
    fn rotate_right(self, n: u32) -> Self;

    /// Shifts the bits to the left by a specified amount amount, `n`, filling
    /// zeros in the least significant bits.
    ///
    /// This is bitwise equivalent to signed `Shl`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0x3456789ABCDEF000u64;
    ///
    /// assert_eq!(n.signed_shl(12), m);
    /// ```
    fn signed_shl(self, n: u32) -> Self;

    /// Shifts the bits to the right by a specified amount amount, `n`, copying
    /// the "sign bit" in the most significant bits even for unsigned types.
    ///
    /// This is bitwise equivalent to signed `Shr`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0xFEDCBA9876543210u64;
    /// let m = 0xFFFFEDCBA9876543u64;
    ///
    /// assert_eq!(n.signed_shr(12), m);
    /// ```
    fn signed_shr(self, n: u32) -> Self;

    /// Shifts the bits to the left by a specified amount amount, `n`, filling
    /// zeros in the least significant bits.
    ///
    /// This is bitwise equivalent to unsigned `Shl`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFi64;
    /// let m = 0x3456789ABCDEF000i64;
    ///
    /// assert_eq!(n.unsigned_shl(12), m);
    /// ```
    fn unsigned_shl(self, n: u32) -> Self;

    /// Shifts the bits to the right by a specified amount amount, `n`, filling
    /// zeros in the most significant bits.
    ///
    /// This is bitwise equivalent to unsigned `Shr`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0xFEDCBA9876543210i64;
    /// let m = 0x000FEDCBA9876543i64;
    ///
    /// assert_eq!(n.unsigned_shr(12), m);
    /// ```
    fn unsigned_shr(self, n: u32) -> Self;

    /// Reverses the byte order of the integer.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0xEFCDAB8967452301u64;
    ///
    /// assert_eq!(n.swap_bytes(), m);
    /// ```
    fn swap_bytes(self) -> Self;

    /// Convert an integer from big endian to the target's endianness.
    ///
    /// On big endian this is a no-op. On little endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "big") {
    ///     assert_eq!(u64::from_be(n), n)
    /// } else {
    ///     assert_eq!(u64::from_be(n), n.swap_bytes())
    /// }
    /// ```
    fn from_be(x: Self) -> Self;

    /// Convert an integer from little endian to the target's endianness.
    ///
    /// On little endian this is a no-op. On big endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "little") {
    ///     assert_eq!(u64::from_le(n), n)
    /// } else {
    ///     assert_eq!(u64::from_le(n), n.swap_bytes())
    /// }
    /// ```
    fn from_le(x: Self) -> Self;

    /// Convert `self` to big endian from the target's endianness.
    ///
    /// On big endian this is a no-op. On little endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "big") {
    ///     assert_eq!(n.to_be(), n)
    /// } else {
    ///     assert_eq!(n.to_be(), n.swap_bytes())
    /// }
    /// ```
    fn to_be(self) -> Self;

    /// Convert `self` to little endian from the target's endianness.
    ///
    /// On little endian this is a no-op. On big endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "little") {
    ///     assert_eq!(n.to_le(), n)
    /// } else {
    ///     assert_eq!(n.to_le(), n.swap_bytes())
    /// }
    /// ```
    fn to_le(self) -> Self;

    /// Raises self to the power of `exp`, using exponentiation by squaring.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// assert_eq!(2i32.pow(4), 16);
    /// ```
    fn pow(self, exp: u32) -> Self;
}

macro_rules! prim_int_impl {
    ($T:ty, $S:ty, $U:ty) => (
        impl PrimInt for $T {
            #[inline]
            fn count_ones(self) -> u32 {
                <$T>::count_ones(self)
            }

            #[inline]
            fn count_zeros(self) -> u32 {
                <$T>::count_zeros(self)
            }

            #[inline]
            fn leading_zeros(self) -> u32 {
                <$T>::leading_zeros(self)
            }

            #[inline]
            fn trailing_zeros(self) -> u32 {
                <$T>::trailing_zeros(self)
            }

            #[inline]
            fn rotate_left(self, n: u32) -> Self {
                <$T>::rotate_left(self, n)
            }

            #[inline]
            fn rotate_right(self, n: u32) -> Self {
                <$T>::rotate_right(self, n)
            }

            #[inline]
            fn signed_shl(self, n: u32) -> Self {
                ((self as $S) << n) as $T
            }

            #[inline]
            fn signed_shr(self, n: u32) -> Self {
                ((self as $S) >> n) as $T
            }

            #[inline]
            fn unsigned_shl(self, n: u32) -> Self {
                ((self as $U) << n) as $T
            }

            #[inline]
            fn unsigned_shr(self, n: u32) -> Self {
                ((self as $U) >> n) as $T
            }

            #[inline]
            fn swap_bytes(self) -> Self {
                <$T>::swap_bytes(self)
            }

            #[inline]
            fn from_be(x: Self) -> Self {
                <$T>::from_be(x)
            }

            #[inline]
            fn from_le(x: Self) -> Self {
                <$T>::from_le(x)
            }

            #[inline]
            fn to_be(self) -> Self {
                <$T>::to_be(self)
            }

            #[inline]
            fn to_le(self) -> Self {
                <$T>::to_le(self)
            }

            #[inline]
            fn pow(self, exp: u32) -> Self {
                <$T>::pow(self, exp)
            }
        }
    )
}

// prim_int_impl!(type, signed, unsigned);
prim_int_impl!(u8,    i8,    u8);
prim_int_impl!(u16,   i16,   u16);
prim_int_impl!(u32,   i32,   u32);
prim_int_impl!(u64,   i64,   u64);
prim_int_impl!(usize, isize, usize);
prim_int_impl!(i8,    i8,    u8);
prim_int_impl!(i16,   i16,   u16);
prim_int_impl!(i32,   i32,   u32);
prim_int_impl!(i64,   i64,   u64);
prim_int_impl!(isize, isize, usize);
<commit_msg>impl PrimInt for Wrapping<T><commit_after>use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use std::num::Wrapping;

use {Num, NumCast};
use bounds::Bounded;
use ops::checked::*;
use ops::saturating::Saturating;

pub trait PrimInt
    : Sized
    + Copy
    + Num + NumCast
    + Bounded
    + PartialOrd + Ord + Eq
    + Not<Output=Self>
    + BitAnd<Output=Self>
    + BitOr<Output=Self>
    + BitXor<Output=Self>
    + Shl<usize, Output=Self>
    + Shr<usize, Output=Self>
    + CheckedAdd<Output=Self>
    + CheckedSub<Output=Self>
    + CheckedMul<Output=Self>
    + CheckedDiv<Output=Self>
    + Saturating
{
    /// Returns the number of ones in the binary representation of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b01001100u8;
    ///
    /// assert_eq!(n.count_ones(), 3);
    /// ```
    fn count_ones(self) -> u32;

    /// Returns the number of zeros in the binary representation of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b01001100u8;
    ///
    /// assert_eq!(n.count_zeros(), 5);
    /// ```
    fn count_zeros(self) -> u32;

    /// Returns the number of leading zeros in the binary representation
    /// of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b0101000u16;
    ///
    /// assert_eq!(n.leading_zeros(), 10);
    /// ```
    fn leading_zeros(self) -> u32;

    /// Returns the number of trailing zeros in the binary representation
    /// of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0b0101000u16;
    ///
    /// assert_eq!(n.trailing_zeros(), 3);
    /// ```
    fn trailing_zeros(self) -> u32;

    /// Shifts the bits to the left by a specified amount amount, `n`, wrapping
    /// the truncated bits to the end of the resulting integer.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0x3456789ABCDEF012u64;
    ///
    /// assert_eq!(n.rotate_left(12), m);
    /// ```
    fn rotate_left(self, n: u32) -> Self;

    /// Shifts the bits to the right by a specified amount amount, `n`, wrapping
    /// the truncated bits to the beginning of the resulting integer.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0xDEF0123456789ABCu64;
    ///
    /// assert_eq!(n.rotate_right(12), m);
    /// ```
    fn rotate_right(self, n: u32) -> Self;

    /// Shifts the bits to the left by a specified amount amount, `n`, filling
    /// zeros in the least significant bits.
    ///
    /// This is bitwise equivalent to signed `Shl`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0x3456789ABCDEF000u64;
    ///
    /// assert_eq!(n.signed_shl(12), m);
    /// ```
    fn signed_shl(self, n: u32) -> Self;

    /// Shifts the bits to the right by a specified amount amount, `n`, copying
    /// the "sign bit" in the most significant bits even for unsigned types.
    ///
    /// This is bitwise equivalent to signed `Shr`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0xFEDCBA9876543210u64;
    /// let m = 0xFFFFEDCBA9876543u64;
    ///
    /// assert_eq!(n.signed_shr(12), m);
    /// ```
    fn signed_shr(self, n: u32) -> Self;

    /// Shifts the bits to the left by a specified amount amount, `n`, filling
    /// zeros in the least significant bits.
    ///
    /// This is bitwise equivalent to unsigned `Shl`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFi64;
    /// let m = 0x3456789ABCDEF000i64;
    ///
    /// assert_eq!(n.unsigned_shl(12), m);
    /// ```
    fn unsigned_shl(self, n: u32) -> Self;

    /// Shifts the bits to the right by a specified amount amount, `n`, filling
    /// zeros in the most significant bits.
    ///
    /// This is bitwise equivalent to unsigned `Shr`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0xFEDCBA9876543210i64;
    /// let m = 0x000FEDCBA9876543i64;
    ///
    /// assert_eq!(n.unsigned_shr(12), m);
    /// ```
    fn unsigned_shr(self, n: u32) -> Self;

    /// Reverses the byte order of the integer.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    /// let m = 0xEFCDAB8967452301u64;
    ///
    /// assert_eq!(n.swap_bytes(), m);
    /// ```
    fn swap_bytes(self) -> Self;

    /// Convert an integer from big endian to the target's endianness.
    ///
    /// On big endian this is a no-op. On little endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "big") {
    ///     assert_eq!(u64::from_be(n), n)
    /// } else {
    ///     assert_eq!(u64::from_be(n), n.swap_bytes())
    /// }
    /// ```
    fn from_be(x: Self) -> Self;

    /// Convert an integer from little endian to the target's endianness.
    ///
    /// On little endian this is a no-op. On big endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "little") {
    ///     assert_eq!(u64::from_le(n), n)
    /// } else {
    ///     assert_eq!(u64::from_le(n), n.swap_bytes())
    /// }
    /// ```
    fn from_le(x: Self) -> Self;

    /// Convert `self` to big endian from the target's endianness.
    ///
    /// On big endian this is a no-op. On little endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "big") {
    ///     assert_eq!(n.to_be(), n)
    /// } else {
    ///     assert_eq!(n.to_be(), n.swap_bytes())
    /// }
    /// ```
    fn to_be(self) -> Self;

    /// Convert `self` to little endian from the target's endianness.
    ///
    /// On little endian this is a no-op. On big endian the bytes are swapped.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// let n = 0x0123456789ABCDEFu64;
    ///
    /// if cfg!(target_endian = "little") {
    ///     assert_eq!(n.to_le(), n)
    /// } else {
    ///     assert_eq!(n.to_le(), n.swap_bytes())
    /// }
    /// ```
    fn to_le(self) -> Self;

    /// Raises self to the power of `exp`, using exponentiation by squaring.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::PrimInt;
    ///
    /// assert_eq!(2i32.pow(4), 16);
    /// ```
    fn pow(self, exp: u32) -> Self;
}

macro_rules! prim_int_impl {
    ($T:ty, $S:ty, $U:ty) => (
        impl PrimInt for $T {
            #[inline]
            fn count_ones(self) -> u32 {
                <$T>::count_ones(self)
            }

            #[inline]
            fn count_zeros(self) -> u32 {
                <$T>::count_zeros(self)
            }

            #[inline]
            fn leading_zeros(self) -> u32 {
                <$T>::leading_zeros(self)
            }

            #[inline]
            fn trailing_zeros(self) -> u32 {
                <$T>::trailing_zeros(self)
            }

            #[inline]
            fn rotate_left(self, n: u32) -> Self {
                <$T>::rotate_left(self, n)
            }

            #[inline]
            fn rotate_right(self, n: u32) -> Self {
                <$T>::rotate_right(self, n)
            }

            #[inline]
            fn signed_shl(self, n: u32) -> Self {
                ((self as $S) << n) as $T
            }

            #[inline]
            fn signed_shr(self, n: u32) -> Self {
                ((self as $S) >> n) as $T
            }

            #[inline]
            fn unsigned_shl(self, n: u32) -> Self {
                ((self as $U) << n) as $T
            }

            #[inline]
            fn unsigned_shr(self, n: u32) -> Self {
                ((self as $U) >> n) as $T
            }

            #[inline]
            fn swap_bytes(self) -> Self {
                <$T>::swap_bytes(self)
            }

            #[inline]
            fn from_be(x: Self) -> Self {
                <$T>::from_be(x)
            }

            #[inline]
            fn from_le(x: Self) -> Self {
                <$T>::from_le(x)
            }

            #[inline]
            fn to_be(self) -> Self {
                <$T>::to_be(self)
            }

            #[inline]
            fn to_le(self) -> Self {
                <$T>::to_le(self)
            }

            #[inline]
            fn pow(self, exp: u32) -> Self {
                <$T>::pow(self, exp)
            }
        }
    )
}

// prim_int_impl!(type, signed, unsigned);
prim_int_impl!(u8,    i8,    u8);
prim_int_impl!(u16,   i16,   u16);
prim_int_impl!(u32,   i32,   u32);
prim_int_impl!(u64,   i64,   u64);
prim_int_impl!(usize, isize, usize);
prim_int_impl!(i8,    i8,    u8);
prim_int_impl!(i16,   i16,   u16);
prim_int_impl!(i32,   i32,   u32);
prim_int_impl!(i64,   i64,   u64);
prim_int_impl!(isize, isize, usize);

// While this might violate the possible assumption that
// PrimInt represents genuine primitive integer types,
// Wrapping<T> is _practically_ one too, so this
// shouldn't be a concern.
impl<T: PrimInt> PrimInt for Wrapping<T>
    where Wrapping<T>:
          Num + NumCast
        + Bounded
        + Not<Output=Wrapping<T>>
        + BitAnd<Output=Wrapping<T>>
        + BitOr<Output=Wrapping<T>>
        + BitXor<Output=Wrapping<T>>
        + Shl<usize, Output=Wrapping<T>>
        + Shr<usize, Output=Wrapping<T>>
        + CheckedAdd<Output=Wrapping<T>>
        + CheckedSub<Output=Wrapping<T>>
        + CheckedMul<Output=Wrapping<T>>
        + CheckedDiv<Output=Wrapping<T>>
        + Saturating
{
    #[inline]
    fn count_ones(self) -> u32 {
        self.0.count_ones()
    }

    #[inline]
    fn count_zeros(self) -> u32 {
        self.0.count_zeros()
    }

    #[inline]
    fn leading_zeros(self) -> u32 {
        self.0.leading_zeros()
    }

    #[inline]
    fn trailing_zeros(self) -> u32 {
        self.0.trailing_zeros()
    }

    #[inline]
    fn rotate_left(self, n: u32) -> Self {
        Wrapping(self.0.rotate_left(n))
    }

    #[inline]
    fn rotate_right(self, n: u32) -> Self {
        Wrapping(self.0.rotate_right(n))
    }

    #[inline]
    fn signed_shl(self, n: u32) -> Self {
        Wrapping(self.0.signed_shl(n))
    }

    #[inline]
    fn signed_shr(self, n: u32) -> Self {
        Wrapping(self.0.signed_shr(n))
    }

    #[inline]
    fn unsigned_shl(self, n: u32) -> Self {
        Wrapping(self.0.unsigned_shl(n))
    }

    #[inline]
    fn unsigned_shr(self, n: u32) -> Self {
        Wrapping(self.0.unsigned_shr(n))
    }

    #[inline]
    fn swap_bytes(self) -> Self {
        Wrapping(self.0.swap_bytes())
    }

    #[inline]
    fn from_be(x: Self) -> Self {
        Wrapping(T::from_be(x.0))
    }

    #[inline]
    fn from_le(x: Self) -> Self {
        Wrapping(T::from_le(x.0))
    }

    #[inline]
    fn to_be(self) -> Self {
        Wrapping(self.0.to_be())
    }

    #[inline]
    fn to_le(self) -> Self {
        Wrapping(self.0.to_le())
    }

    // This is (or should be ?) fine because Wrapping<T> only guarantees that
    // _standard_ operations (Add, Mul, etc) have wrapping semantics.
    #[inline]
    fn pow(self, exp: u32) -> Self {
        Wrapping(self.0.pow(exp))
    }
}
<|endoftext|>