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

// TODO: should not use wire_format here
use wire_format;

pub struct CodeWriter<'a> {
    writer: &'a mut (Write + 'a),
    indent: String,
}

impl<'a> CodeWriter<'a> {
    pub fn new(writer: &'a mut Write) -> CodeWriter<'a> {
        CodeWriter {
            writer: writer,
            indent: "".to_string(),
        }
    }

    pub fn write_line<S : AsRef<str>>(&mut self, line: S) {
        (if line.as_ref().is_empty() {
            self.writer.write_all("\n".as_bytes())
        } else {
            let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat();
            self.writer.write_all(s.as_bytes())
        }).unwrap();
    }

    pub fn write_generated(&mut self) {
        self.write_line("// This file is generated. Do not edit");

        // https://secure.phabricator.com/T784
        self.write_line("// @generated");

        self.write_line("");
        self.comment("https://github.com/Manishearth/rust-clippy/issues/702");
        self.write_line("#![allow(unknown_lints)]");
        self.write_line("#![allow(clippy)]");
        self.write_line("");
        self.write_line("#![cfg_attr(rustfmt, rustfmt_skip)]");
        self.write_line("");
        self.write_line("#![allow(box_pointers)]");
        self.write_line("#![allow(dead_code)]");
        self.write_line("#![allow(non_camel_case_types)]");
        self.write_line("#![allow(non_snake_case)]");
        self.write_line("#![allow(non_upper_case_globals)]");
        self.write_line("#![allow(trivial_casts)]");
        self.write_line("#![allow(unsafe_code)]");
        self.write_line("#![allow(unused_imports)]");
        self.write_line("#![allow(unused_results)]");
    }

    pub fn todo(&mut self, message: &str) {
        self.write_line(format!("panic!(\"TODO: {}\");", message));
    }

    pub fn indented<F>(&mut self, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("{}    ", self.indent),
        });
    }

    #[allow(dead_code)]
    pub fn commented<F>(&mut self, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("// {}", self.indent),
        });
    }

    pub fn lazy_static(&mut self, name: &str, ty: &str) {
        self.stmt_block(&format!("static mut {}: ::protobuf::lazy::Lazy<{}> = ::protobuf::lazy::Lazy", name, ty), |w| {
            w.field_entry("lock", "::protobuf::lazy::ONCE_INIT");
            w.field_entry("ptr", &format!("0 as *const {}", ty));
        });
    }

    pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F)
        where F : Fn(&mut CodeWriter)
    {
        self.lazy_static(name, ty);
        self.unsafe_expr(|w| {
            w.write_line(&format!("{}.get(|| {{", name));
            w.indented(|w| init(w));
            w.write_line(&format!("}})"));
        });
    }

    pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.write_line(first_line);
        self.indented(cb);
        self.write_line(last_line);
    }

    pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.block(&format!("{} {{", prefix), "}", cb);
    }

    pub fn stmt_block<S : AsRef<str>, F>(&mut self, prefix: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.block(&format!("{} {{", prefix.as_ref()), "};", cb);
    }

    pub fn unsafe_expr<F>(&mut self, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block("unsafe", cb);
    }

    pub fn impl_self_block<S : AsRef<str>, F>(&mut self, name: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("impl {}", name.as_ref()), cb);
    }

    pub fn impl_for_block<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("impl {} for {}", tr.as_ref(), ty.as_ref()), cb);
    }

    pub fn unsafe_impl(&mut self, what: &str, for_what: &str) {
        self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what));
    }

    pub fn pub_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
    }

    pub fn def_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("struct {}", name.as_ref()), cb);
    }

    pub fn pub_enum<F>(&mut self, name: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub enum {}", name), cb);
    }

    pub fn pub_trait<F>(&mut self, name: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub trait {}", name), cb);
    }

    pub fn field_entry(&mut self, name: &str, value: &str) {
        self.write_line(&format!("{}: {},", name, value));
    }

    pub fn field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("{}: {},", name, field_type));
    }

    pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("pub {}: {},", name, field_type));
    }

    pub fn derive(&mut self, derive: &[&str]) {
        let v: Vec<String> = derive.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[derive({})]", v.join(",")));
    }

    pub fn allow(&mut self, what: &[&str]) {
        let v: Vec<String> = what.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[allow({})]", v.join(",")));
    }

    pub fn comment(&mut self, comment: &str) {
        if comment.is_empty() {
            self.write_line("//");
        } else {
            self.write_line(&format!("// {}", comment));
        }
    }

    pub fn fn_def(&mut self, sig: &str) {
        self.write_line(&format!("fn {};", sig));
    }

    pub fn pub_fn<S : AsRef<str>, F>(&mut self, sig: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub fn {}", sig.as_ref()), cb);
    }

    pub fn def_fn<S : AsRef<str>, F>(&mut self, sig: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("fn {}", sig.as_ref()), cb);
    }

    pub fn while_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("while {}", cond.as_ref()), cb);
    }

    // if ... { ... }
    pub fn if_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.stmt_block(&format!("if {}", cond.as_ref()), cb);
    }

    // if ... {} else { ... }
    pub fn if_else_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.write_line(&format!("if {} {{", cond.as_ref()));
        self.write_line("} else {");
        self.indented(cb);
        self.write_line("}");
    }

    // if let ... = ... { ... }
    pub fn if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.if_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    // if let ... = ... { } else { ... }
    pub fn if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.if_else_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    pub fn for_stmt<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb)
    }

    pub fn match_block<S : AsRef<str>, F>(&mut self, value: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.stmt_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn match_expr<S : AsRef<str>, F>(&mut self, value: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn case_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.block(&format!("{} => {{", cond.as_ref()), "},", cb);
    }

    pub fn case_expr<S1 : AsRef<str>, S2 : AsRef<str>>(&mut self, cond: S1, body: S2) {
        self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref()));
    }

    pub fn error_unexpected_wire_type(&mut self, wire_type: &str) {
        self.write_line(&format!(
                "return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type({}));",
                wire_type));
    }

    pub fn assert_wire_type(&mut self, wire_type: wire_format::WireType) {
        self.if_stmt(&format!("wire_type != ::protobuf::wire_format::{:?}", wire_type), |w| {
            w.error_unexpected_wire_type("wire_type");
        });
    }
}
<commit_msg>cleanup<commit_after>use std::io::Write;

// TODO: should not use wire_format here
use wire_format;

pub struct CodeWriter<'a> {
    writer: &'a mut (Write + 'a),
    indent: String,
}

impl<'a> CodeWriter<'a> {
    pub fn new(writer: &'a mut Write) -> CodeWriter<'a> {
        CodeWriter {
            writer: writer,
            indent: "".to_string(),
        }
    }

    pub fn write_line<S : AsRef<str>>(&mut self, line: S) {
        (if line.as_ref().is_empty() {
            self.writer.write_all("\n".as_bytes())
        } else {
            let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat();
            self.writer.write_all(s.as_bytes())
        }).unwrap();
    }

    pub fn write_generated(&mut self) {
        self.write_line("// This file is generated. Do not edit");

        // https://secure.phabricator.com/T784
        self.write_line("// @generated");

        self.write_line("");
        self.comment("https://github.com/Manishearth/rust-clippy/issues/702");
        self.write_line("#![allow(unknown_lints)]");
        self.write_line("#![allow(clippy)]");
        self.write_line("");
        self.write_line("#![cfg_attr(rustfmt, rustfmt_skip)]");
        self.write_line("");
        self.write_line("#![allow(box_pointers)]");
        self.write_line("#![allow(dead_code)]");
        self.write_line("#![allow(non_camel_case_types)]");
        self.write_line("#![allow(non_snake_case)]");
        self.write_line("#![allow(non_upper_case_globals)]");
        self.write_line("#![allow(trivial_casts)]");
        self.write_line("#![allow(unsafe_code)]");
        self.write_line("#![allow(unused_imports)]");
        self.write_line("#![allow(unused_results)]");
    }

    pub fn todo(&mut self, message: &str) {
        self.write_line(format!("panic!(\"TODO: {}\");", message));
    }

    pub fn indented<F>(&mut self, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("{}    ", self.indent),
        });
    }

    #[allow(dead_code)]
    pub fn commented<F>(&mut self, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        cb(&mut CodeWriter {
            writer: self.writer,
            indent: format!("// {}", self.indent),
        });
    }

    pub fn lazy_static(&mut self, name: &str, ty: &str) {
        self.stmt_block(&format!("static mut {}: ::protobuf::lazy::Lazy<{}> = ::protobuf::lazy::Lazy", name, ty), |w| {
            w.field_entry("lock", "::protobuf::lazy::ONCE_INIT");
            w.field_entry("ptr", &format!("0 as *const {}", ty));
        });
    }

    pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F)
        where F : Fn(&mut CodeWriter)
    {
        self.lazy_static(name, ty);
        self.unsafe_expr(|w| {
            w.write_line(&format!("{}.get(|| {{", name));
            w.indented(|w| init(w));
            w.write_line(&format!("}})"));
        });
    }

    pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.write_line(first_line);
        self.indented(cb);
        self.write_line(last_line);
    }

    pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.block(&format!("{} {{", prefix), "}", cb);
    }

    pub fn stmt_block<S : AsRef<str>, F>(&mut self, prefix: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.block(&format!("{} {{", prefix.as_ref()), "};", cb);
    }

    pub fn unsafe_expr<F>(&mut self, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block("unsafe", cb);
    }

    pub fn impl_self_block<S : AsRef<str>, F>(&mut self, name: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("impl {}", name.as_ref()), cb);
    }

    pub fn impl_for_block<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("impl {} for {}", tr.as_ref(), ty.as_ref()), cb);
    }

    pub fn unsafe_impl(&mut self, what: &str, for_what: &str) {
        self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what));
    }

    pub fn pub_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
    }

    pub fn def_struct<S : AsRef<str>, F>(&mut self, name: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("struct {}", name.as_ref()), cb);
    }

    pub fn pub_enum<F>(&mut self, name: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub enum {}", name), cb);
    }

    pub fn pub_trait<F>(&mut self, name: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("pub trait {}", name), cb);
    }

    pub fn field_entry(&mut self, name: &str, value: &str) {
        self.write_line(&format!("{}: {},", name, value));
    }

    pub fn field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("{}: {},", name, field_type));
    }

    pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
        self.write_line(&format!("pub {}: {},", name, field_type));
    }

    pub fn derive(&mut self, derive: &[&str]) {
        let v: Vec<String> = derive.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[derive({})]", v.join(",")));
    }

    pub fn allow(&mut self, what: &[&str]) {
        let v: Vec<String> = what.iter().map(|&s| s.to_string()).collect();
        self.write_line(&format!("#[allow({})]", v.join(",")));
    }

    pub fn comment(&mut self, comment: &str) {
        if comment.is_empty() {
            self.write_line("//");
        } else {
            self.write_line(&format!("// {}", comment));
        }
    }

    pub fn fn_def(&mut self, sig: &str) {
        self.write_line(&format!("fn {};", sig));
    }

    pub fn fb_block<F>(&mut self, public: bool, sig: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        if public {
            self.expr_block(&format!("pub fn {}", sig.as_ref()), cb);
        } else {
            self.expr_block(&format!("fn {}", sig.as_ref()), cb);
        }
    }

    pub fn pub_fn<F>(&mut self, sig: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.fn_block(true, sig, cb);
    }

    pub fn def_fn<F>(&mut self, sig: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.fn_block(false, sig, cb);
    }

    pub fn while_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("while {}", cond.as_ref()), cb);
    }

    // if ... { ... }
    pub fn if_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.stmt_block(&format!("if {}", cond.as_ref()), cb);
    }

    // if ... {} else { ... }
    pub fn if_else_stmt<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.write_line(&format!("if {} {{", cond.as_ref()));
        self.write_line("} else {");
        self.indented(cb);
        self.write_line("}");
    }

    // if let ... = ... { ... }
    pub fn if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.if_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    // if let ... = ... { } else { ... }
    pub fn if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.if_else_stmt(&format!("let {} = {}", decl, expr), cb);
    }

    pub fn for_stmt<S1 : AsRef<str>, S2 : AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb)
    }

    pub fn match_block<S : AsRef<str>, F>(&mut self, value: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.stmt_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn match_expr<S : AsRef<str>, F>(&mut self, value: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.expr_block(&format!("match {}", value.as_ref()), cb);
    }

    pub fn case_block<S : AsRef<str>, F>(&mut self, cond: S, cb: F)
        where F : Fn(&mut CodeWriter)
    {
        self.block(&format!("{} => {{", cond.as_ref()), "},", cb);
    }

    pub fn case_expr<S1 : AsRef<str>, S2 : AsRef<str>>(&mut self, cond: S1, body: S2) {
        self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref()));
    }

    pub fn error_unexpected_wire_type(&mut self, wire_type: &str) {
        self.write_line(&format!(
                "return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type({}));",
                wire_type));
    }

    pub fn assert_wire_type(&mut self, wire_type: wire_format::WireType) {
        self.if_stmt(&format!("wire_type != ::protobuf::wire_format::{:?}", wire_type), |w| {
            w.error_unexpected_wire_type("wire_type");
        });
    }
}
<|endoftext|>


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

use clean::*;
use std::iter::Extendable;
use std::mem::{replace, swap};

