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

//! This module implements some validity checks for attributes.
//! In particular it verifies that `#[inline]` and `#[repr]` attributes are
//! attached to items that actually support them and if there are
//! conflicts between multiple such attributes attached to the same
//! item.

use session::Session;

use syntax::ast;
use syntax::visit;
use syntax::visit::Visitor;

#[derive(Copy, Clone, PartialEq)]
enum Target {
    Fn,
    Struct,
    Union,
    Enum,
    Other,
}

impl Target {
    fn from_item(item: &ast::Item) -> Target {
        match item.node {
            ast::ItemKind::Fn(..) => Target::Fn,
            ast::ItemKind::Struct(..) => Target::Struct,
            ast::ItemKind::Union(..) => Target::Union,
            ast::ItemKind::Enum(..) => Target::Enum,
            _ => Target::Other,
        }
    }
}

struct CheckAttrVisitor<'a> {
    sess: &'a Session,
}

impl<'a> CheckAttrVisitor<'a> {
    /// Check any attribute.
    fn check_attribute(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
        if let Some(name) = attr.name() {
            match &*name.as_str() {
                "inline" => self.check_inline(attr, item, target),
                "repr" => self.check_repr(attr, item, target),
                _ => (),
            }
        }
    }

    /// Check if an `#[inline]` is applied to a function.
    fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
        if target != Target::Fn {
            struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
                .span_label(item.span, "not a function")
                .emit();
        }
    }

    /// Check if an `#[repr]` attr is valid.
    fn check_repr(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
        let words = match attr.meta_item_list() {
            Some(words) => words,
            None => {
                return;
            }
        };

        let mut conflicting_reprs = 0;

        for word in words {

            let name = match word.name() {
                Some(word) => word,
                None => continue,
            };

            let (message, label) = match &*name.as_str() {
                "C" => {
                    conflicting_reprs += 1;
                    if target != Target::Struct &&
                            target != Target::Union &&
                            target != Target::Enum {
                                ("attribute should be applied to struct, enum or union",
                                 "a struct, enum or union")
                    } else {
                        continue
                    }
                }
                "packed" => {
                    // Do not increment conflicting_reprs here, because "packed"
                    // can be used to modify another repr hint
                    if target != Target::Struct &&
                            target != Target::Union {
                                ("attribute should be applied to struct or union",
                                 "a struct or union")
                    } else {
                        continue
                    }
                }
                "simd" => {
                    conflicting_reprs += 1;
                    if target != Target::Struct {
                        ("attribute should be applied to struct",
                         "a struct")
                    } else {
                        continue
                    }
                }
                "align" => {
                    if target != Target::Struct &&
                            target != Target::Union {
                        ("attribute should be applied to struct or union",
                         "a struct or union")
                    } else {
                        continue
                    }
                }
                "i8" | "u8" | "i16" | "u16" |
                "i32" | "u32" | "i64" | "u64" |
                "isize" | "usize" => {
                    conflicting_reprs += 1;
                    if target != Target::Enum {
                        ("attribute should be applied to enum",
                         "an enum")
                    } else {
                        continue
                    }
                }
                _ => continue,
            };
            struct_span_err!(self.sess, attr.span, E0517, "{}", message)
                .span_label(item.span, format!("not {}", label))
                .emit();
        }
        if conflicting_reprs > 1 {
            span_warn!(self.sess, attr.span, E0566,
                       "conflicting representation hints");
        }
    }
}

impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
    fn visit_item(&mut self, item: &'a ast::Item) {
        let target = Target::from_item(item);
        for attr in &item.attrs {
            self.check_attribute(attr, item, target);
        }
        visit::walk_item(self, item);
    }
}

pub fn check_crate(sess: &Session, krate: &ast::Crate) {
    visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
}
<commit_msg>Prevent repr(C, u8) from triggering a warning on non-clike enums<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module implements some validity checks for attributes.
//! In particular it verifies that `#[inline]` and `#[repr]` attributes are
//! attached to items that actually support them and if there are
//! conflicts between multiple such attributes attached to the same
//! item.

use session::Session;

use syntax::ast;
use syntax::visit;
use syntax::visit::Visitor;

#[derive(Copy, Clone, PartialEq)]
enum Target {
    Fn,
    Struct,
    Union,
    Enum,
    Other,
}

impl Target {
    fn from_item(item: &ast::Item) -> Target {
        match item.node {
            ast::ItemKind::Fn(..) => Target::Fn,
            ast::ItemKind::Struct(..) => Target::Struct,
            ast::ItemKind::Union(..) => Target::Union,
            ast::ItemKind::Enum(..) => Target::Enum,
            _ => Target::Other,
        }
    }
}

struct CheckAttrVisitor<'a> {
    sess: &'a Session,
}

impl<'a> CheckAttrVisitor<'a> {
    /// Check any attribute.
    fn check_attribute(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
        if let Some(name) = attr.name() {
            match &*name.as_str() {
                "inline" => self.check_inline(attr, item, target),
                "repr" => self.check_repr(attr, item, target),
                _ => (),
            }
        }
    }

    /// Check if an `#[inline]` is applied to a function.
    fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
        if target != Target::Fn {
            struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
                .span_label(item.span, "not a function")
                .emit();
        }
    }

    /// Check if an `#[repr]` attr is valid.
    fn check_repr(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
        let words = match attr.meta_item_list() {
            Some(words) => words,
            None => {
                return;
            }
        };

        let mut int_reprs = 0;
        let mut is_c = false;
        let mut is_simd = false;

        for word in words {

            let name = match word.name() {
                Some(word) => word,
                None => continue,
            };

            let (message, label) = match &*name.as_str() {
                "C" => {
                    is_c = true;
                    if target != Target::Struct &&
                            target != Target::Union &&
                            target != Target::Enum {
                                ("attribute should be applied to struct, enum or union",
                                 "a struct, enum or union")
                    } else {
                        continue
                    }
                }
                "packed" => {
                    // Do not increment conflicting_reprs here, because "packed"
                    // can be used to modify another repr hint
                    if target != Target::Struct &&
                            target != Target::Union {
                                ("attribute should be applied to struct or union",
                                 "a struct or union")
                    } else {
                        continue
                    }
                }
                "simd" => {
                    is_simd = true;
                    if target != Target::Struct {
                        ("attribute should be applied to struct",
                         "a struct")
                    } else {
                        continue
                    }
                }
                "align" => {
                    if target != Target::Struct &&
                            target != Target::Union {
                        ("attribute should be applied to struct or union",
                         "a struct or union")
                    } else {
                        continue
                    }
                }
                "i8" | "u8" | "i16" | "u16" |
                "i32" | "u32" | "i64" | "u64" |
                "isize" | "usize" => {
                    int_reprs += 1;
                    if target != Target::Enum {
                        ("attribute should be applied to enum",
                         "an enum")
                    } else {
                        continue
                    }
                }
                _ => continue,
            };
            struct_span_err!(self.sess, attr.span, E0517, "{}", message)
                .span_label(item.span, format!("not {}", label))
                .emit();
        }

        // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
        if (int_reprs > 1)
           || (is_simd && is_c)
           || (int_reprs == 1 && is_c && is_c_like_enum(item)) {
            span_warn!(self.sess, attr.span, E0566,
                       "conflicting representation hints");
        }
    }
}

impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
    fn visit_item(&mut self, item: &'a ast::Item) {
        let target = Target::from_item(item);
        for attr in &item.attrs {
            self.check_attribute(attr, item, target);
        }
        visit::walk_item(self, item);
    }
}

pub fn check_crate(sess: &Session, krate: &ast::Crate) {
    visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
}

fn is_c_like_enum(item: &ast::Item) -> bool {
    if let ast::ItemKind::Enum(ref def, _) = item.node {
        for variant in &def.variants {
            match variant.node.data {
                ast::VariantData::Unit(_) => { /* continue */ }
                _ => { return false; }
            }
        }
        true
    } else {
        false
    }
}
<|endoftext|>


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

use dom::attr::Attr;
use dom::attr::{AttrHelpers, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, HTMLElementCast, HTMLImageElementDerived};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, LayoutJS, Rootable, Temporary};
use dom::bindings::refcounted::Trusted;
use dom::document::{Document, DocumentHelpers};
use dom::element::Element;
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{document_from_node, Node, NodeTypeId, NodeHelpers, NodeDamage, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use util::str::DOMString;
use string_cache::Atom;

use net_traits::image::base::Image;
use net_traits::image_cache_task::ImageResponder;
use url::{Url, UrlParser};

use std::borrow::ToOwned;
use std::sync::Arc;

#[dom_struct]
pub struct HTMLImageElement {
    htmlelement: HTMLElement,
    url: DOMRefCell<Option<Url>>,
    image: DOMRefCell<Option<Arc<Image>>>,
}

impl HTMLImageElementDerived for EventTarget {
    fn is_htmlimageelement(&self) -> bool {
        *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement)))
    }
}

