<commit_before>extern crate nannou;

use nannou::{App, Event, Frame, LoopMode, WindowEvent, WindowId, VirtualKeyCode, ElementState};

fn main() {
    nannou::run::<Model, Event>(model, update, draw);
}

struct Model {
    window: nannou::WindowId,
}

fn model(app: &App) -> Model {
    let window = app.new_window().build().unwrap();
    Model { window }
}

fn update(app: &App, model: Model, event: Event) -> Model {
    match event {
        Event::WindowEvent(id, event) => {
            println!("{:?}", event);
            window_event(app, model, id, event)
        },
        Event::Update(update) => {
            println!("{:?}", &update);
            model
        },
        _ => model,
    }
}

fn window_event(app: &App, model: Model, _id: WindowId, event: WindowEvent) -> Model {
    match event {
        WindowEvent::KeyboardInput { input, .. } => match input.state {
            ElementState::Pressed => match input.virtual_keycode {
                Some(VirtualKeyCode::Space) => {
                    match app.loop_mode() {
                        LoopMode::Rate { .. } => app.set_loop_mode(LoopMode::wait(3)),
                        LoopMode::Wait { .. } => app.set_loop_mode(LoopMode::rate_fps(60.0)),
                    }
                    println!("Switched LoopMode to: {:?}", app.loop_mode());
                },
                _ => (),
            },
            ElementState::Released => {},
        },
        _ => (),
    }
    model
}

// Draw the state of your `Model` into the given `Frame` here.
fn draw(_app: &App, model: &Model, frame: Frame) -> Frame {
    {
        // Our app only has one window, so retrieve this part of the `Frame`.
        let mut window_frame = frame.window(model.window).unwrap();
        // Paint it! (red, green, blue, alpha).
        window_frame.clear_color(1.0, 0.0, 0.0, 1.0);
    }
    // Return the drawn frame.
    frame
}
<commit_msg>Simplify loop_mode example a bit<commit_after>extern crate nannou;

use nannou::{App, Event, Frame, LoopMode, WindowEvent, WindowId, VirtualKeyCode as Key, ElementState};

fn main() {
    nannou::run(model, update, draw);
}

struct Model {
    window: nannou::WindowId,
}

fn model(app: &App) -> Model {
    app.set_loop_mode(LoopMode::wait(3));
    let window = app.new_window().build().unwrap();
    Model { window }
}

fn update(app: &App, model: Model, event: Event) -> Model {
    match event {
        Event::WindowEvent(id, event) => {
            println!("{:?}", event);
            match event {
                WindowEvent::KeyboardInput { input, .. } => {
                    if let (ElementState::Pressed, Some(_)) = (input.state, input.virtual_keycode) {
                        match app.loop_mode() {
                            LoopMode::Rate { .. } => app.set_loop_mode(LoopMode::wait(3)),
                            LoopMode::Wait { .. } => app.set_loop_mode(LoopMode::rate_fps(60.0)),
                        }
                    }
                },
                _ => (),
            }
        },
        Event::Update(update) => {
            println!("{:?}", &update);
        },
        _ => (),
    }
    model
}

// Draw the state of your `Model` into the given `Frame` here.
fn draw(_app: &App, model: &Model, frame: Frame) -> Frame {
    frame.window(model.window).unwrap().clear_color(0.1, 0.11, 0.12, 1.0);
    frame
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Gilad Naaman
//
// 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.

/// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as
/// much as is possible currently.
#[cfg(memoffset_maybe_uninit)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:tt) => {
        // No UB here, and the pointer does not dangle, either.
        // But we have to make sure that `uninit` lives long enough,
        // so it has to be in the same scope as `$name`. That's why
        // `let_base_ptr` declares a variable (several, actually)
        // instad of returning one.
        let uninit = $crate::mem::MaybeUninit::<$type>::uninit();
        let $name = uninit.as_ptr();
    };
}
#[cfg(not(memoffset_maybe_uninit))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:tt) => {
        // No UB right here, but we will later dereference this pointer to
        // offset into a field, and that is UB when the pointer is dangling.
        let $name = $crate::mem::align_of::<$type>() as *const $type;
    };
}

/// Deref-coercion protection macro.
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:tt, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        let $type { $field: _, .. };
    };
}

/// Calculates the offset of the specified field from the start of the struct.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Foo {
///     a: u32,
///     b: u64,
///     c: [u8; 5]
/// }
///
/// fn main() {
///     assert_eq!(offset_of!(Foo, a), 0);
///     assert_eq!(offset_of!(Foo, b), 4);
/// }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:tt, $field:tt) => {{
        _memoffset__field_check!($parent, $field);

        // Get a base pointer.
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get the field address. This is UB because we are creating a reference to
        // the uninitialized field.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        let field_ptr = unsafe { &(*base_ptr).$field as *const _ };
        let offset = (field_ptr as usize) - (base_ptr as usize);
        offset
    }};
}

#[cfg(test)]
mod tests {
    #[test]
    fn offset_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 8);
    }

    #[test]
    #[cfg(not(miri))] // this creates unaligned references
    fn offset_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 6);
    }

    #[test]
    fn tuple_struct() {
        #[repr(C)]
        struct Tup(i32, i32);

        assert_eq!(offset_of!(Tup, 0), 0);
        assert_eq!(offset_of!(Tup, 1), 4);
    }
}
<commit_msg>explain why we do not have deref coercion problems<commit_after>// Copyright (c) 2017 Gilad Naaman
//
// 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.

/// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as
/// much as is possible currently.
#[cfg(memoffset_maybe_uninit)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:tt) => {
        // No UB here, and the pointer does not dangle, either.
        // But we have to make sure that `uninit` lives long enough,
        // so it has to be in the same scope as `$name`. That's why
        // `let_base_ptr` declares a variable (several, actually)
        // instad of returning one.
        let uninit = $crate::mem::MaybeUninit::<$type>::uninit();
        let $name = uninit.as_ptr();
    };
}
#[cfg(not(memoffset_maybe_uninit))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:tt) => {
        // No UB right here, but we will later dereference this pointer to
        // offset into a field, and that is UB when the pointer is dangling.
        let $name = $crate::mem::align_of::<$type>() as *const $type;
    };
}

/// Deref-coercion protection macro.
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:tt, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        let $type { $field: _, .. };
    };
}

/// Calculates the offset of the specified field from the start of the struct.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Foo {
///     a: u32,
///     b: u64,
///     c: [u8; 5]
/// }
///
/// fn main() {
///     assert_eq!(offset_of!(Foo, a), 0);
///     assert_eq!(offset_of!(Foo, b), 4);
/// }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:tt, $field:tt) => {{
        _memoffset__field_check!($parent, $field);

        // Get a base pointer.
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get the field address. This is UB because we are creating a reference to
        // the uninitialized field.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the `field_check!` we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        let field_ptr = unsafe { &(*base_ptr).$field as *const _ };
        let offset = (field_ptr as usize) - (base_ptr as usize);
        offset
    }};
}