pub trait DocFolder {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        self.fold_item_recur(item)
    }

    /// don't override!
    fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
        let Item { attrs, name, source, visibility, id, inner } = item;
        let inner = inner;
        let c = |x| self.fold_item(x);
        let inner = match inner {
            StructItem(mut i) => {
                let mut foo = ~[]; swap(&mut foo, &mut i.fields);
                let num_fields = foo.len();
                i.fields.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
                i.fields_stripped |= num_fields != i.fields.len();
                StructItem(i)
            },
            ModuleItem(i) => {
                ModuleItem(self.fold_mod(i))
            },
            EnumItem(mut i) => {
                let mut foo = ~[]; swap(&mut foo, &mut i.variants);
                let num_variants = foo.len();
                i.variants.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
                i.variants_stripped |= num_variants != i.variants.len();
                EnumItem(i)
            },
            TraitItem(mut i) => {
                fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
                    match trm {
                        Required(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(Required(x)),
                                None => return None,
                            }
                        },
                        Provided(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(Provided(x)),
                                None => return None,
                            }
                        },
                    }
                }
                let mut foo = ~[]; swap(&mut foo, &mut i.methods);
                i.methods.extend(&mut foo.move_iter().filter_map(|x| vtrm(self, x)));
                TraitItem(i)
            },
            ImplItem(mut i) => {
                let mut foo = ~[]; swap(&mut foo, &mut i.methods);
                i.methods.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
                ImplItem(i)
            },
            VariantItem(i) => {
                let i2 = i.clone(); // this clone is small
                match i.kind {
                    StructVariant(mut j) => {
                        let mut foo = ~[]; swap(&mut foo, &mut j.fields);
                        let num_fields = foo.len();
                        j.fields.extend(&mut foo.move_iter().filter_map(c));
                        j.fields_stripped |= num_fields != j.fields.len();
                        VariantItem(Variant {kind: StructVariant(j), ..i2})
                    },
                    _ => VariantItem(i2)
                }
            },
            x => x
        };

        Some(Item { attrs: attrs, name: name, source: source, inner: inner,
                    visibility: visibility, id: id })
    }

    fn fold_mod(&mut self, m: Module) -> Module {
        Module { items: m.items.move_iter().filter_map(|i| self.fold_item(i)).collect() }
    }

    fn fold_crate(&mut self, mut c: Crate) -> Crate {
        c.module = match replace(&mut c.module, None) {
            Some(module) => self.fold_item(module), None => None
        };
        return c;
    }
}
<commit_msg>librustdoc -- move closure to clarify scope<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use clean::*;
use std::iter::Extendable;
use std::mem::{replace, swap};

pub trait DocFolder {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        self.fold_item_recur(item)
    }

    /// don't override!
    fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
        let Item { attrs, name, source, visibility, id, inner } = item;
        let inner = inner;
        let inner = match inner {
            StructItem(mut i) => {
                let mut foo = ~[]; swap(&mut foo, &mut i.fields);
                let num_fields = foo.len();
                i.fields.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
                i.fields_stripped |= num_fields != i.fields.len();
                StructItem(i)
            },
            ModuleItem(i) => {
                ModuleItem(self.fold_mod(i))
            },
            EnumItem(mut i) => {
                let mut foo = ~[]; swap(&mut foo, &mut i.variants);
                let num_variants = foo.len();
                i.variants.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
                i.variants_stripped |= num_variants != i.variants.len();
                EnumItem(i)
            },
            TraitItem(mut i) => {
                fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
                    match trm {
                        Required(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(Required(x)),
                                None => return None,
                            }
                        },
                        Provided(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(Provided(x)),
                                None => return None,
                            }
                        },
                    }
                }
                let mut foo = ~[]; swap(&mut foo, &mut i.methods);
                i.methods.extend(&mut foo.move_iter().filter_map(|x| vtrm(self, x)));
                TraitItem(i)
            },
            ImplItem(mut i) => {
                let mut foo = ~[]; swap(&mut foo, &mut i.methods);
                i.methods.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
                ImplItem(i)
            },
            VariantItem(i) => {
                let i2 = i.clone(); // this clone is small
                match i.kind {
                    StructVariant(mut j) => {
                        let mut foo = ~[]; swap(&mut foo, &mut j.fields);
                        let num_fields = foo.len();
                        let c = |x| self.fold_item(x);
                        j.fields.extend(&mut foo.move_iter().filter_map(c));
                        j.fields_stripped |= num_fields != j.fields.len();
                        VariantItem(Variant {kind: StructVariant(j), ..i2})
                    },
                    _ => VariantItem(i2)
                }
            },
            x => x
        };

        Some(Item { attrs: attrs, name: name, source: source, inner: inner,
                    visibility: visibility, id: id })
    }

    fn fold_mod(&mut self, m: Module) -> Module {
        Module { items: m.items.move_iter().filter_map(|i| self.fold_item(i)).collect() }
    }

    fn fold_crate(&mut self, mut c: Crate) -> Crate {
        c.module = match replace(&mut c.module, None) {
            Some(module) => self.fold_item(module), None => None
        };
        return c;
    }
}
<|endoftext|>


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

use prelude::v1::*;
use io::prelude::*;

use cmp;
use fmt;
use io::lazy::Lazy;
use io::{self, BufReader, LineWriter};
use sync::{Arc, Mutex, MutexGuard};
use sys::stdio;

/// A handle to a raw instance of the standard input stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdin_raw` function.
pub struct StdinRaw(stdio::Stdin);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdout_raw` function.
pub struct StdoutRaw(stdio::Stdout);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stderr_raw` function.
pub struct StderrRaw(stdio::Stderr);

/// Construct a new raw handle to the standard input of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
/// handles is **not** available to raw handles returned from this function.
///
/// The returned handle has no external synchronization or buffering.
pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`. Note that data is buffered by the
/// `std::io::stdin` handles so writes which happen via this raw handle may
/// appear before previous writes.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
pub fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }

impl Read for StdinRaw {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
}
impl Write for StdoutRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl Write for StderrRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

/// A handle to the standard input stream of a process.
///
/// Each handle is a shared reference to a global buffer of input data to this
/// process. A handle can be `lock`'d to gain full access to `BufRead` methods
/// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect
/// to other writes.
///
/// This handle implements the `Read` trait, but beware that concurrent reads
/// of `Stdin` must be executed with care.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
    inner: Arc<Mutex<BufReader<StdinRaw>>>,
}

/// A locked reference to the a `Stdin` handle.
///
/// This handle implements both the `Read` and `BufRead` traits and is
/// constructed via the `lock` method on `Stdin`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdinLock<'a> {
    inner: MutexGuard<'a, BufReader<StdinRaw>>,
}

/// Create a new handle to the global standard input stream of this process.
///
/// The handle returned refers to a globally shared buffer between all threads.
/// Access is synchronized and can be explicitly controlled with the `lock()`
/// method.
///
/// The `Read` trait is implemented for the returned value but the `BufRead`
/// trait is not due to the global nature of the standard input stream. The
/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
///
/// To avoid locking and buffering altogether, it is recommended to use the
/// `stdin_raw` constructor.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
    return Stdin {
        inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
    };

    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
        // The default buffer capacity is 64k, but apparently windows
        // doesn't like 64k reads on stdin. See #13304 for details, but the
        // idea is that on windows we use a slightly smaller buffer that's
        // been seen to be acceptable.
        Arc::new(Mutex::new(if cfg!(windows) {
            BufReader::with_capacity(8 * 1024, stdin_raw())
        } else {
            BufReader::new(stdin_raw())
        }))
    }
}

impl Stdin {
    /// Lock this handle to the standard input stream, returning a readable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Read` and `BufRead` traits for
    /// accessing the underlying data.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn lock(&self) -> StdinLock {
        StdinLock { inner: self.inner.lock().unwrap() }
    }

    /// Locks this handle and reads a line of input into the specified buffer.
    ///
    /// For detailed semantics of this method, see the documentation on
    /// `BufRead::read_line`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
        self.lock().read_line(buf)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.lock().read(buf)
    }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        self.lock().read_to_end(buf)
    }
    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
        self.lock().read_to_string(buf)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Read for StdinLock<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> BufRead for StdinLock<'a> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
    fn consume(&mut self, n: usize) { self.inner.consume(n) }
}

