1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! A set of internal utility methods that will be used in the auto-generated code on `FromHtml` derive macro.
//! These methods are shorthands to reduce codes in the `quote!` macro. It improves development experience with IDE.
//! You wouldn't call these methods directly in your code.

use crate::from_html::{ExtractionType, StructErrorCause, StructFieldError};
use crate::mapper::Mapper;
use crate::transformer::Transformer;

use crate::Error;
use crate::{CssSelector, FromHtml, HtmlNode};

pub fn select<N>(source: &N, selector: &'static str) -> Vec<N>
where
    N: HtmlNode,
{
    // TODO cache parsed selector
    let selector = N::Selector::parse(selector)
        // this should be never failed because the selector validity has been checked at compile-time
        // TODO avoid unwrap
        .unwrap();
    source.select(&selector)
}

pub fn try_transform_and_map<N, T, M, S>(
    source: S,
    args: &T::Args,
    selector: Option<&'static str>,
    field_name: &'static str,
) -> Result<M, Box<dyn Error>>
where
    N: HtmlNode,
    T: FromHtml,
    M: Mapper<T>,
    S: Transformer<M::Structure<N>>,
{
    source
        .try_transform()
        .map_err(StructErrorCause::StructureUnmatched)
        .and_then(|s| M::try_map(s, args).map_err(StructErrorCause::ParseError))
        .map_err(|e| StructFieldError {
            field_name: field_name.to_string(),
            selector: selector.map(|a| a.to_string()),
            error: e,
        })
        .map_err(|e| Box::new(e) as Box<dyn Error>)
}

pub fn default_argument<T>() -> T
where
    T: DefaultArg,
{
    DefaultArg::default()
}

pub trait DefaultArg {
    fn default() -> Self;
}

impl DefaultArg for () {
    fn default() -> Self {}
}

impl DefaultArg for ExtractionType {
    fn default() -> Self {
        ExtractionType::Text
    }
}