<commit_before>use syntex_syntax::parse::{token, PResult};
use syntex_syntax::codemap;
use syntex_syntax::parse;
use syntex_syntax::ptr::P;
use syntex_syntax::parse::common::SeqSep;
use syntex_syntax::symbol::keywords;
use syntex_syntax::ast;
use syntex_syntax::ast::{Arg, FnDecl, Mutability, SelfKind};
use syntex_pos::mk_sp;
use syntex_syntax::parse::parser::Parser;
use syntex_syntax::ext::base::ExtCtxt;
use syntex_syntax::tokenstream::TokenTree;
use syntex_pos::Span;
use syntex_syntax::parse::parser;
use syntex_syntax::symbol::Symbol;

use {ForeignerClassInfo, ForeignerMethod, MethodVariant, SelfTypeVariant};
use my_ast::{if_result_return_ok_type, normalized_ty_string, self_variant};

/// Returns the parsed optional self argument and whether a self shortcut was used.
fn parse_self_arg<'a>(parser: &mut Parser<'a>) -> parse::PResult<'a, Option<Arg>> {
    let expect_ident = |this: &mut Parser<'a>| match this.token {
        // Preserve hygienic context.
        token::Ident(ident) => {
            this.bump();
            codemap::respan(this.prev_span, ident)
        }
        _ => unreachable!(),
    };
    let isolated_self = |this: &mut Parser<'a>, n| {
        this.look_ahead(n, |t| t.is_keyword(keywords::SelfValue)) &&
            this.look_ahead(n + 1, |t| t != &token::ModSep)
    };

    // Parse optional self parameter of a method.
    // Only a limited set of initial token sequences is considered self parameters, anything
    // else is parsed as a normal function parameter list, so some lookahead is required.
    let eself_lo = parser.span.lo;
    let (eself, eself_ident) = match parser.token {
        token::BinOp(token::And) => {
            // &self
            // &mut self
            // &'lt self
            // &'lt mut self
            // &not_self
            if isolated_self(parser, 1) {
                parser.bump();
                (
                    SelfKind::Region(None, Mutability::Immutable),
                    expect_ident(parser),
                )
            } else if parser.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
                isolated_self(parser, 2)
            {
                parser.bump();
                parser.bump();
                (
                    SelfKind::Region(None, Mutability::Mutable),
                    expect_ident(parser),
                )
            } else if parser.look_ahead(1, |t| t.is_lifetime()) && isolated_self(parser, 2) {
                parser.bump();
                let lt = try!(parser.parse_lifetime());
                (
                    SelfKind::Region(Some(lt), Mutability::Immutable),
                    expect_ident(parser),
                )
            } else if parser.look_ahead(1, |t| t.is_lifetime()) &&
                parser.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
                isolated_self(parser, 3)
            {
                parser.bump();
                let lt = try!(parser.parse_lifetime());
                parser.bump();
                (
                    SelfKind::Region(Some(lt), Mutability::Mutable),
                    expect_ident(parser),
                )
            } else {
                return Ok(None);
            }
        }
        token::BinOp(token::Star) => {
            // *self
            // *const self
            // *mut self
            // *not_self
            // Emit special error for `self` cases.
            if isolated_self(parser, 1) {
                parser.bump();
                parser.span_err(parser.span, "cannot pass `self` by raw pointer");
                (SelfKind::Value(Mutability::Immutable), expect_ident(parser))
            } else if parser.look_ahead(1, |t| t.is_mutability()) && isolated_self(parser, 2) {
                parser.bump();
                parser.bump();
                parser.span_err(parser.span, "cannot pass `self` by raw pointer");
                (SelfKind::Value(Mutability::Immutable), expect_ident(parser))
            } else {
                return Ok(None);
            }
        }
        token::Ident(..) => {
            if isolated_self(parser, 0) {
                // self
                // self: TYPE
                let eself_ident = expect_ident(parser);
                if parser.eat(&token::Colon) {
                    let ty = try!(parser.parse_ty());
                    (SelfKind::Explicit(ty, Mutability::Immutable), eself_ident)
                } else {
                    (SelfKind::Value(Mutability::Immutable), eself_ident)
                }
            } else if parser.token.is_keyword(keywords::Mut) && isolated_self(parser, 1) {
                // mut self
                // mut self: TYPE
                parser.bump();
                let eself_ident = expect_ident(parser);
                if parser.eat(&token::Colon) {
                    let ty = try!(parser.parse_ty());
                    (SelfKind::Explicit(ty, Mutability::Mutable), eself_ident)
                } else {
                    (SelfKind::Value(Mutability::Mutable), eself_ident)
                }
            } else {
                return Ok(None);
            }
        }
        _ => return Ok(None),
    };

    let eself = codemap::respan(mk_sp(eself_lo, parser.prev_span.hi), eself);
    Ok(Some(Arg::from_self(eself, eself_ident)))
}

/// Parse the parameter list and result type of a function that may have a `self` parameter.
fn parse_fn_decl_with_self<'a, F>(
    parser: &mut Parser<'a>,
    parse_arg_fn: F,
) -> PResult<'a, P<FnDecl>>
where
    F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
{
    try!(parser.expect(&token::OpenDelim(token::Paren)));

    // Parse optional self argument
    let self_arg = try!(parse_self_arg(parser));

    // Parse the rest of the function parameter list.
    let sep = SeqSep::trailing_allowed(token::Comma);
    let fn_inputs = if let Some(self_arg) = self_arg {
        if parser.check(&token::CloseDelim(token::Paren)) {
            vec![self_arg]
        } else if parser.eat(&token::Comma) {
            let mut fn_inputs = vec![self_arg];
            fn_inputs.append(
                &mut parser
                    .parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn),
            );
            fn_inputs
        } else {
            return parser.unexpected();
        }
    } else {
        parser.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
    };

    // Parse closing paren and return type.
    try!(parser.expect(&token::CloseDelim(token::Paren)));
    Ok(P(FnDecl {
        inputs: fn_inputs,
        output: try!(parser.parse_ret_ty()),
        variadic: false,
    }))
}

pub(crate) fn parse_foreigner_class(
    cx: &ExtCtxt,
    tokens: &[TokenTree],
) -> Result<ForeignerClassInfo, Span> {
    let class_keyword = ast::Ident::from_str("class");
    let alias_keyword = ast::Ident::from_str("alias");
    let private_keyword = ast::Ident::from_str("private");

    let constructor_keyword = Symbol::intern("constructor");
    let method_keyword = Symbol::intern("method");
    let static_method_keyword = Symbol::intern("static_method");

    let mut parser = parse::new_parser_from_tts(cx.parse_sess, tokens.to_vec());
    if !parser.eat_contextual_keyword(class_keyword) {
        cx.span_err(parser.span, "expect class keyword here");
        return Err(parser.span);
    }

    let class_name_indent = parser.parse_ident().unwrap();
    debug!("CLASS NAME {:?}", class_name_indent);
    let class_span = parser.span;

    parser
        .expect(&token::Token::OpenDelim(token::DelimToken::Brace))
        .unwrap();
    let mut methods = Vec::new();
    let mut rust_self_type = ast::Path {
        span: parser.span,
        segments: Vec::new(),
    };
    let mut constructor_ret_type: Option<ast::Ty> = None;
    let mut this_type_for_method: Option<ast::Ty> = None;
    let mut foreigner_code = String::new();
    loop {
        if parser.eat(&token::Token::CloseDelim(token::DelimToken::Brace)) {
            break;
        }
        let private_func = parser.eat_contextual_keyword(private_keyword);
        let func_type_name = parser.parse_ident().unwrap();
        debug!("func_type {:?}", func_type_name);
        if &*func_type_name.name.as_str() == "self_type" {
            rust_self_type = parser
                .parse_path(parser::PathStyle::Type)
                .expect("Can not parse self_type");
            debug!("self_type: {:?}", rust_self_type);
            parser.expect(&token::Token::Semi).unwrap();
            continue;
        }

        if &*func_type_name.name.as_str() == "foreigner_code" {
            let lit = parser
                .parse_lit()
                .expect("expect literal after foreigner_code");
            match lit.node {
                ast::LitKind::Str(s, _) => {
                    debug!("foreigner_code s: {:?}", s);
                    foreigner_code.push_str(&*s.as_str());
                }
                _ => {
                    cx.span_err(parser.span, "expect string literal after foreigner_code");
                    return Err(parser.span);
                }
            }
            parser.expect(&token::Token::Semi).unwrap();
            continue;
        }

        let mut func_type = match func_type_name.name {
            _ if func_type_name.name == constructor_keyword => MethodVariant::Constructor,
            _ if func_type_name.name == static_method_keyword => MethodVariant::StaticMethod,
            _ if func_type_name.name == method_keyword => {
                MethodVariant::Method(SelfTypeVariant::Default)
            }
            _ => {
                cx.span_err(
                    parser.span,
                    &format!(
                        "expect 'constructor' or 'method' or \
                         'static_method' here, got: {}",
                        func_type_name
                    ),
                );
                return Err(parser.span);
            }
        };
        let func_name = parser.parse_path(parser::PathStyle::Mod).unwrap();
        debug!("func_name {:?}", func_name);

        let func_decl = match func_type {
            MethodVariant::Constructor | MethodVariant::StaticMethod => {
                parser.parse_fn_decl(false).unwrap()
            }
            MethodVariant::Method(ref mut self_type) => {
                let fn_decl = parse_fn_decl_with_self(&mut parser, |p| p.parse_arg()).unwrap();
                *self_type = self_variant(&fn_decl.inputs[0].ty).ok_or_else(|| {
                    cx.span_err(
                        parser.span,
                        &format!("Can not parse type {:?} as self type", fn_decl.inputs[0].ty),
                    );
                    parser.span
                })?;

                fn_decl
            }
        };
        debug!("func_decl {:?}", func_decl);
        parser.expect(&token::Token::Semi).unwrap();
        let mut func_name_alias = None;
        if parser.eat_contextual_keyword(alias_keyword) {
            if func_type == MethodVariant::Constructor {
                cx.span_err(parser.span, "alias not supported for 'constructor'");
                return Err(parser.span);
            }
            func_name_alias = Some(parser.parse_ident().unwrap());
            debug!("we have ALIAS `{:?}`", func_name_alias.unwrap());
            parser
                .expect(&token::Token::Semi)
                .expect("no ; at the end of alias");
        }
        let (may_return_error, ret_type) = match func_decl.output {
            ast::FunctionRetTy::Default(_) => (false, None),
            ast::FunctionRetTy::Ty(ref ret_type) => (
                if_result_return_ok_type(ret_type).is_some(),
                Some(ret_type.clone()),
            ),
        };
        if let MethodVariant::Constructor = func_type {
            let ret_type = match ret_type {
                Some(x) => x,
                None => {
                    cx.span_err(
                        parser.span,
                        &format!("{}: constructor should return value", class_name_indent),
                    );
                    return Err(parser.span);
                }
            };
            if let Some(ref constructor_ret_type) = constructor_ret_type {
                debug!("second constructor, ret type: {:?}", constructor_ret_type);
                if normalized_ty_string(constructor_ret_type) != normalized_ty_string(&*ret_type) {
                    cx.span_err(
                        parser.span,
                        &format!(
                            "mismatched types of construtors: {:?} {:?}",
                            constructor_ret_type,
                            ret_type
                        ),
                    );
                    return Err(parser.span);
                }
            } else {
                let ret_type = ret_type.unwrap();
                constructor_ret_type = Some(ret_type.clone());
                this_type_for_method = Some(
                    if_result_return_ok_type(constructor_ret_type.as_ref().unwrap())
                        .unwrap_or_else(|| ret_type),
                );
            }
        }
        methods.push(ForeignerMethod {
            variant: func_type,
            rust_id: func_name,
            fn_decl: func_decl,
            name_alias: func_name_alias.map(|v| v.name),
            may_return_error: may_return_error,
            foreigner_private: private_func,
        });
    }

    Ok(ForeignerClassInfo {
        name: class_name_indent.name,
        methods,
        self_type: rust_self_type,
        this_type_for_method,
        foreigner_code,
        constructor_ret_type,
        span: class_span,
    })
}
<commit_msg>feature: during parsing foreigner_class! show position where error<commit_after>use syntex_syntax::parse::{token, PResult};
use syntex_syntax::{ast, codemap, parse};
use syntex_syntax::ptr::P;
use syntex_syntax::parse::common::SeqSep;
use syntex_syntax::symbol::keywords;
use syntex_syntax::ast::{Arg, FnDecl, Mutability, SelfKind};
use syntex_pos::{mk_sp, Span, DUMMY_SP};
use syntex_syntax::parse::parser::Parser;
use syntex_syntax::ext::base::ExtCtxt;
use syntex_syntax::tokenstream::TokenTree;
use syntex_syntax::parse::parser;
use syntex_syntax::symbol::Symbol;
use syntex_errors::DiagnosticBuilder;

