<commit_before>// Copyright 2017 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.

//! Liveness analysis which computes liveness of MIR local variables at the boundary of basic blocks
//!
//! This analysis considers references as being used only at the point of the
//! borrow. This means that this does not track uses because of references that
//! already exist:
//!
//! ```Rust
//!     fn foo() {
//!         x = 0;
//!         // `x` is live here
//!         GLOBAL = &x: *const u32;
//!         // but not here, even while it can be accessed through `GLOBAL`.
//!         foo();
//!         x = 1;
//!         // `x` is live again here, because it is assigned to `OTHER_GLOBAL`
//!         OTHER_GLOBAL = &x: *const u32;
//!         // ...
//!     }
//! ```
//!
//! This means that users of this analysis still have to check whether
//! pre-existing references can be used to access the value (e.g. at movable
//! generator yield points, all pre-existing references are invalidated, so this
//! doesn't matter).

use rustc::mir::*;
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::indexed_set::IdxSetBuf;
use util::pretty::{write_basic_block, dump_enabled, write_mir_intro};
use rustc::mir::transform::MirSource;
use rustc::ty::item_path;
use std::path::{PathBuf, Path};
use std::fs;
use rustc::ty::TyCtxt;
use std::io::{self, Write};

pub type LocalSet = IdxSetBuf<Local>;

#[derive(Eq, PartialEq, Clone)]
struct DefsUses {
    defs: LocalSet,
    uses: LocalSet,
}

impl DefsUses {
    fn apply(&self, bits: &mut LocalSet) -> bool {
        bits.subtract(&self.defs) | bits.union(&self.uses)
    }

    fn add_def(&mut self, index: Local) {
        // If it was used already in the block, remove that use
        // now that we found a definition.
        //
        // Example:
        //
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.uses.remove(&index);
        self.defs.add(&index);
    }

    fn add_use(&mut self, index: Local) {
        // Inverse of above.
        //
        // Example:
        //
        //     // Defs = {}, Uses = {X}
        //     use(X)
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.defs.remove(&index);
        self.uses.add(&index);
    }
}

impl<'tcx> Visitor<'tcx> for DefsUses {
    fn visit_local(&mut self,
                   &local: &Local,
                   context: LvalueContext<'tcx>,
                   _: Location) {
        match context {
            ///////////////////////////////////////////////////////////////////////////
            // DEFS

            LvalueContext::Store |

            // We let Call defined the result in both the success and
            // unwind cases. This is not really correct, however it
            // does not seem to be observable due to the way that we
            // generate MIR. See the test case
            // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
            // properly, we would apply the def in call only to the
            // input from the success path and not the unwind
            // path. -nmatsakis
            LvalueContext::Call |

            // Storage live and storage dead aren't proper defines, but we can ignore
            // values that come before them.
            LvalueContext::StorageLive |
            LvalueContext::StorageDead => {
                self.add_def(local);
            }

            ///////////////////////////////////////////////////////////////////////////
            // USES

            LvalueContext::Projection(..) |

            // Borrows only consider their local used at the point of the borrow.
            // This won't affect the results since we use this analysis for generators
            // and we only care about the result at suspension points. Borrows cannot
            // cross suspension points so this behavior is unproblematic.
            LvalueContext::Borrow { .. } |

            LvalueContext::Inspect |
            LvalueContext::Consume |
            LvalueContext::Validate |

            // We consider drops to always be uses of locals.
            // Drop eloboration should be run before this analysis otherwise
            // the results might be too pessimistic.
            LvalueContext::Drop => {
                self.add_use(local);
            }
        }
    }
}

fn block<'tcx>(b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses {
    let mut visitor = DefsUses {
        defs: LocalSet::new_empty(locals),
        uses: LocalSet::new_empty(locals),
    };

    let dummy_location = Location { block: BasicBlock::new(0), statement_index: 0 };

    // Visit the various parts of the basic block in reverse. If we go
    // forward, the logic in `add_def` and `add_use` would be wrong.
    visitor.visit_terminator(BasicBlock::new(0), b.terminator(), dummy_location);
    for statement in b.statements.iter().rev() {
        visitor.visit_statement(BasicBlock::new(0), statement, dummy_location);
    }

    visitor
}

// This gives the result of the liveness analysis at the boundary of basic blocks
pub struct LivenessResult {
    pub ins: IndexVec<BasicBlock, LocalSet>,
    pub outs: IndexVec<BasicBlock, LocalSet>,
}

pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
    let locals = mir.local_decls.len();
    let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
        block(b, locals)
    }).collect();

    let mut ins: IndexVec<_, _> = mir.basic_blocks()
        .indices()
        .map(|_| LocalSet::new_empty(locals))
        .collect();
    let mut outs = ins.clone();

    let mut changed = true;
    let mut bits = LocalSet::new_empty(locals);
    while changed {
        changed = false;

        for b in mir.basic_blocks().indices().rev() {
            // outs[b] = ∪ {ins of successors}
            bits.clear();
            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
                bits.union(&ins[successor]);
            }
            outs[b].clone_from(&bits);

            // bits = use ∪ (bits - def)
            def_use[b].apply(&mut bits);

            // update bits on entry and flag if they have changed
            if ins[b] != bits {
                ins[b].clone_from(&bits);
                changed = true;
            }
        }
    }

    LivenessResult {
        ins,
        outs,
    }
}

impl LivenessResult {
    /// Walks backwards through the statements/terminator in the given
    /// basic block `block`.  At each point within `block`, invokes
    /// the callback `op` with the current location and the set of
    /// variables that are live on entry to that location.
    pub fn simulate_block<'tcx, OP>(&self,
                                    mir: &Mir<'tcx>,
                                    block: BasicBlock,
                                    mut callback: OP)
        where OP: FnMut(Location, &LocalSet)
    {
        let data = &mir[block];

        // Get a copy of the bits on exit from the block.
        let mut bits = self.outs[block].clone();

        // Start with the maximal statement index -- i.e., right before
        // the terminator executes.
        let mut statement_index = data.statements.len();

        // Compute liveness right before terminator and invoke callback.
        let terminator_location = Location { block, statement_index };
        let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
        terminator_defs_uses.apply(&mut bits);
        callback(terminator_location, &bits);

        // Compute liveness before each statement (in rev order) and invoke callback.
        for statement in data.statements.iter().rev() {
            statement_index -= 1;
            let statement_location = Location { block, statement_index };
            let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
            statement_defs_uses.apply(&mut bits);
            callback(statement_location, &bits);
        }

        assert_eq!(bits, self.ins[block]);
    }

    fn defs_uses<'tcx, V>(&self,
                          mir: &Mir<'tcx>,
                          location: Location,
                          thing: &V)
                          -> DefsUses
        where V: MirVisitable<'tcx>,
    {
        let locals = mir.local_decls.len();
        let mut visitor = DefsUses {
            defs: LocalSet::new_empty(locals),
            uses: LocalSet::new_empty(locals),
        };

        // Visit the various parts of the basic block in reverse. If we go
        // forward, the logic in `add_def` and `add_use` would be wrong.
        thing.apply(location, &mut visitor);

        visitor
    }
}

trait MirVisitable<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>;
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_statement(location.block,
                                self,
                                location)
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_terminator(location.block,
                                 self.as_ref().unwrap(),
                                 location)
    }
}

pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          pass_name: &str,
                          source: MirSource,
                          mir: &Mir<'tcx>,
                          result: &LivenessResult) {
    if !dump_enabled(tcx, pass_name, source) {
        return;
    }
    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
    });
    dump_matched_mir_node(tcx, pass_name, &node_path,
                          source, mir, result);
}

fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   pass_name: &str,
                                   node_path: &str,
                                   source: MirSource,
                                   mir: &Mir<'tcx>,
                                   result: &LivenessResult) {
    let mut file_path = PathBuf::new();
    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
        let p = Path::new(file_dir);
        file_path.push(p);
    };
    let file_name = format!("rustc.node{}{}-liveness.mir",
                            source.item_id(), pass_name);
    file_path.push(&file_name);
    let _ = fs::File::create(&file_path).and_then(|mut file| {
        writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
        writeln!(file, "// source = {:?}", source)?;
        writeln!(file, "// pass_name = {}", pass_name)?;
        writeln!(file, "")?;
        write_mir_fn(tcx, source, mir, &mut file, result)?;
        Ok(())
    });
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              src: MirSource,
                              mir: &Mir<'tcx>,
                              w: &mut Write,
                              result: &LivenessResult)
                              -> io::Result<()> {
    write_mir_intro(tcx, src, mir, w)?;
    for block in mir.basic_blocks().indices() {
        let print = |w: &mut Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
            let live: Vec<String> = mir.local_decls.indices()
                .filter(|i| result[block].contains(i))
                .map(|i| format!("{:?}", i))
                .collect();
            writeln!(w, "{} {{{}}}", prefix, live.join(", "))
        };
        print(w, "   ", &result.ins)?;
        write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?;
        print(w, "   ", &result.outs)?;
        if block.index() + 1 != mir.basic_blocks().len() {
            writeln!(w, "")?;
        }
    }

    writeln!(w, "}}")?;
    Ok(())
}

<commit_msg>reorder liveness to bring the more significant code up top<commit_after>// Copyright 2017 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.

