1use std::cell::Cell;
2use std::rc::Rc;
3use std::fmt;
4
5use markup5ever::{Attribute as DomAttribute, QualName};
6use markup5ever_rcdom::{NodeData, Handle as NodeHandle, WeakHandle as WeakNodeHandle, SerializableHandle};
7use html5ever::serialize;
8
9use crate::{Document, Error};
10use crate::result::{Result, ValueError};
11
12#[derive(Debug, Clone)]
13pub enum Value {
14 Boolean(bool),
15 Number(f64),
16 String(String),
17 Nodeset(Nodeset)
18}
19
20impl Value {
21 pub fn exists(&self) -> bool {
22 match self {
23 Value::Boolean(v) => *v,
24 Value::Number(v) => !v.is_nan(),
25 Value::String(v) => !v.is_empty(),
26 Value::Nodeset(v) => !v.nodes.is_empty()
27 }
28 }
29
30 pub fn as_nodeset(&self) -> Result<&Nodeset> {
31 match self {
32 Value::Nodeset(s) => Ok(s),
33 _ => Err(ValueError::Nodeset.into())
34 }
35 }
36
37 pub fn into_nodeset(self) -> Result<Nodeset> {
38 match self {
39 Value::Nodeset(s) => Ok(s),
40 _ => Err(ValueError::Nodeset.into())
41 }
42 }
43
44 pub fn into_iterset(self) -> Result<NodeIterset> {
45 match self {
46 Value::Nodeset(s) => Ok(NodeIterset::new(s.into_iter())),
47 _ => Err(ValueError::Nodeset.into())
48 }
49 }
50
51 pub fn vec_string(self) -> Result<Vec<String>> {
52 let value_iter = self.into_iterset()?
53 .map(|i| i.value().and_then(|v| v.string()))
54 .collect::<Result<Vec<String>>>()?;
55
56 Ok(value_iter)
57 }
58
59
60 pub fn boolean(&self) -> Result<bool> {
61 match self {
62 Value::Boolean(v) => Ok(*v),
63 _ => Err(ValueError::Boolean.into())
64 }
65 }
66
67 pub fn number(&self) -> Result<f64> {
68 match self {
69 Value::Number(v) => Ok(*v),
70 _ => Err(ValueError::Number.into())
71 }
72 }
73
74 pub fn as_string(&self) -> Result<&String> {
75 match self {
76 Value::String(v) => Ok(v),
77 _ => Err(ValueError::String.into())
78 }
79 }
80
81 pub fn string(self) -> Result<String> {
82 match self {
83 Value::String(v) => Ok(v),
84 _ => Err(ValueError::String.into())
85 }
86 }
87}
88
89impl PartialEq for Value {
90 fn eq(&self, other: &Value) -> bool {
91 match (self, other) {
92 (Value::Nodeset(set), Value::String(value)) |
94 (Value::String(value), Value::Nodeset(set)) => {
95
96 if set.nodes.is_empty() {
97 return false;
98 }
99
100 set.nodes.iter()
101 .any(|node| {
102 if &format!("{:?}", node) == value {
104 true
105 } else {
106 match node {
107 Node::Attribute(attr) => {
108 attr.value() == value
109 }
110
111 Node::Text(handle) => {
112 let upgrade = handle.upgrade().unwrap();
113 if let NodeData::Text { contents } = &upgrade.data {
114 contents.try_borrow().map(|v| v.as_ref() == value).unwrap_or_default()
115 } else {
116 false
117 }
118 }
119
120 _ => false
121 }
122 }
123 })
124 }
125
126 (Value::Nodeset(set1), Value::Nodeset(set2)) => {
127 format!("{:?}", set1) == format!("{:?}", set2)
129 }
130
131 _ => false
132 }
133 }
134}
135
136#[derive(Clone)]
143pub struct Attribute {
144 pub parent: WeakNodeHandle,
145 pub attr: DomAttribute
146}
147
148impl Attribute {
149 pub fn new(parent: WeakNodeHandle, attr: DomAttribute) -> Self {
150 Self {
151 parent,
152 attr
153 }
154 }
155
156 pub fn from_node(node: &WeakNodeHandle) -> Option<Vec<Attribute>> {
157 if let NodeData::Element { attrs, .. } = &node.upgrade().unwrap().data {
158 Some(attrs.borrow().iter().map(|a| Attribute::new(node.clone(), a.clone())).collect())
159 } else {
160 None
161 }
162 }
163
164 pub fn name(&self) -> &QualName {
165 &self.attr.name
166 }
167
168 pub fn name_string(&self) -> String {
169 let mut comp = String::new();
170
171 if let Some(prefix) = &self.attr.name.prefix {
172 comp.push_str(&prefix);
173 comp.push(':');
174 }
175
176 comp.push_str(&self.attr.name.local);
177
178 comp
179 }
180
181 pub fn value(&self) -> &str {
182 &*self.attr.value
183 }
184}
185
186
187#[derive(Clone)]
191pub enum Node {
192 Root(NodeHandle),
193 DocType(WeakNodeHandle),
194 Element(WeakNodeHandle),
195 Attribute(Attribute),
196 Text(WeakNodeHandle),
197 Comment(WeakNodeHandle),
198 ProcessingInstruction(WeakNodeHandle),
199 Namespace(WeakNodeHandle), }
201
202impl Node {
203 pub fn enum_name(&self) -> String {
204 match self {
205 Node::DocType(_) => "DocType".into(),
206 Node::Namespace(_) => "Namespace".into(),
207 Node::Root(_) => "Root".into(),
208 Node::Element(_) => "Element".into(),
209 Node::Attribute(_) => "Attribute".into(),
210 Node::Text(_) => "Text".into(),
211 Node::Comment(_) => "Comment".into(),
212 Node::ProcessingInstruction(_) => "ProcessingInstruction".into(),
213 }
214 }
215
216 pub fn is_root(&self) -> bool {
217 matches!(self, Node::Root(_))
218 }
219
220 pub fn is_namespace(&self) -> bool {
221 matches!(self, Node::Namespace(_))
222 }
223
224 pub fn is_element(&self) -> bool {
225 matches!(self, Node::Element(_))
226 }
227
228 pub fn is_attribute(&self) -> bool {
229 matches!(self, Node::Attribute(_))
230 }
231
232 pub fn is_text(&self) -> bool {
233 matches!(self, Node::Text(_))
234 }
235
236 pub fn is_comment(&self) -> bool {
237 matches!(self, Node::Comment(_))
238 }
239
240 pub fn is_processing_instruction(&self) -> bool {
241 matches!(self, Node::ProcessingInstruction(_))
242 }
243
244 pub fn value(&self) -> Result<Value> {
245 match self {
246 Node::Attribute(attr) => {
247 Ok(Value::String(attr.value().to_string()))
248 }
249
250 Node::Text(node) => {
251 if let NodeData::Text { contents } = &node.upgrade().unwrap().data {
252 Ok(Value::String(contents.borrow().to_string()))
253 } else {
254 Err(Error::NodeDidNotContainText)
255 }
256 }
257
258 _ => Err(Error::CannotConvertNodeToValue)
259 }
260 }
261
262 pub fn as_simple_html(&self) -> Option<String> {
263 match self {
264 Node::Root(_) => None,
265
266 Node::Attribute(attr) => {
267 Some(format!("@{}={}", attr.name_string(), attr.value()))
268 }
269
270 _ => {
271 let mut st = Vec::new();
272
273 let write = std::io::Cursor::new(&mut st);
274
275 serialize::<_, SerializableHandle>(
276 write,
277 &self.inner_weak()?.upgrade()?.into(),
278 html5ever::serialize::SerializeOpts { traversal_scope: markup5ever::serialize::TraversalScope::IncludeNode, .. Default::default() })
279 .ok()?;
280
281 Some(String::from_utf8(st).ok()?)
282 }
283 }
284 }
285
286 pub fn attribute(&self) -> Option<&Attribute> {
287 match self {
288 Node::Attribute(attr) => Some(attr),
289 _ => None
290 }
291 }
292
293 pub fn parent(&self) -> Option<Node> {
294 match self {
295 Node::Attribute(attr) => attr.parent.upgrade()
296 .and_then(|node| get_opt_node_from_cell(&node.parent).map(Node::Element)),
297 Node::DocType(_) |
298 Node::Namespace(_) |
299 Node::Root(_) => None,
300 Node::Element(weak) => weak.upgrade()
301 .and_then(|node| get_opt_node_from_cell(&node.parent).map(Node::Element)),
302 Node::Text(weak) => weak.upgrade()
303 .and_then(|node| get_opt_node_from_cell(&node.parent).map(Node::Text)),
304 Node::Comment(weak) => weak.upgrade()
305 .and_then(|node| get_opt_node_from_cell(&node.parent).map(Node::Comment)),
306 Node::ProcessingInstruction(weak) => weak.upgrade()
307 .and_then(|node| get_opt_node_from_cell(&node.parent).map(Node::ProcessingInstruction))
308 }
309 }
310
311 pub fn children(&self) -> Vec<Node> {
312 match self {
313 Node::Root(handle) => {
314 let node = handle.as_ref();
315
316 node.children.borrow()
317 .iter()
318 .map(|c| c.into())
319 .collect()
320 }
321
322 Node::Text(handle) |
323 Node::Comment(handle) |
324 Node::DocType(handle) |
325 Node::Element(handle) => {
326 let node = handle.upgrade().unwrap();
327
328 let borrow = node.children.borrow();
329
330 borrow.iter()
331 .map(|c| c.into())
332 .collect()
333 }
334
335 _ => unimplemented!("Node::children(\"{}\")", self.enum_name())
336 }
337 }
338
339
340 pub fn name(&self) -> Option<QualName> {
341 match self {
342 Node::Element(node) => {
343 if let NodeData::Element { name, .. } = &node.upgrade()?.data {
344 Some(name.clone())
345 } else {
346 None
347 }
348 }
349
350 Node::Attribute(attr) => {
351 if let NodeData::Element { name, .. } = &attr.parent.upgrade()?.data {
352 Some(name.clone())
353 } else {
354 None
355 }
356 }
357
358 _ => None
359 }
360 }
361
362 pub fn target(&self) -> Option<String> {
363 match self {
364 Node::ProcessingInstruction(node) => {
365 if let NodeData::ProcessingInstruction { target, .. } = &node.upgrade()?.data {
366 Some(target.to_string())
367 } else {
368 None
369 }
370 }
371
372 _ => None
373 }
374 }
375
376 pub fn prefix(&self) -> String {
377 unimplemented!("Node::prefix()");
378 }
379
380 pub fn inner_weak(&self) -> Option<&WeakNodeHandle> {
381 match self {
382 Node::Root(..) => None,
383 Node::DocType(weak) |
384 Node::Namespace(weak) |
385 Node::Element(weak) |
386 Node::Text(weak) |
387 Node::Comment(weak) |
388 Node::ProcessingInstruction(weak) => Some(weak),
389 Node::Attribute(weak) => Some(&weak.parent)
390 }
391 }
392
393
394 pub fn evaluate_from<S: Into<String>>(&self, search: S, doc: &Document) -> Result<Value> {
395 doc.evaluate_from(search, self.clone())
396 }
397}
398
399impl From<&NodeHandle> for Node {
400 fn from(handle: &NodeHandle) -> Self {
401 match &handle.data {
402 NodeData::Comment{ .. } => {
403 Node::Comment(Rc::downgrade(handle))
404 }
405
406 NodeData::Document => {
407 panic!("Cannot convert borrowed Document to Node.")
408 }
409
410 NodeData::Element{ .. } => {
411 Node::Element(Rc::downgrade(handle))
412 }
413
414 NodeData::ProcessingInstruction{ .. } => {
415 Node::ProcessingInstruction(Rc::downgrade(handle))
416 }
417
418 NodeData::Text{ .. } => {
419 Node::Text(Rc::downgrade(handle))
420 }
421
422 NodeData::Doctype { .. } => {
423 Node::DocType(Rc::downgrade(handle))
424 }
425 }
426 }
427}
428
429impl From<NodeHandle> for Node {
430 fn from(handle: NodeHandle) -> Self {
431 match handle.data {
432 NodeData::Comment{ .. } => {
433 Node::Comment(Rc::downgrade(&handle))
434 }
435
436 NodeData::Document => {
437 Node::Root(handle)
438 }
439
440 NodeData::Element{ .. } => {
441 Node::Element(Rc::downgrade(&handle))
442 }
443
444 NodeData::Doctype { .. } => {
445 Node::DocType(Rc::downgrade(&handle))
446 }
447
448 NodeData::ProcessingInstruction{ .. } => {
449 Node::ProcessingInstruction(Rc::downgrade(&handle))
450 }
451
452 NodeData::Text{ .. } => {
453 Node::Text(Rc::downgrade(&handle))
454 }
455 }
456 }
457}
458
459impl PartialEq for Node {
460 fn eq(&self, other: &Node) -> bool {
461 if self.is_root() || other.is_root() {
462 return self.is_root() == other.is_root();
463 }
464
465 match (self.inner_weak(), other.inner_weak()) {
466 (Some(left), Some(right)) => compare_weak_nodes(left, right),
467 _ => false
468 }
469 }
470}
471
472pub fn compare_weak_nodes(left: &WeakNodeHandle, right: &WeakNodeHandle) -> bool {
473 let left_upgrade = left.upgrade().unwrap();
474 let right_upgrade = right.upgrade().unwrap();
475
476 compare_nodes(&left_upgrade, &right_upgrade)
477}
478
479
480pub fn following_nodes_from_parent(node: &Node) -> Vec<Node> {
481 find_nodes_from_parent(node, |child_pos, node_pos| child_pos > node_pos)
482}
483
484pub fn preceding_nodes_from_parent(node: &Node) -> Vec<Node> {
485 find_nodes_from_parent(node, |child_pos, node_pos| child_pos < node_pos)
486}
487
488fn find_nodes_from_parent<F: Fn(usize, usize) -> bool>(node: &Node, f_capture: F) -> Vec<Node> {
489 let node = match node.inner_weak().and_then(|v| v.upgrade()) {
490 Some(v) => v,
491 None => return Vec::new()
492 };
493
494 if let Some(weak) = node.parent.take() {
496 let parent = weak.upgrade().expect("dangling weak pointer");
497 node.parent.set(Some(weak));
498
499 let children = parent.children.borrow();
500
501 let i = match children
502 .iter()
503 .enumerate()
504 .find(|&(_, child)| Rc::ptr_eq(&child, &node))
505 {
506 Some((i, _)) => i,
507 None => return Vec::new()
508 };
509
510 children
511 .iter()
512 .enumerate()
513 .filter(|c| f_capture(c.0, i))
514 .map(|i| i.1.into())
515 .collect()
516 } else {
517 Vec::new()
518 }
519}
520
521
522
523pub fn compare_nodes(left_upgrade: &NodeHandle, right_upgrade: &NodeHandle) -> bool {
524 let matched = match (&left_upgrade.data, &right_upgrade.data) {
525 (
526 NodeData::Text {
527 contents: b_contents
528 },
529 NodeData::Text {
530 contents
531 }
532 ) => {
533 b_contents == contents
534 }
535
536 (
537 NodeData::Comment {
538 contents: b_contents
539 },
540 NodeData::Comment {
541 contents
542 }
543 ) => {
544 b_contents == contents
545 }
546
547 (
548 NodeData::Doctype {
549 name: b_name,
550 public_id: b_public_id,
551 system_id: b_system_id
552 },
553 NodeData::Doctype {
554 name,
555 public_id,
556 system_id
557 }
558 ) => {
559 b_name == name ||
560 b_public_id == public_id ||
561 b_system_id == system_id
562 }
563
564 (
565 NodeData::Element {
566 name: b_name,
567 attrs: b_attr,
568 template_contents: b_template_contents,
569 mathml_annotation_xml_integration_point: b_mathml
570 },
571 NodeData::Element {
572 name,
573 attrs,
574 template_contents,
575 mathml_annotation_xml_integration_point
576 }
577 ) => {
578 b_name == name ||
579 b_attr == attrs ||
580 Some((b_template_contents, template_contents))
581 .filter(|c| c.0.is_some() || c.1.is_some())
582 .map(|i| compare_nodes(i.0.as_ref().unwrap(), i.1.as_ref().unwrap()))
583 .unwrap_or_default() ||
584 b_mathml == mathml_annotation_xml_integration_point
585 }
586
587 (
588 NodeData::ProcessingInstruction {
589 target: b_target,
590 contents: b_contents
591 },
592 NodeData::ProcessingInstruction {
593 target,
594 contents
595 }
596 ) => {
597 b_target == target ||
598 b_contents == contents
599 }
600
601 _ => false
602 };
603
604 if matched {
605 return true;
606 }
607
608 let l_children = left_upgrade.children.borrow();
610 let r_children = right_upgrade.children.borrow();
611
612 if l_children.len() != r_children.len() {
613 return false;
614 }
615
616 l_children.iter()
620 .zip(r_children.iter())
621 .position(|c| !compare_nodes(c.0, c.1))
622 .is_none()
623}
624
625
626impl fmt::Debug for Node {
639 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
640 match self {
641 Node::Root(weak) => {
642 f.debug_tuple("Root")
643 .field(&weak)
644 .finish()
645 }
646
647 Node::Attribute(weak) => {
648 f.debug_tuple("Attribute")
649 .field(&weak.parent.upgrade().unwrap().data)
650 .finish()
651 }
652
653 Node::DocType(weak) |
654 Node::Element(weak) |
655 Node::Namespace(weak) |
656 Node::Text(weak) |
657 Node::Comment(weak) |
658 Node::ProcessingInstruction(weak) => {
659 f.debug_tuple("Node")
660 .field(&weak.upgrade().unwrap().data)
661 .finish()
662 }
663 }
664
665 }
666}
667
668#[derive(Clone)]
670pub struct Nodeset {
671 pub nodes: Vec<Node>
672}
673
674impl Nodeset {
675 pub fn new() -> Self {
676 Default::default()
677 }
678
679 pub fn add_node_handle(&mut self, node: &NodeHandle) {
680 self.nodes.push(node.into());
681 }
682
683 pub fn add_node(&mut self, node: Node) {
684 self.nodes.push(node);
685 }
686
687 pub fn extend(&mut self, nodeset: Nodeset) {
688 self.nodes.extend(nodeset.nodes);
689 }
690
691 pub fn len(&self) -> usize {
692 self.nodes.len()
693 }
694
695 pub fn is_empty(&self) -> bool {
696 self.nodes.is_empty()
697 }
698}
699
700impl Default for Nodeset {
701 fn default() -> Self {
702 Nodeset {
703 nodes: Vec::new()
704 }
705 }
706}
707
708
709impl IntoIterator for Nodeset {
710 type Item = Node;
711 type IntoIter = std::vec::IntoIter<Self::Item>;
712
713 fn into_iter(self) -> Self::IntoIter {
714 self.nodes.into_iter()
715 }
716}
717
718impl From<Vec<Node>> for Nodeset {
719 fn from(nodes: Vec<Node>) -> Self {
720 Self {
721 nodes
722 }
723 }
724}
725
726impl fmt::Debug for Nodeset {
727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
728 let mut list = f.debug_list();
729
730 self.nodes.iter()
731 .for_each(|node| {
732 list.entry(&node.as_simple_html());
733 });
734
735
736 list.finish()
737 }
738}
739
740pub struct NodeIterset(std::vec::IntoIter<Node>);
741
742impl NodeIterset {
743 pub fn new(set: std::vec::IntoIter<Node>) -> Self {
744 Self(set)
745 }
746}
747
748impl Iterator for NodeIterset {
749 type Item = Node;
750
751 fn next(&mut self) -> Option<Self::Item> {
752 self.0.next()
753 }
754}
755
756pub struct Valueset(Vec<Value>);
757
758impl Valueset {
759 }
761
762
763pub fn get_opt_node_from_cell(cell: &Cell<Option<WeakNodeHandle>>) -> Option<WeakNodeHandle> {
764 let item = cell.take();
765
766 let cloned = item.clone();
767
768 cell.set(item);
769
770 cloned
771}