<commit_before>use std::{Box, String};
use std::collections::VecDeque;
use std::ops::DerefMut;

use orbital::{Color, Point, Size, Event, KeyEvent, MouseEvent, QuitEvent};

use super::display::Display;
use super::scheduler;

/// A window
pub struct Window {
    /// The position of the window
    pub point: Point,
    /// The size of the window
    pub size: Size,
    /// The title of the window
    pub title: String,
    /// The content of the window
    pub content: Box<Display>,
    /// The color of the window title
    pub title_color: Color,
    /// The color of the border
    pub border_color: Color,
    /// Is the window focused?
    pub focused: bool,
    /// Is the window minimized?
    pub minimized: bool,
    dragging: bool,
    last_mouse_event: MouseEvent,
    events: VecDeque<Event>,
    ptr: *mut Window,
}

impl Window {
    /// Create a new window
    pub fn new(point: Point, size: Size, title: String) -> Box<Self> {
        let mut ret = box Window {
            point: point,
            size: size,
            title: title,
            content: Display::new(size.width, size.height),
            title_color: Color::rgb(255, 255, 255),
            border_color: Color::rgba(64, 64, 64, 128),
            focused: false,
            minimized: false,
            dragging: false,
            last_mouse_event: MouseEvent {
                x: 0,
                y: 0,
                left_button: false,
                right_button: false,
                middle_button: false,
            },
            events: VecDeque::new(),
            ptr: 0 as *mut Window,
        };

        unsafe {
            ret.ptr = ret.deref_mut();

            if ret.ptr as usize > 0 {
                (*super::session_ptr).add_window(ret.ptr);
            }
        }

        ret
    }

    /// Poll the window (new)
    pub fn poll(&mut self) -> Option<Event> {
        let event_option;
        unsafe {
            let reenable = scheduler::start_no_ints();
            event_option = self.events.pop_front();
            scheduler::end_no_ints(reenable);
        }
        return event_option;
    }

    /// Redraw the window
    pub fn redraw(&mut self) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.content.flip();
            (*super::session_ptr).redraw = true;
            (*super::session_ptr).redraw();
            scheduler::end_no_ints(reenable);
        }
    }

    /// Draw the window using a `Display`
    pub fn draw(&mut self, display: &Display, font: usize) {
        if self.focused {
            self.border_color = Color::rgba(128, 128, 128, 192);
        } else {
            self.border_color = Color::rgba(64, 64, 64, 128);
        }

        if self.minimized {
            self.title_color = Color::rgb(0, 0, 0);
        } else {
            self.title_color = Color::rgb(255, 255, 255);

            display.rect(Point::new(self.point.x - 2, self.point.y - 18),
                         Size::new(self.size.width + 4, 18),
                         self.border_color);

            let mut cursor = Point::new(self.point.x, self.point.y - 17);
            for c in self.title.chars() {
                if cursor.x + 8 <= self.point.x + self.size.width as isize {
                    display.char(cursor, c, self.title_color, font);
                }
                cursor.x += 8;
            }

            display.rect(Point::new(self.point.x - 2, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);
            display.rect(Point::new(self.point.x - 2, self.point.y + self.size.height as isize),
                         Size::new(self.size.width + 4, 2),
                         self.border_color);
            display.rect(Point::new(self.point.x + self.size.width as isize, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);

            unsafe {
                let reenable = scheduler::start_no_ints();
                display.image(self.point,
                              self.content.onscreen as *const Color,
                              Size::new(self.content.width, self.content.height));
                scheduler::end_no_ints(reenable);
            }
        }
    }

    /// Called on key press
    pub fn on_key(&mut self, key_event: KeyEvent) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.events.push_back(key_event.to_event());
            scheduler::end_no_ints(reenable);
        }
    }

    fn on_window_decoration(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= -2 && x < self.size.width as isize + 4 && y >= -18 && y < 0
    }

    fn on_window_body(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= 0 && x < self.size.width as isize && y >= 0 &&
        y < self.size.height as isize
    }

    fn mouse_button_pressed(mouse_event: &MouseEvent) -> bool {
        mouse_event.left_button || mouse_event.middle_button || mouse_event.right_button
    }

    /// Called on mouse movement
    pub fn on_mouse(&mut self, orig_mouse_event: MouseEvent, allow_catch: bool, active_window: bool) -> bool {
        let mut mouse_event = orig_mouse_event;

        mouse_event.x -= self.point.x;
        mouse_event.y -= self.point.y;

        let mut caught = false;

        if allow_catch && (active_window || Window::mouse_button_pressed(&mouse_event)) {
            if self.on_window_body(mouse_event.x, mouse_event.y) {
                caught = true;
            } else if self.on_window_decoration(mouse_event.x, mouse_event.y) {
                caught = true;

                if mouse_event.left_button {
                    if !self.last_mouse_event.left_button {
                        self.dragging = true;
                    }
                } else {
                    self.dragging = false;
                }

                if mouse_event.right_button {
                    if !self.last_mouse_event.right_button {
                        self.minimized = !self.minimized;
                    }
                }

                if mouse_event.middle_button {
                    unsafe {
                        let reenable = scheduler::start_no_ints();
                        self.events.push_back(QuitEvent.to_event());
                        scheduler::end_no_ints(reenable);
                    }
                }
            }

            if self.dragging {
                self.point.x += orig_mouse_event.x - self.last_mouse_event.x;
                self.point.y += orig_mouse_event.y - self.last_mouse_event.y;
                caught = true;
            }
        } else {
            self.dragging = false;
        }

        self.last_mouse_event = orig_mouse_event;

        if caught && !self.dragging {
            unsafe {
                let reenable = scheduler::start_no_ints();
                self.events.push_back(mouse_event.to_event());
                scheduler::end_no_ints(reenable);
            }
        }

        caught
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        unsafe {
            if self.ptr as usize > 0 {
                (*super::session_ptr).remove_window(self.ptr);
            }
        }
    }
}
<commit_msg>Fix for case when mouse button held down<commit_after>use std::{Box, String};
use std::collections::VecDeque;
use std::ops::DerefMut;

use orbital::{Color, Point, Size, Event, KeyEvent, MouseEvent, QuitEvent};

use super::display::Display;
use super::scheduler;

/// A window
pub struct Window {
    /// The position of the window
    pub point: Point,
    /// The size of the window
    pub size: Size,
    /// The title of the window
    pub title: String,
    /// The content of the window
    pub content: Box<Display>,
    /// The color of the window title
    pub title_color: Color,
    /// The color of the border
    pub border_color: Color,
    /// Is the window focused?
    pub focused: bool,
    /// Is the window minimized?
    pub minimized: bool,
    dragging: bool,
    last_mouse_event: MouseEvent,
    events: VecDeque<Event>,
    ptr: *mut Window,
}

impl Window {
    /// Create a new window
    pub fn new(point: Point, size: Size, title: String) -> Box<Self> {
        let mut ret = box Window {
            point: point,
            size: size,
            title: title,
            content: Display::new(size.width, size.height),
            title_color: Color::rgb(255, 255, 255),
            border_color: Color::rgba(64, 64, 64, 128),
            focused: false,
            minimized: false,
            dragging: false,
            last_mouse_event: MouseEvent {
                x: 0,
                y: 0,
                left_button: false,
                right_button: false,
                middle_button: false,
            },
            events: VecDeque::new(),
            ptr: 0 as *mut Window,
        };

        unsafe {
            ret.ptr = ret.deref_mut();

            if ret.ptr as usize > 0 {
                (*super::session_ptr).add_window(ret.ptr);
            }
        }

        ret
    }

    /// Poll the window (new)
    pub fn poll(&mut self) -> Option<Event> {
        let event_option;
        unsafe {
            let reenable = scheduler::start_no_ints();
            event_option = self.events.pop_front();
            scheduler::end_no_ints(reenable);
        }
        return event_option;
    }