// As with stdin on windows, stdout often can't handle writes of large
// sizes. For an example, see #14940. For this reason, don't try to
// write the entire output buffer on windows. On unix we can just
// write the whole buffer all at once.
//
// For some other references, it appears that this problem has been
// encountered by others [1] [2]. We choose the number 8KB just because
// libuv does the same.
//
// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
#[cfg(windows)]
const OUT_MAX: usize = 8192;
#[cfg(unix)]
const OUT_MAX: usize = ::usize::MAX;

/// A handle to the global standard output stream of the current process.
///
/// Each handle shares a global buffer of data to be written to the standard
/// output stream. Access is also synchronized via a lock and explicit control
/// over locking is available via the `lock` method.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdout {
    // FIXME: this should be LineWriter or BufWriter depending on the state of
    //        stdout (tty or not). Note that if this is not line buffered it
    //        should also flush-on-panic or some form of flush-on-abort.
    inner: Arc<Mutex<LineWriter<StdoutRaw>>>,
}

/// A locked reference to the a `Stdout` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stdout`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
    inner: MutexGuard<'a, LineWriter<StdoutRaw>>,
}

/// Constructs a new reference to the standard output of the current process.
///
/// Each handle returned is a reference to a shared global buffer whose access
/// is synchronized via a mutex. Explicit control over synchronization is
/// provided via the `lock` method.
///
/// The returned handle implements the `Write` trait.
///
/// To avoid locking and buffering altogether, it is recommended to use the
/// `stdout_raw` constructor.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
    static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init);
    return Stdout {
        inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
    };

    fn stdout_init() -> Arc<Mutex<LineWriter<StdoutRaw>>> {
        Arc::new(Mutex::new(LineWriter::new(stdout_raw())))
    }
}

impl Stdout {
    /// Lock this handle to the standard output stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn lock(&self) -> StdoutLock {
        StdoutLock { inner: self.inner.lock().unwrap() }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for StdoutLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}

/// A handle to the standard error stream of a process.
///
/// For more information, see `stderr`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
    inner: Arc<Mutex<StderrRaw>>,
}

/// A locked reference to the a `Stderr` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stderr`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
    inner: MutexGuard<'a, StderrRaw>,
}

/// Constructs a new reference to the standard error stream of a process.
///
/// Each returned handle is synchronized amongst all other handles created from
/// this function. No handles are buffered, however.
///
/// The returned handle implements the `Write` trait.
///
/// To avoid locking altogether, it is recommended to use the `stderr_raw`
/// constructor.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
    static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init);
    return Stderr {
        inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
    };

    fn stderr_init() -> Arc<Mutex<StderrRaw>> {
        Arc::new(Mutex::new(stderr_raw()))
    }
}

impl Stderr {
    /// Lock this handle to the standard error stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn lock(&self) -> StderrLock {
        StderrLock { inner: self.inner.lock().unwrap() }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for StderrLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}

/// Resets the task-local stdout handle to the specified writer
///
/// This will replace the current task's stdout handle, returning the old
/// handle. All future calls to `print` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
#[unstable(feature = "set_panic",
           reason = "this function may disappear completely or be replaced \
                     with a more general mechanism")]
#[doc(hidden)]
pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
    use panicking::LOCAL_STDERR;
    use mem;
    LOCAL_STDERR.with(move |slot| {
        mem::replace(&mut *slot.borrow_mut(), Some(sink))
    }).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}
<commit_msg>Rollup merge of #23379 - kballard:tweak-stdio-docs-no-raw-constructors, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use prelude::v1::*;
use io::prelude::*;

use cmp;
use fmt;
use io::lazy::Lazy;
use io::{self, BufReader, LineWriter};
use sync::{Arc, Mutex, MutexGuard};
use sys::stdio;

/// A handle to a raw instance of the standard input stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdio::stdin_raw` function.
struct StdinRaw(stdio::Stdin);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdio::stdout_raw` function.
struct StdoutRaw(stdio::Stdout);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdio::stderr_raw` function.
struct StderrRaw(stdio::Stderr);

/// Construct a new raw handle to the standard input of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
/// handles is **not** available to raw handles returned from this function.
///
/// The returned handle has no external synchronization or buffering.
fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`. Note that data is buffered by the
/// `std::io::stdin` handles so writes which happen via this raw handle may
/// appear before previous writes.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }

impl Read for StdinRaw {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
}
impl Write for StdoutRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl Write for StderrRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

/// A handle to the standard input stream of a process.
///
/// Each handle is a shared reference to a global buffer of input data to this
/// process. A handle can be `lock`'d to gain full access to `BufRead` methods
/// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect
/// to other writes.
///
/// This handle implements the `Read` trait, but beware that concurrent reads
/// of `Stdin` must be executed with care.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
    inner: Arc<Mutex<BufReader<StdinRaw>>>,
}

/// A locked reference to the a `Stdin` handle.
///
/// This handle implements both the `Read` and `BufRead` traits and is
/// constructed via the `lock` method on `Stdin`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdinLock<'a> {
    inner: MutexGuard<'a, BufReader<StdinRaw>>,
}

/// Create a new handle to the global standard input stream of this process.
///
/// The handle returned refers to a globally shared buffer between all threads.
/// Access is synchronized and can be explicitly controlled with the `lock()`
/// method.
///
/// The `Read` trait is implemented for the returned value but the `BufRead`
/// trait is not due to the global nature of the standard input stream. The
/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
    return Stdin {
        inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
    };

    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
        // The default buffer capacity is 64k, but apparently windows
        // doesn't like 64k reads on stdin. See #13304 for details, but the
        // idea is that on windows we use a slightly smaller buffer that's
        // been seen to be acceptable.
        Arc::new(Mutex::new(if cfg!(windows) {
            BufReader::with_capacity(8 * 1024, stdin_raw())
        } else {
            BufReader::new(stdin_raw())
        }))
    }
}

impl Stdin {
    /// Lock this handle to the standard input stream, returning a readable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Read` and `BufRead` traits for
    /// accessing the underlying data.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn lock(&self) -> StdinLock {
        StdinLock { inner: self.inner.lock().unwrap() }
    }

    /// Locks this handle and reads a line of input into the specified buffer.
    ///
    /// For detailed semantics of this method, see the documentation on
    /// `BufRead::read_line`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
        self.lock().read_line(buf)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.lock().read(buf)
    }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        self.lock().read_to_end(buf)
    }
    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
        self.lock().read_to_string(buf)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Read for StdinLock<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> BufRead for StdinLock<'a> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
    fn consume(&mut self, n: usize) { self.inner.consume(n) }
}

