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

use invalid_mutations::bounds::{
    ApplyCodeUnitBoundsContext, ApplyOutOfBoundsContext, CodeUnitBoundsMutation,
    OutOfBoundsMutation,
};
use move_binary_format::{
    check_bounds::BoundsChecker, file_format::*, file_format_common,
    proptest_types::CompiledModuleStrategyGen,
};
use move_core_types::{
    account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode,
};
use proptest::{collection::vec, prelude::*};

#[test]
fn empty_module_no_errors() {
    basic_test_module().freeze().unwrap();
}

#[test]
fn invalid_default_module() {
    let m = CompiledModuleMut {
        version: file_format_common::VERSION_MAX,
        ..Default::default()
    };
    m.freeze().unwrap_err();
}

#[test]
fn invalid_self_module_handle_index() {
    let mut m = basic_test_module();
    m.self_module_handle_idx = ModuleHandleIndex(12);
    m.freeze().unwrap_err();
}

#[test]
fn invalid_type_param_in_fn_return_() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.function_handles[0].return_ = SignatureIndex(1);
    m.signatures.push(Signature(vec![TypeParameter(0)]));
    assert_eq!(m.signatures.len(), 2);
    m.freeze().unwrap_err();
}

#[test]
fn invalid_type_param_in_fn_parameters() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.function_handles[0].parameters = SignatureIndex(1);
    m.signatures.push(Signature(vec![TypeParameter(0)]));
    m.freeze().unwrap_err();
}

#[test]
fn invalid_struct_in_fn_return_() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.function_handles[0].return_ = SignatureIndex(1);
    m.signatures
        .push(Signature(vec![Struct(StructHandleIndex::new(1))]));
    m.freeze().unwrap_err();
}

#[test]
fn invalid_type_param_in_field() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    match &mut m.struct_defs[0].field_information {
        StructFieldInformation::Declared(ref mut fields) => {
            fields[0].signature.0 = TypeParameter(0);
            m.freeze().unwrap_err();
        }
        _ => panic!("attempt to change a field that does not exist"),
    }
}

#[test]
fn invalid_struct_in_field() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    match &mut m.struct_defs[0].field_information {
        StructFieldInformation::Declared(ref mut fields) => {
            fields[0].signature.0 = Struct(StructHandleIndex::new(3));
            m.freeze().unwrap_err();
        }
        _ => panic!("attempt to change a field that does not exist"),
    }
}

#[test]
fn invalid_struct_with_actuals_in_field() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    match &mut m.struct_defs[0].field_information {
        StructFieldInformation::Declared(ref mut fields) => {
            fields[0].signature.0 =
                StructInstantiation(StructHandleIndex::new(0), vec![TypeParameter(0)]);
            m.freeze().unwrap_err();
        }
        _ => panic!("attempt to change a field that does not exist"),
    }
}

#[test]
fn invalid_locals_id_in_call() {
    use Bytecode::*;

    let mut m = basic_test_module();
    m.function_instantiations.push(FunctionInstantiation {
        handle: FunctionHandleIndex::new(0),
        type_parameters: SignatureIndex::new(1),
    });
    let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1);
    m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)];
    m.freeze().unwrap_err();
}

#[test]
fn invalid_type_param_in_call() {
    use Bytecode::*;
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.signatures.push(Signature(vec![TypeParameter(0)]));
    m.function_instantiations.push(FunctionInstantiation {
        handle: FunctionHandleIndex::new(0),
        type_parameters: SignatureIndex::new(1),
    });
    let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1);
    m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)];
    m.freeze().unwrap_err();
}

#[test]
fn invalid_struct_as_type_actual_in_exists() {
    use Bytecode::*;
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.signatures
        .push(Signature(vec![Struct(StructHandleIndex::new(3))]));
    m.function_instantiations.push(FunctionInstantiation {
        handle: FunctionHandleIndex::new(0),
        type_parameters: SignatureIndex::new(1),
    });
    let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1);
    m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)];
    m.freeze().unwrap_err();
}

#[test]
fn invalid_friend_module_address() {
    let mut m = basic_test_module();
    m.friend_decls.push(ModuleHandle {
        address: AddressIdentifierIndex::new(m.address_identifiers.len() as TableIndex),
        name: IdentifierIndex::new(0),
    });
    m.freeze().unwrap_err();
}

#[test]
fn invalid_friend_module_name() {
    let mut m = basic_test_module();
    m.friend_decls.push(ModuleHandle {
        address: AddressIdentifierIndex::new(0),
        name: IdentifierIndex::new(m.identifiers.len() as TableIndex),
    });
    m.freeze().unwrap_err();
}

proptest! {
    #[test]
    fn valid_bounds(_module in CompiledModule::valid_strategy(20)) {
        // valid_strategy will panic if there are any bounds check issues.
    }
}

/// Ensure that valid modules that don't have any members (e.g. function args, struct fields) pass
/// bounds checks.
///
/// There are some potentially tricky edge cases around ranges that are captured here.
#[test]
fn valid_bounds_no_members() {
    let mut gen = CompiledModuleStrategyGen::new(20);
    gen.zeros_all();
    proptest!(|(_module in gen.generate())| {
        // gen.generate() will panic if there are any bounds check issues.
    });
}

proptest! {
    #[test]
    fn invalid_out_of_bounds(
        module in CompiledModule::valid_strategy(20),
        oob_mutations in vec(OutOfBoundsMutation::strategy(), 0..40),
    ) {
        let (module, expected_violations) = {
            let oob_context = ApplyOutOfBoundsContext::new(module, oob_mutations);
            oob_context.apply()
        };

        let actual_violations = BoundsChecker::verify(&module);
        prop_assert_eq!(expected_violations.is_empty(), actual_violations.is_ok());
    }

    #[test]
    fn code_unit_out_of_bounds(
        module in CompiledModule::valid_strategy(20),
        mutations in vec(CodeUnitBoundsMutation::strategy(), 0..40),
    ) {
        let mut module = module.into_inner();
        let expected_violations = {
            let context = ApplyCodeUnitBoundsContext::new(&mut module, mutations);
            context.apply()
        };

        let actual_violations = BoundsChecker::verify(&module);

        prop_assert_eq!(expected_violations.is_empty(), actual_violations.is_ok());
    }

    #[test]
    fn no_module_handles(
        identifiers in vec(any::<Identifier>(), 0..20),
        address_identifiers in vec(any::<AccountAddress>(), 0..20),
    ) {
        // If there are no module handles, the only other things that can be stored are intrinsic
        // data.
        let module = CompiledModuleMut {
            identifiers,
            address_identifiers,
            ..Default::default()
        };

        prop_assert_eq!(
            BoundsChecker::verify(&module).map_err(|e| e.major_status()),
            Err(StatusCode::NO_MODULE_HANDLES)
        );
    }
}

proptest! {
    // Generating arbitrary compiled modules is really slow, possibly because of
    // https://github.com/AltSysrq/proptest/issues/143.
    #![proptest_config(ProptestConfig::with_cases(16))]

    /// Make sure that garbage inputs don't crash the bounds checker.
    #[test]
    fn garbage_inputs(module in any_with::<CompiledModuleMut>(16)) {
        let _ = module.freeze();
    }
}
<commit_msg>[move][vm] Test bounds checker error codes<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use invalid_mutations::bounds::{
    ApplyCodeUnitBoundsContext, ApplyOutOfBoundsContext, CodeUnitBoundsMutation,
    OutOfBoundsMutation,
};
use move_binary_format::{
    check_bounds::BoundsChecker, file_format::*, file_format_common,
    proptest_types::CompiledModuleStrategyGen,
};
use move_core_types::{
    account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode,
};
use proptest::{collection::vec, prelude::*};

#[test]
fn empty_module_no_errors() {
    basic_test_module().freeze().unwrap();
}

#[test]
fn invalid_default_module() {
    let m = CompiledModuleMut {
        version: file_format_common::VERSION_MAX,
        ..Default::default()
    };
    m.freeze().unwrap_err();
}

#[test]
fn invalid_self_module_handle_index() {
    let mut m = basic_test_module();
    m.self_module_handle_idx = ModuleHandleIndex(12);
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_type_param_in_fn_return_() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.function_handles[0].return_ = SignatureIndex(1);
    m.signatures.push(Signature(vec![TypeParameter(0)]));
    assert_eq!(m.signatures.len(), 2);
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_type_param_in_fn_parameters() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.function_handles[0].parameters = SignatureIndex(1);
    m.signatures.push(Signature(vec![TypeParameter(0)]));
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_struct_in_fn_return_() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.function_handles[0].return_ = SignatureIndex(1);
    m.signatures
        .push(Signature(vec![Struct(StructHandleIndex::new(1))]));
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_type_param_in_field() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    match &mut m.struct_defs[0].field_information {
        StructFieldInformation::Declared(ref mut fields) => {
            fields[0].signature.0 = TypeParameter(0);
            assert_eq!(
                m.freeze().unwrap_err().major_status(),
                StatusCode::INDEX_OUT_OF_BOUNDS
            );
        }
        _ => panic!("attempt to change a field that does not exist"),
    }
}

#[test]
fn invalid_struct_in_field() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    match &mut m.struct_defs[0].field_information {
        StructFieldInformation::Declared(ref mut fields) => {
            fields[0].signature.0 = Struct(StructHandleIndex::new(3));
            assert_eq!(
                m.freeze().unwrap_err().major_status(),
                StatusCode::INDEX_OUT_OF_BOUNDS
            );
        }
        _ => panic!("attempt to change a field that does not exist"),
    }
}

#[test]
fn invalid_struct_with_actuals_in_field() {
    use SignatureToken::*;

    let mut m = basic_test_module();
    match &mut m.struct_defs[0].field_information {
        StructFieldInformation::Declared(ref mut fields) => {
            fields[0].signature.0 =
                StructInstantiation(StructHandleIndex::new(0), vec![TypeParameter(0)]);
            assert_eq!(
                m.freeze().unwrap_err().major_status(),
                StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH
            );
        }
        _ => panic!("attempt to change a field that does not exist"),
    }
}

