-
-
Save eddyb/69e4d2c14c3610f14ea3 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
| // <core> | |
| #[lang="vtable"] | |
| struct Vtable<T, Sized? Trait>(&'static (unsafe fn(*mut T), uint, uint)); | |
| extern "rust-intrinsic" { fn get_vtable<T, Sized? Trait>() -> Vtable<T, Trait>; } | |
| #[lang="has_vtable"] | |
| trait HasVtable<T, Sized? Trait> {} | |
| // </core> | |
| #[repr(fixed, inline_vtable)] | |
| trait Node: Any { | |
| type V: HasVtable<Node, Self> = Vtable<Node, Self>; | |
| vtable: V, | |
| parent: Rc<Node>, first_child: Rc<Node>; | |
| // TODO(eddyb) this can be made non-virtual using an associated | |
| // const bitset of traits that the V vtable contains as a prefix. | |
| fn as_element<'a>(&'a self) -> Option<&'a Element> { None } | |
| } | |
| impl Node { | |
| fn as_text_node<'a>(&'a self) -> Option<&'a TextNode> { | |
| self.downcast_ref::<TextNode>() | |
| } | |
| } | |
| struct TextNode { | |
| vtable: Vtable<Node, TextNode>, | |
| parent: Rc<Node>, first_child: Rc<Node>, | |
| ... | |
| } | |
| impl Node for TextNode {} | |
| #[repr(fixed, inline_vtable)] | |
| trait Element: Node where Self::V: HasVtable<Element, Self> { | |
| #[override_default] | |
| type V = Vtable<Element, Self>; | |
| attrs: HashMap<String, String>; | |
| fn set_attribute(&self, key: &str, value: &str) { | |
| self.before_set_attr(key, value); | |
| //...update attrs... | |
| self.after_set_attr(key, value); | |
| } | |
| fn before_set_attr(&self, key: &str, value: &str); | |
| fn after_set_attr(&self, key: &str, value: &str); | |
| #[override_default] | |
| fn as_element<'a>(&'a self) -> Option<&'a Element> { Some(self) } | |
| } | |
| struct HTMLImageElement { | |
| vtable: Vtable<Element, HTMLImageElement>, | |
| parent: Rc<Node>, first_child: Rc<Node>, | |
| attrs: HashMap<String, String>, | |
| ... | |
| } | |
| #[allow(override_default)] | |
| impl Element for HTMLImageElement { | |
| fn before_set_attr(&self, key: &str, value: &str) { | |
| if key == "src" { | |
| //..remove cached image with url `value`... | |
| } | |
| Element::default::before_set_attr(self, key, value); | |
| } | |
| } | |
| struct HTMLVideoElement { | |
| vtable: Vtable<Element, HTMLVideoElement>, | |
| parent: Rc<Node>, first_child: Rc<Node>, | |
| attrs: HashMap<String, String>, | |
| cross_origin: bool, | |
| ... | |
| } | |
| #[allow(override_default)] | |
| impl Element for HTMLVideoElement { | |
| fn after_set_attr(&self, key: &str, value: &str) { | |
| if key == "crossOrigin" { | |
| self.cross_origin = value == "true"; | |
| } | |
| Element::default::after_set_attr(self, key, value); | |
| } | |
| } | |
| fn process_any_element(element: &Element) { | |
| //... | |
| } | |
| let videoElement: Rc<HTMLVideoElement> = ...; | |
| process_any_element(&*videoElement); | |
| let node = &*videoElement.first_child; | |
| let element = node.as_element(); | |
| match node.as_element() { | |
| Some(element) => ..., | |
| None => { | |
| let text = node.as_text_node().unwrap(); | |
| ... | |
| } | |
| } |
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
| struct Node { | |
| shared_ptr<Node> parent; | |
| shared_ptr<Node> first_child; | |
| TextNode* as_text_node() { assert(/*sensible check*/); return (TextNode*)this; } | |
| virtual Element* as_element() { return NULL; } | |
| }; | |
| struct TextNode: public Node {}; | |
| struct Element: public Node { | |
| map<string, string> attrs; | |
| void set_attribute(const string& key, const string& value) { | |
| before_set_attr(key, value); | |
| //...update attrs... | |
| after_set_attr(key, value); | |
| } | |
| virtual void before_set_attr(const string& key, const string& value); | |
| virtual void after_set_attr(const string& key, const string& value); | |
| virtual Element* as_element() { return this; } | |
| }; | |
| struct HTMLImageElement: public Element { | |
| virtual void before_set_attr(const string& key, const string& value) { | |
| if(key == "src") { | |
| //..remove cached image with url |value|... | |
| } | |
| Element::before_set_attr(key, value); | |
| } | |
| } | |
| struct HTMLVideoElement: public Element { | |
| bool cross_origin; | |
| void after_set_attr(const string& key, const string& value) { | |
| if(key == "crossOrigin") { | |
| cross_origin = value == "true"; | |
| } | |
| Element::after_set_attr(key, value); | |
| } | |
| } | |
| void process_any_element(Element* element) { | |
| //... | |
| } | |
| shared_ptr<HTMLVideoElement> videoElement = ...; | |
| process_any_element(videoElement); | |
| shared_ptr<Node> node = videoElement->first_child; | |
| shared_ptr<Element> element = node->as_element(); | |
| if(!element) { | |
| shared_ptr<TextNode> text = node->as_text_node(); | |
| } |
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
| #[repr(fixed)] | |
| trait Node: Any { | |
| parent: Rc<Node>, first_child: Rc<Node>; | |
| fn as_element<'a>(&'a self) -> Option<&'a Element> { None } | |
| } | |
| impl Node { | |
| fn as_text_node<'a>(&'a self) -> Option<&'a TextNode> { | |
| self.downcast_ref::<TextNode>() | |
| } | |
| } | |
| struct TextNode { parent: Rc<Node>, first_child: Rc<Node>, ... } | |
| impl Node for TextNode {} | |
| #[repr(fixed)] | |
| trait Element: Node { | |
| attrs: HashMap<String, String>; | |
| fn set_attribute(&self, key: &str, value: &str) { | |
| self.before_set_attr(key, value); | |
| //...update attrs... | |
| self.after_set_attr(key, value); | |
| } | |
| fn before_set_attr(&self, key: &str, value: &str); | |
| fn after_set_attr(&self, key: &str, value: &str); | |
| #[override_default] | |
| fn as_element<'a>(&'a self) -> Option<&'a Element> { Some(self) } | |
| } | |
| struct HTMLImageElement { | |
| parent: Rc<Node>, first_child: Rc<Node>, | |
| attrs: HashMap<String, String>, | |
| ... | |
| } | |
| #[allow(override_default)] | |
| impl Element for HTMLImageElement { | |
| fn before_set_attr(&self, key: &str, value: &str) { | |
| if key == "src" { | |
| //..remove cached image with url `value`... | |
| } | |
| Element::default::before_set_attr(self, key, value); | |
| } | |
| } | |
| struct HTMLVideoElement { | |
| parent: Rc<Node>, first_child: Rc<Node>, | |
| attrs: HashMap<String, String>, | |
| cross_origin: bool, | |
| ... | |
| } | |
| #[allow(override_default)] | |
| impl Element for HTMLVideoElement { | |
| fn after_set_attr(&self, key: &str, value: &str) { | |
| if key == "crossOrigin" { | |
| self.cross_origin = value == "true"; | |
| } | |
| Element::default::after_set_attr(self, key, value); | |
| } | |
| } | |
| fn process_any_element(element: &Element) { | |
| //... | |
| } | |
| let videoElement: Rc<HTMLVideoElement> = ...; | |
| process_any_element(&*videoElement); | |
| let node = &*videoElement.first_child; | |
| let element = node.as_element(); | |
| match node.as_element() { | |
| Some(element) => ..., | |
| None => { | |
| let text = node.as_text_node().unwrap(); | |
| ... | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment