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

use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty;
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::{Name, UintTy};
use crate::utils::{
    contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability,
    span_lint_and_sugg, walk_ptrs_ty,
};
use if_chain::if_chain;

/// **What it does:** Checks for naive byte counts
///
/// **Why is this bad?** The [`bytecount`](https://crates.io/crates/bytecount)
/// crate has methods to count your bytes faster, especially for large slices.
///
/// **Known problems:** If you have predominantly small slices, the
/// `bytecount::count(..)` method may actually be slower. However, if you can
/// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
/// faster in those cases.
///
/// **Example:**
///
/// ```rust
/// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead
/// ```
declare_clippy_lint! {
    pub NAIVE_BYTECOUNT,
    perf,
    "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values"
}

#[derive(Copy, Clone)]
pub struct ByteCount;

impl LintPass for ByteCount {
    fn get_lints(&self) -> LintArray {
        lint_array!(NAIVE_BYTECOUNT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
        if_chain! {
            if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node;
            if count.ident.name == "count";
            if count_args.len() == 1;
            if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node;
            if filter.ident.name == "filter";
            if filter_args.len() == 2;
            if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node;
            then {
                let body = cx.tcx.hir.body(body_id);
                if_chain! {
                    if body.arguments.len() == 1;
                    if let Some(argname) = get_pat_name(&body.arguments[0].pat);
                    if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node;
                    if op.node == BinOpKind::Eq;
                    if match_type(cx,
                               walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])),
                               &paths::SLICE_ITER);
                    then {
                        let needle = match get_path_name(l) {
                            Some(name) if check_arg(name, argname, r) => r,
                            _ => match get_path_name(r) {
                                Some(name) if check_arg(name, argname, l) => l,
                                _ => { return; }
                            }
                        };
                        if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty {
                            return;
                        }
                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
                                filter_args[0].node {
                            let p = path.ident.name;
                            if (p == "iter" || p == "iter_mut") && args.len() == 1 {
                                &args[0]
                            } else {
                                &filter_args[0]
                            }
                        } else {
                            &filter_args[0]
                        };
                        let mut applicability = Applicability::MachineApplicable;
                        span_lint_and_sugg(
                            cx,
                            NAIVE_BYTECOUNT,
                            expr.span,
                            "You appear to be counting bytes the naive way",
                            "Consider using the bytecount crate",
                            format!("bytecount::count({}, {})",
                                    snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
                                    snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
                            Applicability::Unspecified,
                        );
                    }
                };
            }
        };
    }
}

fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool {
    name == arg && !contains_name(name, needle)
}

fn get_path_name(expr: &Expr) -> Option<Name> {
    match expr.node {
        ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => get_path_name(e),
        ExprKind::Block(ref b, _) => if b.stmts.is_empty() {
            b.expr.as_ref().and_then(|p| get_path_name(p))
        } else {
            None
        },
        ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
        _ => None,
    }
}
<commit_msg>Fix NAIVE_BYTECOUNT applicability<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty;
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::{Name, UintTy};
use crate::utils::{
    contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability,
    span_lint_and_sugg, walk_ptrs_ty,
};
use if_chain::if_chain;

/// **What it does:** Checks for naive byte counts
///
/// **Why is this bad?** The [`bytecount`](https://crates.io/crates/bytecount)
/// crate has methods to count your bytes faster, especially for large slices.
///
/// **Known problems:** If you have predominantly small slices, the
/// `bytecount::count(..)` method may actually be slower. However, if you can
/// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
/// faster in those cases.
///
/// **Example:**
///
/// ```rust
/// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead
/// ```
declare_clippy_lint! {
    pub NAIVE_BYTECOUNT,
    perf,
    "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values"
}

#[derive(Copy, Clone)]
pub struct ByteCount;

impl LintPass for ByteCount {
    fn get_lints(&self) -> LintArray {
        lint_array!(NAIVE_BYTECOUNT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
        if_chain! {
            if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node;
            if count.ident.name == "count";
            if count_args.len() == 1;
            if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node;
            if filter.ident.name == "filter";
            if filter_args.len() == 2;
            if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node;
            then {
                let body = cx.tcx.hir.body(body_id);
                if_chain! {
                    if body.arguments.len() == 1;
                    if let Some(argname) = get_pat_name(&body.arguments[0].pat);
                    if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node;
                    if op.node == BinOpKind::Eq;
                    if match_type(cx,
                               walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])),
                               &paths::SLICE_ITER);
                    then {
                        let needle = match get_path_name(l) {
                            Some(name) if check_arg(name, argname, r) => r,
                            _ => match get_path_name(r) {
                                Some(name) if check_arg(name, argname, l) => l,
                                _ => { return; }
                            }
                        };
                        if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty {
                            return;
                        }
                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
                                filter_args[0].node {
                            let p = path.ident.name;
                            if (p == "iter" || p == "iter_mut") && args.len() == 1 {
                                &args[0]
                            } else {
                                &filter_args[0]
                            }
                        } else {
                            &filter_args[0]
                        };
                        let mut applicability = Applicability::MachineApplicable;
                        span_lint_and_sugg(
                            cx,
                            NAIVE_BYTECOUNT,
                            expr.span,
                            "You appear to be counting bytes the naive way",
                            "Consider using the bytecount crate",
                            format!("bytecount::count({}, {})",
                                    snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
                                    snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
                            applicability,
                        );
                    }
                };
            }
        };
    }
}

fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool {
    name == arg && !contains_name(name, needle)
}

fn get_path_name(expr: &Expr) -> Option<Name> {
    match expr.node {
        ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => get_path_name(e),
        ExprKind::Block(ref b, _) => if b.stmts.is_empty() {
            b.expr.as_ref().and_then(|p| get_path_name(p))
        } else {
            None
        },
        ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
        _ => None,
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

#[macro_use]
mod macros;
mod download;
mod idle;
mod install;
mod park;
mod poll;
mod probe;
mod reboot;
mod transition;

use Result;

use self::{
    download::Download, idle::Idle, install::Install, park::Park, poll::Poll, probe::Probe,
    reboot::Reboot,
};

use firmware::Metadata;
use runtime_settings::RuntimeSettings;
use settings::Settings;

trait StateChangeImpl {
    fn handle(self) -> Result<StateMachine>;
}

trait TransitionCallback: Into<State<Idle>> {
    fn callback_state_name(&self) -> &'static str;
}

#[derive(Debug, PartialEq)]
struct State<S>
where
    State<S>: StateChangeImpl,
{
    settings: Settings,
    runtime_settings: RuntimeSettings,
    firmware: Metadata,
    state: S,
}

#[derive(Debug, PartialEq)]
enum StateMachine {
    Park(State<Park>),
    Idle(State<Idle>),
    Poll(State<Poll>),
    Probe(State<Probe>),
    Download(State<Download>),
    Install(State<Install>),
    Reboot(State<Reboot>),
}

impl<S> State<S>
where
    State<S>: TransitionCallback + StateChangeImpl,
{
    fn handle_with_callback(self) -> Result<StateMachine> {
        use states::transition::{state_change_callback, Transition};

        let transition = state_change_callback(
            &self.settings.firmware.metadata_path,
            self.callback_state_name(),
        )?;

        match transition {
            Transition::Continue => Ok(self.handle()?),
            Transition::Cancel => Ok(StateMachine::Idle(self.into())),
        }
    }
}

impl StateMachine {
    fn new(settings: Settings, runtime_settings: RuntimeSettings, firmware: Metadata) -> Self {
        StateMachine::Idle(State {
            settings,
            runtime_settings,
            firmware,
            state: Idle {},
        })
    }

    fn move_to_next_state(self) -> Result<Self> {
        match self {
            StateMachine::Park(s) => Ok(s.handle()?),
            StateMachine::Idle(s) => Ok(s.handle()?),
            StateMachine::Poll(s) => Ok(s.handle()?),
            StateMachine::Probe(s) => Ok(s.handle()?),
            StateMachine::Download(s) => Ok(s.handle_with_callback()?),
            StateMachine::Install(s) => Ok(s.handle_with_callback()?),
            StateMachine::Reboot(s) => Ok(s.handle_with_callback()?),
        }
    }
}

/// Runs the state machine up to completion handling all procing
/// states without extra manual work.
///
/// It supports following states, and transitions, as shown in the
/// below diagram:
///
/// ```text
///           .--------------.
///           |              v
/// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot
///           ^      ^        '          '          '
///           '      '        '          '          '
///           '      `--------'          '          '
///           `---------------'          '          '
///           `--------------------------'          '
///           `-------------------------------------'
/// ```
///
/// # Example
/// ```
/// # extern crate failure;
/// # extern crate updatehub;
/// # use failure;
/// # fn run() -> Result<(), failure::Error> {
/// use updatehub;
///
/// let settings = updatehub::Settings::load()?;
/// updatehub::run(settings)?;
/// # Ok(())
/// # }
/// ```
pub fn run(settings: Settings) -> Result<()> {
    let runtime_settings = RuntimeSettings::new().load(&settings.storage.runtime_settings)?;
    let firmware = Metadata::new(&settings.firmware.metadata_path)?;

    let mut machine = StateMachine::new(settings, runtime_settings, firmware);
    loop {
        machine = match machine.move_to_next_state()? {
            StateMachine::Park(_) => {
                debug!("Parking state machine.");
                return Ok(());
            }
            s => s,
        }
    }
}
<commit_msg>states: Rework `run` for easier reading<commit_after>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

#[macro_use]
mod macros;
mod download;
mod idle;
mod install;
mod park;
mod poll;
mod probe;
mod reboot;
mod transition;

use Result;

use self::{
    download::Download, idle::Idle, install::Install, park::Park, poll::Poll, probe::Probe,
    reboot::Reboot,
};

use firmware::Metadata;
use runtime_settings::RuntimeSettings;
use settings::Settings;

trait StateChangeImpl {
    fn handle(self) -> Result<StateMachine>;
}

trait TransitionCallback: Into<State<Idle>> {
    fn callback_state_name(&self) -> &'static str;
}

#[derive(Debug, PartialEq)]
struct State<S>
where
    State<S>: StateChangeImpl,
{
    settings: Settings,
    runtime_settings: RuntimeSettings,
    firmware: Metadata,
    state: S,
}

#[derive(Debug, PartialEq)]
enum StateMachine {
    Park(State<Park>),
    Idle(State<Idle>),
    Poll(State<Poll>),
    Probe(State<Probe>),
    Download(State<Download>),
    Install(State<Install>),
    Reboot(State<Reboot>),
}

impl<S> State<S>
where
    State<S>: TransitionCallback + StateChangeImpl,
{
    fn handle_with_callback(self) -> Result<StateMachine> {
        use states::transition::{state_change_callback, Transition};

        let transition = state_change_callback(
            &self.settings.firmware.metadata_path,
            self.callback_state_name(),
        )?;

        match transition {
            Transition::Continue => Ok(self.handle()?),
            Transition::Cancel => Ok(StateMachine::Idle(self.into())),
        }
    }
}

impl StateMachine {
    fn new(settings: Settings, runtime_settings: RuntimeSettings, firmware: Metadata) -> Self {
        StateMachine::Idle(State {
            settings,
            runtime_settings,
            firmware,
            state: Idle {},
        })
    }

    fn move_to_next_state(self) -> Result<Self> {
        match self {
            StateMachine::Park(s) => Ok(s.handle()?),
            StateMachine::Idle(s) => Ok(s.handle()?),
            StateMachine::Poll(s) => Ok(s.handle()?),
            StateMachine::Probe(s) => Ok(s.handle()?),
            StateMachine::Download(s) => Ok(s.handle_with_callback()?),
            StateMachine::Install(s) => Ok(s.handle_with_callback()?),
            StateMachine::Reboot(s) => Ok(s.handle_with_callback()?),
        }
    }
}

/// Runs the state machine up to completion handling all procing
/// states without extra manual work.
///
/// It supports following states, and transitions, as shown in the
/// below diagram:
///
/// ```text
///           .--------------.
///           |              v
/// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot
///           ^      ^        '          '          '
///           '      '        '          '          '
///           '      `--------'          '          '
///           `---------------'          '          '
///           `--------------------------'          '
///           `-------------------------------------'
/// ```
///
/// # Example
/// ```
/// # extern crate failure;
/// # extern crate updatehub;
/// # use failure;
/// # fn run() -> Result<(), failure::Error> {
/// use updatehub;
///
/// let settings = updatehub::Settings::load()?;
/// updatehub::run(settings)?;
/// # Ok(())
/// # }
/// ```
pub fn run(settings: Settings) -> Result<()> {
    let runtime_settings = RuntimeSettings::new().load(&settings.storage.runtime_settings)?;
    let firmware = Metadata::new(&settings.firmware.metadata_path)?;
    let mut machine = StateMachine::new(settings, runtime_settings, firmware);

    // Iterate over the state machine.
    loop {
        machine = match machine.move_to_next_state()? {
            StateMachine::Park(_) => {
                debug!("Parking state machine.");
                return Ok(());
            }
            s => s,
        }
    }
}
<|endoftext|>


<commit_before>fn give_princess(gift: &str) {
    // Princesses hate snakes, so we need to stop if
    // she expresses her disapproval!
    if gift == "snake" { panic!("AAAaaaaa!!!!"); }

    println!("I love {}s!!!!!", gift);
}

fn main() {
    give_princess("teddy bear");
    give_princess("snake");
}
<commit_msg>Removed code from chapter intro<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// gpio_status.rs
//
// Retrieves the mode and logic level for each of the pins on the standard
// 40-pin GPIO header, and displays the results in an ASCII table.

use std::fmt;
use std::process::exit;

use rppal::gpio::Gpio;
use rppal::system::{DeviceInfo, Model};

enum PinType {
    Gpio(u8),
    Ground,
    Power3v3,
    Power5v,
}

impl fmt::Display for PinType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            PinType::Gpio(pin) => write!(f, "GPIO{}", pin),
            PinType::Ground => write!(f, "{:<5}", "GND"),
            PinType::Power3v3 => write!(f, "{:<5}", "3.3 V"),
            PinType::Power5v => write!(f, "{:<5}", "5 V"),
        }
    }
}