#[test]
fn invalid_locals_id_in_call() {
    use Bytecode::*;

    let mut m = basic_test_module();
    m.function_instantiations.push(FunctionInstantiation {
        handle: FunctionHandleIndex::new(0),
        type_parameters: SignatureIndex::new(1),
    });
    let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1);
    m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)];
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_type_param_in_call() {
    use Bytecode::*;
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.signatures.push(Signature(vec![TypeParameter(0)]));
    m.function_instantiations.push(FunctionInstantiation {
        handle: FunctionHandleIndex::new(0),
        type_parameters: SignatureIndex::new(1),
    });
    let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1);
    m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)];
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_struct_as_type_actual_in_exists() {
    use Bytecode::*;
    use SignatureToken::*;

    let mut m = basic_test_module();
    m.signatures
        .push(Signature(vec![Struct(StructHandleIndex::new(3))]));
    m.function_instantiations.push(FunctionInstantiation {
        handle: FunctionHandleIndex::new(0),
        type_parameters: SignatureIndex::new(1),
    });
    let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1);
    m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)];
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_friend_module_address() {
    let mut m = basic_test_module();
    m.friend_decls.push(ModuleHandle {
        address: AddressIdentifierIndex::new(m.address_identifiers.len() as TableIndex),
        name: IdentifierIndex::new(0),
    });
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

#[test]
fn invalid_friend_module_name() {
    let mut m = basic_test_module();
    m.friend_decls.push(ModuleHandle {
        address: AddressIdentifierIndex::new(0),
        name: IdentifierIndex::new(m.identifiers.len() as TableIndex),
    });
    assert_eq!(
        m.freeze().unwrap_err().major_status(),
        StatusCode::INDEX_OUT_OF_BOUNDS
    );
}

proptest! {
    #[test]
    fn valid_bounds(_module in CompiledModule::valid_strategy(20)) {
        // valid_strategy will panic if there are any bounds check issues.
    }
}

/// Ensure that valid modules that don't have any members (e.g. function args, struct fields) pass
/// bounds checks.
///
/// There are some potentially tricky edge cases around ranges that are captured here.
#[test]
fn valid_bounds_no_members() {
    let mut gen = CompiledModuleStrategyGen::new(20);
    gen.zeros_all();
    proptest!(|(_module in gen.generate())| {
        // gen.generate() will panic if there are any bounds check issues.
    });
}

proptest! {
    #[test]
    fn invalid_out_of_bounds(
        module in CompiledModule::valid_strategy(20),
        oob_mutations in vec(OutOfBoundsMutation::strategy(), 0..40),
    ) {
        let (module, expected_violations) = {
            let oob_context = ApplyOutOfBoundsContext::new(module, oob_mutations);
            oob_context.apply()
        };

        let actual_violations = BoundsChecker::verify(&module);
        prop_assert_eq!(expected_violations.is_empty(), actual_violations.is_ok());
    }

    #[test]
    fn code_unit_out_of_bounds(
        module in CompiledModule::valid_strategy(20),
        mutations in vec(CodeUnitBoundsMutation::strategy(), 0..40),
    ) {
        let mut module = module.into_inner();
        let expected_violations = {
            let context = ApplyCodeUnitBoundsContext::new(&mut module, mutations);
            context.apply()
        };

        let actual_violations = BoundsChecker::verify(&module);

        prop_assert_eq!(expected_violations.is_empty(), actual_violations.is_ok());
    }

    #[test]
    fn no_module_handles(
        identifiers in vec(any::<Identifier>(), 0..20),
        address_identifiers in vec(any::<AccountAddress>(), 0..20),
    ) {
        // If there are no module handles, the only other things that can be stored are intrinsic
        // data.
        let module = CompiledModuleMut {
            identifiers,
            address_identifiers,
            ..Default::default()
        };

        prop_assert_eq!(
            BoundsChecker::verify(&module).map_err(|e| e.major_status()),
            Err(StatusCode::NO_MODULE_HANDLES)
        );
    }
}

proptest! {
    // Generating arbitrary compiled modules is really slow, possibly because of
    // https://github.com/AltSysrq/proptest/issues/143.
    #![proptest_config(ProptestConfig::with_cases(16))]

    /// Make sure that garbage inputs don't crash the bounds checker.
    #[test]
    fn garbage_inputs(module in any_with::<CompiledModuleMut>(16)) {
        let _ = module.freeze();
    }
}
<|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/. */

//! Element nodes.

use dom::bindings::utils::{DOMString, CacheableWrapper};
use dom::clientrect::ClientRect;
use dom::clientrectlist::ClientRectList;
use dom::node::{ElementNodeTypeId, Node, ScriptView};
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse};

use std::cell::Cell;
use std::comm::ChanOne;
use std::comm;
use std::uint;
use std::str::eq_slice;
use extra::net::url::Url;
use geom::size::Size2D;

pub struct Element {
    parent: Node<ScriptView>,
    tag_name: ~str,     // TODO: This should be an atom, not a ~str.
    attrs: ~[Attr],
}

#[deriving(Eq)]
pub enum ElementTypeId {
    HTMLAnchorElementTypeId,
    HTMLAsideElementTypeId,
    HTMLBRElementTypeId,
    HTMLBodyElementTypeId,
    HTMLBoldElementTypeId,
    HTMLDivElementTypeId,
    HTMLFontElementTypeId,
    HTMLFormElementTypeId,
    HTMLHRElementTypeId,
    HTMLHeadElementTypeId,
    HTMLHeadingElementTypeId,
    HTMLHtmlElementTypeId,
    HTMLIframeElementTypeId,
    HTMLImageElementTypeId,
    HTMLInputElementTypeId,
    HTMLItalicElementTypeId,
    HTMLLinkElementTypeId,
    HTMLListItemElementTypeId,
    HTMLMetaElementTypeId,
    HTMLOListElementTypeId,
    HTMLOptionElementTypeId,
    HTMLParagraphElementTypeId,
    HTMLScriptElementTypeId,
    HTMLSectionElementTypeId,
    HTMLSelectElementTypeId,
    HTMLSmallElementTypeId,
    HTMLSpanElementTypeId,
    HTMLStyleElementTypeId,
    HTMLTableBodyElementTypeId,
    HTMLTableCellElementTypeId,
    HTMLTableElementTypeId,
    HTMLTableRowElementTypeId,
    HTMLTitleElementTypeId,
    HTMLUListElementTypeId,
    UnknownElementTypeId,
}

//
// Regular old elements
//

pub struct HTMLAnchorElement    { parent: Element }
pub struct HTMLAsideElement     { parent: Element }
pub struct HTMLBRElement        { parent: Element }
pub struct HTMLBodyElement      { parent: Element }
pub struct HTMLBoldElement      { parent: Element }
pub struct HTMLDivElement       { parent: Element }
pub struct HTMLFontElement      { parent: Element }
pub struct HTMLFormElement      { parent: Element }
pub struct HTMLHRElement        { parent: Element }
pub struct HTMLHeadElement      { parent: Element }
pub struct HTMLHtmlElement      { parent: Element }
pub struct HTMLInputElement     { parent: Element }
pub struct HTMLItalicElement    { parent: Element }
pub struct HTMLLinkElement      { parent: Element }
pub struct HTMLListItemElement  { parent: Element }
pub struct HTMLMetaElement      { parent: Element }
pub struct HTMLOListElement     { parent: Element }
pub struct HTMLOptionElement    { parent: Element }
pub struct HTMLParagraphElement { parent: Element }
pub struct HTMLScriptElement    { parent: Element }
pub struct HTMLSectionElement   { parent: Element }
pub struct HTMLSelectElement    { parent: Element }
pub struct HTMLSmallElement     { parent: Element }
pub struct HTMLSpanElement      { parent: Element }
pub struct HTMLStyleElement     { parent: Element }
pub struct HTMLTableBodyElement { parent: Element }
pub struct HTMLTableCellElement { parent: Element }
pub struct HTMLTableElement     { parent: Element }
pub struct HTMLTableRowElement  { parent: Element }
pub struct HTMLTitleElement     { parent: Element }
pub struct HTMLUListElement     { parent: Element }
pub struct UnknownElement       { parent: Element }

//
// Fancier elements
//

pub struct HTMLHeadingElement {
    parent: Element,
    level: HeadingLevel,
}

pub struct HTMLIframeElement {
    parent: Element,
    frame: Option<Url>,
    size_future_chan: Option<ChanOne<Size2D<uint>>>,
}

pub struct HTMLImageElement {
    parent: Element,
    image: Option<Url>,
}

//
// Element methods
//

