<commit_before>import std::vec;
import std::str;
import std::istr;
import std::int;
import std::option;
import std::option::none;
import std::option::some;
import middle::ty;
import middle::ty::*;
import metadata::encoder;
import syntax::print::pp;
import syntax::print::pprust;
import syntax::print::pprust::path_to_str;
import syntax::print::pprust::constr_args_to_str;
import syntax::print::pprust::proto_to_str;
import pp::word;
import pp::eof;
import pp::zerobreak;
import pp::hardbreak;
import syntax::ast_util::ty_mach_to_str;
import syntax::ast;
import middle::ast_map;
import metadata::csearch;

fn mode_str(m: &ty::mode) -> istr {
    alt m {
      mo_val. { ~"" }
      mo_alias(false) { ~"&" }
      mo_alias(true) { ~"&mutable " }
      mo_move. { ~"-" }
    }
}

fn mode_str_1(m: &ty::mode) -> istr {
    alt m { mo_val. { ~"val" } _ { mode_str(m) } }
}

fn fn_ident_to_string(id: ast::node_id, i: &ast::fn_ident) -> istr {
    ret alt i {
      none. { ~"anon" + int::str(id) }
      some(s) { s }
    };
}

fn get_id_ident(cx: &ctxt, id: ast::def_id) -> istr {
    if id.crate != ast::local_crate {
        istr::connect(cx.ext_map.get(id), ~"::")
    } else {
        alt cx.items.find(id.node) {
          some(ast_map::node_item(it)) { it.ident }
          _ { fail "get_id_ident: can't find item in ast_map" }
        }
    }
}

fn ty_to_str(cx: &ctxt, typ: &t) -> istr {
    fn fn_input_to_str(cx: &ctxt, input: &{mode: middle::ty::mode, ty: t}) ->
       istr {
        let s = mode_str(input.mode);
        ret s + ty_to_str(cx, input.ty);
    }
    fn fn_to_str(cx: &ctxt, proto: ast::proto, ident: option::t<ast::ident>,
                 inputs: &[arg], output: t, cf: ast::controlflow,
                 constrs: &[@constr]) -> istr {
        let s = proto_to_str(proto);
        alt ident {
          some(i) {
            s += ~" ";
            s += i;
          }
          _ { }
        }
        s += ~"(";
        let strs = [];
        for a: arg in inputs { strs += [fn_input_to_str(cx, a)]; }
        s += istr::connect(strs, ~", ");
        s += ~")";
        if struct(cx, output) != ty_nil {
            alt cf {
              ast::noreturn. { s += ~" -> !"; }
              ast::return. { s += ~" -> " + ty_to_str(cx, output); }
            }
        }
        s += constrs_str(constrs);
        ret s;
    }
    fn method_to_str(cx: &ctxt, m: &method) -> istr {
        ret fn_to_str(cx, m.proto, some::<ast::ident>(m.ident), m.inputs,
                      m.output, m.cf, m.constrs) + ~";";
    }
    fn field_to_str(cx: &ctxt, f: &field) -> istr {
        ret f.ident + ~": " + mt_to_str(cx, f.mt);
    }
    fn mt_to_str(cx: &ctxt, m: &mt) -> istr {
        let mstr;
        alt m.mut {
          ast::mut. { mstr = ~"mutable "; }
          ast::imm. { mstr = ~""; }
          ast::maybe_mut. { mstr = ~"mutable? "; }
        }
        ret mstr + ty_to_str(cx, m.ty);
    }
    alt cname(cx, typ) {
      some(cs) {
        ret cs;
      }
      _ { }
    }
    ret alt struct(cx, typ) {
          ty_native(_) { ~"native" }
          ty_nil. { ~"()" }
          ty_bot. { ~"_|_" }
          ty_bool. { ~"bool" }
          ty_int. { ~"int" }
          ty_float. { ~"float" }
          ty_uint. { ~"uint" }
          ty_machine(tm) { ty_mach_to_str(tm) }
          ty_char. { ~"char" }
          ty_str. { ~"str" }
          ty_istr. { ~"istr" }
          ty_box(tm) { ~"@" + mt_to_str(cx, tm) }
          ty_uniq(t) { ~"~" + ty_to_str(cx, t) }
          ty_vec(tm) { ~"[" + mt_to_str(cx, tm) + ~"]" }
          ty_type. { ~"type" }
          ty_rec(elems) {
            let strs: [istr] = [];
            for fld: field in elems { strs += [field_to_str(cx, fld)]; }
            ~"{" + istr::connect(strs, ~",") + ~"}"
          }
          ty_tup(elems) {
            let strs = [];
            for elem in elems { strs += [ty_to_str(cx, elem)]; }
            ~"(" + istr::connect(strs, ~",") + ~")"
          }
          ty_tag(id, tps) {
            let s = get_id_ident(cx, id);
            if vec::len::<t>(tps) > 0u {
                let strs: [istr] = [];
                for typ: t in tps { strs += [ty_to_str(cx, typ)]; }
                s += ~"[" + istr::connect(strs, ~",") + ~"]";
            }
            s
          }
          ty_fn(proto, inputs, output, cf, constrs) {
            fn_to_str(cx, proto, none, inputs, output, cf, constrs)
          }
          ty_native_fn(_, inputs, output) {
            fn_to_str(cx, ast::proto_fn, none, inputs, output, ast::return,
                      [])
          }
          ty_obj(meths) {
            let strs = [];
            for m: method in meths { strs += [method_to_str(cx, m)]; }
            ~"obj {\n\t" + istr::connect(strs, ~"\n\t") + ~"\n}"
          }
          ty_res(id, _, _) { get_id_ident(cx, id) }
          ty_var(v) { ~"<T" + int::str(v) + ~">" }
          ty_param(id, _) {
            ~"'" + istr::unsafe_from_bytes([('a' as u8) + (id as u8)])
          }
          _ { ty_to_short_str(cx, typ) }
        }
}

fn ty_to_short_str(cx: &ctxt, typ: t) -> istr {
    let s = encoder::encoded_ty(cx, typ);
    if istr::byte_len(s) >= 32u { s = istr::substr(s, 0u, 32u); }
    ret s;
}

fn constr_to_str(c: &@constr) -> istr {
    ret path_to_str(c.node.path) +
        pprust::constr_args_to_str(pprust::uint_to_str, c.node.args);
}

fn constrs_str(constrs: &[@constr]) -> istr {
    let s = ~"";
    let colon = true;
    for c: @constr in constrs {
        if colon { s += ~" : "; colon = false; } else { s += ~", "; }
        s += constr_to_str(c);
    }
    ret s;
}