pub trait HTMLImageElementHelpers {
    fn get_url(&self) -> Option<Url>;
}

impl<'a> HTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
    fn get_url(&self) -> Option<Url>{
        self.url.borrow().clone()
    }
}

trait PrivateHTMLImageElementHelpers {
    fn update_image(self, value: Option<(DOMString, &Url)>);
}

/// This is passed to the image cache when the src attribute
/// changes. It is returned via a message to the script task,
/// which marks the element as dirty and triggers a reflow.
struct Responder {
    element: Trusted<HTMLImageElement>,
}

impl Responder {
    fn new(element: Trusted<HTMLImageElement>) -> Responder {
        Responder {
            element: element
        }
    }
}

impl ImageResponder for Responder {
    fn respond(&self, image: Option<Arc<Image>>) {
        // Update the image field
        let element = self.element.to_temporary().root();
        let element_ref = element.r();
        *element_ref.image.borrow_mut() = image;

        // Mark the node dirty
        let node = NodeCast::from_ref(element.r());
        let document = document_from_node(node).root();
        document.r().content_changed(node, NodeDamage::OtherNodeDamage);

        // Fire image.onload
        let window = window_from_node(document.r()).root();
        let event = Event::new(GlobalRef::Window(window.r()),
                               "load".to_owned(),
                               EventBubbles::DoesNotBubble,
                               EventCancelable::NotCancelable).root();
        let event = event.r();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(node);
        event.fire(target);

        // Trigger reflow
        window.r().add_pending_reflow();
    }
}

impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
    /// Makes the local `image` member match the status of the `src` attribute and starts
    /// prefetching the image. This method must be called after `src` is changed.
    fn update_image(self, value: Option<(DOMString, &Url)>) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let document = node.owner_doc().root();
        let window = document.r().window().root();
        let window = window.r();
        let image_cache = window.image_cache_task();
        match value {
            None => {
                *self.url.borrow_mut() = None;
                *self.image.borrow_mut() = None;
            }
            Some((src, base_url)) => {
                let img_url = UrlParser::new().base_url(base_url).parse(&src);
                // FIXME: handle URL parse errors more gracefully.
                let img_url = img_url.unwrap();
                *self.url.borrow_mut() = Some(img_url.clone());

                let trusted_node = Trusted::new(window.get_cx(), self, window.script_chan());
                let responder = box Responder::new(trusted_node);
                image_cache.request_image(img_url, window.image_cache_chan(), Some(responder));
            }
        }
    }
}

impl HTMLImageElement {
    fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLImageElement {
        HTMLImageElement {
            htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLImageElement, localName, prefix, document),
            url: DOMRefCell::new(None),
            image: DOMRefCell::new(None),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> Temporary<HTMLImageElement> {
        let element = HTMLImageElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
    }
}

pub trait LayoutHTMLImageElementHelpers {
    #[allow(unsafe_code)]
    unsafe fn image(&self) -> Option<Arc<Image>>;

    #[allow(unsafe_code)]
    unsafe fn image_url(&self) -> Option<Url>;
}

impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
    #[allow(unsafe_code)]
    unsafe fn image(&self) -> Option<Arc<Image>> {
        (*self.unsafe_get()).image.borrow_for_layout().clone()
    }

    #[allow(unsafe_code)]
    unsafe fn image_url(&self) -> Option<Url> {
        (*self.unsafe_get()).url.borrow_for_layout().clone()
    }
}

impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
    make_getter!(Alt);

    make_setter!(SetAlt, "alt");

    make_url_getter!(Src);

    make_setter!(SetSrc, "src");

    make_getter!(UseMap);

    make_setter!(SetUseMap, "usemap");

    make_bool_getter!(IsMap);

    fn SetIsMap(self, is_map: bool) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute(&atom!("ismap"), is_map.to_string())
    }

    fn Width(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        rect.size.width.to_px() as u32
    }

    fn SetWidth(self, width: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("width"), width)
    }

    fn Height(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        rect.size.height.to_px() as u32
    }

    fn SetHeight(self, height: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("height"), height)
    }

    fn NaturalWidth(self) -> u32 {
        let image = self.image.borrow();

        match *image {
            Some(ref image) => image.width,
            None => 0,
        }
    }

    fn NaturalHeight(self) -> u32 {
        let image = self.image.borrow();

        match *image {
            Some(ref image) => image.height,
            None => 0,
        }
    }

    fn Complete(self) -> bool {
        let image = self.image.borrow();
        image.is_some()
    }

    make_getter!(Name);

    make_setter!(SetName, "name");

    make_getter!(Align);

    make_setter!(SetAlign, "align");

    make_uint_getter!(Hspace);

    make_uint_setter!(SetHspace, "hspace");

    make_uint_getter!(Vspace);

    make_uint_setter!(SetVspace, "vspace");

    make_getter!(LongDesc);

    make_setter!(SetLongDesc, "longdesc");

    make_getter!(Border);

    make_setter!(SetBorder, "border");
}

impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
    fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
        let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn after_set_attr(&self, attr: JSRef<Attr>) {
        if let Some(ref s) = self.super_type() {
            s.after_set_attr(attr);
        }

        match attr.local_name() {
            &atom!("src") => {
                let window = window_from_node(*self).root();
                let url = window.r().get_url();
                self.update_image(Some(((**attr.value()).to_owned(), &url)));
            },
            _ => ()
        }
    }

    fn before_remove_attr(&self, attr: JSRef<Attr>) {
        if let Some(ref s) = self.super_type() {
            s.before_remove_attr(attr);
        }

        match attr.local_name() {
            &atom!("src") => self.update_image(None),
            _ => ()
        }
    }

    fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
        match name {
            &atom!("width") | &atom!("height") |
            &atom!("hspace") | &atom!("vspace") => AttrValue::from_u32(value, 0),
            _ => self.super_type().unwrap().parse_plain_attribute(name, value),
        }
    }
}

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

use dom::attr::Attr;
use dom::attr::{AttrHelpers, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, HTMLElementCast, HTMLImageElementDerived};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, LayoutJS, Rootable, Temporary};
use dom::bindings::refcounted::Trusted;
use dom::document::{Document, DocumentHelpers};
use dom::element::Element;
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{document_from_node, Node, NodeTypeId, NodeHelpers, NodeDamage, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use util::str::DOMString;
use string_cache::Atom;

use net_traits::image::base::Image;
use net_traits::image_cache_task::ImageResponder;
use url::{Url, UrlParser};

use std::borrow::ToOwned;
use std::sync::Arc;

#[dom_struct]
pub struct HTMLImageElement {
    htmlelement: HTMLElement,
    url: DOMRefCell<Option<Url>>,
    image: DOMRefCell<Option<Arc<Image>>>,
}

impl HTMLImageElementDerived for EventTarget {
    fn is_htmlimageelement(&self) -> bool {
        *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement)))
    }
}

pub trait HTMLImageElementHelpers {
    fn get_url(&self) -> Option<Url>;
}

impl<'a> HTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
    fn get_url(&self) -> Option<Url>{
        self.url.borrow().clone()
    }
}

trait PrivateHTMLImageElementHelpers {
    fn update_image(self, value: Option<(DOMString, &Url)>);
}

/// This is passed to the image cache when the src attribute
/// changes. It is returned via a message to the script task,
/// which marks the element as dirty and triggers a reflow.
struct Responder {
    element: Trusted<HTMLImageElement>,
}

impl Responder {
    fn new(element: Trusted<HTMLImageElement>) -> Responder {
        Responder {
            element: element
        }
    }
}

impl ImageResponder for Responder {
    fn respond(&self, image: Option<Arc<Image>>) {
        // Update the image field
        let element = self.element.to_temporary().root();
        let element_ref = element.r();
        *element_ref.image.borrow_mut() = image;

        // Mark the node dirty
        let node = NodeCast::from_ref(element.r());
        let document = document_from_node(node).root();
        document.r().content_changed(node, NodeDamage::OtherNodeDamage);

        // Fire image.onload
        let window = window_from_node(document.r()).root();
        let event = Event::new(GlobalRef::Window(window.r()),
                               "load".to_owned(),
                               EventBubbles::DoesNotBubble,
                               EventCancelable::NotCancelable).root();
        let event = event.r();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(node);
        event.fire(target);

        // Trigger reflow
        window.r().add_pending_reflow();
    }
}

impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
    /// Makes the local `image` member match the status of the `src` attribute and starts
    /// prefetching the image. This method must be called after `src` is changed.
    fn update_image(self, value: Option<(DOMString, &Url)>) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let document = node.owner_doc().root();
        let window = document.r().window().root();
        let window = window.r();
        let image_cache = window.image_cache_task();
        match value {
            None => {
                *self.url.borrow_mut() = None;
                *self.image.borrow_mut() = None;
            }
            Some((src, base_url)) => {
                let img_url = UrlParser::new().base_url(base_url).parse(&src);
                // FIXME: handle URL parse errors more gracefully.
                let img_url = img_url.unwrap();
                *self.url.borrow_mut() = Some(img_url.clone());

                let trusted_node = Trusted::new(window.get_cx(), self, window.script_chan());
                let responder = box Responder::new(trusted_node);
                image_cache.request_image(img_url, window.image_cache_chan(), Some(responder));
            }
        }
    }
}

impl HTMLImageElement {
    fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLImageElement {
        HTMLImageElement {
            htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLImageElement, localName, prefix, document),
            url: DOMRefCell::new(None),
            image: DOMRefCell::new(None),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> Temporary<HTMLImageElement> {
        let element = HTMLImageElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
    }
}

pub trait LayoutHTMLImageElementHelpers {
    #[allow(unsafe_code)]
    unsafe fn image(&self) -> Option<Arc<Image>>;

    #[allow(unsafe_code)]
    unsafe fn image_url(&self) -> Option<Url>;
}

impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
    #[allow(unsafe_code)]
    unsafe fn image(&self) -> Option<Arc<Image>> {
        (*self.unsafe_get()).image.borrow_for_layout().clone()
    }

    #[allow(unsafe_code)]
    unsafe fn image_url(&self) -> Option<Url> {
        (*self.unsafe_get()).url.borrow_for_layout().clone()
    }
}

impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
    make_getter!(Alt);

    make_setter!(SetAlt, "alt");

    make_url_getter!(Src);

    make_setter!(SetSrc, "src");

    make_getter!(UseMap);

    make_setter!(SetUseMap, "usemap");

    make_bool_getter!(IsMap);

    fn SetIsMap(self, is_map: bool) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute(&atom!("ismap"), is_map.to_string())
    }

    fn Width(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        rect.size.width.to_px() as u32
    }

    fn SetWidth(self, width: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("width"), width)
    }

    fn Height(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        rect.size.height.to_px() as u32
    }

    fn SetHeight(self, height: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("height"), height)
    }

    fn NaturalWidth(self) -> u32 {
        let image = self.image.borrow();

        match *image {
            Some(ref image) => image.width,
            None => 0,
        }
    }

    fn NaturalHeight(self) -> u32 {
        let image = self.image.borrow();

        match *image {
            Some(ref image) => image.height,
            None => 0,
        }
    }

    fn Complete(self) -> bool {
        let image = self.image.borrow();
        image.is_some()
    }

    // https://html.spec.whatwg.org/#dom-img-name
    make_getter!(Name);
    make_atomic_setter!(SetName, "name");

    make_getter!(Align);

    make_setter!(SetAlign, "align");

    make_uint_getter!(Hspace);

    make_uint_setter!(SetHspace, "hspace");

    make_uint_getter!(Vspace);

    make_uint_setter!(SetVspace, "vspace");

    make_getter!(LongDesc);

    make_setter!(SetLongDesc, "longdesc");

    make_getter!(Border);

    make_setter!(SetBorder, "border");
}

impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
    fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
        let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn after_set_attr(&self, attr: JSRef<Attr>) {
        if let Some(ref s) = self.super_type() {
            s.after_set_attr(attr);
        }

        match attr.local_name() {
            &atom!("src") => {
                let window = window_from_node(*self).root();
                let url = window.r().get_url();
                self.update_image(Some(((**attr.value()).to_owned(), &url)));
            },
            _ => ()
        }
    }

    fn before_remove_attr(&self, attr: JSRef<Attr>) {
        if let Some(ref s) = self.super_type() {
            s.before_remove_attr(attr);
        }

        match attr.local_name() {
            &atom!("src") => self.update_image(None),
            _ => ()
        }
    }

    fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
        match name {
            &atom!("name") => AttrValue::from_atomic(value),
            &atom!("width") | &atom!("height") |
            &atom!("hspace") | &atom!("vspace") => AttrValue::from_u32(value, 0),
            _ => self.super_type().unwrap().parse_plain_attribute(name, value),
        }
    }
}

<|endoftext|>


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

use cssparser::RGBA;
use dom::attr::{Attr, AttrValue};
use dom::bindings::codegen::Bindings::HTMLTableElementBinding;
use dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root, RootedReference};
use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::htmlelement::HTMLElement;
use dom::htmltablecaptionelement::HTMLTableCaptionElement;
use dom::htmltablesectionelement::HTMLTableSectionElement;
use dom::node::{Node, document_from_node};
use dom::virtualmethods::VirtualMethods;
use std::cell::Cell;
use string_cache::Atom;
use util::str::{self, DOMString, LengthOrPercentageOrAuto};

#[dom_struct]
pub struct HTMLTableElement {
    htmlelement: HTMLElement,
    background_color: Cell<Option<RGBA>>,
    border: Cell<Option<u32>>,
    cellspacing: Cell<Option<u32>>,
}

impl HTMLTableElement {
    fn new_inherited(localName: Atom, prefix: Option<DOMString>, document: &Document)
                     -> HTMLTableElement {
        HTMLTableElement {
            htmlelement: HTMLElement::new_inherited(localName, prefix, document),
            background_color: Cell::new(None),
            border: Cell::new(None),
            cellspacing: Cell::new(None),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document)
               -> Root<HTMLTableElement> {
        let element = HTMLTableElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLTableElementBinding::Wrap)
    }

    pub fn get_border(&self) -> Option<u32> {
        self.border.get()
    }
}

