<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.

//! See docs in build/expr/mod.rs

use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
use build::scope::LoopScope;
use hair::*;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty;
use rustc::mir::repr::*;
use syntax::codemap::Span;

impl<'a,'tcx> Builder<'a,'tcx> {
    /// Compile `expr`, storing the result into `destination`, which
    /// is assumed to be uninitialized.
    pub fn into_expr(&mut self,
                     destination: &Lvalue<'tcx>,
                     mut block: BasicBlock,
                     expr: Expr<'tcx>)
                     -> BlockAnd<()>
    {
        debug!("into_expr(destination={:?}, block={:?}, expr={:?})",
               destination, block, expr);

        // since we frequently have to reference `self` from within a
        // closure, where `self` would be shadowed, it's easier to
        // just use the name `this` uniformly
        let this = self;
        let expr_span = expr.span;

        match expr.kind {
            ExprKind::Scope { extent, value } => {
                this.in_scope(extent, block, |this| this.into(destination, block, value))
            }
            ExprKind::Block { body: ast_block } => {
                this.ast_block(destination, block, ast_block)
            }
            ExprKind::Match { discriminant, arms } => {
                this.match_expr(destination, expr_span, block, discriminant, arms)
            }
            ExprKind::If { condition: cond_expr, then: then_expr, otherwise: else_expr } => {
                let operand = unpack!(block = this.as_operand(block, cond_expr));

                let mut then_block = this.cfg.start_new_block();
                let mut else_block = this.cfg.start_new_block();
                this.cfg.terminate(block, Terminator::If {
                    cond: operand,
                    targets: (then_block, else_block)
                });

                unpack!(then_block = this.into(destination, then_block, then_expr));
                else_block = if let Some(else_expr) = else_expr {
                    unpack!(this.into(destination, else_block, else_expr))
                } else {
                    // Body of the `if` expression without an `else` clause must return `()`, thus
                    // we implicitly generate a `else {}` if it is not specified.
                    this.cfg.push_assign_unit(else_block, expr_span, &Lvalue::ReturnPointer);
                    else_block
                };

                let join_block = this.cfg.start_new_block();
                this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(else_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::LogicalOp { op, lhs, rhs } => {
                // And:
                //
                // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------false-----------+------------------> [false_block]
                //
                // Or:
                //
                // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------true------------+-------------------> [false_block]

                let (true_block, false_block, mut else_block, join_block) =
                    (this.cfg.start_new_block(), this.cfg.start_new_block(),
                     this.cfg.start_new_block(), this.cfg.start_new_block());

                let lhs = unpack!(block = this.as_operand(block, lhs));
                let blocks = match op {
                    LogicalOp::And => (else_block, false_block),
                    LogicalOp::Or => (true_block, else_block),
                };
                this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });

                let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
                this.cfg.terminate(else_block, Terminator::If {
                    cond: rhs,
                    targets: (true_block, false_block)
                });

                this.cfg.push_assign_constant(
                    true_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.true_literal(),
                    });

                this.cfg.push_assign_constant(
                    false_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.false_literal(),
                    });

                this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(false_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::Loop { condition: opt_cond_expr, body } => {
                // [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
                //                  ^                  |
                //                  |                  0
                //                  |                  |
                //                  |                  v
                //           [body_block_end] <~~~ [body_block]
                //
                // If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
                //
                // [block] --> [loop_block / body_block ] ~~> [body_block_end]    [exit_block]
                //                         ^                          |
                //                         |                          |
                //                         +--------------------------+
                //

                let loop_block = this.cfg.start_new_block();
                let exit_block = this.cfg.start_new_block();

                // start the loop
                this.cfg.terminate(block, Terminator::Goto { target: loop_block });

                let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                    // conduct the test, if necessary
                    let body_block;
                    if let Some(cond_expr) = opt_cond_expr {
                        // This loop has a condition, ergo its exit_block is reachable.
                        this.find_loop_scope(expr_span, None).might_break = true;

                        let loop_block_end;
                        let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                        body_block = this.cfg.start_new_block();
                        this.cfg.terminate(loop_block_end,
                                           Terminator::If {
                                               cond: cond,
                                               targets: (body_block, exit_block)
                                           });
                    } else {
                        body_block = loop_block;
                    }

                    // The “return” value of the loop body must always be an unit, but we cannot
                    // reuse that as a “return” value of the whole loop expressions, because some
                    // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as
                    // the destination for the loop body and assign the loop’s own “return” value
                    // immediately after the iteration is finished.
                    let tmp = this.get_unit_temp();
                    // Execute the body, branching back to the test.
                    let body_block_end = unpack!(this.into(&tmp, body_block, body));
                    this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
                });
                // If the loop may reach its exit_block, we assign an empty tuple to the
                // destination to keep the MIR well-formed.
                if might_break {
                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
                }
                exit_block.unit()
            }
            ExprKind::Assign { lhs, rhs } => {
                // Note: we evaluate assignments right-to-left. This
                // is better for borrowck interaction with overloaded
                // operators like x[j] = x[i].
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));
                unpack!(block = this.build_drop(block, lhs.clone()));
                this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
                block.unit()
            }
            ExprKind::AssignOp { op, lhs, rhs } => {
                // FIXME(#28160) there is an interesting semantics
                // question raised here -- should we "freeze" the
                // value of the lhs here?  I'm inclined to think not,
                // since it seems closer to the semantics of the
                // overloaded version, which takes `&mut self`.  This
                // only affects weird things like `x += {x += 1; x}`
                // -- is that equal to `x + (x + 1)` or `2*(x+1)`?

                // As above, RTL.
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));

                // we don't have to drop prior contents or anything
                // because AssignOp is only legal for Copy types
                // (overloaded ops should be desugared into a call).
                this.cfg.push_assign(block, expr_span, &lhs,
                                     Rvalue::BinaryOp(op,
                                                      Operand::Consume(lhs.clone()),
                                                      rhs));

                block.unit()
            }
            ExprKind::Continue { label } => {
                this.break_or_continue(expr_span, label, block,
                                       |loop_scope| loop_scope.continue_block)
            }
            ExprKind::Break { label } => {
                this.break_or_continue(expr_span, label, block, |loop_scope| {
                    loop_scope.might_break = true;
                    loop_scope.break_block
                })
            }
            ExprKind::Return { value } => {
                block = match value {
                    Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
                    None => {
                        this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
                        block
                    }
                };
                let extent = this.extent_of_outermost_scope();
                this.exit_scope(expr_span, extent, block, END_BLOCK);
                this.cfg.start_new_block().unit()
            }
            ExprKind::Call { ty, fun, args } => {
                let diverges = match ty.sty {
                    ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
                    _ => false
                };
                let fun = unpack!(block = this.as_operand(block, fun));
                let args: Vec<_> =
                    args.into_iter()
                        .map(|arg| unpack!(block = this.as_operand(block, arg)))
                        .collect();

                let success = this.cfg.start_new_block();
                let cleanup = this.diverge_cleanup();
                this.cfg.terminate(block, Terminator::Call {
                    func: fun,
                    args: args,
                    cleanup: cleanup,
                    destination: if diverges {
                        None
                    } else {
                        Some ((destination.clone(), success))
                    }
                });
                success.unit()
            }

            // these are the cases that are more naturally handled by some other mode
            ExprKind::Unary { .. } |
            ExprKind::Binary { .. } |
            ExprKind::Box { .. } |
            ExprKind::Cast { .. } |
            ExprKind::ReifyFnPointer { .. } |
            ExprKind::UnsafeFnPointer { .. } |
            ExprKind::Unsize { .. } |
            ExprKind::Repeat { .. } |
            ExprKind::Borrow { .. } |
            ExprKind::VarRef { .. } |
            ExprKind::SelfRef |
            ExprKind::StaticRef { .. } |
            ExprKind::Vec { .. } |
            ExprKind::Tuple { .. } |
            ExprKind::Adt { .. } |
            ExprKind::Closure { .. } |
            ExprKind::Index { .. } |
            ExprKind::Deref { .. } |
            ExprKind::Literal { .. } |
            ExprKind::InlineAsm { .. } |
            ExprKind::Field { .. } => {
                debug_assert!(match Category::of(&expr.kind).unwrap() {
                    Category::Rvalue(RvalueFunc::Into) => false,
                    _ => true,
                });

                let rvalue = unpack!(block = this.as_rvalue(block, expr));
                this.cfg.push_assign(block, expr_span, destination, rvalue);
                block.unit()
            }
        }
    }

    fn break_or_continue<F>(&mut self,
                            span: Span,
                            label: Option<CodeExtent>,
                            block: BasicBlock,
                            exit_selector: F)
                            -> BlockAnd<()>
        where F: FnOnce(&mut LoopScope) -> BasicBlock
    {
        let (exit_block, extent) = {
            let loop_scope = self.find_loop_scope(span, label);
            (exit_selector(loop_scope), loop_scope.extent)
        };
        self.exit_scope(span, extent, block, exit_block);
        self.cfg.start_new_block().unit()
    }
}
<commit_msg>[MIR] Fix the destination of implicit else branch<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.

