@@ -10,24 +10,19 @@ extern crate scoped_pool;
10
10
11
11
use std:: panic;
12
12
13
- use rustler:: {
14
- NifEnv ,
15
- NifTerm ,
16
- NifResult ,
17
- NifError ,
18
- NifEncoder ,
19
- NifDecoder ,
20
- } ;
13
+ use rustler:: { NifEnv , NifTerm , NifResult , NifError , NifEncoder , NifDecoder } ;
21
14
use rustler:: types:: binary:: NifBinary ;
22
15
use rustler:: env:: OwnedEnv ;
23
16
24
- use html5ever:: { QualName } ;
25
- use html5ever:: rcdom:: { RcDom , Handle , NodeEnum } ;
17
+ use html5ever:: rcdom:: RcDom ;
26
18
use html5ever:: driver:: ParseOpts ;
27
19
use html5ever:: tokenizer:: TokenizerOpts ;
28
20
use html5ever:: tree_builder:: TreeBuilderOpts ;
29
- use html5ever:: tree_builder:: interface:: QuirksMode ;
30
- use tendril:: { TendrilSink , StrTendril } ;
21
+ use html5ever:: tree_builder:: QuirksMode ;
22
+ use tendril:: TendrilSink ;
23
+
24
+ mod rc_dom;
25
+ use rc_dom:: handle_to_term;
31
26
32
27
mod atoms {
33
28
rustler_atoms ! {
@@ -41,11 +36,11 @@ mod atoms {
41
36
atom doctype;
42
37
atom comment;
43
38
44
- atom error_level;
45
39
atom discard_bom;
46
40
atom scripting_enabled;
47
41
atom iframe_srcdoc;
48
42
atom drop_doctype;
43
+ atom error_level;
49
44
50
45
atom none;
51
46
atom some;
@@ -61,10 +56,15 @@ enum ErrorLevel {
61
56
}
62
57
impl < ' a > NifDecoder < ' a > for ErrorLevel {
63
58
fn decode ( term : NifTerm < ' a > ) -> NifResult < ErrorLevel > {
64
- if atoms:: none ( ) == term { Ok ( ErrorLevel :: None ) }
65
- else if atoms:: some ( ) == term { Ok ( ErrorLevel :: Some ) }
66
- else if atoms:: all ( ) == term { Ok ( ErrorLevel :: All ) }
67
- else { Err ( NifError :: BadArg ) }
59
+ if atoms:: none ( ) == term {
60
+ Ok ( ErrorLevel :: None )
61
+ } else if atoms:: some ( ) == term {
62
+ Ok ( ErrorLevel :: Some )
63
+ } else if atoms:: all ( ) == term {
64
+ Ok ( ErrorLevel :: All )
65
+ } else {
66
+ Err ( NifError :: BadArg )
67
+ }
68
68
}
69
69
}
70
70
@@ -74,17 +74,13 @@ fn term_to_configs(term: NifTerm) -> NifResult<ParseOpts> {
74
74
} else {
75
75
let env = term. get_env ( ) ;
76
76
77
- let errors: ErrorLevel =
78
- term. map_get ( atoms:: error_level ( ) . to_term ( env) ) ?. decode ( ) ?;
77
+ let errors: ErrorLevel = term. map_get ( atoms:: error_level ( ) . to_term ( env) ) ?. decode ( ) ?;
79
78
80
- let discard_bom: bool =
81
- term. map_get ( atoms:: discard_bom ( ) . to_term ( env) ) ?. decode ( ) ?;
82
- let scripting_enabled: bool =
83
- term. map_get ( atoms:: scripting_enabled ( ) . to_term ( env) ) ?. decode ( ) ?;
84
- let iframe_srcdoc: bool =
85
- term. map_get ( atoms:: iframe_srcdoc ( ) . to_term ( env) ) ?. decode ( ) ?;
86
- let drop_doctype: bool =
87
- term. map_get ( atoms:: drop_doctype ( ) . to_term ( env) ) ?. decode ( ) ?;
79
+ let discard_bom: bool = term. map_get ( atoms:: discard_bom ( ) . to_term ( env) ) ?. decode ( ) ?;
80
+ let scripting_enabled: bool = term. map_get ( atoms:: scripting_enabled ( ) . to_term ( env) ) ?
81
+ . decode ( ) ?;
82
+ let iframe_srcdoc: bool = term. map_get ( atoms:: iframe_srcdoc ( ) . to_term ( env) ) ?. decode ( ) ?;
83
+ let drop_doctype: bool = term. map_get ( atoms:: drop_doctype ( ) . to_term ( env) ) ?. decode ( ) ?;
88
84
89
85
Ok ( ParseOpts {
90
86
tokenizer : TokenizerOpts {
@@ -106,69 +102,6 @@ fn term_to_configs(term: NifTerm) -> NifResult<ParseOpts> {
106
102
}
107
103
}
108
104
109
- // Zero-cost wrapper types which makes it possible to implement
110
- // NifEncoder for these externally defined types.
111
- // Unsure if this is a great way of doing it, but it's the way
112
- // that produced the cleanest and least noisy code.
113
- struct QNW < ' a > ( & ' a QualName ) ;
114
- struct STW < ' a > ( & ' a StrTendril ) ;
115
-
116
- impl < ' b > NifEncoder for QNW < ' b > {
117
- fn encode < ' a > ( & self , env : NifEnv < ' a > ) -> NifTerm < ' a > {
118
- let data: & str = & * self . 0 . local ;
119
- data. encode ( env)
120
- }
121
- }
122
- impl < ' b > NifEncoder for STW < ' b > {
123
- fn encode < ' a > ( & self , env : NifEnv < ' a > ) -> NifTerm < ' a > {
124
- let data: & str = & * self . 0 ;
125
- data. encode ( env)
126
- }
127
- }
128
-
129
- /// Takes a Handle from a RcDom, encodes it into a NifTerm.
130
- /// This follows the mochiweb encoding scheme with two exceptions:
131
- /// * A `{:doctype, name, pubid, sysid}` node.
132
- /// * Always returns a list as it's root node.
133
- fn handle_to_term < ' a > ( env : NifEnv < ' a > , handle : & Handle ) -> NifTerm < ' a > {
134
- let node = handle. borrow ( ) ;
135
-
136
- // Closure so that we don't encode this when we don't need to return
137
- // it to the user.
138
- let children = || {
139
- // Encodes a Vec<Handle> to a Vec<NifTerm>
140
- let res: Vec < NifTerm < ' a > > =
141
- node. children . iter ( ) . map ( |h| handle_to_term ( env, h) ) . collect ( ) ;
142
- // Encodes to erlang list term.
143
- res. encode ( env)
144
- } ;
145
-
146
- match node. node {
147
- // Root document node. As far as I know, this is only located in the
148
- // root of the DOM.
149
- NodeEnum :: Document =>
150
- children ( ) ,
151
-
152
- NodeEnum :: Doctype ( ref name, ref pubid, ref sysid) =>
153
- ( atoms:: doctype ( ) , STW ( name) , STW ( pubid) , STW ( sysid) ) . encode ( env) ,
154
-
155
- NodeEnum :: Text ( ref text) =>
156
- STW ( text) . encode ( env) ,
157
-
158
- NodeEnum :: Comment ( ref text) =>
159
- ( atoms:: comment ( ) , STW ( text) ) . encode ( env) ,
160
-
161
- NodeEnum :: Element ( ref name, ref _elem_type, ref attributes) => {
162
- let attribute_terms: Vec < NifTerm < ' a > > =
163
- attributes. iter ( )
164
- . map ( |a| ( QNW ( & a. name ) , STW ( & a. value ) ) . encode ( env) )
165
- . collect ( ) ;
166
-
167
- ( QNW ( name) , attribute_terms, children ( ) ) . encode ( env)
168
- } ,
169
- }
170
- }
171
-
172
105
// Thread pool for `parse_async`.
173
106
// TODO: How do we decide on pool size?
174
107
lazy_static ! {
@@ -185,7 +118,7 @@ fn parse_async<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'
185
118
186
119
let return_pid = env. pid ( ) ;
187
120
188
- //let config = term_to_configs(args[1]);
121
+ // let config = term_to_configs(args[1]);
189
122
190
123
POOL . spawn ( move || {
191
124
owned_env. send_and_clear ( & return_pid, |inner_env| {
@@ -201,28 +134,24 @@ fn parse_async<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'
201
134
202
135
// TODO: Use Parser.from_bytes instead?
203
136
let parser = html5ever:: parse_document ( sink, Default :: default ( ) ) ;
204
- let result = parser. one (
205
- std:: str:: from_utf8 ( binary. as_slice ( ) ) . unwrap ( ) ) ;
137
+ let result = parser. one ( std:: str:: from_utf8 ( binary. as_slice ( ) ) . unwrap ( ) ) ;
206
138
207
139
let result_term = handle_to_term ( inner_env, & result. document ) ;
208
- ( atoms:: html5ever_nif_result ( ) , atoms:: ok ( ) , result_term)
209
- . encode ( inner_env)
140
+ ( atoms:: html5ever_nif_result ( ) , atoms:: ok ( ) , result_term. unwrap ( ) ) . encode ( inner_env)
210
141
} ) {
211
142
Ok ( term) => term,
212
143
Err ( err) => {
213
144
// Try to extract a panic reason and return that. If this
214
145
// fails, fail generically.
215
- let reason =
216
- if let Some ( s) = err. downcast_ref :: < String > ( ) {
217
- s. encode ( inner_env)
218
- } else if let Some ( & s) = err. downcast_ref :: < & ' static str > ( ) {
219
- s. encode ( inner_env)
220
- } else {
221
- atoms:: nif_panic ( ) . encode ( inner_env)
222
- } ;
223
- ( atoms:: html5ever_nif_result ( ) , atoms:: error ( ) , reason)
224
- . encode ( inner_env)
225
- } ,
146
+ let reason = if let Some ( s) = err. downcast_ref :: < String > ( ) {
147
+ s. encode ( inner_env)
148
+ } else if let Some ( & s) = err. downcast_ref :: < & ' static str > ( ) {
149
+ s. encode ( inner_env)
150
+ } else {
151
+ atoms:: nif_panic ( ) . encode ( inner_env)
152
+ } ;
153
+ ( atoms:: html5ever_nif_result ( ) , atoms:: error ( ) , reason) . encode ( inner_env)
154
+ }
226
155
}
227
156
} ) ;
228
157
} ) ;
@@ -236,24 +165,19 @@ fn parse_sync<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a
236
165
237
166
// TODO: Use Parser.from_bytes instead?
238
167
let parser = html5ever:: parse_document ( sink, Default :: default ( ) ) ;
239
- let result = parser. one (
240
- std:: str:: from_utf8 ( binary. as_slice ( ) ) . unwrap ( ) ) ;
168
+ let result = parser. one ( std:: str:: from_utf8 ( binary. as_slice ( ) ) . unwrap ( ) ) ;
241
169
242
- //std::thread::sleep(std::time::Duration::from_millis(10));
170
+ // std::thread::sleep(std::time::Duration::from_millis(10));
243
171
244
172
let result_term = handle_to_term ( env, & result. document ) ;
245
173
246
- Ok ( ( atoms:: html5ever_nif_result ( ) , atoms:: ok ( ) , result_term)
247
- . encode ( env) )
174
+ Ok ( ( atoms:: html5ever_nif_result ( ) , atoms:: ok ( ) , result_term. unwrap ( ) ) . encode ( env) )
248
175
249
176
}
250
177
251
- rustler_export_nifs ! (
252
- "Elixir.Html5ever.Native" ,
253
- [ ( "parse_async" , 1 , parse_async) ,
254
- ( "parse_sync" , 1 , parse_sync) ] ,
255
- Some ( on_load)
256
- ) ;
178
+ rustler_export_nifs ! ( "Elixir.Html5ever.Native" ,
179
+ [ ( "parse_async" , 1 , parse_async) , ( "parse_sync" , 1 , parse_sync) ] ,
180
+ Some ( on_load) ) ;
257
181
258
182
259
183
fn on_load < ' a > ( _env : NifEnv < ' a > , _load_info : NifTerm < ' a > ) -> bool {
0 commit comments