impl HTMLTableElementMethods for HTMLTableElement {
    // https://html.spec.whatwg.org/multipage/#dom-table-caption
    fn GetCaption(&self) -> Option<Root<HTMLTableCaptionElement>> {
        self.upcast::<Node>().children().filter_map(Root::downcast).next()
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-caption
    fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) {
        if let Some(ref caption) = self.GetCaption() {
            caption.upcast::<Node>().remove_self();
        }

        if let Some(caption) = new_caption {
            let node = self.upcast::<Node>();
            node.InsertBefore(caption.upcast(), node.GetFirstChild().r())
                .expect("Insertion failed");
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createcaption
    fn CreateCaption(&self) -> Root<HTMLElement> {
        let caption = match self.GetCaption() {
            Some(caption) => caption,
            None => {
                let caption = HTMLTableCaptionElement::new(atom!("caption"),
                                                           None,
                                                           document_from_node(self).r());
                self.SetCaption(Some(caption.r()));
                caption
            }
        };
        Root::upcast(caption)
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-deletecaption
    fn DeleteCaption(&self) {
        if let Some(caption) = self.GetCaption() {
            caption.upcast::<Node>().remove_self();
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createtbody
    fn CreateTBody(&self) -> Root<HTMLTableSectionElement> {
        let tbody = HTMLTableSectionElement::new(atom!("tbody"),
                                                 None,
                                                 document_from_node(self).r());
        let node = self.upcast::<Node>();
        let last_tbody =
            node.rev_children()
                .filter_map(Root::downcast::<Element>)
                .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == &atom!("tbody"));
        let reference_element =
            last_tbody.and_then(|t| t.upcast::<Node>().GetNextSibling());

        node.InsertBefore(tbody.upcast(), reference_element.r())
            .expect("Insertion failed");
        tbody
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
    make_getter!(BgColor, "bgcolor");

    // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
    make_setter!(SetBgColor, "bgcolor");

    // https://html.spec.whatwg.org/multipage/#dom-table-width
    make_getter!(Width, "width");

    // https://html.spec.whatwg.org/multipage/#dom-table-width
    make_nonzero_dimension_setter!(SetWidth, "width");
}

pub trait HTMLTableElementLayoutHelpers {
    fn get_background_color(&self) -> Option<RGBA>;
    fn get_border(&self) -> Option<u32>;
    fn get_cellspacing(&self) -> Option<u32>;
    fn get_width(&self) -> LengthOrPercentageOrAuto;
}

impl HTMLTableElementLayoutHelpers for LayoutJS<HTMLTableElement> {
    #[allow(unsafe_code)]
    fn get_background_color(&self) -> Option<RGBA> {
        unsafe {
            (*self.unsafe_get()).background_color.get()
        }
    }

    #[allow(unsafe_code)]
    fn get_border(&self) -> Option<u32> {
        unsafe {
            (*self.unsafe_get()).border.get()
        }
    }

    #[allow(unsafe_code)]
    fn get_cellspacing(&self) -> Option<u32> {
        unsafe {
            (*self.unsafe_get()).cellspacing.get()
        }
    }

    #[allow(unsafe_code)]
    fn get_width(&self) -> LengthOrPercentageOrAuto {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("width"))
                .map(AttrValue::as_dimension)
                .cloned()
                .unwrap_or(LengthOrPercentageOrAuto::Auto)
        }
    }
}

impl VirtualMethods for HTMLTableElement {
    fn super_type(&self) -> Option<&VirtualMethods> {
        Some(self.upcast::<HTMLElement>() as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        match *attr.local_name() {
            atom!("bgcolor") => {
                self.background_color.set(mutation.new_value(attr).and_then(|value| {
                    str::parse_legacy_color(&value).ok()
                }));
            },
            atom!("border") => {
                // According to HTML5 § 14.3.9, invalid values map to 1px.
                self.border.set(mutation.new_value(attr).map(|value| {
                    str::parse_unsigned_integer(value.chars()).unwrap_or(1)
                }));
            }
            atom!("cellspacing") => {
                self.cellspacing.set(mutation.new_value(attr).and_then(|value| {
                    str::parse_unsigned_integer(value.chars())
                }));
            },
            _ => {},
        }
    }

    fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
        match *local_name {
            atom!("border") => AttrValue::from_u32(value, 1),
            atom!("width") => AttrValue::from_nonzero_dimension(value),
            _ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
        }
    }
}
<commit_msg>Remove parsed attribute 'bgcolor' field HTMLTableElement<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::RGBA;
use dom::attr::{Attr, AttrValue};
use dom::bindings::codegen::Bindings::HTMLTableElementBinding;
use dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root, RootedReference};
use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::htmlelement::HTMLElement;
use dom::htmltablecaptionelement::HTMLTableCaptionElement;
use dom::htmltablesectionelement::HTMLTableSectionElement;
use dom::node::{Node, document_from_node};
use dom::virtualmethods::VirtualMethods;
use std::cell::Cell;
use string_cache::Atom;
use util::str::{self, DOMString, LengthOrPercentageOrAuto};

#[dom_struct]
pub struct HTMLTableElement {
    htmlelement: HTMLElement,
    border: Cell<Option<u32>>,
    cellspacing: Cell<Option<u32>>,
}

impl HTMLTableElement {
    fn new_inherited(localName: Atom, prefix: Option<DOMString>, document: &Document)
                     -> HTMLTableElement {
        HTMLTableElement {
            htmlelement: HTMLElement::new_inherited(localName, prefix, document),
            border: Cell::new(None),
            cellspacing: Cell::new(None),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document)
               -> Root<HTMLTableElement> {
        let element = HTMLTableElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLTableElementBinding::Wrap)
    }

    pub fn get_border(&self) -> Option<u32> {
        self.border.get()
    }
}

impl HTMLTableElementMethods for HTMLTableElement {
    // https://html.spec.whatwg.org/multipage/#dom-table-caption
    fn GetCaption(&self) -> Option<Root<HTMLTableCaptionElement>> {
        self.upcast::<Node>().children().filter_map(Root::downcast).next()
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-caption
    fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) {
        if let Some(ref caption) = self.GetCaption() {
            caption.upcast::<Node>().remove_self();
        }

        if let Some(caption) = new_caption {
            let node = self.upcast::<Node>();
            node.InsertBefore(caption.upcast(), node.GetFirstChild().r())
                .expect("Insertion failed");
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createcaption
    fn CreateCaption(&self) -> Root<HTMLElement> {
        let caption = match self.GetCaption() {
            Some(caption) => caption,
            None => {
                let caption = HTMLTableCaptionElement::new(atom!("caption"),
                                                           None,
                                                           document_from_node(self).r());
                self.SetCaption(Some(caption.r()));
                caption
            }
        };
        Root::upcast(caption)
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-deletecaption
    fn DeleteCaption(&self) {
        if let Some(caption) = self.GetCaption() {
            caption.upcast::<Node>().remove_self();
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createtbody
    fn CreateTBody(&self) -> Root<HTMLTableSectionElement> {
        let tbody = HTMLTableSectionElement::new(atom!("tbody"),
                                                 None,
                                                 document_from_node(self).r());
        let node = self.upcast::<Node>();
        let last_tbody =
            node.rev_children()
                .filter_map(Root::downcast::<Element>)
                .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == &atom!("tbody"));
        let reference_element =
            last_tbody.and_then(|t| t.upcast::<Node>().GetNextSibling());

        node.InsertBefore(tbody.upcast(), reference_element.r())
            .expect("Insertion failed");
        tbody
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
    make_getter!(BgColor, "bgcolor");

    // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
    make_legacy_color_setter!(SetBgColor, "bgcolor");

    // https://html.spec.whatwg.org/multipage/#dom-table-width
    make_getter!(Width, "width");

    // https://html.spec.whatwg.org/multipage/#dom-table-width
    make_nonzero_dimension_setter!(SetWidth, "width");
}

pub trait HTMLTableElementLayoutHelpers {
    fn get_background_color(&self) -> Option<RGBA>;
    fn get_border(&self) -> Option<u32>;
    fn get_cellspacing(&self) -> Option<u32>;
    fn get_width(&self) -> LengthOrPercentageOrAuto;
}

impl HTMLTableElementLayoutHelpers for LayoutJS<HTMLTableElement> {
    #[allow(unsafe_code)]
    fn get_background_color(&self) -> Option<RGBA> {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("bgcolor"))
                .and_then(AttrValue::as_color)
                .cloned()
        }
    }

    #[allow(unsafe_code)]
    fn get_border(&self) -> Option<u32> {
        unsafe {
            (*self.unsafe_get()).border.get()
        }
    }

    #[allow(unsafe_code)]
    fn get_cellspacing(&self) -> Option<u32> {
        unsafe {
            (*self.unsafe_get()).cellspacing.get()
        }
    }

    #[allow(unsafe_code)]
    fn get_width(&self) -> LengthOrPercentageOrAuto {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("width"))
                .map(AttrValue::as_dimension)
                .cloned()
                .unwrap_or(LengthOrPercentageOrAuto::Auto)
        }
    }
}

impl VirtualMethods for HTMLTableElement {
    fn super_type(&self) -> Option<&VirtualMethods> {
        Some(self.upcast::<HTMLElement>() as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        match *attr.local_name() {
            atom!("border") => {
                // According to HTML5 § 14.3.9, invalid values map to 1px.
                self.border.set(mutation.new_value(attr).map(|value| {
                    str::parse_unsigned_integer(value.chars()).unwrap_or(1)
                }));
            }
            atom!("cellspacing") => {
                self.cellspacing.set(mutation.new_value(attr).and_then(|value| {
                    str::parse_unsigned_integer(value.chars())
                }));
            },
            _ => {},
        }
    }

    fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
        match *local_name {
            atom!("border") => AttrValue::from_u32(value, 1),
            atom!("width") => AttrValue::from_nonzero_dimension(value),
            atom!("bgcolor") => AttrValue::from_legacy_color(value),
            _ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
        }
    }
}
<|endoftext|>


<commit_before>fn mod_exp(mut x: u64, mut d: u64, n: u64) -> u64 {
    let mut ret = 1;
    while d != 0 {
        if d % 2 == 1 {
            ret *= x;
            if ret >= n {
                ret %= n;
            }
        }
        d /= 2;
        x *= x;
        if x >= n {
            x %= n;
        }
    }
    ret
}

/// Test if `n` is prime, using the deterministic version of the
/// Miller-Rabin test.
///
/// Doing a lot of primality tests with numbers strictly below some
/// upper bound will be faster using the `is_prime` method of a
/// `Sieve` instance.
pub fn miller_rabin(n: u64) -> bool {
    const HINT: &'static [u64] = &[2];

    // we have a strict upper bound, so we can just use the witness
    // table of Pomerance, Selfridge & Wagstaff and Jeaschke to be as
    // efficient as possible, without having to fall back to
    // randomness.
    const WITNESSES: &'static [(u64, &'static [u64])] =
        &[(2_046, HINT),
          (1_373_652, &[2, 3]),
          (9_080_190, &[31, 73]),
          (25_326_000, &[2, 3, 5]),
          (4_759_123_140, &[2, 7, 61]),
          (1_112_004_669_632, &[2, 13, 23, 1662803]),
          (2_152_302_898_746, &[2, 3, 5, 7, 11]),
          (3_474_749_660_382, &[2, 3, 5, 7, 11, 13]),
          (341_550_071_728_320, &[2, 3, 5, 7, 11, 13, 17]),
          (0xFFFF_FFFF_FFFF_FFFF, &[2, 3, 5, 7, 11, 13, 17, 19, 23])
         ];

    if n % 2 == 0 { return n == 2 }
    if n == 1 { return false }

    let mut d = n - 1;
    let mut s = 0;
    while d % 2 == 0 { d /= 2; s += 1 }

    let witnesses =
        WITNESSES.iter().find(|&&(hi, _)| hi >= n)
            .map(|&(_, wtnss)| wtnss).unwrap();
    'next_witness: for &a in witnesses.iter() {
        let mut power = mod_exp(a, d, n);
        if power == 1 { continue 'next_witness }

        for _r in 0..s {
            if power == n - 1 {
                continue 'next_witness
            }
            power *= power;
            if power >= n {
                power %= n;
            }
        }
        return false
    }

    true
}

#[cfg(test)]
mod tests {
    use primal::Sieve;