    /// Redraw the window
    pub fn redraw(&mut self) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.content.flip();
            (*super::session_ptr).redraw = true;
            (*super::session_ptr).redraw();
            scheduler::end_no_ints(reenable);
        }
    }

    /// Draw the window using a `Display`
    pub fn draw(&mut self, display: &Display, font: usize) {
        if self.focused {
            self.border_color = Color::rgba(128, 128, 128, 192);
        } else {
            self.border_color = Color::rgba(64, 64, 64, 128);
        }

        if self.minimized {
            self.title_color = Color::rgb(0, 0, 0);
        } else {
            self.title_color = Color::rgb(255, 255, 255);

            display.rect(Point::new(self.point.x - 2, self.point.y - 18),
                         Size::new(self.size.width + 4, 18),
                         self.border_color);

            let mut cursor = Point::new(self.point.x, self.point.y - 17);
            for c in self.title.chars() {
                if cursor.x + 8 <= self.point.x + self.size.width as isize {
                    display.char(cursor, c, self.title_color, font);
                }
                cursor.x += 8;
            }

            display.rect(Point::new(self.point.x - 2, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);
            display.rect(Point::new(self.point.x - 2, self.point.y + self.size.height as isize),
                         Size::new(self.size.width + 4, 2),
                         self.border_color);
            display.rect(Point::new(self.point.x + self.size.width as isize, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);

            unsafe {
                let reenable = scheduler::start_no_ints();
                display.image(self.point,
                              self.content.onscreen as *const Color,
                              Size::new(self.content.width, self.content.height));
                scheduler::end_no_ints(reenable);
            }
        }
    }

    /// Called on key press
    pub fn on_key(&mut self, key_event: KeyEvent) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.events.push_back(key_event.to_event());
            scheduler::end_no_ints(reenable);
        }
    }

    fn on_window_decoration(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= -2 && x < self.size.width as isize + 4 && y >= -18 && y < 0
    }

    fn on_window_body(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= 0 && x < self.size.width as isize && y >= 0 &&
        y < self.size.height as isize
    }

    fn mouse_button_pressed(mouse_event: &MouseEvent) -> bool {
        mouse_event.left_button || mouse_event.middle_button || mouse_event.right_button
    }

    /// Called on mouse movement
    pub fn on_mouse(&mut self, orig_mouse_event: MouseEvent, allow_catch: bool, active_window: bool) -> bool {
        let mut mouse_event = orig_mouse_event;

        mouse_event.x -= self.point.x;
        mouse_event.y -= self.point.y;

        let mut caught = false;

        if allow_catch && (active_window || (Window::mouse_button_pressed(&mouse_event) && !Window::mouse_button_pressed(&self.last_mouse_event))) {
            if self.on_window_body(mouse_event.x, mouse_event.y) {
                caught = true;
            } else if self.on_window_decoration(mouse_event.x, mouse_event.y) {
                caught = true;

                if mouse_event.left_button {
                    if !self.last_mouse_event.left_button {
                        self.dragging = true;
                    }
                } else {
                    self.dragging = false;
                }

                if mouse_event.right_button {
                    if !self.last_mouse_event.right_button {
                        self.minimized = !self.minimized;
                    }
                }

                if mouse_event.middle_button {
                    unsafe {
                        let reenable = scheduler::start_no_ints();
                        self.events.push_back(QuitEvent.to_event());
                        scheduler::end_no_ints(reenable);
                    }
                }
            }

            if self.dragging {
                self.point.x += orig_mouse_event.x - self.last_mouse_event.x;
                self.point.y += orig_mouse_event.y - self.last_mouse_event.y;
                caught = true;
            }
        } else {
            self.dragging = false;
        }

        self.last_mouse_event = orig_mouse_event;

        if caught && !self.dragging {
            unsafe {
                let reenable = scheduler::start_no_ints();
                self.events.push_back(mouse_event.to_event());
                scheduler::end_no_ints(reenable);
            }
        }

        caught
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        unsafe {
            if self.ptr as usize > 0 {
                (*super::session_ptr).remove_window(self.ptr);
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>examples/print_torrent<commit_after>extern crate lazy_bencoding;

use std::env;
use std::fs::File;
use std::io::Read;

use lazy_bencoding::*;

fn pretty_print<'a>(bencoded: BEncoded<'a>, padding: &str) {
    if let Some(s) = bencoded.get_utf8_string() {
        println!("{}{}", padding, s);
    } else if let Some(bs) = bencoded.get_byte_string() {
        // Hexdump
        let mut line = String::new();
        for (i, b) in bs.iter().enumerate() {
            line.push_str(&format!("{:02X}", b));
            if i & 15 == 0 {
                println!("{}{}", padding, line);
                line.clear();
            } else if i & 7 == 0 {
                line.push_str("   ");
            } else if i & 3 == 0 {
                line.push_str("  ");
            } else {
                line.push_str(" ");
            }
        }
        if line.len() > 0 {
            println!("{}{}", padding, line);
        }
    } else if let Some(i) = bencoded.get_integer() {
        println!("{}{}", padding, i);
    } else if bencoded.is_dict() {
        for (key, value) in bencoded.dict() {
            if let Some(key) = key.get_utf8_string() {
                println!("{}{}:", padding, key);
            } else {
                pretty_print(key, padding);
            }
            pretty_print(value, &format!("{}    ", padding));
        }
    } else if bencoded.is_list() {
        for (i, elem) in bencoded.list().enumerate() {
            let padding = if i == 0 {
                format!("{}  - ", padding)
            } else {
                let space_padding: String = padding.chars()
                    .map(|c| ' ').collect();
                format!("{}  - ", space_padding)
            };
            pretty_print(elem, &padding);
        }
    } else {
        println!("{}Weird tokens: {:?}", padding, bencoded.collect::<Vec<Token<'a>>>());
    }
}

fn main() {
    for filename in env::args().skip(1) {
        let mut f = match File::open(&filename) {
            Ok(f) => f,
            Err(e) => {
                println!("{}: {:?}", filename, e);
                continue;
            }
        };
        let mut contents = Vec::new();
        f.read_to_end(&mut contents).unwrap();

        let bencoded = BEncoded::new(&contents[..]);
        pretty_print(bencoded, "");
    }
}
<|endoftext|>


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

use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementDerived, HTMLElementCast};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{HTMLIFrameElementTypeId, Element};
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::Window;
use page::IterablePage;
use servo_msg::constellation_msg::{PipelineId, SubpageId};
use servo_msg::constellation_msg::{IFrameSandboxed, IFrameUnsandboxed};
use servo_msg::constellation_msg::{ConstellationChan, LoadIframeUrlMsg};
use servo_util::namespace::Null;
use servo_util::str::DOMString;

use std::ascii::StrAsciiExt;
use std::cell::Cell;
use url::{Url, UrlParser};

enum SandboxAllowance {
    AllowNothing = 0x00,
    AllowSameOrigin = 0x01,
    AllowTopNavigation = 0x02,
    AllowForms = 0x04,
    AllowScripts = 0x08,
    AllowPointerLock = 0x10,
    AllowPopups = 0x20
}

#[deriving(Encodable)]
pub struct HTMLIFrameElement {
    pub htmlelement: HTMLElement,
    pub size: Traceable<Cell<Option<IFrameSize>>>,
    pub sandbox: Traceable<Cell<Option<u8>>>,
}

impl HTMLIFrameElementDerived for EventTarget {
    fn is_htmliframeelement(&self) -> bool {
       self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLIFrameElementTypeId))
    }
}

#[deriving(Encodable)]
pub struct IFrameSize {
    pub pipeline_id: PipelineId,
    pub subpage_id: SubpageId,
}

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

impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
    fn is_sandboxed(&self) -> bool {
        self.sandbox.deref().get().is_some()
    }

    fn get_url(&self) -> Option<Url> {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.get_attribute(Null, "src").root().and_then(|src| {
            let window = window_from_node(self).root();
            UrlParser::new().base_url(&window.deref().page().get_url())
                .parse(src.deref().value().as_slice()).ok()
        })
    }
}

impl HTMLIFrameElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLIFrameElement {
        HTMLIFrameElement {
            htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document),
            size: Traceable::new(Cell::new(None)),
            sandbox: Traceable::new(Cell::new(None)),
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLIFrameElement> {
        let element = HTMLIFrameElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLIFrameElementBinding::Wrap)
    }
}

impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
    fn Src(&self) -> DOMString {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.get_string_attribute("src")
    }

    fn SetSrc(&self, src: DOMString) {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.set_url_attribute("src", src)
    }

    fn Sandbox(&self) -> DOMString {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.get_string_attribute("sandbox")
    }

    fn SetSandbox(&self, sandbox: DOMString) {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("sandbox", sandbox);
    }

    fn GetContentWindow(&self) -> Option<Temporary<Window>> {
        self.size.deref().get().and_then(|size| {
            let window = window_from_node(self).root();
            let children = &*window.deref().page.children.deref().borrow();
            let child = children.iter().find(|child| {
                child.subpage_id.unwrap() == size.subpage_id
            });
            child.and_then(|page| {
                page.frame.deref().borrow().as_ref().map(|frame| {
                    Temporary::new(frame.window.clone())
                })
            })
        })
    }
}

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

    fn after_set_attr(&self, name: DOMString, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
            _ => (),
        }

        if "sandbox" == name.as_slice() {
            let mut modes = AllowNothing as u8;
            for word in value.as_slice().split(' ') {
                modes |= match word.to_ascii_lower().as_slice() {
                    "allow-same-origin" => AllowSameOrigin,
                    "allow-forms" => AllowForms,
                    "allow-pointer-lock" => AllowPointerLock,
                    "allow-popups" => AllowPopups,
                    "allow-scripts" => AllowScripts,
                    "allow-top-navigation" => AllowTopNavigation,
                    _ => AllowNothing
                } as u8;
            }
            self.deref().sandbox.deref().set(Some(modes));
        }
    }

    fn before_remove_attr(&self, name: DOMString, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.before_remove_attr(name.clone(), value),
            _ => (),
        }

        if "sandbox" == name.as_slice() {
            self.deref().sandbox.deref().set(None);
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        match self.super_type() {
            Some(ref s) => s.bind_to_tree(tree_in_doc),
            _ => (),
        }

        if !tree_in_doc { return; }

        match self.get_url() {
            Some(url) => {
                let sandboxed = if self.is_sandboxed() {
                    IFrameSandboxed
                } else {
                    IFrameUnsandboxed
                };

                // Subpage Id
                let window = window_from_node(self).root();
                let page = window.deref().page();
                let subpage_id = page.get_next_subpage_id();

                self.deref().size.deref().set(Some(IFrameSize {
                    pipeline_id: page.id,
                    subpage_id: subpage_id,
                }));

                let ConstellationChan(ref chan) = *page.constellation_chan.deref();
                chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
            }
            _ => ()
        }
    }
}

impl Reflectable for HTMLIFrameElement {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.htmlelement.reflector()
    }
}
<commit_msg> Implement src setter for HTMLIFrameElement #2529<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLIFrameElementDerived};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{HTMLIFrameElementTypeId, Element};
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::Window;
use page::IterablePage;
use servo_msg::constellation_msg::{PipelineId, SubpageId};
use servo_msg::constellation_msg::{IFrameSandboxed, IFrameUnsandboxed};
use servo_msg::constellation_msg::{ConstellationChan, LoadIframeUrlMsg};
use servo_util::namespace::Null;
use servo_util::str::DOMString;

use std::ascii::StrAsciiExt;
use std::cell::Cell;
use url::{Url, UrlParser};

enum SandboxAllowance {
    AllowNothing = 0x00,
    AllowSameOrigin = 0x01,
    AllowTopNavigation = 0x02,
    AllowForms = 0x04,
    AllowScripts = 0x08,
    AllowPointerLock = 0x10,
    AllowPopups = 0x20
}

#[deriving(Encodable)]
pub struct HTMLIFrameElement {
    pub htmlelement: HTMLElement,
    pub size: Traceable<Cell<Option<IFrameSize>>>,
    pub sandbox: Traceable<Cell<Option<u8>>>,
}

impl HTMLIFrameElementDerived for EventTarget {
    fn is_htmliframeelement(&self) -> bool {
       self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLIFrameElementTypeId))
    }
}

