Skip to main content

spire_core/frontier/queue/
link.rs

1use ::http::Uri;
2
3use crate::crawler::Tag;
4use crate::frontier::seed::Seed;
5
6/// A link to follow with [`Queue::follow`](crate::frontier::queue::Queue::follow).
7///
8/// A link is either an `href`, absolute or relative to the page it was found
9/// on, or a complete [`Seed`]. Strings, URIs and seeds convert into links.
10///
11/// ```
12/// use spire_core::frontier::queue::Link;
13///
14/// let next = Link::from("/page/2");
15/// let detail = Link::from("../items/42").with_tag("item");
16/// let next = Link::from("/page/3").with_priority(10);
17/// ```
18#[derive(Debug, Clone)]
19pub struct Link {
20    pub(crate) target: Target,
21    pub(crate) tag: Option<Tag>,
22    pub(crate) priority: Option<i32>,
23}
24
25#[derive(Debug, Clone)]
26pub(crate) enum Target {
27    Href(String),
28    Seed(Box<Seed>),
29}
30
31impl Link {
32    /// Creates a link from an `href`, absolute or relative.
33    #[must_use]
34    pub fn new(href: impl Into<String>) -> Self {
35        Self {
36            target: Target::Href(href.into()),
37            tag: None,
38            priority: None,
39        }
40    }
41
42    /// Routes the followed request to the handler for `tag`.
43    #[must_use]
44    pub fn with_tag(mut self, tag: impl Into<Tag>) -> Self {
45        self.tag = Some(tag.into());
46        self
47    }
48
49    /// Sets the followed request's priority, e.g. scored from the page the
50    /// link was found on; frontiers that order by priority crawl higher
51    /// priorities first. A [scoring](crate::frontier::FrontierExt::score)
52    /// frontier adds its score to it.
53    #[must_use]
54    pub const fn with_priority(mut self, priority: i32) -> Self {
55        self.priority = Some(priority);
56        self
57    }
58}
59
60impl From<&str> for Link {
61    fn from(href: &str) -> Self {
62        Self::new(href)
63    }
64}
65
66impl From<String> for Link {
67    fn from(href: String) -> Self {
68        Self::new(href)
69    }
70}
71
72impl From<&String> for Link {
73    fn from(href: &String) -> Self {
74        Self::new(href.as_str())
75    }
76}
77
78impl From<Uri> for Link {
79    fn from(uri: Uri) -> Self {
80        Self::new(uri.to_string())
81    }
82}
83
84impl From<Seed> for Link {
85    fn from(seed: Seed) -> Self {
86        Self {
87            target: Target::Seed(Box::new(seed)),
88            tag: None,
89            priority: None,
90        }
91    }
92}