    #[test]
    fn miller_rabin() {
        const LIMIT: usize = 1_000_000;
        let sieve = Sieve::new(LIMIT);
        for x in 0..LIMIT {
            let s = sieve.is_prime(x);
            let mr = super::miller_rabin(x as u64);

            assert!(s == mr, "miller_rabin {} mismatches sieve {} for {}",
                    mr, s, x)
        }
    }
}
<commit_msg>check: support large numbers in miller_rabin properly.<commit_after>#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Debug)]
struct U128 {
    hi: u64,
    lo: u64,
}

fn modulo(mut a: U128, m: u64) -> u64 {
    if a.hi >= m {
        a.hi -= (a.hi / m) * m;
    }
    let mut x = a.hi;
    let mut y = a.lo;
    for _ in 0..64 {
        let t = (x as i64 >> 63) as u64;
        x = (x << 1) | (y >> 63);
        y <<= 1;
        if (x | t) >= m {
            x = x.wrapping_sub(m);
            y += 1;
        }
    }
    x
}
fn mul128(u: u64, v: u64) -> U128 {
    let u1 = u >> 32;
    let u0 = u & (!0 >> 32);
    let v1 = v >> 32;
    let v0 = v & (!0 >> 32);

    let t = u0 * v0;
    let w0 = t & (!0 >> 32);
    let k = t >> 32;

    let t = u1 * v0 + k;
    let w1 = t & (!0 >> 32);
    let w2 = t >> 32;

    let t = u0 * v1 + w1;
    let k = t >> 32;
    U128 {
        lo: (t << 32) + w0,
        hi: u1*v1 + w2 + k
    }
}
fn mod_mul_(a: u64, b: u64, m: u64) -> u64 {
    modulo(mul128(a, b), m)
}

fn mod_mul(a: u64, b: u64, m: u64) -> u64 {
    match a.checked_mul(b) {
        Some(r) => if r >= m { r % m } else { r },
        None => mod_mul_(a, b, m),
    }
}

fn mod_sqr(a: u64, m: u64) -> u64 {
    if a < (1 << 32) {
        let r = a * a;
        if r >= m {
            r % m
        } else {
            r
        }
    } else {
        mod_mul_(a, a, m)
    }
}

fn mod_exp(mut x: u64, mut d: u64, n: u64) -> u64 {
    let mut ret: u64 = 1;
    while d != 0 {
        if d % 2 == 1 {
            ret = mod_mul(ret, x, n)
        }
        d /= 2;
        x = mod_sqr(x, n);
    }
    ret
}

/// Test if `n` is prime, using the deterministic version of the
/// Miller-Rabin test.
///
/// Doing a lot of primality tests with numbers strictly below some
/// upper bound will be faster using the `is_prime` method of a
/// `Sieve` instance.
///
/// # Examples
///
/// ```rust
/// # extern crate primal;
/// assert_eq!(primal::is_prime(1), false);
/// assert_eq!(primal::is_prime(2), true);
/// assert_eq!(primal::is_prime(3), true);
/// assert_eq!(primal::is_prime(4), false);
/// assert_eq!(primal::is_prime(5), true);
///
/// assert_eq!(primal::is_prime(22_801_763_487), false);
/// assert_eq!(primal::is_prime(22_801_763_489), true);
/// assert_eq!(primal::is_prime(22_801_763_491), false);
/// ```
pub fn miller_rabin(n: u64) -> bool {
    const HINT: &'static [u64] = &[2];

    // we have a strict upper bound, so we can just use the witness
    // table of Pomerance, Selfridge & Wagstaff and Jeaschke to be as
    // efficient as possible, without having to fall back to
    // randomness.
    const WITNESSES: &'static [(u64, &'static [u64])] =
        &[(2_046, HINT),
          (1_373_652, &[2, 3]),
          (9_080_190, &[31, 73]),
          (25_326_000, &[2, 3, 5]),
          (4_759_123_140, &[2, 7, 61]),
          (1_112_004_669_632, &[2, 13, 23, 1662803]),
          (2_152_302_898_746, &[2, 3, 5, 7, 11]),
          (3_474_749_660_382, &[2, 3, 5, 7, 11, 13]),
          (341_550_071_728_320, &[2, 3, 5, 7, 11, 13, 17]),
          (0xFFFF_FFFF_FFFF_FFFF, &[2, 3, 5, 7, 11, 13, 17, 19, 23])
         ];

    if n % 2 == 0 { return n == 2 }
    if n == 1 { return false }

    let mut d = n - 1;
    let mut s = 0;
    while d % 2 == 0 { d /= 2; s += 1 }

    let witnesses =
        WITNESSES.iter().find(|&&(hi, _)| hi >= n)
            .map(|&(_, wtnss)| wtnss).unwrap();
    'next_witness: for &a in witnesses.iter() {
        let mut power = mod_exp(a, d, n);
        assert!(power < n);
        if power == 1 || power == n - 1 { continue 'next_witness }

        for _r in 0..s {
            power = mod_sqr(power, n);
            assert!(power < n);
            if power == 1 { return false }
            if power == n - 1 {
                continue 'next_witness
            }
        }
        return false
    }

    true
}

#[cfg(test)]
mod tests {
    use primal::Sieve;

    #[test]
    fn modulo() {
        for i in 0..64 {
            let x = 1 << i;
            for j in 0..10 {
                let m = 11 + j * 2;
                assert_eq!(super::modulo(super::U128 { lo: x, hi: 0}, m), x % m);
            }
        }

        let x = 1 << 63;
        assert_eq!(super::modulo(super::U128 { lo: 0, hi: x}, x + 1), 2);
        assert_eq!(super::modulo(super::U128 { lo: 0, hi: x}, x + 3), 18);
        assert_eq!(super::modulo(super::U128 { lo: 0, hi: x}, x + 5), 50);
    }

    #[test]
    fn mul() {
        for i in 1..64 {
            for j in 1..64 {
                let res = super::mul128((1 << i) + 1, (1 << j) + 1);
                let shift = i + j;
                let high_twiddle = i == 63 && j == 63;
                let mut real = if shift >= 64 {
                    super::U128 { lo: 0, hi: (1 << (shift - 64)) + high_twiddle as u64 }
                } else {
                    super::U128 { lo: 1 << shift, hi: 0 }
                };
                real.lo += if high_twiddle { 0 } else { (1 << i) + (1 << j) } + 1;
                assert!(res == real,
                        "(2**{} + 1)*(2**{} + 1): {:?} should be {:?}",
                        i, j, res, real);
            }
        }
    }
    #[test]
    fn mod_mul() {
        assert_eq!(super::mod_mul(1 << 63, 1 << 32, 3), 2);
        assert_eq!(super::mod_mul(1 << 31, 1 << 31, (1 << 32) - 7), 3221225479);
        assert_eq!(super::mod_mul(1 << 32, 1 << 32, (1 << 32) - 7), 49);
        assert_eq!(super::mod_mul(1 << 32, 1 << 32, (1 << 32) + 7), 49);
        assert_eq!(super::mod_mul(1 << 63, 1 << 32, (1 << 32) + 7), 2_147_483_480);
        assert_eq!(super::mod_mul(1 << 63, 1 << 32, (1 << 63) + 7), 9_223_372_006_790_004_743);
        assert_eq!(super::mod_mul(1 << 32, 1 << 32, !0), 1);
    }

    #[test]
    fn miller_rabin() {
        const LIMIT: usize = 1_000_000;
        let sieve = Sieve::new(LIMIT);
        for x in 0..LIMIT {
            let s = sieve.is_prime(x);
            let mr = super::miller_rabin(x as u64);

            assert!(s == mr, "miller_rabin {} mismatches sieve {} for {}",
                    mr, s, x)
        }
    }
    #[test]
    fn miller_rabin_large() {
        let tests = &[
            (4_294_967_311, true),
            (4_294_967_291, true),
            (4_294_967_291 * 4_294_967_291, false),
            (!0, false),
            ];
        for &(n, is_prime) in tests {
            assert!(super::miller_rabin(n) == is_prime,
                    "mismatch for {} (should be {})", n, is_prime);
        }
    }
}
<|endoftext|>


<commit_before>use super::base_helper::{to_utf16, from_utf16};
use super::high_dpi;
use winapi::shared::windef::{HFONT, HWND};
use winapi::shared::minwindef::{UINT, WPARAM, LPARAM, LRESULT};
use winapi::um::winuser::WM_USER;
use winapi::ctypes::c_int;
use std::{ptr, mem};