//! Liveness analysis which computes liveness of MIR local variables at the boundary of basic blocks
//!
//! This analysis considers references as being used only at the point of the
//! borrow. This means that this does not track uses because of references that
//! already exist:
//!
//! ```Rust
//!     fn foo() {
//!         x = 0;
//!         // `x` is live here
//!         GLOBAL = &x: *const u32;
//!         // but not here, even while it can be accessed through `GLOBAL`.
//!         foo();
//!         x = 1;
//!         // `x` is live again here, because it is assigned to `OTHER_GLOBAL`
//!         OTHER_GLOBAL = &x: *const u32;
//!         // ...
//!     }
//! ```
//!
//! This means that users of this analysis still have to check whether
//! pre-existing references can be used to access the value (e.g. at movable
//! generator yield points, all pre-existing references are invalidated, so this
//! doesn't matter).

use rustc::mir::*;
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::indexed_set::IdxSetBuf;
use util::pretty::{write_basic_block, dump_enabled, write_mir_intro};
use rustc::mir::transform::MirSource;
use rustc::ty::item_path;
use std::path::{PathBuf, Path};
use std::fs;
use rustc::ty::TyCtxt;
use std::io::{self, Write};

pub type LocalSet = IdxSetBuf<Local>;

// This gives the result of the liveness analysis at the boundary of basic blocks
pub struct LivenessResult {
    pub ins: IndexVec<BasicBlock, LocalSet>,
    pub outs: IndexVec<BasicBlock, LocalSet>,
}

pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
    let locals = mir.local_decls.len();
    let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
        block(b, locals)
    }).collect();

    let mut ins: IndexVec<_, _> = mir.basic_blocks()
        .indices()
        .map(|_| LocalSet::new_empty(locals))
        .collect();
    let mut outs = ins.clone();

    let mut changed = true;
    let mut bits = LocalSet::new_empty(locals);
    while changed {
        changed = false;

        for b in mir.basic_blocks().indices().rev() {
            // outs[b] = ∪ {ins of successors}
            bits.clear();
            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
                bits.union(&ins[successor]);
            }
            outs[b].clone_from(&bits);

            // bits = use ∪ (bits - def)
            def_use[b].apply(&mut bits);

            // update bits on entry and flag if they have changed
            if ins[b] != bits {
                ins[b].clone_from(&bits);
                changed = true;
            }
        }
    }

    LivenessResult {
        ins,
        outs,
    }
}

impl LivenessResult {
    /// Walks backwards through the statements/terminator in the given
    /// basic block `block`.  At each point within `block`, invokes
    /// the callback `op` with the current location and the set of
    /// variables that are live on entry to that location.
    pub fn simulate_block<'tcx, OP>(&self,
                                    mir: &Mir<'tcx>,
                                    block: BasicBlock,
                                    mut callback: OP)
        where OP: FnMut(Location, &LocalSet)
    {
        let data = &mir[block];

        // Get a copy of the bits on exit from the block.
        let mut bits = self.outs[block].clone();

        // Start with the maximal statement index -- i.e., right before
        // the terminator executes.
        let mut statement_index = data.statements.len();

        // Compute liveness right before terminator and invoke callback.
        let terminator_location = Location { block, statement_index };
        let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
        terminator_defs_uses.apply(&mut bits);
        callback(terminator_location, &bits);

        // Compute liveness before each statement (in rev order) and invoke callback.
        for statement in data.statements.iter().rev() {
            statement_index -= 1;
            let statement_location = Location { block, statement_index };
            let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
            statement_defs_uses.apply(&mut bits);
            callback(statement_location, &bits);
        }

        assert_eq!(bits, self.ins[block]);
    }

    fn defs_uses<'tcx, V>(&self,
                          mir: &Mir<'tcx>,
                          location: Location,
                          thing: &V)
                          -> DefsUses
        where V: MirVisitable<'tcx>,
    {
        let locals = mir.local_decls.len();
        let mut visitor = DefsUses {
            defs: LocalSet::new_empty(locals),
            uses: LocalSet::new_empty(locals),
        };

        // Visit the various parts of the basic block in reverse. If we go
        // forward, the logic in `add_def` and `add_use` would be wrong.
        thing.apply(location, &mut visitor);

        visitor
    }
}

#[derive(Eq, PartialEq, Clone)]
struct DefsUses {
    defs: LocalSet,
    uses: LocalSet,
}

impl DefsUses {
    fn apply(&self, bits: &mut LocalSet) -> bool {
        bits.subtract(&self.defs) | bits.union(&self.uses)
    }

    fn add_def(&mut self, index: Local) {
        // If it was used already in the block, remove that use
        // now that we found a definition.
        //
        // Example:
        //
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.uses.remove(&index);
        self.defs.add(&index);
    }

    fn add_use(&mut self, index: Local) {
        // Inverse of above.
        //
        // Example:
        //
        //     // Defs = {}, Uses = {X}
        //     use(X)
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.defs.remove(&index);
        self.uses.add(&index);
    }
}

impl<'tcx> Visitor<'tcx> for DefsUses {
    fn visit_local(&mut self,
                   &local: &Local,
                   context: LvalueContext<'tcx>,
                   _: Location) {
        match context {
            ///////////////////////////////////////////////////////////////////////////
            // DEFS

            LvalueContext::Store |

            // We let Call defined the result in both the success and
            // unwind cases. This is not really correct, however it
            // does not seem to be observable due to the way that we
            // generate MIR. See the test case
            // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
            // properly, we would apply the def in call only to the
            // input from the success path and not the unwind
            // path. -nmatsakis
            LvalueContext::Call |

            // Storage live and storage dead aren't proper defines, but we can ignore
            // values that come before them.
            LvalueContext::StorageLive |
            LvalueContext::StorageDead => {
                self.add_def(local);
            }

            ///////////////////////////////////////////////////////////////////////////
            // USES

            LvalueContext::Projection(..) |

            // Borrows only consider their local used at the point of the borrow.
            // This won't affect the results since we use this analysis for generators
            // and we only care about the result at suspension points. Borrows cannot
            // cross suspension points so this behavior is unproblematic.
            LvalueContext::Borrow { .. } |

            LvalueContext::Inspect |
            LvalueContext::Consume |
            LvalueContext::Validate |

            // We consider drops to always be uses of locals.
            // Drop eloboration should be run before this analysis otherwise
            // the results might be too pessimistic.
            LvalueContext::Drop => {
                self.add_use(local);
            }
        }
    }
}

fn block<'tcx>(b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses {
    let mut visitor = DefsUses {
        defs: LocalSet::new_empty(locals),
        uses: LocalSet::new_empty(locals),
    };

    let dummy_location = Location { block: BasicBlock::new(0), statement_index: 0 };

    // Visit the various parts of the basic block in reverse. If we go
    // forward, the logic in `add_def` and `add_use` would be wrong.
    visitor.visit_terminator(BasicBlock::new(0), b.terminator(), dummy_location);
    for statement in b.statements.iter().rev() {
        visitor.visit_statement(BasicBlock::new(0), statement, dummy_location);
    }

    visitor
}

trait MirVisitable<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>;
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_statement(location.block,
                                self,
                                location)
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_terminator(location.block,
                                 self.as_ref().unwrap(),
                                 location)
    }
}

pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          pass_name: &str,
                          source: MirSource,
                          mir: &Mir<'tcx>,
                          result: &LivenessResult) {
    if !dump_enabled(tcx, pass_name, source) {
        return;
    }
    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
    });
    dump_matched_mir_node(tcx, pass_name, &node_path,
                          source, mir, result);
}

fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   pass_name: &str,
                                   node_path: &str,
                                   source: MirSource,
                                   mir: &Mir<'tcx>,
                                   result: &LivenessResult) {
    let mut file_path = PathBuf::new();
    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
        let p = Path::new(file_dir);
        file_path.push(p);
    };
    let file_name = format!("rustc.node{}{}-liveness.mir",
                            source.item_id(), pass_name);
    file_path.push(&file_name);
    let _ = fs::File::create(&file_path).and_then(|mut file| {
        writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
        writeln!(file, "// source = {:?}", source)?;
        writeln!(file, "// pass_name = {}", pass_name)?;
        writeln!(file, "")?;
        write_mir_fn(tcx, source, mir, &mut file, result)?;
        Ok(())
    });
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              src: MirSource,
                              mir: &Mir<'tcx>,
                              w: &mut Write,
                              result: &LivenessResult)
                              -> io::Result<()> {
    write_mir_intro(tcx, src, mir, w)?;
    for block in mir.basic_blocks().indices() {
        let print = |w: &mut Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
            let live: Vec<String> = mir.local_decls.indices()
                .filter(|i| result[block].contains(i))
                .map(|i| format!("{:?}", i))
                .collect();
            writeln!(w, "{} {{{}}}", prefix, live.join(", "))
        };
        print(w, "   ", &result.ins)?;
        write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?;
        print(w, "   ", &result.outs)?;
        if block.index() + 1 != mir.basic_blocks().len() {
            writeln!(w, "")?;
        }
    }

    writeln!(w, "}}")?;
    Ok(())
}

<|endoftext|>


<commit_before>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]
#![allow(unstable)]

extern crate "union-find" as union_find;
extern crate term;

use std::io::stdio;
use board::Board;

mod board;
mod geom;
mod pprint;
mod solver;

fn main() {
    let raw_input = stdio::stdin().read_to_end().unwrap();
    let input = String::from_utf8(raw_input).unwrap();
    let board = input.parse::<Board>().unwrap();
    let board = solver::solve(&board).unwrap();
    let _ = pprint::print(&board);
}
<commit_msg>main: `Board::to_string` when stdout is not a tty<commit_after>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]
#![allow(unstable)]