#[deriving(Encodable)]
pub struct IFrameSize {
    pub pipeline_id: PipelineId,
    pub subpage_id: SubpageId,
}

pub trait HTMLIFrameElementHelpers {
    fn is_sandboxed(&self) -> bool;
    fn get_url(&self) -> Option<Url>;
    /// http://www.whatwg.org/html/#process-the-iframe-attributes
    fn process_the_iframe_attributes(&self);
}

impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
    fn is_sandboxed(&self) -> bool {
        self.sandbox.deref().get().is_some()
    }

    fn get_url(&self) -> Option<Url> {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.get_attribute(Null, "src").root().and_then(|src| {
            let window = window_from_node(self).root();
            UrlParser::new().base_url(&window.deref().page().get_url())
                .parse(src.deref().value().as_slice()).ok()
        })
    }

    fn process_the_iframe_attributes(&self) {
        match self.get_url() {
            Some(url) => {
                let sandboxed = if self.is_sandboxed() {
                    IFrameSandboxed
                } else {
                    IFrameUnsandboxed
                };

                // Subpage Id
                let window = window_from_node(self).root();
                let page = window.deref().page();
                let subpage_id = page.get_next_subpage_id();

                self.deref().size.deref().set(Some(IFrameSize {
                    pipeline_id: page.id,
                    subpage_id: subpage_id,
                }));

                let ConstellationChan(ref chan) = *page.constellation_chan.deref();
                chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
            }
            _ => ()
        }
    }
}

impl HTMLIFrameElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLIFrameElement {
        HTMLIFrameElement {
            htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document),
            size: Traceable::new(Cell::new(None)),
            sandbox: Traceable::new(Cell::new(None)),
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLIFrameElement> {
        let element = HTMLIFrameElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLIFrameElementBinding::Wrap)
    }
}

impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
    fn Src(&self) -> DOMString {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.get_string_attribute("src")
    }

    fn SetSrc(&self, src: DOMString) {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.set_url_attribute("src", src)
    }

    fn Sandbox(&self) -> DOMString {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.get_string_attribute("sandbox")
    }

    fn SetSandbox(&self, sandbox: DOMString) {
        let element: &JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("sandbox", sandbox);
    }

    fn GetContentWindow(&self) -> Option<Temporary<Window>> {
        self.size.deref().get().and_then(|size| {
            let window = window_from_node(self).root();
            let children = &*window.deref().page.children.deref().borrow();
            let child = children.iter().find(|child| {
                child.subpage_id.unwrap() == size.subpage_id
            });
            child.and_then(|page| {
                page.frame.deref().borrow().as_ref().map(|frame| {
                    Temporary::new(frame.window.clone())
                })
            })
        })
    }
}

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

    fn after_set_attr(&self, name: DOMString, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
            _ => (),
        }

        if "sandbox" == name.as_slice() {
            let mut modes = AllowNothing as u8;
            for word in value.as_slice().split(' ') {
                modes |= match word.to_ascii_lower().as_slice() {
                    "allow-same-origin" => AllowSameOrigin,
                    "allow-forms" => AllowForms,
                    "allow-pointer-lock" => AllowPointerLock,
                    "allow-popups" => AllowPopups,
                    "allow-scripts" => AllowScripts,
                    "allow-top-navigation" => AllowTopNavigation,
                    _ => AllowNothing
                } as u8;
            }
            self.deref().sandbox.deref().set(Some(modes));
        }

        if "src" == name.as_slice() {
            let node: &JSRef<Node> = NodeCast::from_ref(self);
            if node.is_in_doc() {
                self.process_the_iframe_attributes()
            }
        }
    }

    fn before_remove_attr(&self, name: DOMString, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.before_remove_attr(name.clone(), value),
            _ => (),
        }

        if "sandbox" == name.as_slice() {
            self.deref().sandbox.deref().set(None);
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        match self.super_type() {
            Some(ref s) => s.bind_to_tree(tree_in_doc),
            _ => (),
        }

        if tree_in_doc {
            self.process_the_iframe_attributes();
        }
    }
}

impl Reflectable for HTMLIFrameElement {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.htmlelement.reflector()
    }
}
<|endoftext|>


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

use dom::bindings::cell::{DOMRefCell, Ref, RefMut};
use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
use dom::bindings::codegen::Bindings::WindowBinding;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::error::{Fallible, InvalidCharacter};
use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext;
use dom::console::Console;
use dom::document::Document;
use dom::eventtarget::{EventTarget, WindowTypeId, EventTargetHelpers};
use dom::location::Location;
use dom::navigator::Navigator;
use dom::performance::Performance;
use dom::screen::Screen;
use layout_interface::NoQuery;
use page::Page;
use script_task::{ExitWindowMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
use script_task::FromWindow;
use script_traits::ScriptControlChan;
use timers::{TimerId, TimerManager};

use servo_msg::compositor_msg::ScriptListener;
use servo_msg::constellation_msg::LoadData;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::{DOMString,HTML_SPACE_CHARACTERS};

use js::jsapi::JS_EvaluateUCScript;
use js::jsapi::JSContext;
use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::{JSVal, UndefinedValue};
use js::rust::with_compartment;
use url::{Url, UrlParser};

use libc;
use serialize::base64::{FromBase64, ToBase64, STANDARD};
use std::default::Default;
use std::rc::Rc;
use time;

#[dom_struct]
pub struct Window {
    eventtarget: EventTarget,
    script_chan: ScriptChan,
    control_chan: ScriptControlChan,
    console: MutNullableJS<Console>,
    location: MutNullableJS<Location>,
    navigator: MutNullableJS<Navigator>,
    image_cache_task: ImageCacheTask,
    compositor: DOMRefCell<Box<ScriptListener+'static>>,
    browser_context: DOMRefCell<Option<BrowserContext>>,
    page: Rc<Page>,
    performance: MutNullableJS<Performance>,
    navigation_start: u64,
    navigation_start_precise: f64,
    screen: MutNullableJS<Screen>,
    timers: TimerManager
}

impl Window {
    pub fn get_cx(&self) -> *mut JSContext {
        let js_info = self.page().js_info();
        (*js_info.as_ref().unwrap().js_context).ptr
    }

    pub fn script_chan<'a>(&'a self) -> &'a ScriptChan {
        &self.script_chan
    }

    pub fn control_chan<'a>(&'a self) -> &'a ScriptControlChan {
        &self.control_chan
    }

    pub fn image_cache_task<'a>(&'a self) -> &'a ImageCacheTask {
        &self.image_cache_task
    }

    pub fn compositor(&self) -> RefMut<Box<ScriptListener+'static>> {
        self.compositor.borrow_mut()
    }

    pub fn browser_context(&self) -> Ref<Option<BrowserContext>> {
        self.browser_context.borrow()
    }

    pub fn page<'a>(&'a self) -> &'a Page {
        &*self.page
    }

    pub fn navigation_start(&self) -> u64 {
        self.navigation_start
    }

    pub fn navigation_start_precise(&self) -> f64 {
        self.navigation_start_precise
    }

    pub fn get_url(&self) -> Url {
        self.page().get_url()
    }
}

// http://www.whatwg.org/html/#atob
pub fn base64_btoa(btoa: DOMString) -> Fallible<DOMString> {
    let input = btoa.as_slice();
    // "The btoa() method must throw an InvalidCharacterError exception if
    //  the method's first argument contains any character whose code point
    //  is greater than U+00FF."
    if input.chars().any(|c: char| c > '\u00FF') {
        Err(InvalidCharacter)
    } else {
        // "Otherwise, the user agent must convert that argument to a
        //  sequence of octets whose nth octet is the eight-bit
        //  representation of the code point of the nth character of
        //  the argument,"
        let octets = input.chars().map(|c: char| c as u8).collect::<Vec<u8>>();

        // "and then must apply the base64 algorithm to that sequence of
        //  octets, and return the result. [RFC4648]"
        Ok(octets.as_slice().to_base64(STANDARD))
    }
}

// http://www.whatwg.org/html/#atob
pub fn base64_atob(atob: DOMString) -> Fallible<DOMString> {
    // "Let input be the string being parsed."
    let mut input = atob.as_slice();

    // "Remove all space characters from input."
    // serialize::base64::from_base64 ignores \r and \n,
    // but it treats the other space characters as
    // invalid input.
    fn is_html_space(c: char) -> bool {
        HTML_SPACE_CHARACTERS.iter().any(|&m| m == c)
    }
    let without_spaces = input.chars()
        .filter(|&c| ! is_html_space(c))
        .collect::<String>();
    input = without_spaces.as_slice();

    // "If the length of input divides by 4 leaving no remainder, then:
    //  if input ends with one or two U+003D EQUALS SIGN (=) characters,
    //  remove them from input."
    if input.len() % 4 == 0 {
        if input.ends_with("==") {
            input = input.slice_to(input.len() - 2)
        } else if input.ends_with("=") {
            input = input.slice_to(input.len() - 1)
        }
    }

    // "If the length of input divides by 4 leaving a remainder of 1,
    //  throw an InvalidCharacterError exception and abort these steps."
    if input.len() % 4 == 1 {
        return Err(InvalidCharacter)
    }

    // "If input contains a character that is not in the following list of
    //  characters and character ranges, throw an InvalidCharacterError
    //  exception and abort these steps:
    //
    //  U+002B PLUS SIGN (+)
    //  U+002F SOLIDUS (/)
    //  Alphanumeric ASCII characters"
    if input.chars()
        .find(|&c| !(c == '+' || c == '/' || c.is_alphanumeric()))
        .is_some() {
            return Err(InvalidCharacter)
        }

    match input.from_base64() {
        Ok(data) => Ok(data.iter().map(|&b| b as char).collect::<String>()),
        Err(..) => Err(InvalidCharacter)
    }
}

impl<'a> WindowMethods for JSRef<'a, Window> {
    fn Alert(self, s: DOMString) {
        // Right now, just print to the console
        println!("ALERT: {:s}", s);
    }