fn ty_constr_to_str<Q>(c: &@ast::spanned<ast::constr_general_<ast::path, Q>>)
   -> istr {
    ret path_to_str(c.node.path) +
        constr_args_to_str::<ast::path>(path_to_str, c.node.args);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Eliminate an unchecked use of map::get in ppaux<commit_after>import std::vec;
import std::str;
import std::istr;
import std::int;
import std::option;
import std::option::none;
import std::option::some;
import middle::ty;
import middle::ty::*;
import metadata::encoder;
import syntax::print::pp;
import syntax::print::pprust;
import syntax::print::pprust::path_to_str;
import syntax::print::pprust::constr_args_to_str;
import syntax::print::pprust::proto_to_str;
import pp::word;
import pp::eof;
import pp::zerobreak;
import pp::hardbreak;
import syntax::ast_util::ty_mach_to_str;
import syntax::ast;
import middle::ast_map;
import metadata::csearch;

fn mode_str(m: &ty::mode) -> istr {
    alt m {
      mo_val. { ~"" }
      mo_alias(false) { ~"&" }
      mo_alias(true) { ~"&mutable " }
      mo_move. { ~"-" }
    }
}

fn mode_str_1(m: &ty::mode) -> istr {
    alt m { mo_val. { ~"val" } _ { mode_str(m) } }
}

fn fn_ident_to_string(id: ast::node_id, i: &ast::fn_ident) -> istr {
    ret alt i {
      none. { ~"anon" + int::str(id) }
      some(s) { s }
    };
}

fn get_id_ident(cx: &ctxt, id: ast::def_id) -> istr {
    if id.crate != ast::local_crate {
        alt cx.ext_map.find(id) {
          some(j) { istr::connect(j, ~"::") }
          _ { fail ("get_id_ident: can't find item in ext_map, id.crate = "
                    + istr::to_estr(int::str(id.crate))) }
        }
    } else {
        alt cx.items.find(id.node) {
          some(ast_map::node_item(it)) { it.ident }
          _ { fail "get_id_ident: can't find item in ast_map" }
        }
    }
}

fn ty_to_str(cx: &ctxt, typ: &t) -> istr {
    fn fn_input_to_str(cx: &ctxt, input: &{mode: middle::ty::mode, ty: t}) ->
       istr {
        let s = mode_str(input.mode);
        ret s + ty_to_str(cx, input.ty);
    }
    fn fn_to_str(cx: &ctxt, proto: ast::proto, ident: option::t<ast::ident>,
                 inputs: &[arg], output: t, cf: ast::controlflow,
                 constrs: &[@constr]) -> istr {
        let s = proto_to_str(proto);
        alt ident {
          some(i) {
            s += ~" ";
            s += i;
          }
          _ { }
        }
        s += ~"(";
        let strs = [];
        for a: arg in inputs { strs += [fn_input_to_str(cx, a)]; }
        s += istr::connect(strs, ~", ");
        s += ~")";
        if struct(cx, output) != ty_nil {
            alt cf {
              ast::noreturn. { s += ~" -> !"; }
              ast::return. { s += ~" -> " + ty_to_str(cx, output); }
            }
        }
        s += constrs_str(constrs);
        ret s;
    }
    fn method_to_str(cx: &ctxt, m: &method) -> istr {
        ret fn_to_str(cx, m.proto, some::<ast::ident>(m.ident), m.inputs,
                      m.output, m.cf, m.constrs) + ~";";
    }
    fn field_to_str(cx: &ctxt, f: &field) -> istr {
        ret f.ident + ~": " + mt_to_str(cx, f.mt);
    }
    fn mt_to_str(cx: &ctxt, m: &mt) -> istr {
        let mstr;
        alt m.mut {
          ast::mut. { mstr = ~"mutable "; }
          ast::imm. { mstr = ~""; }
          ast::maybe_mut. { mstr = ~"mutable? "; }
        }
        ret mstr + ty_to_str(cx, m.ty);
    }
    alt cname(cx, typ) {
      some(cs) {
        ret cs;
      }
      _ { }
    }
    ret alt struct(cx, typ) {
          ty_native(_) { ~"native" }
          ty_nil. { ~"()" }
          ty_bot. { ~"_|_" }
          ty_bool. { ~"bool" }
          ty_int. { ~"int" }
          ty_float. { ~"float" }
          ty_uint. { ~"uint" }
          ty_machine(tm) { ty_mach_to_str(tm) }
          ty_char. { ~"char" }
          ty_str. { ~"str" }
          ty_istr. { ~"istr" }
          ty_box(tm) { ~"@" + mt_to_str(cx, tm) }
          ty_uniq(t) { ~"~" + ty_to_str(cx, t) }
          ty_vec(tm) { ~"[" + mt_to_str(cx, tm) + ~"]" }
          ty_type. { ~"type" }
          ty_rec(elems) {
            let strs: [istr] = [];
            for fld: field in elems { strs += [field_to_str(cx, fld)]; }
            ~"{" + istr::connect(strs, ~",") + ~"}"
          }
          ty_tup(elems) {
            let strs = [];
            for elem in elems { strs += [ty_to_str(cx, elem)]; }
            ~"(" + istr::connect(strs, ~",") + ~")"
          }
          ty_tag(id, tps) {
            let s = get_id_ident(cx, id);
            if vec::len::<t>(tps) > 0u {
                let strs: [istr] = [];
                for typ: t in tps { strs += [ty_to_str(cx, typ)]; }
                s += ~"[" + istr::connect(strs, ~",") + ~"]";
            }
            s
          }
          ty_fn(proto, inputs, output, cf, constrs) {
            fn_to_str(cx, proto, none, inputs, output, cf, constrs)
          }
          ty_native_fn(_, inputs, output) {
            fn_to_str(cx, ast::proto_fn, none, inputs, output, ast::return,
                      [])
          }
          ty_obj(meths) {
            let strs = [];
            for m: method in meths { strs += [method_to_str(cx, m)]; }
            ~"obj {\n\t" + istr::connect(strs, ~"\n\t") + ~"\n}"
          }
          ty_res(id, _, _) { get_id_ident(cx, id) }
          ty_var(v) { ~"<T" + int::str(v) + ~">" }
          ty_param(id, _) {
            ~"'" + istr::unsafe_from_bytes([('a' as u8) + (id as u8)])
          }
          _ { ty_to_short_str(cx, typ) }
        }
}

fn ty_to_short_str(cx: &ctxt, typ: t) -> istr {
    let s = encoder::encoded_ty(cx, typ);
    if istr::byte_len(s) >= 32u { s = istr::substr(s, 0u, 32u); }
    ret s;
}

fn constr_to_str(c: &@constr) -> istr {
    ret path_to_str(c.node.path) +
        pprust::constr_args_to_str(pprust::uint_to_str, c.node.args);
}

fn constrs_str(constrs: &[@constr]) -> istr {
    let s = ~"";
    let colon = true;
    for c: @constr in constrs {
        if colon { s += ~" : "; colon = false; } else { s += ~", "; }
        s += constr_to_str(c);
    }
    ret s;
}

fn ty_constr_to_str<Q>(c: &@ast::spanned<ast::constr_general_<ast::path, Q>>)
   -> istr {
    ret path_to_str(c.node.path) +
        constr_args_to_str::<ast::path>(path_to_str, c.node.args);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>#![crate_name = "uu_seq"]

// TODO: Make -w flag work with decimals
// TODO: Support -f flag

extern crate getopts;
extern crate libc;

#[macro_use]
extern crate uucore;

use std::cmp;
use std::io::Write;

static NAME: &'static str = "seq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Clone)]
struct SeqOptions {
    separator: String,
    terminator: Option<String>,
    widths: bool
}

fn parse_float(mut s: &str) -> Result<f64, String> {
    if s.starts_with("+") {
        s = &s[1..];
    }
    match s.parse() {
        Ok(n) => Ok(n),
        Err(e) => Err(format!("seq: invalid floating point argument `{}`: {}", s, e))
    }
}

fn escape_sequences(s: &str) -> String {
    s.replace("\\n", "\n")
     .replace("\\t", "\t")
}

fn parse_options(args: Vec<String>, options: &mut SeqOptions) -> Result<Vec<String>, i32> {
    let mut seq_args = vec!();
    let mut iter = args.into_iter().skip(1);
    loop {
        match iter.next() {
            Some(arg) => match &arg[..] {
                "--help" | "-h" => {
                    print_help();
                    return Err(0);
                }
                "--version" | "-V" => {
                    print_version();
                    return Err(0);
                }
                "-s" | "--separator" => match iter.next() {
                    Some(sep) => options.separator = sep,
                    None => {
                        show_error!("expected a separator after {}", arg);
                        return Err(1);
                    }
                },
                "-t" | "--terminator" => match iter.next() {
                    Some(term) => options.terminator = Some(term),
                    None => {
                        show_error!("expected a terminator after '{}'", arg);
                        return Err(1);
                    }
                },
                "-w" | "--widths" => options.widths = true,
                "--" => {
                    seq_args.extend(iter);
                    break;
                },
                _ => {
                    if arg.len() > 1 && arg.chars().next().unwrap() == '-' {
                        let argptr: *const String = &arg;  // escape from the borrow checker
                        let mut chiter = unsafe { &(*argptr)[..] }.chars().skip(1);
                        let mut ch = ' ';
                        while match chiter.next() { Some(m) => { ch = m; true } None => false } {
                            match ch {
                                'h' => {
                                    print_help();
                                    return Err(0);
                                }
                                'V' => {
                                    print_version();
                                    return Err(0);
                                }
                                's' => match iter.next() {
                                    Some(sep) => {
                                        options.separator = sep;
                                        let next = chiter.next();
                                        if next.is_some() {
                                            show_error!("unexpected character ('{}')", next.unwrap());
                                            return Err(1);
                                        }
                                    }
                                    None => {
                                        show_error!("expected a separator after {}", arg);
                                        return Err(1);
                                    }
                                },
                                't' => match iter.next() {
                                    Some(term) => {
                                        options.terminator = Some(term);
                                        let next = chiter.next();
                                        if next.is_some() {
                                            show_error!("unexpected character ('{}')", next.unwrap());
                                            return Err(1);
                                        }
                                    }
                                    None => {
                                        show_error!("expected a terminator after {}", arg);
                                        return Err(1);
                                    }
                                },
                                'w' => options.widths = true,
                                _ => { seq_args.push(arg); break }
                            }
                        }
                    } else {
                        seq_args.push(arg);
                    }
                }
            },
            None => break
        }
    }
    Ok(seq_args)
}

fn print_help() {
    let mut opts = getopts::Options::new();

    opts.optopt("s", "separator", "Separator character (defaults to \\n)", "");
    opts.optopt("t", "terminator", "Terminator character (defaults to separator)", "");
    opts.optflag("w", "widths", "Equalize widths of all numbers by padding with zeros");
    opts.optflag("h", "help", "print this help text and exit");
    opts.optflag("V", "version", "print version and exit");

    println!("{} {}\n", NAME, VERSION);
    println!("Usage:\n  {} [-w] [-s string] [-t string] [first [step]] last\n", NAME);
    println!("{}", opts.usage("Print sequences of numbers"));
}

fn print_version() {
    println!("{} {}", NAME, VERSION);
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut options = SeqOptions {
        separator: "\n".to_string(),
        terminator: None,
        widths: false
    };
    let free = match parse_options(args, &mut options) {
        Ok(m) => m,
        Err(f) => return f
    };
    if free.len() < 1 || free.len() > 3 {
        crash!(1, "too {} operands.\nTry '{} --help' for more information.",
               if free.len() < 1 { "few" } else { "many" }, NAME);
    }
    let mut largest_dec = 0;
    let mut padding = 0;
    let first = if free.len() > 1 {
        let slice = &free[0][..];
        let len = slice.len();
        let dec = slice.find('.').unwrap_or(len);
        largest_dec = len - dec;
        padding = dec;
        match parse_float(slice) {
            Ok(n) => n,
            Err(s) => { show_error!("{}", s); return 1; }
        }
    } else {
        1.0
    };
    let step = if free.len() > 2 {
        let slice = &free[1][..];
        let len = slice.len();
        let dec = slice.find('.').unwrap_or(len);
        largest_dec = cmp::max(largest_dec, len - dec);
        padding = cmp::max(padding, dec);
        match parse_float(slice) {
            Ok(n) => n,
            Err(s) => { show_error!("{}", s); return 1; }
        }
    } else {
        1.0
    };
    let last = {
        let slice = &free[free.len() - 1][..];
        padding = cmp::max(padding, slice.find('.').unwrap_or(slice.len()));
        match parse_float(slice) {
            Ok(n) => n,
            Err(s) => { show_error!("{}", s); return 1; }
        }
    };
    let separator = escape_sequences(&options.separator[..]);
    let terminator = match options.terminator {
        Some(term) => escape_sequences(&term[..]),
        None => separator.clone()
    };
    print_seq(first, step, last, largest_dec, separator, terminator, options.widths, padding);

    0
}

#[inline(always)]
fn done_printing(next: f64, step: f64, last: f64) -> bool {
    if step >= 0f64 {
        next > last
    } else {
        next < last
    }
}

fn print_seq(first: f64, step: f64, last: f64, largest_dec: usize, separator: String, terminator: String, pad: bool, padding: usize) {
    let mut i = 0isize;
    let mut value = first + i as f64 * step;
    while !done_printing(value, step, last) {
        let istr = value.to_string();
        let ilen = istr.len();
        let before_dec = istr.find('.').unwrap_or(ilen);
        if pad && before_dec < padding {
            for _ in 0..(padding - before_dec) {
                if !pipe_print!("0") {
                    return;
                }
            }
        }
        pipe_print!("{}", istr);
        let mut idec = ilen - before_dec;
        if idec < largest_dec {
            if idec == 0 {
                if !pipe_print!(".") {
                    return;
                }
                idec += 1;
            }
            for _ in idec..largest_dec {
                if !pipe_print!("0") {
                    return;
                }
            }
        }
        i += 1;
        value = first + i as f64 * step;
        if !done_printing(value, step, last) {
            if !pipe_print!("{}", separator) {
                return;
            }
        }
    }
    if (first >= last && step < 0f64) || (first <= last && step > 0f64) {
        pipe_print!("{}", terminator);
    }
    pipe_flush!();
}
<commit_msg>Fix busybox seq formatting test<commit_after>#![crate_name = "uu_seq"]

// TODO: Make -w flag work with decimals
// TODO: Support -f flag

extern crate getopts;
extern crate libc;

#[macro_use]
extern crate uucore;

use std::cmp;
use std::io::Write;

static NAME: &'static str = "seq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Clone)]
struct SeqOptions {
    separator: String,
    terminator: Option<String>,
    widths: bool
}

fn parse_float(mut s: &str) -> Result<f64, String> {
    if s.starts_with("+") {
        s = &s[1..];
    }
    match s.parse() {
        Ok(n) => Ok(n),
        Err(e) => Err(format!("seq: invalid floating point argument `{}`: {}", s, e))
    }
}

fn escape_sequences(s: &str) -> String {
    s.replace("\\n", "\n")
     .replace("\\t", "\t")
}

fn parse_options(args: Vec<String>, options: &mut SeqOptions) -> Result<Vec<String>, i32> {
    let mut seq_args = vec!();
    let mut iter = args.into_iter().skip(1);
    loop {
        match iter.next() {
            Some(arg) => match &arg[..] {
                "--help" | "-h" => {
                    print_help();
                    return Err(0);
                }
                "--version" | "-V" => {
                    print_version();
                    return Err(0);
                }
                "-s" | "--separator" => match iter.next() {
                    Some(sep) => options.separator = sep,
                    None => {
                        show_error!("expected a separator after {}", arg);
                        return Err(1);
                    }
                },
                "-t" | "--terminator" => match iter.next() {
                    Some(term) => options.terminator = Some(term),
                    None => {
                        show_error!("expected a terminator after '{}'", arg);
                        return Err(1);
                    }
                },
                "-w" | "--widths" => options.widths = true,
                "--" => {
                    seq_args.extend(iter);
                    break;
                },
                _ => {
                    if arg.len() > 1 && arg.chars().next().unwrap() == '-' {
                        let argptr: *const String = &arg;  // escape from the borrow checker
                        let mut chiter = unsafe { &(*argptr)[..] }.chars().skip(1);
                        let mut ch = ' ';
                        while match chiter.next() { Some(m) => { ch = m; true } None => false } {
                            match ch {
                                'h' => {
                                    print_help();
                                    return Err(0);
                                }
                                'V' => {
                                    print_version();
                                    return Err(0);
                                }
                                's' => match iter.next() {
                                    Some(sep) => {
                                        options.separator = sep;
                                        let next = chiter.next();
                                        if next.is_some() {
                                            show_error!("unexpected character ('{}')", next.unwrap());
                                            return Err(1);
                                        }
                                    }
                                    None => {
                                        show_error!("expected a separator after {}", arg);
                                        return Err(1);
                                    }
                                },
                                't' => match iter.next() {
                                    Some(term) => {
                                        options.terminator = Some(term);
                                        let next = chiter.next();
                                        if next.is_some() {
                                            show_error!("unexpected character ('{}')", next.unwrap());
                                            return Err(1);
                                        }
                                    }
                                    None => {
                                        show_error!("expected a terminator after {}", arg);
                                        return Err(1);
                                    }
                                },
                                'w' => options.widths = true,
                                _ => { seq_args.push(arg); break }
                            }
                        }
                    } else {
                        seq_args.push(arg);
                    }
                }
            },
            None => break
        }
    }
    Ok(seq_args)
}

fn print_help() {
    let mut opts = getopts::Options::new();

    opts.optopt("s", "separator", "Separator character (defaults to \\n)", "");
    opts.optopt("t", "terminator", "Terminator character (defaults to separator)", "");
    opts.optflag("w", "widths", "Equalize widths of all numbers by padding with zeros");
    opts.optflag("h", "help", "print this help text and exit");
    opts.optflag("V", "version", "print version and exit");

    println!("{} {}\n", NAME, VERSION);
    println!("Usage:\n  {} [-w] [-s string] [-t string] [first [step]] last\n", NAME);
    println!("{}", opts.usage("Print sequences of numbers"));
}

fn print_version() {
    println!("{} {}", NAME, VERSION);
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut options = SeqOptions {
        separator: "\n".to_string(),
        terminator: None,
        widths: false
    };
    let free = match parse_options(args, &mut options) {
        Ok(m) => m,
        Err(f) => return f
    };
    if free.len() < 1 || free.len() > 3 {
        crash!(1, "too {} operands.\nTry '{} --help' for more information.",
               if free.len() < 1 { "few" } else { "many" }, NAME);
    }
    let mut largest_dec = 0;
    let mut padding = 0;
    let first = if free.len() > 1 {
        let slice = &free[0][..];
        let len = slice.len();
        let dec = slice.find('.').unwrap_or(len);
        largest_dec = len - dec;
        padding = dec;
        match parse_float(slice) {
            Ok(n) => n,
            Err(s) => { show_error!("{}", s); return 1; }
        }
    } else {
        1.0
    };
    let step = if free.len() > 2 {
        let slice = &free[1][..];
        let len = slice.len();
        let dec = slice.find('.').unwrap_or(len);
        largest_dec = cmp::max(largest_dec, len - dec);
        padding = cmp::max(padding, dec);
        match parse_float(slice) {
            Ok(n) => n,
            Err(s) => { show_error!("{}", s); return 1; }
        }
    } else {
        1.0
    };
    let last = {
        let slice = &free[free.len() - 1][..];
        padding = cmp::max(padding, slice.find('.').unwrap_or(slice.len()));
        match parse_float(slice) {
            Ok(n) => n,
            Err(s) => { show_error!("{}", s); return 1; }
        }
    };
    if largest_dec > 0 {
        largest_dec -= 1;
    }
    let separator = escape_sequences(&options.separator[..]);
    let terminator = match options.terminator {
        Some(term) => escape_sequences(&term[..]),
        None => separator.clone()
    };
    print_seq(first, step, last, largest_dec, separator, terminator, options.widths, padding);

    0
}

#[inline(always)]
fn done_printing(next: f64, step: f64, last: f64) -> bool {
    if step >= 0f64 {
        next > last
    } else {
        next < last
    }
}

fn print_seq(first: f64, step: f64, last: f64, largest_dec: usize, separator: String, terminator: String, pad: bool, padding: usize) {
    let mut i = 0isize;
    let mut value = first + i as f64 * step;
    while !done_printing(value, step, last) {
        let istr = format!("{:.*}", largest_dec, value);
        let ilen = istr.len();
        let before_dec = istr.find('.').unwrap_or(ilen);
        if pad && before_dec < padding {
            for _ in 0..(padding - before_dec) {
                if !pipe_print!("0") {
                    return;
                }
            }
        }
        pipe_print!("{}", istr);
        i += 1;
        value = first + i as f64 * step;
        if !done_printing(value, step, last) {
            if !pipe_print!("{}", separator) {
                return;
            }
        }
    }
    if (first >= last && step < 0f64) || (first <= last && step > 0f64) {
        pipe_print!("{}", terminator);
    }
    pipe_flush!();
}
<|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/. */

extern crate serde;

use iron::{Request, Response, IronResult};
use self::serde::ser::{ Serialize, Serializer };

pub type ServiceID = String;

#[derive(Clone, Serialize)]
pub struct ServiceProperties {
    pub id: ServiceID,
    pub name: String,
    pub description: String,
    pub http_url: String,
    pub ws_url: String
}

pub trait Service : Send {
    fn get_properties(&self) -> ServiceProperties;
    fn start(&self);
    fn stop(&self);
    fn process_request(&self, req: &Request) -> IronResult<Response>;
}

impl Serialize for Service {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let props = self.get_properties();
        props.serialize(serializer)
    }
}

pub trait ServiceAdapter {
    fn get_name(&self) -> String;
    fn start(&self);
    fn stop(&self);
}
<commit_msg>Add test to Service::serialize()<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/. */

extern crate serde;

use iron::{Request, Response, IronResult};
use self::serde::ser::{ Serialize, Serializer };

pub type ServiceID = String;

#[derive(Clone, Serialize)]
pub struct ServiceProperties {
    pub id: ServiceID,
    pub name: String,
    pub description: String,
    pub http_url: String,
    pub ws_url: String
}

pub trait Service : Send {
    fn get_properties(&self) -> ServiceProperties;
    fn start(&self);
    fn stop(&self);
    fn process_request(&self, req: &Request) -> IronResult<Response>;
}

impl Serialize for Service {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let props = self.get_properties();
        props.serialize(serializer)
    }
}

