Created
November 28, 2013 15:33
-
-
Save jdm/7693770 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use node::{DocumentTypeId, Node, NodeBase}; | |
use jsmanaged::JSManaged; | |
use super::{Reflectable, Reflector}; | |
use eventtarget::{EventTarget, EventTargetBase, NodeTargetTypeId}; | |
pub trait DocumentDerived { fn is_document(&self) -> bool; } | |
pub trait DocumentBase : NodeBase {} | |
impl EventTargetBase for Document {} | |
impl NodeBase for Document {} | |
impl DocumentBase for Document {} | |
pub struct Document { | |
node: Node, | |
title: ~str | |
} | |
impl DocumentDerived for EventTarget { | |
fn is_document(&self) -> bool { | |
self.type_id == NodeTargetTypeId(DocumentTypeId) | |
} | |
} | |
impl Document { | |
pub fn new() -> JSManaged<Document> { | |
let doc = ~Document { | |
node: Node::new_inherited(DocumentTypeId), | |
title: ~"" | |
}; | |
JSManaged::new(doc) | |
} | |
pub fn title(&self) -> ~str { | |
self.title.clone() | |
} | |
pub fn set_title(&mut self, title: ~str) { | |
self.title = title; | |
} | |
} | |
impl Document { | |
pub fn from<T: DocumentBase>(derived: JSManaged<T>) -> JSManaged<Document> { | |
derived.transmute() | |
} | |
pub fn to<T: DocumentDerived>(base: JSManaged<T>) -> JSManaged<Document> { | |
assert!(base.val().is_document()); | |
base.transmute() | |
} | |
} | |
impl Reflectable for Document { | |
fn reflector<'a> (&'a self) -> &'a Reflector { | |
self.node.reflector() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use eventtarget::{EventTarget, EventTargetBase, NodeTargetTypeId}; | |
use node::{NodeBase, Node, ElementNodeTypeId}; | |
use htmlelement::HTMLElementTypeId; | |
use jsmanaged::JSManaged; | |
use super::{Reflectable, Reflector}; | |
pub trait ElementDerived { fn is_element(&self) -> bool; } | |
pub trait ElementBase : NodeBase {} | |
impl ElementDerived for EventTarget { | |
fn is_element(&self) -> bool { | |
match self.type_id { | |
NodeTargetTypeId(ElementNodeTypeId(_)) => true, | |
_ => false | |
} | |
} | |
} | |
impl EventTargetBase for Element {} | |
impl NodeBase for Element {} | |
impl ElementBase for Element {} | |
#[deriving(Eq)] | |
pub enum ElementTypeId { | |
HTMLElementId(HTMLElementTypeId), | |
} | |
struct Element { | |
node: Node | |
} | |
impl Element { | |
pub fn to<T: ElementDerived>(base: JSManaged<T>) -> JSManaged<Element> { | |
assert!(base.val().is_element()); | |
base.transmute() | |
} | |
} | |
impl Reflectable for Element { | |
fn reflector<'a> (&'a self) -> &'a Reflector { | |
self.node.reflector() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use node::NodeTypeId; | |
use super::{Reflectable, Reflector}; | |
use jsmanaged::JSManaged; | |
#[deriving(Eq)] | |
pub enum EventTargetTypeId { | |
NodeTargetTypeId(NodeTypeId), | |
WindowTargetTypeId | |
} | |
pub trait EventTargetBase {} | |
impl EventTargetBase for EventTarget {} | |
struct EventTarget { | |
reflector_: int, | |
type_id: EventTargetTypeId | |
} | |
impl EventTarget { | |
pub fn new_inherited(type_id: EventTargetTypeId) -> EventTarget { | |
EventTarget { | |
reflector_: 0, | |
type_id: type_id | |
} | |
} | |
pub fn from<T: EventTargetBase>(derived: JSManaged<T>) -> JSManaged<EventTarget> { | |
derived.transmute() | |
} | |
} | |
impl Reflectable for EventTarget { | |
fn reflector<'a> (&'a self) -> &'a Reflector { | |
&self.reflector_ | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use super::{Reflectable, Reflector}; | |
use element::{Element, ElementBase, HTMLElementId}; | |
use eventtarget::{EventTargetBase, EventTarget, NodeTargetTypeId}; | |
use node::{NodeBase, ElementNodeTypeId}; | |
pub trait HTMLElementDerived { fn is_htmlelement(&self) -> bool; } | |
pub trait HTMLElementBase : ElementBase {} | |
impl HTMLElementDerived for EventTarget { | |
fn is_htmlelement(&self) -> bool { | |
match self.type_id { | |
NodeTargetTypeId(ElementNodeTypeId(HTMLElementId(_))) => true, | |
_ => false | |
} | |
} | |
} | |
impl EventTargetBase for HTMLElement {} | |
impl NodeBase for HTMLElement {} | |
impl ElementBase for HTMLElement {} | |
impl HTMLElementBase for HTMLElement {} | |
#[deriving(Eq)] | |
pub enum HTMLElementTypeId { | |
VideoElementId, | |
UnknownElementId, | |
} | |
pub struct HTMLElement { | |
element: Element | |
} | |
impl Reflectable for HTMLElement { | |
fn reflector<'a> (&'a self) -> &'a Reflector { | |
self.element.reflector() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[feature(macro_rules)]; | |
#[macro_escape]; | |
use self::window::Window; | |
use self::eventtarget::EventTarget; | |
use self::node::Node; | |
use self::document::Document; | |
pub trait Reflectable { | |
fn reflector<'a> (&'a self) -> &'a Reflector; | |
} | |
macro_rules! delegate_parent( | |
($tr: ident, $ty: ident, $name: ident, $field: ident) => ( | |
impl $tr for $ty { | |
fn $name(&self) -> bool { | |
self.$field.$name() | |
} | |
} | |
) | |
) | |
type Reflector = int; | |
mod document; | |
mod element; | |
mod eventtarget; | |
mod node; | |
mod htmlelement; | |
mod window; | |
mod jsmanaged; | |
fn main() { | |
// Type::from is a statically-checked upcast | |
// Type::to is a statically+dynamically-checked downcast | |
let mut doc = Document::new(); | |
doc.mut_val().set_title(~"title!"); | |
println(doc.val().title()); | |
let doc_node = Node::from(doc); // ok! | |
println!("{:?}", doc_node.val().eventtarget.reflector_); | |
let _doc_target = EventTarget::from(doc); // ok! | |
let _doc_target2 = EventTarget::from(doc_node); // ok! | |
let _win = Window::new(doc); | |
//let _elem = Element::to(doc_node); // error: runtime failure | |
//let _elem = Element::to(_doc_target); // error: runtime failure | |
let _node = Node::to(_doc_target); // ok! | |
//let _node = Document::from(_win); //error! | |
//let _node = Node::to(_win); //error! | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::unstable::raw::Box; | |
use std::cast; | |
use super::Reflectable; | |
pub struct JSManaged<T> { | |
ptr: *mut Box<T> | |
} | |
impl<T: Reflectable> JSManaged<T> { | |
pub fn new(obj: ~T) -> JSManaged<T> { | |
JSManaged { | |
ptr: unsafe { cast::transmute(obj) } | |
} | |
} | |
} | |
impl<T> JSManaged<T> { | |
pub fn val<'a>(&'a self) -> &'a T { | |
unsafe { | |
&(*self.ptr).data | |
} | |
} | |
pub fn mut_val<'a>(&'a mut self) -> &'a mut T { | |
unsafe { | |
&mut (*self.ptr).data | |
} | |
} | |
} | |
impl<From, To> JSManaged<From> { | |
pub fn transmute(self) -> JSManaged<To> { | |
unsafe { | |
cast::transmute(self) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use document::DocumentDerived; | |
use eventtarget::{EventTargetBase, EventTarget, NodeTargetTypeId, WindowTargetTypeId}; | |
use element::{ElementTypeId, ElementDerived}; | |
use htmlelement::HTMLElementDerived; | |
use jsmanaged::JSManaged; | |
use super::{Reflectable, Reflector}; | |
#[deriving(Eq)] | |
pub enum NodeTypeId { | |
DocumentTypeId, | |
ElementNodeTypeId(ElementTypeId) | |
} | |
pub trait NodeDerived { fn is_node(&self) -> bool; } | |
pub trait NodeBase : EventTargetBase {} | |
impl EventTargetBase for Node {} | |
impl NodeBase for Node {} | |
delegate_parent!(HTMLElementDerived, Node, is_htmlelement, eventtarget) | |
delegate_parent!(ElementDerived, Node, is_element, eventtarget) | |
delegate_parent!(DocumentDerived, Node, is_document, eventtarget) | |
impl NodeDerived for EventTarget { | |
fn is_node(&self) -> bool { | |
match self.type_id { | |
NodeTargetTypeId(_) => true, | |
WindowTargetTypeId => false | |
} | |
} | |
} | |
pub struct Node { | |
eventtarget: EventTarget, | |
first_child: Option<JSManaged<Node>> | |
} | |
impl Node { | |
pub fn new_inherited(type_id: NodeTypeId) -> Node { | |
Node { | |
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)), | |
first_child: None | |
} | |
} | |
pub fn type_id(&self) -> NodeTypeId { | |
match self.eventtarget.type_id { | |
NodeTargetTypeId(id) => id, | |
_ => unreachable!() | |
} | |
} | |
pub fn GetFirstChild(&self) -> Option<JSManaged<Node>> { | |
self.first_child | |
} | |
pub fn from<T: NodeBase>(derived: JSManaged<T>) -> JSManaged<Node> { | |
derived.transmute() | |
} | |
pub fn to<T: NodeDerived>(base: JSManaged<T>) -> JSManaged<Node> { | |
assert!(base.val().is_node()); | |
base.transmute() | |
} | |
} | |
impl Reflectable for Node { | |
fn reflector<'a> (&'a self) -> &'a Reflector { | |
self.eventtarget.reflector() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use eventtarget::{WindowTargetTypeId, EventTargetBase, EventTarget}; | |
use jsmanaged::JSManaged; | |
use super::{Reflectable, Reflector}; | |
use document::Document; | |
pub trait WindowDerived { fn is_window(&self) -> bool; } | |
impl WindowDerived for EventTarget { | |
fn is_window(&self) -> bool { | |
self.type_id == WindowTargetTypeId | |
} | |
} | |
impl EventTargetBase for Window {} | |
pub struct Window { | |
eventtarget: EventTarget, | |
document: JSManaged<Document> | |
} | |
impl Window { | |
pub fn new(document: JSManaged<Document>) -> JSManaged<Window> { | |
let win = ~Window { | |
eventtarget: EventTarget::new_inherited(WindowTargetTypeId), | |
document: document | |
}; | |
JSManaged::new(win) | |
} | |
} | |
impl Reflectable for Window { | |
fn reflector<'a> (&'a self) -> &'a Reflector { | |
self.eventtarget.reflector() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment