auto merge of #1099 : Ms2ger/servo/abstract-borrowed-pointers, r=jdm

This commit is contained in:
bors-servo 2013-10-21 09:37:03 -07:00
commit 4d8f7fd056
9 changed files with 158 additions and 218 deletions

View file

@ -101,15 +101,11 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> *JSObject
impl Reflectable for AbstractNode<ScriptView> { impl Reflectable for AbstractNode<ScriptView> {
fn reflector<'a>(&'a self) -> &'a Reflector { fn reflector<'a>(&'a self) -> &'a Reflector {
do self.with_base |base| { self.node().reflector()
unsafe { cast::transmute(base.reflector()) }
}
} }
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
do self.with_mut_base |base| { self.mut_node().mut_reflector()
unsafe { cast::transmute(base.reflector()) }
}
} }
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject { fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
@ -117,9 +113,7 @@ impl Reflectable for AbstractNode<ScriptView> {
} }
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> { fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
do self.with_mut_base |base| { self.node().GetParentObject(cx)
base.GetParentObject(cx)
}
} }
} }

View file

@ -41,7 +41,7 @@ pub trait ReflectableDocument {
#[deriving(Eq)] #[deriving(Eq)]
pub struct AbstractDocument { pub struct AbstractDocument {
document: *Document document: *mut Box<Document>
} }
impl AbstractDocument { impl AbstractDocument {
@ -52,6 +52,18 @@ impl AbstractDocument {
} }
} }
pub fn document<'a>(&'a self) -> &'a Document {
unsafe {
&(*self.document).data
}
}
pub fn mut_document<'a>(&'a self) -> &'a mut Document {
unsafe {
&mut (*self.document).data
}
}
unsafe fn transmute<T, R>(&self, f: &fn(&T) -> R) -> R { unsafe fn transmute<T, R>(&self, f: &fn(&T) -> R) -> R {
let box: *Box<T> = cast::transmute(self.document); let box: *Box<T> = cast::transmute(self.document);
f(&(*box).data) f(&(*box).data)
@ -62,20 +74,8 @@ impl AbstractDocument {
f(&mut (*box).data) f(&mut (*box).data)
} }
pub fn with_base<R>(&self, callback: &fn(&Document) -> R) -> R {
unsafe {
self.transmute(callback)
}
}
pub fn with_mut_base<R>(&self, callback: &fn(&mut Document) -> R) -> R {
unsafe {
self.transmute_mut(callback)
}
}
pub fn with_html<R>(&self, callback: &fn(&HTMLDocument) -> R) -> R { pub fn with_html<R>(&self, callback: &fn(&HTMLDocument) -> R) -> R {
match self.with_base(|doc| doc.doctype) { match self.document().doctype {
HTML => unsafe { self.transmute(callback) }, HTML => unsafe { self.transmute(callback) },
_ => fail!("attempt to downcast a non-HTMLDocument to HTMLDocument") _ => fail!("attempt to downcast a non-HTMLDocument to HTMLDocument")
} }
@ -83,23 +83,20 @@ impl AbstractDocument {
pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractDocument { pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractDocument {
AbstractDocument { AbstractDocument {
document: ptr as *Document document: ptr as *mut Box<Document>
} }
} }
pub fn set_root(&self, root: AbstractNode<ScriptView>) { pub fn set_root(&self, root: AbstractNode<ScriptView>) {
assert!(root.traverse_preorder().all(|node| { assert!(do root.traverse_preorder().all |node| {
do node.with_base |node| { node.node().owner_doc() == *self
node.owner_doc() == *self });
}
})); let document = self.mut_document();
self.with_mut_base(|document| {
document.root = Some(root); document.root = Some(root);
// Register elements having "id" attribute to the owner doc. // Register elements having "id" attribute to the owner doc.
document.register_nodes_with_id(&root); document.register_nodes_with_id(&root);
document.content_changed(); document.content_changed();
});
} }
} }
@ -154,19 +151,15 @@ impl ReflectableDocument for Document {
impl Reflectable for AbstractDocument { impl Reflectable for AbstractDocument {
fn reflector<'a>(&'a self) -> &'a Reflector { fn reflector<'a>(&'a self) -> &'a Reflector {
do self.with_mut_base |doc| { self.document().reflector()
unsafe { cast::transmute(doc.reflector()) }
}
} }
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
do self.with_mut_base |doc| { self.mut_document().mut_reflector()
unsafe { cast::transmute(doc.mut_reflector()) }
}
} }
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
match self.with_base(|doc| doc.doctype) { match self.document().doctype {
HTML => { HTML => {
let doc: @mut HTMLDocument = unsafe { cast::transmute(self.document) }; let doc: @mut HTMLDocument = unsafe { cast::transmute(self.document) };
doc.wrap_object_shared(cx, scope) doc.wrap_object_shared(cx, scope)
@ -178,9 +171,7 @@ impl Reflectable for AbstractDocument {
} }
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> { fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
do self.with_mut_base |doc| { self.document().GetParentObject(cx)
doc.GetParentObject(cx)
}
} }
} }
@ -561,14 +552,12 @@ impl Traceable for Document {
do "root".to_c_str().with_ref |name| { do "root".to_c_str().with_ref |name| {
(*tracer).debugPrintArg = name as *libc::c_void; (*tracer).debugPrintArg = name as *libc::c_void;
debug!("tracing root node"); debug!("tracing root node");
do root.with_base |node| {
JS_CallTracer(tracer as *JSTracer, JS_CallTracer(tracer as *JSTracer,
node.reflector_.object, root.reflector().get_jsobject(),
JSTRACE_OBJECT as u32); JSTRACE_OBJECT as u32);
} }
} }
} }
} }
} }
}
} }