pub trait ServiceAdapter {
    fn get_name(&self) -> String;
    fn start(&self);
    fn stop(&self);
}

describe! service {
    before_each {
        extern crate serde_json;
        use stubs::service::ServiceStub;

        // Box<T> is required because Service is a Trait object. We can't manipulate is unless
        // we have a reference to it
        let service: Box<Service> = Box::new(ServiceStub);
    }

    it "should be serializable" {
        // This works because serialize() is called thanks to to_string(). This is not a real unit
        // test, then. A mock should be used below. As mocks are not easily spy-able, that would
        // require a to implement each of the functions defined here[1]. That sounds overkill for a
        // simple 3-line-function.
        //
        // FIXME: Create a Mock of a Serializer, once we can easily spy on them.
        //
        // [1] https://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html
        let serialized_json = serde_json::to_string(&service).unwrap();
        assert_eq!(serialized_json, "{\"id\":\"1\",\"name\":\"dummy service\",\"description\":\"\
        really nothing to see\",\"http_url\":\"2\",\"ws_url\":\"3\"}");
    }
}
<|endoftext|>


<commit_before>//!
//! A session runs a filesystem implementation while it is being mounted
//! to a specific mount point. A session begins by mounting the filesystem
//! and ends by unmounting it. While the filesystem is mounted, the session
//! loop receives, dispatches and replies to kernel requests for filesystem
//! operations under its mount point.
//!

use std::io;
use std::ffi::OsStr;
use std::fmt;
use std::path::{PathBuf, Path};
use thread_scoped::{scoped, JoinGuard};
use libc::{EAGAIN, EINTR, ENODEV, ENOENT};
use channel;
use channel::Channel;
use Filesystem;
use request::{request, dispatch};

/// The max size of write requests from the kernel. The absolute minimum is 4k,
/// FUSE recommends at least 128k, max 16M. The FUSE default is 16M on OS X
/// and 128k on other systems.
pub const MAX_WRITE_SIZE: usize = 16*1024*1024;

/// Size of the buffer for reading a request from the kernel. Since the kernel may send
/// up to MAX_WRITE_SIZE bytes in a write request, we use that value plus some extra space.
const BUFFER_SIZE: usize = MAX_WRITE_SIZE + 4096;

/// The session data structure
#[derive(Debug)]
pub struct Session<FS: Filesystem> {
    /// Filesystem operation implementations
    pub filesystem: FS,
    /// Communication channel to the kernel driver
    ch: Channel,
    /// FUSE protocol major version
    pub proto_major: u32,
    /// FUSE protocol minor version
    pub proto_minor: u32,
    /// True if the filesystem is initialized (init operation done)
    pub initialized: bool,
    /// True if the filesystem was destroyed (destroy operation done)
    pub destroyed: bool,
}

impl<FS: Filesystem> Session<FS> {
    /// Create a new session by mounting the given filesystem to the given mountpoint
    pub fn new (filesystem: FS, mountpoint: &Path, options: &[&OsStr]) -> io::Result<Session<FS>> {
        info!("Mounting {}", mountpoint.display());
        Channel::new(mountpoint, options).map(
            |ch| Session {
                filesystem: filesystem,
                ch: ch,
                proto_major: 0,
                proto_minor: 0,
                initialized: false,
                destroyed: false,
            })
    }

    /// Return path of the mounted filesystem
    pub fn mountpoint (&self) -> &Path {
        &self.ch.mountpoint()
    }

    /// Run the session loop that receives kernel requests and dispatches them to method
    /// calls into the filesystem. This read-dispatch-loop is non-concurrent to prevent
    /// having multiple buffers (which take up much memory), but the filesystem methods
    /// may run concurrent by spawning threads.
    pub fn run (&mut self) -> io::Result<()> {
        // Buffer for receiving requests from the kernel. Only one is allocated and
        // it is reused immediately after dispatching to conserve memory and allocations.
        let mut buffer: Vec<u8> = Vec::with_capacity(BUFFER_SIZE);
        loop {
            // Read the next request from the given channel to kernel driver
            // The kernel driver makes sure that we get exactly one request per read
            match self.ch.receive(&mut buffer) {
                Ok(()) => match request(self.ch.sender(), &buffer) {
                    // Dispatch request
                    Some(req) => dispatch(&req, self),
                    // Quit loop on illegal request
                    None => break,
                },
                Err(err) => match err.raw_os_error() {
                    // Operation interrupted. Accordingly to FUSE, this is safe to retry
                    Some(ENOENT) => continue,
                    // Interrupted system call, retry
                    Some(EINTR) => continue,
                    // Explicitly try again
                    Some(EAGAIN) => continue,
                    // Filesystem was unmounted, quit the loop
                    Some(ENODEV) => break,
                    // Unhandled error
                    _ => return Err(err),
                },
            }
        }
        Ok(())
    }
}

impl<'a, FS: Filesystem+Send+'a> Session<FS> {
    /// Run the session loop in a background thread
    pub unsafe fn spawn (self) -> io::Result<BackgroundSession<'a>> {
        BackgroundSession::new(self)
    }
}

impl<FS: Filesystem> Drop for Session<FS> {
    fn drop (&mut self) {
        info!("Unmounted {}", self.mountpoint().display());
    }
}

/// The background session data structure
pub struct BackgroundSession<'a> {
    /// Path of the mounted filesystem
    pub mountpoint: PathBuf,
    /// Thread guard of the background session
    pub guard: JoinGuard<'a, io::Result<()>>,
}

impl<'a> BackgroundSession<'a> {
    /// Create a new background session for the given session by running its
    /// session loop in a background thread. If the returned handle is dropped,
    /// the filesystem is unmounted and the given session ends.
    pub unsafe fn new<FS: Filesystem+Send+'a> (se: Session<FS>) -> io::Result<BackgroundSession<'a>> {
        let mountpoint = se.mountpoint().to_path_buf();
        let guard = scoped(move || {
            let mut se = se;
            se.run()
        });
        Ok(BackgroundSession { mountpoint: mountpoint, guard: guard })
    }
}

impl<'a> Drop for BackgroundSession<'a> {
    fn drop (&mut self) {
        info!("Unmounting {}", self.mountpoint.display());
        // Unmounting the filesystem will eventually end the session loop,
        // drop the session and hence end the background thread.
        match channel::unmount(&self.mountpoint) {
            Ok(()) => (),
            Err(err) => error!("Failed to unmount {}: {}", self.mountpoint.display(), err),
        }
    }
}

// replace with #[derive(Debug)] if Debug ever gets implemented for
// thread_scoped::JoinGuard
impl<'a> fmt::Debug for BackgroundSession<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "BackgroundSession {{ mountpoint: {:?}, guard: JoinGuard<()> }}", self.mountpoint)
    }
}
<commit_msg>Clean up use statements (don't import functions)<commit_after>//!
//! A session runs a filesystem implementation while it is being mounted
//! to a specific mount point. A session begins by mounting the filesystem
//! and ends by unmounting it. While the filesystem is mounted, the session
//! loop receives, dispatches and replies to kernel requests for filesystem
//! operations under its mount point.
//!

use std::io;
use std::ffi::OsStr;
use std::fmt;
use std::path::{PathBuf, Path};
use thread_scoped::{scoped, JoinGuard};
use libc::{EAGAIN, EINTR, ENODEV, ENOENT};
use channel::{self, Channel};
use Filesystem;
use request;

/// The max size of write requests from the kernel. The absolute minimum is 4k,
/// FUSE recommends at least 128k, max 16M. The FUSE default is 16M on OS X
/// and 128k on other systems.
pub const MAX_WRITE_SIZE: usize = 16*1024*1024;

/// Size of the buffer for reading a request from the kernel. Since the kernel may send
/// up to MAX_WRITE_SIZE bytes in a write request, we use that value plus some extra space.
const BUFFER_SIZE: usize = MAX_WRITE_SIZE + 4096;

/// The session data structure
#[derive(Debug)]
pub struct Session<FS: Filesystem> {
    /// Filesystem operation implementations
    pub filesystem: FS,
    /// Communication channel to the kernel driver
    ch: Channel,
    /// FUSE protocol major version
    pub proto_major: u32,
    /// FUSE protocol minor version
    pub proto_minor: u32,
    /// True if the filesystem is initialized (init operation done)
    pub initialized: bool,
    /// True if the filesystem was destroyed (destroy operation done)
    pub destroyed: bool,
}

impl<FS: Filesystem> Session<FS> {
    /// Create a new session by mounting the given filesystem to the given mountpoint
    pub fn new (filesystem: FS, mountpoint: &Path, options: &[&OsStr]) -> io::Result<Session<FS>> {
        info!("Mounting {}", mountpoint.display());
        Channel::new(mountpoint, options).map(
            |ch| Session {
                filesystem: filesystem,
                ch: ch,
                proto_major: 0,
                proto_minor: 0,
                initialized: false,
                destroyed: false,
            })
    }

    /// Return path of the mounted filesystem
    pub fn mountpoint (&self) -> &Path {
        &self.ch.mountpoint()
    }

    /// Run the session loop that receives kernel requests and dispatches them to method
    /// calls into the filesystem. This read-dispatch-loop is non-concurrent to prevent
    /// having multiple buffers (which take up much memory), but the filesystem methods
    /// may run concurrent by spawning threads.
    pub fn run (&mut self) -> io::Result<()> {
        // Buffer for receiving requests from the kernel. Only one is allocated and
        // it is reused immediately after dispatching to conserve memory and allocations.
        let mut buffer: Vec<u8> = Vec::with_capacity(BUFFER_SIZE);
        loop {
            // Read the next request from the given channel to kernel driver
            // The kernel driver makes sure that we get exactly one request per read
            match self.ch.receive(&mut buffer) {
                Ok(()) => match request::request(self.ch.sender(), &buffer) {
                    // Dispatch request
                    Some(req) => request::dispatch(&req, self),
                    // Quit loop on illegal request
                    None => break,
                },
                Err(err) => match err.raw_os_error() {
                    // Operation interrupted. Accordingly to FUSE, this is safe to retry
                    Some(ENOENT) => continue,
                    // Interrupted system call, retry
                    Some(EINTR) => continue,
                    // Explicitly try again
                    Some(EAGAIN) => continue,
                    // Filesystem was unmounted, quit the loop
                    Some(ENODEV) => break,
                    // Unhandled error
                    _ => return Err(err),
                },
            }
        }
        Ok(())
    }
}

impl<'a, FS: Filesystem+Send+'a> Session<FS> {
    /// Run the session loop in a background thread
    pub unsafe fn spawn (self) -> io::Result<BackgroundSession<'a>> {
        BackgroundSession::new(self)
    }
}

impl<FS: Filesystem> Drop for Session<FS> {
    fn drop (&mut self) {
        info!("Unmounted {}", self.mountpoint().display());
    }
}

/// The background session data structure
pub struct BackgroundSession<'a> {
    /// Path of the mounted filesystem
    pub mountpoint: PathBuf,
    /// Thread guard of the background session
    pub guard: JoinGuard<'a, io::Result<()>>,
}

impl<'a> BackgroundSession<'a> {
    /// Create a new background session for the given session by running its
    /// session loop in a background thread. If the returned handle is dropped,
    /// the filesystem is unmounted and the given session ends.
    pub unsafe fn new<FS: Filesystem+Send+'a> (se: Session<FS>) -> io::Result<BackgroundSession<'a>> {
        let mountpoint = se.mountpoint().to_path_buf();
        let guard = scoped(move || {
            let mut se = se;
            se.run()
        });
        Ok(BackgroundSession { mountpoint: mountpoint, guard: guard })
    }
}

impl<'a> Drop for BackgroundSession<'a> {
    fn drop (&mut self) {
        info!("Unmounting {}", self.mountpoint.display());
        // Unmounting the filesystem will eventually end the session loop,
        // drop the session and hence end the background thread.
        match channel::unmount(&self.mountpoint) {
            Ok(()) => (),
            Err(err) => error!("Failed to unmount {}: {}", self.mountpoint.display(), err),
        }
    }
}

// replace with #[derive(Debug)] if Debug ever gets implemented for
// thread_scoped::JoinGuard
impl<'a> fmt::Debug for BackgroundSession<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "BackgroundSession {{ mountpoint: {:?}, guard: JoinGuard<()> }}", self.mountpoint)
    }
}
<|endoftext|>


<commit_before>use types::*;

pub const NAME:          &'static str   = "{{protocol.name}}";
pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
pub const REVISION:      ShortShortUInt = {{protocol.revision}};
pub const PORT:          LongUInt       = {{protocol.port}};
pub const COPYRIGHT:     &'static str   = r#"{{copyright}}"#;