//! See docs in build/expr/mod.rs

use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
use build::scope::LoopScope;
use hair::*;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty;
use rustc::mir::repr::*;
use syntax::codemap::Span;

impl<'a,'tcx> Builder<'a,'tcx> {
    /// Compile `expr`, storing the result into `destination`, which
    /// is assumed to be uninitialized.
    pub fn into_expr(&mut self,
                     destination: &Lvalue<'tcx>,
                     mut block: BasicBlock,
                     expr: Expr<'tcx>)
                     -> BlockAnd<()>
    {
        debug!("into_expr(destination={:?}, block={:?}, expr={:?})",
               destination, block, expr);

        // since we frequently have to reference `self` from within a
        // closure, where `self` would be shadowed, it's easier to
        // just use the name `this` uniformly
        let this = self;
        let expr_span = expr.span;

        match expr.kind {
            ExprKind::Scope { extent, value } => {
                this.in_scope(extent, block, |this| this.into(destination, block, value))
            }
            ExprKind::Block { body: ast_block } => {
                this.ast_block(destination, block, ast_block)
            }
            ExprKind::Match { discriminant, arms } => {
                this.match_expr(destination, expr_span, block, discriminant, arms)
            }
            ExprKind::If { condition: cond_expr, then: then_expr, otherwise: else_expr } => {
                let operand = unpack!(block = this.as_operand(block, cond_expr));

                let mut then_block = this.cfg.start_new_block();
                let mut else_block = this.cfg.start_new_block();
                this.cfg.terminate(block, Terminator::If {
                    cond: operand,
                    targets: (then_block, else_block)
                });

                unpack!(then_block = this.into(destination, then_block, then_expr));
                else_block = if let Some(else_expr) = else_expr {
                    unpack!(this.into(destination, else_block, else_expr))
                } else {
                    // Body of the `if` expression without an `else` clause must return `()`, thus
                    // we implicitly generate a `else {}` if it is not specified.
                    this.cfg.push_assign_unit(else_block, expr_span, destination);
                    else_block
                };

                let join_block = this.cfg.start_new_block();
                this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(else_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::LogicalOp { op, lhs, rhs } => {
                // And:
                //
                // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------false-----------+------------------> [false_block]
                //
                // Or:
                //
                // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------true------------+-------------------> [false_block]

                let (true_block, false_block, mut else_block, join_block) =
                    (this.cfg.start_new_block(), this.cfg.start_new_block(),
                     this.cfg.start_new_block(), this.cfg.start_new_block());

                let lhs = unpack!(block = this.as_operand(block, lhs));
                let blocks = match op {
                    LogicalOp::And => (else_block, false_block),
                    LogicalOp::Or => (true_block, else_block),
                };
                this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });

                let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
                this.cfg.terminate(else_block, Terminator::If {
                    cond: rhs,
                    targets: (true_block, false_block)
                });

                this.cfg.push_assign_constant(
                    true_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.true_literal(),
                    });

                this.cfg.push_assign_constant(
                    false_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.false_literal(),
                    });

                this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(false_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::Loop { condition: opt_cond_expr, body } => {
                // [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
                //                  ^                  |
                //                  |                  0
                //                  |                  |
                //                  |                  v
                //           [body_block_end] <~~~ [body_block]
                //
                // If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
                //
                // [block] --> [loop_block / body_block ] ~~> [body_block_end]    [exit_block]
                //                         ^                          |
                //                         |                          |
                //                         +--------------------------+
                //

                let loop_block = this.cfg.start_new_block();
                let exit_block = this.cfg.start_new_block();

                // start the loop
                this.cfg.terminate(block, Terminator::Goto { target: loop_block });

                let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                    // conduct the test, if necessary
                    let body_block;
                    if let Some(cond_expr) = opt_cond_expr {
                        // This loop has a condition, ergo its exit_block is reachable.
                        this.find_loop_scope(expr_span, None).might_break = true;

                        let loop_block_end;
                        let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                        body_block = this.cfg.start_new_block();
                        this.cfg.terminate(loop_block_end,
                                           Terminator::If {
                                               cond: cond,
                                               targets: (body_block, exit_block)
                                           });
                    } else {
                        body_block = loop_block;
                    }

                    // The “return” value of the loop body must always be an unit, but we cannot
                    // reuse that as a “return” value of the whole loop expressions, because some
                    // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as
                    // the destination for the loop body and assign the loop’s own “return” value
                    // immediately after the iteration is finished.
                    let tmp = this.get_unit_temp();
                    // Execute the body, branching back to the test.
                    let body_block_end = unpack!(this.into(&tmp, body_block, body));
                    this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
                });
                // If the loop may reach its exit_block, we assign an empty tuple to the
                // destination to keep the MIR well-formed.
                if might_break {
                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
                }
                exit_block.unit()
            }
            ExprKind::Assign { lhs, rhs } => {
                // Note: we evaluate assignments right-to-left. This
                // is better for borrowck interaction with overloaded
                // operators like x[j] = x[i].
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));
                unpack!(block = this.build_drop(block, lhs.clone()));
                this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
                block.unit()
            }
            ExprKind::AssignOp { op, lhs, rhs } => {
                // FIXME(#28160) there is an interesting semantics
                // question raised here -- should we "freeze" the
                // value of the lhs here?  I'm inclined to think not,
                // since it seems closer to the semantics of the
                // overloaded version, which takes `&mut self`.  This
                // only affects weird things like `x += {x += 1; x}`
                // -- is that equal to `x + (x + 1)` or `2*(x+1)`?

                // As above, RTL.
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));

                // we don't have to drop prior contents or anything
                // because AssignOp is only legal for Copy types
                // (overloaded ops should be desugared into a call).
                this.cfg.push_assign(block, expr_span, &lhs,
                                     Rvalue::BinaryOp(op,
                                                      Operand::Consume(lhs.clone()),
                                                      rhs));

                block.unit()
            }
            ExprKind::Continue { label } => {
                this.break_or_continue(expr_span, label, block,
                                       |loop_scope| loop_scope.continue_block)
            }
            ExprKind::Break { label } => {
                this.break_or_continue(expr_span, label, block, |loop_scope| {
                    loop_scope.might_break = true;
                    loop_scope.break_block
                })
            }
            ExprKind::Return { value } => {
                block = match value {
                    Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
                    None => {
                        this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
                        block
                    }
                };
                let extent = this.extent_of_outermost_scope();
                this.exit_scope(expr_span, extent, block, END_BLOCK);
                this.cfg.start_new_block().unit()
            }
            ExprKind::Call { ty, fun, args } => {
                let diverges = match ty.sty {
                    ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
                    _ => false
                };
                let fun = unpack!(block = this.as_operand(block, fun));
                let args: Vec<_> =
                    args.into_iter()
                        .map(|arg| unpack!(block = this.as_operand(block, arg)))
                        .collect();

                let success = this.cfg.start_new_block();
                let cleanup = this.diverge_cleanup();
                this.cfg.terminate(block, Terminator::Call {
                    func: fun,
                    args: args,
                    cleanup: cleanup,
                    destination: if diverges {
                        None
                    } else {
                        Some ((destination.clone(), success))
                    }
                });
                success.unit()
            }

            // these are the cases that are more naturally handled by some other mode
            ExprKind::Unary { .. } |
            ExprKind::Binary { .. } |
            ExprKind::Box { .. } |
            ExprKind::Cast { .. } |
            ExprKind::ReifyFnPointer { .. } |
            ExprKind::UnsafeFnPointer { .. } |
            ExprKind::Unsize { .. } |
            ExprKind::Repeat { .. } |
            ExprKind::Borrow { .. } |
            ExprKind::VarRef { .. } |
            ExprKind::SelfRef |
            ExprKind::StaticRef { .. } |
            ExprKind::Vec { .. } |
            ExprKind::Tuple { .. } |
            ExprKind::Adt { .. } |
            ExprKind::Closure { .. } |
            ExprKind::Index { .. } |
            ExprKind::Deref { .. } |
            ExprKind::Literal { .. } |
            ExprKind::InlineAsm { .. } |
            ExprKind::Field { .. } => {
                debug_assert!(match Category::of(&expr.kind).unwrap() {
                    Category::Rvalue(RvalueFunc::Into) => false,
                    _ => true,
                });

                let rvalue = unpack!(block = this.as_rvalue(block, expr));
                this.cfg.push_assign(block, expr_span, destination, rvalue);
                block.unit()
            }
        }
    }

    fn break_or_continue<F>(&mut self,
                            span: Span,
                            label: Option<CodeExtent>,
                            block: BasicBlock,
                            exit_selector: F)
                            -> BlockAnd<()>
        where F: FnOnce(&mut LoopScope) -> BasicBlock
    {
        let (exit_block, extent) = {
            let loop_scope = self.find_loop_scope(span, label);
            (exit_selector(loop_scope), loop_scope.extent)
        };
        self.exit_scope(span, extent, block, exit_block);
        self.cfg.start_new_block().unit()
    }
}
<|endoftext|>


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