impl<'self> Element {
    pub fn new(type_id: ElementTypeId, tag_name: ~str) -> Element {
        Element {
            parent: Node::new(ElementNodeTypeId(type_id)),
            tag_name: tag_name,
            attrs: ~[]
        }
    }

    pub fn get_attr(&'self self, name: &str) -> Option<&'self str> {
        // FIXME: Need an each() that links lifetimes in Rust.
        for uint::range(0, self.attrs.len()) |i| {
            if eq_slice(self.attrs[i].name, name) {
                let val: &str = self.attrs[i].value;
                return Some(val);
            }
        }
        return None;
    }

    pub fn set_attr(&mut self, name: &DOMString, value: &DOMString) {
        let name = name.to_str();
        let value = value.to_str();
        // FIXME: We need a better each_mut in Rust; this is ugly.
        let value_cell = Cell::new(value);
        let mut found = false;
        for uint::range(0, self.attrs.len()) |i| {
            if eq_slice(self.attrs[i].name, name) {
                self.attrs[i].value = value_cell.take().clone();
                found = true;
                break;
            }
        }
        if !found {
            self.attrs.push(Attr::new(name.to_str(), value_cell.take().clone()));
        }

        match self.parent.owner_doc {
            Some(owner) => owner.content_changed(),
            None => {}
        }
    }

    pub fn getClientRects(&self) -> Option<@mut ClientRectList> {
        let (rects, cx, scope) = match self.parent.owner_doc {
            Some(doc) => {
                match doc.window {
                    Some(win) => {
                        let node = self.parent.abstract.get();
                        assert!(node.is_element());
                        let page = win.page;
                        let (port, chan) = comm::stream();
                        // TODO(tkuehn): currently just queries top-level page layout. Needs to query
                        // subframe layout if this element is in a subframe. Probably need an ID field.
                        match unsafe {(*page).query_layout(ContentBoxesQuery(node, chan), port)} {
                            Ok(ContentBoxesResponse(rects)) => {
                                let cx = unsafe {(*page).js_info.get_ref().js_compartment.cx.ptr};
                                let cache = win.get_wrappercache();
                                let scope = cache.get_wrapper();
                                let rects = do rects.map |r| {
                                    ClientRect::new(
                                         r.origin.y.to_f32(),
                                         (r.origin.y + r.size.height).to_f32(),
                                         r.origin.x.to_f32(),
                                         (r.origin.x + r.size.width).to_f32(),
                                         cx,
                                         scope)
                                };
                                Some((rects, cx, scope))
                            },
                            Err(()) => {
                                debug!("layout query error");
                                None
                            }
                        }
                    }
                    None => {
                        debug!("no window");
                        None
                    }
                }
            }
            None => {
                debug!("no document");
                None
            }
        }.get();

        Some(ClientRectList::new(rects, cx, scope))
    }

    pub fn getBoundingClientRect(&self) -> Option<@mut ClientRect> {
        match self.parent.owner_doc {
            Some(doc) => {
                match doc.window {
                    Some(win) => {
                        let page = win.page;
                        let node = self.parent.abstract.get();
                        assert!(node.is_element());
                        let (port, chan) = comm::stream();
                        match unsafe{(*page).query_layout(ContentBoxQuery(node, chan), port)} {
                            Ok(ContentBoxResponse(rect)) => {
                                let cx = unsafe {(*page).js_info.get_ref().js_compartment.cx.ptr};
                                let cache = win.get_wrappercache();
                                let scope = cache.get_wrapper();
                                Some(ClientRect::new(
                                         rect.origin.y.to_f32(),
                                         (rect.origin.y + rect.size.height).to_f32(),
                                         rect.origin.x.to_f32(),
                                         (rect.origin.x + rect.size.width).to_f32(),
                                         cx,
                                         scope))
                            },
                            Err(()) => {
                                debug!("error querying layout");
                                None
                            }
                        }
                    }
                    None => {
                        debug!("no window");
                        None
                    }
                }
            }
            None => {
                debug!("no document");
                None
            }
        }
    }
}

pub struct Attr {
    name: ~str,
    value: ~str,
}

impl Attr {
    pub fn new(name: ~str, value: ~str) -> Attr {
        Attr {
            name: name,
            value: value
        }
    }
}

pub enum HeadingLevel {
    Heading1,
    Heading2,
    Heading3,
    Heading4,
    Heading5,
    Heading6,
}

<commit_msg>auto merge of #640 : recrack/servo/fixme_each_mut, r=jdm<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/. */

//! Element nodes.

use dom::bindings::utils::{DOMString, CacheableWrapper};
use dom::clientrect::ClientRect;
use dom::clientrectlist::ClientRectList;
use dom::node::{ElementNodeTypeId, Node, ScriptView};
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse};

use std::cell::Cell;
use std::comm::ChanOne;
use std::comm;
use std::str::eq_slice;
use extra::net::url::Url;
use geom::size::Size2D;

pub struct Element {
    parent: Node<ScriptView>,
    tag_name: ~str,     // TODO: This should be an atom, not a ~str.
    attrs: ~[Attr],
}

#[deriving(Eq)]
pub enum ElementTypeId {
    HTMLAnchorElementTypeId,
    HTMLAsideElementTypeId,
    HTMLBRElementTypeId,
    HTMLBodyElementTypeId,
    HTMLBoldElementTypeId,
    HTMLDivElementTypeId,
    HTMLFontElementTypeId,
    HTMLFormElementTypeId,
    HTMLHRElementTypeId,
    HTMLHeadElementTypeId,
    HTMLHeadingElementTypeId,
    HTMLHtmlElementTypeId,
    HTMLIframeElementTypeId,
    HTMLImageElementTypeId,
    HTMLInputElementTypeId,
    HTMLItalicElementTypeId,
    HTMLLinkElementTypeId,
    HTMLListItemElementTypeId,
    HTMLMetaElementTypeId,
    HTMLOListElementTypeId,
    HTMLOptionElementTypeId,
    HTMLParagraphElementTypeId,
    HTMLScriptElementTypeId,
    HTMLSectionElementTypeId,
    HTMLSelectElementTypeId,
    HTMLSmallElementTypeId,
    HTMLSpanElementTypeId,
    HTMLStyleElementTypeId,
    HTMLTableBodyElementTypeId,
    HTMLTableCellElementTypeId,
    HTMLTableElementTypeId,
    HTMLTableRowElementTypeId,
    HTMLTitleElementTypeId,
    HTMLUListElementTypeId,
    UnknownElementTypeId,
}

//
// Regular old elements
//

pub struct HTMLAnchorElement    { parent: Element }
pub struct HTMLAsideElement     { parent: Element }
pub struct HTMLBRElement        { parent: Element }
pub struct HTMLBodyElement      { parent: Element }
pub struct HTMLBoldElement      { parent: Element }
pub struct HTMLDivElement       { parent: Element }
pub struct HTMLFontElement      { parent: Element }
pub struct HTMLFormElement      { parent: Element }
pub struct HTMLHRElement        { parent: Element }
pub struct HTMLHeadElement      { parent: Element }
pub struct HTMLHtmlElement      { parent: Element }
pub struct HTMLInputElement     { parent: Element }
pub struct HTMLItalicElement    { parent: Element }
pub struct HTMLLinkElement      { parent: Element }
pub struct HTMLListItemElement  { parent: Element }
pub struct HTMLMetaElement      { parent: Element }
pub struct HTMLOListElement     { parent: Element }
pub struct HTMLOptionElement    { parent: Element }
pub struct HTMLParagraphElement { parent: Element }
pub struct HTMLScriptElement    { parent: Element }
pub struct HTMLSectionElement   { parent: Element }
pub struct HTMLSelectElement    { parent: Element }
pub struct HTMLSmallElement     { parent: Element }
pub struct HTMLSpanElement      { parent: Element }
pub struct HTMLStyleElement     { parent: Element }
pub struct HTMLTableBodyElement { parent: Element }
pub struct HTMLTableCellElement { parent: Element }
pub struct HTMLTableElement     { parent: Element }
pub struct HTMLTableRowElement  { parent: Element }
pub struct HTMLTitleElement     { parent: Element }
pub struct HTMLUListElement     { parent: Element }
pub struct UnknownElement       { parent: Element }

//
// Fancier elements
//

pub struct HTMLHeadingElement {
    parent: Element,
    level: HeadingLevel,
}

pub struct HTMLIframeElement {
    parent: Element,
    frame: Option<Url>,
    size_future_chan: Option<ChanOne<Size2D<uint>>>,
}

pub struct HTMLImageElement {
    parent: Element,
    image: Option<Url>,
}

//
// Element methods
//

impl<'self> Element {
    pub fn new(type_id: ElementTypeId, tag_name: ~str) -> Element {
        Element {
            parent: Node::new(ElementNodeTypeId(type_id)),
            tag_name: tag_name,
            attrs: ~[]
        }
    }

    pub fn get_attr(&'self self, name: &str) -> Option<&'self str> {
        // FIXME: Need an each() that links lifetimes in Rust.
        for self.attrs.iter().advance |attr| {
            if eq_slice(attr.name, name) {
                let val: &str = attr.value;
                return Some(val);
            }
        }
        return None;
    }

    pub fn set_attr(&mut self, name: &DOMString, value: &DOMString) {
        let name = name.to_str();
        let value = value.to_str();
        let value_cell = Cell::new(value);
        let mut found = false;
        for self.attrs.mut_iter().advance |attr| {
            if eq_slice(attr.name, name) {
                attr.value = value_cell.take().clone();
                found = true;
                break;
            }
        }
        if !found {
            self.attrs.push(Attr::new(name.to_str(), value_cell.take().clone()));
        }

        match self.parent.owner_doc {
            Some(owner) => owner.content_changed(),
            None => {}
        }
    }

    pub fn getClientRects(&self) -> Option<@mut ClientRectList> {
        let (rects, cx, scope) = match self.parent.owner_doc {
            Some(doc) => {
                match doc.window {
                    Some(win) => {
                        let node = self.parent.abstract.get();
                        assert!(node.is_element());
                        let page = win.page;
                        let (port, chan) = comm::stream();
                        // TODO(tkuehn): currently just queries top-level page layout. Needs to query
                        // subframe layout if this element is in a subframe. Probably need an ID field.
                        match unsafe {(*page).query_layout(ContentBoxesQuery(node, chan), port)} {
                            Ok(ContentBoxesResponse(rects)) => {
                                let cx = unsafe {(*page).js_info.get_ref().js_compartment.cx.ptr};
                                let cache = win.get_wrappercache();
                                let scope = cache.get_wrapper();
                                let rects = do rects.map |r| {
                                    ClientRect::new(
                                         r.origin.y.to_f32(),
                                         (r.origin.y + r.size.height).to_f32(),
                                         r.origin.x.to_f32(),
                                         (r.origin.x + r.size.width).to_f32(),
                                         cx,
                                         scope)
                                };
                                Some((rects, cx, scope))
                            },
                            Err(()) => {
                                debug!("layout query error");
                                None
                            }
                        }
                    }
                    None => {
                        debug!("no window");
                        None
                    }
                }
            }
            None => {
                debug!("no document");
                None
            }
        }.get();

        Some(ClientRectList::new(rects, cx, scope))
    }

    pub fn getBoundingClientRect(&self) -> Option<@mut ClientRect> {
        match self.parent.owner_doc {
            Some(doc) => {
                match doc.window {
                    Some(win) => {
                        let page = win.page;
                        let node = self.parent.abstract.get();
                        assert!(node.is_element());
                        let (port, chan) = comm::stream();
                        match unsafe{(*page).query_layout(ContentBoxQuery(node, chan), port)} {
                            Ok(ContentBoxResponse(rect)) => {
                                let cx = unsafe {(*page).js_info.get_ref().js_compartment.cx.ptr};
                                let cache = win.get_wrappercache();
                                let scope = cache.get_wrapper();
                                Some(ClientRect::new(
                                         rect.origin.y.to_f32(),
                                         (rect.origin.y + rect.size.height).to_f32(),
                                         rect.origin.x.to_f32(),
                                         (rect.origin.x + rect.size.width).to_f32(),
                                         cx,
                                         scope))
                            },
                            Err(()) => {
                                debug!("error querying layout");
                                None
                            }
                        }
                    }
                    None => {
                        debug!("no window");
                        None
                    }
                }
            }
            None => {
                debug!("no document");
                None
            }
        }
    }
}