// As with stdin on windows, stdout often can't handle writes of large
// sizes. For an example, see #14940. For this reason, don't try to
// write the entire output buffer on windows. On unix we can just
// write the whole buffer all at once.
//
// For some other references, it appears that this problem has been
// encountered by others [1] [2]. We choose the number 8KB just because
// libuv does the same.
//
// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
#[cfg(windows)]
const OUT_MAX: usize = 8192;
#[cfg(unix)]
const OUT_MAX: usize = ::usize::MAX;

/// A handle to the global standard output stream of the current process.
///
/// Each handle shares a global buffer of data to be written to the standard
/// output stream. Access is also synchronized via a lock and explicit control
/// over locking is available via the `lock` method.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdout {
    // FIXME: this should be LineWriter or BufWriter depending on the state of
    //        stdout (tty or not). Note that if this is not line buffered it
    //        should also flush-on-panic or some form of flush-on-abort.
    inner: Arc<Mutex<LineWriter<StdoutRaw>>>,
}

/// A locked reference to the a `Stdout` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stdout`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
    inner: MutexGuard<'a, LineWriter<StdoutRaw>>,
}

/// Constructs a new reference to the standard output of the current process.
///
/// Each handle returned is a reference to a shared global buffer whose access
/// is synchronized via a mutex. Explicit control over synchronization is
/// provided via the `lock` method.
///
/// The returned handle implements the `Write` trait.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
    static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init);
    return Stdout {
        inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
    };

    fn stdout_init() -> Arc<Mutex<LineWriter<StdoutRaw>>> {
        Arc::new(Mutex::new(LineWriter::new(stdout_raw())))
    }
}

impl Stdout {
    /// Lock this handle to the standard output stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn lock(&self) -> StdoutLock {
        StdoutLock { inner: self.inner.lock().unwrap() }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for StdoutLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}

/// A handle to the standard error stream of a process.
///
/// For more information, see `stderr`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
    inner: Arc<Mutex<StderrRaw>>,
}

/// A locked reference to the a `Stderr` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stderr`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
    inner: MutexGuard<'a, StderrRaw>,
}

/// Constructs a new reference to the standard error stream of a process.
///
/// Each returned handle is synchronized amongst all other handles created from
/// this function. No handles are buffered, however.
///
/// The returned handle implements the `Write` trait.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
    static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init);
    return Stderr {
        inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
    };

    fn stderr_init() -> Arc<Mutex<StderrRaw>> {
        Arc::new(Mutex::new(stderr_raw()))
    }
}

impl Stderr {
    /// Lock this handle to the standard error stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn lock(&self) -> StderrLock {
        StderrLock { inner: self.inner.lock().unwrap() }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for StderrLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}

/// Resets the task-local stdout handle to the specified writer
///
/// This will replace the current task's stdout handle, returning the old
/// handle. All future calls to `print` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
#[unstable(feature = "set_panic",
           reason = "this function may disappear completely or be replaced \
                     with a more general mechanism")]
#[doc(hidden)]
pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
    use panicking::LOCAL_STDERR;
    use mem;
    LOCAL_STDERR.with(move |slot| {
        mem::replace(&mut *slot.borrow_mut(), Some(sink))
    }).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}
<|endoftext|>


<commit_before>use std;
use std::io;
use std::path::Path;
use std::fs::File;
use map;
use map::Map;
use regex::Regex;

// Parse errors
#[derive(Debug)]
pub enum Error {
    IO(io::Error),
    Invalid(String),
    IntParse(std::num::ParseIntError),
    NoHeader,
}

// Read file's header, return dimensions of the pattern
fn parse_header<'a, I>(lines: &mut I) -> Result<(usize, usize), Error>
    where I: Iterator<Item=&'a str>
{
    lazy_static! {
        // regex to match "x = m, y = n", ignore "rule = ..."
        static ref HEADER: Regex = Regex::new(r"^\s*x\s*=\s*(\d+)\s*,\s*y\s*=\s*(\d+)").unwrap();
    }

    for line in lines {
        if line.starts_with("#") {
            // Other unsupported options, ignore
        } else if HEADER.is_match(line) {
            let cap = HEADER.captures_iter(line).next().unwrap();
            let x = cap[1].parse().map_err(Error::IntParse)?;
            let y = cap[2].parse().map_err(Error::IntParse)?;
            return Ok((x, y));
        } else {
            return Err(Error::Invalid(line.to_string()));
        }
    };

    Err(Error::NoHeader)
}

struct Parse {
    x: usize,
    y: usize,
    stop: bool,
    live: Vec<(usize, usize)>,
}
fn parse(line: &str, mut x: usize, mut y: usize) -> Result<Parse, Error> {
    let mut vec = Vec::new();
    let mut stop = false;
    let mut cnt = 0;

    let mut debug = String::new();
    for ch in line.chars() {
        debug.push(ch);
        if ch == '!' {
            stop = true;
            break;
        } else if ch == '$' {
            if cnt == 0 {
                cnt = 1;
            }
            y += cnt;
            cnt = 0;
        } else if ch == 'b' || ch == 'o' {
            if cnt == 0 {
                cnt = 1;
            }
            for _ in 0..cnt {
                // rust may be able to remove this if statement,
                // if it cannot, the code must be rewrited.
                if ch == 'b' {
                    vec.push((x, y));
                }
                x += 1;
            }
            cnt = 0;
        } else if let Some(d) = ch.to_digit(10) {
            cnt = cnt * 10 + d as usize;
        }
        // ignore all other characters, this behavior needs to be reconsidered.
    }

    Ok(Parse {
        x: x,
        y: y,
        stop: stop,
        live: vec,
    })
}

pub fn read_file<P: AsRef<Path>>(p: P) -> Result<Map, Error> {
    let input = {
        use std::io::Read;
        let mut file = File::open(p).map_err(Error::IO)?;
        let mut s = String::new();
        file.read_to_string(&mut s).map_err(Error::IO)?;
        s
    };

    let mut lines = input.lines();
    parse_header(&mut lines)?;
    let mut map = Map::new();
    let mut x = 0;
    let mut y = 0;
    for line in lines {
        let res = parse(line, x, y)?;
        x = res.x;
        y = res.y;
        for (x, y) in res.live {
            map.set_cell_alive(&map::pos(x as i32, y as i32));
        }
        if res.stop {
            break;
        }
    }
    Ok(map)
}
<commit_msg>fix bug<commit_after>use std;
use std::io;
use std::path::Path;
use std::fs::File;
use map;
use map::Map;
use regex::Regex;

// Parse errors
#[derive(Debug)]
pub enum Error {
    IO(io::Error),
    Invalid(String),
    IntParse(std::num::ParseIntError),
    NoHeader,
}