{{#each protocol.constants as |constant| ~}}
pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
{{/each ~}}
pub mod soft_errors {
    use types::*;
    {{#each protocol.soft_errors as |constant| ~}}
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}
pub mod hard_errors {
    use types::*;
    {{#each protocol.hard_errors as |constant| ~}}
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}
<commit_msg>protocol: rework how we expose error<commit_after>use types::*;

pub const NAME:          &'static str   = "{{protocol.name}}";
pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
pub const REVISION:      ShortShortUInt = {{protocol.revision}};
pub const PORT:          LongUInt       = {{protocol.port}};
pub const COPYRIGHT:     &'static str   = r#"{{copyright}}"#;

{{#each protocol.constants as |constant| ~}}
pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
{{/each ~}}

pub enum AMQPError {
    Soft(AMQPSoftError),
    Hard(AMQPHardError),
}

impl AMQPError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(|e| AMQPError::Soft(e)).or_else(|| AMQPHardError::from_id(id).map(|e| AMQPError::Hard(e)))
    }
}

pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}
<|endoftext|>


<commit_before>use ga::{self, Tensor};
use ga::tensor::TensorMode;

use super::graph::Node;
use super::var_store::{VarIndex, VarStore};

pub trait Operation : 'static {
    fn forward(&mut self, &ga::Context, &mut VarStore, &mut Node);
    fn backward(&mut self, &ga::Context, &mut VarStore, &mut Node);
}

pub trait OpBuilder {
    type Op;

    fn build(&self, ctx: &ga::Context, v: &VarStore)
             -> Result<(Self::Op, Vec<VarIndex>, Vec<Vec<usize>>), String>;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct MatMul(pub VarIndex, pub VarIndex);

impl OpBuilder for MatMul {
    type Op = MatMulImpl;

    fn build(&self, ctx: &ga::Context, v: &VarStore)
             -> Result<(MatMulImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        let b = &v.get(self.1);
        Ok((MatMulImpl::new(ctx, a.shape().to_vec(), b.shape().to_vec()),
            vec![self.0, self.1],
            vec![vec![a.shape()[0], b.shape()[1]]]))
    }
}

pub struct MatMulImpl {
    a_t: Tensor<f32>,
    b_t: Tensor<f32>,
}

impl MatMulImpl {
    pub fn new(ctx: &ga::Context, a_shape: Vec<usize>, b_shape: Vec<usize>) -> Self {
        MatMulImpl {
            a_t: Tensor::new(ctx, vec![a_shape[1], a_shape[0]], TensorMode::Mut),
            b_t: Tensor::new(ctx, vec![b_shape[1], b_shape[0]], TensorMode::Mut),
        }
    }
}

impl Operation for MatMulImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.inputs[1]);
        let c = &v.get(n.outputs[0]);
        ga::matmul(ctx, a, b, c); // c = a*b
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.inputs[1]);
        let a_d = &v.get(n.in_grad[0]);
        let b_d = &v.get(n.in_grad[1]);
        let g = &v.get(n.out_grad[0].gradient());

        // Derivative with respect to first input
        // a_d = g*b_t
        ga::transpose(ctx, b, &self.b_t);
        ga::matmul(ctx, g, &self.b_t, a_d);

        // Derivative with respect to second input
        // b_d = a_t*g
        ga::transpose(ctx, a, &self.a_t);
        ga::matmul(ctx, &self.a_t, g, b_d);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Add(pub VarIndex, pub VarIndex, pub i32);

impl OpBuilder for Add {
    type Op = AddImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(AddImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        let b = &v.get(self.1);
        if a.shape() != b.shape() {
            return Err("DIM ERROR: Shapes must be equal for Add".to_string());
        }
        Ok((AddImpl::new(self.2), vec![self.0, self.1], vec![a.shape().to_vec()]))
    }
}

pub struct AddImpl {
    axis: i32,
}

impl AddImpl {
    pub fn new(axis: i32) -> Self {
        AddImpl {
            axis: axis,
        }
    }
}

impl Operation for AddImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.inputs[1]);
        let c = &v.get(n.outputs[0]);
        ga::add(ctx, a, self.axis, b, c); // c = a+b
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a_d = &v.get(n.in_grad[0]);
        let b_d = &v.get(n.in_grad[1]);
        let g = &v.get(n.out_grad[0].gradient());
        ga::copy_to(ctx, g, a_d);
        ga::sum(ctx, g, self.axis as usize, b_d);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Relu(pub VarIndex);

impl OpBuilder for Relu {
    type Op = ReluImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(ReluImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        Ok((ReluImpl, vec![self.0], vec![a.shape().to_vec()]))
    }
}

pub struct ReluImpl;

impl Operation for ReluImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.outputs[0]);
        ga::max(ctx, a, 0.0, b); // b = max(0, a)
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let a_d = &v.get(n.in_grad[0]);
        let g = &v.get(n.out_grad[0].gradient());
        ga::dmax(ctx, a, 0.0, a_d);
        ga::multiply(ctx, g, -1, a_d, a_d);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Mse(pub VarIndex, pub VarIndex);

impl OpBuilder for Mse {
    type Op = MseImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(MseImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        let b = &v.get(self.1);
        if a.shape() != b.shape() {
            return Err("DIM ERROR: Shapes must be equal for MSE".to_string());
        }
        Ok((MseImpl, vec![self.0, self.1], vec![a.shape().to_vec()]))
    }
}

pub struct MseImpl;

impl Operation for MseImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let h = &v.get(n.inputs[0]); // predictions
        let y = &v.get(n.inputs[1]); // training output
        let out = &v.get(n.outputs[0]);
        ga::mse(ctx, h, y, out); // out = mse(h, y)
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let h = &v.get(n.inputs[0]); // predictions
        let h_d = &v.get(n.in_grad[0]);
        let y = &v.get(n.inputs[1]); // training output
        let g = &v.get(n.out_grad[0].gradient());
        ga::dmse(ctx, h, y, h_d); // h_d = dmse(h, y)
        ga::multiply(ctx, h_d, 0, g, h_d); // h_d = g*h_d
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Lstm(input, state)
/*pub struct Lstm(pub VarIndex, pub VarIndex, usize);

impl OpBuilder for Lstm {
    type Op = LstmImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(LstmImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let x = &v.get(self.0);
        let s = &v.get(self.1);
        let hidden_size = self.2;
        if x.shape() != s.shape() {
            return Err("DIM ERROR: Shapes must be equal for LSTM".to_string());
        }
        Ok((LstmImpl::new(), vec![self.0, self.1], vec![x.shape().to_vec()]))
    }
}

pub struct LstmImpl {
    ifog: Tensor<f32>, // input, forget, output, gate (IFOG)

    // Recurrent connections from last sequence
    c0: Tensor<f32>,
    h0: Tensor<f32>,

    seq_len: usize,
    batch_size: usize,
    input_size: usize,
    hidden_size: usize,
}

impl LstmImpl {
    fn new(seq_len: usize, batch_size: usize, input_size: usize, hidden_size: usize) -> Self {
        let n = seq_len;
        let b = batch_size;
        let d = hidden_size;
        LstmImpl {
            ifog: Tensor::new(ctx, vec![n, b, d*4], TensorMode::Mut)),
            c0: Tensor::new(ctx, vec![b, d], TensorMode::Mut)),
            h0: Tensor::new(ctx, vec![b, d], TensorMode::Mut)),

            seq_len: seq_len,
            batch_size: batch_size,
            input_size: input_size,
            hidden_size: hidden_size,
        }
    }
}

impl Operation for LstmImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let x = &v.get(n.inputs[0]); // input
        let c = &v.get(n.outputs[0]); // cell
        let h = &v.get(n.outputs[1]); // output

        for t in 0..self.seq_len {
            self.ifog[t].dot(ctx, h);
            h.mse(ctx, y, out); // out = mse(h, y)
        }
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
    }
}*/
<commit_msg>LSTM progress<commit_after>use ga::{self, Tensor};
use ga::tensor::TensorMode;

use super::graph::Node;
use super::var_store::{VarIndex, VarStore};

pub trait Operation : 'static {
    fn forward(&mut self, &ga::Context, &mut VarStore, &mut Node);
    fn backward(&mut self, &ga::Context, &mut VarStore, &mut Node);
}

pub trait OpBuilder {
    type Op;

    fn build(&self, ctx: &ga::Context, v: &VarStore)
             -> Result<(Self::Op, Vec<VarIndex>, Vec<Vec<usize>>), String>;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct MatMul(pub VarIndex, pub VarIndex);

impl OpBuilder for MatMul {
    type Op = MatMulImpl;

    fn build(&self, ctx: &ga::Context, v: &VarStore)
             -> Result<(MatMulImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        let b = &v.get(self.1);
        Ok((MatMulImpl::new(ctx, a.shape().to_vec(), b.shape().to_vec()),
            vec![self.0, self.1],
            vec![vec![a.shape()[0], b.shape()[1]]]))
    }
}

pub struct MatMulImpl {
    a_t: Tensor<f32>,
    b_t: Tensor<f32>,
}

impl MatMulImpl {
    pub fn new(ctx: &ga::Context, a_shape: Vec<usize>, b_shape: Vec<usize>) -> Self {
        MatMulImpl {
            a_t: Tensor::new(ctx, vec![a_shape[1], a_shape[0]], TensorMode::Mut),
            b_t: Tensor::new(ctx, vec![b_shape[1], b_shape[0]], TensorMode::Mut),
        }
    }
}

impl Operation for MatMulImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.inputs[1]);
        let c = &v.get(n.outputs[0]);
        ga::matmul(ctx, a, b, c); // c = a*b
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.inputs[1]);
        let a_d = &v.get(n.in_grad[0]);
        let b_d = &v.get(n.in_grad[1]);
        let g = &v.get(n.out_grad[0].gradient());

        // Derivative with respect to first input
        // a_d = g*b_t
        ga::transpose(ctx, b, &self.b_t);
        ga::matmul(ctx, g, &self.b_t, a_d);

        // Derivative with respect to second input
        // b_d = a_t*g
        ga::transpose(ctx, a, &self.a_t);
        ga::matmul(ctx, &self.a_t, g, b_d);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Add(pub VarIndex, pub VarIndex, pub i32);

impl OpBuilder for Add {
    type Op = AddImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(AddImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        let b = &v.get(self.1);
        if a.shape() != b.shape() {
            return Err("DIM ERROR: Shapes must be equal for Add".to_string());
        }
        Ok((AddImpl::new(self.2), vec![self.0, self.1], vec![a.shape().to_vec()]))
    }
}

pub struct AddImpl {
    axis: i32,
}

impl AddImpl {
    pub fn new(axis: i32) -> Self {
        AddImpl {
            axis: axis,
        }
    }
}

impl Operation for AddImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.inputs[1]);
        let c = &v.get(n.outputs[0]);
        ga::add(ctx, a, self.axis, b, c); // c = a+b
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a_d = &v.get(n.in_grad[0]);
        let b_d = &v.get(n.in_grad[1]);
        let g = &v.get(n.out_grad[0].gradient());
        ga::copy_to(ctx, g, a_d);
        ga::sum(ctx, g, self.axis as usize, b_d);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Relu(pub VarIndex);

impl OpBuilder for Relu {
    type Op = ReluImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(ReluImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        Ok((ReluImpl, vec![self.0], vec![a.shape().to_vec()]))
    }
}

pub struct ReluImpl;

impl Operation for ReluImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let b = &v.get(n.outputs[0]);
        ga::max(ctx, a, 0.0, b); // b = max(0, a)
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let a = &v.get(n.inputs[0]);
        let a_d = &v.get(n.in_grad[0]);
        let g = &v.get(n.out_grad[0].gradient());
        ga::dmax(ctx, a, 0.0, a_d);
        ga::multiply(ctx, g, -1, a_d, a_d);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Mse(pub VarIndex, pub VarIndex);

impl OpBuilder for Mse {
    type Op = MseImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(MseImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let a = &v.get(self.0);
        let b = &v.get(self.1);
        if a.shape() != b.shape() {
            return Err("DIM ERROR: Shapes must be equal for MSE".to_string());
        }
        Ok((MseImpl, vec![self.0, self.1], vec![a.shape().to_vec()]))
    }
}

pub struct MseImpl;