pub struct Attr {
    name: ~str,
    value: ~str,
}

impl Attr {
    pub fn new(name: ~str, value: ~str) -> Attr {
        Attr {
            name: name,
            value: value
        }
    }
}

pub enum HeadingLevel {
    Heading1,
    Heading2,
    Heading3,
    Heading4,
    Heading5,
    Heading6,
}

<|endoftext|>


<commit_before>//! `crypto_scalarmult_curve25519` specified in
//! [Cryptography in NaCl](http://nacl.cr.yp.to/valid.html), Sections 2, 3, and 4.
//! This function is conjectured to be strong. For background see Bernstein,
//! "Curve25519: new Diffie-Hellman speed records," Lecture Notes in Computer
//! Science 3958 (2006), 207–228, http://cr.yp.to/papers.html#curve25519.
use ffi;

pub const BYTES: usize = ffi::crypto_scalarmult_curve25519_BYTES;
pub const SCALARBYTES: usize = ffi::crypto_scalarmult_curve25519_SCALARBYTES;

/// `Scalar` value (integer in byte representation)
#[derive(Copy)]
pub struct Scalar(pub [u8; SCALARBYTES]);

newtype_clone!(Scalar);
newtype_impl!(Scalar, SCALARBYTES);

/// `GroupElement`
#[derive(Copy)]
pub struct GroupElement(pub [u8; BYTES]);

newtype_clone!(GroupElement);
newtype_impl!(GroupElement, BYTES);

/// `scalarmult()` multiplies a group element `p`
/// by an integer `n`. It returns the resulting group element
/// `q`.
pub fn scalarmult(&Scalar(ref n): &Scalar,
                  &GroupElement(ref p): &GroupElement) -> GroupElement {
    let mut q = [0; BYTES];
    unsafe {
        ffi::crypto_scalarmult_curve25519(&mut q, n, p);
    }
    GroupElement(q)
}

/// `scalarmult_base()` computes the scalar product of a standard
/// group element and an integer `n`. It returns the resulting
/// group element `q`/
pub fn scalarmult_base(&Scalar(ref n): &Scalar) -> GroupElement {
    let mut q = [0; BYTES];
    unsafe {
        ffi::crypto_scalarmult_curve25519_base(&mut q, n);
    }
    GroupElement(q)
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_vector_1() {
        // corresponding to tests/scalarmult.c and tests/scalarmult3.cpp from NaCl
        let alicesk = Scalar([0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
                             ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
                             ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
                             ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a]);
        let alicepk_expected = [0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
                               ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
                               ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
                               ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a];
        let GroupElement(alicepk) = scalarmult_base(&alicesk);
        assert!(alicepk == alicepk_expected);
    }

    #[test]
    fn test_vector_2() {
        // corresponding to tests/scalarmult2.c and tests/scalarmult4.cpp from NaCl
        let bobsk = Scalar([0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
                           ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
                           ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
                           ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb]);
        let bobpk_expected = [0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
                             ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
                             ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
                             ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f];
        let GroupElement(bobpk) = scalarmult_base(&bobsk);
        assert!(bobpk == bobpk_expected);
    }

    #[test]
    fn test_vector_3() {
        // corresponding to tests/scalarmult5.c and tests/scalarmult7.cpp from NaCl
        let alicesk = Scalar([0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
                             ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
                             ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
                             ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a]);
        let bobpk = GroupElement([0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
                                 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
                                 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
                                 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f]);
        let k_expected = [0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
                         ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
                         ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
                         ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42];
        let GroupElement(k) = scalarmult(&alicesk, &bobpk);
        assert!(k == k_expected);
    }

    #[test]
    fn test_vector_4() {
        // corresponding to tests/scalarmult6.c from NaCl
        let bobsk = Scalar([0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
                           ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
                           ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
                           ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb]);
        let alicepk = GroupElement([0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
                                   ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
                                   ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
                                   ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a]);
        let k_expected = [0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
                         ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
                         ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
                         ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42];
        let GroupElement(k) = scalarmult(&bobsk, &alicepk);
        assert!(k == k_expected);
    }
}

#[cfg(feature = "benchmarks")]
#[cfg(test)]
mod bench {
    extern crate test;
    use randombytes::randombytes_into;
    use super::*;

    #[bench]
    fn bench_scalarmult(b: &mut test::Bencher) {
        let mut gbs = [0u8; BYTES];
        let mut sbs = [0u8; SCALARBYTES];
        randombytes_into(&mut gbs);
        randombytes_into(&mut sbs);
        let g = GroupElement(gbs);
        let s = Scalar(sbs);
        b.iter(|| {
            scalarmult(&s, &g);
        });
    }

    #[bench]
    fn bench_scalarmult_base(b: &mut test::Bencher) {
        let mut sbs = [0u8; SCALARBYTES];
        randombytes_into(&mut sbs);
        let s = Scalar(sbs);
        b.iter(|| {
            scalarmult_base(&s);
        });
    }
}
<commit_msg>Zero scalars when dropped<commit_after>//! `crypto_scalarmult_curve25519` specified in
//! [Cryptography in NaCl](http://nacl.cr.yp.to/valid.html), Sections 2, 3, and 4.
//! This function is conjectured to be strong. For background see Bernstein,
//! "Curve25519: new Diffie-Hellman speed records," Lecture Notes in Computer
//! Science 3958 (2006), 207–228, http://cr.yp.to/papers.html#curve25519.
use ffi;

pub const BYTES: usize = ffi::crypto_scalarmult_curve25519_BYTES;
pub const SCALARBYTES: usize = ffi::crypto_scalarmult_curve25519_SCALARBYTES;

/// `Scalar` value (integer in byte representation)
#[derive(Copy)]
pub struct Scalar(pub [u8; SCALARBYTES]);

newtype_drop!(Scalar);
newtype_clone!(Scalar);
newtype_impl!(Scalar, SCALARBYTES);

/// `GroupElement`
#[derive(Copy)]
pub struct GroupElement(pub [u8; BYTES]);

newtype_clone!(GroupElement);
newtype_impl!(GroupElement, BYTES);

/// `scalarmult()` multiplies a group element `p`
/// by an integer `n`. It returns the resulting group element
/// `q`.
pub fn scalarmult(&Scalar(ref n): &Scalar,
                  &GroupElement(ref p): &GroupElement) -> GroupElement {
    let mut q = [0; BYTES];
    unsafe {
        ffi::crypto_scalarmult_curve25519(&mut q, n, p);
    }
    GroupElement(q)
}

/// `scalarmult_base()` computes the scalar product of a standard
/// group element and an integer `n`. It returns the resulting
/// group element `q`/
pub fn scalarmult_base(&Scalar(ref n): &Scalar) -> GroupElement {
    let mut q = [0; BYTES];
    unsafe {
        ffi::crypto_scalarmult_curve25519_base(&mut q, n);
    }
    GroupElement(q)
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_vector_1() {
        // corresponding to tests/scalarmult.c and tests/scalarmult3.cpp from NaCl
        let alicesk = Scalar([0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
                             ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
                             ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
                             ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a]);
        let alicepk_expected = [0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
                               ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
                               ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
                               ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a];
        let GroupElement(alicepk) = scalarmult_base(&alicesk);
        assert!(alicepk == alicepk_expected);
    }

    #[test]
    fn test_vector_2() {
        // corresponding to tests/scalarmult2.c and tests/scalarmult4.cpp from NaCl
        let bobsk = Scalar([0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
                           ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
                           ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
                           ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb]);
        let bobpk_expected = [0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
                             ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
                             ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
                             ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f];
        let GroupElement(bobpk) = scalarmult_base(&bobsk);
        assert!(bobpk == bobpk_expected);
    }

    #[test]
    fn test_vector_3() {
        // corresponding to tests/scalarmult5.c and tests/scalarmult7.cpp from NaCl
        let alicesk = Scalar([0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
                             ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
                             ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
                             ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a]);
        let bobpk = GroupElement([0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
                                 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
                                 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
                                 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f]);
        let k_expected = [0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
                         ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
                         ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
                         ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42];
        let GroupElement(k) = scalarmult(&alicesk, &bobpk);
        assert!(k == k_expected);
    }

    #[test]
    fn test_vector_4() {
        // corresponding to tests/scalarmult6.c from NaCl
        let bobsk = Scalar([0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
                           ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
                           ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
                           ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb]);
        let alicepk = GroupElement([0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
                                   ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
                                   ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
                                   ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a]);
        let k_expected = [0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
                         ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
                         ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
                         ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42];
        let GroupElement(k) = scalarmult(&bobsk, &alicepk);
        assert!(k == k_expected);
    }
}

