1mod error;
2
3pub use error::*;
4
5pub use xpather::{
6 self,
7 factory::ProduceIter,
8 value::Node,
9 Document,
10 Value
11};
12
13pub use scraper_macros::Scraper;
14
15pub trait ScraperMain: Sized {
32 fn scrape(doc: &Document, container: Option<&Node>) -> Result<Self>;
33}
34
35pub fn evaluate<'a, S: Into<String>>(search: S, doc: &'a Document, container: Option<&'a Node>) -> Result<ProduceIter<'a>> {
41 Ok(if let Some(node) = container {
42 doc.evaluate_from(search, node)?
43 } else {
44 doc.evaluate(search)?
45 })
46}
47
48pub trait ConvertToValue<T>: Sized {
50 fn convert_from(self, doc: &Document) -> Result<T>;
51}
52
53
54impl<'a> ConvertToValue<Option<String>> for Result<ProduceIter<'a>> {
55 fn convert_from(self, _: &Document) -> Result<Option<String>> {
56 self?.next().map(value_to_string).transpose()
57 }
58}
59
60impl<'a> ConvertToValue<String> for Result<ProduceIter<'a>> {
61 fn convert_from(self, _: &Document) -> Result<String> {
62 self?.next()
63 .map(value_to_string)
64 .transpose()?
65 .ok_or(Error::ConvertFromValue(None))
66 }
67}
68
69impl<'a> ConvertToValue<Vec<String>> for Result<ProduceIter<'a>> {
70 fn convert_from(self, _: &Document) -> Result<Vec<String>> {
71 Ok(value_to_string_vec(self?).into_iter().filter_map(|v| v.ok()).collect())
72 }
73}
74
75impl<'a> ConvertToValue<Vec<Result<String>>> for Result<ProduceIter<'a>> {
76 fn convert_from(self, _: &Document) -> Result<Vec<Result<String>>> {
77 Ok(value_to_string_vec(self?))
78 }
79}
80
81
82
83impl<'a, T> ConvertToValue<Vec<T>> for Result<ProduceIter<'a>> where T: ScraperMain {
84 fn convert_from(self, doc: &Document) -> Result<Vec<T>> {
85 self?.map(|n| T::scrape(doc, Some(n?.as_node()?))).collect::<Result<Vec<_>>>()
86 }
87}
88
89impl<'a, T> ConvertToValue<Option<T>> for Result<ProduceIter<'a>> where T: ScraperMain {
90 fn convert_from(self, doc: &Document) -> Result<Option<T>> {
91 self?.next().map(|n| T::scrape(doc, Some(n?.as_node()?))).transpose()
92 }
93}
94
95pub fn value_to_string(value: xpather::Result<Value>) -> Result<String> {
97 match value? {
98 Value::Node(node) => {
99 value_to_string(node.value())
100 }
101
102 Value::String(v) => Ok(v),
103
104 value => Err(Error::ConvertFromValue(Some(value)))
105 }
106}
107
108pub fn value_to_string_vec(iter: ProduceIter) -> Vec<Result<String>> {
110 iter.map(value_to_string).collect()
111}