use {ForeignerClassInfo, ForeignerMethod, MethodVariant, SelfTypeVariant};
use my_ast::{if_result_return_ok_type, normalized_ty_string, self_variant};

/// Returns the parsed optional self argument and whether a self shortcut was used.
fn parse_self_arg<'a>(parser: &mut Parser<'a>) -> parse::PResult<'a, Option<Arg>> {
    let expect_ident = |this: &mut Parser<'a>| match this.token {
        // Preserve hygienic context.
        token::Ident(ident) => {
            this.bump();
            codemap::respan(this.prev_span, ident)
        }
        _ => unreachable!(),
    };
    let isolated_self = |this: &mut Parser<'a>, n| {
        this.look_ahead(n, |t| t.is_keyword(keywords::SelfValue)) &&
            this.look_ahead(n + 1, |t| t != &token::ModSep)
    };

    // Parse optional self parameter of a method.
    // Only a limited set of initial token sequences is considered self parameters, anything
    // else is parsed as a normal function parameter list, so some lookahead is required.
    let eself_lo = parser.span.lo;
    let (eself, eself_ident) = match parser.token {
        token::BinOp(token::And) => {
            // &self
            // &mut self
            // &'lt self
            // &'lt mut self
            // &not_self
            if isolated_self(parser, 1) {
                parser.bump();
                (
                    SelfKind::Region(None, Mutability::Immutable),
                    expect_ident(parser),
                )
            } else if parser.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
                isolated_self(parser, 2)
            {
                parser.bump();
                parser.bump();
                (
                    SelfKind::Region(None, Mutability::Mutable),
                    expect_ident(parser),
                )
            } else if parser.look_ahead(1, |t| t.is_lifetime()) && isolated_self(parser, 2) {
                parser.bump();
                let lt = try!(parser.parse_lifetime());
                (
                    SelfKind::Region(Some(lt), Mutability::Immutable),
                    expect_ident(parser),
                )
            } else if parser.look_ahead(1, |t| t.is_lifetime()) &&
                parser.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
                isolated_self(parser, 3)
            {
                parser.bump();
                let lt = try!(parser.parse_lifetime());
                parser.bump();
                (
                    SelfKind::Region(Some(lt), Mutability::Mutable),
                    expect_ident(parser),
                )
            } else {
                return Ok(None);
            }
        }
        token::BinOp(token::Star) => {
            // *self
            // *const self
            // *mut self
            // *not_self
            // Emit special error for `self` cases.
            if isolated_self(parser, 1) {
                parser.bump();
                parser.span_err(parser.span, "cannot pass `self` by raw pointer");
                (SelfKind::Value(Mutability::Immutable), expect_ident(parser))
            } else if parser.look_ahead(1, |t| t.is_mutability()) && isolated_self(parser, 2) {
                parser.bump();
                parser.bump();
                parser.span_err(parser.span, "cannot pass `self` by raw pointer");
                (SelfKind::Value(Mutability::Immutable), expect_ident(parser))
            } else {
                return Ok(None);
            }
        }
        token::Ident(..) => {
            if isolated_self(parser, 0) {
                // self
                // self: TYPE
                let eself_ident = expect_ident(parser);
                if parser.eat(&token::Colon) {
                    let ty = try!(parser.parse_ty());
                    (SelfKind::Explicit(ty, Mutability::Immutable), eself_ident)
                } else {
                    (SelfKind::Value(Mutability::Immutable), eself_ident)
                }
            } else if parser.token.is_keyword(keywords::Mut) && isolated_self(parser, 1) {
                // mut self
                // mut self: TYPE
                parser.bump();
                let eself_ident = expect_ident(parser);
                if parser.eat(&token::Colon) {
                    let ty = try!(parser.parse_ty());
                    (SelfKind::Explicit(ty, Mutability::Mutable), eself_ident)
                } else {
                    (SelfKind::Value(Mutability::Mutable), eself_ident)
                }
            } else {
                return Ok(None);
            }
        }
        _ => return Ok(None),
    };

    let eself = codemap::respan(mk_sp(eself_lo, parser.prev_span.hi), eself);
    Ok(Some(Arg::from_self(eself, eself_ident)))
}

/// Parse the parameter list and result type of a function that may have a `self` parameter.
fn parse_fn_decl_with_self<'a, F>(
    parser: &mut Parser<'a>,
    parse_arg_fn: F,
) -> PResult<'a, P<FnDecl>>
where
    F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
{
    try!(parser.expect(&token::OpenDelim(token::Paren)));

    // Parse optional self argument
    let self_arg = try!(parse_self_arg(parser));

    // Parse the rest of the function parameter list.
    let sep = SeqSep::trailing_allowed(token::Comma);
    let fn_inputs = if let Some(self_arg) = self_arg {
        if parser.check(&token::CloseDelim(token::Paren)) {
            vec![self_arg]
        } else if parser.eat(&token::Comma) {
            let mut fn_inputs = vec![self_arg];
            fn_inputs.append(
                &mut parser
                    .parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn),
            );
            fn_inputs
        } else {
            return parser.unexpected();
        }
    } else {
        parser.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
    };

    // Parse closing paren and return type.
    try!(parser.expect(&token::CloseDelim(token::Paren)));
    Ok(P(FnDecl {
        inputs: fn_inputs,
        output: try!(parser.parse_ret_ty()),
        variadic: false,
    }))
}