extern crate "union-find" as union_find;
extern crate term;

use std::io::stdio;
use board::Board;

mod board;
mod geom;
mod pprint;
mod solver;

fn main() {
    let raw_input = stdio::stdin().read_to_end().unwrap();
    let input = String::from_utf8(raw_input).unwrap();
    let board = input.parse::<Board>().unwrap();
    let board = solver::solve(&board).unwrap();

    if stdio::stdout_raw().isatty() {
        let _ = pprint::print(&board);
    } else {
        print!("{}", board.to_string());
    }
}
<|endoftext|>


<commit_before>macro_rules! def_store_number {
    ($m: ident, $t: ty) => {
        pub mod $m {
            use raft::state_machine::StateMachineCtl;
            use bifrost_hasher::hash_str;
            pub struct Number {
                pub num: $t,
                id: u64
            }
            raft_state_machine! {
                def cmd set(v: $t);
                def qry get() -> $t;

                def cmd get_and_add(n: $t) -> $t;
                def cmd add_and_get(n: $t) -> $t;

                def cmd get_and_minus(n: $t) -> $t;
                def cmd minus_and_get(n: $t) -> $t;

                def cmd get_and_incr(n: $t) -> $t;
                def cmd incr_and_get(n: $t) -> $t;

                def cmd get_and_decr(n: $t) -> $t;
                def cmd decr_and_get(n: $t) -> $t;
            }
            impl StateMachineCmds for Number {
                fn set(&mut self, n: $t) -> Result<(),()> {
                    self.num = n;
                    Ok(())
                }
                fn get(&self) -> Result<$t, ()> {
                    Ok(self.num)
                }
                fn get_and_add(&mut self, n: $t) -> Result<$t, ()> {
                    let on = self.num;
                    self.num += n;
                    Ok(on)
                }
                fn add_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.num += n;
                    Ok(self.num)
                }
                fn get_and_minus(&mut self, n: $t) -> Result<$t, ()> {
                    let on = self.num;
                    self.num -= n;
                    Ok(on)
                }
                fn minus_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.num -= n;
                    Ok(self.num)
                }
                fn get_and_incr(&mut self, n: $t) -> Result<$t, ()> {
                    self.get_and_add(1)
                }
                fn incr_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.add_and_get(1)
                }
                fn get_and_decr(&mut self, n: $t) -> Result<$t, ()> {
                    self.get_and_minus(1)
                }
                fn decr_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.minus_and_get(1)
                }
            }
            impl StateMachineCtl for Number {
                sm_complete!();
                fn snapshot(&self) -> Option<Vec<u8>> {
                    Some(serialize!(&self.num))
                }
                fn recover(&mut self, data: Vec<u8>) {
                    self.num = deserialize!(&data);
                }
                fn id(&self) -> u64 {self.id}
            }
            impl Number {
                pub fn new(id: u64, val: $t) -> Number {
                    Number {
                        num: val,
                        id: id,
                    }
                }
                pub fn new_by_name(name: String, num: $t) -> Number {
                    Number::new(hash_str(name), num)
                }
            }
        }
    };
}

def_store_number!(I8, i8);
def_store_number!(I16, i16);
def_store_number!(I32, i32);
def_store_number!(I64, i64);
def_store_number!(U8, u8);
def_store_number!(U16, u16);
def_store_number!(U32, u32);
def_store_number!(U64, u64);<commit_msg>multiply and divide<commit_after>macro_rules! def_store_number {
    ($m: ident, $t: ty) => {
        pub mod $m {
            use raft::state_machine::StateMachineCtl;
            use bifrost_hasher::hash_str;
            pub struct Number {
                pub num: $t,
                id: u64
            }
            raft_state_machine! {
                def cmd set(v: $t);
                def qry get() -> $t;

                def cmd get_and_add(n: $t) -> $t;
                def cmd add_and_get(n: $t) -> $t;

                def cmd get_and_minus(n: $t) -> $t;
                def cmd minus_and_get(n: $t) -> $t;

                def cmd get_and_incr(n: $t) -> $t;
                def cmd incr_and_get(n: $t) -> $t;

                def cmd get_and_decr(n: $t) -> $t;
                def cmd decr_and_get(n: $t) -> $t;

                def cmd get_and_multiply(n: $t) -> $t;
                def cmd multiply_and_get(n: $t) -> $t;

                def cmd get_and_divide(n: $t) -> $t;
                def cmd divide_and_get(n: $t) -> $t;
            }
            impl StateMachineCmds for Number {
                fn set(&mut self, n: $t) -> Result<(),()> {
                    self.num = n;
                    Ok(())
                }
                fn get(&self) -> Result<$t, ()> {
                    Ok(self.num)
                }
                fn get_and_add(&mut self, n: $t) -> Result<$t, ()> {
                    let on = self.num;
                    self.num += n;
                    Ok(on)
                }
                fn add_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.num += n;
                    Ok(self.num)
                }
                fn get_and_minus(&mut self, n: $t) -> Result<$t, ()> {
                    let on = self.num;
                    self.num -= n;
                    Ok(on)
                }
                fn minus_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.num -= n;
                    Ok(self.num)
                }
                fn get_and_incr(&mut self, n: $t) -> Result<$t, ()> {
                    self.get_and_add(1)
                }
                fn incr_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.add_and_get(1)
                }
                fn get_and_decr(&mut self, n: $t) -> Result<$t, ()> {
                    self.get_and_minus(1)
                }
                fn decr_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.minus_and_get(1)
                }
                fn get_and_multiply(&mut self, n: $t) -> Result<$t, ()> {
                    let on = self.num;
                    self.num *= n;
                    Ok(on)
                }
                fn multiply_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.num *= n;
                    Ok(self.num)
                }
                fn get_and_divide(&mut self, n: $t) -> Result<$t, ()> {
                    let on = self.num;
                    self.num /= n;
                    Ok(on)
                }
                fn divide_and_get(&mut self, n: $t) -> Result<$t, ()> {
                    self.num /= n;
                    Ok(self.num)
                }
            }
            impl StateMachineCtl for Number {
                sm_complete!();
                fn snapshot(&self) -> Option<Vec<u8>> {
                    Some(serialize!(&self.num))
                }
                fn recover(&mut self, data: Vec<u8>) {
                    self.num = deserialize!(&data);
                }
                fn id(&self) -> u64 {self.id}
            }
            impl Number {
                pub fn new(id: u64, val: $t) -> Number {
                    Number {
                        num: val,
                        id: id,
                    }
                }
                pub fn new_by_name(name: String, num: $t) -> Number {
                    Number::new(hash_str(name), num)
                }
            }
        }
    };
}

def_store_number!(I8, i8);
def_store_number!(I16, i16);
def_store_number!(I32, i32);
def_store_number!(I64, i64);
def_store_number!(U8, u8);
def_store_number!(U16, u16);
def_store_number!(U32, u32);
def_store_number!(U64, u64);<|endoftext|>


<commit_before>fn main( )
{
  let a = 123u;

  match a
  {   0       => println!( "ししとうがらし" )
  , 123 | 456 => println!( "ぴーまん" )
  , 500..2500 => println!( "ぱぷりか" )
  , _         => println!( "はらぺーにょ" )
  }

  println!
    ( "{}"
    , match ( 123u, 456u )
      { ( 123,   t ) if t < 123 => "三鷹"
      , ( 456,   _ )            => "能鷹"
      , (   s, 123 ) if s > 456 => "黄辛"
      , (   _,   _ )            => "万願寺"
      }
    )
}
<commit_msg>追記した: マッチ部分の変数への取得  とタプルの要素の得方について<commit_after>fn main( )
{
  let a = 123u;

  match a
  {   0       => println!( "ししとうがらし" )
  , 123 | 456 => println!( "ぴーまん" )
  , 500..2500 => println!( "ぱぷりか" )
  , _         => println!( "はらぺーにょ" )
  }

  println!
    ( "{}"
    , match ( 123u, 456u )
      { ( 123,   t ) if t < 123 => "三鷹"
      , ( 456,   _ )            => "能鷹"
      , (   s, 123 ) if s > 456 => "黄辛"
      , (   _,   _ )            => "万願寺"
      }
    )

  let ( x, _, z ) =
    match a
    { s @ 0..100 => ( s + 1,  1, ( s + 1 ) * ( s + 1 ) )
    , s @ _      => ( s - 1, -1, ( s - 1 ) * ( s - 1 ) )
    };

  println!( "x: {} y: {}", x, z );
}
<|endoftext|>


<commit_before>// Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

#![deny(warnings)]
// Enable all clippy lints except for many of the pedantic ones. It's a shame this needs to be copied and pasted across crates, but there doesn't appear to be a way to include inner attributes from a common source.
#![deny(
  clippy::all,
  clippy::default_trait_access,
  clippy::expl_impl_clone_on_copy,
  clippy::if_not_else,
  clippy::needless_continue,
  clippy::unseparated_literal_suffix,
  clippy::used_underscore_binding
)]
// It is often more clear to show that nothing is being moved.
#![allow(clippy::match_ref_pats)]
// Subjective style.
#![allow(
  clippy::len_without_is_empty,
  clippy::redundant_field_names,
  clippy::too_many_arguments
)]
// Default isn't as big a deal as people seem to think it is.
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
// Arc<Mutex> can be more clear than needing to grok Orderings:
#![allow(clippy::mutex_atomic)]