#[cfg(feature = "benchmarks")]
#[cfg(test)]
mod bench {
    extern crate test;
    use randombytes::randombytes_into;
    use super::*;

    #[bench]
    fn bench_scalarmult(b: &mut test::Bencher) {
        let mut gbs = [0u8; BYTES];
        let mut sbs = [0u8; SCALARBYTES];
        randombytes_into(&mut gbs);
        randombytes_into(&mut sbs);
        let g = GroupElement(gbs);
        let s = Scalar(sbs);
        b.iter(|| {
            scalarmult(&s, &g);
        });
    }

    #[bench]
    fn bench_scalarmult_base(b: &mut test::Bencher) {
        let mut sbs = [0u8; SCALARBYTES];
        randombytes_into(&mut sbs);
        let s = Scalar(sbs);
        b.iter(|| {
            scalarmult_base(&s);
        });
    }
}
<|endoftext|>


<commit_before>use crate::nodes::Node;
use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct GenericRequest<P> {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// An identifier for the request established by the client
    /// The standard allows this to be a number or a string but here we use
    /// `u64` because it proved to require less code and is probably more efficient.
    pub id: Option<u64>,

    /// Parameters of the method call
    pub params: P,
}

/// A JSON-RPC 2.0 request
///
/// @see {@link https://www.jsonrpc.org/specification#request_object}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "method", rename_all = "lowercase")]
pub enum Request {
    Decode(GenericRequest<crate::decode::rpc::Params>),
    Execute(GenericRequest<crate::execute::rpc::Params>),
}

impl Request {
    pub fn id(&self) -> Option<u64> {
        match self {
            Request::Decode(request) => request.id,
            Request::Execute(request) => request.id,
        }
    }

    pub fn dispatch(self) -> Result<Node> {
        match self {
            Request::Decode(request) => crate::decode::rpc::decode(request.params),
            Request::Execute(request) => crate::execute::rpc::execute(request.params),
        }
    }
}

/// A JSON-RPC 2.0 response
///
/// @see {@link https://www.jsonrpc.org/specification#response_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Response {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: String,

    /// The id of the request that this response is for
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<u64>,

    /// The result of the method call
    #[serde(skip_serializing_if = "Option::is_none")]
    pub result: Option<Node>,

    /// Any error that may have occurred
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<Error>,
}

impl Response {
    pub fn new(id: Option<u64>, result: Option<Node>, error: Option<anyhow::Error>) -> Self {
        Response {
            id,
            result,
            error: match error {
                Some(error) => Some(Error::server_error(&error.to_string())),
                None => None,
            },
            ..Default::default()
        }
    }
}

impl Default for Response {
    fn default() -> Self {
        Self {
            jsonrpc: "2.0".to_string(),
            id: None,
            result: None,
            error: None,
        }
    }
}

/// A JSON-RPC 2.0 error
///
/// @see {@link https://www.jsonrpc.org/specification#error_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Error {
    /// A number that indicates the error type that ocurred
    pub code: i16,

    /// A string providing a short description of the error
    pub message: String,

    /// A value that contains additional information about the error
    pub data: Option<serde_json::Value>,
}

impl Error {
    /// Create an error
    pub fn new(code: i16, message: &str, data: Option<serde_json::Value>) -> Self {
        Self {
            code,
            message: message.to_string(),
            data: data,
        }
    }

    /// A parse error
    pub fn parse_error(details: &str) -> Self {
        Self {
            code: -32700,
            message: format!("Error while parsing request: {}", details),
            data: Some(serde_json::json!({ "details": details })),
        }
    }

    /// An error when a client sends an invalid request
    pub fn invalid_request_error(message: &str) -> Self {
        Self {
            code: -32600,
            message: format!("Request is invalid: {}", message),
            data: None,
        }
    }

    /// An error when the requested method does not exist
    pub fn method_not_found_error(method: &str) -> Self {
        Self {
            code: -32601,
            message: format!("Method '{}' does not exist", method),
            data: None,
        }
    }

    /// An error when one of more parameters are invalid
    pub fn invalid_param_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// A generic internal server error
    pub fn server_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// An error to indicate the server lacks the requested capability
    pub fn capability_error(capability: &str, method: &str, params: &serde_json::Value) -> Self {
        Self {
            code: -32001,
            message: format!("Incapable of {}", capability),
            data: Some(serde_json::json!({
                "method": method,
                "params": params
            })),
        }
    }
}
<commit_msg>chore(*): RPC linting and refactoring<commit_after>use crate::nodes::Node;
use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct GenericRequest<P> {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// An identifier for the request established by the client
    /// The standard allows this to be a number or a string but here we use
    /// `u64` because it proved to require less code and is probably more efficient.
    /// May be `None` for notifications from the server
    pub id: Option<u64>,

    /// Parameters of the method call
    pub params: P,
}

/// A JSON-RPC 2.0 request
///
/// @see {@link https://www.jsonrpc.org/specification#request_object}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "method", rename_all = "lowercase")]
pub enum Request {
    Decode(GenericRequest<crate::decode::rpc::Params>),
    Execute(GenericRequest<crate::execute::rpc::Params>),
}

impl Request {
    pub fn id(&self) -> Option<u64> {
        match self {
            Request::Decode(request) => request.id,
            Request::Execute(request) => request.id,
        }
    }

    pub fn dispatch(self) -> Result<Node> {
        match self {
            Request::Decode(request) => crate::decode::rpc::decode(request.params),
            Request::Execute(request) => crate::execute::rpc::execute(request.params),
        }
    }
}

/// A JSON-RPC 2.0 response
///
/// @see {@link https://www.jsonrpc.org/specification#response_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Response {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// The id of the request that this response is for
    /// May be `None` for notifications from the server
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<u64>,

    /// The result of the method call
    #[serde(skip_serializing_if = "Option::is_none")]
    pub result: Option<Node>,

    /// Any error that may have occurred
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<Error>,
}

impl Response {
    pub fn new(id: Option<u64>, result: Option<Node>, error: Option<anyhow::Error>) -> Self {
        Response {
            id,
            result,
            error: match error {
                Some(error) => Some(Error::server_error(&error.to_string())),
                None => None,
            },
            ..Default::default()
        }
    }
}

impl Default for Response {
    fn default() -> Self {
        Self {
            jsonrpc: Some("2.0".to_string()),
            id: None,
            result: None,
            error: None,
        }
    }
}

/// A JSON-RPC 2.0 error
///
/// @see {@link https://www.jsonrpc.org/specification#error_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Error {
    /// A number that indicates the error type that ocurred
    pub code: i16,

    /// A string providing a short description of the error
    pub message: String,

    /// A value that contains additional information about the error
    pub data: Option<serde_json::Value>,
}

impl Error {
    /// Create an error
    pub fn new(code: i16, message: &str, data: Option<serde_json::Value>) -> Self {
        Self {
            code,
            message: message.to_string(),
            data,
        }
    }

    /// A parse error
    pub fn parse_error(details: &str) -> Self {
        Self {
            code: -32700,
            message: format!("Error while parsing request: {}", details),
            data: Some(serde_json::json!({ "details": details })),
        }
    }

    /// An error when a client sends an invalid request
    pub fn invalid_request_error(message: &str) -> Self {
        Self {
            code: -32600,
            message: format!("Request is invalid: {}", message),
            data: None,
        }
    }

    /// An error when the requested method does not exist
    pub fn method_not_found_error(method: &str) -> Self {
        Self {
            code: -32601,
            message: format!("Method '{}' does not exist", method),
            data: None,
        }
    }

    /// An error when one of more parameters are invalid
    pub fn invalid_param_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// A generic internal server error
    pub fn server_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// An error to indicate the server lacks the requested capability
    pub fn capability_error(capability: &str, method: &str, params: &serde_json::Value) -> Self {
        Self {
            code: -32001,
            message: format!("Incapable of {}", capability),
            data: Some(serde_json::json!({
                "method": method,
                "params": params
            })),
        }
    }
}
<|endoftext|>


<commit_before>use card_strategy::CardStrategy;

use card::Card;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;

#[derive(Debug)]
pub struct DefensiveCardStrategy;

/*
    Play 2 of clubs if in hand.
    If going to win a deal, do so with highest ranking card.
*/
impl DefensiveCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus) -> (i32, i32, i32, i32) {
        let card_penalty_to_me = Self::card_penalty_to_me(card, game_status);
        let card_penalty = 0 - Self::card_penalty(card, game_status);
        let trouble = Self::trouble_score(card, game_status);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card)
            .map(|penalty| *penalty)
            .unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            Self::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn trouble_score(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            let trouble = u32::from(card.rank) as i32;
            if Self::card_penalty_to_me(card, game_status) < 0 {
                0 - trouble
            } else {
                trouble
            }
        } else {
            0
        }
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        game_status.my_in_progress_deal.as_ref().and_then(|deal|
            deal.suit.and_then(|suit|
                deal.deal_cards.iter()
                    .map(|deal_card| deal_card.card)
                    .filter(|card| card.suit == suit)
                    .max()
                    .map(|winning_card| card.suit == suit && card.rank > winning_card.rank))).unwrap_or(true)
    }
}

impl CardStrategy for DefensiveCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        // Need to order cards by potential to win lowest penalty hands
        let mut initial_hand = game_status.my_initial_hand.iter().collect::<Vec<&Card>>();
        initial_hand.reverse();
        initial_hand.into_iter().take(3).collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards = game_status.my_current_hand.iter()
            .filter(|card| Some(card.suit) == current_suit)
            .collect::<Vec<&Card>>();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        valid_cards.into_iter()
            .map(|card| ((Self::score_card(card, game_status), card), card))
            .collect::<BTreeMap<((i32, i32, i32, i32), &Card), &Card>>()
            .values()
            .next()
            .expect("No valid cards to play!")
    }

}<commit_msg>add dev note<commit_after>use card_strategy::CardStrategy;