//! This module crawls a `clean::Crate` and produces a summarization of the
//! stability levels within the crate. The summary contains the module
//! hierarchy, with item counts for every stability level per module. A parent
//! module's count includes its children's.

use std::ops::Add;
use std::num::Zero;

use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
use syntax::ast::Public;

use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};

use html::render::cache;

#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
/// The counts for each stability level.
pub struct Counts {
    pub deprecated: uint,
    pub experimental: uint,
    pub unstable: uint,
    pub stable: uint,
    pub frozen: uint,
    pub locked: uint,

    /// No stability level, inherited or otherwise.
    pub unmarked: uint,
}

impl Copy for Counts {}

impl Add<Counts, Counts> for Counts {
    fn add(&self, other: &Counts) -> Counts {
        Counts {
            deprecated:   self.deprecated   + other.deprecated,
            experimental: self.experimental + other.experimental,
            unstable:     self.unstable     + other.unstable,
            stable:       self.stable       + other.stable,
            frozen:       self.frozen       + other.frozen,
            locked:       self.locked       + other.locked,
            unmarked:     self.unmarked     + other.unmarked,
        }
    }
}

impl Counts {
    fn zero() -> Counts {
        Counts {
            deprecated:   0,
            experimental: 0,
            unstable:     0,
            stable:       0,
            frozen:       0,
            locked:       0,
            unmarked:     0,
        }
    }

    pub fn total(&self) -> uint {
        self.deprecated + self.experimental + self.unstable + self.stable +
            self.frozen + self.locked + self.unmarked
    }
}

#[deriving(Encodable, Decodable, PartialEq, Eq)]
/// A summarized module, which includes total counts and summarized children
/// modules.
pub struct ModuleSummary {
    pub name: String,
    pub counts: Counts,
    pub submodules: Vec<ModuleSummary>,
}

impl PartialOrd for ModuleSummary {
    fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
        self.name.partial_cmp(&other.name)
    }
}

impl Ord for ModuleSummary {
    fn cmp(&self, other: &ModuleSummary) -> Ordering {
        self.name.cmp(&other.name)
    }
}

// is the item considered publically visible?
fn visible(item: &Item) -> bool {
    match item.inner {
        ImplItem(_) => true,
        _ => item.visibility == Some(Public)
    }
}

fn count_stability(stab: Option<&Stability>) -> Counts {
    match stab {
        None             => Counts { unmarked: 1,     .. Counts::zero() },
        Some(ref stab) => match stab.level {
            Deprecated   => Counts { deprecated: 1,   .. Counts::zero() },
            Experimental => Counts { experimental: 1, .. Counts::zero() },
            Unstable     => Counts { unstable: 1,     .. Counts::zero() },
            Stable       => Counts { stable: 1,       .. Counts::zero() },
            Frozen       => Counts { frozen: 1,       .. Counts::zero() },
            Locked       => Counts { locked: 1,       .. Counts::zero() },
        }
    }
}

fn summarize_methods(item: &Item) -> Counts {
    match cache().impls.get(&item.def_id) {
        Some(v) => {
            v.iter().map(|i| {
                let count = count_stability(i.stability.as_ref());
                if i.impl_.trait_.is_none() {
                    count + i.impl_.items.iter()
                        .map(|ti| summarize_item(ti).0)
                        .fold(Counts::zero(), |acc, c| acc + c)
                } else {
                    count
                }
            }).fold(Counts::zero(), |acc, c| acc + c)
        },
        None => {
            Counts::zero()
        },
    }
}

// Produce the summary for an arbitrary item. If the item is a module, include a
// module summary. The counts for items with nested items (e.g. modules, traits,
// impls) include all children counts.
fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
    let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);

    // Count this item's children, if any. Note that a trait impl is
    // considered to have no children.
    match item.inner {
        // Require explicit `pub` to be visible
        ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
            let subcounts = subitems.iter().filter(|i| visible(*i))
                                           .map(summarize_item)
                                           .map(|s| s.val0())
                                           .fold(Counts::zero(), |acc, x| acc + x);
            (subcounts, None)
        }
        // `pub` automatically
        EnumItem(Enum { variants: ref subitems, .. }) => {
            let subcounts = subitems.iter().map(summarize_item)
                                           .map(|s| s.val0())
                                           .fold(Counts::zero(), |acc, x| acc + x);
            (item_counts + subcounts, None)
        }
        TraitItem(Trait {
            items: ref trait_items,
            ..
        }) => {
            fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item {
                match *trait_item {
                    ProvidedMethod(ref item) |
                    RequiredMethod(ref item) |
                    TypeTraitItem(ref item) => item
                }
            }
            let subcounts = trait_items.iter()
                                       .map(extract_item)
                                       .map(summarize_item)
                                       .map(|s| s.val0())
                                       .fold(Counts::zero(), |acc, x| acc + x);
            (item_counts + subcounts, None)
        }
        ModuleItem(Module { ref items, .. }) => {
            let mut counts = item_counts;
            let mut submodules = Vec::new();

            for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
                                                      .map(summarize_item) {
                counts = counts + subcounts;
                submodule.map(|m| submodules.push(m));
            }
            submodules.sort();

            (counts, Some(ModuleSummary {
                name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
                counts: counts,
                submodules: submodules,
            }))
        }
        // no stability information for the following items:
        ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
        _ => (item_counts, None)
    }
}

/// Summarizes the stability levels in a crate.
pub fn build(krate: &Crate) -> ModuleSummary {
    match krate.module {
        None => ModuleSummary {
            name: krate.name.clone(),
            counts: Counts::zero(),
            submodules: Vec::new(),
        },
        Some(ref item) => ModuleSummary {
            name: krate.name.clone(), .. summarize_item(item).val1().unwrap()
        }
    }
}
<commit_msg>librustdoc: convert `Counts` binops to by value<commit_after>// Copyright 2014 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.

//! This module crawls a `clean::Crate` and produces a summarization of the
//! stability levels within the crate. The summary contains the module
//! hierarchy, with item counts for every stability level per module. A parent
//! module's count includes its children's.

use std::ops::Add;
use std::num::Zero;

use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
use syntax::ast::Public;

use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};

use html::render::cache;

#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
/// The counts for each stability level.
pub struct Counts {
    pub deprecated: uint,
    pub experimental: uint,
    pub unstable: uint,
    pub stable: uint,
    pub frozen: uint,
    pub locked: uint,

    /// No stability level, inherited or otherwise.
    pub unmarked: uint,
}

impl Copy for Counts {}

impl Add<Counts, Counts> for Counts {
    fn add(self, other: Counts) -> Counts {
        Counts {
            deprecated:   self.deprecated   + other.deprecated,
            experimental: self.experimental + other.experimental,
            unstable:     self.unstable     + other.unstable,
            stable:       self.stable       + other.stable,
            frozen:       self.frozen       + other.frozen,
            locked:       self.locked       + other.locked,
            unmarked:     self.unmarked     + other.unmarked,
        }
    }
}

impl Counts {
    fn zero() -> Counts {
        Counts {
            deprecated:   0,
            experimental: 0,
            unstable:     0,
            stable:       0,
            frozen:       0,
            locked:       0,
            unmarked:     0,
        }
    }

    pub fn total(&self) -> uint {
        self.deprecated + self.experimental + self.unstable + self.stable +
            self.frozen + self.locked + self.unmarked
    }
}

#[deriving(Encodable, Decodable, PartialEq, Eq)]
/// A summarized module, which includes total counts and summarized children
/// modules.
pub struct ModuleSummary {
    pub name: String,
    pub counts: Counts,
    pub submodules: Vec<ModuleSummary>,
}

impl PartialOrd for ModuleSummary {
    fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
        self.name.partial_cmp(&other.name)
    }
}

impl Ord for ModuleSummary {
    fn cmp(&self, other: &ModuleSummary) -> Ordering {
        self.name.cmp(&other.name)
    }
}

// is the item considered publically visible?
fn visible(item: &Item) -> bool {
    match item.inner {
        ImplItem(_) => true,
        _ => item.visibility == Some(Public)
    }
}

fn count_stability(stab: Option<&Stability>) -> Counts {
    match stab {
        None             => Counts { unmarked: 1,     .. Counts::zero() },
        Some(ref stab) => match stab.level {
            Deprecated   => Counts { deprecated: 1,   .. Counts::zero() },
            Experimental => Counts { experimental: 1, .. Counts::zero() },
            Unstable     => Counts { unstable: 1,     .. Counts::zero() },
            Stable       => Counts { stable: 1,       .. Counts::zero() },
            Frozen       => Counts { frozen: 1,       .. Counts::zero() },
            Locked       => Counts { locked: 1,       .. Counts::zero() },
        }
    }
}