use termion;

use std::collections::{BTreeMap, VecDeque};
use std::io::Read;
use std::io::Write;
use std::io::{stdout, Result, Stdout};

use termion::raw::IntoRawMode;
use termion::raw::RawTerminal;
use termion::screen::AlternateScreen;
use termion::{async_stdin, AsyncReader};
use termion::{clear, color, cursor};
use unicode_segmentation::UnicodeSegmentation;

enum Console {
  Uninitialized,
  Terminal(RawTerminal<AlternateScreen<Stdout>>),
  Pipe(Stdout),
}

#[derive(Clone)]
struct PrintableMsg {
  msg: String,
  output: PrintableMsgOutput,
}

#[derive(Clone)]
enum PrintableMsgOutput {
  Stdout,
  Stderr,
}

pub enum KeyboardCommand {
  None,
  CtrlC,
}

pub struct EngineDisplay {
  sigil: char,
  divider: String,
  padding: String,
  terminal: Console,
  action_map: BTreeMap<String, String>,
  logs: VecDeque<String>,
  printable_msgs: VecDeque<PrintableMsg>,
  cursor_start: (u16, u16),
  terminal_size: (u16, u16),
  async_stdin: AsyncReader,
}

// TODO: Prescribe a threading/polling strategy for callers - or implement a built-in one.
// TODO: Better error handling for .flush() and .write() failure modes.
// TODO: Permit scrollback in the terminal - both at exit and during the live run.
impl EngineDisplay {
  /// Create a new EngineDisplay
  pub fn new(indent_level: u16) -> EngineDisplay {
    EngineDisplay {
      sigil: '⚡',
      divider: "▵".to_string(),
      padding: " ".repeat(indent_level.into()),
      terminal: Console::Uninitialized,
      action_map: BTreeMap::new(),
      // This is arbitrary based on a guesstimated peak terminal row size for modern displays.
      // The reason this can't be capped to e.g. the starting size is because of resizing - we
      // want to be able to fill the entire screen if resized much larger than when we started.
      logs: VecDeque::with_capacity(500),
      printable_msgs: VecDeque::with_capacity(500),
      // N.B. This will cause the screen to clear - but with some improved position
      // tracking logic we could avoid screen clearing in favor of using the value
      // of `EngineDisplay::get_cursor_pos()` as initialization here. From there, the
      // trick would be to push the on-screen text screen up (ideally, prior to entering
      // raw mode) via newline printing - and then ensuring the rendered text never
      // overflows past the screen row bounds. Before we could safely do that tho, we
      // probably want to plumb a signal handler for SIGWINCH so that ^L works to redraw
      // the screen in the case of any display issues. Otherwise, simply clearing the screen
      // as we've done here is the safest way to avoid terminal oddness.
      cursor_start: (1, 1),
      terminal_size: EngineDisplay::get_size(),
      async_stdin: async_stdin(),
    }
  }

  pub fn initialize(&mut self, display_worker_count: usize) {
    let worker_ids: Vec<String> = (0..display_worker_count)
      .map(|s| format!("{}", s))
      .collect();
    for worker_id in worker_ids {
      self.add_worker(worker_id);
    }
  }

  pub fn stdout_is_tty() -> bool {
    termion::is_tty(&stdout())
  }

  pub fn write_stdout(&mut self, msg: &str) {
    self.printable_msgs.push_back(PrintableMsg {
      msg: msg.to_string(),
      output: PrintableMsgOutput::Stdout,
    });
  }

  pub fn write_stderr(&mut self, msg: &str) {
    self.printable_msgs.push_back(PrintableMsg {
      msg: msg.to_string(),
      output: PrintableMsgOutput::Stderr,
    });
  }

  fn start_raw_mode(&mut self) -> Result<()> {
    match self.terminal {
      Console::Terminal(ref mut t) => t.activate_raw_mode(),
      _ => Ok(()),
    }
  }

  // Gets the current terminal's width and height, if applicable.
  fn get_size() -> (u16, u16) {
    termion::terminal_size().unwrap_or((0, 0))
  }

  // Sets the terminal size per-render for signal-free resize detection.
  fn set_size(&mut self) {
    self.terminal_size = EngineDisplay::get_size();
  }

  // Sets the terminal size for signal-free resize detection.
  fn get_max_log_rows(&self) -> usize {
    // TODO: If the terminal size is smaller than the action map, we should fall back
    // to non-tty mode output to avoid.
    self.terminal_size.1 as usize - self.action_map.len() - 1
  }

  // Prep the screen for painting by clearing it from the cursor start position.
  fn clear(&mut self) {
    let cursor_start = self.cursor_start;
    self
      .write(&format!(
        "{goto_origin}{clear}",
        goto_origin = cursor::Goto(cursor_start.0, cursor_start.1),
        clear = clear::AfterCursor,
      ))
      .expect("could not write to terminal");
  }

  // Flush terminal output.
  fn flush(&mut self) -> Result<()> {
    match self.terminal {
      Console::Terminal(ref mut t) => t.flush(),
      Console::Pipe(ref mut p) => p.flush(),
      Console::Uninitialized => Ok(()),
    }
  }

  // Writes output to the terminal.
  fn write(&mut self, msg: &str) -> Result<usize> {
    let res = match self.terminal {
      Console::Terminal(ref mut t) => t.write(msg.as_bytes()),
      Console::Pipe(ref mut p) => p.write(msg.as_bytes()),
      Console::Uninitialized => Ok(0),
    };
    self.flush()?;
    res
  }

  // Renders a divider between the logs and action output.
  fn render_divider(&mut self, offset: u16) {
    let cursor_start = self.cursor_start;
    let padding = self.padding.clone();
    let divider = self.divider.clone();

    self
      .write(&format!(
        "{pos}{clear_line}{padding}{blue}{divider}{reset}",
        pos = cursor::Goto(1, cursor_start.1 + offset),
        clear_line = clear::CurrentLine,
        padding = padding,
        blue = color::Fg(color::Blue),
        divider = divider,
        reset = color::Fg(color::Reset)
      ))
      .expect("could not write to terminal");
  }

  // Renders one frame of the log portion of the screen.
  fn render_logs(&mut self, max_entries: usize) -> usize {
    let cursor_start = self.cursor_start;
    let printable_logs: Vec<String> = self.logs.iter().take(max_entries).cloned().collect();

    let mut counter: usize = 0;
    for (n, log_entry) in printable_logs.iter().rev().enumerate() {
      counter += 1;
      let line_shortened_log_entry: String = format!(
        "{padding}{log_entry}",
        padding = self.padding,
        log_entry = log_entry
      )
      .graphemes(true)
      .take(self.terminal_size.0 as usize)
      .collect();

      self
        .write(&format!(
          "{pos}{clear_line}{entry}",
          pos = cursor::Goto(1, cursor_start.1 + n as u16),
          clear_line = clear::CurrentLine,
          entry = line_shortened_log_entry
        ))
        .expect("could not write to terminal");
    }

    if counter > 0 {
      self.render_divider(counter as u16);
      counter += 1;
    }
    counter
  }

  // Renders one frame of the action portion of the screen.
  fn render_actions(&mut self, start_row: usize) {
    let cursor_start = self.cursor_start;
    let worker_states = self.action_map.clone();

    // For every active worker in the action map, jump to the exact cursor
    // representing the swimlane for this worker and lay down a text label.
    for (n, (_worker_id, action)) in worker_states.iter().enumerate() {
      let line_shortened_output: String = format!(
        "{padding}{blue}{sigil}{reset}{action}",
        padding = self.padding,
        blue = color::Fg(color::LightBlue),
        sigil = self.sigil,
        reset = color::Fg(color::Reset),
        action = action
      )
      .graphemes(true)
      // Account for control characters.
      .take(self.terminal_size.0 as usize + 14)
      .collect();

      self
        .write(&format!(
          "{pos}{entry}",
          pos = cursor::Goto(1, cursor_start.1 + start_row as u16 + n as u16),
          entry = line_shortened_output
        ))
        .expect("could not write to terminal");
    }
  }

  // Paints one screen of rendering.
  pub fn render(&mut self) -> std::result::Result<KeyboardCommand, String> {
    self.set_size();
    self.clear();
    let max_log_rows = self.get_max_log_rows();
    let rendered_count = self.render_logs(max_log_rows);
    self.render_actions(rendered_count);
    if let Err(err) = self.flush() {
      return Err(format!("Could not flush terminal: {}", err));
    }
    self.handle_stdin()
  }

  fn handle_stdin(&mut self) -> std::result::Result<KeyboardCommand, String> {
    use termion::event::{parse_event, Event, Key};
    //This buffer must have non-zero size because termion's `read` implementation for
    //AsyncReader will return early without doing anything if it is of length 0.
    //(See https://docs.rs/termion/1.5.4/src/termion/async.rs.html#69 )
    let mut buf: [u8; 32] = [0; 32];

    match self.async_stdin.read(&mut buf) {
      Ok(0) => Ok(KeyboardCommand::None),
      Ok(_) => {
        let initial_byte: u8 = buf[0];
        let mut iter = buf[1..].iter().map(|byte| Ok(*byte));
        // TODO: calling `parse_event` in this way means that we will potentially miss keyboard
        // events - a Ctrl-C event has to be the very first event in each `render` frame, or it
        // won't be handled. In practice, the refresh interval is 100 ms, which is fast enough
        // on human timescales that hitting Ctrl-C while the program is running will wind up
        // at the beginning of some frame.  Note that internally termion uses this function
        // in the context of the `next()` function of an Iterator:
        // https://github.com/redox-os/termion/blob/master/src/input.rs .
        let event_or_err = parse_event(initial_byte, &mut iter);
        match event_or_err {
          Ok(Event::Key(Key::Ctrl('c'))) => Ok(KeyboardCommand::CtrlC),
          Err(err) => Err(format!("EngineDisplay keyboard event error: {}", err)),
          _ => Ok(KeyboardCommand::None),
        }
      }
      Err(err) => Err(format!("EngineDisplay stdin error: {}", err)),
    }
  }