    fn Close(self) {
        let ScriptChan(ref chan) = self.script_chan;
        chan.send(ExitWindowMsg(self.page.id.clone()));
    }

    fn Document(self) -> Temporary<Document> {
        let frame = self.page().frame();
        Temporary::new(frame.as_ref().unwrap().document.clone())
    }

    fn Location(self) -> Temporary<Location> {
        if self.location.get().is_none() {
            let page = self.page.clone();
            let location = Location::new(self, page);
            self.location.assign(Some(location));
        }
        self.location.get().unwrap()
    }

    fn Console(self) -> Temporary<Console> {
        if self.console.get().is_none() {
            let console = Console::new(&global::Window(self));
            self.console.assign(Some(console));
        }
        self.console.get().unwrap()
    }

    fn Navigator(self) -> Temporary<Navigator> {
        if self.navigator.get().is_none() {
            let navigator = Navigator::new(self);
            self.navigator.assign(Some(navigator));
        }
        self.navigator.get().unwrap()
    }

    fn SetTimeout(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.timers.set_timeout_or_interval(callback,
                                            timeout,
                                            false, // is_interval
                                            FromWindow(self.page.id.clone()),
                                            self.script_chan.clone())
    }

    fn ClearTimeout(self, handle: i32) {
        self.timers.clear_timeout_or_interval(handle);
    }

    fn SetInterval(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.timers.set_timeout_or_interval(callback,
                                            timeout,
                                            true, // is_interval
                                            FromWindow(self.page.id.clone()),
                                            self.script_chan.clone())
    }

    fn ClearInterval(self, handle: i32) {
        self.ClearTimeout(handle);
    }

    fn Window(self) -> Temporary<Window> {
        Temporary::from_rooted(self)
    }

    fn Self(self) -> Temporary<Window> {
        self.Window()
    }

    // http://www.whatwg.org/html/#dom-frames
    fn Frames(self) -> Temporary<Window> {
        self.Window()
    }

    fn Parent(self) -> Temporary<Window> {
        //TODO - Once we support iframes correctly this needs to return the parent frame
        self.Window()
    }

    fn Performance(self) -> Temporary<Performance> {
        if self.performance.get().is_none() {
            let performance = Performance::new(self);
            self.performance.assign(Some(performance));
        }
        self.performance.get().unwrap()
    }

    event_handler!(click, GetOnclick, SetOnclick)
    event_handler!(load, GetOnload, SetOnload)
    event_handler!(unload, GetOnunload, SetOnunload)
    error_event_handler!(error, GetOnerror, SetOnerror)

    fn Screen(self) -> Temporary<Screen> {
        if self.screen.get().is_none() {
            let screen = Screen::new(self);
            self.screen.assign(Some(screen));
        }
        self.screen.get().unwrap()
    }

    fn Debug(self, message: DOMString) {
        debug!("{:s}", message);
    }

    fn Gc(self) {
        unsafe {
            JS_GC(JS_GetRuntime(self.get_cx()));
        }
    }

    fn Btoa(self, btoa: DOMString) -> Fallible<DOMString> {
        base64_btoa(btoa)
    }

    fn Atob(self, atob: DOMString) -> Fallible<DOMString> {
        base64_atob(atob)
    }
}

impl Reflectable for Window {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.eventtarget.reflector()
    }
}

pub trait WindowHelpers {
    fn reflow(self);
    fn flush_layout(self);
    fn wait_until_safe_to_modify_dom(self);
    fn init_browser_context(self, doc: JSRef<Document>);
    fn load_url(self, href: DOMString);
    fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext);
    fn evaluate_js_with_result(self, code: &str) -> JSVal;
    fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal;
}

impl<'a> WindowHelpers for JSRef<'a, Window> {
    fn evaluate_js_with_result(self, code: &str) -> JSVal {
        self.evaluate_script_with_result(code, "")
    }

    fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal {
        let global = self.reflector().get_jsobject();
        let code: Vec<u16> = code.as_slice().utf16_units().collect();
        let mut rval = UndefinedValue();
        let filename = filename.to_c_str();
        let cx = self.get_cx();

        with_compartment(cx, global, || {
            unsafe {
                if JS_EvaluateUCScript(cx, global, code.as_ptr(),
                                       code.len() as libc::c_uint,
                                       filename.as_ptr(), 1, &mut rval) == 0 {
                    debug!("error evaluating JS string");
                }
                rval
            }
        })
    }

    fn reflow(self) {
        self.page().damage();
    }

    fn flush_layout(self) {
        self.page().flush_layout(NoQuery);
    }

    fn wait_until_safe_to_modify_dom(self) {
        // FIXME: This disables concurrent layout while we are modifying the DOM, since
        //        our current architecture is entirely unsafe in the presence of races.
        self.page().join_layout();
    }

    fn init_browser_context(self, doc: JSRef<Document>) {
        *self.browser_context.borrow_mut() = Some(BrowserContext::new(doc));
    }

    /// Commence a new URL load which will either replace this window or scroll to a fragment.
    fn load_url(self, href: DOMString) {
        let base_url = self.page().get_url();
        debug!("current page url is {}", base_url);
        let url = UrlParser::new().base_url(&base_url).parse(href.as_slice());
        // FIXME: handle URL parse errors more gracefully.
        let url = url.unwrap();
        let ScriptChan(ref script_chan) = self.script_chan;
        if href.as_slice().starts_with("#") {
            script_chan.send(TriggerFragmentMsg(self.page.id, url));
        } else {
            script_chan.send(TriggerLoadMsg(self.page.id, LoadData::new(url)));
        }
    }

    fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
        let this_value = self.reflector().get_jsobject();
        self.timers.fire_timer(timer_id, this_value, cx);
    }
}

impl Window {
    pub fn new(cx: *mut JSContext,
               page: Rc<Page>,
               script_chan: ScriptChan,
               control_chan: ScriptControlChan,
               compositor: Box<ScriptListener+'static>,
               image_cache_task: ImageCacheTask)
               -> Temporary<Window> {
        let win = box Window {
            eventtarget: EventTarget::new_inherited(WindowTypeId),
            script_chan: script_chan,
            control_chan: control_chan,
            console: Default::default(),
            compositor: DOMRefCell::new(compositor),
            page: page,
            location: Default::default(),
            navigator: Default::default(),
            image_cache_task: image_cache_task,
            browser_context: DOMRefCell::new(None),
            performance: Default::default(),
            navigation_start: time::get_time().sec as u64,
            navigation_start_precise: time::precise_time_s(),
            screen: Default::default(),
            timers: TimerManager::new()
        };

        WindowBinding::Wrap(cx, win)
    }
}
<commit_msg>Flush layout after executing timers.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::{DOMRefCell, Ref, RefMut};
use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
use dom::bindings::codegen::Bindings::WindowBinding;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::error::{Fallible, InvalidCharacter};
use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext;
use dom::console::Console;
use dom::document::Document;
use dom::eventtarget::{EventTarget, WindowTypeId, EventTargetHelpers};
use dom::location::Location;
use dom::navigator::Navigator;
use dom::performance::Performance;
use dom::screen::Screen;
use layout_interface::NoQuery;
use page::Page;
use script_task::{ExitWindowMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
use script_task::FromWindow;
use script_traits::ScriptControlChan;
use timers::{TimerId, TimerManager};

use servo_msg::compositor_msg::ScriptListener;
use servo_msg::constellation_msg::LoadData;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::{DOMString,HTML_SPACE_CHARACTERS};

use js::jsapi::JS_EvaluateUCScript;
use js::jsapi::JSContext;
use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::{JSVal, UndefinedValue};
use js::rust::with_compartment;
use url::{Url, UrlParser};

use libc;
use serialize::base64::{FromBase64, ToBase64, STANDARD};
use std::default::Default;
use std::rc::Rc;
use time;

#[dom_struct]
pub struct Window {
    eventtarget: EventTarget,
    script_chan: ScriptChan,
    control_chan: ScriptControlChan,
    console: MutNullableJS<Console>,
    location: MutNullableJS<Location>,
    navigator: MutNullableJS<Navigator>,
    image_cache_task: ImageCacheTask,
    compositor: DOMRefCell<Box<ScriptListener+'static>>,
    browser_context: DOMRefCell<Option<BrowserContext>>,
    page: Rc<Page>,
    performance: MutNullableJS<Performance>,
    navigation_start: u64,
    navigation_start_precise: f64,
    screen: MutNullableJS<Screen>,
    timers: TimerManager
}

impl Window {
    pub fn get_cx(&self) -> *mut JSContext {
        let js_info = self.page().js_info();
        (*js_info.as_ref().unwrap().js_context).ptr
    }

    pub fn script_chan<'a>(&'a self) -> &'a ScriptChan {
        &self.script_chan
    }

    pub fn control_chan<'a>(&'a self) -> &'a ScriptControlChan {
        &self.control_chan
    }

    pub fn image_cache_task<'a>(&'a self) -> &'a ImageCacheTask {
        &self.image_cache_task
    }

    pub fn compositor(&self) -> RefMut<Box<ScriptListener+'static>> {
        self.compositor.borrow_mut()
    }

    pub fn browser_context(&self) -> Ref<Option<BrowserContext>> {
        self.browser_context.borrow()
    }

    pub fn page<'a>(&'a self) -> &'a Page {
        &*self.page
    }

    pub fn navigation_start(&self) -> u64 {
        self.navigation_start
    }

    pub fn navigation_start_precise(&self) -> f64 {
        self.navigation_start_precise
    }

    pub fn get_url(&self) -> Url {
        self.page().get_url()
    }
}

// http://www.whatwg.org/html/#atob
pub fn base64_btoa(btoa: DOMString) -> Fallible<DOMString> {
    let input = btoa.as_slice();
    // "The btoa() method must throw an InvalidCharacterError exception if
    //  the method's first argument contains any character whose code point
    //  is greater than U+00FF."
    if input.chars().any(|c: char| c > '\u00FF') {
        Err(InvalidCharacter)
    } else {
        // "Otherwise, the user agent must convert that argument to a
        //  sequence of octets whose nth octet is the eight-bit
        //  representation of the code point of the nth character of
        //  the argument,"
        let octets = input.chars().map(|c: char| c as u8).collect::<Vec<u8>>();

        // "and then must apply the base64 algorithm to that sequence of
        //  octets, and return the result. [RFC4648]"
        Ok(octets.as_slice().to_base64(STANDARD))
    }
}