pub const NOTICE_MESSAGE: UINT = WM_USER+100;
pub const NWG_INIT: UINT = WM_USER + 101;
pub const NWG_TRAY: UINT = WM_USER + 102;

/// Haha you maybe though that destroying windows would be easy right? WRONG.
/// The window children must first be destroyed otherwise `DestroyWindow` will free them and the associated rust value will be ~CORRUPTED~
pub fn destroy_window(hwnd: HWND) {
    use winapi::um::winuser::{SetParent, DestroyWindow};

    // Remove the children from the window
    iterate_window_children(hwnd, |child| {
        unsafe {
            set_window_visibility(child, false);
            SetParent(child, ptr::null_mut());
        }
    });

    unsafe { DestroyWindow(hwnd); }
}

/// Execute the callback for each first level children of the window
pub fn iterate_window_children<F>(hwnd_parent: HWND, cb: F)
    where F: FnMut(HWND) -> ()
{
    use winapi::um::winuser::EnumChildWindows;
    use winapi::shared::minwindef::BOOL;

    struct EnumChildData<F> {
        parent: HWND,
        callback: F,
    }

    unsafe extern "system" fn enum_child<F>(hwnd: HWND, p: LPARAM) -> BOOL
        where F: FnMut(HWND) -> ()
    {
        // Only iterate over the top level children
        let enum_data_ptr = p as *mut EnumChildData<F>;
        let enum_data = &mut *enum_data_ptr;
        if get_window_parent(hwnd) == enum_data.parent {
            (enum_data.callback)(hwnd);
        };

        1
    }

    unsafe {
        let mut data = EnumChildData {
            parent: hwnd_parent,
            callback: cb
        };
        EnumChildWindows(hwnd_parent, Some(enum_child::<F>), &mut data as *mut EnumChildData<F> as _);
    }
}

#[cfg(any(feature="timer", feature="notice"))]
pub fn window_valid(hwnd: HWND) -> bool {
    use winapi::um::winuser::IsWindow;

    unsafe {
        IsWindow(hwnd) != 0
    }
}

pub fn get_window_parent(hwnd: HWND) -> HWND {
    use winapi::um::winuser::GetParent;
    unsafe { GetParent(hwnd) }
}

pub fn get_window_font(handle: HWND) -> HFONT {
    use winapi::um::winuser::{ WM_GETFONT };
    unsafe {
        let h = send_message(handle, WM_GETFONT, 0, 0);
        mem::transmute(h)
    }
}

/// Set the font of a window
pub unsafe fn set_window_font(handle: HWND, font_handle: Option<HFONT>, redraw: bool) {
    use winapi::um::winuser::WM_SETFONT;
    use winapi::um::winuser::SendMessageW;

    let font_handle = font_handle.unwrap_or(ptr::null_mut());

    SendMessageW(handle, WM_SETFONT, mem::transmute(font_handle), redraw as LPARAM);
}

#[cfg(feature = "timer")]
pub fn kill_timer(hwnd: HWND, id: u32) {
    use winapi::um::winuser::KillTimer;
    use winapi::shared::basetsd::UINT_PTR;

    unsafe {
        KillTimer(hwnd, id as UINT_PTR);
    }
}

#[cfg(feature = "timer")]
pub fn start_timer(hwnd: HWND, id: u32, interval: u32) {
    use winapi::um::winuser::SetTimer;
    use winapi::shared::basetsd::UINT_PTR;

    unsafe {
        SetTimer(hwnd, id as UINT_PTR, interval, None);
    }
}

pub fn get_style(handle: HWND) -> UINT {
    use ::winapi::um::winuser::GWL_STYLE;
    get_window_long(handle, GWL_STYLE) as UINT
}

#[cfg(feature="list-view")]
pub fn set_style(handle: HWND, style: u32) {
    use ::winapi::um::winuser::GWL_STYLE;
    set_window_long(handle, GWL_STYLE, style as usize);
}

pub fn send_message(hwnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT {
    unsafe { ::winapi::um::winuser::SendMessageW(hwnd, msg, w, l) }
}

pub fn post_message(hwnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) {
    unsafe { ::winapi::um::winuser::PostMessageW(hwnd, msg, w, l) };
}

pub unsafe fn set_focus(handle: HWND) {
    ::winapi::um::winuser::SetFocus(handle);
}

pub unsafe fn get_focus(handle: HWND) -> bool {
    ::winapi::um::winuser::GetFocus() == handle
}

pub unsafe fn get_window_text(handle: HWND) -> String {
    use winapi::um::winuser::{GetWindowTextW, GetWindowTextLengthW};

    let mut buffer_size = GetWindowTextLengthW(handle) as usize;
    if buffer_size == 0 { return String::new(); }

    buffer_size += 1;
    let mut buffer: Vec<u16> = Vec::with_capacity(buffer_size);
    buffer.set_len(buffer_size);

    if GetWindowTextW(handle, buffer.as_mut_ptr(), buffer_size as c_int) == 0 {
        String::new()
    } else {
        from_utf16(&buffer[..])
    }
}

pub unsafe fn set_window_text<'a>(handle: HWND, text: &'a str) {
    use winapi::um::winuser::{SetWindowTextW};

    let text = to_utf16(text);
    SetWindowTextW(handle, text.as_ptr());
}

pub unsafe fn set_window_position(handle: HWND, x: i32, y: i32) {
    use winapi::um::winuser::SetWindowPos;
    use winapi::um::winuser::{SWP_NOZORDER, SWP_NOSIZE, SWP_NOACTIVATE};

    let (x, y) = high_dpi::logical_to_physical(x, y);
    SetWindowPos(handle, ptr::null_mut(), x as c_int, y as c_int, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
}

pub unsafe fn get_window_position(handle: HWND) -> (i32, i32) {
    use winapi::um::winuser::{GetWindowRect, ScreenToClient, GetParent};
    use winapi::shared::windef::{RECT, POINT};

    let mut r: RECT = mem::zeroed();
    GetWindowRect(handle, &mut r);

    let parent = GetParent(handle);
    let (x, y) = if !parent.is_null() {
        let mut pt = POINT{x: r.left, y: r.top};
        ScreenToClient(parent, &mut pt);
        (pt.x as i32, pt.y as i32)
    } else {
        (r.left as i32, r.top as i32)
    };

    high_dpi::physical_to_logical(x, y)
}

pub unsafe fn set_window_size(handle: HWND, w: u32, h: u32, fix: bool) {
    use winapi::um::winuser::{SetWindowPos, AdjustWindowRectEx, GetWindowLongW};
    use winapi::um::winuser::{SWP_NOZORDER, SWP_NOMOVE, SWP_NOACTIVATE, SWP_NOCOPYBITS, GWL_STYLE, GWL_EXSTYLE};
    use winapi::shared::windef::RECT;

    let (mut w, mut h) = high_dpi::logical_to_physical(w as i32, h as i32);

    if fix {
        let flags = GetWindowLongW(handle, GWL_STYLE) as u32;
        let ex_flags = GetWindowLongW(handle, GWL_EXSTYLE) as u32;
        let mut rect = RECT {left: 0, top: 0, right: w, bottom: h};
        AdjustWindowRectEx(&mut rect, flags, 0, ex_flags);

        w = rect.right - rect.left;
        h = rect.bottom  - rect.top;
    }

    SetWindowPos(handle, ptr::null_mut(), 0, 0, w, h, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}

pub unsafe fn get_window_size(handle: HWND) -> (u32, u32) {
    get_window_size_impl(handle, false)
}

#[allow(unused)]
pub unsafe fn get_window_physical_size(handle: HWND) -> (u32, u32) {
    get_window_size_impl(handle, true)
}

unsafe fn get_window_size_impl(handle: HWND, return_physical: bool) -> (u32, u32) {
    use winapi::um::winuser::GetClientRect;
    use winapi::shared::windef::RECT;

    let mut r: RECT = mem::zeroed();
    GetClientRect(handle, &mut r);

    let (w, h) = if return_physical {
        (r.right, r.bottom)
    } else {
        high_dpi::physical_to_logical(r.right, r.bottom)
    };

    (w as u32, h as u32)
}

pub unsafe fn set_window_visibility(handle: HWND, visible: bool) {
    use winapi::um::winuser::ShowWindow;
    use winapi::um::winuser::{SW_HIDE, SW_SHOW};

    let visible = if visible { SW_SHOW } else { SW_HIDE };
    ShowWindow(handle, visible);
}

pub unsafe fn get_window_visibility(handle: HWND) -> bool {
    use winapi::um::winuser::IsWindowVisible;
    IsWindowVisible(handle) != 0
}

pub unsafe fn get_window_enabled(handle: HWND) -> bool {
    use winapi::um::winuser::{GWL_STYLE, WS_DISABLED};

    let style = get_window_long(handle, GWL_STYLE) as UINT;
    (style & WS_DISABLED) != WS_DISABLED
}

pub unsafe fn set_window_enabled(handle: HWND, enabled: bool) {
    use winapi::um::winuser::{GWL_STYLE, WS_DISABLED};
    use winapi::um::winuser::{UpdateWindow, InvalidateRect};

    let old_style = get_window_long(handle, GWL_STYLE) as usize;
    if enabled {
        set_window_long(handle, GWL_STYLE, old_style&(!WS_DISABLED as usize) );
    } else {
        set_window_long(handle, GWL_STYLE, old_style|(WS_DISABLED as usize));
    }

    // Tell the control to redraw itself to show the new style.
    InvalidateRect(handle, ptr::null(), 1);
    UpdateWindow(handle);
}

#[cfg(feature = "tabs")]
pub unsafe fn get_window_class_name(handle: HWND) -> String {
    use std::ffi::OsString;
    use std::os::windows::ffi::OsStringExt;
    use winapi::shared::ntdef::WCHAR;
    use winapi::um::winuser::GetClassNameW;

    let mut class_name_raw: Vec<WCHAR> = Vec::with_capacity(100);
    class_name_raw.set_len(100);

    let count = GetClassNameW(handle, class_name_raw.as_mut_ptr(), 100) as usize;

    OsString::from_wide(&class_name_raw[..count]).into_string().unwrap_or("".to_string())
}

#[cfg(target_arch = "x86")] use winapi::shared::ntdef::LONG;
#[cfg(target_arch = "x86_64")] use winapi::shared::basetsd::LONG_PTR;

#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn get_window_long(handle: HWND, index: c_int) -> LONG_PTR {
    unsafe{ ::winapi::um::winuser::GetWindowLongPtrW(handle, index) }
}

#[inline(always)]
#[cfg(target_arch = "x86")]
pub fn get_window_long(handle: HWND, index: c_int) -> LONG {
    unsafe { ::winapi::um::winuser::GetWindowLongW(handle, index) }
}

#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn set_window_long(handle: HWND, index: c_int, v: usize) {
    unsafe{ ::winapi::um::winuser::SetWindowLongPtrW(handle, index, v as LONG_PTR); }
}