fn summarize_methods(item: &Item) -> Counts {
    match cache().impls.get(&item.def_id) {
        Some(v) => {
            v.iter().map(|i| {
                let count = count_stability(i.stability.as_ref());
                if i.impl_.trait_.is_none() {
                    count + i.impl_.items.iter()
                        .map(|ti| summarize_item(ti).0)
                        .fold(Counts::zero(), |acc, c| acc + c)
                } else {
                    count
                }
            }).fold(Counts::zero(), |acc, c| acc + c)
        },
        None => {
            Counts::zero()
        },
    }
}

// Produce the summary for an arbitrary item. If the item is a module, include a
// module summary. The counts for items with nested items (e.g. modules, traits,
// impls) include all children counts.
fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
    let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);

    // Count this item's children, if any. Note that a trait impl is
    // considered to have no children.
    match item.inner {
        // Require explicit `pub` to be visible
        ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
            let subcounts = subitems.iter().filter(|i| visible(*i))
                                           .map(summarize_item)
                                           .map(|s| s.val0())
                                           .fold(Counts::zero(), |acc, x| acc + x);
            (subcounts, None)
        }
        // `pub` automatically
        EnumItem(Enum { variants: ref subitems, .. }) => {
            let subcounts = subitems.iter().map(summarize_item)
                                           .map(|s| s.val0())
                                           .fold(Counts::zero(), |acc, x| acc + x);
            (item_counts + subcounts, None)
        }
        TraitItem(Trait {
            items: ref trait_items,
            ..
        }) => {
            fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item {
                match *trait_item {
                    ProvidedMethod(ref item) |
                    RequiredMethod(ref item) |
                    TypeTraitItem(ref item) => item
                }
            }
            let subcounts = trait_items.iter()
                                       .map(extract_item)
                                       .map(summarize_item)
                                       .map(|s| s.val0())
                                       .fold(Counts::zero(), |acc, x| acc + x);
            (item_counts + subcounts, None)
        }
        ModuleItem(Module { ref items, .. }) => {
            let mut counts = item_counts;
            let mut submodules = Vec::new();

            for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
                                                      .map(summarize_item) {
                counts = counts + subcounts;
                submodule.map(|m| submodules.push(m));
            }
            submodules.sort();

            (counts, Some(ModuleSummary {
                name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
                counts: counts,
                submodules: submodules,
            }))
        }
        // no stability information for the following items:
        ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
        _ => (item_counts, None)
    }
}

/// Summarizes the stability levels in a crate.
pub fn build(krate: &Crate) -> ModuleSummary {
    match krate.module {
        None => ModuleSummary {
            name: krate.name.clone(),
            counts: Counts::zero(),
            submodules: Vec::new(),
        },
        Some(ref item) => ModuleSummary {
            name: krate.name.clone(), .. summarize_item(item).val1().unwrap()
        }
    }
}
<|endoftext|>


<commit_before>fn main(){
    let mut x = 5i;
    let z: int = 5i;
    x = 6i;
    println!("Hello, world = {:d}", x * z);

    let (a,b) = (1i, 1.0f64 / 3.0f64 );
    println!("a {:d} b {:f} {}", a, b, x);

    if x == 7i {
        println!("x == 6 integer");
    }

    let y: int = if x == 6i { 1i } else { 2i };
    println!("y == {}", y);
}
<commit_msg>fix formatting (breaking change)<commit_after>fn main(){
    let mut x: i32;
    let z: i32 = 5i32;
    x = 632;
    println!("Hello, world = {0}", x * z);

    let (a,b) = (1i32, 1.0f64 / 3.0f64 );
    println!("a {a} {b} {x}", a=a, b=b, x=x);

    if x == 732 {
        println!("x == 6 integer");
    }

    let y: i32 = if x == 632 { 1i32 } else { 2i32 };
    println!("y == x{0:X}", y);

    let q = 5us;
    println!("q {:08}", q);
}
<|endoftext|>


<commit_before>//! An example demonstrating sRGB color spaces.
//!
//! sRGB is one of those things that's a bit subtle, a bit obscure,
//! and easy to get wrong, but worth knowing because it crops up
//! from time to time and makes things mysteriously "look wrong" in
//! some cases.  It also is sort of overloaded to do two things at
//! once.  The first is what you will find [Wikipedia talking about](https://en.wikipedia.org/wiki/Srgb),
//! which is "how do you prove that 'green' on my monitor is the same
//! as 'green' on your monitor?".  That part we can safely ignore,
//! since it's a job for your monitor manufacturer.
//!
//! The other part is [gamma
//! correction](https://en.wikipedia.org/wiki/Gamma_correction) which
//! deals with the fact that the response of the human visual system
//! is non-linear, or in non-science talk, if you make a pixel twice
//! as bright, it doesn't *look* twice as bright.  To make something
//! *look* twice as bright, you have to make it about 2^2.2 times
//! brighter.  The exact math for how to fiddle the numbers to make
//! things Look Nice is defined as part of the sRGB standard, so often
//! a color scheme that complies with this gamma correction process is
//! just called "sRGB".
//!
//! In a perfect world, we don't ever have to worry about this.
//! Images are generally all stored in the sRGB color space (or
//! something similar to it), monitors all display in the sRGB color
//! space, and our graphics drivers know how to do whatever is
//! necessary to make the two line up.  The problem comes because we
//! are programmers, and have to be able to poke things instead of
//! just using pre-loaded assets.  So the question is: if you do
//! `Color::new(0.5, 0.0, 0.0, 1.0)` and `Color::new(1.0, 0.0, 0.0, 1.0)`,
//! will the second color LOOK twice as bright as the first one?
//!
//! So we have to know what color space we are talking about when we
//! say `Color`!  Are we talking about linear, "real" color where your
//! pixel puts out twice as many photons for the second color as the
//! first?  Or are we talking about sRGB color, where the pixel
//! actually LOOKS twice as bright?  And if we want to, say, write a
//! shader that does math to these colors, AND to colors that come
//! from images that use the sRGB color space, how do we make sure
//! everything matches?  To make it even worse, the sRGB conversion
//! done by graphics drivers is toggle-able, and can be set on a
//! per-render-target or per-texture basis, so it's possible for
//! things to get REAL mixed up in subtle ways.
//!
//! The Right Answer, as far as I know, is this: All colors that a
//! human specifies or touches are sRGB-encoded, so a number that is
//! twice as big then .  We do our color math in shaders, and (if we
//! set our render target to be an sRGB texture, which ggez always
//! does) the graphics driver will turn the linear colors we specify
//! into sRGB colors.  So if we do `vec4 x = vec4(0.25, 0.0, 0.0, 1.0);`,
//! assigning one pixel `x` and another `x * 2` will make the
//! second one *look* twice as bright as the first.
//!
//! BUT, this process also has to be done on INPUT as well; if we pass
//! the shader a value taken from an image file, that image file is in
//! sRGB color.  The graphics driver must THEN convert the sRGB color into
//! a linear color when passing it to the shader, so that if we get the
//! color and call it `x`, assigning one output pixel `x` and another
//! `x * 2` again makes the second one LOOK twice as bright as the first.
//! Then it converts the value back on the way out.
//!
//! ggez should handle all of this for you.  `graphics::Color` is
//! explicitly a sRGB-corrected color, all textures including the
//! final render target are sRGB-enabled, and when you provide
//! a linear color to something like `graphics::Mesh` it turns it
//! into sRGB for you to match everything else.  The purpose of this
//! example is to show that this actually *works* correctly!

use ggez;
use ggez::event;
use ggez::graphics::{self, DrawParam};
use ggez::nalgebra as na;
use ggez::{Context, GameResult};

/// This is a nice aqua test color that will look a lot brighter
/// than it should if we mess something up.
/// See https://github.com/ggez/ggez/issues/209 for examples.
const AQUA: graphics::Color = graphics::Color::new(0.0078, 0.7647, 0.6039, 1.0);

