1111extern crate html5ever;
1212
1313use std:: borrow:: Cow ;
14+ use std:: cell:: { Cell , RefCell } ;
1415use std:: collections:: HashMap ;
1516use std:: io;
1617
@@ -20,14 +21,14 @@ use html5ever::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
2021use html5ever:: { Attribute , ExpandedName , QualName } ;
2122
2223struct Sink {
23- next_id : usize ,
24- names : HashMap < usize , QualName > ,
24+ next_id : Cell < usize > ,
25+ names : RefCell < HashMap < usize , & ' static QualName > > ,
2526}
2627
2728impl Sink {
28- fn get_id ( & mut self ) -> usize {
29- let id = self . next_id ;
30- self . next_id += 2 ;
29+ fn get_id ( & self ) -> usize {
30+ let id = self . next_id . get ( ) ;
31+ self . next_id . set ( id + 2 ) ;
3132 id
3233 }
3334}
@@ -43,12 +44,13 @@ impl TreeSink for Sink {
4344 self
4445 }
4546
46- fn get_document ( & mut self ) -> usize {
47+ fn get_document ( & self ) -> usize {
4748 0
4849 }
4950
50- fn get_template_contents ( & mut self , target : & usize ) -> usize {
51- if let Some ( expanded_name ! ( html "template" ) ) = self . names . get ( target) . map ( |n| n. expanded ( ) )
51+ fn get_template_contents ( & self , target : & usize ) -> usize {
52+ if let Some ( expanded_name ! ( html "template" ) ) =
53+ self . names . borrow ( ) . get ( target) . map ( |n| n. expanded ( ) )
5254 {
5355 target + 1
5456 } else {
@@ -61,53 +63,63 @@ impl TreeSink for Sink {
6163 }
6264
6365 fn elem_name ( & self , target : & usize ) -> ExpandedName {
64- self . names . get ( target) . expect ( "not an element" ) . expanded ( )
66+ self . names
67+ . borrow ( )
68+ . get ( target)
69+ . expect ( "not an element" )
70+ . expanded ( )
6571 }
6672
67- fn create_element ( & mut self , name : QualName , _: Vec < Attribute > , _: ElementFlags ) -> usize {
73+ fn create_element ( & self , name : QualName , _: Vec < Attribute > , _: ElementFlags ) -> usize {
6874 let id = self . get_id ( ) ;
69- self . names . insert ( id, name) ;
75+ // N.B. We intentionally leak memory here to minimize the implementation complexity
76+ // of this example code. A real implementation would either want to use a real
77+ // real DOM tree implentation, or else use an arena as the backing store for
78+ // memory used by the parser.
79+ self . names
80+ . borrow_mut ( )
81+ . insert ( id, Box :: leak ( Box :: new ( name) ) ) ;
7082 id
7183 }
7284
73- fn create_comment ( & mut self , _text : StrTendril ) -> usize {
85+ fn create_comment ( & self , _text : StrTendril ) -> usize {
7486 self . get_id ( )
7587 }
7688
7789 #[ allow( unused_variables) ]
78- fn create_pi ( & mut self , target : StrTendril , value : StrTendril ) -> usize {
90+ fn create_pi ( & self , target : StrTendril , value : StrTendril ) -> usize {
7991 unimplemented ! ( )
8092 }
8193
82- fn append_before_sibling ( & mut self , _sibling : & usize , _new_node : NodeOrText < usize > ) { }
94+ fn append_before_sibling ( & self , _sibling : & usize , _new_node : NodeOrText < usize > ) { }
8395
8496 fn append_based_on_parent_node (
85- & mut self ,
97+ & self ,
8698 _element : & usize ,
8799 _prev_element : & usize ,
88100 _new_node : NodeOrText < usize > ,
89101 ) {
90102 }
91103
92- fn parse_error ( & mut self , _msg : Cow < ' static , str > ) { }
93- fn set_quirks_mode ( & mut self , _mode : QuirksMode ) { }
94- fn append ( & mut self , _parent : & usize , _child : NodeOrText < usize > ) { }
104+ fn parse_error ( & self , _msg : Cow < ' static , str > ) { }
105+ fn set_quirks_mode ( & self , _mode : QuirksMode ) { }
106+ fn append ( & self , _parent : & usize , _child : NodeOrText < usize > ) { }
95107
96- fn append_doctype_to_document ( & mut self , _: StrTendril , _: StrTendril , _: StrTendril ) { }
97- fn add_attrs_if_missing ( & mut self , target : & usize , _attrs : Vec < Attribute > ) {
98- assert ! ( self . names. contains_key( target) , "not an element" ) ;
108+ fn append_doctype_to_document ( & self , _: StrTendril , _: StrTendril , _: StrTendril ) { }
109+ fn add_attrs_if_missing ( & self , target : & usize , _attrs : Vec < Attribute > ) {
110+ assert ! ( self . names. borrow ( ) . contains_key( target) , "not an element" ) ;
99111 }
100- fn remove_from_parent ( & mut self , _target : & usize ) { }
101- fn reparent_children ( & mut self , _node : & usize , _new_parent : & usize ) { }
102- fn mark_script_already_started ( & mut self , _node : & usize ) { }
112+ fn remove_from_parent ( & self , _target : & usize ) { }
113+ fn reparent_children ( & self , _node : & usize , _new_parent : & usize ) { }
114+ fn mark_script_already_started ( & self , _node : & usize ) { }
103115}
104116
105117/// In this example we implement the TreeSink trait which takes each parsed elements and insert
106118/// it to a hashmap, while each element is given a numeric id.
107119fn main ( ) {
108120 let sink = Sink {
109- next_id : 1 ,
110- names : HashMap :: new ( ) ,
121+ next_id : Cell :: new ( 1 ) ,
122+ names : RefCell :: new ( HashMap :: new ( ) ) ,
111123 } ;
112124
113125 // Read HTML from the standard input and parse it
0 commit comments