// Read file's header, return dimensions of the pattern
fn parse_header<'a, I>(lines: &mut I) -> Result<(usize, usize), Error>
    where I: Iterator<Item=&'a str>
{
    lazy_static! {
        // regex to match "x = m, y = n", ignore "rule = ..."
        static ref HEADER: Regex = Regex::new(r"^\s*x\s*=\s*(\d+)\s*,\s*y\s*=\s*(\d+)").unwrap();
    }

    for line in lines {
        if line.starts_with("#") {
            // Other unsupported options, ignore
        } else if HEADER.is_match(line) {
            let cap = HEADER.captures_iter(line).next().unwrap();
            let x = cap[1].parse().map_err(Error::IntParse)?;
            let y = cap[2].parse().map_err(Error::IntParse)?;
            return Ok((x, y));
        } else {
            return Err(Error::Invalid(line.to_string()));
        }
    };

    Err(Error::NoHeader)
}

struct Parse {
    x: usize,
    y: usize,
    stop: bool,
    live: Vec<(usize, usize)>,
}
fn parse(line: &str, mut x: usize, mut y: usize) -> Result<Parse, Error> {
    let mut vec = Vec::new();
    let mut stop = false;
    let mut cnt = 0;

    for ch in line.chars() {
        if ch == '!' {
            stop = true;
            break;
        } else if ch == '$' {
            if cnt == 0 {
                cnt = 1;
            }
            y += cnt;
            x = 0;
            cnt = 0;
        } else if ch == 'b' || ch == 'o' {
            if cnt == 0 {
                cnt = 1;
            }
            if ch == 'o' {
                vec.extend((x..x+cnt).map(|x| (x, y)));
            }
            x += cnt;
            cnt = 0;
        } else if let Some(d) = ch.to_digit(10) {
            cnt = cnt * 10 + d as usize;
        }
        // ignore all other characters, this behavior needs to be reconsidered.
    }

    Ok(Parse {
        x: x,
        y: y,
        stop: stop,
        live: vec,
    })
}

pub fn read_file<P: AsRef<Path>>(p: P) -> Result<Map, Error> {
    let input = {
        use std::io::Read;
        let mut file = File::open(p).map_err(Error::IO)?;
        let mut s = String::new();
        file.read_to_string(&mut s).map_err(Error::IO)?;
        s
    };

    let mut lines = input.lines();
    parse_header(&mut lines)?;
    let mut map = Map::new();
    let mut x = 0;
    let mut y = 0;
    for line in lines {
        let res = parse(line, x, y)?;
        x = res.x;
        y = res.y;
        for (x, y) in res.live {
            map.set_cell_alive(&map::pos(x as i32, y as i32));
        }
        if res.stop {
            break;
        }
    }
    Ok(map)
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

use ::ProcessorExt;

/// Struct containing values to compute a CPU usage.
#[derive(Clone, Copy)]
pub struct CpuValues {
    user: u64,
    nice: u64,
    system: u64,
    idle: u64,
    iowait: u64,
    irq: u64,
    softirq: u64,
    steal: u64,
    guest: u64,
    guest_nice: u64,
}

impl CpuValues {
    /// Creates a new instance of `CpuValues` with everything set to `0`.
    pub fn new() -> CpuValues {
        CpuValues {
            user: 0,
            nice: 0,
            system: 0,
            idle: 0,
            iowait: 0,
            irq: 0,
            softirq: 0,
            steal: 0,
            guest: 0,
            guest_nice: 0,
        }
    }

    /// Creates a new instance of `CpuValues` with everything set to the corresponding argument.
    pub fn new_with_values(user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                           irq: u64, softirq: u64, steal: u64, guest: u64,
                           guest_nice: u64) -> CpuValues {
        CpuValues {
            user: user,
            nice: nice,
            system: system,
            idle: idle,
            iowait: iowait,
            irq: irq,
            softirq: softirq,
            steal: steal,
            guest: guest,
            guest_nice: guest_nice
        }
    }

    /*pub fn is_zero(&self) -> bool {
        self.user == 0 && self.nice == 0 && self.system == 0 && self.idle == 0 &&
        self.iowait == 0 && self.irq == 0 && self.softirq == 0 && self.steal == 0 &&
        self.guest == 0 && self.guest_nice == 0
    }*/

    /// Sets the given argument to the corresponding fields.
    pub fn set(&mut self, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
               irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) {
        self.user = user;
        self.nice = nice;
        self.system = system;
        self.idle = idle;
        self.iowait = iowait;
        self.irq = irq;
        self.softirq = softirq;
        self.steal = steal;
        self.guest = guest;
        self.guest_nice = guest_nice;
    }

    /// Returns work time.
    pub fn work_time(&self) -> u64 {
        self.user + self.nice + self.system
    }

    /// Returns total time.
    pub fn total_time(&self) -> u64 {
        self.work_time() + self.idle + self.iowait + self.irq + self.softirq
            + self.steal + self.guest + self.guest_nice
    }
}

/// Struct containing a processor information.
pub struct Processor {
    old_values: CpuValues,
    new_values: CpuValues,
    name: String,
    cpu_usage: f32,
    total_time: u64,
    old_total_time: u64,
}

impl Processor {
    #[allow(dead_code)]
    fn new() -> Processor {
        Processor {
            name: String::new(),
            old_values: CpuValues::new(),
            new_values: CpuValues::new(),
            cpu_usage: 0f32,
            total_time: 0,
            old_total_time: 0,
        }
    }

    fn new_with_values(name: &str, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                       irq: u64, softirq: u64, steal: u64, guest: u64,
                       guest_nice: u64) -> Processor {
        Processor {
            name: name.to_owned(),
            old_values: CpuValues::new(),
            new_values: CpuValues::new_with_values(user, nice, system, idle, iowait, irq,
                softirq, steal, guest, guest_nice),
            cpu_usage: 0f32,
            total_time: 0,
            old_total_time: 0,
        }
    }

    fn set(&mut self, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
           irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) {
            //if !self.new_values.is_zero() {
                self.old_values = self.new_values;
            //}
            self.new_values.set(user, nice, system, idle, iowait, irq, softirq, steal,
                guest, guest_nice);
            self.cpu_usage = (self.new_values.work_time() - self.old_values.work_time()) as f32 /
                (self.new_values.total_time() - self.old_values.total_time()) as f32;
            self.old_total_time = self.old_values.total_time();
            self.total_time = self.new_values.total_time();
    }
}

impl ProcessorExt for Processor {
    fn get_cpu_usage(&self) -> f32 {
        self.cpu_usage
    }

    fn get_name(&self) -> &str {
        &self.name
    }
}

pub fn new_processor(name: &str, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                     irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) -> Processor {
    Processor::new_with_values(name, user, nice, system, idle, iowait, irq, softirq, steal,
        guest, guest_nice)
}

pub fn set_processor(p: &mut Processor, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                     irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) {
    p.set(user, nice, system, idle, iowait, irq, softirq, steal,
        guest, guest_nice)
}

pub fn get_raw_times(p: &Processor) -> (u64, u64) {
    (p.new_values.total_time(), p.old_values.total_time())
}
<commit_msg>Fix runtime error<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

use ::ProcessorExt;

/// Struct containing values to compute a CPU usage.
#[derive(Clone, Copy)]
pub struct CpuValues {
    user: u64,
    nice: u64,
    system: u64,
    idle: u64,
    iowait: u64,
    irq: u64,
    softirq: u64,
    steal: u64,
    guest: u64,
    guest_nice: u64,
}

impl CpuValues {
    /// Creates a new instance of `CpuValues` with everything set to `0`.
    pub fn new() -> CpuValues {
        CpuValues {
            user: 0,
            nice: 0,
            system: 0,
            idle: 0,
            iowait: 0,
            irq: 0,
            softirq: 0,
            steal: 0,
            guest: 0,
            guest_nice: 0,
        }
    }

    /// Creates a new instance of `CpuValues` with everything set to the corresponding argument.
    pub fn new_with_values(user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                           irq: u64, softirq: u64, steal: u64, guest: u64,
                           guest_nice: u64) -> CpuValues {
        CpuValues {
            user: user,
            nice: nice,
            system: system,
            idle: idle,
            iowait: iowait,
            irq: irq,
            softirq: softirq,
            steal: steal,
            guest: guest,
            guest_nice: guest_nice
        }
    }

    /*pub fn is_zero(&self) -> bool {
        self.user == 0 && self.nice == 0 && self.system == 0 && self.idle == 0 &&
        self.iowait == 0 && self.irq == 0 && self.softirq == 0 && self.steal == 0 &&
        self.guest == 0 && self.guest_nice == 0
    }*/

    /// Sets the given argument to the corresponding fields.
    pub fn set(&mut self, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
               irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) {
        self.user = user;
        self.nice = nice;
        self.system = system;
        self.idle = idle;
        self.iowait = iowait;
        self.irq = irq;
        self.softirq = softirq;
        self.steal = steal;
        self.guest = guest;
        self.guest_nice = guest_nice;
    }

    /// Returns work time.
    pub fn work_time(&self) -> u64 {
        self.user + self.nice + self.system
    }

    /// Returns total time.
    pub fn total_time(&self) -> u64 {
        self.work_time() + self.idle + self.iowait + self.irq + self.softirq
            + self.steal + self.guest + self.guest_nice
    }
}

/// Struct containing a processor information.
pub struct Processor {
    old_values: CpuValues,
    new_values: CpuValues,
    name: String,
    cpu_usage: f32,
    total_time: u64,
    old_total_time: u64,
}

impl Processor {
    #[allow(dead_code)]
    fn new() -> Processor {
        Processor {
            name: String::new(),
            old_values: CpuValues::new(),
            new_values: CpuValues::new(),
            cpu_usage: 0f32,
            total_time: 0,
            old_total_time: 0,
        }
    }

    fn new_with_values(name: &str, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                       irq: u64, softirq: u64, steal: u64, guest: u64,
                       guest_nice: u64) -> Processor {
        Processor {
            name: name.to_owned(),
            old_values: CpuValues::new(),
            new_values: CpuValues::new_with_values(user, nice, system, idle, iowait, irq,
                softirq, steal, guest, guest_nice),
            cpu_usage: 0f32,
            total_time: 0,
            old_total_time: 0,
        }
    }

    fn set(&mut self, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
           irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) {
        fn min(a: u64, b: u64) -> f32 {
            if a == b { 1 } else if a > b { a - b } else { b - a } as f32
        }
        //if !self.new_values.is_zero() {
            self.old_values = self.new_values;
        //}
        self.new_values.set(user, nice, system, idle, iowait, irq, softirq, steal,
            guest, guest_nice);
        self.cpu_usage = min(self.new_values.work_time(), self.old_values.work_time()) /
            min(self.new_values.total_time(), - self.old_values.total_time());
        self.old_total_time = self.old_values.total_time();
        self.total_time = self.new_values.total_time();
    }
}

impl ProcessorExt for Processor {
    fn get_cpu_usage(&self) -> f32 {
        self.cpu_usage
    }

    fn get_name(&self) -> &str {
        &self.name
    }
}

pub fn new_processor(name: &str, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                     irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) -> Processor {
    Processor::new_with_values(name, user, nice, system, idle, iowait, irq, softirq, steal,
        guest, guest_nice)
}

pub fn set_processor(p: &mut Processor, user: u64, nice: u64, system: u64, idle: u64, iowait: u64,
                     irq: u64, softirq: u64, steal: u64, guest: u64, guest_nice: u64) {
    p.set(user, nice, system, idle, iowait, irq, softirq, steal,
        guest, guest_nice)
}

pub fn get_raw_times(p: &Processor) -> (u64, u64) {
    (p.new_values.total_time(), p.old_values.total_time())
}
<|endoftext|>


<commit_before>use std::mem;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};