#[inline(always)]
#[cfg(target_arch = "x86")]
pub fn set_window_long(handle: HWND, index: c_int, v: usize) {
    unsafe { ::winapi::um::winuser::SetWindowLongW(handle, index, v as LONG); }
}
<commit_msg>Fix build with only progress-bar feature<commit_after>use super::base_helper::{to_utf16, from_utf16};
use super::high_dpi;
use winapi::shared::windef::{HFONT, HWND};
use winapi::shared::minwindef::{UINT, WPARAM, LPARAM, LRESULT};
use winapi::um::winuser::WM_USER;
use winapi::ctypes::c_int;
use std::{ptr, mem};

pub const NOTICE_MESSAGE: UINT = WM_USER+100;
pub const NWG_INIT: UINT = WM_USER + 101;
pub const NWG_TRAY: UINT = WM_USER + 102;

/// Haha you maybe though that destroying windows would be easy right? WRONG.
/// The window children must first be destroyed otherwise `DestroyWindow` will free them and the associated rust value will be ~CORRUPTED~
pub fn destroy_window(hwnd: HWND) {
    use winapi::um::winuser::{SetParent, DestroyWindow};

    // Remove the children from the window
    iterate_window_children(hwnd, |child| {
        unsafe {
            set_window_visibility(child, false);
            SetParent(child, ptr::null_mut());
        }
    });

    unsafe { DestroyWindow(hwnd); }
}

/// Execute the callback for each first level children of the window
pub fn iterate_window_children<F>(hwnd_parent: HWND, cb: F)
    where F: FnMut(HWND) -> ()
{
    use winapi::um::winuser::EnumChildWindows;
    use winapi::shared::minwindef::BOOL;

    struct EnumChildData<F> {
        parent: HWND,
        callback: F,
    }

    unsafe extern "system" fn enum_child<F>(hwnd: HWND, p: LPARAM) -> BOOL
        where F: FnMut(HWND) -> ()
    {
        // Only iterate over the top level children
        let enum_data_ptr = p as *mut EnumChildData<F>;
        let enum_data = &mut *enum_data_ptr;
        if get_window_parent(hwnd) == enum_data.parent {
            (enum_data.callback)(hwnd);
        };

        1
    }

    unsafe {
        let mut data = EnumChildData {
            parent: hwnd_parent,
            callback: cb
        };
        EnumChildWindows(hwnd_parent, Some(enum_child::<F>), &mut data as *mut EnumChildData<F> as _);
    }
}

#[cfg(any(feature="timer", feature="notice"))]
pub fn window_valid(hwnd: HWND) -> bool {
    use winapi::um::winuser::IsWindow;

    unsafe {
        IsWindow(hwnd) != 0
    }
}

pub fn get_window_parent(hwnd: HWND) -> HWND {
    use winapi::um::winuser::GetParent;
    unsafe { GetParent(hwnd) }
}

pub fn get_window_font(handle: HWND) -> HFONT {
    use winapi::um::winuser::{ WM_GETFONT };
    unsafe {
        let h = send_message(handle, WM_GETFONT, 0, 0);
        mem::transmute(h)
    }
}

/// Set the font of a window
pub unsafe fn set_window_font(handle: HWND, font_handle: Option<HFONT>, redraw: bool) {
    use winapi::um::winuser::WM_SETFONT;
    use winapi::um::winuser::SendMessageW;

    let font_handle = font_handle.unwrap_or(ptr::null_mut());

    SendMessageW(handle, WM_SETFONT, mem::transmute(font_handle), redraw as LPARAM);
}

#[cfg(feature = "timer")]
pub fn kill_timer(hwnd: HWND, id: u32) {
    use winapi::um::winuser::KillTimer;
    use winapi::shared::basetsd::UINT_PTR;

    unsafe {
        KillTimer(hwnd, id as UINT_PTR);
    }
}

#[cfg(feature = "timer")]
pub fn start_timer(hwnd: HWND, id: u32, interval: u32) {
    use winapi::um::winuser::SetTimer;
    use winapi::shared::basetsd::UINT_PTR;

    unsafe {
        SetTimer(hwnd, id as UINT_PTR, interval, None);
    }
}

pub fn get_style(handle: HWND) -> UINT {
    use ::winapi::um::winuser::GWL_STYLE;
    get_window_long(handle, GWL_STYLE) as UINT
}

#[cfg(any(feature = "list-view", feature = "progress-bar"))]
pub fn set_style(handle: HWND, style: u32) {
    use ::winapi::um::winuser::GWL_STYLE;
    set_window_long(handle, GWL_STYLE, style as usize);
}

pub fn send_message(hwnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT {
    unsafe { ::winapi::um::winuser::SendMessageW(hwnd, msg, w, l) }
}

pub fn post_message(hwnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) {
    unsafe { ::winapi::um::winuser::PostMessageW(hwnd, msg, w, l) };
}

pub unsafe fn set_focus(handle: HWND) {
    ::winapi::um::winuser::SetFocus(handle);
}

pub unsafe fn get_focus(handle: HWND) -> bool {
    ::winapi::um::winuser::GetFocus() == handle
}

pub unsafe fn get_window_text(handle: HWND) -> String {
    use winapi::um::winuser::{GetWindowTextW, GetWindowTextLengthW};

    let mut buffer_size = GetWindowTextLengthW(handle) as usize;
    if buffer_size == 0 { return String::new(); }

    buffer_size += 1;
    let mut buffer: Vec<u16> = Vec::with_capacity(buffer_size);
    buffer.set_len(buffer_size);

    if GetWindowTextW(handle, buffer.as_mut_ptr(), buffer_size as c_int) == 0 {
        String::new()
    } else {
        from_utf16(&buffer[..])
    }
}

pub unsafe fn set_window_text<'a>(handle: HWND, text: &'a str) {
    use winapi::um::winuser::{SetWindowTextW};

    let text = to_utf16(text);
    SetWindowTextW(handle, text.as_ptr());
}