View file

@ -199,9 +199,8 @@ impl<'self> Element {
} }
if abstract_self.is_in_doc() { if abstract_self.is_in_doc() {
do self.node.owner_doc().with_base |owner| { let document = self.node.owner_doc();
owner.content_changed(); document.document().content_changed();
}
} }
} }
} }
@ -286,8 +285,7 @@ impl Element {
} }
pub fn GetClientRects(&self, abstract_self: AbstractNode<ScriptView>) -> @mut ClientRectList { pub fn GetClientRects(&self, abstract_self: AbstractNode<ScriptView>) -> @mut ClientRectList {
let document = self.node.owner_doc(); let win = self.node.owner_doc().document().window;
let win = document.with_base(|doc| doc.window);
let node = abstract_self; let node = abstract_self;
assert!(node.is_element()); assert!(node.is_element());
let (port, chan) = comm::stream(); let (port, chan) = comm::stream();
@ -313,8 +311,7 @@ impl Element {
} }
pub fn GetBoundingClientRect(&self, abstract_self: AbstractNode<ScriptView>) -> @mut ClientRect { pub fn GetBoundingClientRect(&self, abstract_self: AbstractNode<ScriptView>) -> @mut ClientRect {
let document = self.node.owner_doc(); let win = self.node.owner_doc().document().window;
let win = document.with_base(|doc| doc.window);
let node = abstract_self; let node = abstract_self;
assert!(node.is_element()); assert!(node.is_element());
let (port, chan) = comm::stream(); let (port, chan) = comm::stream();

View file

@ -43,14 +43,12 @@ impl HTMLImageElement {
pub fn AfterSetAttr(&mut self, name: &DOMString, _value: &DOMString) { pub fn AfterSetAttr(&mut self, name: &DOMString, _value: &DOMString) {
let name = null_str_as_empty(name); let name = null_str_as_empty(name);
if "src" == name { if "src" == name {
let doc = self.htmlelement.element.node.owner_doc(); let document = self.htmlelement.element.node.owner_doc();
do doc.with_base |doc| { let window = document.document().window;
let window = doc.window;
let url = window.page.url.map(|&(ref url, _)| url.clone()); let url = window.page.url.map(|&(ref url, _)| url.clone());
self.update_image(window.image_cache_task.clone(), url); self.update_image(window.image_cache_task.clone(), url);
} }
} }
}
pub fn Alt(&self) -> DOMString { pub fn Alt(&self) -> DOMString {
None None
@ -100,7 +98,7 @@ impl HTMLImageElement {
pub fn Width(&self, abstract_self: AbstractNode<ScriptView>) -> u32 { pub fn Width(&self, abstract_self: AbstractNode<ScriptView>) -> u32 {
let node = &self.htmlelement.element.node; let node = &self.htmlelement.element.node;
let page = node.owner_doc().with_base(|doc| doc.window).page; let page = node.owner_doc().document().window.page;
let (port, chan) = stream(); let (port, chan) = stream();
match page.query_layout(ContentBoxQuery(abstract_self, chan), port) { match page.query_layout(ContentBoxQuery(abstract_self, chan), port) {
ContentBoxResponse(rect) => { ContentBoxResponse(rect) => {
@ -121,7 +119,7 @@ impl HTMLImageElement {
pub fn Height(&self, abstract_self: AbstractNode<ScriptView>) -> u32 { pub fn Height(&self, abstract_self: AbstractNode<ScriptView>) -> u32 {
let node = &self.htmlelement.element.node; let node = &self.htmlelement.element.node;
let page = node.owner_doc().with_base(|doc| doc.window).page; let page = node.owner_doc().document().window.page;
let (port, chan) = stream(); let (port, chan) = stream();
match page.query_layout(ContentBoxQuery(abstract_self, chan), port) { match page.query_layout(ContentBoxQuery(abstract_self, chan), port) {
ContentBoxResponse(rect) => { ContentBoxResponse(rect) => {

View file

@ -52,7 +52,7 @@ pub struct LayoutView;
/// FIXME: This should be replaced with a trait once they can inherit from structs. /// FIXME: This should be replaced with a trait once they can inherit from structs.
#[deriving(Eq)] #[deriving(Eq)]
pub struct AbstractNode<View> { pub struct AbstractNode<View> {
priv obj: *mut Node<View>, priv obj: *mut Box<Node<View>>,
} }
pub struct AbstractNodeChildrenIterator<View> { pub struct AbstractNodeChildrenIterator<View> {
@ -115,6 +115,18 @@ impl<View> Clone for AbstractNode<View> {
} }
impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> { impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
fn node<'a>(&'a self) -> &'a Node<View> {
unsafe {
&(*self.obj).data
}
}
fn mut_node<'a>(&'a self) -> &'a mut Node<View> {
unsafe {
&mut (*self.obj).data
}
}
fn parent_node(node: &Node<View>) -> Option<AbstractNode<View>> { fn parent_node(node: &Node<View>) -> Option<AbstractNode<View>> {
node.parent_node node.parent_node
} }
@ -147,15 +159,6 @@ impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
node.next_sibling = new_next_sibling node.next_sibling = new_next_sibling
} }
// FIXME: The duplication between `with_base` and `with_mut_base` is ugly.
fn with_base<R>(&self, callback: &fn(&Node<View>) -> R) -> R {
self.transmute(callback)
}
fn with_mut_base<R>(&self, callback: &fn(&mut Node<View>) -> R) -> R {
self.transmute_mut(callback)
}
fn is_element(&self) -> bool { fn is_element(&self) -> bool {
match self.type_id() { match self.type_id() {
ElementNodeTypeId(*) => true, ElementNodeTypeId(*) => true,
@ -194,7 +197,7 @@ impl<'self, View> AbstractNode<View> {
/// chain for nodes. /// chain for nodes.
pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractNode<View> { pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractNode<View> {
AbstractNode { AbstractNode {
obj: ptr as *mut Node<View> obj: ptr as *mut Box<Node<View>>
} }
} }
@ -202,32 +205,32 @@ impl<'self, View> AbstractNode<View> {
/// Returns the type ID of this node. Fails if this node is borrowed mutably. /// Returns the type ID of this node. Fails if this node is borrowed mutably.
pub fn type_id(self) -> NodeTypeId { pub fn type_id(self) -> NodeTypeId {
self.with_base(|b| b.type_id) self.node().type_id
} }
/// Returns the parent node of this node. Fails if this node is borrowed mutably. /// Returns the parent node of this node. Fails if this node is borrowed mutably.
pub fn parent_node(self) -> Option<AbstractNode<View>> { pub fn parent_node(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.parent_node) self.node().parent_node
} }
/// Returns the first child of this node. Fails if this node is borrowed mutably. /// Returns the first child of this node. Fails if this node is borrowed mutably.
pub fn first_child(self) -> Option<AbstractNode<View>> { pub fn first_child(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.first_child) self.node().first_child
} }
/// Returns the last child of this node. Fails if this node is borrowed mutably. /// Returns the last child of this node. Fails if this node is borrowed mutably.
pub fn last_child(self) -> Option<AbstractNode<View>> { pub fn last_child(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.last_child) self.node().last_child
} }
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably. /// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
pub fn prev_sibling(self) -> Option<AbstractNode<View>> { pub fn prev_sibling(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.prev_sibling) self.node().prev_sibling
} }
/// Returns the next sibling of this node. Fails if this node is borrowed mutably. /// Returns the next sibling of this node. Fails if this node is borrowed mutably.
pub fn next_sibling(self) -> Option<AbstractNode<View>> { pub fn next_sibling(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.next_sibling) self.node().next_sibling
} }
/// Is this node a root? /// Is this node a root?
@ -381,11 +384,11 @@ impl<'self, View> AbstractNode<View> {
self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId) self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId)
} }
pub unsafe fn raw_object(self) -> *mut Node<View> { pub unsafe fn raw_object(self) -> *mut Box<Node<View>> {
self.obj self.obj
} }
pub fn from_raw(raw: *mut Node<View>) -> AbstractNode<View> { pub fn from_raw(raw: *mut Box<Node<View>>) -> AbstractNode<View> {
AbstractNode { AbstractNode {
obj: raw obj: raw
} }
@ -425,9 +428,8 @@ impl<'self, View> AbstractNode<View> {
// Issue #1030: should not walk the tree // Issue #1030: should not walk the tree
pub fn is_in_doc(&self) -> bool { pub fn is_in_doc(&self) -> bool {
do self.with_base |node| { let document = self.node().owner_doc();
do node.owner_doc().with_base |document| { match document.document().GetDocumentElement() {
match document.GetDocumentElement() {
None => false, None => false,
Some(root) => { Some(root) => {
let mut node = *self; let mut node = *self;
@ -448,8 +450,6 @@ impl<'self, View> AbstractNode<View> {
} }
} }
} }
}
}
} }
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> { impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
@ -486,34 +486,24 @@ impl Node<ScriptView> {
let mut cur_node = self.first_child; let mut cur_node = self.first_child;
while cur_node.is_some() { while cur_node.is_some() {
for node in cur_node.unwrap().traverse_preorder() { for node in cur_node.unwrap().traverse_preorder() {
do node.with_mut_base |node_base| { node.mut_node().set_owner_doc(doc);
node_base.set_owner_doc(doc);
}
}; };
cur_node = cur_node.unwrap().next_sibling(); cur_node = cur_node.unwrap().next_sibling();
} }
// Unregister elements having "id' from the old doc. // Unregister elements having "id' from the old doc.
do old_doc.with_mut_base |old_doc| { old_doc.mut_document().unregister_nodes_with_id(&abstract_self);
old_doc.unregister_nodes_with_id(&abstract_self);
}
// Register elements having "id" attribute to the owner doc. // Register elements having "id" attribute to the owner doc.
do doc.with_mut_base |doc| { doc.mut_document().register_nodes_with_id(&abstract_self);
doc.register_nodes_with_id(&abstract_self);
}
// Signal the old document that it needs to update its display // Signal the old document that it needs to update its display
if old_doc != doc { if old_doc != doc {
do old_doc.with_base |old_doc| { old_doc.document().content_changed();
old_doc.content_changed();
}
} }
// Signal the new document that it needs to update its display // Signal the new document that it needs to update its display
do doc.with_base |doc| { doc.document().content_changed();
doc.content_changed();
}
} }
pub fn new(type_id: NodeTypeId, doc: AbstractDocument) -> Node<ScriptView> { pub fn new(type_id: NodeTypeId, doc: AbstractDocument) -> Node<ScriptView> {
@ -683,7 +673,7 @@ impl Node<ScriptView> {
} }
pub fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) { pub fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let win = self.owner_doc().with_base(|doc| doc.window); let win = self.owner_doc().document().window;
(win.reflector().get_jsobject(), win.get_cx()) (win.reflector().get_jsobject(), win.get_cx())
} }
@ -715,10 +705,8 @@ impl Node<ScriptView> {
let node = if is_empty { let node = if is_empty {
None None
} else { } else {
let text_node = do self.owner_doc().with_base |document| { let document = self.owner_doc();
document.CreateTextNode(self.owner_doc(), value) Some(document.document().CreateTextNode(document, value))
};
Some(text_node)
}; };
self.replace_all(abstract_self, node); self.replace_all(abstract_self, node);
} }
@ -729,9 +717,8 @@ impl Node<ScriptView> {
characterdata.data = null_str_as_empty(value); characterdata.data = null_str_as_empty(value);
// Notify the document that the content of this node is different // Notify the document that the content of this node is different
do self.owner_doc().with_base |doc| { let document = self.owner_doc();
doc.content_changed(); document.document().content_changed();
}
} }
} }
DoctypeNodeTypeId => {} DoctypeNodeTypeId => {}
@ -744,9 +731,8 @@ impl Node<ScriptView> {
} }
fn wait_until_safe_to_modify_dom(&self) { fn wait_until_safe_to_modify_dom(&self) {
do self.owner_doc().with_base |doc| { let document = self.owner_doc();
doc.wait_until_safe_to_modify_dom(); document.document().wait_until_safe_to_modify_dom();
}
} }
pub fn AppendChild(&mut self, pub fn AppendChild(&mut self,
@ -784,9 +770,7 @@ impl Node<ScriptView> {
// If the node already exists it is removed from current parent node. // If the node already exists it is removed from current parent node.
node.parent_node().map(|parent| parent.remove_child(node)); node.parent_node().map(|parent| parent.remove_child(node));
abstract_self.add_child(node); abstract_self.add_child(node);
do node.with_mut_base |node| { node.mut_node().add_to_doc(node, self.owner_doc());
node.add_to_doc(abstract_self, self.owner_doc());
}
Ok(node) Ok(node)
} }
@ -813,15 +797,12 @@ impl Node<ScriptView> {
// Unregister elements having "id' from the owner doc. // Unregister elements having "id' from the owner doc.
// This need be called before target nodes are removed from tree. // This need be called before target nodes are removed from tree.
do self.owner_doc.with_mut_base |doc| { self.owner_doc.mut_document().unregister_nodes_with_id(&abstract_self);
doc.unregister_nodes_with_id(&abstract_self);
}
abstract_self.remove_child(node); abstract_self.remove_child(node);
// Signal the document that it needs to update its display. // Signal the document that it needs to update its display.
do self.owner_doc().with_base |document| { let document = self.owner_doc();
document.content_changed(); document.document().content_changed();
}
Ok(node) Ok(node)
} }
@ -949,14 +930,10 @@ impl AbstractNode<LayoutView> {
// Node. Also this makes it easier to switch to RWArc if we decide that is // Node. Also this makes it easier to switch to RWArc if we decide that is
// necessary. // necessary.
pub fn read_layout_data<R>(self, blk: &fn(data: &LayoutData) -> R) -> R { pub fn read_layout_data<R>(self, blk: &fn(data: &LayoutData) -> R) -> R {
do self.with_base |b| { blk(&self.node().layout_data)
blk(&b.layout_data)
}
} }
pub fn write_layout_data<R>(self, blk: &fn(data: &mut LayoutData) -> R) -> R { pub fn write_layout_data<R>(self, blk: &fn(data: &mut LayoutData) -> R) -> R {
do self.with_mut_base |b| { blk(&mut self.mut_node().layout_data)
blk(&mut b.layout_data)
}
} }
} }

View file

@ -253,18 +253,16 @@ impl Traceable for Window {
unsafe { unsafe {
match self.page.frame { match self.page.frame {
Some(frame) => { Some(frame) => {
do frame.document.with_base |doc| {
(*tracer).debugPrinter = ptr::null(); (*tracer).debugPrinter = ptr::null();
(*tracer).debugPrintIndex = -1; (*tracer).debugPrintIndex = -1;
do "document".to_c_str().with_ref |name| { do "document".to_c_str().with_ref |name| {
(*tracer).debugPrintArg = name as *libc::c_void; (*tracer).debugPrintArg = name as *libc::c_void;
debug!("tracing document"); debug!("tracing document");
JS_CallTracer(tracer as *JSTracer, JS_CallTracer(tracer as *JSTracer,
doc.reflector_.object, frame.document.reflector().get_jsobject(),
JSTRACE_OBJECT as u32); JSTRACE_OBJECT as u32);
} }
} }
}
None => () None => ()
} }
} }

View file

@ -214,9 +214,8 @@ impl<'self> Iterator<@mut Page> for PageTreeIterator<'self> {
impl Page { impl Page {
/// Adds the given damage. /// Adds the given damage.
fn damage(&mut self, level: DocumentDamageLevel) { fn damage(&mut self, level: DocumentDamageLevel) {
let root = do self.frame.get_ref().document.with_base |doc| { let root = self.frame.get_ref().document.document().
doc.GetDocumentElement() GetDocumentElement();
};
match root { match root {
None => {}, None => {},
Some(root) => { Some(root) => {
@ -277,9 +276,7 @@ impl Page {
let root = match self.frame { let root = match self.frame {
None => fail!(~"Tried to relayout with no root frame!"), None => fail!(~"Tried to relayout with no root frame!"),
Some(ref frame) => { Some(ref frame) => {
do frame.document.with_base |doc| { frame.document.document().GetDocumentElement()
doc.GetDocumentElement()
}
} }
}; };
match root { match root {
@ -804,9 +801,8 @@ impl ScriptTask {
ClickEvent(_button, point) => { ClickEvent(_button, point) => {
debug!("ClickEvent: clicked at %?", point); debug!("ClickEvent: clicked at %?", point);
let root = do page.frame.expect("root frame is None").document.with_base |doc| { let document = page.frame.expect("root frame is None").document;
doc.GetDocumentElement() let root = document.document().GetDocumentElement();
};
if root.is_none() { if root.is_none() {
return; return;
} }

View file

@ -171,8 +171,10 @@ fn matches_compound_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
}; };
let mut node = element.clone(); let mut node = element.clone();
loop { loop {
let next_node = do node.with_base |node| { let next_node = if siblings {
if siblings { node.prev_sibling() } else { node.parent_node() } node.node().prev_sibling()
} else {
node.node().parent_node()
}; };
match next_node { match next_node {
None => return false, None => return false,

View file

@ -37,7 +37,7 @@ impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for ChildIterator<Ref> {
// FIXME: Do we need two clones here? // FIXME: Do we need two clones here?
let x = self.current.get_ref().clone(); let x = self.current.get_ref().clone();
self.current = x.with_base(|n| TreeNodeRef::<Node>::next_sibling(n)); self.current = TreeNodeRef::<Node>::next_sibling(x.node());
Some(x.clone()) Some(x.clone())
} }
} }
@ -54,7 +54,7 @@ impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for AncestorIterator<Ref> {
// FIXME: Do we need two clones here? // FIXME: Do we need two clones here?
let x = self.current.get_ref().clone(); let x = self.current.get_ref().clone();
self.current = x.with_base(|n| TreeNodeRef::<Node>::parent_node(n)); self.current = TreeNodeRef::<Node>::parent_node(x.node());
Some(x.clone()) Some(x.clone())
} }
} }
@ -98,11 +98,9 @@ pub trait TreeNodeRef<Node>: Clone {
// Fundamental operations on refs. // Fundamental operations on refs.
/// Borrows this node as immutable. /// Borrows this node as immutable.
fn with_base<R>(&self, callback: &fn(&Node) -> R) -> R; fn node<'a>(&'a self) -> &'a Node;
/// Borrows this node as mutable. /// Borrows this node as mutable.
fn with_mut_base<R>(&self, callback: &fn(&mut Node) -> R) -> R; fn mut_node<'a>(&'a self) -> &'a mut Node;
// Fundamental operations on nodes. // Fundamental operations on nodes.
@ -141,17 +139,15 @@ pub trait TreeNodeRef<Node>: Clone {
/// Returns true if this node is disconnected from the tree or has no children. /// Returns true if this node is disconnected from the tree or has no children.
fn is_leaf(&self) -> bool { fn is_leaf(&self) -> bool {
do self.with_base |this_node| { (get!(self.node(), first_child)).is_none()
(get!(this_node, first_child)).is_none()
}
} }
/// Adds a new child to the end of this node's list of children. /// Adds a new child to the end of this node's list of children.
/// ///
/// Fails unless `new_child` is disconnected from the tree. /// Fails unless `new_child` is disconnected from the tree.
fn add_child(&self, new_child: Self) { fn add_child(&self, new_child: Self) {
do self.with_mut_base |this_node| { let this_node = self.mut_node();
do new_child.with_mut_base |new_child_node| { let new_child_node = new_child.mut_node();
assert!((get!(new_child_node, parent_node)).is_none()); assert!((get!(new_child_node, parent_node)).is_none());
assert!((get!(new_child_node, prev_sibling)).is_none()); assert!((get!(new_child_node, prev_sibling)).is_none());
assert!((get!(new_child_node, next_sibling)).is_none()); assert!((get!(new_child_node, next_sibling)).is_none());
@ -159,64 +155,57 @@ pub trait TreeNodeRef<Node>: Clone {
match get!(this_node, last_child) { match get!(this_node, last_child) {
None => set!(this_node, set_first_child, Some(new_child.clone())), None => set!(this_node, set_first_child, Some(new_child.clone())),
Some(last_child) => { Some(last_child) => {
do last_child.with_mut_base |last_child_node| { let last_child_node = last_child.mut_node();
assert!((get!(last_child_node, next_sibling)).is_none()); assert!((get!(last_child_node, next_sibling)).is_none());
set!(last_child_node, set_next_sibling, Some(new_child.clone())); set!(last_child_node, set_next_sibling, Some(new_child.clone()));
set!(new_child_node, set_prev_sibling, Some(last_child.clone())); set!(new_child_node, set_prev_sibling, Some(last_child.clone()));
} }
} }
}
set!(this_node, set_last_child, Some(new_child.clone())); set!(this_node, set_last_child, Some(new_child.clone()));
set!(new_child_node, set_parent_node, Some((*self).clone())); set!(new_child_node, set_parent_node, Some((*self).clone()));
} }
}
}
/// Removes the given child from this node's list of children. /// Removes the given child from this node's list of children.
/// ///
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.) /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
fn remove_child(&self, child: Self) { fn remove_child(&self, child: Self) {
do self.with_mut_base |this_node| { let this_node = self.mut_node();
do child.with_mut_base |child_node| { let child_node = child.mut_node();
assert!((get!(child_node, parent_node)).is_some()); assert!((get!(child_node, parent_node)).is_some());
match get!(child_node, prev_sibling) { match get!(child_node, prev_sibling) {
None => set!(this_node, set_first_child, get!(child_node, next_sibling)), None => set!(this_node, set_first_child, get!(child_node, next_sibling)),
Some(prev_sibling) => { Some(prev_sibling) => {
do prev_sibling.with_mut_base |prev_sibling_node| { let prev_sibling_node = prev_sibling.mut_node();
set!(prev_sibling_node, set_next_sibling, get!(child_node, next_sibling)); set!(prev_sibling_node, set_next_sibling, get!(child_node, next_sibling));
} }
} }
}
match get!(child_node, next_sibling) { match get!(child_node, next_sibling) {
None => set!(this_node, set_last_child, get!(child_node, prev_sibling)), None => set!(this_node, set_last_child, get!(child_node, prev_sibling)),
Some(next_sibling) => { Some(next_sibling) => {
do next_sibling.with_mut_base |next_sibling_node| { let next_sibling_node = next_sibling.mut_node();
set!(next_sibling_node, set_prev_sibling, get!(child_node, prev_sibling)); set!(next_sibling_node, set_prev_sibling, get!(child_node, prev_sibling));
} }
} }
}
set!(child_node, set_prev_sibling, None); set!(child_node, set_prev_sibling, None);
set!(child_node, set_next_sibling, None); set!(child_node, set_next_sibling, None);
set!(child_node, set_parent_node, None); set!(child_node, set_parent_node, None);
} }
}
}
/// Iterates over all children of this node. /// Iterates over all children of this node.
fn children(&self) -> ChildIterator<Self> { fn children(&self) -> ChildIterator<Self> {
ChildIterator { ChildIterator {
current: self.with_base(|n| get!(n, first_child)), current: get!(self.node(), first_child),
} }
} }
/// Iterates over all ancestors of this node. /// Iterates over all ancestors of this node.
fn ancestors(&self) -> AncestorIterator<Self> { fn ancestors(&self) -> AncestorIterator<Self> {
AncestorIterator { AncestorIterator {
current: self.with_base(|n| get!(n, parent_node)), current: get!(self.node(), parent_node),
} }
} }