#[cfg(test)]
mod tests {
    #[test]
    fn offset_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 8);
    }

    #[test]
    #[cfg(not(miri))] // this creates unaligned references
    fn offset_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 6);
    }

    #[test]
    fn tuple_struct() {
        #[repr(C)]
        struct Tup(i32, i32);

        assert_eq!(offset_of!(Tup, 0), 0);
        assert_eq!(offset_of!(Tup, 1), 4);
    }
}
<|endoftext|>


<commit_before>use super::frontend_prelude::*;

use crate::models::{CrateOwner, CrateOwnerInvitation, OwnerKind, User};
use crate::schema::{crate_owner_invitations, crate_owners, users};
use crate::views::{EncodableCrateOwnerInvitation, EncodablePublicUser, InvitationResponse};
use diesel::dsl::any;
use std::collections::{HashMap, HashSet};
use std::iter::FromIterator;

/// Handles the `GET /me/crate_owner_invitations` route.
pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
    // Ensure that the user is authenticated
    let user = req.authenticate()?.user();

    // Load all pending invitations for the user
    let conn = &*req.db_read_only()?;
    let crate_owner_invitations: Vec<CrateOwnerInvitation> = crate_owner_invitations::table
        .filter(crate_owner_invitations::invited_user_id.eq(user.id))
        .load(&*conn)?;

    // Make a list of all related users and deduplicate it by using a `HashSet`
    let mut user_ids = HashSet::new();
    for invitation in &crate_owner_invitations {
        user_ids.insert(invitation.invited_by_user_id);
    }

    // Load all related users
    let users: Vec<User> = users::table
        .filter(users::id.eq(any(Vec::from_iter(user_ids))))
        .load(conn)?;

    let users: HashMap<i32, User> = users.into_iter().map(|user| (user.id, user)).collect();

    // Turn `CrateOwnerInvitation` list into `EncodableCrateOwnerInvitation` list
    let crate_owner_invitations = crate_owner_invitations
        .into_iter()
        .map(|invitation| {
            let inviter_id = invitation.invited_by_user_id;
            let inviter_name = users
                .get(&inviter_id)
                .map(|user| user.gh_login.clone())
                .unwrap_or_default();

            let crate_name = invitation.crate_name(conn);
            EncodableCrateOwnerInvitation::from(invitation, inviter_name, crate_name)
        })
        .collect();

    // Turn `User` list into `EncodablePublicUser` list
    let users = users
        .into_iter()
        .map(|(_, user)| EncodablePublicUser::from(user))
        .collect();

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
        users: Vec<EncodablePublicUser>,
    }
    Ok(req.json(&R {
        crate_owner_invitations,
        users,
    }))
}

#[derive(Deserialize)]
struct OwnerInvitation {
    crate_owner_invite: InvitationResponse,
}

/// Handles the `PUT /me/crate_owner_invitations/:crate_id` route.
pub fn handle_invite(req: &mut dyn RequestExt) -> EndpointResult {
    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let crate_invite: OwnerInvitation =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let crate_invite = crate_invite.crate_owner_invite;
    let user_id = req.authenticate()?.user_id();
    let conn = &*req.db_conn()?;

    if crate_invite.accepted {
        accept_invite(req, conn, crate_invite, user_id)
    } else {
        decline_invite(req, conn, crate_invite, user_id)
    }
}

/// Handles the `PUT /me/crate_owner_invitations/accept/:token` route.
pub fn handle_invite_with_token(req: &mut dyn RequestExt) -> EndpointResult {
    let conn = req.db_conn()?;
    let req_token = &req.params()["token"];

    let crate_owner_invite: CrateOwnerInvitation = crate_owner_invitations::table
        .filter(crate_owner_invitations::token.eq(req_token))
        .first(&*conn)?;

    let invite_reponse = InvitationResponse {
        crate_id: crate_owner_invite.crate_id,
        accepted: true,
    };
    accept_invite(
        req,
        &conn,
        invite_reponse,
        crate_owner_invite.invited_user_id,
    )
}

fn accept_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::{delete, insert_into};

    conn.transaction(|| {
        let pending_crate_owner: CrateOwnerInvitation = crate_owner_invitations::table
            .find((user_id, crate_invite.crate_id))
            .first(&*conn)?;

        insert_into(crate_owners::table)
            .values(&CrateOwner {
                crate_id: crate_invite.crate_id,
                owner_id: user_id,
                created_by: pending_crate_owner.invited_by_user_id,
                owner_kind: OwnerKind::User as i32,
                email_notifications: true,
            })
            .on_conflict(crate_owners::table.primary_key())
            .do_update()
            .set(crate_owners::deleted.eq(false))
            .execute(conn)?;
        delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id)))
            .execute(conn)?;

        #[derive(Serialize)]
        struct R {
            crate_owner_invitation: InvitationResponse,
        }
        Ok(req.json(&R {
            crate_owner_invitation: crate_invite,
        }))
    })
}

fn decline_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::delete;

    delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id))).execute(conn)?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }

    Ok(req.json(&R {
        crate_owner_invitation: crate_invite,
    }))
}
<commit_msg>CrateOwnerInvitation: Remove unnecessary `user_ids` deduplication<commit_after>use super::frontend_prelude::*;

use crate::models::{CrateOwner, CrateOwnerInvitation, OwnerKind, User};
use crate::schema::{crate_owner_invitations, crate_owners, users};
use crate::views::{EncodableCrateOwnerInvitation, EncodablePublicUser, InvitationResponse};
use diesel::dsl::any;
use std::collections::HashMap;