struct MainState {
    demo_mesh: graphics::Mesh,
    square_mesh: graphics::Mesh,
    demo_image: graphics::Image,
    demo_text: graphics::Text,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let demo_mesh = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            na::Point2::new(0.0, 0.0),
            100.0,
            2.0,
            AQUA,
        )?;
        let square_mesh = graphics::Mesh::new_rectangle(
            ctx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(0.0, 0.0, 400.0, 400.0),
            graphics::WHITE,
        )?;
        let demo_image = graphics::Image::solid(ctx, 200, AQUA)?;
        let demo_text = graphics::Text::new(graphics::TextFragment {
            text: "-".to_string(),
            color: Some(AQUA),
            font: Some(graphics::Font::default()),
            scale: Some(graphics::Scale::uniform(300.0)),
        });

        let s = MainState {
            demo_mesh,
            square_mesh,
            demo_image,
            demo_text,
        };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, AQUA);

        // Draw a white square so we can see things
        graphics::draw(
            ctx,
            &self.square_mesh,
            DrawParam::default().dest(na::Point2::new(200.0, 100.0)),
        )?;

        // Draw things partially over the white square so we can see
        // where they are; they SHOULD be the same color as the
        // background.
        graphics::draw(
            ctx,
            &self.demo_mesh,
            DrawParam::default().dest(na::Point2::new(150.0, 200.0)),
        )?;

        graphics::draw(
            ctx,
            &self.demo_image,
            DrawParam::default().dest(na::Point2::new(450.0, 200.0)),
        )?;

        graphics::draw(
            ctx,
            &self.demo_text,
            DrawParam::default().dest(na::Point2::new(150.0, 135.0)),
        )?;

        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    use std::env;
    use std::path;
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("super_simple", "ggez").add_resource_path(resource_dir);
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}
<commit_msg>Add spritebatch to the colorspace example<commit_after>//! An example demonstrating sRGB color spaces.
//!
//! sRGB is one of those things that's a bit subtle, a bit obscure,
//! and easy to get wrong, but worth knowing because it crops up
//! from time to time and makes things mysteriously "look wrong" in
//! some cases.  It also is sort of overloaded to do two things at
//! once.  The first is what you will find [Wikipedia talking about](https://en.wikipedia.org/wiki/Srgb),
//! which is "how do you prove that 'green' on my monitor is the same
//! as 'green' on your monitor?".  That part we can safely ignore,
//! since it's a job for your monitor manufacturer.
//!
//! The other part is [gamma
//! correction](https://en.wikipedia.org/wiki/Gamma_correction) which
//! deals with the fact that the response of the human visual system
//! is non-linear, or in non-science talk, if you make a pixel twice
//! as bright, it doesn't *look* twice as bright.  To make something
//! *look* twice as bright, you have to make it about 2^2.2 times
//! brighter.  The exact math for how to fiddle the numbers to make
//! things Look Nice is defined as part of the sRGB standard, so often
//! a color scheme that complies with this gamma correction process is
//! just called "sRGB".
//!
//! In a perfect world, we don't ever have to worry about this.
//! Images are generally all stored in the sRGB color space (or
//! something similar to it), monitors all display in the sRGB color
//! space, and our graphics drivers know how to do whatever is
//! necessary to make the two line up.  The problem comes because we
//! are programmers, and have to be able to poke things instead of
//! just using pre-loaded assets.  So the question is: if you do
//! `Color::new(0.5, 0.0, 0.0, 1.0)` and `Color::new(1.0, 0.0, 0.0, 1.0)`,
//! will the second color LOOK twice as bright as the first one?
//!
//! So we have to know what color space we are talking about when we
//! say `Color`!  Are we talking about linear, "real" color where your
//! pixel puts out twice as many photons for the second color as the
//! first?  Or are we talking about sRGB color, where the pixel
//! actually LOOKS twice as bright?  And if we want to, say, write a
//! shader that does math to these colors, AND to colors that come
//! from images that use the sRGB color space, how do we make sure
//! everything matches?  To make it even worse, the sRGB conversion
//! done by graphics drivers is toggle-able, and can be set on a
//! per-render-target or per-texture basis, so it's possible for
//! things to get REAL mixed up in subtle ways.
//!
//! The Right Answer, as far as I know, is this: All colors that a
//! human specifies or touches are sRGB-encoded, so a number that is
//! twice as big then .  We do our color math in shaders, and (if we
//! set our render target to be an sRGB texture, which ggez always
//! does) the graphics driver will turn the linear colors we specify
//! into sRGB colors.  So if we do `vec4 x = vec4(0.25, 0.0, 0.0, 1.0);`,
//! assigning one pixel `x` and another `x * 2` will make the
//! second one *look* twice as bright as the first.
//!
//! BUT, this process also has to be done on INPUT as well; if we pass
//! the shader a value taken from an image file, that image file is in
//! sRGB color.  The graphics driver must THEN convert the sRGB color into
//! a linear color when passing it to the shader, so that if we get the
//! color and call it `x`, assigning one output pixel `x` and another
//! `x * 2` again makes the second one LOOK twice as bright as the first.
//! Then it converts the value back on the way out.
//!
//! ggez should handle all of this for you.  `graphics::Color` is
//! explicitly a sRGB-corrected color, all textures including the
//! final render target are sRGB-enabled, and when you provide
//! a linear color to something like `graphics::Mesh` it turns it
//! into sRGB for you to match everything else.  The purpose of this
//! example is to show that this actually *works* correctly!

use ggez;
use ggez::event;
use ggez::graphics::{self, DrawParam};
use ggez::nalgebra as na;
use ggez::{Context, GameResult};

/// This is a nice aqua test color that will look a lot brighter
/// than it should if we mess something up.
/// See https://github.com/ggez/ggez/issues/209 for examples.
const AQUA: graphics::Color = graphics::Color::new(0.0078, 0.7647, 0.6039, 1.0);

struct MainState {
    demo_mesh: graphics::Mesh,
    square_mesh: graphics::Mesh,
    demo_image: graphics::Image,
    demo_text: graphics::Text,
    demo_spritebatch: graphics::spritebatch::SpriteBatch,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let demo_mesh = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            na::Point2::new(0.0, 0.0),
            100.0,
            2.0,
            AQUA,
        )?;
        let square_mesh = graphics::Mesh::new_rectangle(
            ctx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(0.0, 0.0, 400.0, 400.0),
            graphics::WHITE,
        )?;
        let demo_image = graphics::Image::solid(ctx, 200, AQUA)?;
        let demo_text = graphics::Text::new(graphics::TextFragment {
            text: "-".to_string(),
            color: Some(AQUA),
            font: Some(graphics::Font::default()),
            scale: Some(graphics::Scale::uniform(300.0)),
        });
        let demo_spritebatch = graphics::spritebatch::SpriteBatch::new(demo_image.clone());

        let s = MainState {
            demo_mesh,
            square_mesh,
            demo_image,
            demo_text,
            demo_spritebatch
        };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, AQUA);

        // Draw a white square so we can see things
        graphics::draw(
            ctx,
            &self.square_mesh,
            DrawParam::default().dest(na::Point2::new(200.0, 100.0)),
        )?;

        // Draw things partially over the white square so we can see
        // where they are; they SHOULD be the same color as the
        // background.

        // mesh
        graphics::draw(
            ctx,
            &self.demo_mesh,
            DrawParam::default().dest(na::Point2::new(150.0, 200.0)),
        )?;

        // image
        graphics::draw(
            ctx,
            &self.demo_image,
            DrawParam::default().dest(na::Point2::new(450.0, 200.0)),
        )?;

        // text
        graphics::draw(
            ctx,
            &self.demo_text,
            DrawParam::default().dest(na::Point2::new(150.0, 135.0)),
        )?;

        // spritebatch
        self.demo_spritebatch.add(
            DrawParam::default()
                .dest(na::Point2::new(250.0, 350.0))
                .scale(na::Vector2::new(0.25, 0.25))
        );
        self.demo_spritebatch.add(
            DrawParam::default()
                .dest(na::Point2::new(250.0, 425.0))
                .scale(na::Vector2::new(0.1, 0.1))
        );
        graphics::draw(
            ctx,
            &self.demo_spritebatch,
            DrawParam::default().dest(na::Point2::new(0.0, 0.0)),
        )?;
        self.demo_spritebatch.clear();

        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    use std::env;
    use std::path;
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("super_simple", "ggez").add_resource_path(resource_dir);
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}
<|endoftext|>


<commit_before>#![allow(unused_mut)]
// Bug in the compiler with Arc/Mutex references.

extern crate iron;
extern crate http;
extern crate persistent;

use std::io::net::ip::Ipv4Addr;
use persistent::Persistent;
use http::status;
use iron::{Request, Response, Alloy, Iron, Server, Chain, Status, Continue, FromFn};
use iron::mixin::Serve;

pub struct HitCounter;

fn hit_counter(_: &mut Request, _: &mut Response, alloy: &mut Alloy) -> Status {
    // Bug in the compiler
    let mut count = alloy.find::<Persistent<uint, HitCounter>>().unwrap().data.write();
    *count += 1;
    println!("{} hits!", *count);
    Continue
}

fn serve_hits(_: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
    let mut count = alloy.find::<Persistent<uint, HitCounter>>().unwrap().data.read();
    let _ = res.serve(status::Ok, format!("{} hits!", *count).as_slice());
    Continue
}