pub unsafe fn set_window_position(handle: HWND, x: i32, y: i32) {
    use winapi::um::winuser::SetWindowPos;
    use winapi::um::winuser::{SWP_NOZORDER, SWP_NOSIZE, SWP_NOACTIVATE};

    let (x, y) = high_dpi::logical_to_physical(x, y);
    SetWindowPos(handle, ptr::null_mut(), x as c_int, y as c_int, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
}

pub unsafe fn get_window_position(handle: HWND) -> (i32, i32) {
    use winapi::um::winuser::{GetWindowRect, ScreenToClient, GetParent};
    use winapi::shared::windef::{RECT, POINT};

    let mut r: RECT = mem::zeroed();
    GetWindowRect(handle, &mut r);

    let parent = GetParent(handle);
    let (x, y) = if !parent.is_null() {
        let mut pt = POINT{x: r.left, y: r.top};
        ScreenToClient(parent, &mut pt);
        (pt.x as i32, pt.y as i32)
    } else {
        (r.left as i32, r.top as i32)
    };

    high_dpi::physical_to_logical(x, y)
}

pub unsafe fn set_window_size(handle: HWND, w: u32, h: u32, fix: bool) {
    use winapi::um::winuser::{SetWindowPos, AdjustWindowRectEx, GetWindowLongW};
    use winapi::um::winuser::{SWP_NOZORDER, SWP_NOMOVE, SWP_NOACTIVATE, SWP_NOCOPYBITS, GWL_STYLE, GWL_EXSTYLE};
    use winapi::shared::windef::RECT;

    let (mut w, mut h) = high_dpi::logical_to_physical(w as i32, h as i32);

    if fix {
        let flags = GetWindowLongW(handle, GWL_STYLE) as u32;
        let ex_flags = GetWindowLongW(handle, GWL_EXSTYLE) as u32;
        let mut rect = RECT {left: 0, top: 0, right: w, bottom: h};
        AdjustWindowRectEx(&mut rect, flags, 0, ex_flags);

        w = rect.right - rect.left;
        h = rect.bottom  - rect.top;
    }

    SetWindowPos(handle, ptr::null_mut(), 0, 0, w, h, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}

pub unsafe fn get_window_size(handle: HWND) -> (u32, u32) {
    get_window_size_impl(handle, false)
}

#[allow(unused)]
pub unsafe fn get_window_physical_size(handle: HWND) -> (u32, u32) {
    get_window_size_impl(handle, true)
}

unsafe fn get_window_size_impl(handle: HWND, return_physical: bool) -> (u32, u32) {
    use winapi::um::winuser::GetClientRect;
    use winapi::shared::windef::RECT;

    let mut r: RECT = mem::zeroed();
    GetClientRect(handle, &mut r);

    let (w, h) = if return_physical {
        (r.right, r.bottom)
    } else {
        high_dpi::physical_to_logical(r.right, r.bottom)
    };

    (w as u32, h as u32)
}

pub unsafe fn set_window_visibility(handle: HWND, visible: bool) {
    use winapi::um::winuser::ShowWindow;
    use winapi::um::winuser::{SW_HIDE, SW_SHOW};

    let visible = if visible { SW_SHOW } else { SW_HIDE };
    ShowWindow(handle, visible);
}

pub unsafe fn get_window_visibility(handle: HWND) -> bool {
    use winapi::um::winuser::IsWindowVisible;
    IsWindowVisible(handle) != 0
}

pub unsafe fn get_window_enabled(handle: HWND) -> bool {
    use winapi::um::winuser::{GWL_STYLE, WS_DISABLED};

    let style = get_window_long(handle, GWL_STYLE) as UINT;
    (style & WS_DISABLED) != WS_DISABLED
}

pub unsafe fn set_window_enabled(handle: HWND, enabled: bool) {
    use winapi::um::winuser::{GWL_STYLE, WS_DISABLED};
    use winapi::um::winuser::{UpdateWindow, InvalidateRect};

    let old_style = get_window_long(handle, GWL_STYLE) as usize;
    if enabled {
        set_window_long(handle, GWL_STYLE, old_style&(!WS_DISABLED as usize) );
    } else {
        set_window_long(handle, GWL_STYLE, old_style|(WS_DISABLED as usize));
    }

    // Tell the control to redraw itself to show the new style.
    InvalidateRect(handle, ptr::null(), 1);
    UpdateWindow(handle);
}

#[cfg(feature = "tabs")]
pub unsafe fn get_window_class_name(handle: HWND) -> String {
    use std::ffi::OsString;
    use std::os::windows::ffi::OsStringExt;
    use winapi::shared::ntdef::WCHAR;
    use winapi::um::winuser::GetClassNameW;

    let mut class_name_raw: Vec<WCHAR> = Vec::with_capacity(100);
    class_name_raw.set_len(100);

    let count = GetClassNameW(handle, class_name_raw.as_mut_ptr(), 100) as usize;

    OsString::from_wide(&class_name_raw[..count]).into_string().unwrap_or("".to_string())
}

#[cfg(target_arch = "x86")] use winapi::shared::ntdef::LONG;
#[cfg(target_arch = "x86_64")] use winapi::shared::basetsd::LONG_PTR;

#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn get_window_long(handle: HWND, index: c_int) -> LONG_PTR {
    unsafe{ ::winapi::um::winuser::GetWindowLongPtrW(handle, index) }
}

#[inline(always)]
#[cfg(target_arch = "x86")]
pub fn get_window_long(handle: HWND, index: c_int) -> LONG {
    unsafe { ::winapi::um::winuser::GetWindowLongW(handle, index) }
}

#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn set_window_long(handle: HWND, index: c_int, v: usize) {
    unsafe{ ::winapi::um::winuser::SetWindowLongPtrW(handle, index, v as LONG_PTR); }
}

#[inline(always)]
#[cfg(target_arch = "x86")]
pub fn set_window_long(handle: HWND, index: c_int, v: usize) {
    unsafe { ::winapi::um::winuser::SetWindowLongW(handle, index, v as LONG); }
}
<|endoftext|>


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

#![feature(proc_macro)]

extern crate gtk;
extern crate libxdo;
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

mod utils;

use std::thread;

use gtk::WidgetExt;
use libxdo::XDo;
use mg::{
    CustomCommand,
    Mg,
    Modes,
};
use relm::{Widget, init_test};
use relm_attributes::widget;

use self::AppCommand::*;
use self::Msg::*;
use utils::XDoExt;

#[derive(Commands)]
pub enum AppCommand {
    #[help(text="Show the text in the label")]
    Show(String),
    Quit,
}

#[derive(Default, Settings)]
pub struct AppSettings {
    boolean: bool,
}

pub struct Model {
    text: String,
}

#[derive(Msg)]
pub enum Msg {
    Command(AppCommand),
}

static MODES: Modes = &[
    ("i", "insert"),
];

#[widget]
impl Widget for Win {
    fn model() -> Model {
        Model {
            text: "Label".to_string(),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            Command(command) => {
                match command {
                    Show(text) => self.model.text = format!("Showing text: {}", text),
                    Quit => gtk::main_quit(),
                }
            },
        }
    }

    view! {
        #[name="mg"]
        Mg<AppCommand, AppSettings>((MODES, "examples/main.conf")) {
            #[name="label"]
            gtk::Label {
                text: &self.model.text,
            },
            CustomCommand(command) => Command(command),
        }
    }
}

#[test]
fn test_basic_command() {
    gtk::init().unwrap();

    let win = init_test::<Win>(()).unwrap();

    assert_eq!(Some("Label".to_string()), win.widget().label.get_text());

    thread::spawn(|| {
        let xdo = XDo::new(None).unwrap();
        xdo.enter_command("show test");
        xdo.enter_command("quit");
    });

    gtk::main();

    assert_eq!(Some("Showing text: test".to_string()), win.widget().label.get_text());
}
<commit_msg>Fix test<commit_after>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
extern crate libxdo;
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

mod utils;

use std::thread;

use gtk::WidgetExt;
use libxdo::XDo;
use mg::{
    CustomCommand,
    Mg,
    Modes,
};
use relm::{Widget, init_test};
use relm_attributes::widget;

use self::AppCommand::*;
use self::Msg::*;
use utils::XDoExt;

#[derive(Commands)]
pub enum AppCommand {
    #[help(text="Show the text in the label")]
    Show(String),
    Quit,
}

#[derive(Default, Settings)]
pub struct AppSettings {
    boolean: bool,
}

pub struct Model {
    text: String,
}

#[derive(Msg)]
pub enum Msg {
    Command(AppCommand),
}

static MODES: Modes = &[
    ("i", "insert"),
];

#[widget]
impl Widget for Win {
    fn model() -> Model {
        Model {
            text: "Label".to_string(),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            Command(command) => {
                match command {
                    Show(text) => self.model.text = format!("Showing text: {}", text),
                    Quit => gtk::main_quit(),
                }
            },
        }
    }

    view! {
        #[name="mg"]
        Mg<AppCommand, AppSettings>((MODES, "examples/main.conf", None)) {
            #[name="label"]
            gtk::Label {
                text: &self.model.text,
            },
            CustomCommand(command) => Command(command),
        }
    }
}

#[test]
fn test_basic_command() {
    gtk::init().unwrap();

    let win = init_test::<Win>(()).unwrap();

    assert_eq!(Some("Label".to_string()), win.widget().label.get_text());

    thread::spawn(|| {
        let xdo = XDo::new(None).unwrap();
        xdo.enter_command("show test");
        xdo.enter_command("quit");
    });

    gtk::main();

    assert_eq!(Some("Showing text: test".to_string()), win.widget().label.get_text());
}
<|endoftext|>