// http://www.whatwg.org/html/#atob
pub fn base64_atob(atob: DOMString) -> Fallible<DOMString> {
    // "Let input be the string being parsed."
    let mut input = atob.as_slice();

    // "Remove all space characters from input."
    // serialize::base64::from_base64 ignores \r and \n,
    // but it treats the other space characters as
    // invalid input.
    fn is_html_space(c: char) -> bool {
        HTML_SPACE_CHARACTERS.iter().any(|&m| m == c)
    }
    let without_spaces = input.chars()
        .filter(|&c| ! is_html_space(c))
        .collect::<String>();
    input = without_spaces.as_slice();

    // "If the length of input divides by 4 leaving no remainder, then:
    //  if input ends with one or two U+003D EQUALS SIGN (=) characters,
    //  remove them from input."
    if input.len() % 4 == 0 {
        if input.ends_with("==") {
            input = input.slice_to(input.len() - 2)
        } else if input.ends_with("=") {
            input = input.slice_to(input.len() - 1)
        }
    }

    // "If the length of input divides by 4 leaving a remainder of 1,
    //  throw an InvalidCharacterError exception and abort these steps."
    if input.len() % 4 == 1 {
        return Err(InvalidCharacter)
    }

    // "If input contains a character that is not in the following list of
    //  characters and character ranges, throw an InvalidCharacterError
    //  exception and abort these steps:
    //
    //  U+002B PLUS SIGN (+)
    //  U+002F SOLIDUS (/)
    //  Alphanumeric ASCII characters"
    if input.chars()
        .find(|&c| !(c == '+' || c == '/' || c.is_alphanumeric()))
        .is_some() {
            return Err(InvalidCharacter)
        }

    match input.from_base64() {
        Ok(data) => Ok(data.iter().map(|&b| b as char).collect::<String>()),
        Err(..) => Err(InvalidCharacter)
    }
}

impl<'a> WindowMethods for JSRef<'a, Window> {
    fn Alert(self, s: DOMString) {
        // Right now, just print to the console
        println!("ALERT: {:s}", s);
    }

    fn Close(self) {
        let ScriptChan(ref chan) = self.script_chan;
        chan.send(ExitWindowMsg(self.page.id.clone()));
    }

    fn Document(self) -> Temporary<Document> {
        let frame = self.page().frame();
        Temporary::new(frame.as_ref().unwrap().document.clone())
    }

    fn Location(self) -> Temporary<Location> {
        if self.location.get().is_none() {
            let page = self.page.clone();
            let location = Location::new(self, page);
            self.location.assign(Some(location));
        }
        self.location.get().unwrap()
    }

    fn Console(self) -> Temporary<Console> {
        if self.console.get().is_none() {
            let console = Console::new(&global::Window(self));
            self.console.assign(Some(console));
        }
        self.console.get().unwrap()
    }

    fn Navigator(self) -> Temporary<Navigator> {
        if self.navigator.get().is_none() {
            let navigator = Navigator::new(self);
            self.navigator.assign(Some(navigator));
        }
        self.navigator.get().unwrap()
    }

    fn SetTimeout(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.timers.set_timeout_or_interval(callback,
                                            timeout,
                                            false, // is_interval
                                            FromWindow(self.page.id.clone()),
                                            self.script_chan.clone())
    }

    fn ClearTimeout(self, handle: i32) {
        self.timers.clear_timeout_or_interval(handle);
    }

    fn SetInterval(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.timers.set_timeout_or_interval(callback,
                                            timeout,
                                            true, // is_interval
                                            FromWindow(self.page.id.clone()),
                                            self.script_chan.clone())
    }

    fn ClearInterval(self, handle: i32) {
        self.ClearTimeout(handle);
    }

    fn Window(self) -> Temporary<Window> {
        Temporary::from_rooted(self)
    }

    fn Self(self) -> Temporary<Window> {
        self.Window()
    }

    // http://www.whatwg.org/html/#dom-frames
    fn Frames(self) -> Temporary<Window> {
        self.Window()
    }

    fn Parent(self) -> Temporary<Window> {
        //TODO - Once we support iframes correctly this needs to return the parent frame
        self.Window()
    }

    fn Performance(self) -> Temporary<Performance> {
        if self.performance.get().is_none() {
            let performance = Performance::new(self);
            self.performance.assign(Some(performance));
        }
        self.performance.get().unwrap()
    }

    event_handler!(click, GetOnclick, SetOnclick)
    event_handler!(load, GetOnload, SetOnload)
    event_handler!(unload, GetOnunload, SetOnunload)
    error_event_handler!(error, GetOnerror, SetOnerror)

    fn Screen(self) -> Temporary<Screen> {
        if self.screen.get().is_none() {
            let screen = Screen::new(self);
            self.screen.assign(Some(screen));
        }
        self.screen.get().unwrap()
    }

    fn Debug(self, message: DOMString) {
        debug!("{:s}", message);
    }

    fn Gc(self) {
        unsafe {
            JS_GC(JS_GetRuntime(self.get_cx()));
        }
    }

    fn Btoa(self, btoa: DOMString) -> Fallible<DOMString> {
        base64_btoa(btoa)
    }

    fn Atob(self, atob: DOMString) -> Fallible<DOMString> {
        base64_atob(atob)
    }
}

impl Reflectable for Window {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.eventtarget.reflector()
    }
}

pub trait WindowHelpers {
    fn reflow(self);
    fn flush_layout(self);
    fn wait_until_safe_to_modify_dom(self);
    fn init_browser_context(self, doc: JSRef<Document>);
    fn load_url(self, href: DOMString);
    fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext);
    fn evaluate_js_with_result(self, code: &str) -> JSVal;
    fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal;
}

impl<'a> WindowHelpers for JSRef<'a, Window> {
    fn evaluate_js_with_result(self, code: &str) -> JSVal {
        self.evaluate_script_with_result(code, "")
    }

    fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal {
        let global = self.reflector().get_jsobject();
        let code: Vec<u16> = code.as_slice().utf16_units().collect();
        let mut rval = UndefinedValue();
        let filename = filename.to_c_str();
        let cx = self.get_cx();

        with_compartment(cx, global, || {
            unsafe {
                if JS_EvaluateUCScript(cx, global, code.as_ptr(),
                                       code.len() as libc::c_uint,
                                       filename.as_ptr(), 1, &mut rval) == 0 {
                    debug!("error evaluating JS string");
                }
                rval
            }
        })
    }

    fn reflow(self) {
        self.page().damage();
    }

    fn flush_layout(self) {
        self.page().flush_layout(NoQuery);
    }

    fn wait_until_safe_to_modify_dom(self) {
        // FIXME: This disables concurrent layout while we are modifying the DOM, since
        //        our current architecture is entirely unsafe in the presence of races.
        self.page().join_layout();
    }

    fn init_browser_context(self, doc: JSRef<Document>) {
        *self.browser_context.borrow_mut() = Some(BrowserContext::new(doc));
    }

    /// Commence a new URL load which will either replace this window or scroll to a fragment.
    fn load_url(self, href: DOMString) {
        let base_url = self.page().get_url();
        debug!("current page url is {}", base_url);
        let url = UrlParser::new().base_url(&base_url).parse(href.as_slice());
        // FIXME: handle URL parse errors more gracefully.
        let url = url.unwrap();
        let ScriptChan(ref script_chan) = self.script_chan;
        if href.as_slice().starts_with("#") {
            script_chan.send(TriggerFragmentMsg(self.page.id, url));
        } else {
            script_chan.send(TriggerLoadMsg(self.page.id, LoadData::new(url)));
        }
    }

    fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
        let this_value = self.reflector().get_jsobject();
        self.timers.fire_timer(timer_id, this_value, cx);
        self.flush_layout();
    }
}

impl Window {
    pub fn new(cx: *mut JSContext,
               page: Rc<Page>,
               script_chan: ScriptChan,
               control_chan: ScriptControlChan,
               compositor: Box<ScriptListener+'static>,
               image_cache_task: ImageCacheTask)
               -> Temporary<Window> {
        let win = box Window {
            eventtarget: EventTarget::new_inherited(WindowTypeId),
            script_chan: script_chan,
            control_chan: control_chan,
            console: Default::default(),
            compositor: DOMRefCell::new(compositor),
            page: page,
            location: Default::default(),
            navigator: Default::default(),
            image_cache_task: image_cache_task,
            browser_context: DOMRefCell::new(None),
            performance: Default::default(),
            navigation_start: time::get_time().sec as u64,
            navigation_start_precise: time::precise_time_s(),
            screen: Default::default(),
            timers: TimerManager::new()
        };

        WindowBinding::Wrap(cx, win)
    }
}
<|endoftext|>


<commit_before><commit_msg>Add problem #91<commit_after>use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 91,
    answer: "14234",
    solver: solve
};

fn count_right_o(x_max: uint, y_max: uint) -> uint {
    return x_max * y_max;
}

fn count_right_p(x_max: uint, y_max: uint) -> uint {
    let mut cnt = x_max * y_max; // (0, y0) - (xi, y0) => xi: [1, x_max], y0: [0, y_max]

    for uint::range(1, x_max + 1) |x| {
        for uint::range(1, y_max + 1) |y| {
            let d = x.gcd(&y);
            let (dx, neg_dy) = (y / d, x / d);
            cnt += uint::min(y / neg_dy, (x_max - x) / dx);
        }
    }

    return cnt;
}

fn solve() -> ~str {
    let (x_max, y_max) = (50, 50);
    let answer = count_right_o(x_max, y_max) + count_right_p(x_max, y_max) * 2;
    return answer.to_str();
}
<|endoftext|>


<commit_before><commit_msg>Add testing module for Coord<commit_after><|endoftext|>


<commit_before><commit_msg>Add test for wild fields<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![deny(unneeded_field_pattern)]
#[allow(dead_code, unused)]

struct Foo {
    a: i32,
    b: i32,
    c: i32,
}

fn main() {
    let f = Foo { a: 0, b: 0, c: 0 };

    match f {
        Foo { a: _, b: 0, .. } => {} //~ERROR You matched a field with a wildcard pattern
                                     //~^ HELP Try with `Foo { b: 0, .. }`
        Foo { a: _, b: _, c: _ } => {} //~ERROR All the struct fields are matched to a
                                       //~^ HELP Try with `Foo { .. }`
    }
    match f {
        Foo { b: 0, .. } => {} // should be OK
        Foo { .. } => {} // and the Force might be with this one
    }
}<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/prost-codegen/0.1.1")]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "4096"]

extern crate itertools;
extern crate proc_macro;
extern crate syn;

#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate quote;

use std::str;

use itertools::Itertools;
use proc_macro::TokenStream;
use syn::Ident;

// Proc-macro crates can't export anything, so error chain definitions go in a private module.
mod error {
    error_chain!();
}
use error::*;

mod field;
use field::Field;

fn try_message(input: TokenStream) -> Result<TokenStream> {
    let syn::DeriveInput { ident, generics, body, .. } = syn::parse_derive_input(&input.to_string())?;

    if !generics.lifetimes.is_empty() ||
       !generics.ty_params.is_empty() ||
       !generics.where_clause.predicates.is_empty() {
        bail!("Message may not be derived for generic type");
    }

    let fields = match body {
        syn::Body::Struct(syn::VariantData::Struct(fields)) => fields,
        syn::Body::Struct(syn::VariantData::Tuple(fields)) => fields,
        syn::Body::Struct(syn::VariantData::Unit) => Vec::new(),
        syn::Body::Enum(..) => bail!("Message can not be derived for an enum"),
    };

    let mut fields = fields.into_iter()
                           .enumerate()
                           .flat_map(|(idx, field)| {
                               let field_ident = field.ident
                                                       .unwrap_or_else(|| Ident::new(idx.to_string()));
                               match Field::new(field.attrs) {
                                   Ok(Some(field)) => Some(Ok((field_ident, field))),
                                   Ok(None) => None,
                                   Err(err) => Some(Err(err).chain_err(|| {
                                       format!("invalid message field {}.{}",
                                               ident, field_ident)
                                   })),
                               }
                           })
                           .collect::<Result<Vec<(Ident, Field)>>>()?;

    // Sort the fields by tag number so that fields will be encoded in tag order.
    // TODO: This encodes oneof fields in the position of their lowest tag,
    // regardless of the currently occupied variant, is that consequential?
    // See: https://developers.google.com/protocol-buffers/docs/encoding#order
    fields.sort_by_key(|&(_, ref field)| field.tags().into_iter().min().unwrap());
    let fields = fields;

    let mut tags = fields.iter().flat_map(|&(_, ref field)| field.tags()).collect::<Vec<_>>();
    let num_tags = tags.len();
    tags.sort();
    tags.dedup();
    if tags.len() != num_tags {
        bail!("message {} has fields with duplicate tags", ident);
    }

    let dummy_const = Ident::new(format!("_IMPL_MESSAGE_FOR_{}", ident));

    let encoded_len = fields.iter()
                            .map(|&(ref field_ident, ref field)| {
                                field.encoded_len(&Ident::new(format!("self.{}", field_ident)))
                            });

    let encode = fields.iter()
                       .map(|&(ref field_ident, ref field)| {
                           field.encode(&Ident::new(format!("self.{}", field_ident)))
                       });

    let merge = fields.iter().map(|&(ref field_ident, ref field)| {
        let merge = field.merge(&Ident::new(format!("self.{}", field_ident)));
        let tags = field.tags().into_iter().map(|tag| quote!(#tag)).intersperse(quote!(|));
        quote!(#(#tags)* => #merge.map_err(|mut error| {
            error.push(stringify!(#ident), stringify!(#field_ident));
            error
        }),)
    });

    let default = fields.iter()
                        .map(|&(ref field_ident, ref field)| {
                            let value = field.default();
                            quote!(#field_ident: #value,)
                        });

    let methods = fields.iter()
                        .flat_map(|&(ref field_ident, ref field)| field.methods(field_ident))
                        .collect::<Vec<_>>();
    let methods = if methods.is_empty() {
        quote!()
    } else {
        quote! {
            impl #ident {
                #(#methods)*
            }
        }
    };

    let expanded = quote! {
        #[allow(
            non_upper_case_globals,
            unused_attributes,
            unused_imports,
            unused_qualifications,
            unused_variables
        )]
        const #dummy_const: () = {

            extern crate prost as _prost;
            extern crate bytes as _bytes;

            #[automatically_derived]
            impl _prost::Message for #ident {
                #[inline]
                fn encode_raw<B>(&self, buf: &mut B) where B: _bytes::BufMut {
                    #(#encode)*
                }

                #[inline]
                fn merge_field<B>(&mut self, buf: &mut B) -> ::std::result::Result<(), _prost::DecodeError>
                where B: _bytes::Buf {
                    let (tag, wire_type) = _prost::encoding::decode_key(buf)?;
                    match tag {
                        #(#merge)*
                        _ => _prost::encoding::skip_field(wire_type, buf),
                    }
                }

                #[inline]
                fn encoded_len(&self) -> usize {
                    0 #(+ #encoded_len)*
                }
            }

            #[automatically_derived]
            impl Default for #ident {
                fn default() -> #ident {
                    #ident {
                        #(#default)*
                    }
                }
            }
        };

        #methods
    };

    expanded.parse::<TokenStream>().map_err(|err| Error::from(format!("{:?}", err)))
}

#[proc_macro_derive(Message, attributes(prost))]
pub fn message(input: TokenStream) -> TokenStream {
    try_message(input).unwrap()
}

#[proc_macro_derive(Enumeration, attributes(prost))]
pub fn enumeration(input: TokenStream) -> TokenStream {
    let syn::DeriveInput { ident, generics, body, .. } =
        syn::parse_derive_input(&input.to_string()).expect("unable to parse enumeration type");

    if !generics.lifetimes.is_empty() ||
       !generics.ty_params.is_empty() ||
       !generics.where_clause.predicates.is_empty() {
        panic!("Enumeration may not be derived for generic type");
    }

    let variants = match body {
        syn::Body::Struct(..) => panic!("Enumeration can not be derived for a struct"),
        syn::Body::Enum(variants) => variants,
    };

    let variants = variants.into_iter().map(|syn::Variant { ident: variant, data, discriminant, .. }| {
        if let syn::VariantData::Unit = data {
            if let Some(discriminant) = discriminant {
                (variant, discriminant)
            } else {
                panic!("Enumeration variants must have a discriminant value: {}::{}", ident, variant);
            }
        } else {
            panic!("Enumeration variants may not have fields: {}::{}", ident, variant);
        }
    }).collect::<Vec<_>>();

    if variants.is_empty() {
        panic!("Enumeration must have at least one variant: {}", ident);
    }

    let default = variants[0].0.clone();

    let dummy_const = Ident::new(format!("_IMPL_ENUMERATION_FOR_{}", ident));
    let is_valid = variants.iter().map(|&(_, ref value)| quote!(#value => true));
    let from = variants.iter().map(|&(ref variant, ref value)| quote!(#value => ::std::option::Option::Some(#ident::#variant)));

    let is_valid_doc = format!("Returns `true` if `value` is a variant of `{}`.", ident);
    let from_i32_doc = format!("Converts an `i32` to a `{}`, or `None` if `value` is not a valid variant.", ident);

    let expanded = quote! {
        #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
        const #dummy_const: () = {
            extern crate bytes as _bytes;
            extern crate prost as _prost;

            #[automatically_derived]
            impl #ident {

                #[doc=#is_valid_doc]
                pub fn is_valid(value: i32) -> bool {
                    match value {
                        #(#is_valid,)*
                        _ => false,
                    }
                }

                #[doc=#from_i32_doc]
                pub fn from_i32(value: i32) -> ::std::option::Option<#ident> {
                    match value {
                        #(#from,)*
                        _ => ::std::option::Option::None,
                    }
                }
            }

            #[automatically_derived]
            impl ::std::default::Default for #ident {
                fn default() -> #ident {
                    #ident::#default
                }
            }

            #[automatically_derived]
            impl ::std::convert::From<#ident> for i32 {
                fn from(value: #ident) -> i32 {
                    value as i32
                }
            }
        };
    };

    expanded.parse().unwrap()
}