fn main() {
    let mut server: Server = Iron::new();
    let counter: Persistent<uint, HitCounter> = Persistent::new(0u);
    server.chain.link(counter);
    server.chain.link(FromFn::new(hit_counter));
    server.chain.link(FromFn::new(serve_hits));
    server.listen(Ipv4Addr(127, 0, 0, 1), 3001);
}

<commit_msg>(fix) Removed use of mixin.<commit_after>#![allow(unused_mut)]
// Bug in the compiler with Arc/Mutex references.

extern crate iron;
extern crate http;
extern crate persistent;

use std::io::net::ip::Ipv4Addr;
use persistent::Persistent;
use http::status;
use iron::{Request, Response, Alloy, Iron, Server, Chain, Status, Continue, FromFn};

pub struct HitCounter;

fn hit_counter(_: &mut Request, _: &mut Response, alloy: &mut Alloy) -> Status {
    // Bug in the compiler
    let mut count = alloy.find::<Persistent<uint, HitCounter>>().unwrap().data.write();
    *count += 1;
    println!("{} hits!", *count);
    Continue
}

fn serve_hits(_: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
    let mut count = alloy.find::<Persistent<uint, HitCounter>>().unwrap().data.read();
    let _ = res.serve(status::Ok, format!("{} hits!", *count));
    Continue
}