use card::Card;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;

#[derive(Debug)]
pub struct DefensiveCardStrategy;

/*
    Play 2 of clubs if in hand.
    If going to win a deal, do so with highest ranking card.
*/
impl DefensiveCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus) -> (i32, i32, i32, i32) {
        let card_penalty_to_me = Self::card_penalty_to_me(card, game_status);
        let card_penalty = 0 - Self::card_penalty(card, game_status);
        let trouble = Self::trouble_score(card, game_status);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card)
            .map(|penalty| *penalty)
            .unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            Self::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn trouble_score(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            let trouble = u32::from(card.rank) as i32;
            if Self::card_penalty_to_me(card, game_status) < 0 {
                0 - trouble
            } else {
                trouble
            }
        } else {
            0
        }
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        game_status.my_in_progress_deal.as_ref().and_then(|deal|
            deal.suit.and_then(|suit|
                deal.deal_cards.iter()
                    .map(|deal_card| deal_card.card)
                    .filter(|card| card.suit == suit)
                    .max()
                    .map(|winning_card| card.suit == suit && card.rank > winning_card.rank))).unwrap_or(true)
    }
}

impl CardStrategy for DefensiveCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        // Need to order cards by potential to win lowest penalty hands
        // make sure high risk cards are passed, including those that will win high risk cards (Queen of Spades)
        let mut initial_hand = game_status.my_initial_hand.iter().collect::<Vec<&Card>>();
        initial_hand.reverse();
        initial_hand.into_iter().take(3).collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards = game_status.my_current_hand.iter()
            .filter(|card| Some(card.suit) == current_suit)
            .collect::<Vec<&Card>>();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        valid_cards.into_iter()
            .map(|card| ((Self::score_card(card, game_status), card), card))
            .collect::<BTreeMap<((i32, i32, i32, i32), &Card), &Card>>()
            .values()
            .next()
            .expect("No valid cards to play!")
    }

}<|endoftext|>


<commit_before>extern crate crossbeam;
#[macro_use] extern crate version;
extern crate walkdir;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;

use walkdir::WalkDir;
use crossbeam::*;

fn help(cmds: Vec<String>) {
    println!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:
    "#);

    for cmd in cmds.iter() {
        println!("\t{}", cmd);
    }

    println!(r#"

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#);
}

fn get_commands() -> Vec<String> {
    let path = env::var("PATH");
    if path.is_err() {
        println!("PATH error: {:?}", path);
        exit(1);
    }
    let pathelements = path.unwrap();
    let pathelements = pathelements.split(":");

    let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
        .map(|elem| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    WalkDir::new(elem)
                        .max_depth(1)
                        .into_iter()
                        .filter(|path| {
                            match path {
                                &Ok(ref path) => path.path().starts_with(format!("{}/imag-", elem)),
                                &Err(_)   => false,
                            }
                        })
                        .filter_map(|x| x.ok())
                        .map(|path| {
                            path.path()
                                .to_str()
                                .map(String::from)
                        })
                        .filter_map(|x| x)
                        .collect()
                })
            })
        })
        .collect();

    let mut execs = vec![];
    for joinhandle in joinhandles.into_iter() {
        let mut v = joinhandle.join();
        execs.append(&mut v);
    }

    execs
}

fn find_command() -> Option<String> {
    env::args().skip(1).filter(|x| !x.starts_with("-")).next()
}

fn find_args(command: &str) -> Vec<String> {
    env::args()
        .skip(1)
        .position(|e| e == command)
        .map(|pos| env::args().skip(pos + 2).collect::<Vec<String>>())
        .unwrap_or(vec![])
}

fn main() {
    let commands  = get_commands();
    let mut args  = env::args();
    let _         = args.next();
    let first_arg = match find_command() {
        Some(s) => s,
        None    => {
            help(commands);
            exit(0);
        },
    };

    match &first_arg[..] {
        "--help" | "-h" => {
            help(commands);
            exit(0);
        },

        "--version"  => println!("imag {}", &version!()[..]),

        "--versions" => {
            let mut result = vec![];
            for command in commands.iter() {
                result.push(crossbeam::scope(|scope| {
                    scope.spawn(|| {
                        let v = Command::new(command).arg("--version").output();
                        match v {
                            Ok(v) => match String::from_utf8(v.stdout) {
                                Ok(s) => format!("{} -> {}", command, s),
                                Err(e) => format!("Failed calling {} -> {:?}", command, e),
                            },
                            Err(e) => format!("Failed calling {} -> {:?}", command, e),
                        }
                    })
                }))
            }

            for versionstring in result.into_iter().map(|handle| handle.join()) {
                println!("{}", versionstring);
            }
        },

        s => {
            match Command::new(format!("imag-{}", s))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .args(&find_args(s)[..])
                .spawn()
                .and_then(|mut handle| handle.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        println!("{} exited with non-zero exit code", s);
                        exit(exit_status.code().unwrap_or(42));
                    }
                },

                Err(e) => {
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", s);
                            exit(2);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", s);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1337);
                        }
                    }
                }
            }

        },
    }
}
<commit_msg>changed from path().starts_with(PATH/imag-) to path.filename().starts_with(imag-) for simplicity. Also filtered out the command name for displaying<commit_after>extern crate crossbeam;
#[macro_use] extern crate version;
extern crate walkdir;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;

use walkdir::WalkDir;
use crossbeam::*;

fn help(cmds: Vec<String>) {
    println!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:
    "#);

    for cmd in cmds.iter() {
        println!("\t{}", cmd);
    }

    println!(r#"

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#);
}

fn get_commands() -> Vec<String> {
    let path = env::var("PATH");
    if path.is_err() {
        println!("PATH error: {:?}", path);
        exit(1);
    }
    let pathelements = path.unwrap();
    let pathelements = pathelements.split(":");

    let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
        .map(|elem| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    WalkDir::new(elem)
                        .max_depth(1)
                        .into_iter()
                        .filter(|path| {
                            match path {
                                &Ok(ref p) => p.file_name()
                                    .to_str()
                                    .map_or(false, |filename| filename.starts_with("imag-")),
                                &Err(_)   => false,
                            }
                        })
                        .filter_map(|x| x.ok())
                        .filter_map(|path| {
                           path.file_name()
                               .to_str()
                               .map(String::from)
                        })
                        .collect()
                })
            })
        })
        .collect();

    let mut execs = vec![];
    for joinhandle in joinhandles.into_iter() {
        let mut v = joinhandle.join();
        execs.append(&mut v);
    }

    execs
}

fn find_command() -> Option<String> {
    env::args().skip(1).filter(|x| !x.starts_with("-")).next()
}

fn find_args(command: &str) -> Vec<String> {
    env::args()
        .skip(1)
        .position(|e| e == command)
        .map(|pos| env::args().skip(pos + 2).collect::<Vec<String>>())
        .unwrap_or(vec![])
}

fn main() {
    let commands  = get_commands();
    let mut args  = env::args();
    let _         = args.next();
    let first_arg = match find_command() {
        Some(s) => s,
        None    => {
            help(commands);
            exit(0);
        },
    };

    match &first_arg[..] {
        "--help" | "-h" => {
            help(commands);
            exit(0);
        },

        "--version"  => println!("imag {}", &version!()[..]),

        "--versions" => {
            let mut result = vec![];
            for command in commands.iter() {
                result.push(crossbeam::scope(|scope| {
                    scope.spawn(|| {
                        let v = Command::new(command).arg("--version").output();
                        match v {
                            Ok(v) => match String::from_utf8(v.stdout) {
                                Ok(s) => format!("{} -> {}", command, s),
                                Err(e) => format!("Failed calling {} -> {:?}", command, e),
                            },
                            Err(e) => format!("Failed calling {} -> {:?}", command, e),
                        }
                    })
                }))
            }

            for versionstring in result.into_iter().map(|handle| handle.join()) {
                println!("{}", versionstring);
            }
        },

        s => {
            match Command::new(format!("imag-{}", s))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .args(&find_args(s)[..])
                .spawn()
                .and_then(|mut handle| handle.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        println!("{} exited with non-zero exit code", s);
                        exit(exit_status.code().unwrap_or(42));
                    }
                },

                Err(e) => {
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", s);
                            exit(2);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", s);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1337);
                        }
                    }
                }
            }

        },
    }
}
<|endoftext|>


<commit_before>#[derive(Copy, Clone, Debug)]
pub enum Style {
    Default,
    Selection,
    Hint,
    StatusBar,
    InputLine,
    MenuShortcut,
    MenuEntry,
    MenuTitle
}

#[derive(Copy, Clone, Debug)]
pub enum KeyPress {
    Key(char),
    Shortcut(char),
    Left,
    Right,
    Up,
    Down,
    PageUp,
    PageDown,
    Home,
    End,
    Backspace,
    Delete,
    Tab,
    Insert,
    Enter,
    Esc
}

pub enum Event {
    KeyPressEvent(KeyPress),
    Resize(usize, usize),
}

pub trait Frontend {
    fn clear(&self);
    fn present(&self);
    fn print_style(&self, x: usize, y: usize, style: Style, s: &str);
    fn print_char_style(&self, x: usize, y: usize, style: Style, c: char);
    fn print_slice_style(&self, x: usize, y: usize, style: Style, chars: &[char]);
    fn set_cursor(&mut self, x: isize, y: isize);
    fn height(&self) -> usize;
    fn width(&self) -> usize;
    fn poll_event(&mut self) -> Event;
}
<commit_msg>Make frontend event debuggable and copyable<commit_after>#[derive(Copy, Clone, Debug)]
pub enum Style {
    Default,
    Selection,
    Hint,
    StatusBar,
    InputLine,
    MenuShortcut,
    MenuEntry,
    MenuTitle
}