use time::{Timespec};
use byteorder::{ByteOrder, LittleEndian};

use super::super::crypto::{Hash, PublicKey};

use super::Error;

pub trait Field<'a> {
    // TODO: use Read and Cursor
    // TODO: debug_assert_eq!(to-from == size of Self)
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Self;
    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize);

    #[allow(unused_variables)]
    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        Ok(())
    }
}

impl<'a> Field<'a> for bool {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> bool {
        buffer[from] == 1
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, _: usize) {
        buffer[from] = if *self {1} else {0}
    }

    fn check(buffer: &'a [u8], from: usize, _: usize)
        -> Result<(), Error> {
        if buffer[from] != 0 && buffer[from] != 1 {
            Err(Error::IncorrectBoolean {
                position: from as u32,
                value: buffer[from]
            })
        } else {
            Ok(())
        }
    }
}

impl<'a> Field<'a> for u32 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u32 {
        LittleEndian::read_u32(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u32(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for u64 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u64 {
        LittleEndian::read_u64(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u64(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for &'a Hash {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a Hash {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for &'a PublicKey {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a PublicKey {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for Timespec {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Timespec {
        let nsec = LittleEndian::read_u64(&buffer[from..to]);
        Timespec {
            sec:  (nsec / 1_000_000_000) as i64,
            nsec: (nsec % 1_000_000_000) as i32,
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let nsec = (self.sec as u64) * 1_000_000_000 + self.nsec as u64;
        LittleEndian::write_u64(&mut buffer[from..to], nsec)
    }
}

impl<'a> Field<'a> for SocketAddr {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> SocketAddr {
        let ip = Ipv4Addr::new(buffer[from+0], buffer[from+1],
                               buffer[from+2], buffer[from+3]);
        let port = LittleEndian::read_u16(&buffer[from+4..to]);
        SocketAddr::V4(SocketAddrV4::new(ip, port))
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        match *self {
            SocketAddr::V4(addr) => {
                &mut buffer[from..to-2].copy_from_slice(&addr.ip().octets());
            },
            SocketAddr::V6(_) => {
                // FIXME: Supporting Ipv6
                panic!("Ipv6 are currently unsupported")
            },
        }
        LittleEndian::write_u16(&mut buffer[to-2..to], self.port());
    }
}

pub trait SegmentField<'a> {
    const ITEM_SIZE: usize;

    fn from_slice(slice: &'a [u8]) -> Self;
    fn as_slice(&self) -> &'a [u8];
    fn count(&self) -> u32;

    #[allow(unused_variables)]
    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        Ok(())
    }
}

impl<'a, T> Field<'a> for T where T: SegmentField<'a> {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> T {
        let pos = LittleEndian::read_u32(&buffer[from..from+4]);
        let len = LittleEndian::read_u32(&buffer[from+4..to]);
        Self::from_slice(unsafe {
            ::std::slice::from_raw_parts(pos as *const u8, len as usize)
        })
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let pos = buffer.len();
        LittleEndian::write_u32(&mut buffer[from..from+4], pos as u32);
        LittleEndian::write_u32(&mut buffer[from+4..to], self.count());
        buffer.extend_from_slice(self.as_slice());
    }

    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        let pos = LittleEndian::read_u32(&buffer[from..from+4]);
        let count = LittleEndian::read_u32(&buffer[from+4..to]);

        if count == 0 {
            return Ok(())
        }

        let start = pos as usize;

        if start < from + 8 {
            return Err(Error::IncorrectSegmentRefference {
                position: from as u32,
                value: pos
            })
        }

        let end = start + Self::ITEM_SIZE * (count as usize);

        if end > buffer.len() {
            return Err(Error::IncorrectSegmentSize {
                position: (from + 4) as u32,
                value: count
            })
        }

        return Self::check_data(unsafe {
            ::std::slice::from_raw_parts(pos as *const u8, count as usize)
        }, from as u32);
    }
}

impl<'a> SegmentField<'a> for &'a [u8] {
    const ITEM_SIZE: usize = 1;

    fn from_slice(slice: &'a [u8]) -> Self {
        slice
    }

    fn as_slice(&self) -> &'a [u8] {
        self
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a [Hash] {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::slice::from_raw_parts(slice.as_ptr() as *const Hash,
                                         slice.len() / 32)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(self.as_ptr() as *const u8,
                                         self.len() * 32)
        }
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a str {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::str::from_utf8_unchecked(slice)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        self.as_bytes()
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }

    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        if let Err(e) = ::std::str::from_utf8(slice) {
            return Err(Error::Utf8 {
                position: pos,
                error: e,
            });
        }
        Ok(())
    }
}
<commit_msg>Fix segfault<commit_after>use std::mem;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};

use time::{Timespec};
use byteorder::{ByteOrder, LittleEndian};

use super::super::crypto::{Hash, PublicKey};

use super::Error;

pub trait Field<'a> {
    // TODO: use Read and Cursor
    // TODO: debug_assert_eq!(to-from == size of Self)
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Self;
    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize);