const HEADER_40: [PinType; 40] = [
    PinType::Power3v3, // Physical pin 1
    PinType::Power5v,  // Physical pin 2
    PinType::Gpio(2),  // Physical pin 3
    PinType::Power5v,  // Physical pin 4
    PinType::Gpio(3),  // Physical pin 5
    PinType::Ground,   // Physical pin 6
    PinType::Gpio(4),  // Physical pin 7
    PinType::Gpio(14), // Physical pin 8
    PinType::Ground,   // Physical pin 9
    PinType::Gpio(15), // Physical pin 10
    PinType::Gpio(17), // Physical pin 11
    PinType::Gpio(18), // Physical pin 12
    PinType::Gpio(27), // Physical pin 13
    PinType::Ground,   // Physical pin 14
    PinType::Gpio(22), // Physical pin 15
    PinType::Gpio(23), // Physical pin 16
    PinType::Power3v3, // Physical pin 17
    PinType::Gpio(24), // Physical pin 18
    PinType::Gpio(10), // Physical pin 19
    PinType::Ground,   // Physical pin 20
    PinType::Gpio(9),  // Physical pin 21
    PinType::Gpio(25), // Physical pin 22
    PinType::Gpio(11), // Physical pin 23
    PinType::Gpio(8),  // Physical pin 24
    PinType::Ground,   // Physical pin 25
    PinType::Gpio(7),  // Physical pin 26
    PinType::Gpio(0),  // Physical pin 27
    PinType::Gpio(1),  // Physical pin 28
    PinType::Gpio(5),  // Physical pin 29
    PinType::Ground,   // Physical pin 30
    PinType::Gpio(6),  // Physical pin 31
    PinType::Gpio(12), // Physical pin 32
    PinType::Gpio(13), // Physical pin 33
    PinType::Ground,   // Physical pin 34
    PinType::Gpio(19), // Physical pin 35
    PinType::Gpio(16), // Physical pin 36
    PinType::Gpio(26), // Physical pin 37
    PinType::Gpio(20), // Physical pin 38
    PinType::Ground,   // Physical pin 39
    PinType::Gpio(21), // Physical pin 40
];

fn print_pin(
    pin: usize,
    gpio: impl fmt::Display,
    mode: impl fmt::Display,
    level: impl fmt::Display,
) {
    if pin % 2 != 0 {
        print!("| {:>4} | {:<5} | {:>1} | {:>2} |", gpio, mode, level, pin);
    } else {
        println!(" {:>2} | {:>1} | {:<5} | {:>4} |", pin, level, mode, gpio);
    }
}

fn print_gpio_status() {
    let gpio = Gpio::new().unwrap_or_else(|e| {
        eprintln!("Error: Can't access GPIO peripheral ({})", e);
        exit(1);
    });

    println!("+------+-------+---+---------+---+-------+------+");
    println!("| GPIO | Mode  | L |   Pin   | L | Mode  | GPIO |");
    println!("+------+-------+---+----+----+---+-------+------+");

    for (idx, pin_type) in HEADER_40.iter().enumerate() {
        match pin_type {
            PinType::Gpio(bcm_gpio) => {
                let pin = gpio.get(*bcm_gpio).unwrap_or_else(|| {
                    eprintln!("Error: Can't access GPIO pin {}", *bcm_gpio);
                    exit(1);
                });

                print_pin(
                    idx + 1,
                    bcm_gpio,
                    format!("{}", pin.mode()).to_uppercase(),
                    pin.read() as u8,
                );
            }
            _ => print_pin(idx + 1, "", pin_type, ""),
        };
    }

    println!("+------+-------+---+----+----+---+-------+------+");
}

fn main() {
    match DeviceInfo::new()
        .unwrap_or_else(|e| {
            eprintln!("Error: Can't identify Raspberry Pi model ({})", e);
            exit(1);
        })
        .model()
    {
        Model::RaspberryPiAPlus
        | Model::RaspberryPiBPlus
        | Model::RaspberryPi2B
        | Model::RaspberryPi3APlus
        | Model::RaspberryPi3B
        | Model::RaspberryPi3BPlus
        | Model::RaspberryPiZero
        | Model::RaspberryPiZeroW => print_gpio_status(),
        model => {
            eprintln!("Error: No GPIO header information available for {}", model);
        }
    }
}
<commit_msg>Return exit code 1 for unknown GPIO headers<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// gpio_status.rs
//
// Retrieves the mode and logic level for each of the pins on the standard
// 40-pin GPIO header, and displays the results in an ASCII table.

use std::fmt;
use std::process::exit;

use rppal::gpio::Gpio;
use rppal::system::{DeviceInfo, Model};

enum PinType {
    Gpio(u8),
    Ground,
    Power3v3,
    Power5v,
}

impl fmt::Display for PinType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            PinType::Gpio(pin) => write!(f, "GPIO{}", pin),
            PinType::Ground => write!(f, "{:<5}", "GND"),
            PinType::Power3v3 => write!(f, "{:<5}", "3.3 V"),
            PinType::Power5v => write!(f, "{:<5}", "5 V"),
        }
    }
}