  // Starts the EngineDisplay at the current cursor position.
  pub fn start(&mut self) {
    let write_handle = termion::screen::AlternateScreen::from(stdout());
    self.terminal = match write_handle.into_raw_mode() {
      Ok(t) => Console::Terminal(t),
      Err(_) => Console::Pipe(stdout()),
    };

    self.start_raw_mode().unwrap();
    let cursor_start = self.cursor_start;
    self
      .write(&format!(
        "{hide_cursor}{cursor_init}{clear_after_cursor}",
        hide_cursor = termion::cursor::Hide,
        cursor_init = cursor::Goto(cursor_start.0, cursor_start.1),
        clear_after_cursor = clear::AfterCursor
      ))
      .expect("could not write to terminal");
  }

  // Adds a worker/thread to the visual representation.
  pub fn add_worker(&mut self, worker_name: String) {
    let action_msg = format!("booting {}", worker_name);
    self.update(worker_name, action_msg);
  }

  // Updates the status of a worker/thread.
  pub fn update(&mut self, worker_name: String, action: String) {
    self.action_map.insert(worker_name, action);
  }

  // Removes a worker/thread from the visual representation.
  pub fn remove_worker(&mut self, worker_id: &str) {
    self.action_map.remove(worker_id);
  }

  // Adds a log entry for display.
  pub fn log(&mut self, log_entry: String) {
    self.logs.push_front(log_entry)
  }

  pub fn worker_count(&self) -> usize {
    self.action_map.len()
  }

  pub fn suspend(&mut self) {
    {
      self.terminal = Console::Uninitialized;
    }
    println!("{}", termion::cursor::Show);
  }

  pub fn unsuspend(&mut self) {
    let write_handle = termion::screen::AlternateScreen::from(stdout());
    self.terminal = match write_handle.into_raw_mode() {
      Ok(t) => Console::Terminal(t),
      Err(_) => Console::Pipe(stdout()),
    };
  }

  // Initiates one last screen render, then terminates the EngineDisplay and returns the cursor
  // to a static position, then prints all buffered stdout/stderr output.
  pub fn finish(&mut self) {
    //We don't care about handling the output from render() here, since we're about to shut down
    //the EngineDisplay anyway.
    let _ = self.render();
    {
      self.terminal = Console::Uninitialized; //This forces the AlternateScreen to drop, restoring the original terminal state.
    }

    println!("{}", termion::cursor::Show);
    for log in self.logs.iter() {
      println!("{}", log);
    }
    for PrintableMsg { msg, output } in self.printable_msgs.iter() {
      match output {
        PrintableMsgOutput::Stdout => print!("{}", msg),
        PrintableMsgOutput::Stderr => eprint!("{}", msg),
      }
    }
  }
}
<commit_msg>Disable and re-enable async stdin when UI is disabled (#9222)<commit_after>// Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

#![deny(warnings)]
// Enable all clippy lints except for many of the pedantic ones. It's a shame this needs to be copied and pasted across crates, but there doesn't appear to be a way to include inner attributes from a common source.
#![deny(
  clippy::all,
  clippy::default_trait_access,
  clippy::expl_impl_clone_on_copy,
  clippy::if_not_else,
  clippy::needless_continue,
  clippy::unseparated_literal_suffix,
  clippy::used_underscore_binding
)]
// It is often more clear to show that nothing is being moved.
#![allow(clippy::match_ref_pats)]
// Subjective style.
#![allow(
  clippy::len_without_is_empty,
  clippy::redundant_field_names,
  clippy::too_many_arguments
)]
// Default isn't as big a deal as people seem to think it is.
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
// Arc<Mutex> can be more clear than needing to grok Orderings:
#![allow(clippy::mutex_atomic)]

use termion;

use std::collections::{BTreeMap, VecDeque};
use std::io::Read;
use std::io::Write;
use std::io::{stdout, Result, Stdout};

use termion::raw::IntoRawMode;
use termion::raw::RawTerminal;
use termion::screen::AlternateScreen;
use termion::{async_stdin, AsyncReader};
use termion::{clear, color, cursor};
use unicode_segmentation::UnicodeSegmentation;

enum Console {
  Uninitialized,
  Terminal(RawTerminal<AlternateScreen<Stdout>>),
  Pipe(Stdout),
}

#[derive(Clone)]
struct PrintableMsg {
  msg: String,
  output: PrintableMsgOutput,
}

#[derive(Clone)]
enum PrintableMsgOutput {
  Stdout,
  Stderr,
}

pub enum KeyboardCommand {
  None,
  CtrlC,
}

pub struct EngineDisplay {
  sigil: char,
  divider: String,
  padding: String,
  terminal: Console,
  action_map: BTreeMap<String, String>,
  logs: VecDeque<String>,
  printable_msgs: VecDeque<PrintableMsg>,
  cursor_start: (u16, u16),
  terminal_size: (u16, u16),
  async_stdin: Option<AsyncReader>,
  suspended: bool,
}

// TODO: Prescribe a threading/polling strategy for callers - or implement a built-in one.
// TODO: Better error handling for .flush() and .write() failure modes.
// TODO: Permit scrollback in the terminal - both at exit and during the live run.
impl EngineDisplay {
  /// Create a new EngineDisplay
  pub fn new(indent_level: u16) -> EngineDisplay {
    EngineDisplay {
      sigil: '⚡',
      divider: "▵".to_string(),
      padding: " ".repeat(indent_level.into()),
      terminal: Console::Uninitialized,
      action_map: BTreeMap::new(),
      // This is arbitrary based on a guesstimated peak terminal row size for modern displays.
      // The reason this can't be capped to e.g. the starting size is because of resizing - we
      // want to be able to fill the entire screen if resized much larger than when we started.
      logs: VecDeque::with_capacity(500),
      printable_msgs: VecDeque::with_capacity(500),
      // N.B. This will cause the screen to clear - but with some improved position
      // tracking logic we could avoid screen clearing in favor of using the value
      // of `EngineDisplay::get_cursor_pos()` as initialization here. From there, the
      // trick would be to push the on-screen text screen up (ideally, prior to entering
      // raw mode) via newline printing - and then ensuring the rendered text never
      // overflows past the screen row bounds. Before we could safely do that tho, we
      // probably want to plumb a signal handler for SIGWINCH so that ^L works to redraw
      // the screen in the case of any display issues. Otherwise, simply clearing the screen
      // as we've done here is the safest way to avoid terminal oddness.
      cursor_start: (1, 1),
      terminal_size: EngineDisplay::get_size(),
      async_stdin: Some(async_stdin()),
      suspended: false,
    }
  }

  pub fn initialize(&mut self, display_worker_count: usize) {
    let worker_ids: Vec<String> = (0..display_worker_count)
      .map(|s| format!("{}", s))
      .collect();
    for worker_id in worker_ids {
      self.add_worker(worker_id);
    }
  }

  pub fn stdout_is_tty() -> bool {
    termion::is_tty(&stdout())
  }

  pub fn write_stdout(&mut self, msg: &str) {
    self.printable_msgs.push_back(PrintableMsg {
      msg: msg.to_string(),
      output: PrintableMsgOutput::Stdout,
    });
  }

  pub fn write_stderr(&mut self, msg: &str) {
    self.printable_msgs.push_back(PrintableMsg {
      msg: msg.to_string(),
      output: PrintableMsgOutput::Stderr,
    });
  }

  fn start_raw_mode(&mut self) -> Result<()> {
    match self.terminal {
      Console::Terminal(ref mut t) => t.activate_raw_mode(),
      _ => Ok(()),
    }
  }

  // Gets the current terminal's width and height, if applicable.
  fn get_size() -> (u16, u16) {
    termion::terminal_size().unwrap_or((0, 0))
  }

  // Sets the terminal size per-render for signal-free resize detection.
  fn set_size(&mut self) {
    self.terminal_size = EngineDisplay::get_size();
  }

  // Sets the terminal size for signal-free resize detection.
  fn get_max_log_rows(&self) -> usize {
    // TODO: If the terminal size is smaller than the action map, we should fall back
    // to non-tty mode output to avoid.
    self.terminal_size.1 as usize - self.action_map.len() - 1
  }

  // Prep the screen for painting by clearing it from the cursor start position.
  fn clear(&mut self) {
    let cursor_start = self.cursor_start;
    self
      .write(&format!(
        "{goto_origin}{clear}",
        goto_origin = cursor::Goto(cursor_start.0, cursor_start.1),
        clear = clear::AfterCursor,
      ))
      .expect("could not write to terminal");
  }

  // Flush terminal output.
  fn flush(&mut self) -> Result<()> {
    match self.terminal {
      Console::Terminal(ref mut t) => t.flush(),
      Console::Pipe(ref mut p) => p.flush(),
      Console::Uninitialized => Ok(()),
    }
  }