impl Operation for MseImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let h = &v.get(n.inputs[0]); // predictions
        let y = &v.get(n.inputs[1]); // training output
        let out = &v.get(n.outputs[0]);
        ga::mse(ctx, h, y, out); // out = mse(h, y)
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let h = &v.get(n.inputs[0]); // predictions
        let h_d = &v.get(n.in_grad[0]);
        let y = &v.get(n.inputs[1]); // training output
        let g = &v.get(n.out_grad[0].gradient());
        ga::dmse(ctx, h, y, h_d); // h_d = dmse(h, y)
        ga::multiply(ctx, h_d, 0, g, h_d); // h_d = g*h_d
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Lstm(input, state)
/*pub struct Lstm(pub VarIndex, pub VarIndex, usize);

impl OpBuilder for Lstm {
    type Op = LstmImpl;

    fn build(&self, _: &ga::Context, v: &VarStore)
             -> Result<(LstmImpl, Vec<VarIndex>, Vec<Vec<usize>>), String> {
        let x = &v.get(self.0);
        let s = &v.get(self.1);
        let hidden_size = self.2;
        if x.shape() != s.shape() {
            return Err("DIM ERROR: Shapes must be equal for LSTM".to_string());
        }
        Ok((LstmImpl::new(), vec![self.0, self.1], vec![x.shape().to_vec()]))
    }
}

pub struct LstmImpl {
    ifog: af::Array, // input, forget, output, gate (IFOG)
    ifog_f: af::Array,
    c: af::Array,

    // Recurrent connections from last sequence
    c0: af::Array,
    h0: af::Array,

    seq_len: usize,
    batch_size: usize,
    input_size: usize,
    hidden_size: usize,
}

impl LstmImpl {
    fn new(seq_len: usize, batch_size: usize, input_size: usize, hidden_size: usize) -> Self {
        let n = seq_len;
        let b = batch_size;
        let d = hidden_size;
        LstmImpl {
            ifog: Tensor::new(vec![n, b, d*4], TensorMode::Mut),
            c0: Tensor::new(vec![b, d], TensorMode::Mut),
            h0: Tensor::new(vec![b, d], TensorMode::Mut),

            seq_len: seq_len,
            batch_size: batch_size,
            input_size: input_size,
            hidden_size: hidden_size,
        }
    }
}

impl Operation for LstmImpl {
    fn forward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
        let n = self.seq_len;
        let b = self.batch_size;
        let d = self.hidden_size;
        let i = self.input_size;

        let x = &v.get(n.inputs[0]); // input
        let wlstm = &v.get(n.inputs[1]); // all of the weights for all the cells
        let c_f = &v.get(n.outputs[0]); // cell
        let h = &v.get(n.outputs[1]); // output

        for t in 0..self.seq_len {
            // Output from last time step
            let ref prevh = if t > 0 { h.slice(s![t-1]) } else { self.h0 };
            // Input
            ga::fill(Hin.slice(s![t, .., 0]), 1); // bias
            ga::copy_slice(ctx, x.slice(s![t]), Hin.slice(s![t, .., 1..i+1]));
            ga::copy_slice(ctx, prevh, Hin.slice(s![t, .., i+1..]));
            // Multiply inputs and weights, and add biases; all in one dot product!
            ga::matmul(ctx, Hin, WLSTM, self.ifog.slice(s![t]));
            // Compute internal activations
            ga::sigmoid(ctx, IFOG.slice(s![t, .., ..3*d]), IFOGf.slice(s![t, .., ..3*d])); // sigmoids; these are the gates
            ga::tanh(ctx, IFOG.slice(s![t, .., 3*d..]), IFOGf.slice(s![t, .., 3*d..])); // tanh
            // compute the LSTM cell activation
            let ref prevc = if t > 0 { c.slice(s![t-1]) } else { self.c0 };
            c.slice(s![t]) = IFOGf.slice(s![t, .., ..d]) * IFOGf.slice(s![t, .., 3*d..]) + IFOGf.slice(s![t, .., d..2*d]) * prevc
            ga::tanh(ctx, c.slice(s![t]), c_f.slice(s![t]));
            ga::multiply(ctx, self.ifog_f.slice(s![t, .., 2*d..3*d]), Ct.slice(s![t]), h.slice(s![t]));
        }
    }

    fn backward(&mut self, ctx: &ga::Context, v: &mut VarStore, n: &mut Node) {
    }
}*/
<|endoftext|>


<commit_before>use crate::utils::{match_def_path, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead.
    ///
    /// **Why is this bad?** Sometimes `std::fs::crate_dir` is mistakenly chosen over `std::fs::create_dir_all`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// std::fs::create_dir("foo");
    /// ```
    /// Use instead:
    /// ```rust
    /// std::fs::create_dir_all("foo");
    /// ```
    pub CREATE_DIR,
    restriction,
    "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`"
}

declare_lint_pass!(CreateDir => [CREATE_DIR]);

impl LateLintPass<'_> for CreateDir {
    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let ExprKind::Call(ref func, ref args) = expr.kind;
            if let ExprKind::Path(ref path) = func.kind;
            if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
            if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR);
            then {
                span_lint_and_sugg(
                    cx,
                    CREATE_DIR,
                    expr.span,
                    "calling `std::fs::create_dir` where there may be a better way",
                    "consider calling `std::fs::create_dir_all` instead",
                    format!("create_dir_all({})", snippet(cx, args[0].span, "..")),
                    Applicability::MaybeIncorrect,
                )
            }
        }
    }
}
<commit_msg>Auto merge of #6461 - Dorumin:patch-1, r=Manishearth<commit_after>use crate::utils::{match_def_path, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead.
    ///
    /// **Why is this bad?** Sometimes `std::fs::create_dir` is mistakenly chosen over `std::fs::create_dir_all`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// std::fs::create_dir("foo");
    /// ```
    /// Use instead:
    /// ```rust
    /// std::fs::create_dir_all("foo");
    /// ```
    pub CREATE_DIR,
    restriction,
    "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`"
}

declare_lint_pass!(CreateDir => [CREATE_DIR]);

impl LateLintPass<'_> for CreateDir {
    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let ExprKind::Call(ref func, ref args) = expr.kind;
            if let ExprKind::Path(ref path) = func.kind;
            if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
            if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR);
            then {
                span_lint_and_sugg(
                    cx,
                    CREATE_DIR,
                    expr.span,
                    "calling `std::fs::create_dir` where there may be a better way",
                    "consider calling `std::fs::create_dir_all` instead",
                    format!("create_dir_all({})", snippet(cx, args[0].span, "..")),
                    Applicability::MaybeIncorrect,
                )
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{self, Read, Write, Seek, SeekFrom, Cursor};
use file::tempfile;

/// An object that behaves like a regular temporary file, but keeps data in
/// memory until it reaches a configured size, at which point the data is
/// written to a temporary file on disk, and further operations use the file
/// on disk.
#[derive(Debug)]
pub struct SpooledTempFile {
    max_size: usize,
    cursor: Option<Cursor<Vec<u8>>>,
    file: Option<File>,
}

/// Create a new spooled temporary file.
///
/// # Security
///
/// This variant is secure/reliable in the presence of a pathological temporary
/// file cleaner.
///
/// # Resource Leaking
///
/// The temporary file will be automatically removed by the OS when the last
/// handle to it is closed. This doesn't rely on Rust destructors being run, so
/// will (almost) never fail to clean up the temporary file.
///
/// # Examples
///
/// ```
/// # extern crate tempfile;
/// use tempfile::spooled_tempfile;
/// use std::io::{self, Write};
///
/// # fn main() {
/// #     if let Err(_) = run() {
/// #         ::std::process::exit(1);
/// #     }
/// # }
/// # fn run() -> Result<(), io::Error> {
/// let mut file = spooled_tempfile(15);
///
/// writeln!(file, "short line")?;
/// assert!(!file.rolled_over());
///
/// // as a result of this write call, the size of the data will exceed
/// // `max_size` (15), so it will be written to a temporary file on disk,
/// // and the in-memory buffer will be dropped
/// writeln!(file, "marvin gardens")?;
/// assert(file.rolled_over());
///
/// # Ok(())
/// # }
/// ```
pub fn spooled_tempfile(max_size: usize) -> SpooledTempFile {
    SpooledTempFile {
        max_size: max_size,
        cursor: Some(Cursor::new(Vec::new())),
        file: None,
    }
}

impl SpooledTempFile {
    /// Returns true if the file has been rolled over to disk.
    pub fn rolled_over(&self) -> bool {
        if let Some(ref _file) = self.file {
            true
        } else {
            false
        }
    }
}

impl Read for SpooledTempFile {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if let Some(ref mut cursor) = self.cursor {
            cursor.read(buf)
        } else if let Some(ref mut file) = self.file {
            file.read(buf)
        } else {
            panic!(); // bug
        }
    }
}

impl Write for SpooledTempFile {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // roll over to file if necessary
        let mut rolling = false;
        if let Some(ref mut cursor) = self.cursor {
            rolling = cursor.position() as usize + buf.len() > self.max_size;
            if rolling {
                let mut file = tempfile()?;
                file.write(cursor.get_ref())?;
                file.seek(SeekFrom::Start(cursor.position()))?;
                self.file = Some(file);
            }
        }
        if rolling {
            self.cursor.take();
        }

        // write the bytes
        if let Some(ref mut cursor) = self.cursor {
            cursor.write(buf)
        } else if let Some(ref mut file) = self.file {
            file.write(buf)
        } else {
            panic!(); // bug
        }
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        if let Some(ref mut cursor) = self.cursor {
            cursor.flush()
        } else if let Some(ref mut file) = self.file {
            file.flush()
        } else {
            panic!(); // bug
        }
    }
}

impl Seek for SpooledTempFile {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        if let Some(ref mut cursor) = self.cursor {
            cursor.seek(pos)
        } else if let Some(ref mut file) = self.file {
            file.seek(pos)
        } else {
            panic!(); // bug
        }
    }
}
<commit_msg>missed a bang<commit_after>use std::fs::File;
use std::io::{self, Read, Write, Seek, SeekFrom, Cursor};
use file::tempfile;

/// An object that behaves like a regular temporary file, but keeps data in
/// memory until it reaches a configured size, at which point the data is
/// written to a temporary file on disk, and further operations use the file
/// on disk.
#[derive(Debug)]
pub struct SpooledTempFile {
    max_size: usize,
    cursor: Option<Cursor<Vec<u8>>>,
    file: Option<File>,
}

/// Create a new spooled temporary file.
///
/// # Security
///
/// This variant is secure/reliable in the presence of a pathological temporary
/// file cleaner.
///
/// # Resource Leaking
///
/// The temporary file will be automatically removed by the OS when the last
/// handle to it is closed. This doesn't rely on Rust destructors being run, so
/// will (almost) never fail to clean up the temporary file.
///
/// # Examples
///
/// ```
/// # extern crate tempfile;
/// use tempfile::spooled_tempfile;
/// use std::io::{self, Write};
///
/// # fn main() {
/// #     if let Err(_) = run() {
/// #         ::std::process::exit(1);
/// #     }
/// # }
/// # fn run() -> Result<(), io::Error> {
/// let mut file = spooled_tempfile(15);
///
/// writeln!(file, "short line")?;
/// assert!(!file.rolled_over());
///
/// // as a result of this write call, the size of the data will exceed
/// // `max_size` (15), so it will be written to a temporary file on disk,
/// // and the in-memory buffer will be dropped
/// writeln!(file, "marvin gardens")?;
/// assert!(file.rolled_over());
///
/// # Ok(())
/// # }
/// ```
pub fn spooled_tempfile(max_size: usize) -> SpooledTempFile {
    SpooledTempFile {
        max_size: max_size,
        cursor: Some(Cursor::new(Vec::new())),
        file: None,
    }
}