const HEADER_40: [PinType; 40] = [
    PinType::Power3v3, // Physical pin 1
    PinType::Power5v,  // Physical pin 2
    PinType::Gpio(2),  // Physical pin 3
    PinType::Power5v,  // Physical pin 4
    PinType::Gpio(3),  // Physical pin 5
    PinType::Ground,   // Physical pin 6
    PinType::Gpio(4),  // Physical pin 7
    PinType::Gpio(14), // Physical pin 8
    PinType::Ground,   // Physical pin 9
    PinType::Gpio(15), // Physical pin 10
    PinType::Gpio(17), // Physical pin 11
    PinType::Gpio(18), // Physical pin 12
    PinType::Gpio(27), // Physical pin 13
    PinType::Ground,   // Physical pin 14
    PinType::Gpio(22), // Physical pin 15
    PinType::Gpio(23), // Physical pin 16
    PinType::Power3v3, // Physical pin 17
    PinType::Gpio(24), // Physical pin 18
    PinType::Gpio(10), // Physical pin 19
    PinType::Ground,   // Physical pin 20
    PinType::Gpio(9),  // Physical pin 21
    PinType::Gpio(25), // Physical pin 22
    PinType::Gpio(11), // Physical pin 23
    PinType::Gpio(8),  // Physical pin 24
    PinType::Ground,   // Physical pin 25
    PinType::Gpio(7),  // Physical pin 26
    PinType::Gpio(0),  // Physical pin 27
    PinType::Gpio(1),  // Physical pin 28
    PinType::Gpio(5),  // Physical pin 29
    PinType::Ground,   // Physical pin 30
    PinType::Gpio(6),  // Physical pin 31
    PinType::Gpio(12), // Physical pin 32
    PinType::Gpio(13), // Physical pin 33
    PinType::Ground,   // Physical pin 34
    PinType::Gpio(19), // Physical pin 35
    PinType::Gpio(16), // Physical pin 36
    PinType::Gpio(26), // Physical pin 37
    PinType::Gpio(20), // Physical pin 38
    PinType::Ground,   // Physical pin 39
    PinType::Gpio(21), // Physical pin 40
];

fn print_pin(
    pin: usize,
    gpio: impl fmt::Display,
    mode: impl fmt::Display,
    level: impl fmt::Display,
) {
    if pin % 2 != 0 {
        print!("| {:>4} | {:<5} | {:>1} | {:>2} |", gpio, mode, level, pin);
    } else {
        println!(" {:>2} | {:>1} | {:<5} | {:>4} |", pin, level, mode, gpio);
    }
}

fn print_gpio_status() {
    let gpio = Gpio::new().unwrap_or_else(|e| {
        eprintln!("Error: Can't access GPIO peripheral ({})", e);
        exit(1);
    });

    println!("+------+-------+---+---------+---+-------+------+");
    println!("| GPIO | Mode  | L |   Pin   | L | Mode  | GPIO |");
    println!("+------+-------+---+----+----+---+-------+------+");

    for (idx, pin_type) in HEADER_40.iter().enumerate() {
        match pin_type {
            PinType::Gpio(bcm_gpio) => {
                let pin = gpio.get(*bcm_gpio).unwrap_or_else(|| {
                    eprintln!("Error: Can't access GPIO pin {}", *bcm_gpio);
                    exit(1);
                });

                print_pin(
                    idx + 1,
                    bcm_gpio,
                    format!("{}", pin.mode()).to_uppercase(),
                    pin.read() as u8,
                );
            }
            _ => print_pin(idx + 1, "", pin_type, ""),
        };
    }

    println!("+------+-------+---+----+----+---+-------+------+");
}

fn main() {
    match DeviceInfo::new()
        .unwrap_or_else(|e| {
            eprintln!("Error: Can't identify Raspberry Pi model ({})", e);
            exit(1);
        })
        .model()
    {
        Model::RaspberryPiAPlus
        | Model::RaspberryPiBPlus
        | Model::RaspberryPi2B
        | Model::RaspberryPi3APlus
        | Model::RaspberryPi3B
        | Model::RaspberryPi3BPlus
        | Model::RaspberryPiZero
        | Model::RaspberryPiZeroW => print_gpio_status(),
        model => {
            eprintln!("Error: No GPIO header information available for {}", model);
            exit(1);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// gpio_status.rs
//
// Retrieves the mode and logic level for each of the pins on the standard
// 40-pin GPIO header, and displays the results in an ASCII table.

use std::fmt;
use std::process::exit;

use rppal::gpio::Gpio;
use rppal::system::{DeviceInfo, Model};

enum PinType {
    Gpio(u8),
    Ground,
    Power3v3,
    Power5v,
}

impl fmt::Display for PinType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            PinType::Gpio(pin) => write!(f, "GPIO{}", pin),
            PinType::Ground => write!(f, "{:<5}", "GND"),
            PinType::Power3v3 => write!(f, "{:<5}", "3.3 V"),
            PinType::Power5v => write!(f, "{:<5}", "5 V"),
        }
    }
}

const HEADER_40: [PinType; 40] = [
    PinType::Power3v3, // Physical pin 1
    PinType::Power5v,  // Physical pin 2
    PinType::Gpio(2),  // Physical pin 3
    PinType::Power5v,  // Physical pin 4
    PinType::Gpio(3),  // Physical pin 5
    PinType::Ground,   // Physical pin 6
    PinType::Gpio(4),  // Physical pin 7
    PinType::Gpio(14), // Physical pin 8
    PinType::Ground,   // Physical pin 9
    PinType::Gpio(15), // Physical pin 10
    PinType::Gpio(17), // Physical pin 11
    PinType::Gpio(18), // Physical pin 12
    PinType::Gpio(27), // Physical pin 13
    PinType::Ground,   // Physical pin 14
    PinType::Gpio(22), // Physical pin 15
    PinType::Gpio(23), // Physical pin 16
    PinType::Power3v3, // Physical pin 17
    PinType::Gpio(24), // Physical pin 18
    PinType::Gpio(10), // Physical pin 19
    PinType::Ground,   // Physical pin 20
    PinType::Gpio(9),  // Physical pin 21
    PinType::Gpio(25), // Physical pin 22
    PinType::Gpio(11), // Physical pin 23
    PinType::Gpio(8),  // Physical pin 24
    PinType::Ground,   // Physical pin 25
    PinType::Gpio(7),  // Physical pin 26
    PinType::Gpio(0),  // Physical pin 27
    PinType::Gpio(1),  // Physical pin 28
    PinType::Gpio(5),  // Physical pin 29
    PinType::Ground,   // Physical pin 30
    PinType::Gpio(6),  // Physical pin 31
    PinType::Gpio(12), // Physical pin 32
    PinType::Gpio(13), // Physical pin 33
    PinType::Ground,   // Physical pin 34
    PinType::Gpio(19), // Physical pin 35
    PinType::Gpio(16), // Physical pin 36
    PinType::Gpio(26), // Physical pin 37
    PinType::Gpio(20), // Physical pin 38
    PinType::Ground,   // Physical pin 39
    PinType::Gpio(21), // Physical pin 40
];

fn print_pin(
    pin: usize,
    gpio: impl fmt::Display,
    mode: impl fmt::Display,
    level: impl fmt::Display,
) {
    if pin % 2 != 0 {
        print!("| {:>4} | {:<5} | {:>1} | {:>2} |", gpio, mode, level, pin);
    } else {
        println!(" {:>2} | {:>1} | {:<5} | {:>4} |", pin, level, mode, gpio);
    }
}

fn print_gpio_status() {
    let gpio = Gpio::new().unwrap_or_else(|e| {
        eprintln!("Error: Can't access GPIO peripheral ({})", e);
        exit(1);
    });

    println!("+------+-------+---+---------+---+-------+------+");
    println!("| GPIO | Mode  | L |   Pin   | L | Mode  | GPIO |");
    println!("+------+-------+---+----+----+---+-------+------+");

    for (idx, pin_type) in HEADER_40.iter().enumerate() {
        match pin_type {
            PinType::Gpio(bcm_gpio) => {
                let pin = gpio.get(*bcm_gpio).unwrap_or_else(|| {
                    eprintln!("Error: Can't access GPIO pin {}", *bcm_gpio);
                    exit(1);
                });

                print_pin(
                    idx + 1,
                    bcm_gpio,
                    format!("{}", pin.mode()).to_uppercase(),
                    pin.read() as u8,
                );
            }
            _ => print_pin(idx + 1, "", pin_type, ""),
        };
    }

    println!("+------+-------+---+----+----+---+-------+------+");
}

fn main() {
    match DeviceInfo::new()
        .unwrap_or_else(|e| {
            eprintln!("Error: Can't identify Raspberry Pi model ({})", e);
            exit(1);
        })
        .model()
    {
        Model::RaspberryPiAPlus
        | Model::RaspberryPiBPlus
        | Model::RaspberryPi2B
        | Model::RaspberryPi3APlus
        | Model::RaspberryPi3B
        | Model::RaspberryPi3BPlus
        | Model::RaspberryPiZero
        | Model::RaspberryPiZeroW => print_gpio_status(),
        model => {
            eprintln!("Error: No GPIO header information available for {}", model);
            exit(1);
        }
    }
}
<commit_msg>Buffer output<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// gpio_status.rs
//
// Retrieves the mode and logic level for each of the pins on the standard
// 40-pin GPIO header, and displays the results in an ASCII table.

use std::fmt;
use std::process::exit;

use rppal::gpio::Gpio;
use rppal::system::{DeviceInfo, Model};

enum PinType {
    Gpio(u8),
    Ground,
    Power3v3,
    Power5v,
}

impl fmt::Display for PinType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            PinType::Gpio(pin) => write!(f, "GPIO{}", pin),
            PinType::Ground => write!(f, "{:<5}", "GND"),
            PinType::Power3v3 => write!(f, "{:<5}", "3.3 V"),
            PinType::Power5v => write!(f, "{:<5}", "5 V"),
        }
    }
}

const HEADER_40: [PinType; 40] = [
    PinType::Power3v3, // Physical pin 1
    PinType::Power5v,  // Physical pin 2
    PinType::Gpio(2),  // Physical pin 3
    PinType::Power5v,  // Physical pin 4
    PinType::Gpio(3),  // Physical pin 5
    PinType::Ground,   // Physical pin 6
    PinType::Gpio(4),  // Physical pin 7
    PinType::Gpio(14), // Physical pin 8
    PinType::Ground,   // Physical pin 9
    PinType::Gpio(15), // Physical pin 10
    PinType::Gpio(17), // Physical pin 11
    PinType::Gpio(18), // Physical pin 12
    PinType::Gpio(27), // Physical pin 13
    PinType::Ground,   // Physical pin 14
    PinType::Gpio(22), // Physical pin 15
    PinType::Gpio(23), // Physical pin 16
    PinType::Power3v3, // Physical pin 17
    PinType::Gpio(24), // Physical pin 18
    PinType::Gpio(10), // Physical pin 19
    PinType::Ground,   // Physical pin 20
    PinType::Gpio(9),  // Physical pin 21
    PinType::Gpio(25), // Physical pin 22
    PinType::Gpio(11), // Physical pin 23
    PinType::Gpio(8),  // Physical pin 24
    PinType::Ground,   // Physical pin 25
    PinType::Gpio(7),  // Physical pin 26
    PinType::Gpio(0),  // Physical pin 27
    PinType::Gpio(1),  // Physical pin 28
    PinType::Gpio(5),  // Physical pin 29
    PinType::Ground,   // Physical pin 30
    PinType::Gpio(6),  // Physical pin 31
    PinType::Gpio(12), // Physical pin 32
    PinType::Gpio(13), // Physical pin 33
    PinType::Ground,   // Physical pin 34
    PinType::Gpio(19), // Physical pin 35
    PinType::Gpio(16), // Physical pin 36
    PinType::Gpio(26), // Physical pin 37
    PinType::Gpio(20), // Physical pin 38
    PinType::Ground,   // Physical pin 39
    PinType::Gpio(21), // Physical pin 40
];

fn format_pin(
    buffer: &mut impl fmt::Write,
    pin: usize,
    gpio: impl fmt::Display,
    mode: impl fmt::Display,
    level: impl fmt::Display,
) {
    if pin % 2 != 0 {
        write!(
            buffer,
            "| {:>4} | {:<5} | {:>1} | {:>2} |",
            gpio, mode, level, pin
        )
        .unwrap();
    } else {
        writeln!(
            buffer,
            " {:>2} | {:>1} | {:<5} | {:>4} |",
            pin, level, mode, gpio
        )
        .unwrap();
    }
}

fn print_gpio_status() {
    let gpio = Gpio::new().unwrap_or_else(|e| {
        eprintln!("Error: Can't access GPIO peripheral ({})", e);
        exit(1);
    });

    let mut buf = String::with_capacity(1600);

    buf.push_str("+------+-------+---+---------+---+-------+------+\n");
    buf.push_str("| GPIO | Mode  | L |   Pin   | L | Mode  | GPIO |\n");
    buf.push_str("+------+-------+---+----+----+---+-------+------+\n");

    for (idx, pin_type) in HEADER_40.iter().enumerate() {
        match pin_type {
            PinType::Gpio(bcm_gpio) => {
                let pin = gpio.get(*bcm_gpio).unwrap_or_else(|| {
                    eprintln!("Error: Can't access GPIO pin {}", *bcm_gpio);
                    exit(1);
                });

                format_pin(
                    &mut buf,
                    idx + 1,
                    bcm_gpio,
                    format!("{}", pin.mode()).to_uppercase(),
                    pin.read() as u8,
                );
            }
            _ => format_pin(&mut buf, idx + 1, "", pin_type, ""),
        };
    }

    buf.push_str("+------+-------+---+----+----+---+-------+------+\n");

    print!("{}", buf);
}

fn main() {
    match DeviceInfo::new()
        .unwrap_or_else(|e| {
            eprintln!("Error: Can't identify Raspberry Pi model ({})", e);
            exit(1);
        })
        .model()
    {
        Model::RaspberryPiAPlus
        | Model::RaspberryPiBPlus
        | Model::RaspberryPi2B
        | Model::RaspberryPi3APlus
        | Model::RaspberryPi3B
        | Model::RaspberryPi3BPlus
        | Model::RaspberryPiZero
        | Model::RaspberryPiZeroW => print_gpio_status(),
        model => {
            eprintln!("Error: No GPIO header information available for {}", model);
            exit(1);
        }
    }
}
<|endoftext|>


<commit_before>// This is a comment, and will be ignored by the compiler
// You can test this code by clicking the "Run" button over there ->
// or if prefer to use your keyboard, you can use the "Ctrl + Enter" shortcut

// This code is editable, feel free to hack it!
// You can always return to the original code by clicking the "Reset" button ->

// This is the main function
fn main() {
    // The statements here will be executed when the compiled binary is called

    // Print text to the console, 你好
    println!("Hello World!");
}
<commit_msg>translate hello.rs<commit_after>// 这是注释内容，编译器将忽略这些内容
// 你可以通过单击前面的按钮"Run"来测试这段代码 ->
// 若想用键盘操作，你可以使用快捷键"Ctrl + Enter"来运行

// 这段代码支持编辑，你可以自由地改进代码！
// 通过单击"Reset"按钮可以使代码恢复到原始的代码 ->

// 这是主函数
fn main() {
    // 当已编译成的可执行文件被调用时，这里面的语句将被执行

    // 打印文本到控制台
    println!("Hello World!");
}
<|endoftext|>


<commit_before>use integer::Integer;
use traits::{Zero, One};

use biguint::BigUint;

struct MontyReducer<'a> {
    p: &'a BigUint,
    n: Vec<u32>,
    n0inv: u32
}

// Calculate the modular inverse of `num`, using Extended GCD.
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20
fn inv_mod_u32(num: u32) -> u32 {
    // num needs to be relatively prime to 2**32 -- i.e. it must be odd.
    assert!(num % 2 != 0);

    let mut a: i64 = num as i64;
    let mut b: i64 = (u32::max_value() as i64) + 1;

    // ExtendedGcd
    // Input: positive integers a and b
    // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb
    // As we don't need v for modular inverse, we don't calculate it.

    // 1: (u, w) <- (1, 0)
    let mut u = 1;
    let mut w = 0;
    // 3: while b != 0
    while b != 0 {
        // 4: (q, r) <- DivRem(a, b)
        let q = a / b;
        let r = a % b;
        // 5: (a, b) <- (b, r)
        a = b; b = r;
        // 6: (u, w) <- (w, u - qw)
        let m = u - w*q;
        u = w; w = m;
    }

    assert!(a == 1);
    // Downcasting acts like a mod 2^32 too.
    u as u32
}

impl<'a> MontyReducer<'a> {
    fn new(p: &'a BigUint) -> Self {
        let n : Vec<u32> = p.data.clone();
        let n0inv = inv_mod_u32(n[0]);
        MontyReducer { p: p, n: n, n0inv: n0inv }
    }
}

// Montgomery Reduction
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6
fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint {
    let mut c = a.data;
    let n = &mr.n;
    let n_size = n.len();

    // Allocate sufficient work space
    c.resize(2 * n_size + 2, 0);

    // β is the size of a word, in this case 32 bits. So "a mod β" is
    // equivalent to masking a to 32 bits.
    let beta_mask = u32::max_value() as u64;
    // mu <- -N^(-1) mod β
    let mu = (beta_mask-mr.n0inv as u64)+1;

    // 1: for i = 0 to (n-1)
    for i in 0..n_size {
        // 2: q_i <- mu*c_i mod β
        let q_i = ((c[i] as u64) * mu) & beta_mask;

        // 3: C <- C + q_i * N * β^i
        super::algorithms::mac_digit(&mut c[i..], n, q_i as u32);
    }

    // 4: R <- C * β^(-n)
    // This is an n-word bitshift, equivalent to skipping n words.
    let r : Vec<u32> = c.iter().skip(n_size).cloned().collect();
    let ret = BigUint::new(r);

    // 5: if R >= β^n then return R-N else return R.
    if &ret < mr.p {
        ret
    } else {
        &ret-mr.p
    }
}

// Montgomery Multiplication
fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint {
    monty_redc(a * b, mr)
}

// Montgomery Squaring
fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint {
    // TODO: Replace with an optimised squaring function
    monty_redc(&a * &a, mr)
}

pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint{
    let mr = MontyReducer::new(modulus);

    // Calculate the Montgomery parameter
    let mut r : BigUint = One::one();
    while &r < mr.p {
        r = r << 32;
    }

    // Map the base to the Montgomery domain
    let mut apri = a * &r % mr.p;

    // Binary exponentiation
    let mut ans = &r % mr.p;
    let mut e = exp.clone();
    let zero = Zero::zero();
    while e > zero {
        if e.is_odd() {
            ans = monty_mult(ans, &apri, &mr);
        }
        apri = monty_sqr(apri, &mr);
        e = e >> 1;
    }

    // Map the result back to the residues domain
    monty_redc(ans, &mr)
}
<commit_msg>bigint::monty: simplify redc masks<commit_after>use integer::Integer;
use traits::{Zero, One};

use biguint::BigUint;

struct MontyReducer<'a> {
    p: &'a BigUint,
    n: Vec<u32>,
    n0inv: u32
}

// Calculate the modular inverse of `num`, using Extended GCD.
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20
fn inv_mod_u32(num: u32) -> u32 {
    // num needs to be relatively prime to 2**32 -- i.e. it must be odd.
    assert!(num % 2 != 0);

    let mut a: i64 = num as i64;
    let mut b: i64 = (u32::max_value() as i64) + 1;

    // ExtendedGcd
    // Input: positive integers a and b
    // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb
    // As we don't need v for modular inverse, we don't calculate it.

    // 1: (u, w) <- (1, 0)
    let mut u = 1;
    let mut w = 0;
    // 3: while b != 0
    while b != 0 {
        // 4: (q, r) <- DivRem(a, b)
        let q = a / b;
        let r = a % b;
        // 5: (a, b) <- (b, r)
        a = b; b = r;
        // 6: (u, w) <- (w, u - qw)
        let m = u - w*q;
        u = w; w = m;
    }

    assert!(a == 1);
    // Downcasting acts like a mod 2^32 too.
    u as u32
}

impl<'a> MontyReducer<'a> {
    fn new(p: &'a BigUint) -> Self {
        let n : Vec<u32> = p.data.clone();
        let n0inv = inv_mod_u32(n[0]);
        MontyReducer { p: p, n: n, n0inv: n0inv }
    }
}

// Montgomery Reduction
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6
fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint {
    let mut c = a.data;
    let n = &mr.n;
    let n_size = n.len();

    // Allocate sufficient work space
    c.resize(2 * n_size + 2, 0);

    // β is the size of a word, in this case 32 bits. So "a mod β" is
    // equivalent to masking a to 32 bits.
    // mu <- -N^(-1) mod β
    let mu = 0u32.wrapping_sub(mr.n0inv);

    // 1: for i = 0 to (n-1)
    for i in 0..n_size {
        // 2: q_i <- mu*c_i mod β
        let q_i = c[i].wrapping_mul(mu);

        // 3: C <- C + q_i * N * β^i
        super::algorithms::mac_digit(&mut c[i..], n, q_i);
    }

    // 4: R <- C * β^(-n)
    // This is an n-word bitshift, equivalent to skipping n words.
    let r : Vec<u32> = c.iter().skip(n_size).cloned().collect();
    let ret = BigUint::new(r);

    // 5: if R >= β^n then return R-N else return R.
    if &ret < mr.p {
        ret
    } else {
        &ret-mr.p
    }
}

// Montgomery Multiplication
fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint {
    monty_redc(a * b, mr)
}

// Montgomery Squaring
fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint {
    // TODO: Replace with an optimised squaring function
    monty_redc(&a * &a, mr)
}

pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint{
    let mr = MontyReducer::new(modulus);

    // Calculate the Montgomery parameter
    let mut r : BigUint = One::one();
    while &r < mr.p {
        r = r << 32;
    }

    // Map the base to the Montgomery domain
    let mut apri = a * &r % mr.p;

    // Binary exponentiation
    let mut ans = &r % mr.p;
    let mut e = exp.clone();
    let zero = Zero::zero();
    while e > zero {
        if e.is_odd() {
            ans = monty_mult(ans, &apri, &mr);
        }
        apri = monty_sqr(apri, &mr);
        e = e >> 1;
    }

    // Map the result back to the residues domain
    monty_redc(ans, &mr)
}
<|endoftext|>


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

use devtools_traits::{CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERROR, CONSOLE_API};
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
use devtools_traits::{ConsoleAPI, PageError};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::js::Root;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers};
use dom::document::DocumentHelpers;
use page::{IterablePage, Page};
use msg::constellation_msg::PipelineId;
use script_task::{get_page, ScriptTask};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;

use std::sync::mpsc::Sender;
use std::rc::Rc;

pub fn handle_evaluate_js(page: &Rc<Page>, pipeline: PipelineId, eval: String, reply: Sender<EvaluateJSReply>){
    let page = get_page(&*page, pipeline);
    let window = page.window();
    let cx = window.r().get_cx();
    let mut rval = RootedValue::new(cx, UndefinedValue());
    window.r().evaluate_js_on_global_with_result(&eval, rval.handle_mut());

    reply.send(if rval.ptr.is_undefined() {
        EvaluateJSReply::VoidValue
    } else if rval.ptr.is_boolean() {
        EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
    } else if rval.ptr.is_double() {
        EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap())
    } else if rval.ptr.is_string() {
        //FIXME: use jsstring_to_str when jsval grows to_jsstring
        EvaluateJSReply::StringValue(
            FromJSValConvertible::from_jsval(cx, rval.handle(), StringificationBehavior::Default).unwrap())
    } else if rval.ptr.is_null() {
        EvaluateJSReply::NullValue
    } else {
        //FIXME: jsvals don't have an is_int32/is_number yet
        assert!(rval.ptr.is_object());
        panic!("object values unimplemented")
    }).unwrap();
}

pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();

    let node = NodeCast::from_ref(document.r());
    reply.send(node.summarize()).unwrap();
}

pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let document_element = document.r().GetDocumentElement().unwrap();

    let node = NodeCast::from_ref(document_element.r());
    reply.send(node.summarize()).unwrap();
}

fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Root<Node> {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let node = NodeCast::from_ref(document.r());

    for candidate in node.traverse_preorder() {
        if candidate.r().get_unique_id() == node_id {
            return candidate;
        }
    }

    panic!("couldn't find node with unique id {}", node_id)
}

pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
    let parent = find_node_by_unique_id(&*page, pipeline, node_id);
    let children = parent.r().children().map(|child| {
        child.r().summarize()
    }).collect();
    reply.send(children).unwrap();
}

pub fn handle_get_layout(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<(f32, f32)>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
    let rect = elem.GetBoundingClientRect();
    let width = *rect.r().Width();
    let height = *rect.r().Height();
    reply.send((width, height)).unwrap();
}

pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
                                  message_types: CachedConsoleMessageTypes,
                                  reply: Sender<Vec<CachedConsoleMessage>>) {
    //TODO: check the messageTypes against a global Cache for console messages and page exceptions
    let mut messages = Vec::new();
    if message_types.contains(PAGE_ERROR) {
        //TODO: make script error reporter pass all reported errors
        //      to devtools and cache them for returning here.
        let msg = PageError {
            _type: "PageError".to_owned(),
            errorMessage: "page error test".to_owned(),
            sourceName: String::new(),
            lineText: String::new(),
            lineNumber: 0,
            columnNumber: 0,
            category: String::new(),
            timeStamp: 0,
            error: false,
            warning: false,
            exception: false,
            strict: false,
            private: false,
        };
        messages.push(CachedConsoleMessage::PageError(msg));
    }
    if message_types.contains(CONSOLE_API) {
        //TODO: do for real
        let msg = ConsoleAPI {
            _type: "ConsoleAPI".to_owned(),
            level: "error".to_owned(),
            filename: "http://localhost/~mihai/mozilla/test.html".to_owned(),
            lineNumber: 0,
            functionName: String::new(),
            timeStamp: 0,
            private: false,
            arguments: vec!["console error test".to_owned()],
        };
        messages.push(CachedConsoleMessage::ConsoleAPI(msg));
    }
    reply.send(messages).unwrap();
}

pub fn handle_modify_attribute(page: &Rc<Page>,
                               pipeline: PipelineId,
                               node_id: String,
                               modifications: Vec<Modification>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");

    for modification in modifications.iter(){
        match modification.newValue {
            Some(ref string) => {
                let _ = elem.SetAttribute(modification.attributeName.clone(), string.clone());
            },
            None => elem.RemoveAttribute(modification.attributeName.clone()),
        }
    }
}

pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId, send_notifications: bool) {
    let page = get_page(&*page, pipeline_id);
    let window = page.window();
    window.r().set_devtools_wants_updates(send_notifications);
}

pub fn handle_set_timeline_markers(page: &Rc<Page>,
                                   script_task: &ScriptTask,
                                   marker_types: Vec<TimelineMarkerType>,
                                   reply: Sender<TimelineMarker>) {
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                let window = page.window();
                window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
            }
            TimelineMarkerType::DOMEvent => {
                script_task.set_devtools_timeline_marker(TimelineMarkerType::DOMEvent, reply.clone());
            }
        }
    }
}

pub fn handle_drop_timeline_markers(page: &Rc<Page>,
                                    script_task: &ScriptTask,
                                    marker_types: Vec<TimelineMarkerType>) {
    let window = page.window();
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                window.r().drop_devtools_timeline_markers();
            }
            TimelineMarkerType::DOMEvent => {
                script_task.drop_devtools_timeline_markers();
            }
        }
    }
}

pub fn handle_request_animation_frame(page: &Rc<Page>, id: PipelineId, callback: Box<Fn(f64, )>) {
    let page = page.find(id).expect("There is no such page");
    let doc = page.document();
    doc.r().request_animation_frame(callback);
}
<commit_msg>Eval'ing int32's in devtools panic'd<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use devtools_traits::{CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERROR, CONSOLE_API};
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
use devtools_traits::{ConsoleAPI, PageError};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::js::Root;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers};
use dom::document::DocumentHelpers;
use page::{IterablePage, Page};
use msg::constellation_msg::PipelineId;
use script_task::{get_page, ScriptTask};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;

use std::sync::mpsc::Sender;
use std::rc::Rc;

pub fn handle_evaluate_js(
        page: &Rc<Page>,
        pipeline: PipelineId,
        eval: String,
        reply: Sender<EvaluateJSReply>
    ) {
    let page = get_page(&*page, pipeline);
    let window = page.window();
    let cx = window.r().get_cx();
    let mut rval = RootedValue::new(cx, UndefinedValue());
    window.r().evaluate_js_on_global_with_result(&eval, rval.handle_mut());

    reply.send(if rval.ptr.is_undefined() {
        EvaluateJSReply::VoidValue
    } else if rval.ptr.is_boolean() {
        EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
    } else if rval.ptr.is_double() || rval.ptr.is_int32() {
        EvaluateJSReply::NumberValue(
            FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap()
        )
    } else if rval.ptr.is_string() {
        //FIXME: use jsstring_to_str when jsval grows to_jsstring
        EvaluateJSReply::StringValue(
            FromJSValConvertible::from_jsval(cx, rval.handle(), StringificationBehavior::Default).unwrap())
    } else if rval.ptr.is_null() {
        EvaluateJSReply::NullValue
    } else {
        //FIXME: jsvals don't have an is_int32/is_number yet
        assert!(rval.ptr.is_object());
        panic!("object values unimplemented")
    }).unwrap();
}

pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();

    let node = NodeCast::from_ref(document.r());
    reply.send(node.summarize()).unwrap();
}

pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let document_element = document.r().GetDocumentElement().unwrap();

    let node = NodeCast::from_ref(document_element.r());
    reply.send(node.summarize()).unwrap();
}

fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Root<Node> {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let node = NodeCast::from_ref(document.r());

    for candidate in node.traverse_preorder() {
        if candidate.r().get_unique_id() == node_id {
            return candidate;
        }
    }

    panic!("couldn't find node with unique id {}", node_id)
}

pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
    let parent = find_node_by_unique_id(&*page, pipeline, node_id);
    let children = parent.r().children().map(|child| {
        child.r().summarize()
    }).collect();
    reply.send(children).unwrap();
}

pub fn handle_get_layout(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<(f32, f32)>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
    let rect = elem.GetBoundingClientRect();
    let width = *rect.r().Width();
    let height = *rect.r().Height();
    reply.send((width, height)).unwrap();
}

pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
                                  message_types: CachedConsoleMessageTypes,
                                  reply: Sender<Vec<CachedConsoleMessage>>) {
    //TODO: check the messageTypes against a global Cache for console messages and page exceptions
    let mut messages = Vec::new();
    if message_types.contains(PAGE_ERROR) {
        //TODO: make script error reporter pass all reported errors
        //      to devtools and cache them for returning here.
        let msg = PageError {
            _type: "PageError".to_owned(),
            errorMessage: "page error test".to_owned(),
            sourceName: String::new(),
            lineText: String::new(),
            lineNumber: 0,
            columnNumber: 0,
            category: String::new(),
            timeStamp: 0,
            error: false,
            warning: false,
            exception: false,
            strict: false,
            private: false,
        };
        messages.push(CachedConsoleMessage::PageError(msg));
    }
    if message_types.contains(CONSOLE_API) {
        //TODO: do for real
        let msg = ConsoleAPI {
            _type: "ConsoleAPI".to_owned(),
            level: "error".to_owned(),
            filename: "http://localhost/~mihai/mozilla/test.html".to_owned(),
            lineNumber: 0,
            functionName: String::new(),
            timeStamp: 0,
            private: false,
            arguments: vec!["console error test".to_owned()],
        };
        messages.push(CachedConsoleMessage::ConsoleAPI(msg));
    }
    reply.send(messages).unwrap();
}

pub fn handle_modify_attribute(page: &Rc<Page>,
                               pipeline: PipelineId,
                               node_id: String,
                               modifications: Vec<Modification>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");

    for modification in modifications.iter(){
        match modification.newValue {
            Some(ref string) => {
                let _ = elem.SetAttribute(modification.attributeName.clone(), string.clone());
            },
            None => elem.RemoveAttribute(modification.attributeName.clone()),
        }
    }
}

pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId, send_notifications: bool) {
    let page = get_page(&*page, pipeline_id);
    let window = page.window();
    window.r().set_devtools_wants_updates(send_notifications);
}

pub fn handle_set_timeline_markers(page: &Rc<Page>,
                                   script_task: &ScriptTask,
                                   marker_types: Vec<TimelineMarkerType>,
                                   reply: Sender<TimelineMarker>) {
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                let window = page.window();
                window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
            }
            TimelineMarkerType::DOMEvent => {
                script_task.set_devtools_timeline_marker(TimelineMarkerType::DOMEvent, reply.clone());
            }
        }
    }
}

pub fn handle_drop_timeline_markers(page: &Rc<Page>,
                                    script_task: &ScriptTask,
                                    marker_types: Vec<TimelineMarkerType>) {
    let window = page.window();
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                window.r().drop_devtools_timeline_markers();
            }
            TimelineMarkerType::DOMEvent => {
                script_task.drop_devtools_timeline_markers();
            }
        }
    }
}

pub fn handle_request_animation_frame(page: &Rc<Page>, id: PipelineId, callback: Box<Fn(f64, )>) {
    let page = page.find(id).expect("There is no such page");
    let doc = page.document();
    doc.r().request_animation_frame(callback);
}
<|endoftext|>


<commit_before>extern crate libc;

use x11::xlib::Window;
use x11::xlib;

const CWX: libc::c_uint = 1<<0;
const CWY: libc::c_uint = 1<<1;
const CWWidth: libc::c_uint = 1<<2;
const CWHeight: libc::c_uint = 1<<3;
const CWBorderWidth: libc::c_uint = 1<<4;
const CWSibling: libc::c_uint =	1<<5;
const CWStackMode: libc::c_uint = 1<<6;

pub trait Layout {
    fn configure(&self, windows: &[Window], display: *mut xlib::Display,screen_num: libc::c_int);
    fn toggle(&mut self) {}
    fn get_type(&self) -> Type;
}

pub enum Direction {
    Vertical,
    Horizontal,
}

#[derive(PartialEq)]
pub enum Type {
    Tiling,
}

pub struct TilingLayout {
    direction: Direction,
}

impl TilingLayout {
    pub fn new(d: Direction) -> TilingLayout{
        TilingLayout {
            direction: d,
        }
    }
}

impl Layout for TilingLayout {
    fn get_type(&self) -> Type { Type::Tiling }
    fn toggle(&mut self) {
        match self.direction {
            Direction::Vertical => self.direction = Direction::Horizontal,
            Direction::Horizontal => self.direction = Direction::Vertical,
        }
    }
    /// once we add or remove a window, we need to reconfig
    fn configure(&self, windows: &[Window], display: *mut xlib::Display,screen_num: libc::c_int,) {
        let size = windows.len();
        if size == 0 {
            return;
        }

        unsafe {
            let screen_height = xlib::XDisplayHeight(display, screen_num);
            let screen_width = xlib::XDisplayWidth(display, screen_num);
            let mask = CWX | CWY | CWHeight | CWWidth;

            let width = screen_width  / size as libc::c_int;
            let height = screen_height / size as libc::c_int;

            for (i, w) in windows.iter().enumerate() {
                println!("{}", i);
                let mut change = xlib::XWindowChanges {
                    x: 0,
                    y: 0,
                    width: screen_width,
                    height: screen_height,
                    border_width: 0,
                    sibling: 0,
                    stack_mode: 0
                };
                match self.direction {
                    Direction::Vertical => {
                        change.y = height * i as libc::c_int;
                        change.height = height;
                    }
                    Direction::Horizontal => {
                        change.x = width * i as libc::c_int;
                        change.width = width;
                    }
                };

                debug!("config x: {}, y: {}, width: {}, height: {}",
                       change.x, change.y, change.width, change.height);
                xlib::XConfigureWindow(display, *w, mask, &mut change);
            }
        }
    }
}
<commit_msg>layout type can clone<commit_after>extern crate libc;

use x11::xlib::Window;
use x11::xlib;

const CWX: libc::c_uint = 1<<0;
const CWY: libc::c_uint = 1<<1;
const CWWidth: libc::c_uint = 1<<2;
const CWHeight: libc::c_uint = 1<<3;
const CWBorderWidth: libc::c_uint = 1<<4;
const CWSibling: libc::c_uint =	1<<5;
const CWStackMode: libc::c_uint = 1<<6;

pub trait Layout {
    fn configure(&self, windows: &[Window], display: *mut xlib::Display,screen_num: libc::c_int);
    fn toggle(&mut self) {}
    fn get_type(&self) -> Type;
}

pub enum Direction {
    Vertical,
    Horizontal,
}

#[derive(PartialEq, Clone)]
pub enum Type {
    Tiling,
}

pub struct TilingLayout {
    direction: Direction,
}

impl TilingLayout {
    pub fn new(d: Direction) -> TilingLayout{
        TilingLayout {
            direction: d,
        }
    }
}

impl Layout for TilingLayout {
    fn get_type(&self) -> Type { Type::Tiling }
    fn toggle(&mut self) {
        match self.direction {
            Direction::Vertical => self.direction = Direction::Horizontal,
            Direction::Horizontal => self.direction = Direction::Vertical,
        }
    }
    /// once we add or remove a window, we need to reconfig
    fn configure(&self, windows: &[Window], display: *mut xlib::Display,screen_num: libc::c_int,) {
        let size = windows.len();
        if size == 0 {
            return;
        }

        unsafe {
            let screen_height = xlib::XDisplayHeight(display, screen_num);
            let screen_width = xlib::XDisplayWidth(display, screen_num);
            let mask = CWX | CWY | CWHeight | CWWidth;

            let width = screen_width  / size as libc::c_int;
            let height = screen_height / size as libc::c_int;

            for (i, w) in windows.iter().enumerate() {
                println!("{}", i);
                let mut change = xlib::XWindowChanges {
                    x: 0,
                    y: 0,
                    width: screen_width,
                    height: screen_height,
                    border_width: 0,
                    sibling: 0,
                    stack_mode: 0
                };
                match self.direction {
                    Direction::Vertical => {
                        change.y = height * i as libc::c_int;
                        change.height = height;
                    }
                    Direction::Horizontal => {
                        change.x = width * i as libc::c_int;
                        change.width = width;
                    }
                };

                debug!("config x: {}, y: {}, width: {}, height: {}",
                       change.x, change.y, change.width, change.height);
                xlib::XConfigureWindow(display, *w, mask, &mut change);
            }
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;

extern crate glutin;

use std::thread;

mod support;

#[cfg(target_os = "android")]
android_start!(main);

#[cfg(not(feature = "window"))]
fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }

#[cfg(feature = "window")]
fn main() {
    let window1 = glutin::Window::new().unwrap();
    let window2 = glutin::Window::new().unwrap();
    let window3 = glutin::Window::new().unwrap();

    let t1 = thread::scoped(move || {
        run(window1, (0.0, 1.0, 0.0, 1.0));
    });

    let t2 = thread::scoped(move || {
        run(window2, (0.0, 0.0, 1.0, 1.0));
    });

    let t3 = thread::scoped(move || {
        run(window3, (1.0, 0.0, 0.0, 1.0));
    });

    let _ = t1.join();
    let _ = t2.join();
    let _ = t3.join();
}

#[cfg(feature = "window")]
fn run(window: glutin::Window, color: (f32, f32, f32, f32)) {
    unsafe { window.make_current() };

    let context = support::load(&window);

    while !window.is_closed() {
        context.draw_frame(color);
        window.swap_buffers();

        window.wait_events().next();
    }
}
<commit_msg>Fix examples so that travis passes again<commit_after>#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;

extern crate glutin;

use std::thread;

mod support;

#[cfg(target_os = "android")]
android_start!(main);

#[cfg(not(feature = "window"))]
fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }

#[cfg(feature = "window")]
fn main() {
    let window1 = glutin::Window::new().unwrap();
    let window2 = glutin::Window::new().unwrap();
    let window3 = glutin::Window::new().unwrap();

    let t1 = thread::spawn(move || {
        run(window1, (0.0, 1.0, 0.0, 1.0));
    });

    let t2 = thread::spawn(move || {
        run(window2, (0.0, 0.0, 1.0, 1.0));
    });

    let t3 = thread::spawn(move || {
        run(window3, (1.0, 0.0, 0.0, 1.0));
    });

    let _ = t1.join();
    let _ = t2.join();
    let _ = t3.join();
}

#[cfg(feature = "window")]
fn run(window: glutin::Window, color: (f32, f32, f32, f32)) {
    unsafe { window.make_current() };

    let context = support::load(&window);

    while !window.is_closed() {
        context.draw_frame(color);
        window.swap_buffers();

        window.wait_events().next();
    }
}
<|endoftext|>


<commit_before>use std::{
    cell::{Cell, RefCell},
    collections::BTreeMap,
};

use dces::prelude::{Entity, Component};

use crate::{prelude::*, render::RenderContext2D, tree::Tree, utils::prelude::*};

use super::Layout;

/// Stacks visual the children widgets vertical or horizontal.
#[derive(Default)]
pub struct StackLayout {
    desired_size: RefCell<DirtySize>,
    old_alignment: Cell<(Alignment, Alignment)>,
}

impl StackLayout {
    pub fn new() -> Self {
        StackLayout::default()
    }