fn main() {
    let mut server: Server = Iron::new();
    let counter: Persistent<uint, HitCounter> = Persistent::new(0u);
    server.chain.link(counter);
    server.chain.link(FromFn::new(hit_counter));
    server.chain.link(FromFn::new(serve_hits));
    server.listen(Ipv4Addr(127, 0, 0, 1), 3001);
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::{Arc, mpsc};

use objects::Update;
use command::Command;
use bot::Bot;

/// A `Dispatcher` which will receive updates from the `Updater` and dispatches
/// them to the registered handlers.
///
/// You can add your command and message handlers to the `Dispatcher`.
pub struct Dispatcher {
    command_handlers: HashMap<String, (Box<Command>, bool)>,
    message_handlers: Vec<Box<Command>>,
}

impl Dispatcher {
    /// Constructs a new `Dispatcher`.
    pub fn new() -> Self {
        debug!("Going to construct a new Dispatcher...");
        Dispatcher {
            command_handlers: HashMap::new(),
            message_handlers: Vec::new(),
        }
    }

    /// Add a function which implements the `Command` trait to the `Dispatcher.command_handlers`.
    pub fn add_command_handler<C: Command>(&mut self, command_name: &str, command: C, args: bool) {
        self.command_handlers
            .insert(command_name.to_string(), (Box::new(command), args));
    }

    /// Add a function which implements the `Command` trait to the `Dispatcher.message_handlers`.
    pub fn add_message_handler<C: Command>(&mut self, command: C) {
        self.message_handlers.push(Box::new(command));
    }

    /// Starts the update handling process and dispatches all the updates to the assigned handlers.
    pub fn start_handling(&mut self, rx: mpsc::Receiver<Update>, bot: Arc<Bot>) {
        debug!("Going to start dispatcher thread...");
        loop {
            let update = rx.recv().unwrap();

            if let Some(t) = update.clone().message.and_then(|t| t.text) {
                if t.starts_with("/") {
                    let msg = t.split_whitespace().collect::<Vec<&str>>();
                    let (_, bot_command) = msg[0].split_at(1);
                    let name_command = bot_command.split("@").collect::<Vec<&str>>();

                    if name_command.len() == 1 ||
                       name_command.len() == 2 && name_command[1] == bot.username {
                        let command = self.command_handlers.get_mut(name_command[0]);

                        if let Some(c) = command {
                            debug!("Going to execute the {} command...", name_command[0]);
                            if c.1 {
                                let args = msg.clone().split_off(1);
                                debug!("With these arguments: {:?}", args);
                                c.0.execute(&bot, update, Some(args));
                            } else {
                                c.0.execute(&bot, update, None);
                            }
                            continue;
                        }
                    }
                }
            }
            for message_handler in self.message_handlers.iter_mut() {
                message_handler.execute(&bot, update.clone(), None);
            }
        }
    }
}
<commit_msg>Adding debug log for message handler.<commit_after>use std::collections::HashMap;
use std::sync::{Arc, mpsc};

use objects::Update;
use command::Command;
use bot::Bot;

/// A `Dispatcher` which will receive updates from the `Updater` and dispatches
/// them to the registered handlers.
///
/// You can add your command and message handlers to the `Dispatcher`.
pub struct Dispatcher {
    command_handlers: HashMap<String, (Box<Command>, bool)>,
    message_handlers: Vec<Box<Command>>,
}

impl Dispatcher {
    /// Constructs a new `Dispatcher`.
    pub fn new() -> Self {
        debug!("Going to construct a new Dispatcher...");
        Dispatcher {
            command_handlers: HashMap::new(),
            message_handlers: Vec::new(),
        }
    }

    /// Add a function which implements the `Command` trait to the `Dispatcher.command_handlers`.
    pub fn add_command_handler<C: Command>(&mut self, command_name: &str, command: C, args: bool) {
        self.command_handlers
            .insert(command_name.to_string(), (Box::new(command), args));
    }

    /// Add a function which implements the `Command` trait to the `Dispatcher.message_handlers`.
    pub fn add_message_handler<C: Command>(&mut self, command: C) {
        self.message_handlers.push(Box::new(command));
    }

    /// Starts the update handling process and dispatches all the updates to the assigned handlers.
    pub fn start_handling(&mut self, rx: mpsc::Receiver<Update>, bot: Arc<Bot>) {
        debug!("Going to start dispatcher thread...");
        loop {
            let update = rx.recv().unwrap();

            if let Some(t) = update.clone().message.and_then(|t| t.text) {
                if t.starts_with("/") {
                    let msg = t.split_whitespace().collect::<Vec<&str>>();
                    let (_, bot_command) = msg[0].split_at(1);
                    let name_command = bot_command.split("@").collect::<Vec<&str>>();

                    if name_command.len() == 1 ||
                       name_command.len() == 2 && name_command[1] == bot.username {
                        let command = self.command_handlers.get_mut(name_command[0]);

                        if let Some(c) = command {
                            debug!("Going to execute the {} command...", name_command[0]);
                            if c.1 {
                                let args = msg.clone().split_off(1);
                                debug!("With these arguments: {:?}", args);
                                c.0.execute(&bot, update, Some(args));
                            } else {
                                c.0.execute(&bot, update, None);
                            }
                            continue;
                        }
                    }
                }
            }
            for message_handler in self.message_handlers.iter_mut() {
                debug!("Going to execute a message handler...");
                message_handler.execute(&bot, update.clone(), None);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! client and server support for the varlink protocol

extern crate bytes;
extern crate itertools;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

extern crate varlink_parser;

pub mod generator;

use serde_json::Value;
use serde::ser::Serialize;

use std::convert::From;
use std::collections::HashMap;
use std::borrow::Cow;
use std::io::{self, BufRead, BufReader, Error, ErrorKind, Read, Write};

pub trait Interface {
    fn get_description(&self) -> &'static str;
    fn get_name(&self) -> &'static str;
    fn call(&self, &mut Call) -> io::Result<()>;
    fn call_upgraded(&self, &mut Call) -> io::Result<()>;
}

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Request {
    pub more: Option<bool>,
    pub oneshot: Option<bool>,
    pub upgrade: Option<bool>,
    pub method: Cow<'static, str>,
    pub parameters: Option<Value>,
}

pub trait VarlinkReply {}

#[derive(Serialize, Deserialize)]
pub struct Reply {
    continues: Option<bool>,
    upgraded: Option<bool>,
    error: Option<Cow<'static, str>>,
    parameters: Option<Value>,
}

impl Reply {
    pub fn parameters(parameters: Value) -> Self {
        Reply {
            continues: None,
            upgraded: None,
            error: None,
            parameters: Some(parameters),
        }
    }

    pub fn error(name: Cow<'static, str>, parameters: Option<Value>) -> Self {
        Reply {
            continues: None,
            upgraded: None,
            error: Some(name),
            parameters,
        }
    }
}

impl<T> From<T> for Reply
where
    T: VarlinkReply + Serialize,
{
    fn from(a: T) -> Self {
        Reply::parameters(serde_json::to_value(a).unwrap())
    }
}

pub struct Call<'a> {
    writer: &'a mut Write,
    pub request: Option<&'a Request>,
    pub continues: bool,
    pub upgraded: bool,
}

pub trait CallTrait {
    fn reply_struct(&mut self, Reply) -> io::Result<()>;
}

impl<'a> CallTrait for Call<'a> {
    fn reply_struct(&mut self, mut reply: Reply) -> io::Result<()> {
        if self.continues && !self.wants_more() {
            return Err(Error::new(
                ErrorKind::Other,
                "Call::reply() called with continues, but without more in the request",
            ));
        }
        if self.continues {
            reply.continues = Some(true);
        }
        let mut buf = serde_json::to_vec(&reply)?;
        buf.push(0);
        self.writer.write_all(&mut buf)?;
        self.writer.flush()?;
        Ok(())
    }
}

impl<'a> Call<'a> {
    fn new(writer: &'a mut Write, request: &'a Request) -> Self {
        Call {
            writer,
            request: Some(request),
            continues: false,
            upgraded: false,
        }
    }
    fn new_upgraded(writer: &'a mut Write) -> Self {
        Call {
            writer,
            request: None,
            continues: false,
            upgraded: false,
        }
    }
    pub fn is_oneshot(&self) -> bool {
        match self.request {
            Some(req) => {
                if let Some(val) = req.oneshot {
                    val
                } else {
                    false
                }
            }
            None => false,
        }
    }

    pub fn wants_more(&self) -> bool {
        match self.request {
            Some(req) => if let Some(val) = req.more {
                val
            } else {
                false
            },
            None => false,
        }
    }

    fn reply_interface_not_found(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.InterfaceNotFound".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"interface\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    pub fn reply_method_not_found(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.MethodNotFound".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"method\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    pub fn reply_method_not_implemented(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.MethodNotImplemented".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"method\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    pub fn reply_invalid_parameter(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.InvalidParameter".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"parameter\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    fn reply_parameters(&mut self, parameters: Value) -> io::Result<()> {
        let reply = Reply::parameters(parameters);
        let mut buf = serde_json::to_vec(&reply)?;
        buf.push(0);
        self.writer.write_all(&mut buf)?;
        self.writer.flush()?;
        Ok(())
    }
}

#[derive(Deserialize)]
struct GetInterfaceArgs {
    interface: Cow<'static, str>,
}

#[derive(Serialize, Deserialize)]
struct ServiceInfo {
    vendor: Cow<'static, str>,
    product: Cow<'static, str>,
    version: Cow<'static, str>,
    url: Cow<'static, str>,
    interfaces: Vec<Cow<'static, str>>,
}

pub struct VarlinkService {
    info: ServiceInfo,
    ifaces: HashMap<Cow<'static, str>, Box<Interface + Send + Sync>>,
}

impl Interface for VarlinkService {
    fn get_description(&self) -> &'static str {
        r#"
# The Varlink Service Interface is provided by every varlink service. It
# describes the service and the interfaces it implements.
interface org.varlink.service

# Get a list of all the interfaces a service provides and information
# about the implementation.
method GetInfo() -> (
  vendor: string,
  product: string,
  version: string,
  url: string,
  interfaces: string[]
)

# Get the description of an interface that is implemented by this service.
method GetInterfaceDescription(interface: string) -> (description: string)

# The requested interface was not found.
error InterfaceNotFound (interface: string)

# The requested method was not found
error MethodNotFound (method: string)

# The interface defines the requested method, but the service does not
# implement it.
error MethodNotImplemented (method: string)

# One of the passed parameters is invalid.
error InvalidParameter (parameter: string)
	"#
    }

    fn get_name(&self) -> &'static str {
        "org.varlink.service"
    }

    fn call(&self, call: &mut Call) -> io::Result<()> {
        let req = call.request.unwrap();
        match req.method.as_ref() {
            "org.varlink.service.GetInfo" => {
                return call.reply_parameters(serde_json::to_value(&self.info)?);
            }
            "org.varlink.service.GetInterfaceDescription" => {
                if req.parameters == None {
                    return call.reply_invalid_parameter(None);
                }
                if let Some(val) = req.parameters.clone() {
                    let args: GetInterfaceArgs = serde_json::from_value(val)?;
                    match args.interface.as_ref() {
                        "org.varlink.service" => {
                            return call.reply_parameters(
                                json!({"description": self.get_description()}),
                            );
                        }
                        key => {
                            if self.ifaces.contains_key(key) {
                                return call.reply_parameters(
                                    json!({"description": self.ifaces[key].get_description()}),
                                );
                            } else {
                                return call.reply_invalid_parameter(Some("interface".into()));
                            }
                        }
                    }
                } else {
                    return call.reply_invalid_parameter(Some("interface".into()));
                }
            }
            _ => {
                let method: String = req.method.clone().into();
                let n: usize = match method.rfind('.') {
                    None => 0,
                    Some(x) => x + 1,
                };
                let m = String::from(&method[n..]);
                return call.reply_method_not_found(Some(m.into()));
            }
        }
    }
    fn call_upgraded(&self, call: &mut Call) -> io::Result<()> {
        call.upgraded = false;
        Ok(())
    }
}

impl VarlinkService {
    pub fn new(
        vendor: &str,
        product: &str,
        version: &str,
        url: &str,
        ifaces: Vec<Box<Interface + Send + Sync>>,
    ) -> Self {
        let mut ifhashmap = HashMap::<Cow<'static, str>, Box<Interface + Send + Sync>>::new();
        for i in ifaces {
            ifhashmap.insert(i.get_name().into(), i);
        }
        let mut ifnames: Vec<Cow<'static, str>> = Vec::new();
        ifnames.push("org.varlink.service".into());
        ifnames.extend(
            ifhashmap
                .keys()
                .map(|i| Cow::<'static, str>::from(i.clone())),
        );
        VarlinkService {
            info: ServiceInfo {
                vendor: String::from(vendor).into(),
                product: String::from(product).into(),
                version: String::from(version).into(),
                url: String::from(url).into(),
                interfaces: ifnames,
            },
            ifaces: ifhashmap,
        }
    }

    fn call(&self, iface: String, call: &mut Call) -> io::Result<()> {
        match iface.as_ref() {
            "org.varlink.service" => return self::Interface::call(self, call),
            key => {
                if self.ifaces.contains_key(key) {
                    return self.ifaces[key].call(call);
                } else {
                    return call.reply_interface_not_found(Some(iface.clone().into()));
                }
            }
        }
    }

    fn call_upgraded(&self, iface: String, call: &mut Call) -> io::Result<()> {
        match iface.as_ref() {
            "org.varlink.service" => return self::Interface::call_upgraded(self, call),
            key => {
                if self.ifaces.contains_key(key) {
                    return self.ifaces[key].call_upgraded(call);
                } else {
                    return call.reply_interface_not_found(Some(iface.clone().into()));
                }
            }
        }
    }

    pub fn handle(&self, reader: &mut Read, writer: &mut Write) -> io::Result<()> {
        let mut bufreader = BufReader::new(reader);
        let mut upgraded = false;
        let mut last_iface = String::from("");
        loop {
            if !upgraded {
                let mut buf = Vec::new();
                let read_bytes = bufreader.read_until(b'\0', &mut buf)?;
                if read_bytes > 0 {
                    buf.pop();
                    let req: Request = serde_json::from_slice(&buf)?;
                    let mut call = Call::new(writer, &req);

                    let n: usize = match req.method.rfind('.') {
                        None => {
                            let method = req.method.clone();
                            return call.reply_interface_not_found(Some(method.into()));
                        }
                        Some(x) => x,
                    };

                    let iface = String::from(&req.method[..n]);

                    self.call(iface.clone(), &mut call)?;
                    upgraded = call.upgraded;
                    if upgraded {
                        last_iface = iface;
                    }
                } else {
                    break;
                }
            } else {
                let mut call = Call::new_upgraded(writer);
                self.call_upgraded(last_iface.clone(), &mut call)?;
                upgraded = call.upgraded;
            }
        }
        Ok(())
    }
}
<commit_msg>lib.rs: move error methods to CallTrait<commit_after>//! client and server support for the varlink protocol

extern crate bytes;
extern crate itertools;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

extern crate varlink_parser;

pub mod generator;

use serde_json::Value;
use serde::ser::Serialize;

use std::convert::From;
use std::collections::HashMap;
use std::borrow::Cow;
use std::io::{self, BufRead, BufReader, Error, ErrorKind, Read, Write};

pub trait Interface {
    fn get_description(&self) -> &'static str;
    fn get_name(&self) -> &'static str;
    fn call(&self, &mut Call) -> io::Result<()>;
    fn call_upgraded(&self, &mut Call) -> io::Result<()>;
}

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Request {
    pub more: Option<bool>,
    pub oneshot: Option<bool>,
    pub upgrade: Option<bool>,
    pub method: Cow<'static, str>,
    pub parameters: Option<Value>,
}

pub trait VarlinkReply {}

#[derive(Serialize, Deserialize)]
pub struct Reply {
    continues: Option<bool>,
    upgraded: Option<bool>,
    error: Option<Cow<'static, str>>,
    parameters: Option<Value>,
}

impl Reply {
    pub fn parameters(parameters: Value) -> Self {
        Reply {
            continues: None,
            upgraded: None,
            error: None,
            parameters: Some(parameters),
        }
    }

    pub fn error(name: Cow<'static, str>, parameters: Option<Value>) -> Self {
        Reply {
            continues: None,
            upgraded: None,
            error: Some(name),
            parameters,
        }
    }
}

impl<T> From<T> for Reply
where
    T: VarlinkReply + Serialize,
{
    fn from(a: T) -> Self {
        Reply::parameters(serde_json::to_value(a).unwrap())
    }
}

pub struct Call<'a> {
    writer: &'a mut Write,
    pub request: Option<&'a Request>,
    pub continues: bool,
    pub upgraded: bool,
}

pub trait CallTrait {
    fn reply_struct(&mut self, Reply) -> io::Result<()>;

    fn reply_method_not_found(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.MethodNotFound".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"method\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    fn reply_method_not_implemented(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.MethodNotImplemented".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"method\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    fn reply_invalid_parameter(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.InvalidParameter".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"parameter\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }
}

impl<'a> CallTrait for Call<'a> {
    fn reply_struct(&mut self, mut reply: Reply) -> io::Result<()> {
        if self.continues && !self.wants_more() {
            return Err(Error::new(
                ErrorKind::Other,
                "Call::reply() called with continues, but without more in the request",
            ));
        }
        if self.continues {
            reply.continues = Some(true);
        }
        let mut buf = serde_json::to_vec(&reply)?;
        buf.push(0);
        self.writer.write_all(&mut buf)?;
        self.writer.flush()?;
        Ok(())
    }
}

impl<'a> Call<'a> {
    fn new(writer: &'a mut Write, request: &'a Request) -> Self {
        Call {
            writer,
            request: Some(request),
            continues: false,
            upgraded: false,
        }
    }
    fn new_upgraded(writer: &'a mut Write) -> Self {
        Call {
            writer,
            request: None,
            continues: false,
            upgraded: false,
        }
    }
    pub fn is_oneshot(&self) -> bool {
        match self.request {
            Some(req) => {
                if let Some(val) = req.oneshot {
                    val
                } else {
                    false
                }
            }
            None => false,
        }
    }

    pub fn wants_more(&self) -> bool {
        match self.request {
            Some(req) => if let Some(val) = req.more {
                val
            } else {
                false
            },
            None => false,
        }
    }

    fn reply_interface_not_found(&mut self, arg: Option<String>) -> io::Result<()> {
        self.reply_struct(Reply::error(
            "org.varlink.service.InterfaceNotFound".into(),
            match arg {
                Some(a) => {
                    let s = format!("{{  \"interface\" : \"{}\" }}", a);
                    Some(serde_json::from_str(s.as_ref()).unwrap())
                }
                None => None,
            },
        ))
    }

    fn reply_parameters(&mut self, parameters: Value) -> io::Result<()> {
        let reply = Reply::parameters(parameters);
        let mut buf = serde_json::to_vec(&reply)?;
        buf.push(0);
        self.writer.write_all(&mut buf)?;
        self.writer.flush()?;
        Ok(())
    }
}

#[derive(Deserialize)]
struct GetInterfaceArgs {
    interface: Cow<'static, str>,
}

#[derive(Serialize, Deserialize)]
struct ServiceInfo {
    vendor: Cow<'static, str>,
    product: Cow<'static, str>,
    version: Cow<'static, str>,
    url: Cow<'static, str>,
    interfaces: Vec<Cow<'static, str>>,
}

pub struct VarlinkService {
    info: ServiceInfo,
    ifaces: HashMap<Cow<'static, str>, Box<Interface + Send + Sync>>,
}

impl Interface for VarlinkService {
    fn get_description(&self) -> &'static str {
        r#"
# The Varlink Service Interface is provided by every varlink service. It
# describes the service and the interfaces it implements.
interface org.varlink.service

# Get a list of all the interfaces a service provides and information
# about the implementation.
method GetInfo() -> (
  vendor: string,
  product: string,
  version: string,
  url: string,
  interfaces: string[]
)

# Get the description of an interface that is implemented by this service.
method GetInterfaceDescription(interface: string) -> (description: string)

# The requested interface was not found.
error InterfaceNotFound (interface: string)

# The requested method was not found
error MethodNotFound (method: string)

# The interface defines the requested method, but the service does not
# implement it.
error MethodNotImplemented (method: string)

# One of the passed parameters is invalid.
error InvalidParameter (parameter: string)
	"#
    }

    fn get_name(&self) -> &'static str {
        "org.varlink.service"
    }

    fn call(&self, call: &mut Call) -> io::Result<()> {
        let req = call.request.unwrap();
        match req.method.as_ref() {
            "org.varlink.service.GetInfo" => {
                return call.reply_parameters(serde_json::to_value(&self.info)?);
            }
            "org.varlink.service.GetInterfaceDescription" => {
                if req.parameters == None {
                    return call.reply_invalid_parameter(None);
                }
                if let Some(val) = req.parameters.clone() {
                    let args: GetInterfaceArgs = serde_json::from_value(val)?;
                    match args.interface.as_ref() {
                        "org.varlink.service" => {
                            return call.reply_parameters(
                                json!({"description": self.get_description()}),
                            );
                        }
                        key => {
                            if self.ifaces.contains_key(key) {
                                return call.reply_parameters(
                                    json!({"description": self.ifaces[key].get_description()}),
                                );
                            } else {
                                return call.reply_invalid_parameter(Some("interface".into()));
                            }
                        }
                    }
                } else {
                    return call.reply_invalid_parameter(Some("interface".into()));
                }
            }
            _ => {
                let method: String = req.method.clone().into();
                let n: usize = match method.rfind('.') {
                    None => 0,
                    Some(x) => x + 1,
                };
                let m = String::from(&method[n..]);
                return call.reply_method_not_found(Some(m.into()));
            }
        }
    }
    fn call_upgraded(&self, call: &mut Call) -> io::Result<()> {
        call.upgraded = false;
        Ok(())
    }
}

impl VarlinkService {
    pub fn new(
        vendor: &str,
        product: &str,
        version: &str,
        url: &str,
        ifaces: Vec<Box<Interface + Send + Sync>>,
    ) -> Self {
        let mut ifhashmap = HashMap::<Cow<'static, str>, Box<Interface + Send + Sync>>::new();
        for i in ifaces {
            ifhashmap.insert(i.get_name().into(), i);
        }
        let mut ifnames: Vec<Cow<'static, str>> = Vec::new();
        ifnames.push("org.varlink.service".into());
        ifnames.extend(
            ifhashmap
                .keys()
                .map(|i| Cow::<'static, str>::from(i.clone())),
        );
        VarlinkService {
            info: ServiceInfo {
                vendor: String::from(vendor).into(),
                product: String::from(product).into(),
                version: String::from(version).into(),
                url: String::from(url).into(),
                interfaces: ifnames,
            },
            ifaces: ifhashmap,
        }
    }

    fn call(&self, iface: String, call: &mut Call) -> io::Result<()> {
        match iface.as_ref() {
            "org.varlink.service" => return self::Interface::call(self, call),
            key => {
                if self.ifaces.contains_key(key) {
                    return self.ifaces[key].call(call);
                } else {
                    return call.reply_interface_not_found(Some(iface.clone().into()));
                }
            }
        }
    }

    fn call_upgraded(&self, iface: String, call: &mut Call) -> io::Result<()> {
        match iface.as_ref() {
            "org.varlink.service" => return self::Interface::call_upgraded(self, call),
            key => {
                if self.ifaces.contains_key(key) {
                    return self.ifaces[key].call_upgraded(call);
                } else {
                    return call.reply_interface_not_found(Some(iface.clone().into()));
                }
            }
        }
    }

    pub fn handle(&self, reader: &mut Read, writer: &mut Write) -> io::Result<()> {
        let mut bufreader = BufReader::new(reader);
        let mut upgraded = false;
        let mut last_iface = String::from("");
        loop {
            if !upgraded {
                let mut buf = Vec::new();
                let read_bytes = bufreader.read_until(b'\0', &mut buf)?;
                if read_bytes > 0 {
                    buf.pop();
                    let req: Request = serde_json::from_slice(&buf)?;
                    let mut call = Call::new(writer, &req);

                    let n: usize = match req.method.rfind('.') {
                        None => {
                            let method = req.method.clone();
                            return call.reply_interface_not_found(Some(method.into()));
                        }
                        Some(x) => x,
                    };

                    let iface = String::from(&req.method[..n]);

                    self.call(iface.clone(), &mut call)?;
                    upgraded = call.upgraded;
                    if upgraded {
                        last_iface = iface;
                    }
                } else {
                    break;
                }
            } else {
                let mut call = Call::new_upgraded(writer);
                self.call_upgraded(last_iface.clone(), &mut call)?;
                upgraded = call.upgraded;
            }
        }
        Ok(())
    }
}
<|endoftext|>