impl SpooledTempFile {
    /// Returns true if the file has been rolled over to disk.
    pub fn rolled_over(&self) -> bool {
        if let Some(ref _file) = self.file {
            true
        } else {
            false
        }
    }
}

impl Read for SpooledTempFile {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if let Some(ref mut cursor) = self.cursor {
            cursor.read(buf)
        } else if let Some(ref mut file) = self.file {
            file.read(buf)
        } else {
            panic!(); // bug
        }
    }
}

impl Write for SpooledTempFile {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // roll over to file if necessary
        let mut rolling = false;
        if let Some(ref mut cursor) = self.cursor {
            rolling = cursor.position() as usize + buf.len() > self.max_size;
            if rolling {
                let mut file = tempfile()?;
                file.write(cursor.get_ref())?;
                file.seek(SeekFrom::Start(cursor.position()))?;
                self.file = Some(file);
            }
        }
        if rolling {
            self.cursor.take();
        }

        // write the bytes
        if let Some(ref mut cursor) = self.cursor {
            cursor.write(buf)
        } else if let Some(ref mut file) = self.file {
            file.write(buf)
        } else {
            panic!(); // bug
        }
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        if let Some(ref mut cursor) = self.cursor {
            cursor.flush()
        } else if let Some(ref mut file) = self.file {
            file.flush()
        } else {
            panic!(); // bug
        }
    }
}

impl Seek for SpooledTempFile {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        if let Some(ref mut cursor) = self.cursor {
            cursor.seek(pos)
        } else if let Some(ref mut file) = self.file {
            file.seek(pos)
        } else {
            panic!(); // bug
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

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

#![allow(dead_code)]
#![allow(deprecated)]
use kvproto::raftpb::{HardState, ConfState, Entry, Snapshot};
use raft::errors::{Result, Error, StorageError};
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use util::{self, HandyRwLock};

#[derive(Debug, Clone)]
pub struct RaftState {
    pub hard_state: HardState,
    pub conf_state: ConfState,
}

pub trait Storage {
    fn initial_state(&self) -> Result<RaftState>;
    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<Vec<Entry>>;
    fn term(&self, idx: u64) -> Result<u64>;
    fn first_index(&self) -> Result<u64>;
    fn last_index(&self) -> Result<u64>;
    fn snapshot(&self) -> Result<Snapshot>;
}

pub struct MemStorageCore {
    hard_state: HardState,
    snapshot: Snapshot,
    // TODO: maybe vec_deque
    entries: Vec<Entry>,
}

impl Default for MemStorageCore {
    fn default() -> MemStorageCore {
        MemStorageCore {
            // When starting from scratch populate the list with a dummy entry at term zero.
            entries: vec![Entry::new()],
            hard_state: HardState::new(),
            snapshot: Snapshot::new(),
        }
    }
}

impl MemStorageCore {
    pub fn set_hardstate(&mut self, hs: HardState) {
        self.hard_state = hs;
    }

    fn inner_last_index(&self) -> u64 {
        self.entries[0].get_index() + self.entries.len() as u64 - 1
    }

    pub fn apply_snapshot(&mut self, snapshot: Snapshot) -> Result<()> {
        let mut e = Entry::new();
        e.set_term(snapshot.get_metadata().get_term());
        e.set_index(snapshot.get_metadata().get_index());
        self.entries = vec![e];
        self.snapshot = snapshot;
        Ok(())
    }

    pub fn create_snapshot(&mut self,
                           idx: u64,
                           cs: Option<ConfState>,
                           data: Vec<u8>)
                           -> Result<&Snapshot> {
        if idx <= self.snapshot.get_metadata().get_index() {
            return Err(Error::Store(StorageError::SnapshotOutOfDate));
        }

        let offset = self.entries[0].get_index();
        if idx > self.inner_last_index() {
            panic!("snapshot {} is out of bound lastindex({})",
                   idx,
                   self.inner_last_index())
        }
        self.snapshot.mut_metadata().set_index(idx);
        self.snapshot.mut_metadata().set_term(self.entries[(idx - offset) as usize].get_term());
        if let Some(cs) = cs {
            self.snapshot.mut_metadata().set_conf_state(cs)
        }
        self.snapshot.set_data(data);
        Ok(&self.snapshot)
    }

    pub fn compact(&mut self, compact_index: u64) -> Result<()> {
        let offset = self.entries[0].get_index();
        if compact_index <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        if compact_index > self.inner_last_index() {
            panic!("compact {} is out of bound lastindex({})",
                   compact_index,
                   self.inner_last_index())
        }

        let i = (compact_index - offset) as usize;
        let entries = self.entries.drain(i..).collect();
        self.entries = entries;
        Ok(())
    }

    pub fn append(&mut self, ents: &[Entry]) -> Result<()> {
        if ents.is_empty() {
            return Ok(());
        }
        let first: u64 = self.entries[0].get_index() + 1;
        let last: u64 = ents[0].get_index() + ents.len() as u64 - 1;

        if last < first {
            return Ok(());
        }
        // truncate compacted entries
        let te: &[Entry] = if first > ents[0].get_index() {
            let start = (first - ents[0].get_index()) as usize;
            &ents[start..ents.len()]
        } else {
            ents
        };

        let offset = te[0].get_index() - self.entries[0].get_index();
        if self.entries.len() as u64 > offset {
            let mut new_entries: Vec<Entry> = vec![];
            new_entries.extend_from_slice(&self.entries[..offset as usize]);
            new_entries.extend_from_slice(te);
            self.entries = new_entries;
        } else if self.entries.len() as u64 == offset {
            self.entries.extend_from_slice(te);
        } else {
            panic!("missing log entry [last: {}, append at: {}]",
                   self.inner_last_index(),
                   te[0].get_index())
        }

        Ok(())
    }
}

pub struct MemStorage {
    core: RwLock<MemStorageCore>,
}

/// A thread-safe in-memory storage implementation.
/// Mainly for tests purpose.
impl MemStorage {
    pub fn new() -> MemStorage {
        MemStorage { ..Default::default() }
    }

    pub fn rl(&self) -> RwLockReadGuard<MemStorageCore> {
        self.core.rl()
    }

    pub fn wl(&self) -> RwLockWriteGuard<MemStorageCore> {
        self.core.wl()
    }
}

impl Default for MemStorage {
    fn default() -> MemStorage {
        MemStorage { core: RwLock::new(MemStorageCore::default()) }
    }
}

impl Storage for MemStorage {
    fn initial_state(&self) -> Result<RaftState> {
        let core = self.rl();
        Ok(RaftState {
            hard_state: core.hard_state.clone(),
            conf_state: core.snapshot.get_metadata().get_conf_state().clone(),
        })
    }

    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<Vec<Entry>> {
        let core = self.rl();
        let offset = core.entries[0].get_index();
        if low <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }

        if high > core.inner_last_index() + 1 {
            panic!("index out of bound")
        }
        // only contains dummy entries.
        if core.entries.len() == 1 {
            return Err(Error::Store(StorageError::Unavailable));
        }

        let lo = (low - offset) as usize;
        let hi = (high - offset) as usize;
        let ents: &[Entry] = &core.entries[lo..hi];
        Ok(util::limit_size(ents, max_size))
    }

    fn term(&self, idx: u64) -> Result<u64> {
        let core = self.rl();
        let offset = core.entries[0].get_index();
        if idx < offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        Ok(core.entries[(idx - offset) as usize].get_term())
    }

    fn first_index(&self) -> Result<u64> {
        let core = self.rl();
        Ok(core.entries[0].get_index() + 1)
    }

    fn last_index(&self) -> Result<u64> {
        let core = self.rl();
        Ok(core.inner_last_index())
    }

    fn snapshot(&self) -> Result<Snapshot> {
        let core = self.rl();
        Ok(core.snapshot.clone())
    }
}
<commit_msg>cluster: tiny clean up (#690)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

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

#![allow(dead_code)]
#![allow(deprecated)]
use kvproto::raftpb::{HardState, ConfState, Entry, Snapshot};
use raft::errors::{Result, Error, StorageError};
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use util::{self, HandyRwLock};

#[derive(Debug, Clone)]
pub struct RaftState {
    pub hard_state: HardState,
    pub conf_state: ConfState,
}

pub trait Storage {
    fn initial_state(&self) -> Result<RaftState>;
    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<Vec<Entry>>;
    fn term(&self, idx: u64) -> Result<u64>;
    fn first_index(&self) -> Result<u64>;
    fn last_index(&self) -> Result<u64>;
    fn snapshot(&self) -> Result<Snapshot>;
}

pub struct MemStorageCore {
    hard_state: HardState,
    snapshot: Snapshot,
    // TODO: maybe vec_deque
    entries: Vec<Entry>,
}

impl Default for MemStorageCore {
    fn default() -> MemStorageCore {
        MemStorageCore {
            // When starting from scratch populate the list with a dummy entry at term zero.
            entries: vec![Entry::new()],
            hard_state: HardState::new(),
            snapshot: Snapshot::new(),
        }
    }
}

impl MemStorageCore {
    pub fn set_hardstate(&mut self, hs: HardState) {
        self.hard_state = hs;
    }

    fn inner_last_index(&self) -> u64 {
        self.entries[0].get_index() + self.entries.len() as u64 - 1
    }

    pub fn apply_snapshot(&mut self, snapshot: Snapshot) -> Result<()> {
        let mut e = Entry::new();
        e.set_term(snapshot.get_metadata().get_term());
        e.set_index(snapshot.get_metadata().get_index());
        self.entries = vec![e];
        self.snapshot = snapshot;
        Ok(())
    }

    pub fn create_snapshot(&mut self,
                           idx: u64,
                           cs: Option<ConfState>,
                           data: Vec<u8>)
                           -> Result<&Snapshot> {
        if idx <= self.snapshot.get_metadata().get_index() {
            return Err(Error::Store(StorageError::SnapshotOutOfDate));
        }

        let offset = self.entries[0].get_index();
        if idx > self.inner_last_index() {
            panic!("snapshot {} is out of bound lastindex({})",
                   idx,
                   self.inner_last_index())
        }
        self.snapshot.mut_metadata().set_index(idx);
        self.snapshot.mut_metadata().set_term(self.entries[(idx - offset) as usize].get_term());
        if let Some(cs) = cs {
            self.snapshot.mut_metadata().set_conf_state(cs)
        }
        self.snapshot.set_data(data);
        Ok(&self.snapshot)
    }

    pub fn compact(&mut self, compact_index: u64) -> Result<()> {
        let offset = self.entries[0].get_index();
        if compact_index <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        if compact_index > self.inner_last_index() {
            panic!("compact {} is out of bound lastindex({})",
                   compact_index,
                   self.inner_last_index())
        }

        let i = (compact_index - offset) as usize;
        let entries = self.entries.drain(i..).collect();
        self.entries = entries;
        Ok(())
    }

    pub fn append(&mut self, ents: &[Entry]) -> Result<()> {
        if ents.is_empty() {
            return Ok(());
        }
        let first = self.entries[0].get_index() + 1;
        let last = ents[0].get_index() + ents.len() as u64 - 1;

        if last < first {
            return Ok(());
        }
        // truncate compacted entries
        let te: &[Entry] = if first > ents[0].get_index() {
            let start = (first - ents[0].get_index()) as usize;
            &ents[start..ents.len()]
        } else {
            ents
        };

        let offset = te[0].get_index() - self.entries[0].get_index();
        if self.entries.len() as u64 > offset {
            let mut new_entries: Vec<Entry> = vec![];
            new_entries.extend_from_slice(&self.entries[..offset as usize]);
            new_entries.extend_from_slice(te);
            self.entries = new_entries;
        } else if self.entries.len() as u64 == offset {
            self.entries.extend_from_slice(te);
        } else {
            panic!("missing log entry [last: {}, append at: {}]",
                   self.inner_last_index(),
                   te[0].get_index())
        }

        Ok(())
    }
}

pub struct MemStorage {
    core: RwLock<MemStorageCore>,
}

/// A thread-safe in-memory storage implementation.
/// Mainly for tests purpose.
impl MemStorage {
    pub fn new() -> MemStorage {
        MemStorage { ..Default::default() }
    }

    pub fn rl(&self) -> RwLockReadGuard<MemStorageCore> {
        self.core.rl()
    }

    pub fn wl(&self) -> RwLockWriteGuard<MemStorageCore> {
        self.core.wl()
    }
}

impl Default for MemStorage {
    fn default() -> MemStorage {
        MemStorage { core: RwLock::new(MemStorageCore::default()) }
    }
}

impl Storage for MemStorage {
    fn initial_state(&self) -> Result<RaftState> {
        let core = self.rl();
        Ok(RaftState {
            hard_state: core.hard_state.clone(),
            conf_state: core.snapshot.get_metadata().get_conf_state().clone(),
        })
    }

    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<Vec<Entry>> {
        let core = self.rl();
        let offset = core.entries[0].get_index();
        if low <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }

        if high > core.inner_last_index() + 1 {
            panic!("index out of bound")
        }
        // only contains dummy entries.
        if core.entries.len() == 1 {
            return Err(Error::Store(StorageError::Unavailable));
        }

        let lo = (low - offset) as usize;
        let hi = (high - offset) as usize;
        let ents: &[Entry] = &core.entries[lo..hi];
        Ok(util::limit_size(ents, max_size))
    }

    fn term(&self, idx: u64) -> Result<u64> {
        let core = self.rl();
        let offset = core.entries[0].get_index();
        if idx < offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        Ok(core.entries[(idx - offset) as usize].get_term())
    }

    fn first_index(&self) -> Result<u64> {
        let core = self.rl();
        Ok(core.entries[0].get_index() + 1)
    }

    fn last_index(&self) -> Result<u64> {
        let core = self.rl();
        Ok(core.inner_last_index())
    }

    fn snapshot(&self) -> Result<Snapshot> {
        let core = self.rl();
        Ok(core.snapshot.clone())
    }
}
<|endoftext|>


<commit_before>use mio::{Evented, EventSet, EventLoop, Handler, Token};
use mio::util::Slab;
use lifeguard::{Pool, RcRecycled};

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

use slab::Index;

use Buffer;

//TODO: Provide impl for T where T: Evented + Read + Write
pub trait EventedByteStream : Evented + Read + Write {
  fn on_ready(&mut self);
  fn on_readable_bytes(&mut self, &mut Buffer);
  fn on_writable_bytes(&mut self, &Buffer);
  fn on_error(&mut self);
}

impl <T> EventedByteStream for T where T: Evented + Read + Write {
  fn on_ready(&mut self) {
    debug!("Impl ready");
  }

