11
11
extern crate html5ever;
12
12
13
13
use std:: borrow:: Cow ;
14
+ use std:: cell:: { Cell , RefCell } ;
14
15
use std:: collections:: HashMap ;
15
16
use std:: io;
16
17
@@ -20,14 +21,14 @@ use html5ever::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
20
21
use html5ever:: { Attribute , ExpandedName , QualName } ;
21
22
22
23
struct Sink {
23
- next_id : usize ,
24
- names : HashMap < usize , QualName > ,
24
+ next_id : Cell < usize > ,
25
+ names : RefCell < HashMap < usize , & ' static QualName > > ,
25
26
}
26
27
27
28
impl 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 ) ;
31
32
id
32
33
}
33
34
}
@@ -43,12 +44,13 @@ impl TreeSink for Sink {
43
44
self
44
45
}
45
46
46
- fn get_document ( & mut self ) -> usize {
47
+ fn get_document ( & self ) -> usize {
47
48
0
48
49
}
49
50
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 ( ) )
52
54
{
53
55
target + 1
54
56
} else {
@@ -61,53 +63,63 @@ impl TreeSink for Sink {
61
63
}
62
64
63
65
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 ( )
65
71
}
66
72
67
- fn create_element ( & mut self , name : QualName , _: Vec < Attribute > , _: ElementFlags ) -> usize {
73
+ fn create_element ( & self , name : QualName , _: Vec < Attribute > , _: ElementFlags ) -> usize {
68
74
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) ) ) ;
70
82
id
71
83
}
72
84
73
- fn create_comment ( & mut self , _text : StrTendril ) -> usize {
85
+ fn create_comment ( & self , _text : StrTendril ) -> usize {
74
86
self . get_id ( )
75
87
}
76
88
77
89
#[ allow( unused_variables) ]
78
- fn create_pi ( & mut self , target : StrTendril , value : StrTendril ) -> usize {
90
+ fn create_pi ( & self , target : StrTendril , value : StrTendril ) -> usize {
79
91
unimplemented ! ( )
80
92
}
81
93
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 > ) { }
83
95
84
96
fn append_based_on_parent_node (
85
- & mut self ,
97
+ & self ,
86
98
_element : & usize ,
87
99
_prev_element : & usize ,
88
100
_new_node : NodeOrText < usize > ,
89
101
) {
90
102
}
91
103
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 > ) { }
95
107
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" ) ;
99
111
}
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 ) { }
103
115
}
104
116
105
117
/// In this example we implement the TreeSink trait which takes each parsed elements and insert
106
118
/// it to a hashmap, while each element is given a numeric id.
107
119
fn main ( ) {
108
120
let sink = Sink {
109
- next_id : 1 ,
110
- names : HashMap :: new ( ) ,
121
+ next_id : Cell :: new ( 1 ) ,
122
+ names : RefCell :: new ( HashMap :: new ( ) ) ,
111
123
} ;
112
124
113
125
// Read HTML from the standard input and parse it
0 commit comments