pub(crate) fn parse_foreigner_class(
    cx: &ExtCtxt,
    tokens: &[TokenTree],
) -> Result<ForeignerClassInfo, Span> {
    let class_keyword = ast::Ident::from_str("class");
    let alias_keyword = ast::Ident::from_str("alias");
    let private_keyword = ast::Ident::from_str("private");

    let constructor_keyword = Symbol::intern("constructor");
    let method_keyword = Symbol::intern("method");
    let static_method_keyword = Symbol::intern("static_method");

    let mut parser = parse::new_parser_from_tts(cx.parse_sess, tokens.to_vec());
    if !parser.eat_contextual_keyword(class_keyword) {
        cx.span_err(parser.span, "expect class keyword here");
        return Err(parser.span);
    }

    let map_perror = |err: DiagnosticBuilder| -> Span {
        let diag = err.into_diagnostic();
        let primary_span = diag.span.primary_span().unwrap_or(DUMMY_SP);
        cx.parse_sess
            .span_diagnostic
            .span_err(diag.span.clone(), &diag.message());
        primary_span
    };

    let class_name_indent = parser.parse_ident().unwrap();
    debug!("CLASS NAME {:?}", class_name_indent);
    let class_span = parser.span;

    parser
        .expect(&token::Token::OpenDelim(token::DelimToken::Brace))
        .map_err(&map_perror)?;
    let mut methods = Vec::new();
    let mut rust_self_type = ast::Path {
        span: parser.span,
        segments: Vec::new(),
    };
    let mut constructor_ret_type: Option<ast::Ty> = None;
    let mut this_type_for_method: Option<ast::Ty> = None;
    let mut foreigner_code = String::new();
    loop {
        if parser.eat(&token::Token::CloseDelim(token::DelimToken::Brace)) {
            break;
        }
        let private_func = parser.eat_contextual_keyword(private_keyword);
        let func_type_name = parser.parse_ident().map_err(&map_perror)?;
        debug!("func_type {:?}", func_type_name);
        if &*func_type_name.name.as_str() == "self_type" {
            rust_self_type = parser
                .parse_path(parser::PathStyle::Type)
                .expect("Can not parse self_type");
            debug!("self_type: {:?}", rust_self_type);
            parser.expect(&token::Token::Semi).map_err(&map_perror)?;
            continue;
        }

        if &*func_type_name.name.as_str() == "foreigner_code" {
            let lit = parser
                .parse_lit()
                .expect("expect literal after foreigner_code");
            match lit.node {
                ast::LitKind::Str(s, _) => {
                    debug!("foreigner_code s: {:?}", s);
                    foreigner_code.push_str(&*s.as_str());
                }
                _ => {
                    cx.span_err(parser.span, "expect string literal after foreigner_code");
                    return Err(parser.span);
                }
            }
            parser.expect(&token::Token::Semi).map_err(&map_perror)?;
            continue;
        }

        let mut func_type = match func_type_name.name {
            _ if func_type_name.name == constructor_keyword => MethodVariant::Constructor,
            _ if func_type_name.name == static_method_keyword => MethodVariant::StaticMethod,
            _ if func_type_name.name == method_keyword => {
                MethodVariant::Method(SelfTypeVariant::Default)
            }
            _ => {
                cx.span_err(
                    parser.span,
                    &format!(
                        "expect 'constructor' or 'method' or \
                         'static_method' here, got: {}",
                        func_type_name
                    ),
                );
                return Err(parser.span);
            }
        };
        let func_name = parser
            .parse_path(parser::PathStyle::Mod)
            .map_err(&map_perror)?;
        debug!("func_name {:?}", func_name);

        let func_decl = match func_type {
            MethodVariant::Constructor | MethodVariant::StaticMethod => {
                parser.parse_fn_decl(false).map_err(&map_perror)?
            }
            MethodVariant::Method(ref mut self_type) => {
                let fn_decl = parse_fn_decl_with_self(&mut parser, |p| p.parse_arg())
                    .map_err(&map_perror)?;
                *self_type = self_variant(&fn_decl.inputs[0].ty).ok_or_else(|| {
                    cx.span_err(
                        parser.span,
                        &format!("Can not parse type {:?} as self type", fn_decl.inputs[0].ty),
                    );
                    parser.span
                })?;

                fn_decl
            }
        };
        debug!("func_decl {:?}", func_decl);
        parser.expect(&token::Token::Semi).map_err(&map_perror)?;
        let mut func_name_alias = None;
        if parser.eat_contextual_keyword(alias_keyword) {
            if func_type == MethodVariant::Constructor {
                cx.span_err(parser.span, "alias not supported for 'constructor'");
                return Err(parser.span);
            }
            func_name_alias = Some(parser.parse_ident().map_err(&map_perror)?);
            debug!("we have ALIAS `{:?}`", func_name_alias.unwrap());
            parser
                .expect(&token::Token::Semi)
                .expect("no ; at the end of alias");
        }
        let (may_return_error, ret_type) = match func_decl.output {
            ast::FunctionRetTy::Default(_) => (false, None),
            ast::FunctionRetTy::Ty(ref ret_type) => (
                if_result_return_ok_type(ret_type).is_some(),
                Some(ret_type.clone()),
            ),
        };
        if let MethodVariant::Constructor = func_type {
            let ret_type = match ret_type {
                Some(x) => x,
                None => {
                    cx.span_err(
                        parser.span,
                        &format!("{}: constructor should return value", class_name_indent),
                    );
                    return Err(parser.span);
                }
            };
            if let Some(ref constructor_ret_type) = constructor_ret_type {
                debug!("second constructor, ret type: {:?}", constructor_ret_type);
                if normalized_ty_string(constructor_ret_type) != normalized_ty_string(&*ret_type) {
                    cx.span_err(
                        parser.span,
                        &format!(
                            "mismatched types of construtors: {:?} {:?}",
                            constructor_ret_type,
                            ret_type
                        ),
                    );
                    return Err(parser.span);
                }
            } else {
                let ret_type = ret_type.unwrap();
                constructor_ret_type = Some(ret_type.clone());
                this_type_for_method = Some(
                    if_result_return_ok_type(constructor_ret_type.as_ref().unwrap())
                        .unwrap_or_else(|| ret_type),
                );
            }
        }
        methods.push(ForeignerMethod {
            variant: func_type,
            rust_id: func_name,
            fn_decl: func_decl,
            name_alias: func_name_alias.map(|v| v.name),
            may_return_error: may_return_error,
            foreigner_private: private_func,
        });
    }

    Ok(ForeignerClassInfo {
        name: class_name_indent.name,
        methods,
        self_type: rust_self_type,
        this_type_for_method,
        foreigner_code,
        constructor_ret_type,
        span: class_span,
    })
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::Cursive;
use cursive::views::{Dialog, SelectView, TextView};
use cursive::align::HAlign;
use cursive::traits::*;

fn main() {
    let mut select = SelectView::new().h_align(HAlign::Center);

    // Read the list of cities from separate file, and fill the view with it.
    // (We include the file at compile-time to avoid runtime read errors.)
    let content = include_str!("../assets/cities.txt");
    select.add_all_str(content.lines());

    // Sets the callback for when "Enter" is pressed.
    select.set_on_submit(show_next_window);

    let mut siv = Cursive::new();

    // Let's add a BoxView to keep the list at a reasonable size - it can scroll anyway.
    siv.add_layer(Dialog::around(select.fixed_size((20, 10)))
        .title("Where are you from?"));

    siv.run();
}

// Let's put the callback in a separate function to keep it clean, but it's not required.
fn show_next_window(siv: &mut Cursive, city: &str) {
    siv.pop_layer();
    let text = format!("{} is a great city!", city);
    siv.add_layer(Dialog::around(TextView::new(text))
        .button("Quit", |s| s.quit()));
}
<commit_msg>Add j/k navigation to select example<commit_after>extern crate cursive;

use cursive::Cursive;
use cursive::align::HAlign;
use cursive::event::EventResult;
use cursive::traits::*;
use cursive::views::{Dialog, OnEventView, SelectView, TextView};

fn main() {
    let mut select = SelectView::new().h_align(HAlign::Center);

    // Read the list of cities from separate file, and fill the view with it.
    // (We include the file at compile-time to avoid runtime read errors.)
    let content = include_str!("../assets/cities.txt");
    select.add_all_str(content.lines());

    // Sets the callback for when "Enter" is pressed.
    select.set_on_submit(show_next_window);

    // Let's override the `j` and `k` keys for navigation
    let select = OnEventView::new(select)
        .on_pre_event_inner('k', |s| {
            s.select_up(1);
            Some(EventResult::Consumed(None))
        })
        .on_pre_event_inner('j', |s| {
            s.select_down(1);
            Some(EventResult::Consumed(None))
        });

    let mut siv = Cursive::new();

    // Let's add a BoxView to keep the list at a reasonable size - it can scroll anyway.
    siv.add_layer(
        Dialog::around(select.fixed_size((20, 10)))
            .title("Where are you from?"),
    );

    siv.run();
}

// Let's put the callback in a separate function to keep it clean, but it's not required.
fn show_next_window(siv: &mut Cursive, city: &str) {
    siv.pop_layer();
    let text = format!("{} is a great city!", city);
    siv.add_layer(
        Dialog::around(TextView::new(text)).button("Quit", |s| s.quit()),
    );
}
<|endoftext|>


<commit_before>// This example uses fds() to find out which file descriptors c-ares
// wants us to listen on, and uses select() to satisfy those requirements.
#[cfg(windows)]
mod example {
    extern crate c_ares;

    use winapi::winsock2::{fd_set, timeval, FD_SETSIZE, SOCKET_ERROR, WSADATA};
    use ws2_32::{select, WSACleanup, WSAStartup};
    use std::error::Error;
    use std::mem;
    use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
    use std::ptr;

    fn print_soa_result(result: &c_ares::Result<c_ares::SOAResult>) {
        match *result {
            Err(ref e) => {
                println!("SOA lookup failed with error '{}'", e.description());
            }
            Ok(ref soa_result) => {
                println!("Successful SOA lookup...");
                println!("Name server: {}", soa_result.name_server());
                println!("Hostmaster: {}", soa_result.hostmaster());
                println!("Serial: {}", soa_result.serial());
                println!("Retry: {}", soa_result.retry());
                println!("Expire: {}", soa_result.expire());
                println!("Min TTL: {}", soa_result.min_ttl());
            }
        }
    }

    fn print_name_info_result(result: &c_ares::Result<c_ares::NameInfoResult>) {
        match *result {
            Err(ref e) => {
                println!("Name info lookup failed with error '{}'", e.description());
            }
            Ok(ref name_info_result) => {
                println!("Successful name info lookup...");
                println!("Node: {}", name_info_result.node().unwrap_or("<None>"));
                println!(
                    "Service: {}",
                    name_info_result.service().unwrap_or("<None>")
                );
            }
        }
    }

    pub fn main() {
        // Windows peculiarities.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the c_ares::Channel.
        let mut options = c_ares::Options::new();
        options
            .set_domains(&["example.com"])
            .set_flags(c_ares::Flags::STAYOPEN)
            .set_timeout(500)
            .set_tries(3);
        let mut ares_channel =
            c_ares::Channel::with_options(options).expect("Failed to create channel");
        ares_channel
            .set_servers(&["8.8.8.8"])
            .expect("Failed to set servers");

        // Set up some queries.
        ares_channel.query_soa("google.com", move |result| {
            println!();
            print_soa_result(&result);
        });

        let ipv4 = "216.58.210.14".parse::<Ipv4Addr>().unwrap();
        let sock = SocketAddr::V4(SocketAddrV4::new(ipv4, 80));
        ares_channel.get_name_info(
            &sock,
            c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
            move |result| {
                println!();
                print_name_info_result(&result);
            },
        );

        let ipv6 = "2a00:1450:4009:80a::200e".parse::<Ipv6Addr>().unwrap();
        let sock = SocketAddr::V6(SocketAddrV6::new(ipv6, 80, 0, 0));
        ares_channel.get_name_info(
            &sock,
            c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
            move |result| {
                println!();
                print_name_info_result(&result);
            },
        );

        // While c-ares wants us to listen for events, do so..
        loop {
            let mut read_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let mut write_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let count = ares_channel.fds(&mut read_fds, &mut write_fds);
            if count == 0 {
                break;
            }

            // Wait for something to happen.
            let timeout = timeval {
                tv_sec: 0,
                tv_usec: 500000,
            };
            let results =
                unsafe { select(0, &mut read_fds, &mut write_fds, ptr::null_mut(), &timeout) };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => ares_channel.process(&mut read_fds, &mut write_fds),
            }
        }
        unsafe {
            WSACleanup();
        }
    }
}

#[cfg(windows)]
pub fn main() {
    example::main();
}

#[cfg(not(windows))]
pub fn main() {
    println!("this example is not supported on this platform");
}
<commit_msg>fix windows build<commit_after>// This example uses fds() to find out which file descriptors c-ares
// wants us to listen on, and uses select() to satisfy those requirements.
#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
mod example {
    extern crate c_ares;

    use winapi::um::winsock2::{fd_set, select, timeval, WSACleanup, WSAStartup, FD_SETSIZE,
                               SOCKET_ERROR, WSADATA};
    use std::error::Error;
    use std::mem;
    use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
    use std::ptr;

    fn print_soa_result(result: &c_ares::Result<c_ares::SOAResult>) {
        match *result {
            Err(ref e) => {
                println!("SOA lookup failed with error '{}'", e.description());
            }
            Ok(ref soa_result) => {
                println!("Successful SOA lookup...");
                println!("Name server: {}", soa_result.name_server());
                println!("Hostmaster: {}", soa_result.hostmaster());
                println!("Serial: {}", soa_result.serial());
                println!("Retry: {}", soa_result.retry());
                println!("Expire: {}", soa_result.expire());
                println!("Min TTL: {}", soa_result.min_ttl());
            }
        }
    }

    fn print_name_info_result(result: &c_ares::Result<c_ares::NameInfoResult>) {
        match *result {
            Err(ref e) => {
                println!("Name info lookup failed with error '{}'", e.description());
            }
            Ok(ref name_info_result) => {
                println!("Successful name info lookup...");
                println!("Node: {}", name_info_result.node().unwrap_or("<None>"));
                println!(
                    "Service: {}",
                    name_info_result.service().unwrap_or("<None>")
                );
            }
        }
    }

    pub fn main() {
        // Windows peculiarities.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the c_ares::Channel.
        let mut options = c_ares::Options::new();
        options
            .set_domains(&["example.com"])
            .set_flags(c_ares::Flags::STAYOPEN)
            .set_timeout(500)
            .set_tries(3);
        let mut ares_channel =
            c_ares::Channel::with_options(options).expect("Failed to create channel");
        ares_channel
            .set_servers(&["8.8.8.8"])
            .expect("Failed to set servers");

        // Set up some queries.
        ares_channel.query_soa("google.com", move |result| {
            println!();
            print_soa_result(&result);
        });

        let ipv4 = "216.58.210.14".parse::<Ipv4Addr>().unwrap();
        let sock = SocketAddr::V4(SocketAddrV4::new(ipv4, 80));
        ares_channel.get_name_info(
            &sock,
            c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
            move |result| {
                println!();
                print_name_info_result(&result);
            },
        );

        let ipv6 = "2a00:1450:4009:80a::200e".parse::<Ipv6Addr>().unwrap();
        let sock = SocketAddr::V6(SocketAddrV6::new(ipv6, 80, 0, 0));
        ares_channel.get_name_info(
            &sock,
            c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
            move |result| {
                println!();
                print_name_info_result(&result);
            },
        );

        // While c-ares wants us to listen for events, do so..
        loop {
            let mut read_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let mut write_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let count = ares_channel.fds(&mut read_fds, &mut write_fds);
            if count == 0 {
                break;
            }

            // Wait for something to happen.
            let timeout = timeval {
                tv_sec: 0,
                tv_usec: 500_000,
            };
            let results = unsafe {
                select(0, &mut read_fds, &mut write_fds, ptr::null_mut(), &timeout)
            };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => ares_channel.process(&mut read_fds, &mut write_fds),
            }
        }
        unsafe {
            WSACleanup();
        }
    }
}

#[cfg(windows)]
pub fn main() {
    example::main();
}

#[cfg(not(windows))]
pub fn main() {
    println!("this example is not supported on this platform");
}
<|endoftext|>


<commit_before>use ::thud_game;
use ::{EdgeData, VertexData};
use ::search_graph;
use ::statistics::ThudStatistics;

pub type ThudState = thud_game::state::State<thud_game::board::TranspositionalEquivalence>;
pub type ThudEdge<'a> = search_graph::nav::Edge<'a, ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;
pub type ThudGraph = search_graph::Graph<ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;
pub type ThudNode<'a> = search_graph::nav::Node<'a, ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;
pub type ThudChildList<'a> = search_graph::nav::ChildList<'a, ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;
pub type ThudParentList<'a> = search_graph::nav::ParentList<'a, ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;
pub type ThudParentListIter<'a> = search_graph::nav::ParentListIter<'a, ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;
pub type ThudMutNode<'a> = search_graph::mutators::MutNode<'a, ThudState, VertexData, EdgeData<ThudStatistics, thud_game::Action>>;

<commit_msg>Remove unused module code from mcts crate.<commit_after><|endoftext|>


<commit_before>use regex::Regex;
use std::path::PathBuf;
use std::result::Result;
use subprocess::{Exec, Redirection};

const LOOP_BACKING_DEVICE_BASENAME: &'static str = "flaglock6-home";
const LOOP_DEVICE_PARTITION_LABEL: &'static str = "fl6";
const RSYNC_DOT_NET_REMOTE_DIR: &'static str = "usw-s007.rsync.net:./";

#[derive(Debug)]
pub enum AuricError {
    Invocation(String),
    Io(String),
    Subprocess(String),
    NotFound,
}

enum AuricOperationMode {
    Mount,
    Unmount,
}

impl From<subprocess::PopenError> for AuricError {
    fn from(err: subprocess::PopenError) -> AuricError {
        AuricError::Subprocess(err.to_string())
    }
}

struct SshfsManager {
    mountpoint: PathBuf,
}

struct LoopManager {
    target: Regex,
    backing: PathBuf,
}

struct LuksManager {
    device: PathBuf,
}

struct AuricImpl {
    sshfs_manager: SshfsManager,
    loop_manager: LoopManager,
    luks_manager: LuksManager,
}

impl SshfsManager {
    pub fn new() -> Result<SshfsManager, AuricError> {
        let xdg_runtime_dir = match std::env::var("XDG_RUNTIME_DIR") {
            Ok(val) => val,
            Err(e) => {
                return Err(AuricError::Invocation(format!(
                    "fatal error getting ${{XDG_RUNTIME_DIR}}: ``{}''",
                    e
                )))
            }
        };
        let mut mountpoint = PathBuf::new();
        mountpoint.push(xdg_runtime_dir);
        mountpoint.push("rsync.net-mountpoint");

        Ok(SshfsManager {
            mountpoint: mountpoint,
        })
    }

    fn ensure_mountpoint_is_dir(&self) -> Result<(), AuricError> {
        if self.mountpoint.is_dir() {
            return Ok(());
        }
        std::fs::create_dir(self.mountpoint.as_path())
            .map_err(|e| AuricError::Io(format!("bad mountpoint: ``{}''", e)))
    }

    // Does _not_ ensure that backing device exists.
    pub fn loop_backing_device_path(&self) -> PathBuf {
        let mut result: PathBuf = self.mountpoint.clone();
        result.push(LOOP_BACKING_DEVICE_BASENAME);
        result
    }

    fn loop_backing_device_present(&self) -> bool {
        self.loop_backing_device_path().is_file()
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        self.ensure_mountpoint_is_dir()?;
        if self.loop_backing_device_present() {
            return Ok(());
        }

        let result = Exec::cmd("sshfs")
            .arg("-o")
            .arg("allow_other")
            .arg(RSYNC_DOT_NET_REMOTE_DIR)
            .arg(&self.mountpoint)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "sshfs failed: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        if !self.loop_backing_device_present() {
            return Ok(());
        }

        let result = Exec::cmd("fusermount")
            .arg("-u")
            .arg(&self.mountpoint)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "fusermount -u failed: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

impl LoopManager {
    pub fn new(backing: &PathBuf) -> LoopManager {
        let target = format!(
            r"^(/dev/loop\d)(\s+\d+){{4}}\s+({})\s+",
            backing.to_str().unwrap()
        );
        LoopManager {
            target: Regex::new(&target).unwrap(),
            backing: backing.clone(),
        }
    }