  fn on_readable_bytes(&mut self, buffer: &mut Buffer) {
    debug!("Impl ready");
  }

  fn on_writable_bytes(&mut self, buffer: &Buffer) {
    debug!("Impl ready");
  }

  fn on_error(&mut self) {
    debug!("Impl ready");
  }
}

#[derive(Debug)]
pub struct EventedFrameStream<E> where E: EventedByteStream {
  stream: E,
  // TODO: Could be Option<Recycled<'a, Buffer>> with lifetimes
  buffer: Option<RcRecycled<Buffer>>,
}

pub struct FrameEngineBuilder<E> where E: EventedByteStream {
  pub frame_engine: FrameEngine<E>, // TODO: make private?
  pub event_loop: EventLoop<FrameEngine<E>>
}

pub struct FrameEngine<E> where E: EventedByteStream {
  // TODO: Add server?
  pub streams: Slab<EventedFrameStream<E>>,
  pub buffer_pool: Pool<Buffer>,
  pub next_token: usize
}

impl <E> FrameEngineBuilder<E> where E: EventedByteStream {

 fn get_next_token(&mut self) -> Token {
   let token = self.frame_engine.next_token;
   self.frame_engine.next_token += 1;
   Index::from_usize(token)
 }

 // TODO: This should return a Result
 pub fn manage(&mut self, evented_byte_stream: E) {
    let evented_frame_stream = EventedFrameStream {
      stream: evented_byte_stream,
      buffer: None
    };
    // Store new stream, get token to use
    let token = match self.frame_engine.streams.insert(evented_frame_stream) {
      Ok(token) => token,
      _ => return
    };
    let efs_ref: &EventedFrameStream<E> = self.frame_engine.streams.get(token).unwrap();
    //TODO: Handle error?
    let _ = self.event_loop.register(&efs_ref.stream, token).unwrap();
  }

  pub fn run(self) {
    let mut event_loop: EventLoop<FrameEngine<E>> = self.event_loop;
    let mut frame_engine : FrameEngine<E> = self.frame_engine;
    let _ = event_loop.run(&mut frame_engine);
  }
}

impl <E> Handler for FrameEngine<E> where E: Evented {
  type Timeout = ();
  type Message = ();

  fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, event_set: EventSet) {
    debug!("Token={:?} ready, EventSet={:?}", token, event_set);
  }

  fn notify(&mut self, event_loop: &mut EventLoop<Self>, message: Self::Message) {
    debug!("Notify called, Message={:?}", message);
  }

  fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Self::Timeout) {
    debug!("Timeout called, Timeout={:?}", timeout);
  }

  fn interrupted(&mut self, event_loop: &mut EventLoop<Self>) {
    debug!("Interrupted");
  }
}

<commit_msg>Readiness testing<commit_after>use mio::{Evented, EventSet, EventLoop, Handler, Token};
use mio::util::Slab;
use lifeguard::{Pool, RcRecycled};

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

use slab::Index;

use Buffer;

//TODO: Provide impl for T where T: Evented + Read + Write
pub trait EventedByteStream : Evented + Read + Write {
  fn on_ready(&mut self);
  fn on_readable(&mut self, &mut Buffer);
  fn on_writable(&mut self, &Buffer);
  fn on_error(&mut self);
}

impl <T> EventedByteStream for T where T: Evented + Read + Write {
  fn on_ready(&mut self) {
    debug!("EventedByteStream ready");
  }

  fn on_readable(&mut self, buffer: &mut Buffer) {
    debug!("EventedByteStream readable");
  }

  fn on_writable(&mut self, buffer: &Buffer) {
    debug!("EventedByteStream writable");
  }

  fn on_error(&mut self) {
    debug!("EventedByteStream error");
  }
}

#[derive(Debug)]
enum StreamState {
  NotReady,
  Ready,
  Error,
  Closed
}

#[derive(Debug)]
pub struct EventedFrameStream<E> where E: EventedByteStream {
  stream: E,
  state: StreamState,
  // TODO: Could be Option<Recycled<'a, Buffer>> with lifetimes
  buffer: Option<RcRecycled<Buffer>>,
}

pub trait FrameHandler {
  fn on_frame_received(&mut self);
  fn on_frame_written(&mut self);
}

pub struct FrameEngineBuilder<E> where E: EventedByteStream {
  pub frame_engine: FrameEngine<E>, // TODO: make private?
  pub event_loop: EventLoop<FrameEngine<E>>
}

pub struct FrameEngine<E> where E: EventedByteStream {
  // TODO: Add server?
  pub streams: Slab<EventedFrameStream<E>>,
  pub buffer_pool: Pool<Buffer>,
  pub next_token: usize
}

impl <E> FrameEngineBuilder<E> where E: EventedByteStream {

 fn get_next_token(&mut self) -> Token {
   let token = self.frame_engine.next_token;
   self.frame_engine.next_token += 1;
   Index::from_usize(token)
 }

 // TODO: This should return a Result
 pub fn manage(&mut self, evented_byte_stream: E) {
    let evented_frame_stream = EventedFrameStream {
      stream: evented_byte_stream,
      state: StreamState::NotReady,
      buffer: None
    };
    // Store new stream, get token to use
    let token = match self.frame_engine.streams.insert(evented_frame_stream) {
      Ok(token) => token,
      _ => return
    };
    let efs: &EventedFrameStream<E> = self.frame_engine.streams.get(token).unwrap();
    //TODO: Handle error?
    let _ = self.event_loop.register(&efs.stream, token).unwrap();
  }

  pub fn run(self) {
    let mut event_loop: EventLoop<FrameEngine<E>> = self.event_loop;
    let mut frame_engine : FrameEngine<E> = self.frame_engine;
    let _ = event_loop.run(&mut frame_engine);
  }
}

impl <E> Handler for FrameEngine<E> where E: EventedByteStream {
  type Timeout = ();
  type Message = ();

  fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, event_set: EventSet) {
    use self::StreamState::*;
    debug!("Token={:?} ready, EventSet={:?}", token, event_set);
    let efs: &mut EventedFrameStream<E> = self.streams.get_mut(token).unwrap();

    if event_set.is_writable() {
      match efs.state {
        NotReady => {
          efs.state = Ready;
          efs.stream.on_ready();
        },
        _ => {
          // TODO: See if it already has a buffer
          efs.stream.on_writable(&self.buffer_pool.new());
          event_loop.shutdown();
        }
      }
    }
  }

  fn notify(&mut self, event_loop: &mut EventLoop<Self>, message: Self::Message) {
    debug!("Notify called, Message={:?}", message);
  }

  fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Self::Timeout) {
    debug!("Timeout called, Timeout={:?}", timeout);
  }

  fn interrupted(&mut self, event_loop: &mut EventLoop<Self>) {
    debug!("Interrupted");
  }
}

<|endoftext|>