/// Handles the `GET /me/crate_owner_invitations` route.
pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
    // Ensure that the user is authenticated
    let user = req.authenticate()?.user();

    // Load all pending invitations for the user
    let conn = &*req.db_read_only()?;
    let crate_owner_invitations: Vec<CrateOwnerInvitation> = crate_owner_invitations::table
        .filter(crate_owner_invitations::invited_user_id.eq(user.id))
        .load(&*conn)?;

    // Make a list of all related users
    let user_ids: Vec<_> = crate_owner_invitations
        .iter()
        .map(|invitation| invitation.invited_by_user_id)
        .collect();

    // Load all related users
    let users: Vec<User> = users::table
        .filter(users::id.eq(any(user_ids)))
        .load(conn)?;

    let users: HashMap<i32, User> = users.into_iter().map(|user| (user.id, user)).collect();

    // Turn `CrateOwnerInvitation` list into `EncodableCrateOwnerInvitation` list
    let crate_owner_invitations = crate_owner_invitations
        .into_iter()
        .map(|invitation| {
            let inviter_id = invitation.invited_by_user_id;
            let inviter_name = users
                .get(&inviter_id)
                .map(|user| user.gh_login.clone())
                .unwrap_or_default();

            let crate_name = invitation.crate_name(conn);
            EncodableCrateOwnerInvitation::from(invitation, inviter_name, crate_name)
        })
        .collect();

    // Turn `User` list into `EncodablePublicUser` list
    let users = users
        .into_iter()
        .map(|(_, user)| EncodablePublicUser::from(user))
        .collect();

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
        users: Vec<EncodablePublicUser>,
    }
    Ok(req.json(&R {
        crate_owner_invitations,
        users,
    }))
}

#[derive(Deserialize)]
struct OwnerInvitation {
    crate_owner_invite: InvitationResponse,
}

/// Handles the `PUT /me/crate_owner_invitations/:crate_id` route.
pub fn handle_invite(req: &mut dyn RequestExt) -> EndpointResult {
    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let crate_invite: OwnerInvitation =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let crate_invite = crate_invite.crate_owner_invite;
    let user_id = req.authenticate()?.user_id();
    let conn = &*req.db_conn()?;

    if crate_invite.accepted {
        accept_invite(req, conn, crate_invite, user_id)
    } else {
        decline_invite(req, conn, crate_invite, user_id)
    }
}

/// Handles the `PUT /me/crate_owner_invitations/accept/:token` route.
pub fn handle_invite_with_token(req: &mut dyn RequestExt) -> EndpointResult {
    let conn = req.db_conn()?;
    let req_token = &req.params()["token"];

    let crate_owner_invite: CrateOwnerInvitation = crate_owner_invitations::table
        .filter(crate_owner_invitations::token.eq(req_token))
        .first(&*conn)?;

    let invite_reponse = InvitationResponse {
        crate_id: crate_owner_invite.crate_id,
        accepted: true,
    };
    accept_invite(
        req,
        &conn,
        invite_reponse,
        crate_owner_invite.invited_user_id,
    )
}

fn accept_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::{delete, insert_into};

    conn.transaction(|| {
        let pending_crate_owner: CrateOwnerInvitation = crate_owner_invitations::table
            .find((user_id, crate_invite.crate_id))
            .first(&*conn)?;

        insert_into(crate_owners::table)
            .values(&CrateOwner {
                crate_id: crate_invite.crate_id,
                owner_id: user_id,
                created_by: pending_crate_owner.invited_by_user_id,
                owner_kind: OwnerKind::User as i32,
                email_notifications: true,
            })
            .on_conflict(crate_owners::table.primary_key())
            .do_update()
            .set(crate_owners::deleted.eq(false))
            .execute(conn)?;
        delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id)))
            .execute(conn)?;

        #[derive(Serialize)]
        struct R {
            crate_owner_invitation: InvitationResponse,
        }
        Ok(req.json(&R {
            crate_owner_invitation: crate_invite,
        }))
    })
}

fn decline_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::delete;

    delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id))).execute(conn)?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }

    Ok(req.json(&R {
        crate_owner_invitation: crate_invite,
    }))
}
<|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 dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyleDeclarationMethods};
use dom::bindings::conversions::Castable;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, StylePriority};
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
use dom::window::Window;
use selectors::parser::PseudoElement;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Ref;
use string_cache::Atom;
use style::properties::PropertyDeclaration;
use style::properties::{is_supported_property, longhands_from_shorthand, parse_one_declaration};
use util::str::{DOMString, str_join};

// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
#[dom_struct]
pub struct CSSStyleDeclaration {
    reflector_: Reflector,
    owner: JS<Element>,
    readonly: bool,
    pseudo: Option<PseudoElement>,
}

#[derive(PartialEq, HeapSizeOf)]
pub enum CSSModificationAccess {
    ReadWrite,
    Readonly
}

macro_rules! css_properties(
    ( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => (
        $(
            fn $getter(&self) -> DOMString {
                self.GetPropertyValue($cssprop.to_owned())
            }
            fn $setter(&self, value: DOMString) -> ErrorResult {
                self.SetPropertyValue($cssprop.to_owned(), value)
            }
        )*
    );
);

fn serialize_list(list: &[Ref<PropertyDeclaration>]) -> DOMString {
    let str_iter = list.iter().map(|d| d.value());
    str_join(str_iter, " ")
}

impl CSSStyleDeclaration {
    pub fn new_inherited(owner: &Element,
                         pseudo: Option<PseudoElement>,
                         modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
        CSSStyleDeclaration {
            reflector_: Reflector::new(),
            owner: JS::from_ref(owner),
            pseudo: pseudo,
            readonly: modification_access == CSSModificationAccess::Readonly,
        }
    }

    pub fn new(global: &Window, owner: &Element,
               pseudo: Option<PseudoElement>,
               modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
        reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, pseudo, modification_access),
                           GlobalRef::Window(global),
                           CSSStyleDeclarationBinding::Wrap)
    }

    fn get_computed_style(&self, property: &Atom) -> Option<DOMString> {
        let owner = self.owner.root();
        let node = owner.upcast::<Node>();
        if !node.is_in_doc() {
            // TODO: Node should be matched against the style rules of this window.
            // Firefox is currently the only browser to implement this.
            return None;
        }
        let addr = node.to_trusted_node_address();
        window_from_node(owner.r()).resolved_style_query(addr, self.pseudo.clone(), property)
    }
}

impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
    fn Length(&self) -> u32 {
        let owner = self.owner.root();
        let elem = owner.upcast::<Element>();
        let len = match *elem.style_attribute().borrow() {
            Some(ref declarations) => declarations.normal.len() + declarations.important.len(),
            None => 0
        };
        len as u32
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item
    fn Item(&self, index: u32) -> DOMString {
        let index = index as usize;
        let owner = self.owner.root();
        let elem = owner.upcast::<Element>();
        let style_attribute = elem.style_attribute().borrow();
        let result = style_attribute.as_ref().and_then(|declarations| {
            if index > declarations.normal.len() {
                declarations.important
                            .get(index - declarations.normal.len())
                            .map(|decl| format!("{:?} !important", decl))
            } else {
                declarations.normal
                            .get(index)
                            .map(|decl| format!("{:?}", decl))
            }
        });

        result.unwrap_or("".to_owned())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
    fn GetPropertyValue(&self, mut property: DOMString) -> DOMString {
        let owner = self.owner.root();

        // Step 1
        property.make_ascii_lowercase();
        let property = Atom::from_slice(&property);

        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            return self.get_computed_style(&property).unwrap_or("".to_owned());
        }

        // Step 2
        let longhand_properties = longhands_from_shorthand(&property);
        if let Some(longhand_properties) = longhand_properties {
            // Step 2.1
            let mut list = vec!();

            // Step 2.2
            for longhand in &*longhand_properties {
                // Step 2.2.1
                let declaration = owner.get_inline_style_declaration(&Atom::from_slice(&longhand));

                // Step 2.2.2 & 2.2.3
                match declaration {
                    Some(declaration) => list.push(declaration),
                    None => return "".to_owned(),
                }
            }

            // Step 2.3
            return serialize_list(&list);
        }

        // Step 3 & 4
        // FIXME: redundant let binding https://github.com/rust-lang/rust/issues/22252
        let result = match owner.get_inline_style_declaration(&property) {
            Some(declaration) => declaration.value(),
            None => "".to_owned(),
        };
        result
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
    fn GetPropertyPriority(&self, mut property: DOMString) -> DOMString {
        // Step 1
        property.make_ascii_lowercase();
        let property = Atom::from_slice(&property);

        // Step 2
        let longhand_properties = longhands_from_shorthand(&property);
        if let Some(longhand_properties) = longhand_properties {
            // Step 2.1 & 2.2 & 2.3
            if longhand_properties.iter()
                                  .map(|&longhand| self.GetPropertyPriority(longhand.to_owned()))
                                  .all(|priority| priority == "important") {

                return "important".to_owned();
            }
        // Step 3
        } else {
            // FIXME: extra let binding https://github.com/rust-lang/rust/issues/22323
            let owner = self.owner.root();
            if owner.get_important_inline_style_declaration(&property).is_some() {
                return "important".to_owned();
            }
        }

        // Step 4
        "".to_owned()
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty
    fn SetProperty(&self, mut property: DOMString, value: DOMString,
                   priority: DOMString) -> ErrorResult {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        // Step 2
        property.make_ascii_lowercase();

        // Step 3
        if !is_supported_property(&property) {
            return Ok(());
        }

        // Step 4
        if value.is_empty() {
            return self.RemoveProperty(property).map(|_| ());
        }

        // Step 5
        let priority = match &*priority {
            "" => StylePriority::Normal,
            p if p.eq_ignore_ascii_case("important") => StylePriority::Important,
            _ => return Ok(()),
        };

        // Step 6
        let owner = self.owner.root();
        let window = window_from_node(owner.r());
        let declarations = parse_one_declaration(&property, &value, &window.r().get_url());

        // Step 7
        let declarations = if let Ok(declarations) = declarations {
            declarations
        } else {
            return Ok(());
        };

        let owner = self.owner.root();
        let element = owner.upcast::<Element>();

        // Step 8
        for decl in declarations {
            // Step 9
            element.update_inline_style(decl, priority);
        }

        let document = document_from_node(element);
        let node = element.upcast();
        document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
        Ok(())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertypriority
    fn SetPropertyPriority(&self, property: DOMString, priority: DOMString) -> ErrorResult {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        // Step 2 & 3
        if !is_supported_property(&property) {
            return Ok(());
        }

        // Step 4
        let priority = match &*priority {
            "" => StylePriority::Normal,
            p if p.eq_ignore_ascii_case("important") => StylePriority::Important,
            _ => return Ok(()),
        };

        let owner = self.owner.root();
        let element = owner.upcast::<Element>();

        // Step 5 & 6
        match longhands_from_shorthand(&property) {
            Some(properties) => element.set_inline_style_property_priority(properties, priority),
            None => element.set_inline_style_property_priority(&[&*property], priority)
        }

        let document = document_from_node(element);
        let node = element.upcast();
        document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
        Ok(())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertyvalue
    fn SetPropertyValue(&self, property: DOMString, value: DOMString) -> ErrorResult {
        self.SetProperty(property, value, "".to_owned())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-removeproperty
    fn RemoveProperty(&self, mut property: DOMString) -> Fallible<DOMString> {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        // Step 2
        property.make_ascii_lowercase();

        // Step 3
        let value = self.GetPropertyValue(property.clone());

        let owner = self.owner.root();
        let elem = owner.upcast::<Element>();

        match longhands_from_shorthand(&property) {
            // Step 4
            Some(longhands) => {
                for longhand in &*longhands {
                    elem.remove_inline_style_property(longhand)
                }
            }
            // Step 5
            None => elem.remove_inline_style_property(&property)
        }

        // Step 6
        Ok(value)
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
    fn CssFloat(&self) -> DOMString {
        self.GetPropertyValue("float".to_owned())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
    fn SetCssFloat(&self, value: DOMString) -> ErrorResult {
        self.SetPropertyValue("float".to_owned(), value)
    }

    // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
    fn IndexedGetter(&self, index: u32, found: &mut bool) -> DOMString {
        let rval = self.Item(index);
        *found = index < self.Length();
        rval
    }

    // https://drafts.csswg.org/cssom/#cssstyledeclaration
    css_properties_accessors!(css_properties);
}
<commit_msg>Remove unnecessary rooting from `CSSStyleDeclaration`<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 dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyleDeclarationMethods};
use dom::bindings::conversions::Castable;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, StylePriority};
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
use dom::window::Window;
use selectors::parser::PseudoElement;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Ref;
use string_cache::Atom;
use style::properties::PropertyDeclaration;
use style::properties::{is_supported_property, longhands_from_shorthand, parse_one_declaration};
use util::str::{DOMString, str_join};

// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
#[dom_struct]
pub struct CSSStyleDeclaration {
    reflector_: Reflector,
    owner: JS<Element>,
    readonly: bool,
    pseudo: Option<PseudoElement>,
}

#[derive(PartialEq, HeapSizeOf)]
pub enum CSSModificationAccess {
    ReadWrite,
    Readonly
}

macro_rules! css_properties(
    ( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => (
        $(
            fn $getter(&self) -> DOMString {
                self.GetPropertyValue($cssprop.to_owned())
            }
            fn $setter(&self, value: DOMString) -> ErrorResult {
                self.SetPropertyValue($cssprop.to_owned(), value)
            }
        )*
    );
);

fn serialize_list(list: &[Ref<PropertyDeclaration>]) -> DOMString {
    let str_iter = list.iter().map(|d| d.value());
    str_join(str_iter, " ")
}

impl CSSStyleDeclaration {
    pub fn new_inherited(owner: &Element,
                         pseudo: Option<PseudoElement>,
                         modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
        CSSStyleDeclaration {
            reflector_: Reflector::new(),
            owner: JS::from_ref(owner),
            pseudo: pseudo,
            readonly: modification_access == CSSModificationAccess::Readonly,
        }
    }

    pub fn new(global: &Window, owner: &Element,
               pseudo: Option<PseudoElement>,
               modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
        reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, pseudo, modification_access),
                           GlobalRef::Window(global),
                           CSSStyleDeclarationBinding::Wrap)
    }

    fn get_computed_style(&self, property: &Atom) -> Option<DOMString> {
        let node = self.owner.upcast::<Node>();
        if !node.is_in_doc() {
            // TODO: Node should be matched against the style rules of this window.
            // Firefox is currently the only browser to implement this.
            return None;
        }
        let addr = node.to_trusted_node_address();
        window_from_node(&*self.owner).resolved_style_query(addr, self.pseudo.clone(), property)
    }
}

impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
    fn Length(&self) -> u32 {
        let elem = self.owner.upcast::<Element>();
        let len = match *elem.style_attribute().borrow() {
            Some(ref declarations) => declarations.normal.len() + declarations.important.len(),
            None => 0
        };
        len as u32
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item
    fn Item(&self, index: u32) -> DOMString {
        let index = index as usize;
        let elem = self.owner.upcast::<Element>();
        let style_attribute = elem.style_attribute().borrow();
        let result = style_attribute.as_ref().and_then(|declarations| {
            if index > declarations.normal.len() {
                declarations.important
                            .get(index - declarations.normal.len())
                            .map(|decl| format!("{:?} !important", decl))
            } else {
                declarations.normal
                            .get(index)
                            .map(|decl| format!("{:?}", decl))
            }
        });

        result.unwrap_or("".to_owned())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
    fn GetPropertyValue(&self, mut property: DOMString) -> DOMString {
        let owner = &self.owner;

        // Step 1
        property.make_ascii_lowercase();
        let property = Atom::from_slice(&property);

        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            return self.get_computed_style(&property).unwrap_or("".to_owned());
        }

        // Step 2
        let longhand_properties = longhands_from_shorthand(&property);
        if let Some(longhand_properties) = longhand_properties {
            // Step 2.1
            let mut list = vec!();

            // Step 2.2
            for longhand in &*longhand_properties {
                // Step 2.2.1
                let declaration = owner.get_inline_style_declaration(&Atom::from_slice(&longhand));

                // Step 2.2.2 & 2.2.3
                match declaration {
                    Some(declaration) => list.push(declaration),
                    None => return "".to_owned(),
                }
            }

            // Step 2.3
            return serialize_list(&list);
        }

        // Step 3 & 4
        let result = match owner.get_inline_style_declaration(&property) {
            Some(declaration) => declaration.value(),
            None => "".to_owned(),
        };
        result
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
    fn GetPropertyPriority(&self, mut property: DOMString) -> DOMString {
        // Step 1
        property.make_ascii_lowercase();
        let property = Atom::from_slice(&property);

        // Step 2
        let longhand_properties = longhands_from_shorthand(&property);
        if let Some(longhand_properties) = longhand_properties {
            // Step 2.1 & 2.2 & 2.3
            if longhand_properties.iter()
                                  .map(|&longhand| self.GetPropertyPriority(longhand.to_owned()))
                                  .all(|priority| priority == "important") {

                return "important".to_owned();
            }
        // Step 3
        } else {
            if self.owner.get_important_inline_style_declaration(&property).is_some() {
                return "important".to_owned();
            }
        }

        // Step 4
        "".to_owned()
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty
    fn SetProperty(&self, mut property: DOMString, value: DOMString,
                   priority: DOMString) -> ErrorResult {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        // Step 2
        property.make_ascii_lowercase();

        // Step 3
        if !is_supported_property(&property) {
            return Ok(());
        }

        // Step 4
        if value.is_empty() {
            return self.RemoveProperty(property).map(|_| ());
        }

        // Step 5
        let priority = match &*priority {
            "" => StylePriority::Normal,
            p if p.eq_ignore_ascii_case("important") => StylePriority::Important,
            _ => return Ok(()),
        };

        // Step 6
        let window = window_from_node(&*self.owner);
        let declarations = parse_one_declaration(&property, &value, &window.r().get_url());

        // Step 7
        let declarations = if let Ok(declarations) = declarations {
            declarations
        } else {
            return Ok(());
        };

        let element = self.owner.upcast::<Element>();

        // Step 8
        for decl in declarations {
            // Step 9
            element.update_inline_style(decl, priority);
        }

        let document = document_from_node(element);
        let node = element.upcast();
        document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
        Ok(())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertypriority
    fn SetPropertyPriority(&self, property: DOMString, priority: DOMString) -> ErrorResult {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        // Step 2 & 3
        if !is_supported_property(&property) {
            return Ok(());
        }

        // Step 4
        let priority = match &*priority {
            "" => StylePriority::Normal,
            p if p.eq_ignore_ascii_case("important") => StylePriority::Important,
            _ => return Ok(()),
        };

        let element = self.owner.upcast::<Element>();

        // Step 5 & 6
        match longhands_from_shorthand(&property) {
            Some(properties) => element.set_inline_style_property_priority(properties, priority),
            None => element.set_inline_style_property_priority(&[&*property], priority)
        }

        let document = document_from_node(element);
        let node = element.upcast();
        document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
        Ok(())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertyvalue
    fn SetPropertyValue(&self, property: DOMString, value: DOMString) -> ErrorResult {
        self.SetProperty(property, value, "".to_owned())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-removeproperty
    fn RemoveProperty(&self, mut property: DOMString) -> Fallible<DOMString> {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        // Step 2
        property.make_ascii_lowercase();

        // Step 3
        let value = self.GetPropertyValue(property.clone());

        let elem = self.owner.upcast::<Element>();

        match longhands_from_shorthand(&property) {
            // Step 4
            Some(longhands) => {
                for longhand in &*longhands {
                    elem.remove_inline_style_property(longhand)
                }
            }
            // Step 5
            None => elem.remove_inline_style_property(&property)
        }

        // Step 6
        Ok(value)
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
    fn CssFloat(&self) -> DOMString {
        self.GetPropertyValue("float".to_owned())
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
    fn SetCssFloat(&self, value: DOMString) -> ErrorResult {
        self.SetPropertyValue("float".to_owned(), value)
    }

    // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
    fn IndexedGetter(&self, index: u32, found: &mut bool) -> DOMString {
        let rval = self.Item(index);
        *found = index < self.Length();
        rval
    }

    // https://drafts.csswg.org/cssom/#cssstyledeclaration
    css_properties_accessors!(css_properties);
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::chained_bft_consensus_provider::InitialSetup;
use crate::chained_bft::epoch_manager::EpochManager;
use crate::chained_bft::network::{NetworkReceivers, NetworkTask};
use crate::{
    chained_bft::{
        block_storage::BlockStore,
        event_processor::EventProcessor,
        persistent_storage::{PersistentStorage, RecoveryData},
    },
    counters,
    state_replication::{StateComputer, StateMachineReplication, TxnManager},
    util::time_service::ClockTimeService,
};
use channel;
use consensus_types::common::{Payload, Round};
use failure::prelude::*;
use futures::{select, stream::StreamExt};
use libra_config::config::{ConsensusConfig, ConsensusProposerType};
use libra_logger::prelude::*;
use std::{
    sync::Arc,
    time::{Duration, Instant},
};
use tokio::runtime::{Runtime, TaskExecutor};

/// Consensus configuration derived from ConsensusConfig
pub struct ChainedBftSMRConfig {
    /// Keep up to this number of committed blocks before cleaning them up from the block store.
    pub max_pruned_blocks_in_mem: usize,
    /// Initial timeout for pacemaker
    pub pacemaker_initial_timeout: Duration,
    /// Consensus proposer type
    pub proposer_type: ConsensusProposerType,
    /// Contiguous rounds for proposer
    pub contiguous_rounds: u32,
    /// Max block size (number of transactions) that consensus pulls from mempool
    pub max_block_size: u64,
}

impl ChainedBftSMRConfig {
    pub fn from_node_config(cfg: &ConsensusConfig) -> ChainedBftSMRConfig {
        let pacemaker_initial_timeout_ms = cfg.pacemaker_initial_timeout_ms().unwrap_or(1000);
        ChainedBftSMRConfig {
            max_pruned_blocks_in_mem: cfg.max_pruned_blocks_in_mem().unwrap_or(10000) as usize,
            pacemaker_initial_timeout: Duration::from_millis(pacemaker_initial_timeout_ms),
            proposer_type: cfg.get_proposer_type(),
            contiguous_rounds: cfg.contiguous_rounds(),
            max_block_size: cfg.max_block_size(),
        }
    }
}

/// ChainedBFTSMR is the one to generate the components (BlockStore, Proposer, etc.) and start the
/// driver. ChainedBftSMR implements the StateMachineReplication, it is going to be used by
/// ConsensusProvider for the e2e flow.
pub struct ChainedBftSMR<T> {
    initial_setup: Option<InitialSetup>,
    runtime: Option<Runtime>,
    block_store: Option<Arc<BlockStore<T>>>,
    config: Option<ChainedBftSMRConfig>,
    storage: Arc<dyn PersistentStorage<T>>,
    initial_data: Option<RecoveryData<T>>,
}

impl<T: Payload> ChainedBftSMR<T> {
    pub fn new(
        initial_setup: InitialSetup,
        runtime: Runtime,
        config: ChainedBftSMRConfig,
        storage: Arc<dyn PersistentStorage<T>>,
        initial_data: RecoveryData<T>,
    ) -> Self {
        Self {
            initial_setup: Some(initial_setup),
            runtime: Some(runtime),
            block_store: None,
            config: Some(config),
            storage,
            initial_data: Some(initial_data),
        }
    }

    #[cfg(test)]
    pub fn block_store(&self) -> Option<Arc<BlockStore<T>>> {
        self.block_store.clone()
    }

    fn start_event_processing(
        executor: TaskExecutor,
        mut epoch_manager: EpochManager<T>,
        mut event_processor: EventProcessor<T>,
        mut pacemaker_timeout_sender_rx: channel::Receiver<Round>,
        network_task: NetworkTask<T>,
        mut network_receivers: NetworkReceivers<T>,
    ) {
        let fut = async move {
            event_processor.start().await;
            loop {
                let pre_select_instant = Instant::now();
                let idle_duration;
                select! {
                    proposal_msg = network_receivers.proposals.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_proposal_msg(proposal_msg).await;
                    }
                    block_retrieval = network_receivers.block_retrieval.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_block_retrieval(block_retrieval).await;
                    }
                    vote_msg = network_receivers.votes.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_vote(vote_msg).await;
                    }
                    local_timeout_round = pacemaker_timeout_sender_rx.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_local_timeout(local_timeout_round).await;
                    }
                    sync_info_msg = network_receivers.sync_info_msgs.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_sync_info_msg(sync_info_msg.0, sync_info_msg.1).await;
                    }
                    ledger_info = network_receivers.epoch_change.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor = epoch_manager.start_new_epoch(ledger_info);
                        // clean up all the previous messages from the old epochs
                        network_receivers.clear_prev_epoch_msgs();
                        event_processor.start().await;
                    }
                    different_epoch_and_peer = network_receivers.different_epoch.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        epoch_manager.process_different_epoch(different_epoch_and_peer.0, different_epoch_and_peer.1).await
                    }
                    epoch_retrieval_and_peer = network_receivers.epoch_retrieval.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        epoch_manager.process_epoch_retrieval(epoch_retrieval_and_peer.0, epoch_retrieval_and_peer.1).await
                    }
                    complete => {
                        break;
                    }
                }
                counters::EVENT_PROCESSING_LOOP_BUSY_DURATION_S
                    .observe_duration(pre_select_instant.elapsed() - idle_duration);
                counters::EVENT_PROCESSING_LOOP_IDLE_DURATION_S.observe_duration(idle_duration);
            }
        };
        executor.spawn(network_task.start());
        executor.spawn(fut);
    }
}

impl<T: Payload> StateMachineReplication for ChainedBftSMR<T> {
    type Payload = T;

    /// We're following the steps to start
    /// 1. Construct the EpochManager from the latest libradb state
    /// 2. Construct per-epoch component with the fixed Validators provided by EpochManager including
    /// ProposerElection, Pacemaker, SafetyRules, Network(Populate with known validators), EventProcessor
    fn start(
        &mut self,
        txn_manager: Arc<dyn TxnManager<Payload = Self::Payload>>,
        state_computer: Arc<dyn StateComputer<Payload = Self::Payload>>,
    ) -> Result<()> {
        let initial_setup = self
            .initial_setup
            .take()
            .expect("already started, initial setup is None");
        let initial_data = self
            .initial_data
            .take()
            .expect("already started, initial data is None");
        // Step 1 TODO: read validators from libradb instead of config
        let validator = Arc::new(initial_setup.validator);
        let executor = self
            .runtime
            .as_mut()
            .expect("Consensus start: No valid runtime found!")
            .executor();
        let time_service = Arc::new(ClockTimeService::new(executor.clone()));

        let (timeout_sender, timeout_receiver) =
            channel::new(1_024, &counters::PENDING_PACEMAKER_TIMEOUTS);
        let (self_sender, self_receiver) = channel::new(1_024, &counters::PENDING_SELF_MESSAGES);
        let signer = Arc::new(initial_setup.signer);
        let epoch = initial_data.epoch();
        let epoch_mgr = EpochManager::new(
            epoch,
            self.config.take().expect("already started, config is None"),
            time_service,
            self_sender,
            initial_setup.network_sender,
            timeout_sender,
            txn_manager,
            state_computer,
            self.storage.clone(),
            signer.clone(),
        );

        // Step 2
        let event_processor = epoch_mgr.start_epoch(signer, validator.clone(), initial_data);

        // TODO: this is test only, we should remove this
        self.block_store = Some(event_processor.block_store());

        let (network_task, network_receiver) = NetworkTask::new(
            epoch,
            initial_setup.network_events,
            self_receiver,
            validator,
        );

        Self::start_event_processing(
            executor,
            epoch_mgr,
            event_processor,
            timeout_receiver,
            network_task,
            network_receiver,
        );
        debug!("Chained BFT SMR started.");
        Ok(())
    }

    /// Stop is synchronous: waits for all the worker threads to terminate.
    fn stop(&mut self) {
        if let Some(rt) = self.runtime.take() {
            rt.shutdown_now();
            debug!("Chained BFT SMR stopped.")
        }
    }
}
<commit_msg>[consensus] removing the `terminate` in chained_bft_smr loop<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::chained_bft_consensus_provider::InitialSetup;
use crate::chained_bft::epoch_manager::EpochManager;
use crate::chained_bft::network::{NetworkReceivers, NetworkTask};
use crate::{
    chained_bft::{
        block_storage::BlockStore,
        event_processor::EventProcessor,
        persistent_storage::{PersistentStorage, RecoveryData},
    },
    counters,
    state_replication::{StateComputer, StateMachineReplication, TxnManager},
    util::time_service::ClockTimeService,
};
use channel;
use consensus_types::common::{Payload, Round};
use failure::prelude::*;
use futures::{select, stream::StreamExt};
use libra_config::config::{ConsensusConfig, ConsensusProposerType};
use libra_logger::prelude::*;
use std::{
    sync::Arc,
    time::{Duration, Instant},
};
use tokio::runtime::{Runtime, TaskExecutor};

/// Consensus configuration derived from ConsensusConfig
pub struct ChainedBftSMRConfig {
    /// Keep up to this number of committed blocks before cleaning them up from the block store.
    pub max_pruned_blocks_in_mem: usize,
    /// Initial timeout for pacemaker
    pub pacemaker_initial_timeout: Duration,
    /// Consensus proposer type
    pub proposer_type: ConsensusProposerType,
    /// Contiguous rounds for proposer
    pub contiguous_rounds: u32,
    /// Max block size (number of transactions) that consensus pulls from mempool
    pub max_block_size: u64,
}

impl ChainedBftSMRConfig {
    pub fn from_node_config(cfg: &ConsensusConfig) -> ChainedBftSMRConfig {
        let pacemaker_initial_timeout_ms = cfg.pacemaker_initial_timeout_ms().unwrap_or(1000);
        ChainedBftSMRConfig {
            max_pruned_blocks_in_mem: cfg.max_pruned_blocks_in_mem().unwrap_or(10000) as usize,
            pacemaker_initial_timeout: Duration::from_millis(pacemaker_initial_timeout_ms),
            proposer_type: cfg.get_proposer_type(),
            contiguous_rounds: cfg.contiguous_rounds(),
            max_block_size: cfg.max_block_size(),
        }
    }
}

/// ChainedBFTSMR is the one to generate the components (BlockStore, Proposer, etc.) and start the
/// driver. ChainedBftSMR implements the StateMachineReplication, it is going to be used by
/// ConsensusProvider for the e2e flow.
pub struct ChainedBftSMR<T> {
    initial_setup: Option<InitialSetup>,
    runtime: Option<Runtime>,
    block_store: Option<Arc<BlockStore<T>>>,
    config: Option<ChainedBftSMRConfig>,
    storage: Arc<dyn PersistentStorage<T>>,
    initial_data: Option<RecoveryData<T>>,
}

impl<T: Payload> ChainedBftSMR<T> {
    pub fn new(
        initial_setup: InitialSetup,
        runtime: Runtime,
        config: ChainedBftSMRConfig,
        storage: Arc<dyn PersistentStorage<T>>,
        initial_data: RecoveryData<T>,
    ) -> Self {
        Self {
            initial_setup: Some(initial_setup),
            runtime: Some(runtime),
            block_store: None,
            config: Some(config),
            storage,
            initial_data: Some(initial_data),
        }
    }

    #[cfg(test)]
    pub fn block_store(&self) -> Option<Arc<BlockStore<T>>> {
        self.block_store.clone()
    }

    fn start_event_processing(
        executor: TaskExecutor,
        mut epoch_manager: EpochManager<T>,
        mut event_processor: EventProcessor<T>,
        mut pacemaker_timeout_sender_rx: channel::Receiver<Round>,
        network_task: NetworkTask<T>,
        mut network_receivers: NetworkReceivers<T>,
    ) {
        let fut = async move {
            event_processor.start().await;
            loop {
                let pre_select_instant = Instant::now();
                let idle_duration;
                select! {
                    proposal_msg = network_receivers.proposals.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_proposal_msg(proposal_msg).await;
                    }
                    block_retrieval = network_receivers.block_retrieval.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_block_retrieval(block_retrieval).await;
                    }
                    vote_msg = network_receivers.votes.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_vote(vote_msg).await;
                    }
                    local_timeout_round = pacemaker_timeout_sender_rx.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_local_timeout(local_timeout_round).await;
                    }
                    sync_info_msg = network_receivers.sync_info_msgs.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor.process_sync_info_msg(sync_info_msg.0, sync_info_msg.1).await;
                    }
                    ledger_info = network_receivers.epoch_change.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        event_processor = epoch_manager.start_new_epoch(ledger_info);
                        // clean up all the previous messages from the old epochs
                        network_receivers.clear_prev_epoch_msgs();
                        event_processor.start().await;
                    }
                    different_epoch_and_peer = network_receivers.different_epoch.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        epoch_manager.process_different_epoch(different_epoch_and_peer.0, different_epoch_and_peer.1).await
                    }
                    epoch_retrieval_and_peer = network_receivers.epoch_retrieval.select_next_some() => {
                        idle_duration = pre_select_instant.elapsed();
                        epoch_manager.process_epoch_retrieval(epoch_retrieval_and_peer.0, epoch_retrieval_and_peer.1).await
                    }
                }
                counters::EVENT_PROCESSING_LOOP_BUSY_DURATION_S
                    .observe_duration(pre_select_instant.elapsed() - idle_duration);
                counters::EVENT_PROCESSING_LOOP_IDLE_DURATION_S.observe_duration(idle_duration);
            }
        };
        executor.spawn(network_task.start());
        executor.spawn(fut);
    }
}

impl<T: Payload> StateMachineReplication for ChainedBftSMR<T> {
    type Payload = T;

    /// We're following the steps to start
    /// 1. Construct the EpochManager from the latest libradb state
    /// 2. Construct per-epoch component with the fixed Validators provided by EpochManager including
    /// ProposerElection, Pacemaker, SafetyRules, Network(Populate with known validators), EventProcessor
    fn start(
        &mut self,
        txn_manager: Arc<dyn TxnManager<Payload = Self::Payload>>,
        state_computer: Arc<dyn StateComputer<Payload = Self::Payload>>,
    ) -> Result<()> {
        let initial_setup = self
            .initial_setup
            .take()
            .expect("already started, initial setup is None");
        let initial_data = self
            .initial_data
            .take()
            .expect("already started, initial data is None");
        // Step 1 TODO: read validators from libradb instead of config
        let validator = Arc::new(initial_setup.validator);
        let executor = self
            .runtime
            .as_mut()
            .expect("Consensus start: No valid runtime found!")
            .executor();
        let time_service = Arc::new(ClockTimeService::new(executor.clone()));

        let (timeout_sender, timeout_receiver) =
            channel::new(1_024, &counters::PENDING_PACEMAKER_TIMEOUTS);
        let (self_sender, self_receiver) = channel::new(1_024, &counters::PENDING_SELF_MESSAGES);
        let signer = Arc::new(initial_setup.signer);
        let epoch = initial_data.epoch();
        let epoch_mgr = EpochManager::new(
            epoch,
            self.config.take().expect("already started, config is None"),
            time_service,
            self_sender,
            initial_setup.network_sender,
            timeout_sender,
            txn_manager,
            state_computer,
            self.storage.clone(),
            signer.clone(),
        );

        // Step 2
        let event_processor = epoch_mgr.start_epoch(signer, validator.clone(), initial_data);

        // TODO: this is test only, we should remove this
        self.block_store = Some(event_processor.block_store());

        let (network_task, network_receiver) = NetworkTask::new(
            epoch,
            initial_setup.network_events,
            self_receiver,
            validator,
        );

        Self::start_event_processing(
            executor,
            epoch_mgr,
            event_processor,
            timeout_receiver,
            network_task,
            network_receiver,
        );
        debug!("Chained BFT SMR started.");
        Ok(())
    }