    pub fn find(&self) -> Result<PathBuf, AuricError> {
        let result = Exec::cmd("losetup")
            .arg("-l")
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to list loop devices: ``{}''",
                result.stderr_str()
            )));
        }

        for line in result.stdout_str().lines() {
            if let Some(captures) = self.target.captures(line) {
                return Ok(PathBuf::from(captures.get(1).unwrap().as_str()));
            }
        }
        Err(AuricError::NotFound)
    }

    pub fn attach(&self) -> Result<(), AuricError> {
        if let Ok(_attached_loop) = self.find() {
            return Ok(());
        }

        let result = Exec::cmd("udisksctl")
            .arg("loop-setup")
            .arg("-f")
            .arg(&self.backing)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to attach loop device: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }

    // Note that the loop device will linger if the volume remains
    // unlocked. Prefer not to call this before locking.
    pub fn detach(&self) -> Result<(), AuricError> {
        let attached_loop = match self.find() {
            Ok(path) => path,
            Err(e) => {
                if let AuricError::NotFound = e {
                    return Ok(());
                }
                return Err(e);
            }
        };
        let result = Exec::cmd("udisksctl")
            .arg("loop-delete")
            .arg("-b")
            .arg(&attached_loop)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to detach loop device: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

impl LuksManager {
    pub fn new() -> LuksManager {
        let mut device = PathBuf::from("/dev/disk/by-label");
        device.push(LOOP_DEVICE_PARTITION_LABEL);
        LuksManager { device: device }
    }

    // `locked_device` is necessary as an external argument because no
    // device mapping exists in a pre-unlock world, so we need to target
    // the loop device directly.
    pub fn unlock(&self, locked_device: &PathBuf) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("unlock")
            .arg("-b")
            .arg(locked_device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to unlock {}: ``{}''",
                locked_device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    // No extra argument is needed here (c.f. `self::unlock()`) because
    // we can go straight after the well-known device available in
    // /dev/disk/by-label.
    pub fn lock(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("lock")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to lock {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("mount")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to mount {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("unmount")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to unmount {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

fn get_action() -> Result<AuricOperationMode, AuricError> {
    let mut args_iter = std::env::args();
    args_iter.next();
    if let Some(action) = args_iter.next() {
        match action.as_str() {
            "mount" => return Ok(AuricOperationMode::Mount),
            "unmount" => return Ok(AuricOperationMode::Unmount),
            _ => {
                return Err(AuricError::Invocation(format!(
                    "unknown action: ``{}''",
                    action
                )))
            }
        }
    }
    Err(AuricError::Invocation("no action given".to_string()))
}

impl AuricImpl {
    pub fn new() -> Result<AuricImpl, AuricError> {
        let sshfs_manager = SshfsManager::new()?;
        let loop_backing_device_path = sshfs_manager.loop_backing_device_path();
        Ok(AuricImpl {
            sshfs_manager: sshfs_manager,
            loop_manager: LoopManager::new(&loop_backing_device_path),
            luks_manager: LuksManager::new(),
        })
    }

    fn mount(&self) -> Result<(), AuricError> {
        self.sshfs_manager.mount()?;
        self.loop_manager.attach()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.unlock(&loop_device)?;
        self.luks_manager.mount()
    }

    fn unmount(&self) -> Result<(), AuricError> {
        self.luks_manager.unmount()?;
        self.luks_manager.lock()?;
        self.loop_manager.detach()?;
        self.sshfs_manager.unmount()
    }

    pub fn act(&self, mode: AuricOperationMode) -> Result<(), AuricError> {
        match mode {
            AuricOperationMode::Mount => return self.mount(),
            AuricOperationMode::Unmount => return self.unmount(),
        }
    }
}

fn main_impl() -> Result<(), AuricError> {
    let action = get_action()?;
    let auric_impl = AuricImpl::new()?;
    auric_impl.act(action)
}

fn main() {
    std::process::exit(match main_impl() {
        Ok(_) => 0,
        Err(e) => {
            eprintln!("{:?}", e);
            1
        }
    });
}
<commit_msg>apricot-auric: Lock underlying device<commit_after>use regex::Regex;
use std::path::PathBuf;
use std::result::Result;
use subprocess::{Exec, Redirection};

const LOOP_BACKING_DEVICE_BASENAME: &'static str = "flaglock6-home";
const LOOP_DEVICE_PARTITION_LABEL: &'static str = "fl6";
const RSYNC_DOT_NET_REMOTE_DIR: &'static str = "usw-s007.rsync.net:./";

#[derive(Debug)]
pub enum AuricError {
    Invocation(String),
    Io(String),
    Subprocess(String),
    NotFound,
}

enum AuricOperationMode {
    Mount,
    Unmount,
}

impl From<subprocess::PopenError> for AuricError {
    fn from(err: subprocess::PopenError) -> AuricError {
        AuricError::Subprocess(err.to_string())
    }
}

struct SshfsManager {
    mountpoint: PathBuf,
}

struct LoopManager {
    target: Regex,
    backing: PathBuf,
}

struct LuksManager {
    device: PathBuf,
}

struct AuricImpl {
    sshfs_manager: SshfsManager,
    loop_manager: LoopManager,
    luks_manager: LuksManager,
}

impl SshfsManager {
    pub fn new() -> Result<SshfsManager, AuricError> {
        let xdg_runtime_dir = match std::env::var("XDG_RUNTIME_DIR") {
            Ok(val) => val,
            Err(e) => {
                return Err(AuricError::Invocation(format!(
                    "fatal error getting ${{XDG_RUNTIME_DIR}}: ``{}''",
                    e
                )))
            }
        };
        let mut mountpoint = PathBuf::new();
        mountpoint.push(xdg_runtime_dir);
        mountpoint.push("rsync.net-mountpoint");

        Ok(SshfsManager {
            mountpoint: mountpoint,
        })
    }

    fn ensure_mountpoint_is_dir(&self) -> Result<(), AuricError> {
        if self.mountpoint.is_dir() {
            return Ok(());
        }
        std::fs::create_dir(self.mountpoint.as_path())
            .map_err(|e| AuricError::Io(format!("bad mountpoint: ``{}''", e)))
    }

    // Does _not_ ensure that backing device exists.
    pub fn loop_backing_device_path(&self) -> PathBuf {
        let mut result: PathBuf = self.mountpoint.clone();
        result.push(LOOP_BACKING_DEVICE_BASENAME);
        result
    }

    fn loop_backing_device_present(&self) -> bool {
        self.loop_backing_device_path().is_file()
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        self.ensure_mountpoint_is_dir()?;
        if self.loop_backing_device_present() {
            return Ok(());
        }

        let result = Exec::cmd("sshfs")
            .arg("-o")
            .arg("allow_other")
            .arg(RSYNC_DOT_NET_REMOTE_DIR)
            .arg(&self.mountpoint)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "sshfs failed: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        if !self.loop_backing_device_present() {
            return Ok(());
        }

        let result = Exec::cmd("fusermount")
            .arg("-u")
            .arg(&self.mountpoint)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "fusermount -u failed: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

impl LoopManager {
    pub fn new(backing: &PathBuf) -> LoopManager {
        let target = format!(
            r"^(/dev/loop\d)(\s+\d+){{4}}\s+({})\s+",
            backing.to_str().unwrap()
        );
        LoopManager {
            target: Regex::new(&target).unwrap(),
            backing: backing.clone(),
        }
    }

    pub fn find(&self) -> Result<PathBuf, AuricError> {
        let result = Exec::cmd("losetup")
            .arg("-l")
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to list loop devices: ``{}''",
                result.stderr_str()
            )));
        }

        for line in result.stdout_str().lines() {
            if let Some(captures) = self.target.captures(line) {
                return Ok(PathBuf::from(captures.get(1).unwrap().as_str()));
            }
        }
        Err(AuricError::NotFound)
    }

    pub fn attach(&self) -> Result<(), AuricError> {
        if let Ok(_attached_loop) = self.find() {
            return Ok(());
        }

        let result = Exec::cmd("udisksctl")
            .arg("loop-setup")
            .arg("-f")
            .arg(&self.backing)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to attach loop device: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }

    // Note that the loop device will linger if the volume remains
    // unlocked. Prefer not to call this before locking.
    pub fn detach(&self) -> Result<(), AuricError> {
        let attached_loop = match self.find() {
            Ok(path) => path,
            Err(e) => {
                if let AuricError::NotFound = e {
                    return Ok(());
                }
                return Err(e);
            }
        };
        let result = Exec::cmd("udisksctl")
            .arg("loop-delete")
            .arg("-b")
            .arg(&attached_loop)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to detach loop device: ``{}''",
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

impl LuksManager {
    pub fn new() -> LuksManager {
        let mut device = PathBuf::from("/dev/disk/by-label");
        device.push(LOOP_DEVICE_PARTITION_LABEL);
        LuksManager { device: device }
    }

    pub fn unlock(&self, locked_device: &PathBuf) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("unlock")
            .arg("-b")
            .arg(locked_device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to unlock {}: ``{}''",
                locked_device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn lock(&self, underlying_device: &PathBuf) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("lock")
            .arg("-b")
            .arg(underlying_device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to lock {}: ``{}''",
                underlying_device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn mount(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("mount")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to mount {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }

    pub fn unmount(&self) -> Result<(), AuricError> {
        let result = Exec::cmd("udisksctl")
            .arg("unmount")
            .arg("-b")
            .arg(&self.device)
            .stdout(Redirection::Pipe)
            .stderr(Redirection::Pipe)
            .capture()?;
        if !result.success() {
            return Err(AuricError::Subprocess(format!(
                "failed to unmount {}: ``{}''",
                self.device.to_str().unwrap(),
                result.stderr_str()
            )));
        }
        Ok(())
    }
}

fn get_action() -> Result<AuricOperationMode, AuricError> {
    let mut args_iter = std::env::args();
    args_iter.next();
    if let Some(action) = args_iter.next() {
        match action.as_str() {
            "mount" => return Ok(AuricOperationMode::Mount),
            "unmount" => return Ok(AuricOperationMode::Unmount),
            _ => {
                return Err(AuricError::Invocation(format!(
                    "unknown action: ``{}''",
                    action
                )))
            }
        }
    }
    Err(AuricError::Invocation("no action given".to_string()))
}

impl AuricImpl {
    pub fn new() -> Result<AuricImpl, AuricError> {
        let sshfs_manager = SshfsManager::new()?;
        let loop_backing_device_path = sshfs_manager.loop_backing_device_path();
        Ok(AuricImpl {
            sshfs_manager: sshfs_manager,
            loop_manager: LoopManager::new(&loop_backing_device_path),
            luks_manager: LuksManager::new(),
        })
    }

    fn mount(&self) -> Result<(), AuricError> {
        self.sshfs_manager.mount()?;
        self.loop_manager.attach()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.unlock(&loop_device)?;
        self.luks_manager.mount()
    }

    fn unmount(&self) -> Result<(), AuricError> {
        self.luks_manager.unmount()?;
        let loop_device = self.loop_manager.find()?;
        self.luks_manager.lock(&loop_device)?;
        self.loop_manager.detach()?;
        self.sshfs_manager.unmount()
    }

    pub fn act(&self, mode: AuricOperationMode) -> Result<(), AuricError> {
        match mode {
            AuricOperationMode::Mount => return self.mount(),
            AuricOperationMode::Unmount => return self.unmount(),
        }
    }
}

fn main_impl() -> Result<(), AuricError> {
    let action = get_action()?;
    let auric_impl = AuricImpl::new()?;
    auric_impl.act(action)
}

fn main() {
    std::process::exit(match main_impl() {
        Ok(_) => 0,
        Err(e) => {
            eprintln!("{:?}", e);
            1
        }
    });
}
<|endoftext|>


<commit_before>
pub use libc::c_int;
use libc::c_uint;
use libc::c_char;
use libc::c_uchar;
use libc::c_void;
use libc::size_t;
use libc::c_ulong;
use libc::c_long;
use libc::c_double;
use std::option::Option;
//use core::marker::Sync;

include!(concat!(env!("OUT_DIR"), "/nif_versions.snippet"));
// example of included content:
// const NIF_MAJOR_VERSION: c_int = 2;
// const NIF_MINOR_VERSION: c_int = 7;

// FIXME
#[allow(non_camel_case_types)]
pub type ERL_NIF_UINT = size_t;
//type ERL_NIF_UINT = usize;  // users complain about non-ffi type.

#[allow(non_camel_case_types)]
pub type ERL_NIF_TERM = *const c_void;
//pub type ERL_NIF_TERM = ERL_NIF_UINT;

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifEnv;

// #[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifFunc {
	pub name:     *const u8,
	pub arity:    c_uint,
//	pub function: Option<extern "C" fn(env: *mut ErlNifEnv, argc: c_int, argv: *const ERL_NIF_TERM) -> ERL_NIF_TERM>,
	pub function: extern "C" fn(env: *mut ErlNifEnv, argc: c_int, argv: *const ERL_NIF_TERM) -> ERL_NIF_TERM,
	pub flags:    c_uint,
}
// unsafe impl Sync for ErlNifFunc {}

// #[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifEntry {
	pub major:        c_int,
	pub minor:        c_int,
	pub name:         *const u8,
	pub num_of_funcs: c_int,
	pub funcs:        *const ErlNifFunc,
	pub load:    Option<extern "C" fn(arg1: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM)-> c_int>,
	pub reload:  Option<extern "C" fn(arg1: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM) -> c_int>,
	pub upgrade: Option<extern "C" fn(arg1: *mut ErlNifEnv,	priv_data: *mut *mut c_void, old_priv_data:	*mut *mut c_void, load_info: ERL_NIF_TERM) -> c_int>,
	pub unload:  Option<extern "C" fn(arg1: *mut ErlNifEnv,	priv_data: *mut c_void)	-> ()>,
	pub vm_variant: *const u8,
	pub options: c_uint,
}
//unsafe impl Sync for ErlNifEntry {}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifBinary {
	size: size_t,
	data: *mut [u8],
	/* Internals (avert your eyes) */
	bin_term: ERL_NIF_TERM,
	ref_bin: *mut c_void,
}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifResourceType;

#[allow(missing_copy_implementations)]
pub type ErlNifResourceDtor = extern "C" fn(arg1: *mut ErlNifEnv, arg2: *mut c_void) -> ();

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifResourceFlags {
	ERL_NIF_RT_CREATE = 1,
	ERL_NIF_RT_TAKEOVER = 2,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifCharEncoding {
	ERL_NIF_LATIN1 = 1,
	DUMMY = 999, // prevents "univariant enum" compile error
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ErlNifPid {
	pid: ERL_NIF_TERM,
}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifSysInfo {
	pub driver_major_version: c_int,
	pub driver_minor_version: c_int,
	pub erts_version: *mut c_char,
	pub otp_release: *mut c_char,
	pub thread_support: c_int,
	pub smp_support: c_int,
	pub async_threads: c_int,
	pub scheduler_threads: c_int,
	pub nif_major_version: c_int,
	pub nif_minor_version: c_int,
	pub dirty_scheduler_support: c_int,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifDirtyTaskFlags {
	ERL_NIF_DIRTY_JOB_CPU_BOUND = 1,
	ERL_NIF_DIRTY_JOB_IO_BOUND = 2,
}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifMapIterator {
	map: ERL_NIF_TERM,
	t_limit: ERL_NIF_UINT,
	idx: ERL_NIF_UINT,
	ks: *mut ERL_NIF_TERM,
	vs: *mut ERL_NIF_TERM,
	__spare__: [*mut c_void; 2us],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifMapIteratorEntry {
	ERL_NIF_MAP_ITERATOR_HEAD = 1,
	ERL_NIF_MAP_ITERATOR_TAIL = 2,
}

include!(concat!(env!("OUT_DIR"), "/nif_api.snippet"));
// example of included content:
// extern "C" {
//     pub fn enif_priv_data(arg1: *mut ErlNifEnv) -> *mut c_void;
//     pub fn enif_alloc(size: size_t) -> *mut c_void;
//     pub fn enif_free(ptr: *mut c_void);
//     pub fn enif_is_atom(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
//     pub fn enif_is_binary(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
// ...

#[cfg(target_pointer_width = "64")]
pub fn enif_make_int64(env: *mut ErlNifEnv, i: i64) -> ERL_NIF_TERM
 	{ unsafe {enif_make_long(env, i)}}

#[cfg(target_pointer_width = "64")]
pub fn enif_make_uint64(env: *mut ErlNifEnv, i: u64) -> ERL_NIF_TERM
 	{ unsafe {enif_make_ulong(env, i) }}

#[cfg(target_pointer_width = "64")]
pub fn enif_get_int64(env: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut i64) -> c_int
 	{ unsafe {enif_get_long(env, term, ip) }}

#[cfg(target_pointer_width = "64")]
pub fn enif_get_uint64(env: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut u64) -> c_int
 	{ unsafe {enif_get_ulong(env, term, ip) }}
<commit_msg>fix ErlNifBinary data pointer<commit_after>
pub use libc::c_int;
use libc::c_uint;
use libc::c_char;
use libc::c_uchar;
use libc::c_void;
use libc::size_t;
use libc::c_ulong;
use libc::c_long;
use libc::c_double;
use std::option::Option;
//use core::marker::Sync;

include!(concat!(env!("OUT_DIR"), "/nif_versions.snippet"));
// example of included content:
// const NIF_MAJOR_VERSION: c_int = 2;
// const NIF_MINOR_VERSION: c_int = 7;

// FIXME
#[allow(non_camel_case_types)]
pub type ERL_NIF_UINT = size_t;
//type ERL_NIF_UINT = usize;  // users complain about non-ffi type.

#[allow(non_camel_case_types)]
pub type ERL_NIF_TERM = *const c_void;
//pub type ERL_NIF_TERM = ERL_NIF_UINT;

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifEnv;

// #[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifFunc {
	pub name:     *const u8,
	pub arity:    c_uint,
//	pub function: Option<extern "C" fn(env: *mut ErlNifEnv, argc: c_int, argv: *const ERL_NIF_TERM) -> ERL_NIF_TERM>,
	pub function: extern "C" fn(env: *mut ErlNifEnv, argc: c_int, argv: *const ERL_NIF_TERM) -> ERL_NIF_TERM,
	pub flags:    c_uint,
}
// unsafe impl Sync for ErlNifFunc {}

// #[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifEntry {
	pub major:        c_int,
	pub minor:        c_int,
	pub name:         *const u8,
	pub num_of_funcs: c_int,
	pub funcs:        *const ErlNifFunc,
	pub load:    Option<extern "C" fn(arg1: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM)-> c_int>,
	pub reload:  Option<extern "C" fn(arg1: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM) -> c_int>,
	pub upgrade: Option<extern "C" fn(arg1: *mut ErlNifEnv,	priv_data: *mut *mut c_void, old_priv_data:	*mut *mut c_void, load_info: ERL_NIF_TERM) -> c_int>,
	pub unload:  Option<extern "C" fn(arg1: *mut ErlNifEnv,	priv_data: *mut c_void)	-> ()>,
	pub vm_variant: *const u8,
	pub options: c_uint,
}
//unsafe impl Sync for ErlNifEntry {}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifBinary {
	size: size_t,
	data: *const u8,
	/* Internals (avert your eyes) */
	bin_term: ERL_NIF_TERM,
	ref_bin: *mut c_void,
}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifResourceType;

#[allow(missing_copy_implementations)]
pub type ErlNifResourceDtor = extern "C" fn(arg1: *mut ErlNifEnv, arg2: *mut c_void) -> ();

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifResourceFlags {
	ERL_NIF_RT_CREATE = 1,
	ERL_NIF_RT_TAKEOVER = 2,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifCharEncoding {
	ERL_NIF_LATIN1 = 1,
	DUMMY = 999, // prevents "univariant enum" compile error
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ErlNifPid {
	pid: ERL_NIF_TERM,
}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifSysInfo {
	pub driver_major_version: c_int,
	pub driver_minor_version: c_int,
	pub erts_version: *mut c_char,
	pub otp_release: *mut c_char,
	pub thread_support: c_int,
	pub smp_support: c_int,
	pub async_threads: c_int,
	pub scheduler_threads: c_int,
	pub nif_major_version: c_int,
	pub nif_minor_version: c_int,
	pub dirty_scheduler_support: c_int,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifDirtyTaskFlags {
	ERL_NIF_DIRTY_JOB_CPU_BOUND = 1,
	ERL_NIF_DIRTY_JOB_IO_BOUND = 2,
}

#[allow(missing_copy_implementations)]
#[repr(C)]
pub struct ErlNifMapIterator {
	map: ERL_NIF_TERM,
	t_limit: ERL_NIF_UINT,
	idx: ERL_NIF_UINT,
	ks: *mut ERL_NIF_TERM,
	vs: *mut ERL_NIF_TERM,
	__spare__: [*mut c_void; 2us],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum ErlNifMapIteratorEntry {
	ERL_NIF_MAP_ITERATOR_HEAD = 1,
	ERL_NIF_MAP_ITERATOR_TAIL = 2,
}

include!(concat!(env!("OUT_DIR"), "/nif_api.snippet"));
// example of included content:
// extern "C" {
//     pub fn enif_priv_data(arg1: *mut ErlNifEnv) -> *mut c_void;
//     pub fn enif_alloc(size: size_t) -> *mut c_void;
//     pub fn enif_free(ptr: *mut c_void);
//     pub fn enif_is_atom(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
//     pub fn enif_is_binary(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
// ...

#[cfg(target_pointer_width = "64")]
pub fn enif_make_int64(env: *mut ErlNifEnv, i: i64) -> ERL_NIF_TERM
 	{ unsafe {enif_make_long(env, i)}}

#[cfg(target_pointer_width = "64")]
pub fn enif_make_uint64(env: *mut ErlNifEnv, i: u64) -> ERL_NIF_TERM
 	{ unsafe {enif_make_ulong(env, i) }}

#[cfg(target_pointer_width = "64")]
pub fn enif_get_int64(env: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut i64) -> c_int
 	{ unsafe {enif_get_long(env, term, ip) }}

#[cfg(target_pointer_width = "64")]
pub fn enif_get_uint64(env: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut u64) -> c_int
 	{ unsafe {enif_get_ulong(env, term, ip) }}
<|endoftext|>


<commit_before>use collections::string::ToString;
use core::ops::*;

use bounded::Bounded;
use to_primitive::ToPrimitive;
use from_primitive::FromPrimitive;
use round::Round;
use one::One;
use sqrt::Sqrt;
use trig::Trig;
use zero::Zero;

pub trait Num:
    Clone + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>

    + AddAssign<Self>
    + MulAssign<Self>
    + SubAssign<Self>
    + DivAssign<Self>
    + RemAssign<Self>
{
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-50).clamp(0, 100), 0);
    /// assert_eq!(50.clamp(0, 100), 50);
    /// assert_eq!(150.clamp(0, 100), 100);
    /// ~~~
    #[inline(always)]
    fn clamp(self, min: Self, max: Self) -> Self {
        if self < min {
            min
        } else if self > max {
            max
        } else {
            self
        }
    }
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-0.5).clamp01(), 0.0);
    /// assert_eq!(0.5.clamp01(), 0.5);
    /// assert_eq!(1.50.clamp01(), 1.0);
    /// ~~~
    #[inline(always)]
    fn clamp01(self) -> Self {
        self.clamp(Zero::zero(), One::one())
    }
}

impl<T> Num for T where T:
    Clone + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>

    + AddAssign<T>
    + MulAssign<T>
    + SubAssign<T>
    + DivAssign<T>
    + RemAssign<T> {}
<commit_msg>clean up<commit_after>use collections::string::ToString;
use core::ops::*;

use bounded::Bounded;
use to_primitive::ToPrimitive;
use from_primitive::FromPrimitive;
use round::Round;
use one::One;
use sqrt::Sqrt;
use trig::Trig;
use zero::Zero;

pub trait Num:
    Clone + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>

    + AddAssign<Self>
    + MulAssign<Self>
    + SubAssign<Self>
    + DivAssign<Self>
    + RemAssign<Self>
{
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-50).clamp(&0, &100), 0);
    /// assert_eq!(50.clamp(&0, &100), 50);
    /// assert_eq!(150.clamp(&0, &100), 100);
    /// ~~~
    #[inline(always)]
    fn clamp(&self, min: &Self, max: &Self) -> Self {
        if self < min {
            min.clone()
        } else if self > max {
            max.clone()
        } else {
            self.clone()
        }
    }
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-0.5).clamp01(), 0.0);
    /// assert_eq!(0.5.clamp01(), 0.5);
    /// assert_eq!(1.50.clamp01(), 1.0);
    /// ~~~
    #[inline(always)]
    fn clamp01(&self) -> Self {
        self.clamp(&Zero::zero(), &One::one())
    }
}

impl<T> Num for T where T:
    Clone + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>

    + AddAssign<T>
    + MulAssign<T>
    + SubAssign<T>
    + DivAssign<T>
    + RemAssign<T> {}
<|endoftext|>


<commit_before>use ipnetwork::IpNetwork;

use maxminddb::geoip2;
use maxminddb::Within;

fn main() -> Result<(), String> {
    let mut args = std::env::args().skip(1);
    let reader = maxminddb::Reader::open_readfile(
        args.next()
            .ok_or("First argument must be the path to the IP database")?,
    )
    .unwrap();
    let cidr: String = args
        .next()
        .ok_or("Second argument must be the IP address and mask in CIDR notation")?
        .parse()
        .unwrap();
    let ip_net = if cidr.contains(":") {
        IpNetwork::V6(cidr.parse().unwrap())
    } else {
        IpNetwork::V4(cidr.parse().unwrap())
    };
    // TODO: is there a way to omit the _, it should be discernable from the reader
    let within: Within<geoip2::City, _> = reader.within(ip_net).unwrap();
    for item in within {
        println!("item={:#?}", item);
    }
    Ok(())
}
<commit_msg>Cleaner way to hint to compiler about the iterator item type<commit_after>use ipnetwork::IpNetwork;

use maxminddb::geoip2;

fn main() -> Result<(), String> {
    let mut args = std::env::args().skip(1);
    let reader = maxminddb::Reader::open_readfile(
        args.next()
            .ok_or("First argument must be the path to the IP database")?,
    )
    .unwrap();
    let cidr: String = args
        .next()
        .ok_or("Second argument must be the IP address and mask in CIDR notation")?
        .parse()
        .unwrap();
    let ip_net = if cidr.contains(":") {
        IpNetwork::V6(cidr.parse().unwrap())
    } else {
        IpNetwork::V4(cidr.parse().unwrap())
    };
    // TODO: error handling
    for i in reader.within(ip_net).unwrap() {
        let (ip_net, info): (IpNetwork, geoip2::City) = (i.ip_net, i.info);
        println!("ip_net={}, info={:#?}", ip_net, info);
    }
    Ok(())
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use regex::Regex;

pub mod id;
pub mod id_type;
pub mod header;
pub mod hash;

use module::Module;
use storage::file::id::*;
use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash;
use super::parser::{FileHeaderParser, Parser, ParserError};

use self::header::spec::*;
use self::header::data::*;

/*
 * Internal abstract view on a file. Does not exist on the FS and is just kept
 * internally until it is written to disk.
 */
pub struct File<'a> {
    owning_module   : &'a Module<'a>,
    header          : FileHeaderData,
    data            : String,
    id              : FileID,
}

impl<'a> File<'a> {

    pub fn new(module: &'a Module<'a>) -> File<'a> {
        let f = File {
            owning_module: module,
            header: FileHeaderData::Null,
            data: String::from(""),
            id: File::get_new_file_id(),
        };
        debug!("Create new File object: {:?}", f);
        f
    }

    pub fn from_parser_result(module: &'a Module<'a>, id: FileID, header: FileHeaderData, data: String) -> File<'a> {
        let f = File {
            owning_module: module,
            header: header,
            data: data,
            id: id,
        };
        debug!("Create new File object from parser result: {:?}", f);
        f
    }

    pub fn new_with_header(module: &'a Module<'a>, h: FileHeaderData) -> File<'a> {
        let f = File {
            owning_module: module,
            header: h,
            data: String::from(""),
            id: File::get_new_file_id(),
        };
        debug!("Create new File object with header: {:?}", f);
        f
    }

    pub fn new_with_data(module: &'a Module<'a>, d: String) -> File<'a> {
        let f = File {
            owning_module: module,
            header: FileHeaderData::Null,
            data: d,
            id: File::get_new_file_id(),
        };
        debug!("Create new File object with data: {:?}", f);
        f
    }

    pub fn new_with_content(module: &'a Module<'a>, h: FileHeaderData, d: String) -> File<'a> {
        let f = File {
            owning_module: module,
            header: h,
            data: d,
            id: File::get_new_file_id(),
        };
        debug!("Create new File object with content: {:?}", f);
        f
    }

    /**
     * Call editor on the file
     *
     * Return true if exit code from editor was good (and content was changed), false otherwise.
     */
    pub fn edit(rt: &Runtime) {
        unimplemented!()
    }

    pub fn header(&self) -> FileHeaderData {
        self.header.clone()
    }

    pub fn data(&self) -> String {
        self.data.clone()
    }

    pub fn contents(&self) -> (FileHeaderData, String) {
        (self.header(), self.data())
    }

    pub fn id(&self) -> FileID {
        self.id.clone()
    }

    pub fn owner(&self) -> &'a Module<'a> {
        self.owning_module
    }

    pub fn matches_with(&self, r: &Regex) -> bool {
        r.is_match(&self.data[..]) || self.header.matches_with(r)
    }

    fn get_new_file_id() -> FileID {
        use uuid::Uuid;
        let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
        FileID::new(FileIDType::UUID, hash)
    }
}

impl<'a> Display for File<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt,
"[File] Owner : '{:?}'
        FileID: '{:?}'
        Header: '{:?}'
        Data  : '{:?}'",
               self.owning_module,
               self.header,
               self.data,
               self.id);
        Ok(())
    }

}

impl<'a> Debug for File<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt,
"[File] Owner : '{:?}'
        FileID: '{:?}'
        Header: '{:?}'
        Data  : '{:?}'",
               self.owning_module,
               self.header,
               self.data,
               self.id);
        Ok(())
    }

}

#[cfg(test)]
mod test {
    // we use the JSON parser here, so we can generate FileHeaderData
    use storage::json::parser::JsonHeaderParser;
    use super::match_header_spec;
    use storage::parser::{FileHeaderParser, ParserError};
    use storage::file::FileHeaderData as FHD;
    use storage::file::FileHeaderSpec as FHS;

    #[test]
    fn test_spec_matching() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser  = JsonHeaderParser::new(Some(spec.clone()));
        let datares = parser.read(Some(text.clone()));
        assert!(datares.is_ok(), "Text could not be parsed: '{}'", text);
        let data = datares.unwrap();

        let matchres = match_header_spec(&spec, &data);
        assert!(matchres.is_none(), "Matching returns error: {:?}", matchres);
    }
}