  // Writes output to the terminal.
  fn write(&mut self, msg: &str) -> Result<usize> {
    let res = match self.terminal {
      Console::Terminal(ref mut t) => t.write(msg.as_bytes()),
      Console::Pipe(ref mut p) => p.write(msg.as_bytes()),
      Console::Uninitialized => Ok(0),
    };
    self.flush()?;
    res
  }

  // Renders a divider between the logs and action output.
  fn render_divider(&mut self, offset: u16) {
    let cursor_start = self.cursor_start;
    let padding = self.padding.clone();
    let divider = self.divider.clone();

    self
      .write(&format!(
        "{pos}{clear_line}{padding}{blue}{divider}{reset}",
        pos = cursor::Goto(1, cursor_start.1 + offset),
        clear_line = clear::CurrentLine,
        padding = padding,
        blue = color::Fg(color::Blue),
        divider = divider,
        reset = color::Fg(color::Reset)
      ))
      .expect("could not write to terminal");
  }

  // Renders one frame of the log portion of the screen.
  fn render_logs(&mut self, max_entries: usize) -> usize {
    let cursor_start = self.cursor_start;
    let printable_logs: Vec<String> = self.logs.iter().take(max_entries).cloned().collect();

    let mut counter: usize = 0;
    for (n, log_entry) in printable_logs.iter().rev().enumerate() {
      counter += 1;
      let line_shortened_log_entry: String = format!(
        "{padding}{log_entry}",
        padding = self.padding,
        log_entry = log_entry
      )
      .graphemes(true)
      .take(self.terminal_size.0 as usize)
      .collect();

      self
        .write(&format!(
          "{pos}{clear_line}{entry}",
          pos = cursor::Goto(1, cursor_start.1 + n as u16),
          clear_line = clear::CurrentLine,
          entry = line_shortened_log_entry
        ))
        .expect("could not write to terminal");
    }

    if counter > 0 {
      self.render_divider(counter as u16);
      counter += 1;
    }
    counter
  }

  // Renders one frame of the action portion of the screen.
  fn render_actions(&mut self, start_row: usize) {
    let cursor_start = self.cursor_start;
    let worker_states = self.action_map.clone();

    // For every active worker in the action map, jump to the exact cursor
    // representing the swimlane for this worker and lay down a text label.
    for (n, (_worker_id, action)) in worker_states.iter().enumerate() {
      let line_shortened_output: String = format!(
        "{padding}{blue}{sigil}{reset}{action}",
        padding = self.padding,
        blue = color::Fg(color::LightBlue),
        sigil = self.sigil,
        reset = color::Fg(color::Reset),
        action = action
      )
      .graphemes(true)
      // Account for control characters.
      .take(self.terminal_size.0 as usize + 14)
      .collect();

      self
        .write(&format!(
          "{pos}{entry}",
          pos = cursor::Goto(1, cursor_start.1 + start_row as u16 + n as u16),
          entry = line_shortened_output
        ))
        .expect("could not write to terminal");
    }
  }

  // Paints one screen of rendering.
  pub fn render(&mut self) -> std::result::Result<KeyboardCommand, String> {
    if self.suspended {
      return Ok(KeyboardCommand::None);
    }
    self.set_size();
    self.clear();
    let max_log_rows = self.get_max_log_rows();
    let rendered_count = self.render_logs(max_log_rows);
    self.render_actions(rendered_count);
    if let Err(err) = self.flush() {
      return Err(format!("Could not flush terminal: {}", err));
    }
    self.handle_stdin()
  }

  fn handle_stdin(&mut self) -> std::result::Result<KeyboardCommand, String> {
    use termion::event::{parse_event, Event, Key};
    //This buffer must have non-zero size because termion's `read` implementation for
    //AsyncReader will return early without doing anything if it is of length 0.
    //(See https://docs.rs/termion/1.5.4/src/termion/async.rs.html#69 )
    let mut buf: [u8; 32] = [0; 32];

    match self.async_stdin.as_mut().map(|s| s.read(&mut buf)) {
      Some(Ok(0)) | None => Ok(KeyboardCommand::None),
      Some(Ok(_)) => {
        let initial_byte: u8 = buf[0];
        let mut iter = buf[1..].iter().map(|byte| Ok(*byte));
        // TODO: calling `parse_event` in this way means that we will potentially miss keyboard
        // events - a Ctrl-C event has to be the very first event in each `render` frame, or it
        // won't be handled. In practice, the refresh interval is 100 ms, which is fast enough
        // on human timescales that hitting Ctrl-C while the program is running will wind up
        // at the beginning of some frame.  Note that internally termion uses this function
        // in the context of the `next()` function of an Iterator:
        // https://github.com/redox-os/termion/blob/master/src/input.rs .
        let event_or_err = parse_event(initial_byte, &mut iter);
        match event_or_err {
          Ok(Event::Key(Key::Ctrl('c'))) => Ok(KeyboardCommand::CtrlC),
          Err(err) => Err(format!("EngineDisplay keyboard event error: {}", err)),
          _ => Ok(KeyboardCommand::None),
        }
      }
      Some(Err(err)) => Err(format!("EngineDisplay stdin error: {}", err)),
    }
  }

  // Starts the EngineDisplay at the current cursor position.
  pub fn start(&mut self) {
    let write_handle = termion::screen::AlternateScreen::from(stdout());
    self.terminal = match write_handle.into_raw_mode() {
      Ok(t) => Console::Terminal(t),
      Err(_) => Console::Pipe(stdout()),
    };

    self.start_raw_mode().unwrap();
    let cursor_start = self.cursor_start;
    self
      .write(&format!(
        "{hide_cursor}{cursor_init}{clear_after_cursor}",
        hide_cursor = termion::cursor::Hide,
        cursor_init = cursor::Goto(cursor_start.0, cursor_start.1),
        clear_after_cursor = clear::AfterCursor
      ))
      .expect("could not write to terminal");
  }

  // Adds a worker/thread to the visual representation.
  pub fn add_worker(&mut self, worker_name: String) {
    let action_msg = format!("booting {}", worker_name);
    self.update(worker_name, action_msg);
  }

  // Updates the status of a worker/thread.
  pub fn update(&mut self, worker_name: String, action: String) {
    self.action_map.insert(worker_name, action);
  }

  // Removes a worker/thread from the visual representation.
  pub fn remove_worker(&mut self, worker_id: &str) {
    self.action_map.remove(worker_id);
  }

  // Adds a log entry for display.
  pub fn log(&mut self, log_entry: String) {
    self.logs.push_front(log_entry)
  }

  pub fn worker_count(&self) -> usize {
    self.action_map.len()
  }

  pub fn suspend(&mut self) {
    {
      self.terminal = Console::Uninitialized;
      self.suspended = true;
      self.async_stdin = None;
    }
    println!("{}", termion::cursor::Show);
  }

  pub fn unsuspend(&mut self) {
    let write_handle = termion::screen::AlternateScreen::from(stdout());
    self.terminal = match write_handle.into_raw_mode() {
      Ok(t) => Console::Terminal(t),
      Err(_) => Console::Pipe(stdout()),
    };
    self.suspended = false;
    self.async_stdin = Some(async_stdin());
  }

  // Initiates one last screen render, then terminates the EngineDisplay and returns the cursor
  // to a static position, then prints all buffered stdout/stderr output.
  pub fn finish(&mut self) {
    //We don't care about handling the output from render() here, since we're about to shut down
    //the EngineDisplay anyway.
    let _ = self.render();
    {
      self.terminal = Console::Uninitialized; //This forces the AlternateScreen to drop, restoring the original terminal state.
    }

    println!("{}", termion::cursor::Show);
    for log in self.logs.iter() {
      println!("{}", log);
    }
    for PrintableMsg { msg, output } in self.printable_msgs.iter() {
      match output {
        PrintableMsgOutput::Stdout => print!("{}", msg),
        PrintableMsgOutput::Stderr => eprint!("{}", msg),
      }
    }
  }
}
<|endoftext|>


<commit_before>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm.

use std::fmt::Debug;

pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    // Place the first element's index (0) as the first element of the output_index vector.
    output_index.push(0);

    println!("n = {:?}", n);
    println!("input:        {:?}", input);
    println!("output_index: {:?}", output_index);

    if n > 1 {
        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            let i = i_start_at_0 + 1;
            println!("  i={:?} Finding where to put element {:?} (i={:?}) in output_index: {:?}", i, elem, i, output_index);

            // Verify next element if it is smaller
            // If next element is larger than the last stored index, just place that element at
            // the end.
            if *elem >= input[*output_index.last().unwrap()] {
                // Next element "elem" is already larger than the previous stored index.
                // Just use its index.
                output_index.push(i);

                println!("    1. Pushing element '{:?}' at the end.", elem);
            } else {
                println!("    2. elem ?< input[output_index[0]]");
                println!("           {:?} ?< {:?}", elem, input[output_index[0]]);
                // The next element of the input vector is smaller than the last stored on.
                // Let's find where it should go by looping back on the stored indices.
                // NOTE: we must use a loop on indices as to prevent problems with the borrow-checker.
                if *elem < input[output_index[0]] {
                    println!("        2a. Yes: --> putting i in front");
                    output_index.insert(0, i);
                } else {
                    println!("        2b. No: --> Looping back");
                    for j in (0..i).rev() {
                        println!("            j={:?}   elem={:?}   input[output_index[j]]={:?}", j, elem, input[output_index[j]]);
                        if *elem > input[output_index[j]] {
                            output_index.insert(j+1, i);
                            break;
                        }
                    }
                }
                println!("        3. output_index: {:?}", output_index);
            }

            print!("           output: [");
            for j in output_index.iter() {
                    print!("{:?}, ", input[*j]);
            }
            println!("]");
        }
    }

    println!("END: output_index: {:?}", output_index);
    print!("END: output: [");
    for j in output_index.iter() {
            print!("{:?}, ", input[*j]);
    }
    println!("]");

    assert_eq!(output_index.len(), n);

    return output_index;
}
<commit_msg>Comments<commit_after>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