fn try_oneof(input: TokenStream) -> Result<TokenStream> {
    let syn::DeriveInput { ident, generics, body, .. } = syn::parse_derive_input(&input.to_string())?;

    if !generics.lifetimes.is_empty() ||
       !generics.ty_params.is_empty() ||
       !generics.where_clause.predicates.is_empty() {
        panic!("Oneof may not be derived for generic type");
    }

    let variants = match body {
        syn::Body::Enum(variants) => variants,
        syn::Body::Struct(..) => panic!("Oneof can not be derived for a struct"),
    };

    // Map the variants into 'fields'.
    let fields = variants.into_iter().map(|variant| {
        let variant_ident = variant.ident;
        let attrs = variant.attrs;
        if let syn::VariantData::Tuple(fields) = variant.data {
            if fields.len() != 1 {
                bail!("invalid oneof variant {}::{}: oneof variants must have a single field",
                      ident, variant_ident);
            }
            match Field::new_oneof(attrs) {
                Ok(Some(field)) => Ok((variant_ident, field)),
                Ok(None) => bail!("invalid oneof variant {}::{}: oneof variants may not be ignored",
                                  ident, variant_ident),
                Err(err) => bail!("invalid oneof variant {}::{}: {}", ident, variant_ident, err),
            }
        } else {
            bail!("invalid oneof variant {}::{}: oneof variants must have a single field",
                  ident, variant_ident);
        }
    }).collect::<Result<Vec<(Ident, Field)>>>()?;

    let mut tags = fields.iter().flat_map(|&(ref variant_ident, ref field)| -> Result<u32> {
        if field.tags().len() > 1 {
            bail!("invalid oneof variant {}::{}: oneof variants may only have a single tag",
                  ident, variant_ident);
        }
        Ok(field.tags()[0])
    }).collect::<Vec<_>>();
    tags.sort();
    tags.dedup();
    if tags.len() != fields.len() {
        panic!("invalid oneof {}: variants have duplicate tags", ident);
    }

    let dummy_const = Ident::new(format!("_IMPL_ONEOF_FOR_{}", ident));

    let encode = fields.iter().map(|&(ref variant_ident, ref field)| {
        let encode = field.encode(&Ident::new("*value"));
        quote!(#ident::#variant_ident(ref value) => { #encode })
    });

    let merge = fields.iter().map(|&(ref variant_ident, ref field)| {
        let tag = field.tags()[0];
        let merge = field.merge(&Ident::new("value"));
        quote! {
            #tag => {
                let mut value = ::std::default::Default::default();
                #merge.map(|_| *field = ::std::option::Option::Some(#ident::#variant_ident(value)))
            }
        }
    });

    let encoded_len = fields.iter().map(|&(ref variant_ident, ref field)| {
        let encoded_len = field.encoded_len(&Ident::new("*value"));
        quote!(#ident::#variant_ident(ref value) => #encoded_len)
    });

    let expanded = quote! {
        #[allow(
            non_upper_case_globals,
            unused_attributes,
            unused_imports,
            unused_qualifications,
            unused_variables
        )]
        const #dummy_const: () = {
            extern crate bytes as _bytes;
            extern crate prost as _prost;

            impl #ident {
                pub fn encode<B>(&self, buf: &mut B) where B: _bytes::BufMut {
                    match *self {
                        #(#encode,)*
                    }
                }

                pub fn merge<B>(field: &mut ::std::option::Option<#ident>,
                                tag: u32,
                                wire_type: _prost::encoding::WireType,
                                buf: &mut B)
                                -> ::std::result::Result<(), _prost::DecodeError>
                where B: _bytes::Buf {
                    match tag {
                        #(#merge,)*
                        _ => unreachable!(concat!("invalid ", stringify!(#ident), " tag: {}"), tag),
                    }
                }

                pub fn encoded_len(&self) -> usize {
                    match *self {
                        #(#encoded_len,)*
                    }
                }
            }
        };
    };

    expanded.parse::<TokenStream>().map_err(|err| Error::from(format!("{:?}", err)))
}

#[proc_macro_derive(Oneof, attributes(prost))]
pub fn oneof(input: TokenStream) -> TokenStream {
    try_oneof(input).unwrap()
}
<commit_msg>Remove inline annotations in derive output<commit_after>#![doc(html_root_url = "https://docs.rs/prost-codegen/0.1.1")]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "4096"]

extern crate itertools;
extern crate proc_macro;
extern crate syn;

#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate quote;

use std::str;

use itertools::Itertools;
use proc_macro::TokenStream;
use syn::Ident;

// Proc-macro crates can't export anything, so error chain definitions go in a private module.
mod error {
    error_chain!();
}
use error::*;

mod field;
use field::Field;

fn try_message(input: TokenStream) -> Result<TokenStream> {
    let syn::DeriveInput { ident, generics, body, .. } = syn::parse_derive_input(&input.to_string())?;

    if !generics.lifetimes.is_empty() ||
       !generics.ty_params.is_empty() ||
       !generics.where_clause.predicates.is_empty() {
        bail!("Message may not be derived for generic type");
    }

    let fields = match body {
        syn::Body::Struct(syn::VariantData::Struct(fields)) => fields,
        syn::Body::Struct(syn::VariantData::Tuple(fields)) => fields,
        syn::Body::Struct(syn::VariantData::Unit) => Vec::new(),
        syn::Body::Enum(..) => bail!("Message can not be derived for an enum"),
    };

    let mut fields = fields.into_iter()
                           .enumerate()
                           .flat_map(|(idx, field)| {
                               let field_ident = field.ident
                                                       .unwrap_or_else(|| Ident::new(idx.to_string()));
                               match Field::new(field.attrs) {
                                   Ok(Some(field)) => Some(Ok((field_ident, field))),
                                   Ok(None) => None,
                                   Err(err) => Some(Err(err).chain_err(|| {
                                       format!("invalid message field {}.{}",
                                               ident, field_ident)
                                   })),
                               }
                           })
                           .collect::<Result<Vec<(Ident, Field)>>>()?;

    // Sort the fields by tag number so that fields will be encoded in tag order.
    // TODO: This encodes oneof fields in the position of their lowest tag,
    // regardless of the currently occupied variant, is that consequential?
    // See: https://developers.google.com/protocol-buffers/docs/encoding#order
    fields.sort_by_key(|&(_, ref field)| field.tags().into_iter().min().unwrap());
    let fields = fields;

    let mut tags = fields.iter().flat_map(|&(_, ref field)| field.tags()).collect::<Vec<_>>();
    let num_tags = tags.len();
    tags.sort();
    tags.dedup();
    if tags.len() != num_tags {
        bail!("message {} has fields with duplicate tags", ident);
    }

    let dummy_const = Ident::new(format!("_IMPL_MESSAGE_FOR_{}", ident));

    let encoded_len = fields.iter()
                            .map(|&(ref field_ident, ref field)| {
                                field.encoded_len(&Ident::new(format!("self.{}", field_ident)))
                            });

    let encode = fields.iter()
                       .map(|&(ref field_ident, ref field)| {
                           field.encode(&Ident::new(format!("self.{}", field_ident)))
                       });

    let merge = fields.iter().map(|&(ref field_ident, ref field)| {
        let merge = field.merge(&Ident::new(format!("self.{}", field_ident)));
        let tags = field.tags().into_iter().map(|tag| quote!(#tag)).intersperse(quote!(|));
        quote!(#(#tags)* => #merge.map_err(|mut error| {
            error.push(stringify!(#ident), stringify!(#field_ident));
            error
        }),)
    });

    let default = fields.iter()
                        .map(|&(ref field_ident, ref field)| {
                            let value = field.default();
                            quote!(#field_ident: #value,)
                        });

    let methods = fields.iter()
                        .flat_map(|&(ref field_ident, ref field)| field.methods(field_ident))
                        .collect::<Vec<_>>();
    let methods = if methods.is_empty() {
        quote!()
    } else {
        quote! {
            impl #ident {
                #(#methods)*
            }
        }
    };

    let expanded = quote! {
        #[allow(
            non_upper_case_globals,
            unused_attributes,
            unused_imports,
            unused_qualifications,
            unused_variables
        )]
        const #dummy_const: () = {

            extern crate prost as _prost;
            extern crate bytes as _bytes;

            #[automatically_derived]
            impl _prost::Message for #ident {
                fn encode_raw<B>(&self, buf: &mut B) where B: _bytes::BufMut {
                    #(#encode)*
                }

                fn merge_field<B>(&mut self, buf: &mut B) -> ::std::result::Result<(), _prost::DecodeError>
                where B: _bytes::Buf {
                    let (tag, wire_type) = _prost::encoding::decode_key(buf)?;
                    match tag {
                        #(#merge)*
                        _ => _prost::encoding::skip_field(wire_type, buf),
                    }
                }

                fn encoded_len(&self) -> usize {
                    0 #(+ #encoded_len)*
                }
            }

            #[automatically_derived]
            impl Default for #ident {
                fn default() -> #ident {
                    #ident {
                        #(#default)*
                    }
                }
            }
        };

        #methods
    };

    expanded.parse::<TokenStream>().map_err(|err| Error::from(format!("{:?}", err)))
}

#[proc_macro_derive(Message, attributes(prost))]
pub fn message(input: TokenStream) -> TokenStream {
    try_message(input).unwrap()
}

#[proc_macro_derive(Enumeration, attributes(prost))]
pub fn enumeration(input: TokenStream) -> TokenStream {
    let syn::DeriveInput { ident, generics, body, .. } =
        syn::parse_derive_input(&input.to_string()).expect("unable to parse enumeration type");

    if !generics.lifetimes.is_empty() ||
       !generics.ty_params.is_empty() ||
       !generics.where_clause.predicates.is_empty() {
        panic!("Enumeration may not be derived for generic type");
    }

    let variants = match body {
        syn::Body::Struct(..) => panic!("Enumeration can not be derived for a struct"),
        syn::Body::Enum(variants) => variants,
    };

    let variants = variants.into_iter().map(|syn::Variant { ident: variant, data, discriminant, .. }| {
        if let syn::VariantData::Unit = data {
            if let Some(discriminant) = discriminant {
                (variant, discriminant)
            } else {
                panic!("Enumeration variants must have a discriminant value: {}::{}", ident, variant);
            }
        } else {
            panic!("Enumeration variants may not have fields: {}::{}", ident, variant);
        }
    }).collect::<Vec<_>>();

    if variants.is_empty() {
        panic!("Enumeration must have at least one variant: {}", ident);
    }

    let default = variants[0].0.clone();

    let dummy_const = Ident::new(format!("_IMPL_ENUMERATION_FOR_{}", ident));
    let is_valid = variants.iter().map(|&(_, ref value)| quote!(#value => true));
    let from = variants.iter().map(|&(ref variant, ref value)| quote!(#value => ::std::option::Option::Some(#ident::#variant)));

    let is_valid_doc = format!("Returns `true` if `value` is a variant of `{}`.", ident);
    let from_i32_doc = format!("Converts an `i32` to a `{}`, or `None` if `value` is not a valid variant.", ident);

    let expanded = quote! {
        #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
        const #dummy_const: () = {
            extern crate bytes as _bytes;
            extern crate prost as _prost;

            #[automatically_derived]
            impl #ident {

                #[doc=#is_valid_doc]
                pub fn is_valid(value: i32) -> bool {
                    match value {
                        #(#is_valid,)*
                        _ => false,
                    }
                }

                #[doc=#from_i32_doc]
                pub fn from_i32(value: i32) -> ::std::option::Option<#ident> {
                    match value {
                        #(#from,)*
                        _ => ::std::option::Option::None,
                    }
                }
            }

            #[automatically_derived]
            impl ::std::default::Default for #ident {
                fn default() -> #ident {
                    #ident::#default
                }
            }

            #[automatically_derived]
            impl ::std::convert::From<#ident> for i32 {
                fn from(value: #ident) -> i32 {
                    value as i32
                }
            }
        };
    };

    expanded.parse().unwrap()
}