    pub fn set_dirty(&self, dirty: bool) {
        self.desired_size.borrow_mut().set_dirty(dirty);
    }
}

impl Layout for StackLayout {
    fn measure(
        &self,
        render_context_2_d: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
        layouts: &BTreeMap<Entity, Box<dyn Layout>>,
        theme: &ThemeValue,
    ) -> DirtySize {
        if component::<Visibility>(ecm, entity, "visibility") == Visibility::Collapsed {
            let mut desired = self.desired_size.borrow_mut();
            desired.set_size(0.0, 0.0);
            return desired.clone();
        }

        let halign: Alignment = component(ecm, entity, "horizontal_alignment");
        let valign: Alignment = component(ecm, entity, "vertical_alignment");
        let (old_valign, old_halign) = self.old_alignment.get();

        if halign != old_halign || valign != old_valign {
            self.set_dirty(true);
        }

        let orientation: Orientation = component(ecm, entity, "orientation");
        let mut dirty = false;
        let mut desired_size: (f64, f64) = (0.0, 0.0);

        let nchildren = ecm.entity_store().children[&entity].len();
        let spacing: f64 = component_or_default(ecm, entity, "spacing");

        for index in 0..nchildren {
            let child = ecm.entity_store().children[&entity][index];

            if let Some(child_layout) = layouts.get(&child) {
                let child_desired_size =
                    child_layout.measure(render_context_2_d, child, ecm, layouts, theme);

                let mut child_margin = {
                    if child_desired_size.width() > 0.0 && child_desired_size.height() > 0.0 {
                        component(ecm, child, "margin")
                    } else {
                        Thickness::default()
                    }
                };

                if spacing != 0.0 && nchildren > 1 {
                    apply_spacing(&mut child_margin, spacing, orientation, index, nchildren);
                }

                accumulate_desired_size(&mut desired_size, child_desired_size, child_margin, orientation);

                if child_desired_size.dirty() || self.desired_size.borrow().dirty() {
                    dirty = true;
                }
            }
        }

        self.set_dirty(dirty);

        let mut desired = self.desired_size.borrow_mut();
        desired.set_size(desired_size.0, desired_size.1);
        desired.clone()
    }

    fn arrange(
        &self,
        render_context_2_d: &mut RenderContext2D,
        parent_size: (f64, f64),
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
        layouts: &BTreeMap<Entity, Box<dyn Layout>>,
        theme: &ThemeValue,
    ) -> (f64, f64) {
        if component::<Visibility>(ecm, entity, "visibility") == Visibility::Collapsed {
            self.desired_size.borrow_mut().set_size(0.0, 0.0);
            return (0.0, 0.0);
        }

        if !self.desired_size.borrow().dirty() {
            return self.desired_size.borrow().size();
        }

        let halign: Alignment = component(ecm, entity, "horizontal_alignment");
        let valign: Alignment = component(ecm, entity, "vertical_alignment");
        let margin: Thickness = component(ecm, entity, "margin");
        let constraint: Constraint = component(ecm, entity, "constraint");
        let orientation: Orientation = component(ecm, entity, "orientation");

        let mut size_counter = 0.0;

        let size = constraint.perform((
            halign.align_measure(
                parent_size.0,
                self.desired_size.borrow().width(),
                margin.left(),
                margin.right(),
            ),
            valign.align_measure(
                parent_size.1,
                self.desired_size.borrow().height(),
                margin.top(),
                margin.bottom(),
            ),
        ));

        if let Some(bounds) = component_try_mut::<Rectangle>(ecm, entity, "bounds") {
            bounds.set_width(size.0);
            bounds.set_height(size.1);
        }

        let available_size = size;
        let nchildren = ecm.entity_store().children[&entity].len();
        let spacing: f64 = component_or_default(ecm, entity, "spacing");

        for index in 0..nchildren {
            let child = ecm.entity_store().children[&entity][index];

            let mut child_desired_size = (0.0, 0.0);
            if let Some(child_layout) = layouts.get(&child) {
                let dimensions = match orientation {
                    // set width to 0.0 to shrink width of the child
                    Orientation::Horizontal => (0.0, size.1),

                    // set height to 0.0 to shrink height of the child
                    Orientation::Vertical => (size.0, 0.0)
                };

                child_desired_size = child_layout.arrange(
                    render_context_2_d,
                    dimensions,
                    child,
                    ecm,
                    layouts,
                    theme,
                );
            }

            let mut child_margin = {
                if child_desired_size.0 > 0.0 && child_desired_size.1 > 0.0 {
                    component(ecm, child, "margin")
                } else {
                    Thickness::default()
                }
            };

            if spacing != 0.0 && nchildren > 1 {
                apply_spacing(&mut child_margin, spacing, orientation, index, nchildren);
            }

            let child_halign: Alignment = component(ecm, child, "horizontal_alignment");
            let child_valign: Alignment = component(ecm, child, "vertical_alignment");

            if let Some(child_bounds) = component_try_mut::<Rectangle>(ecm, child, "bounds") {
                apply_arrangement(
                    child_bounds,
                    &mut size_counter,
                    child_margin,
                    (child_halign, child_valign),
                    orientation,
                    available_size
                );
            }
        }

        self.set_dirty(false);
        size
    }
}

impl From<StackLayout> for Box<dyn Layout> {
    fn from(layout: StackLayout) -> Self {
        Box::new(layout)
    }
}

fn apply_arrangement(
    bounds: &mut Rectangle,
    size_counter: &mut f64,
    margin: Thickness,
    alignment: (Alignment, Alignment),
    orientation: Orientation,
    available_size: (f64, f64)
) {
    let (xpos, ypos, size);

    match orientation {
        Orientation::Horizontal => {
            xpos = *size_counter + alignment.0.align_position(
                available_size.0,
                bounds.width(),
                margin.left(),
                margin.right(),
            );

            ypos = alignment.1.align_position(
                available_size.1,
                bounds.height(),
                margin.top(),
                margin.bottom(),
            );

            size = bounds.width() + margin.left() + margin.right();
        }
        _ => {
            xpos = alignment.0.align_position(
                available_size.0,
                bounds.width(),
                margin.left(),
                margin.right(),
            );

            ypos = *size_counter + alignment.1.align_position(
                available_size.1,
                bounds.height(),
                margin.top(),
                margin.bottom(),
            );

            size = bounds.height() + margin.top() + margin.bottom();
        }
    };

    bounds.set_x(xpos);
    bounds.set_y(ypos);
    *size_counter += size;
}

/// Applies spacing to widgets in a stack, depending upon their position, and the orientation.
fn apply_spacing(margins: &mut Thickness, spacing: f64, orientation: Orientation, index: usize, nchildren: usize) {
    let start =  if index == 0 { 0.0 } else { spacing / 2.0 };
    let end = if index == nchildren - 1 { 0.0 } else { spacing / 2.0 };

    match orientation {
        Orientation::Vertical => {
            margins.top += start;
            margins.bottom += end;
        }
        Orientation::Horizontal => {
            margins.left += start;
            margins.right += end;
        }
    }
}

fn accumulate_desired_size(
    desired_size: &mut (f64, f64),
    desired: DirtySize,
    margin: Thickness,
    orientation: Orientation
) {
    let width = desired.width() + margin.left() + margin.right();
    let height = desired.height() + margin.top() + margin.bottom();

    match orientation {
        Orientation::Horizontal => {
            desired_size.0 += width;
            desired_size.1 = height;
        }
        Orientation::Vertical => {
            desired_size.0 = width;
            desired_size.1 += height;
        }
    }
}

fn component<C: Component + Clone>(
    ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    entity: Entity,
    component: &str
) -> C {
    ecm.component_store().get::<C>(component, entity).unwrap().clone()
}

fn component_or_default<C: Component + Clone + Default>(
    ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    entity: Entity,
    component: &str
) -> C {
    ecm.component_store()
        .get::<C>(component, entity)
        .map(Clone::clone)
        .unwrap_or_default()
}

fn component_try_mut<'a, C: Component>(
    ecm: &'a mut EntityComponentManager<Tree, StringComponentStore>,
    entity: Entity,
    component: &str
) -> Option<&'a mut C> {
    ecm.component_store_mut().get_mut::<C>(component, entity).ok()
}

#[cfg(test)]
mod tests {
    use orbtk_utils::{Thickness, Orientation};
    use std::iter;

    use super::apply_spacing;

    const NUM_WIDGETS: usize = 5;

    #[test]
    fn spacing_vertical() {
        let expected = iter::once(Thickness { left: 0.0, right: 0.0, top: 0.0, bottom: 2.0 })
            .chain(iter::repeat(Thickness { left: 0.0, right: 0.0, top: 2.0, bottom: 2.0 }).take(3))
            .chain(iter::once(Thickness { left: 0.0, right: 0.0, top: 2.0, bottom: 0.0 }));

        spacing(Orientation::Vertical, 4.0, expected);
    }

    #[test]
    fn spacing_horizontal() {
        let expected = iter::once(Thickness { left: 0.0, right: 4.0, top: 0.0, bottom: 0.0 })
            .chain(iter::repeat(Thickness { left: 4.0, right: 4.0, top: 0.0, bottom: 0.0 }).take(3))
            .chain(iter::once(Thickness { left: 4.0, right: 0.0, top: 0.0, bottom: 0.0 }));

        spacing(Orientation::Horizontal, 8.0, expected);
    }

    fn spacing(orientation: Orientation, spacing: f64, expected: impl Iterator<Item = Thickness>) {
        let inputs = (0..NUM_WIDGETS).map(|id| (id, Thickness::default()));

        for ((index, mut input), expected) in inputs.zip(expected) {
            apply_spacing(&mut input, spacing, orientation, index, NUM_WIDGETS);
            assert_eq!(input, expected);
        }
    }
}
<commit_msg>fix(layout): Fix widgets within a stack having a parent height of 0.0<commit_after>use std::{
    cell::{Cell, RefCell},
    collections::BTreeMap,
};