    #[allow(unused_variables)]
    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        Ok(())
    }
}

impl<'a> Field<'a> for bool {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> bool {
        buffer[from] == 1
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, _: usize) {
        buffer[from] = if *self {1} else {0}
    }

    fn check(buffer: &'a [u8], from: usize, _: usize)
        -> Result<(), Error> {
        if buffer[from] != 0 && buffer[from] != 1 {
            Err(Error::IncorrectBoolean {
                position: from as u32,
                value: buffer[from]
            })
        } else {
            Ok(())
        }
    }
}

impl<'a> Field<'a> for u32 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u32 {
        LittleEndian::read_u32(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u32(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for u64 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u64 {
        LittleEndian::read_u64(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u64(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for &'a Hash {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a Hash {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for &'a PublicKey {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a PublicKey {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for Timespec {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Timespec {
        let nsec = LittleEndian::read_u64(&buffer[from..to]);
        Timespec {
            sec:  (nsec / 1_000_000_000) as i64,
            nsec: (nsec % 1_000_000_000) as i32,
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let nsec = (self.sec as u64) * 1_000_000_000 + self.nsec as u64;
        LittleEndian::write_u64(&mut buffer[from..to], nsec)
    }
}

impl<'a> Field<'a> for SocketAddr {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> SocketAddr {
        let ip = Ipv4Addr::new(buffer[from+0], buffer[from+1],
                               buffer[from+2], buffer[from+3]);
        let port = LittleEndian::read_u16(&buffer[from+4..to]);
        SocketAddr::V4(SocketAddrV4::new(ip, port))
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        match *self {
            SocketAddr::V4(addr) => {
                &mut buffer[from..to-2].copy_from_slice(&addr.ip().octets());
            },
            SocketAddr::V6(_) => {
                // FIXME: Supporting Ipv6
                panic!("Ipv6 are currently unsupported")
            },
        }
        LittleEndian::write_u16(&mut buffer[to-2..to], self.port());
    }
}

pub trait SegmentField<'a> {
    const ITEM_SIZE: usize;

    fn from_slice(slice: &'a [u8]) -> Self;
    fn as_slice(&self) -> &'a [u8];
    fn count(&self) -> u32;

    #[allow(unused_variables)]
    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        Ok(())
    }
}

impl<'a, T> Field<'a> for T where T: SegmentField<'a> {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> T {
        unsafe {
            let pos = LittleEndian::read_u32(&buffer[from..from+4]);
            let len = LittleEndian::read_u32(&buffer[from+4..to]);
            let ptr = buffer.as_ptr().offset(pos as isize);
            Self::from_slice(unsafe {
                ::std::slice::from_raw_parts(ptr as *const u8, len as usize)
            })
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let pos = buffer.len();
        LittleEndian::write_u32(&mut buffer[from..from+4], pos as u32);
        LittleEndian::write_u32(&mut buffer[from+4..to], self.count());
        buffer.extend_from_slice(self.as_slice());
    }

    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        let pos = LittleEndian::read_u32(&buffer[from..from+4]);
        let count = LittleEndian::read_u32(&buffer[from+4..to]);

        if count == 0 {
            return Ok(())
        }

        let start = pos as usize;

        if start < from + 8 {
            return Err(Error::IncorrectSegmentRefference {
                position: from as u32,
                value: pos
            })
        }

        let end = start + Self::ITEM_SIZE * (count as usize);

        if end > buffer.len() {
            return Err(Error::IncorrectSegmentSize {
                position: (from + 4) as u32,
                value: count
            })
        }

        return Self::check_data(unsafe {
            ::std::slice::from_raw_parts(pos as *const u8, count as usize)
        }, from as u32);
    }
}

impl<'a> SegmentField<'a> for &'a [u8] {
    const ITEM_SIZE: usize = 1;

    fn from_slice(slice: &'a [u8]) -> Self {
        slice
    }

    fn as_slice(&self) -> &'a [u8] {
        self
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a [Hash] {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::slice::from_raw_parts(slice.as_ptr() as *const Hash,
                                         slice.len() / 32)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(self.as_ptr() as *const u8,
                                         self.len() * 32)
        }
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a str {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::str::from_utf8_unchecked(slice)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        self.as_bytes()
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }

    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        if let Err(e) = ::std::str::from_utf8(slice) {
            return Err(Error::Utf8 {
                position: pos,
                error: e,
            });
        }
        Ok(())
    }
}
<|endoftext|>