    /// Stop is synchronous: waits for all the worker threads to terminate.
    fn stop(&mut self) {
        if let Some(rt) = self.runtime.take() {
            rt.shutdown_now();
            debug!("Chained BFT SMR stopped.")
        }
    }
}
<|endoftext|>


<commit_before>//! Random number generation

export Rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:Copy>(values: &[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:Copy>(values: &[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: Copy>(v : &[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:Copy>(v: &[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:Copy>(v: &[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        r
    }

    /// Shuffle a vec
    fn shuffle<T:Copy>(values: &[T]) -> ~[T] {
        let mut m = vec::from_slice(values);
        self.shuffle_mut(m);
        return m;
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(values: &[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    c: *rctx,
    drop { rustrt::rand_free(self.c); }
}

fn RandRes(c: *rctx) -> RandRes {
    RandRes {
        c: c
    }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn Rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::Rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::Rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::Rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::Rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::Rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::Rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::Rng();
        let x: Option<int> = r.choose_option([]);
        assert x.is_none();
        assert r.choose_option([1, 1, 1]) == Some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::Rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::Rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        let v: Option<int> = r.choose_weighted_option([]);
        assert v.is_none();
    }

    #[test]
    fn weighted_vec() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Make all remaining moves explicit in libcore<commit_after>//! Random number generation

export Rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        move s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:Copy>(values: &[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:Copy>(values: &[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: Copy>(v : &[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:Copy>(v: &[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:Copy>(v: &[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        move r
    }

    /// Shuffle a vec
    fn shuffle<T:Copy>(values: &[T]) -> ~[T] {
        let mut m = vec::from_slice(values);
        self.shuffle_mut(m);
        move m
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(values: &[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    c: *rctx,
    drop { rustrt::rand_free(self.c); }
}

fn RandRes(c: *rctx) -> RandRes {
    RandRes {
        c: c
    }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn Rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::Rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::Rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::Rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::Rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::Rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::Rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::Rng();
        let x: Option<int> = r.choose_option([]);
        assert x.is_none();
        assert r.choose_option([1, 1, 1]) == Some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::Rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::Rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        let v: Option<int> = r.choose_weighted_option([]);
        assert v.is_none();
    }

    #[test]
    fn weighted_vec() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>#![no_builtins]

#![allow(private_no_mangle_fns)]

extern crate core;

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"]
extern fn panic_fmt(args: &core::fmt::Arguments,
                    file: &str,
                    line: u32) -> ! {
    loop {}
}

// in future, replace with proper crate
// most from chrichton's rlibc to get it to compile will move to a mod or elsewhere later

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: usize) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as isize) = *src.offset(i as isize);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as isize) = *src.offset(i as isize);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as isize);
        let b = *s2.offset(i as isize);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

// TODO: ADD IMPLEMENTATIONS

#[no_mangle]
pub unsafe extern fn fmodf () -> f32 {
    0.0
}

#[no_mangle]
pub unsafe extern fn fmod () -> f64 {
    0.0f64
}

#[no_mangle]
pub unsafe extern fn __powisf2 () -> f64 {
    0.0f64
}

#[no_mangle]
pub unsafe extern fn __powidf2 () -> f64 {
    0.0f64
}
<commit_msg>remove unused file<commit_after><|endoftext|>


<commit_before>struct Counter {
    count: u32
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;

        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

#[test]
fn calling_counter_next() {
    let mut counter = Counter::new();

    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}<commit_msg>Implement test showing that we can also use other iter methods<commit_after>struct Counter {
    count: u32
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;

        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

#[test]
fn calling_counter_next() {
    let mut counter = Counter::new();

    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}

#[test]
fn using_other_iterator_trait_methods() {
    let sum: u32 = Counter::new().zip(Counter::new().skip(1))
                                 .map(|(a, b)| a * b)
                                 .filter(|x| x % 3 == 0)
                                 .sum();
    assert_eq!(sum, 18);
}<|endoftext|>