use std::fmt::Debug;

pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    // Place the first element's index (0) as the first element of the output_index vector.
    output_index.push(0);

    println!("n = {:?}", n);
    println!("input:        {:?}", input);
    println!("output_index: {:?}", output_index);

    if n > 1 {
        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            let i = i_start_at_0 + 1;
            println!("  i={:?} Finding where to put element {:?} (i={:?}) in output_index: {:?}", i, elem, i, output_index);

            // Verify next element if it is smaller
            // If next element is larger than the last stored index, just place that element at
            // the end.
            if *elem >= input[*output_index.last().unwrap()] {
                // Next element "elem" is already larger than the previous stored index.
                // Just use its index.
                output_index.push(i);

                println!("    1. Pushing element '{:?}' at the end.", elem);
            } else {
                println!("    2. elem ?< input[output_index[0]]");
                println!("           {:?} ?< {:?}", elem, input[output_index[0]]);
                // The next element of the input vector is smaller than the last stored on.
                // Let's find where it should go by looping back on the stored indices.
                // NOTE: we must use a loop on indices as to prevent problems with the borrow-checker.
                if *elem < input[output_index[0]] {
                    println!("        2a. Yes: --> putting i in front");
                    output_index.insert(0, i);
                } else {
                    println!("        2b. No: --> Looping back");
                    for j in (0..i).rev() {
                        println!("            j={:?}   elem={:?}   input[output_index[j]]={:?}", j, elem, input[output_index[j]]);
                        if *elem > input[output_index[j]] {
                            output_index.insert(j+1, i);
                            break;
                        }
                    }
                }
                println!("        3. output_index: {:?}", output_index);
            }

            print!("           output: [");
            for j in output_index.iter() {
                    print!("{:?}, ", input[*j]);
            }
            println!("]");
        }
    }

    println!("END: output_index: {:?}", output_index);
    print!("END: output: [");
    for j in output_index.iter() {
            print!("{:?}, ", input[*j]);
    }
    println!("]");

    assert_eq!(output_index.len(), n);

    return output_index;
}
<|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.

// ignore-cloudabi no environment variables present
// ignore-emscripten env vars don't work?

#![feature(path)]

use std::env::*;
use std::path::PathBuf;

#[cfg(unix)]
fn main() {
    let oldhome = var("HOME");

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");
    if cfg!(target_os = "android") {
        assert!(home_dir().is_none());
    } else {
        assert!(home_dir().is_some());
    }
}

#[cfg(windows)]
fn main() {
    let oldhome = var("HOME");
    let olduserprofile = var("USERPROFILE");

    remove_var("HOME");
    remove_var("USERPROFILE");

    assert!(home_dir().is_some());

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");

    set_var("USERPROFILE", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    set_var("HOME", "/home/MountainView");
    set_var("USERPROFILE", "/home/PaloAlto");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
}
<commit_msg>Make run-pass/env-home-dir.rs test more robust<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.

// ignore-cloudabi no environment variables present
// ignore-emscripten env vars don't work?

#![feature(path)]

use std::env::*;
use std::path::PathBuf;

/// When HOME is not set, some platforms return `None`, but others return `Some` with a default.
/// Just check that it is not "/home/MountainView".

#[cfg(unix)]
fn main() {
    let oldhome = var("HOME");

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");
    if cfg!(target_os = "android") {
        assert!(home_dir().is_none());
    } else {
        assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
    }
}

#[cfg(windows)]
fn main() {
    let oldhome = var("HOME");
    let olduserprofile = var("USERPROFILE");

    remove_var("HOME");
    remove_var("USERPROFILE");

    assert!(home_dir().is_some());

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");

    set_var("USERPROFILE", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    set_var("HOME", "/home/MountainView");
    set_var("USERPROFILE", "/home/PaloAlto");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
}
<|endoftext|>


<commit_before>// check-pass

macro_rules! def_target {
    ($target: expr) => {
        #[target_feature(enable=$target)]
        unsafe fn f() {
            #[target_feature(enable=$target)]
            ()
        }
    };
}

def_target!("avx2");

fn main() {}
<commit_msg>Fix test not to depend on environment<commit_after>// check-pass

macro_rules! foo {
    ($doc: expr) => {
        fn f() {
            #[doc = $doc]
            ()
        }
    };
}

foo!("doc");

fn main() {}
<|endoftext|>


<commit_before>// Copyright 2016 Serde YAML Developers
//
// 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.

//! YAML Deserialization
//!
//! This module provides YAML deserialization with the type `Deserializer`.

use std::io;
use std::iter;
use std::slice;
use std::str;

use yaml_rust::{Yaml, YamlLoader};
use yaml_rust::yaml;

use serde::de::{self, Deserialize};

use super::error::{Error, Result};

/// A structure for deserializing a YAML value into a Rust value.
pub struct Deserializer<'a> {
    /// YAML value being deserialized.
    doc: &'a Yaml,
}

impl<'a> Deserializer<'a> {
    /// Creates the YAML deserializer from an in-memory `Yaml`.
    pub fn new(doc: &'a Yaml) -> Self {
        Deserializer {
            doc: doc,
        }
    }
}

struct SeqVisitor<'a> {
    /// Iterator over the YAML array being visited.
    iter: slice::Iter<'a, Yaml>,
}

impl<'a> SeqVisitor<'a> {
    fn new(seq: &'a [Yaml]) -> Self {
        SeqVisitor {
            iter: seq.iter(),
        }
    }
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some(ref t) => {
                Deserialize::deserialize(&mut Deserializer::new(t)).map(Some)
            },
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }
}

struct MapVisitor<'a> {
    /// Iterator over the YAML hash being visited.
    iter: <&'a yaml::Hash as iter::IntoIterator>::IntoIter,
    /// Value associated with the most recently visited key.
    v: Option<&'a Yaml>,
}

impl<'a> MapVisitor<'a> {
    fn new(hash: &'a yaml::Hash) -> Self {
        MapVisitor {
            iter: hash.into_iter(),
            v: None,
        }
    }
}

impl<'a> de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some((ref k, ref v)) => {
                self.v = Some(v);
                Deserialize::deserialize(&mut Deserializer::new(k)).map(Some)
            },
        }
    }

    fn visit_value<V>(&mut self) -> Result<V>
        where V: Deserialize,
    {
        if let Some(v) = self.v {
            Deserialize::deserialize(&mut Deserializer::new(v))
        } else {
            panic!("must call visit_key before visit_value")
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }

    fn missing_field<V>(&mut self, field: &'static str) -> Result<V>
        where V: de::Deserialize,
    {
        struct MissingFieldDeserializer(&'static str);

        impl de::Deserializer for MissingFieldDeserializer {
            type Error = Error;

            fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value>
                where V: de::Visitor,
            {
                let &mut MissingFieldDeserializer(field) = self;
                Err(de::Error::missing_field(field))
            }

            fn deserialize_option<V>(&mut self,
                                     mut visitor: V) -> Result<V::Value>
                where V: de::Visitor,
            {
                visitor.visit_none()
            }
        }

        let mut de = MissingFieldDeserializer(field);
        Ok(try!(de::Deserialize::deserialize(&mut de)))
    }
}

struct VariantVisitor<'a> {
    /// Representation of which variant it is.
    variant: &'a Yaml,
    /// Representation of the content of the variant.
    content: &'a Yaml,
}

impl<'a> VariantVisitor<'a> {
    fn new(variant: &'a Yaml, content: &'a Yaml) -> Self {
        VariantVisitor {
            variant: variant,
            content: content,
        }
    }
}

impl <'a> de::VariantVisitor for VariantVisitor<'a> {
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V>
        where V: Deserialize
    {
        Deserialize::deserialize(&mut Deserializer::new(self.variant))
    }

    fn visit_unit(&mut self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype<T>(&mut self) -> Result<T>
        where T: Deserialize,
    {
        Deserialize::deserialize(&mut Deserializer::new(self.content))
    }

    fn visit_tuple<V>(&mut self,
                      _len: usize,
                      visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::deserialize(&mut Deserializer::new(self.content), visitor)
    }

    fn visit_struct<V>(&mut self,
                       _fields: &'static [&'static str],
                       visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::deserialize(&mut Deserializer::new(self.content), visitor)
    }
}

impl<'a> de::Deserializer for Deserializer<'a> {
    type Error = Error;

    fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Integer(i) => visitor.visit_i64(i),
            Yaml::Real(ref s) | Yaml::String(ref s) => visitor.visit_str(s),
            Yaml::Boolean(b) => visitor.visit_bool(b),
            Yaml::Array(ref seq) => visitor.visit_seq(SeqVisitor::new(seq)),
            Yaml::Hash(ref hash) => visitor.visit_map(MapVisitor::new(hash)),
            Yaml::Alias(_) => Err(Error::AliasUnsupported),
            Yaml::Null => visitor.visit_unit(),
            Yaml::BadValue => {
                // The yaml-rust library produces BadValue when a nonexistent
                // node is accessed by the Index trait, and when a type
                // conversion is invalid. Both of these are unexpected in our
                // usage.
                panic!("bad value")
            },
        }
    }

    /// Parses `null` as None and any other values as `Some(...)`.
    fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Null => visitor.visit_none(),
            _ => visitor.visit_some(self),
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn deserialize_newtype_struct<V>(&mut self,
                               _name: &str,
                               mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        visitor.visit_newtype_struct(self)
    }

    /// Parses an enum as a single key:value pair where the key identifies the
    /// variant and the value gives the content.
    fn deserialize_enum<V>(&mut self,
                     name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value>
        where V: de::EnumVisitor,
    {
        if let Yaml::Hash(ref hash) = *self.doc {
            let mut iter = hash.iter();
            if let (Some(entry), None) = (iter.next(), iter.next()) {
                let (variant, content) = entry;
                visitor.visit(VariantVisitor::new(variant, content))
            } else {
                Err(Error::VariantMapWrongSize(String::from(name), hash.len()))
            }
        } else {
            Err(Error::VariantNotAMap(String::from(name)))
        }
    }
}