#[derive(Copy, Clone, Debug)]
pub enum KeyPress {
    Key(char),
    Shortcut(char),
    Left,
    Right,
    Up,
    Down,
    PageUp,
    PageDown,
    Home,
    End,
    Backspace,
    Delete,
    Tab,
    Insert,
    Enter,
    Esc
}

#[derive(Copy, Clone, Debug)]
pub enum Event {
    KeyPressEvent(KeyPress),
    Resize(usize, usize),
}

pub trait Frontend {
    fn clear(&self);
    fn present(&self);
    fn print_style(&self, x: usize, y: usize, style: Style, s: &str);
    fn print_char_style(&self, x: usize, y: usize, style: Style, c: char);
    fn print_slice_style(&self, x: usize, y: usize, style: Style, chars: &[char]);
    fn set_cursor(&mut self, x: isize, y: isize);
    fn height(&self) -> usize;
    fn width(&self) -> usize;
    fn poll_event(&mut self) -> Event;
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Initial 32-bit bootloader for x86_64
#![crate_name = "boot"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![feature(static_recursion)]
#![feature(linkage)]
#![feature(struct_field_attributes)]
#![feature(stmt_expr_attributes)]
#![no_std]

const TABLE_LENGTH: usize = 512;

type Table = [u64; TABLE_LENGTH];

use core::ptr;
//
// #[lang = "panic_fmt"]
// #[cold]
// unsafe extern fn panic_fmt() -> ! {
//     boot_write(b"boot panic occurred!");
//     die();
// }

#[repr(C, packed)]
pub struct Gdt { _null: u64
               , code: u64
               , data: u64
               , _pad: u16
               , pub ptr: GdtPointer
        //    , ptr: GdtPointer
           }

#[repr(C, packed)]
pub struct GdtPointer { /// the length of the descriptor table
                     pub limit: u16
                   , /// pointer to the region in memory
                     /// containing the descriptor table.
                     pub base: &'static Gdt
                   }

// TODO: this sucks please fix
#[link_name = ".gdt64"]
#[link_section = ".gdt"]
#[no_mangle]
pub static GDT: Gdt
    = Gdt { _null: 0
          , #[export_name = "gdt64.code"] #[no_mangle]
            code: (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
          , data: (1 << 44) | (1 << 47) | (1 << 41)
          , _pad: 0
          , ptr:
                #[no_mangle]
                GdtPointer { limit: 23
                            , base: &GDT
                            }
          };

// #[no_mangle]
// static mut GDT_PTR: GdtPointer
//     = GdtPointer { limit: 15
//                  , base: &GDT
//                  };

#[inline(always)]
#[naked]
fn boot_write(s: &[u8]) {
	// use core::ptr;
    let mut offset = 0;
    unsafe {
        let vga_buf: *mut u16 = 0xb8000 as *mut u16;
    	for c in s {
    		ptr::write_volatile( vga_buf.offset(offset)
                               , 0x0200 + *c as u16);
    		offset += 1;
    	}

    }

}
macro_rules! write_char {
    ($c:expr) => {
        ptr::write_volatile(0xb8000 as *mut u16, 0x0200 + $c as u16)
    }
}

extern "C" {
    static mut pml4_table: Table;
    static mut pdp_table: Table;
    static mut pd_table: Table;    // static mut page_table: Table;
    fn arch_init(mboot: u64);
}

// #[naked]
// #[inline(always)]
// unsafe fn set_cs(cs: u16) {
//     asm!("ljmpl $0, $$fake_label
//           fake_label: \n\t"
//         :
//         : "i"(cs)
//         : "ax"
//         : "volatile"
//         );
// }

#[naked]
#[inline(always)]
pub unsafe fn create_page_tables() {
    // 3. if everything is okay, create the page tables and start long mode
    const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB

    //-- map the PML4 and PDP tables -----------------------------------------
    // recursive map last PML4 entry
    pml4_table[511] = (&pml4_table[0] as *const _ as u64) | 3;
    // map first PML4 entry to PDP table
    pml4_table[0] = (&pdp_table[0] as *const _ as u64) | 3;
    // map first PDPT entry to PD table
    pdp_table[0] = (&pd_table[0] as *const _ as u64) | 3;

    boot_write(b"3.1");

    //-- map the PD table ----------------------------------------------------
    for (number, entry) in pd_table.iter_mut().enumerate() {
        // set each PD entry equal to the start address of the page (the page
        // number times the page's size)
        let addr = number as u64 * HUGE_PAGE_SIZE;
        // with the appropriate flags (present + writable + huge)
        // TODO: do we want to do this using bitflags, or is that too
        //       heavyweight for the boot module?
        //          - eliza, 1/23/2017
        *entry = addr | 0b10000011;
    }
}

#[naked]
#[inline(always)]
pub unsafe fn set_long_mode() {
    // load PML4 addr to cr3
    asm!( "mov  eax, pml4_table
           mov   cr3, eax"
        :::: "intel");
    // boot_write(b"3.2");
    // enable PAE flag in cr4
    asm!( "mov   eax, cr4
           or    eax, 1 << 5
           mov   cr4, eax"
        :::: "intel");
    // boot_write(b"3.3");

    // set the long mode bit in EFER MSR (model specific register)
    asm!( "mov   ecx, 0xC0000080
           rdmsr
           or    eax, 1 << 8
           wrmsr"
        :::: "intel");
    boot_write(b"3.4");

    // enable paging in cr0
    asm!( "mov  eax, cr0
           or   eax, 1 << 31
           or   eax, 1 << 16
           mov  cr0, eax"
        :::: "intel");
    boot_write(b"3.5");
}

#[cold]
#[no_mangle]
#[naked]
pub unsafe extern "C" fn _start() {
    // 0. Move the stack pointer to the top of the stack.
    asm!( "mov esp, stack_top"
        :::: "intel");
    boot_write(b"0");
    asm!("cli");

    // 1. Move Multiboot info pointer to edi
    let multiboot: usize;
    asm!("mov edi, $0" : "=r"(multiboot) ::: "intel");
    boot_write(b"1");

    // 2. make sure the system supports SOS
    // TODO: port this from boot.asm
    boot_write(b"2");

    create_page_tables();
    set_long_mode();

    // 4. load the 64-bit GDT
    asm!(  "lgdt ($0)"
        :: "r"(&GDT.ptr)
        :  "memory"
        );
    boot_write(b"4");

    // 5. update selectors
    asm!("mov ax, 16" :::: "intel");
    boot_write(b"5.1");
    // stack selector
    asm!("mov ss, ax" :::: "intel");
    boot_write(b"5.2");
    // data selector
    asm!("mov ds, ax" :::: "intel");
    boot_write(b"5.3");
    // extra selector
    asm!("mov es, ax" :::: "intel");
    boot_write(b"5.4");

    // 6. jump to the 64-bit boot subroutine.
    // asm!("jmp $0:$1" :: "X"(&GDT.descriptors[1]), "X"(arch_init as unsafe extern "C" fn() -> !) :: "intel");
    // asm!("jmp $0:arch_init" :: "r"(&GDT.descriptors[1] as *const u64) :: "intel");
    // arch_init();
    // asm!(  "jmp $0:arch_init"
    //     :: "r"(&GDT.code as *const _ as usize -
    //            &GDT as *const _ as usize)
    //     :: "intel");
    // asm!( "ljmp $0:$1" :: "X"(8), "X"("arch_init"):: "volatile", "intel");

    // asm!("ljmpw $$0x0008, $$arch_init"
    //     :: // "i"(arch_init)
    //     :: "volatile");
    asm!(  "ljmpl $$8, $$arch_init"
        :: //"I"((&GDT.code as *const _ as usize) - &GDT as *const _ as usize)
        :: "volatile"
       );
    // asm!("jmp far 0x0008:arch_init" :::: "intel", "volatile");
    // set_cs(0x0008);
    // loop { boot_write(b"hey i set the code segment selector"); }
    // asm!("calll $$arch_init");
    // arch_init(multiboot as u64);
    // asm!("ljmpl $$0x0008, $$0x106000");
    // asm!("ljmpl *(arch_init)");
    // asm!("ljmpl [arch_init]" );

}
<commit_msg>[boot] slightly prettier code for setting long mode?<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Initial 32-bit bootloader for x86_64
#![crate_name = "boot"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![feature(static_recursion)]
#![feature(linkage)]
#![feature(struct_field_attributes)]
#![feature(stmt_expr_attributes)]
#![no_std]

const TABLE_LENGTH: usize = 512;

type Table = [u64; TABLE_LENGTH];

use core::ptr;
//
// #[lang = "panic_fmt"]
// #[cold]
// unsafe extern fn panic_fmt() -> ! {
//     boot_write(b"boot panic occurred!");
//     die();
// }

#[repr(C, packed)]
pub struct Gdt { _null: u64
               , code: u64
               , data: u64
               , _pad: u16
               , pub ptr: GdtPointer
        //    , ptr: GdtPointer
           }

#[repr(C, packed)]
pub struct GdtPointer { /// the length of the descriptor table
                     pub limit: u16
                   , /// pointer to the region in memory
                     /// containing the descriptor table.
                     pub base: &'static Gdt
                   }

// TODO: this sucks please fix
#[link_name = ".gdt64"]
#[link_section = ".gdt"]
#[no_mangle]
pub static GDT: Gdt
    = Gdt { _null: 0
          , #[export_name = "gdt64.code"] #[no_mangle]
            code: (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
          , data: (1 << 44) | (1 << 47) | (1 << 41)
          , _pad: 0
          , ptr:
                #[no_mangle]
                GdtPointer { limit: 23
                            , base: &GDT
                            }
          };

// #[no_mangle]
// static mut GDT_PTR: GdtPointer
//     = GdtPointer { limit: 15
//                  , base: &GDT
//                  };

#[inline(always)]
#[naked]
fn boot_write(s: &[u8]) {
	// use core::ptr;
    let mut offset = 0;
    unsafe {
        let vga_buf: *mut u16 = 0xb8000 as *mut u16;
    	for c in s {
    		ptr::write_volatile( vga_buf.offset(offset)
                               , 0x0200 + *c as u16);
    		offset += 1;
    	}

    }

}
macro_rules! write_char {
    ($c:expr) => {
        ptr::write_volatile(0xb8000 as *mut u16, 0x0200 + $c as u16)
    }
}

extern "C" {
    static mut pml4_table: Table;
    static mut pdp_table: Table;
    static mut pd_table: Table;    // static mut page_table: Table;
    fn arch_init(mboot: u64);
    static mut stack_top: *mut u8;
}

// #[naked]
// #[inline(always)]
// unsafe fn set_cs(cs: u16) {
//     asm!("ljmpl $0, $$fake_label
//           fake_label: \n\t"
//         :
//         : "i"(cs)
//         : "ax"
//         : "volatile"
//         );
// }

#[naked]
#[inline(always)]
pub unsafe fn create_page_tables() {
    // 3. if everything is okay, create the page tables and start long mode
    const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB

    //-- map the PML4 and PDP tables -----------------------------------------
    // recursive map last PML4 entry
    pml4_table[511] = (&pml4_table[0] as *const _ as u64) | 3;
    // map first PML4 entry to PDP table
    pml4_table[0] = (&pdp_table[0] as *const _ as u64) | 3;
    // map first PDPT entry to PD table
    pdp_table[0] = (&pd_table[0] as *const _ as u64) | 3;

    boot_write(b"3.1");

    //-- map the PD table ----------------------------------------------------
    for (number, entry) in pd_table.iter_mut().enumerate() {
        // set each PD entry equal to the start address of the page (the page
        // number times the page's size)
        let addr = number as u64 * HUGE_PAGE_SIZE;
        // with the appropriate flags (present + writable + huge)
        // TODO: do we want to do this using bitflags, or is that too
        //       heavyweight for the boot module?
        //          - eliza, 1/23/2017
        *entry = addr | 0b10000011;
    }
}

#[naked]
pub unsafe fn set_long_mode() {
    // load PML4 addr to cr3
    asm!( "mov   cr3, $0" :: "r"(&pml4_table) :: "intel");
    boot_write(b"3.2");

    // enable PAE flag in cr4
    let mut cr4: usize;
    asm!("mov $0, cr4" : "=r"(cr4) ::: "intel");
    cr4 |= 1 << 5;
    asm!("mov cr4, $0" :: "r"(cr4) :: "intel");
    boot_write(b"3.3");

    // set the long mode bit in EFER MSR (model specific register)
    asm!( "mov   ecx, 0xC0000080
           rdmsr
           or    eax, 1 << 8
           wrmsr"
        :::: "intel");
    boot_write(b"3.4");

    // enable paging in cr0
    let mut cr0: usize;
    asm!( "mov $0, cr0" : "=r"(cr0) ::: "intel");
    cr0 |= 1 << 31;
    cr0 |= 1 << 16;
    asm!( "mov cr0, $0" :: "r"(cr0) ::: "intel");
    boot_write(b"3.5");
}

#[cold]
#[no_mangle]
#[naked]
pub unsafe extern "C" fn _start() {
    // boot_write(b"0");
    asm!("cli");

    // 1. Move Multiboot info pointer to edi
    // let multiboot: usize;
    asm!("mov edi, edx"
         : //"=r"(multiboot)
         ::: "intel"
    );
    // boot_write(b"1");

    // 2. make sure the system supports SOS
    // TODO: port this from boot.asm
    // boot_write(b"2");

    create_page_tables();
    set_long_mode();

    // 4. load the 64-bit GDT
    asm!(  "lgdt ($0)"
        :: "r"(&GDT.ptr)
        :  "memory"
        );
    // boot_write(b"4");

    // 5. update selectors
    asm!("mov ax, 16" :::: "intel");
    // boot_write(b"5.1");
    // stack selector
    asm!("mov ss, ax" :::: "intel");
    // boot_write(b"5.2");
    // data selector
    asm!("mov ds, ax" :::: "intel");
    // boot_write(b"5.3");
    // extra selector
    asm!("mov es, ax" :::: "intel");
    // boot_write(b"5.4");

    // 6. jump to the 64-bit boot subroutine.
    // asm!("jmp $0:$1" :: "X"(&GDT.descriptors[1]), "X"(arch_init as unsafe extern "C" fn() -> !) :: "intel");
    // asm!("jmp $0:arch_init" :: "r"(&GDT.descriptors[1] as *const u64) :: "intel");
    // arch_init();
    // asm!(  "jmp $0:arch_init"
    //     :: "r"(&GDT.code as *const _ as usize -
    //            &GDT as *const _ as usize)
    //     :: "intel");
    // asm!( "ljmp $0:$1" :: "X"(8), "X"("arch_init"):: "volatile", "intel");

    // asm!("ljmpw $$0x0008, $$arch_init"
    //     :: // "i"(arch_init)
    //     :: "volatile");
    asm!(  "ljmpl $$8, $$arch_init"
        :: //"I"((&GDT.code as *const _ as usize) - &GDT as *const _ as usize)
        :: "volatile"
       );
    // asm!("jmp far 0x0008:arch_init" :::: "intel", "volatile");
    // set_cs(0x0008);
    // loop { boot_write(b"hey i set the code segment selector"); }
    // asm!("calll $$arch_init");
    // arch_init(multiboot as u64);
    // asm!("ljmpl $$0x0008, $$0x106000");
    // asm!("ljmpl *(arch_init)");
    // asm!("ljmpl [arch_init]" );

}
<|endoftext|>


<commit_before>use errors::*;
use io::Stream;
use lib_futures::Async;
use lib_futures::Async::Ready;
use lib_futures::Failed;
use lib_futures::failed;
use lib_futures::Future;
use lib_futures::Poll;
use proto::NewPacket;
use std::collections::VecDeque;
use std::io;
use std::net::ToSocketAddrs;
use tokio::net::TcpStream;
use tokio::net::TcpStreamNew;
use tokio::reactor::Handle;

enum Step {
    WaitForStream(TcpStreamNew),
    Fail(Failed<TcpStream, Error>),
}

/// Future that resolves to a `Stream` connected to a MySql server.
pub struct ConnectingStream
{
    step: Step,
}

pub fn new<S>(addr: S, handle: &Handle) -> ConnectingStream
where S: ToSocketAddrs,
{
    match addr.to_socket_addrs() {
        Ok(addrs) => {
            for addr in addrs {
                let future = TcpStream::connect(&addr, handle);
                return ConnectingStream {
                    step: Step::WaitForStream(future),
                }
            }
            let err = io::Error::new(io::ErrorKind::InvalidInput,
                                     "could not resolve to any address");
            ConnectingStream {
                step: Step::Fail(failed(Error::from(err))),
            }
        },
        Err(err) => ConnectingStream {
            step: Step::Fail(failed(Error::from(err))),
        }
    }
}

impl ConnectingStream {
    fn either_poll(&mut self) -> Result<Async<TcpStream>> {
        match self.step {
            Step::WaitForStream(ref mut fut) => Ok(Ready(try_ready!(fut.poll()))),
            Step::Fail(ref mut fut) => Ok(Ready(try_ready!(fut.poll()))),
        }
    }
}

impl Future for ConnectingStream
{
    type Item = Stream;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.either_poll()) {
            stream => {
                Ok(Ready(Stream {
                    closed: false,
                    next_packet: Some(NewPacket::empty().parse()),
                    buf: Some(VecDeque::new()),
                    endpoint: Some(stream)
                }))
            }
        }
    }
}<commit_msg>Use steps! for ConnectingStream future<commit_after>use errors::*;
use io::Stream;
use lib_futures::Async;
use lib_futures::Async::Ready;
use lib_futures::Failed;
use lib_futures::failed;
use lib_futures::Future;
use lib_futures::Poll;
use proto::NewPacket;
use std::collections::VecDeque;
use std::io;
use std::net::ToSocketAddrs;
use tokio::net::TcpStream;
use tokio::net::TcpStreamNew;
use tokio::reactor::Handle;

steps! {
    ConnectingStream {
        WaitForStream(TcpStreamNew),
        Fail(Failed<(), Error>),
    }
}

/// Future that resolves to a `Stream` connected to a MySql server.
pub struct ConnectingStream
{
    step: Step,
}

pub fn new<S>(addr: S, handle: &Handle) -> ConnectingStream
where S: ToSocketAddrs,
{
    match addr.to_socket_addrs() {
        Ok(addrs) => {
            for addr in addrs {
                let future = TcpStream::connect(&addr, handle);
                return ConnectingStream {
                    step: Step::WaitForStream(future),
                }
            }
            let err = io::Error::new(io::ErrorKind::InvalidInput,
                                     "could not resolve to any address");
            ConnectingStream {
                step: Step::Fail(failed(err.into())),
            }
        },
        Err(err) => ConnectingStream {
            step: Step::Fail(failed(err.into())),
        }
    }
}

impl Future for ConnectingStream
{
    type Item = Stream;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.either_poll()) {
            Out::WaitForStream(stream) => {
                Ok(Ready(Stream {
                    closed: false,
                    next_packet: Some(NewPacket::empty().parse()),
                    buf: Some(VecDeque::new()),
                    endpoint: Some(stream)
                }))
            },
            Out::Fail(_) => unreachable!(),
        }
    }
}<|endoftext|>