<commit_msg>Add File::edit_contents()<commit_after>use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use regex::Regex;

pub mod id;
pub mod id_type;
pub mod header;
pub mod hash;

use module::Module;
use storage::file::id::*;
use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash;
use super::parser::{FileHeaderParser, Parser, ParserError};

use self::header::spec::*;
use self::header::data::*;

/*
 * Internal abstract view on a file. Does not exist on the FS and is just kept
 * internally until it is written to disk.
 */
pub struct File<'a> {
    owning_module   : &'a Module<'a>,
    header          : FileHeaderData,
    data            : String,
    id              : FileID,
}

impl<'a> File<'a> {

    pub fn new(module: &'a Module<'a>) -> File<'a> {
        let f = File {
            owning_module: module,
            header: FileHeaderData::Null,
            data: String::from(""),
            id: File::get_new_file_id(),
        };
        debug!("Create new File object: {:?}", f);
        f
    }

    pub fn from_parser_result(module: &'a Module<'a>, id: FileID, header: FileHeaderData, data: String) -> File<'a> {
        let f = File {
            owning_module: module,
            header: header,
            data: data,
            id: id,
        };
        debug!("Create new File object from parser result: {:?}", f);
        f
    }

    pub fn new_with_header(module: &'a Module<'a>, h: FileHeaderData) -> File<'a> {
        let f = File {
            owning_module: module,
            header: h,
            data: String::from(""),
            id: File::get_new_file_id(),
        };
        debug!("Create new File object with header: {:?}", f);
        f
    }

    pub fn new_with_data(module: &'a Module<'a>, d: String) -> File<'a> {
        let f = File {
            owning_module: module,
            header: FileHeaderData::Null,
            data: d,
            id: File::get_new_file_id(),
        };
        debug!("Create new File object with data: {:?}", f);
        f
    }

    pub fn new_with_content(module: &'a Module<'a>, h: FileHeaderData, d: String) -> File<'a> {
        let f = File {
            owning_module: module,
            header: h,
            data: d,
            id: File::get_new_file_id(),
        };
        debug!("Create new File object with content: {:?}", f);
        f
    }

    /**
     * Call editor on the file
     *
     * Return true if exit code from editor was good (and content was changed), false otherwise.
     */
    pub fn edit(rt: &Runtime) {
        unimplemented!()
    }

    /**
     * Call editor on the file contents, but don't include the header inside the editor call.
     *
     * Return true if exit code from editor was good (and content was changed), false otherwise.
     */
    pub fn edit_contents(rt: &Runtime) -> bool {
    }

    pub fn header(&self) -> FileHeaderData {
        self.header.clone()
    }

    pub fn data(&self) -> String {
        self.data.clone()
    }

    pub fn contents(&self) -> (FileHeaderData, String) {
        (self.header(), self.data())
    }

    pub fn id(&self) -> FileID {
        self.id.clone()
    }

    pub fn owner(&self) -> &'a Module<'a> {
        self.owning_module
    }

    pub fn matches_with(&self, r: &Regex) -> bool {
        r.is_match(&self.data[..]) || self.header.matches_with(r)
    }

    fn get_new_file_id() -> FileID {
        use uuid::Uuid;
        let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
        FileID::new(FileIDType::UUID, hash)
    }
}

impl<'a> Display for File<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt,
"[File] Owner : '{:?}'
        FileID: '{:?}'
        Header: '{:?}'
        Data  : '{:?}'",
               self.owning_module,
               self.header,
               self.data,
               self.id);
        Ok(())
    }

}

impl<'a> Debug for File<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt,
"[File] Owner : '{:?}'
        FileID: '{:?}'
        Header: '{:?}'
        Data  : '{:?}'",
               self.owning_module,
               self.header,
               self.data,
               self.id);
        Ok(())
    }

}

#[cfg(test)]
mod test {
    // we use the JSON parser here, so we can generate FileHeaderData
    use storage::json::parser::JsonHeaderParser;
    use super::match_header_spec;
    use storage::parser::{FileHeaderParser, ParserError};
    use storage::file::FileHeaderData as FHD;
    use storage::file::FileHeaderSpec as FHS;

    #[test]
    fn test_spec_matching() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser  = JsonHeaderParser::new(Some(spec.clone()));
        let datares = parser.read(Some(text.clone()));
        assert!(datares.is_ok(), "Text could not be parsed: '{}'", text);
        let data = datares.unwrap();