use dces::prelude::{Entity, Component};

use crate::{prelude::*, render::RenderContext2D, tree::Tree, utils::prelude::*};

use super::Layout;

/// Stacks visual the children widgets vertical or horizontal.
#[derive(Default)]
pub struct StackLayout {
    desired_size: RefCell<DirtySize>,
    old_alignment: Cell<(Alignment, Alignment)>,
}

impl StackLayout {
    pub fn new() -> Self {
        StackLayout::default()
    }

    pub fn set_dirty(&self, dirty: bool) {
        self.desired_size.borrow_mut().set_dirty(dirty);
    }
}

impl Layout for StackLayout {
    fn measure(
        &self,
        render_context_2_d: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
        layouts: &BTreeMap<Entity, Box<dyn Layout>>,
        theme: &ThemeValue,
    ) -> DirtySize {
        if component::<Visibility>(ecm, entity, "visibility") == Visibility::Collapsed {
            let mut desired = self.desired_size.borrow_mut();
            desired.set_size(0.0, 0.0);
            return desired.clone();
        }

        let halign: Alignment = component(ecm, entity, "horizontal_alignment");
        let valign: Alignment = component(ecm, entity, "vertical_alignment");
        let (old_valign, old_halign) = self.old_alignment.get();

        if halign != old_halign || valign != old_valign {
            self.set_dirty(true);
        }

        let orientation: Orientation = component(ecm, entity, "orientation");
        let mut dirty = false;
        let mut desired_size: (f64, f64) = (0.0, 0.0);

        let nchildren = ecm.entity_store().children[&entity].len();
        let spacing: f64 = component_or_default(ecm, entity, "spacing");

        for index in 0..nchildren {
            let child = ecm.entity_store().children[&entity][index];

            if let Some(child_layout) = layouts.get(&child) {
                let child_desired_size =
                    child_layout.measure(render_context_2_d, child, ecm, layouts, theme);

                let mut child_margin = {
                    if child_desired_size.width() > 0.0 && child_desired_size.height() > 0.0 {
                        component(ecm, child, "margin")
                    } else {
                        Thickness::default()
                    }
                };

                if spacing != 0.0 && nchildren > 1 {
                    apply_spacing(&mut child_margin, spacing, orientation, index, nchildren);
                }

                accumulate_desired_size(&mut desired_size, child_desired_size, child_margin, orientation);

                if child_desired_size.dirty() || self.desired_size.borrow().dirty() {
                    dirty = true;
                }
            }
        }

        self.set_dirty(dirty);

        let mut desired = self.desired_size.borrow_mut();
        desired.set_size(desired_size.0, desired_size.1);
        desired.clone()
    }

    fn arrange(
        &self,
        render_context_2_d: &mut RenderContext2D,
        parent_size: (f64, f64),
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
        layouts: &BTreeMap<Entity, Box<dyn Layout>>,
        theme: &ThemeValue,
    ) -> (f64, f64) {
        if component::<Visibility>(ecm, entity, "visibility") == Visibility::Collapsed {
            self.desired_size.borrow_mut().set_size(0.0, 0.0);
            return (0.0, 0.0);
        }

        if !self.desired_size.borrow().dirty() {
            return self.desired_size.borrow().size();
        }

        let halign: Alignment = component(ecm, entity, "horizontal_alignment");
        let valign: Alignment = component(ecm, entity, "vertical_alignment");
        let margin: Thickness = component(ecm, entity, "margin");
        let constraint: Constraint = component(ecm, entity, "constraint");
        let orientation: Orientation = component(ecm, entity, "orientation");

        let mut size_counter = 0.0;

        let size = constraint.perform((
            halign.align_measure(
                parent_size.0,
                self.desired_size.borrow().width(),
                margin.left(),
                margin.right(),
            ),
            valign.align_measure(
                parent_size.1,
                self.desired_size.borrow().height(),
                margin.top(),
                margin.bottom(),
            ),
        ));

        if let Some(bounds) = component_try_mut::<Rectangle>(ecm, entity, "bounds") {
            bounds.set_width(size.0);
            bounds.set_height(size.1);
        }

        let available_size = size;
        let nchildren = ecm.entity_store().children[&entity].len();
        let spacing: f64 = component_or_default(ecm, entity, "spacing");

        for index in 0..nchildren {
            let child = ecm.entity_store().children[&entity][index];

            let mut child_desired_size = (0.0, 0.0);
            if let Some(child_layout) = layouts.get(&child) {
                child_desired_size = child_layout.arrange(
                    render_context_2_d,
                    size,
                    child,
                    ecm,
                    layouts,
                    theme,
                );
            }

            let mut child_margin = {
                if child_desired_size.0 > 0.0 && child_desired_size.1 > 0.0 {
                    component(ecm, child, "margin")
                } else {
                    Thickness::default()
                }
            };

            if spacing != 0.0 && nchildren > 1 {
                apply_spacing(&mut child_margin, spacing, orientation, index, nchildren);
            }

            let child_halign: Alignment = component(ecm, child, "horizontal_alignment");
            let child_valign: Alignment = component(ecm, child, "vertical_alignment");

            if let Some(child_bounds) = component_try_mut::<Rectangle>(ecm, child, "bounds") {
                apply_arrangement(
                    child_bounds,
                    &mut size_counter,
                    child_margin,
                    (child_halign, child_valign),
                    orientation,
                    available_size
                );
            }
        }

        self.set_dirty(false);
        size
    }
}

impl From<StackLayout> for Box<dyn Layout> {
    fn from(layout: StackLayout) -> Self {
        Box::new(layout)
    }
}

fn apply_arrangement(
    bounds: &mut Rectangle,
    size_counter: &mut f64,
    margin: Thickness,
    alignment: (Alignment, Alignment),
    orientation: Orientation,
    available_size: (f64, f64)
) {
    let (xpos, ypos, size);

    match orientation {
        Orientation::Horizontal => {
            xpos = *size_counter + alignment.0.align_position(
                available_size.0,
                bounds.width(),
                margin.left(),
                margin.right(),
            );

            ypos = alignment.1.align_position(
                available_size.1,
                bounds.height(),
                margin.top(),
                margin.bottom(),
            );

            size = bounds.width() + margin.left() + margin.right();
        }
        _ => {
            xpos = alignment.0.align_position(
                available_size.0,
                bounds.width(),
                margin.left(),
                margin.right(),
            );

            ypos = *size_counter + alignment.1.align_position(
                available_size.1,
                bounds.height(),
                margin.top(),
                margin.bottom(),
            );

            size = bounds.height() + margin.top() + margin.bottom();
        }
    };

    bounds.set_x(xpos);
    bounds.set_y(ypos);
    *size_counter += size;
}

/// Applies spacing to widgets in a stack, depending upon their position, and the orientation.
fn apply_spacing(margins: &mut Thickness, spacing: f64, orientation: Orientation, index: usize, nchildren: usize) {
    let start =  if index == 0 { 0.0 } else { spacing / 2.0 };
    let end = if index == nchildren - 1 { 0.0 } else { spacing / 2.0 };

    match orientation {
        Orientation::Vertical => {
            margins.top += start;
            margins.bottom += end;
        }
        Orientation::Horizontal => {
            margins.left += start;
            margins.right += end;
        }
    }
}

fn accumulate_desired_size(
    desired_size: &mut (f64, f64),
    desired: DirtySize,
    margin: Thickness,
    orientation: Orientation
) {
    let width = desired.width() + margin.left() + margin.right();
    let height = desired.height() + margin.top() + margin.bottom();

    match orientation {
        Orientation::Horizontal => {
            desired_size.0 += width;
            desired_size.1 = height;
        }
        Orientation::Vertical => {
            desired_size.0 = width;
            desired_size.1 += height;
        }
    }
}

fn component<C: Component + Clone>(
    ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    entity: Entity,
    component: &str
) -> C {
    ecm.component_store().get::<C>(component, entity).unwrap().clone()
}

fn component_or_default<C: Component + Clone + Default>(
    ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    entity: Entity,
    component: &str
) -> C {
    ecm.component_store()
        .get::<C>(component, entity)
        .map(Clone::clone)
        .unwrap_or_default()
}

fn component_try_mut<'a, C: Component>(
    ecm: &'a mut EntityComponentManager<Tree, StringComponentStore>,
    entity: Entity,
    component: &str
) -> Option<&'a mut C> {
    ecm.component_store_mut().get_mut::<C>(component, entity).ok()
}

#[cfg(test)]
mod tests {
    use orbtk_utils::{Thickness, Orientation};
    use std::iter;

    use super::apply_spacing;

    const NUM_WIDGETS: usize = 5;

    #[test]
    fn spacing_vertical() {
        let expected = iter::once(Thickness { left: 0.0, right: 0.0, top: 0.0, bottom: 2.0 })
            .chain(iter::repeat(Thickness { left: 0.0, right: 0.0, top: 2.0, bottom: 2.0 }).take(3))
            .chain(iter::once(Thickness { left: 0.0, right: 0.0, top: 2.0, bottom: 0.0 }));

        spacing(Orientation::Vertical, 4.0, expected);
    }

    #[test]
    fn spacing_horizontal() {
        let expected = iter::once(Thickness { left: 0.0, right: 4.0, top: 0.0, bottom: 0.0 })
            .chain(iter::repeat(Thickness { left: 4.0, right: 4.0, top: 0.0, bottom: 0.0 }).take(3))
            .chain(iter::once(Thickness { left: 4.0, right: 0.0, top: 0.0, bottom: 0.0 }));

        spacing(Orientation::Horizontal, 8.0, expected);
    }

    fn spacing(orientation: Orientation, spacing: f64, expected: impl Iterator<Item = Thickness>) {
        let inputs = (0..NUM_WIDGETS).map(|id| (id, Thickness::default()));

        for ((index, mut input), expected) in inputs.zip(expected) {
            apply_spacing(&mut input, spacing, orientation, index, NUM_WIDGETS);
            assert_eq!(input, expected);
        }
    }
}
<|endoftext|>