/// Decodes a YAML value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T>
    where T: Deserialize
{
    let docs = try!(YamlLoader::load_from_str(s));
    match docs.len() {
        0 => Err(Error::EndOfStream),
        1 => {
            let doc = &docs[0];
            Deserialize::deserialize(&mut Deserializer::new(doc))
        },
        n => Err(Error::TooManyDocuments(n)),
    }
}

pub fn from_iter<I, T>(iter: I) -> Result<T>
    where I: Iterator<Item=io::Result<u8>>,
          T: Deserialize,
{
    let bytes: Vec<u8> = try!(iter.collect());
    from_str(try!(str::from_utf8(&bytes)))
}

pub fn from_reader<R, T>(rdr: R) -> Result<T>
    where R: io::Read,
          T: Deserialize,
{
    from_iter(rdr.bytes())
}

pub fn from_slice<T>(v: &[u8]) -> Result<T>
    where T: Deserialize
{
    from_iter(v.iter().map(|byte| Ok(*byte)))
}
<commit_msg>Simplify missing_field implementation<commit_after>// Copyright 2016 Serde YAML Developers
//
// 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.

//! YAML Deserialization
//!
//! This module provides YAML deserialization with the type `Deserializer`.

use std::io;
use std::iter;
use std::slice;
use std::str;

use yaml_rust::{Yaml, YamlLoader};
use yaml_rust::yaml;

use serde::de::{self, Deserialize};

use super::error::{Error, Result};

/// A structure for deserializing a YAML value into a Rust value.
pub struct Deserializer<'a> {
    /// YAML value being deserialized.
    doc: &'a Yaml,
}

impl<'a> Deserializer<'a> {
    /// Creates the YAML deserializer from an in-memory `Yaml`.
    pub fn new(doc: &'a Yaml) -> Self {
        Deserializer {
            doc: doc,
        }
    }
}

struct SeqVisitor<'a> {
    /// Iterator over the YAML array being visited.
    iter: slice::Iter<'a, Yaml>,
}

impl<'a> SeqVisitor<'a> {
    fn new(seq: &'a [Yaml]) -> Self {
        SeqVisitor {
            iter: seq.iter(),
        }
    }
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some(ref t) => {
                Deserialize::deserialize(&mut Deserializer::new(t)).map(Some)
            },
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }
}

struct MapVisitor<'a> {
    /// Iterator over the YAML hash being visited.
    iter: <&'a yaml::Hash as iter::IntoIterator>::IntoIter,
    /// Value associated with the most recently visited key.
    v: Option<&'a Yaml>,
}

impl<'a> MapVisitor<'a> {
    fn new(hash: &'a yaml::Hash) -> Self {
        MapVisitor {
            iter: hash.into_iter(),
            v: None,
        }
    }
}

impl<'a> de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some((ref k, ref v)) => {
                self.v = Some(v);
                Deserialize::deserialize(&mut Deserializer::new(k)).map(Some)
            },
        }
    }

    fn visit_value<V>(&mut self) -> Result<V>
        where V: Deserialize,
    {
        if let Some(v) = self.v {
            Deserialize::deserialize(&mut Deserializer::new(v))
        } else {
            panic!("must call visit_key before visit_value")
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }

    fn missing_field<V>(&mut self, field: &'static str) -> Result<V>
        where V: de::Deserialize,
    {
        struct MissingFieldDeserializer(&'static str);

        impl de::Deserializer for MissingFieldDeserializer {
            type Error = Error;

            fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value>
                where V: de::Visitor,
            {
                Err(de::Error::missing_field(self.0))
            }

            fn deserialize_option<V>(&mut self,
                                     mut visitor: V) -> Result<V::Value>
                where V: de::Visitor,
            {
                visitor.visit_none()
            }
        }

        let mut de = MissingFieldDeserializer(field);
        Ok(try!(de::Deserialize::deserialize(&mut de)))
    }
}

struct VariantVisitor<'a> {
    /// Representation of which variant it is.
    variant: &'a Yaml,
    /// Representation of the content of the variant.
    content: &'a Yaml,
}

impl<'a> VariantVisitor<'a> {
    fn new(variant: &'a Yaml, content: &'a Yaml) -> Self {
        VariantVisitor {
            variant: variant,
            content: content,
        }
    }
}

impl <'a> de::VariantVisitor for VariantVisitor<'a> {
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V>
        where V: Deserialize
    {
        Deserialize::deserialize(&mut Deserializer::new(self.variant))
    }

    fn visit_unit(&mut self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype<T>(&mut self) -> Result<T>
        where T: Deserialize,
    {
        Deserialize::deserialize(&mut Deserializer::new(self.content))
    }

    fn visit_tuple<V>(&mut self,
                      _len: usize,
                      visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::deserialize(&mut Deserializer::new(self.content), visitor)
    }

    fn visit_struct<V>(&mut self,
                       _fields: &'static [&'static str],
                       visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::deserialize(&mut Deserializer::new(self.content), visitor)
    }
}

impl<'a> de::Deserializer for Deserializer<'a> {
    type Error = Error;

    fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Integer(i) => visitor.visit_i64(i),
            Yaml::Real(ref s) | Yaml::String(ref s) => visitor.visit_str(s),
            Yaml::Boolean(b) => visitor.visit_bool(b),
            Yaml::Array(ref seq) => visitor.visit_seq(SeqVisitor::new(seq)),
            Yaml::Hash(ref hash) => visitor.visit_map(MapVisitor::new(hash)),
            Yaml::Alias(_) => Err(Error::AliasUnsupported),
            Yaml::Null => visitor.visit_unit(),
            Yaml::BadValue => {
                // The yaml-rust library produces BadValue when a nonexistent
                // node is accessed by the Index trait, and when a type
                // conversion is invalid. Both of these are unexpected in our
                // usage.
                panic!("bad value")
            },
        }
    }

    /// Parses `null` as None and any other values as `Some(...)`.
    fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Null => visitor.visit_none(),
            _ => visitor.visit_some(self),
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn deserialize_newtype_struct<V>(&mut self,
                               _name: &str,
                               mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        visitor.visit_newtype_struct(self)
    }

    /// Parses an enum as a single key:value pair where the key identifies the
    /// variant and the value gives the content.
    fn deserialize_enum<V>(&mut self,
                     name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value>
        where V: de::EnumVisitor,
    {
        if let Yaml::Hash(ref hash) = *self.doc {
            let mut iter = hash.iter();
            if let (Some(entry), None) = (iter.next(), iter.next()) {
                let (variant, content) = entry;
                visitor.visit(VariantVisitor::new(variant, content))
            } else {
                Err(Error::VariantMapWrongSize(String::from(name), hash.len()))
            }
        } else {
            Err(Error::VariantNotAMap(String::from(name)))
        }
    }
}

/// Decodes a YAML value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T>
    where T: Deserialize
{
    let docs = try!(YamlLoader::load_from_str(s));
    match docs.len() {
        0 => Err(Error::EndOfStream),
        1 => {
            let doc = &docs[0];
            Deserialize::deserialize(&mut Deserializer::new(doc))
        },
        n => Err(Error::TooManyDocuments(n)),
    }
}

pub fn from_iter<I, T>(iter: I) -> Result<T>
    where I: Iterator<Item=io::Result<u8>>,
          T: Deserialize,
{
    let bytes: Vec<u8> = try!(iter.collect());
    from_str(try!(str::from_utf8(&bytes)))
}

pub fn from_reader<R, T>(rdr: R) -> Result<T>
    where R: io::Read,
          T: Deserialize,
{
    from_iter(rdr.bytes())
}

pub fn from_slice<T>(v: &[u8]) -> Result<T>
    where T: Deserialize
{
    from_iter(v.iter().map(|byte| Ok(*byte)))
}
<|endoftext|>


<commit_before><commit_msg>Use wildcards for public re-exports<commit_after><|endoftext|>


<commit_before><commit_msg>Increase loglevel.<commit_after><|endoftext|>


<commit_before><commit_msg>Fix typo.<commit_after><|endoftext|>


<commit_before><commit_msg>Add sun altitude<commit_after><|endoftext|>


<commit_before><commit_msg>added second general usecase to documentation<commit_after><|endoftext|>


<commit_before><commit_msg>And forgot these...<commit_after><|endoftext|>