        let matchres = match_header_spec(&spec, &data);
        assert!(matchres.is_none(), "Matching returns error: {:?}", matchres);
    }
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::util::StateCallback;

pub struct Transaction {}

impl Transaction {
    pub fn new<F, T>(
        timeout: u64,
        callback: StateCallback<Result<T, crate::Error>>,
        new_device_cb: F,
    ) -> Result<Self, crate::Error>
    where
        F: Fn(String, &Fn() -> bool),
    {
        callback.call(Err(crate::Error::NotSupported));
        Err(crate::Error::NotSupported)
    }

    pub fn cancel(&mut self) {
        /* No-op. */
    }
}
<commit_msg>stub fix<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::util::StateCallback;

pub struct Transaction {}

impl Transaction {
    pub fn new<F, T>(
        timeout: u64,
        callback: StateCallback<Result<T, crate::Error>>,
        new_device_cb: F,
    ) -> Result<Self, crate::Error>
    where
        F: Fn(String, &dyn Fn() -> bool),
    {
        callback.call(Err(crate::Error::NotSupported));
        Err(crate::Error::NotSupported)
    }

    pub fn cancel(&mut self) {
        /* No-op. */
    }
}
<|endoftext|>


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

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct GistFile {
  pub size: i64,
  pub raw_url: String,
  // type: String
//  pub truncated: bool,
  pub language: Option<String>
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Gist {
  pub url: String,
  pub forks_url: String,
  pub commits_url: String,
  pub id: String,
  pub description: Option<String>,
  pub public: bool,
  pub owner: User,
  pub user: Option<User>,
  pub files: HashMap<String, GistFile>,
  pub comments: i64,
  pub comments_url: String,
  pub html_url: String,
  pub git_pull_url: String,
  pub git_push_url: String,
  pub created_at: String,
  pub updated_at: String
}

#[derive(Debug, RustcDecodable)]
pub struct GistFork {
  user: User,
  url: String,
  id: String,
  created_at: String,
  updated_at: String
}

#[derive(Debug, RustcEncodable)]
pub struct Content {
  pub content: &'static str
}

impl Content {
  pub fn new(content: &'static str) -> Content {
    Content { content: content }
  }
}

#[derive(Debug, RustcEncodable)]
pub struct GistReq {
  pub description: Option<&'static str>,
  pub public: Option<bool>,
  pub files: HashMap<&'static str, Content>
}

impl GistReq {
  pub fn new(desc: Option<&'static str>, public: bool, files: HashMap<&'static str, Content>) -> GistReq {
    GistReq {
      description: desc,
      public: Some(public),
      files: files
    }
  }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Permissions {
  pub admin: bool,
  pub push: bool,
  pub pull: bool
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Repo {
  pub id: i64,
  pub owner: User,
  pub name: String,
  pub full_name: String,
  pub description: String,
  // private (keyword)
  pub fork: bool,
  pub url: String,
  html_url: String,
  archive_url: String,
  assignees_url: String,
  blobs_url: String,
  branches_url: String,
  clone_url: String,
  collaborators_url: String,
  comments_url: String,
  commits_url: String,
  compare_url: String,
  contents_url: String,
  contributors_url: String,
  downloads_url: String,
  events_url: String,
  forks_url: String,
  git_commits_url: String,
  git_refs_url: String,
  git_tags_url: String,
  git_url: String,
  hooks_url: String,
  issue_comment_url: String,
  issue_events_url: String,
  issues_url: String,
  keys_url: String,
  labels_url: String,
  languages_url: String,
  merges_url: String,
  milestones_url: String,
  mirror_url: Option<String>,
  notifications_url: String,
  pulls_url: String,
  releases_url: String,
  ssh_url: String,
  stargazers_url: String,
  statuses_url: String,
  subscribers_url: String,
  subscription_url: String,
  svn_url: String,
  tags_url: String,
  teams_url: String,
  trees_url: String,
  homepage: String,
  language: Option<String>,
  forks_count: i64,
  stargazers_count: i64,
  watchers_count: i64,
  size: i64,
  default_branch: String,
  open_issues_count: i64,
  has_issues: bool,
  has_wiki: bool,
  has_pages: bool,
  has_downloads: bool,
  pushed_at: String,
  created_at: String,
  updated_at: String,
//  permissions: Permissions
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct User {
  pub login: String,
  pub id: u64,
  pub avatar_url: String,
  pub gravatar_id: String,
  pub url: String,
  pub html_url: String,
  pub followers_url: String,
  following_url: String,
  gists_url: String,
  starred_url: String,
  subscriptions_url: String,
  organizations_url: String,
  repos_url: String,
  events_url: String,
  received_events_url: String,
  // type (keyword)
  site_admin: bool
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Commit {
  pub label: String,
  // ref (keyword)
  pub sha: String,
  pub user: User,
  pub repo: Option<Repo>
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Label {
  pub url: String,
  pub name: String,
  pub color: String
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Pull {
  pub id: u64,
  pub url: String,
  pub html_url: String,
  diff_url: String,
  patch_url: String,
  issue_url: String,
  commits_url: String,
  review_comments_url: String,
  review_comment_url: String,
  comments_url: String,
  statuses_url: String,
  pub number: u64,
  pub state: String,
  pub title: String,
  pub body: String,
  pub created_at: String,
  pub updated_at: String,
  pub closed_at: Option<String>,
  pub merged_at: Option<String>,
  pub head: Commit,
//  pub base: Commit,
  // links
  pub user: User
}
<commit_msg>fill in some rep blanks<commit_after>use std::collections::HashMap;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct GistFile {
  pub size: i64,
  pub raw_url: String,
  // type: String
//  pub truncated: bool,
  pub language: Option<String>
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Gist {
  pub url: String,
  pub forks_url: String,
  pub commits_url: String,
  pub id: String,
  pub description: Option<String>,
  pub public: bool,
  pub owner: User,
  pub user: Option<User>,
  pub files: HashMap<String, GistFile>,
  pub comments: i64,
  pub comments_url: String,
  pub html_url: String,
  pub git_pull_url: String,
  pub git_push_url: String,
  pub created_at: String,
  pub updated_at: String
}

#[derive(Debug, RustcDecodable)]
pub struct GistFork {
  user: User,
  url: String,
  id: String,
  created_at: String,
  updated_at: String
}

#[derive(Debug, RustcEncodable)]
pub struct Content {
  pub filename: Option<&'static str>,
  pub content: &'static str
}

impl Content {
  pub fn new(filename: Option<&'static str>, content: &'static str) -> Content {
    Content { filename: filename, content: content }
  }
}

#[derive(Debug, RustcEncodable)]
pub struct GistReq {
  pub description: Option<&'static str>,
  pub public: Option<bool>,
  pub files: HashMap<&'static str, Content>
}

impl GistReq {
  pub fn new(desc: Option<&'static str>, public: bool, files: HashMap<&'static str, &'static str>) -> GistReq {
    let mut contents = HashMap::new();
    for (k,v) in files {
      contents.insert(k, Content::new(None, v));
    }
    GistReq {
      description: desc,
      public: Some(public),
      files: contents
    }
  }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Permissions {
  pub admin: bool,
  pub push: bool,
  pub pull: bool
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Repo {
  pub id: i64,
  pub owner: User,
  pub name: String,
  pub full_name: String,
  pub description: String,
  // private (keyword)
  pub fork: bool,
  pub url: String,
  html_url: String,
  archive_url: String,
  assignees_url: String,
  blobs_url: String,
  branches_url: String,
  clone_url: String,
  collaborators_url: String,
  comments_url: String,
  commits_url: String,
  compare_url: String,
  contents_url: String,
  contributors_url: String,
  downloads_url: String,
  events_url: String,
  forks_url: String,
  git_commits_url: String,
  git_refs_url: String,
  git_tags_url: String,
  git_url: String,
  hooks_url: String,
  issue_comment_url: String,
  issue_events_url: String,
  issues_url: String,
  keys_url: String,
  labels_url: String,
  languages_url: String,
  merges_url: String,
  milestones_url: String,
  mirror_url: Option<String>,
  notifications_url: String,
  pulls_url: String,
  releases_url: String,
  ssh_url: String,
  stargazers_url: String,
  statuses_url: String,
  subscribers_url: String,
  subscription_url: String,
  svn_url: String,
  tags_url: String,
  teams_url: String,
  trees_url: String,
  homepage: Option<String>,
  language: Option<String>,
  forks_count: i64,
  stargazers_count: i64,
  watchers_count: i64,
  size: i64,
  default_branch: String,
  open_issues_count: i64,
  has_issues: bool,
  has_wiki: bool,
  has_pages: bool,
  has_downloads: bool,
  pushed_at: String,
  created_at: String,
  updated_at: String,
//  permissions: Permissions
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct User {
  pub login: String,
  pub id: u64,
  pub avatar_url: String,
  pub gravatar_id: String,
  pub url: String,
  pub html_url: String,
  pub followers_url: String,
  following_url: String,
  gists_url: String,
  starred_url: String,
  subscriptions_url: String,
  organizations_url: String,
  repos_url: String,
  events_url: String,
  received_events_url: String,
  // type (keyword)
  site_admin: bool
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Commit {
  pub label: String,
  // ref (keyword)
  pub sha: String,
  pub user: User,
  pub repo: Option<Repo>
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Label {
  pub url: String,
  pub name: String,
  pub color: String
}

#[derive(Debug, RustcEncodable)]
pub struct PullReq {
  pub title: &'static str,
  pub head: &'static str,
  pub base: &'static str,
  pub body: Option<&'static str>
}

impl PullReq {
  pub fn new(title: &'static str, head: &'static str, base: &'static str, body: Option<&'static str>) -> PullReq {
    PullReq {
      title: title,
      head: head,
      base: base,
      body: body
    }
  }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Pull {
  pub id: u64,
  pub url: String,
  pub html_url: String,
  pub diff_url: String,
  pub patch_url: String,
  pub issue_url: String,
  pub commits_url: String,
  pub review_comments_url: String,
  pub review_comment_url: String,
  pub comments_url: String,
  pub statuses_url: String,
  pub number: u64,
  pub state: String,
  pub title: String,
  pub body: String,
  pub created_at: String,
  pub updated_at: String,
  pub closed_at: Option<String>,
  pub merged_at: Option<String>,
  //pub head: Commit,
//  pub base: Commit,
  // links
  pub user: User,
  pub merge_commit_sha: Option<String>,
  pub mergeable: Option<bool>,
  pub merged_by: Option<User>,
  pub comments: Option<u64>,
  pub commits: Option<u64>,
  pub additions: Option<u64>,
  pub deletions: Option<u64>,
  pub changed_files: Option<u64>
}
<|endoftext|>