fn try_oneof(input: TokenStream) -> Result<TokenStream> {
    let syn::DeriveInput { ident, generics, body, .. } = syn::parse_derive_input(&input.to_string())?;

    if !generics.lifetimes.is_empty() ||
       !generics.ty_params.is_empty() ||
       !generics.where_clause.predicates.is_empty() {
        panic!("Oneof may not be derived for generic type");
    }

    let variants = match body {
        syn::Body::Enum(variants) => variants,
        syn::Body::Struct(..) => panic!("Oneof can not be derived for a struct"),
    };

    // Map the variants into 'fields'.
    let fields = variants.into_iter().map(|variant| {
        let variant_ident = variant.ident;
        let attrs = variant.attrs;
        if let syn::VariantData::Tuple(fields) = variant.data {
            if fields.len() != 1 {
                bail!("invalid oneof variant {}::{}: oneof variants must have a single field",
                      ident, variant_ident);
            }
            match Field::new_oneof(attrs) {
                Ok(Some(field)) => Ok((variant_ident, field)),
                Ok(None) => bail!("invalid oneof variant {}::{}: oneof variants may not be ignored",
                                  ident, variant_ident),
                Err(err) => bail!("invalid oneof variant {}::{}: {}", ident, variant_ident, err),
            }
        } else {
            bail!("invalid oneof variant {}::{}: oneof variants must have a single field",
                  ident, variant_ident);
        }
    }).collect::<Result<Vec<(Ident, Field)>>>()?;

    let mut tags = fields.iter().flat_map(|&(ref variant_ident, ref field)| -> Result<u32> {
        if field.tags().len() > 1 {
            bail!("invalid oneof variant {}::{}: oneof variants may only have a single tag",
                  ident, variant_ident);
        }
        Ok(field.tags()[0])
    }).collect::<Vec<_>>();
    tags.sort();
    tags.dedup();
    if tags.len() != fields.len() {
        panic!("invalid oneof {}: variants have duplicate tags", ident);
    }

    let dummy_const = Ident::new(format!("_IMPL_ONEOF_FOR_{}", ident));

    let encode = fields.iter().map(|&(ref variant_ident, ref field)| {
        let encode = field.encode(&Ident::new("*value"));
        quote!(#ident::#variant_ident(ref value) => { #encode })
    });

    let merge = fields.iter().map(|&(ref variant_ident, ref field)| {
        let tag = field.tags()[0];
        let merge = field.merge(&Ident::new("value"));
        quote! {
            #tag => {
                let mut value = ::std::default::Default::default();
                #merge.map(|_| *field = ::std::option::Option::Some(#ident::#variant_ident(value)))
            }
        }
    });

    let encoded_len = fields.iter().map(|&(ref variant_ident, ref field)| {
        let encoded_len = field.encoded_len(&Ident::new("*value"));
        quote!(#ident::#variant_ident(ref value) => #encoded_len)
    });

    let expanded = quote! {
        #[allow(
            non_upper_case_globals,
            unused_attributes,
            unused_imports,
            unused_qualifications,
            unused_variables
        )]
        const #dummy_const: () = {
            extern crate bytes as _bytes;
            extern crate prost as _prost;

            impl #ident {
                pub fn encode<B>(&self, buf: &mut B) where B: _bytes::BufMut {
                    match *self {
                        #(#encode,)*
                    }
                }

                pub fn merge<B>(field: &mut ::std::option::Option<#ident>,
                                tag: u32,
                                wire_type: _prost::encoding::WireType,
                                buf: &mut B)
                                -> ::std::result::Result<(), _prost::DecodeError>
                where B: _bytes::Buf {
                    match tag {
                        #(#merge,)*
                        _ => unreachable!(concat!("invalid ", stringify!(#ident), " tag: {}"), tag),
                    }
                }

                pub fn encoded_len(&self) -> usize {
                    match *self {
                        #(#encoded_len,)*
                    }
                }
            }
        };
    };

    expanded.parse::<TokenStream>().map_err(|err| Error::from(format!("{:?}", err)))
}

#[proc_macro_derive(Oneof, attributes(prost))]
pub fn oneof(input: TokenStream) -> TokenStream {
    try_oneof(input).unwrap()
}
<|endoftext|>


<commit_before>extern mod kiss3d;
extern mod nalgebra;
extern mod glfw;

//use nalgebra::mat::Rotation;
use nalgebra::na::Vec3;
use kiss3d::window;
use kiss3d::event::KeyReleased;
use kiss3d::camera::{Camera, FirstPersonStereo};
use kiss3d::post_processing::post_processing_effect::PostProcessingEffect;
use kiss3d::post_processing::oculus_stereo::OculusStereo;
//use kiss3d::post_processing::grayscales::Grayscales;

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
    do window::Window::spawn_size("kiss3d_stereo", 1280, 800) |window| {
        let mut c = window.add_cube(1.0, 1.0, 1.0);
        //c.position(

        let eye = Vec3::new(00.0f64, 0.0, 10.0);
        let at  = Vec3::new(00.0f64, 0.0, 0.0);
        let first_person_stereo = @mut FirstPersonStereo::new(eye, at, 0.3f64);
        let camera = first_person_stereo as @mut Camera;
        window.set_camera(camera);

        // Position the window correctly. -6/-26 takes care of icewm default
        // window decoration. Should probably just disable decorations (since
        // the top title is obscured anyway).
        window.glfw_window().set_pos(-6, -26);
        c.set_color(1.0, 0.0, 0.0);

        window.set_light(window::StickToCamera);

        let effect = Some(@mut OculusStereo::new() as @mut PostProcessingEffect);
        //let effect = Some(@mut Grayscales::new() as @mut PostProcessingEffect);
        window.set_post_processing_effect(effect);
        let mut using_shader = true;

        do window.render_loop |w| {
            //c.rotate_by(&Vec3::new(0.0f64, 0.014, 0.0))
            fn update_ipd(camera: @mut FirstPersonStereo, val: f64) -> bool {
                //  cannot borrow `*camera` as immutable because it is also borrowed as mutable
                let ipd = camera.ipd();
                camera.set_ipd(ipd + val);
                println(fmt!("ipd = %f", camera.ipd() as f64));
                true
            }
            do w.poll_events |w, event| {
                match *event {
                    KeyReleased(key) => {
                        match key {
                            glfw::Key1 => {
                                update_ipd(first_person_stereo, 0.1f64)
                            },
                            glfw::Key2 => {
                                update_ipd(first_person_stereo, -0.1f64)
                            },
                            glfw::KeyS => {
                                using_shader = match using_shader {
                                    false =>  {
                                        w.set_post_processing_effect(effect);
                                        true
                                    },
                                    true => {
                                        w.set_post_processing_effect(None);
                                        false
                                    },
                                };
                                false
                            },
                            _ => {
                                false
                            },
                        }
                    }
                    _ => { true }
                }
            }
        }
    }
}
<commit_msg>Allow default keyboard handling on the stereo demo.<commit_after>extern mod kiss3d;
extern mod nalgebra;
extern mod glfw;

//use nalgebra::mat::Rotation;
use nalgebra::na::Vec3;
use kiss3d::window;
use kiss3d::event::KeyReleased;
use kiss3d::camera::{Camera, FirstPersonStereo};
use kiss3d::post_processing::post_processing_effect::PostProcessingEffect;
use kiss3d::post_processing::oculus_stereo::OculusStereo;
//use kiss3d::post_processing::grayscales::Grayscales;

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
    do window::Window::spawn_size("kiss3d_stereo", 1280, 800) |window| {
        let mut c = window.add_cube(1.0, 1.0, 1.0);
        //c.position(

        let eye = Vec3::new(00.0f64, 0.0, 10.0);
        let at  = Vec3::new(00.0f64, 0.0, 0.0);
        let first_person_stereo = @mut FirstPersonStereo::new(eye, at, 0.3f64);
        let camera = first_person_stereo as @mut Camera;
        window.set_camera(camera);

        // Position the window correctly. -6/-26 takes care of icewm default
        // window decoration. Should probably just disable decorations (since
        // the top title is obscured anyway).
        window.glfw_window().set_pos(-6, -26);
        c.set_color(1.0, 0.0, 0.0);

        window.set_light(window::StickToCamera);

        let effect = Some(@mut OculusStereo::new() as @mut PostProcessingEffect);
        //let effect = Some(@mut Grayscales::new() as @mut PostProcessingEffect);
        window.set_post_processing_effect(effect);
        let mut using_shader = true;

        do window.render_loop |w| {
            //c.rotate_by(&Vec3::new(0.0f64, 0.014, 0.0))
            fn update_ipd(camera: @mut FirstPersonStereo, val: f64) -> bool {
                //  cannot borrow `*camera` as immutable because it is also borrowed as mutable
                let ipd = camera.ipd();
                camera.set_ipd(ipd + val);
                println(fmt!("ipd = %f", camera.ipd() as f64));
                true
            }
            do w.poll_events |w, event| {
                match *event {
                    KeyReleased(key) => {
                        match key {
                            glfw::Key1 => {
                                update_ipd(first_person_stereo, 0.1f64)
                            },
                            glfw::Key2 => {
                                update_ipd(first_person_stereo, -0.1f64)
                            },
                            glfw::KeyS => {
                                using_shader = match using_shader {
                                    false =>  {
                                        w.set_post_processing_effect(effect);
                                        true
                                    },
                                    true => {
                                        w.set_post_processing_effect(None);
                                        false
                                    },
                                };
                                false
                            },
                            _ => {
                                true
                            },
                        }
                    }
                    _ => { true }
                }
            }
        }
    }
}
<|endoftext|>