1use serde::{Deserialize, Serialize};
4use url::Url;
5
6use crate::crawl::{RobotsFile, SitemapSummary};
7use crate::page::PageRecord;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11pub struct Edge {
12 pub from: u32,
14 pub to: u32,
16 pub anchor: u32,
18 pub nofollow: bool,
19}
20
21#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
24pub struct LinkGraph {
25 pub edges: Vec<Edge>,
26 pub anchors: Vec<String>,
27}
28
29impl LinkGraph {
30 pub fn anchor(&self, e: &Edge) -> &str {
31 &self.anchors[e.anchor as usize]
32 }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37#[serde(rename_all = "snake_case", tag = "kind", content = "reason")]
38pub enum StopReason {
39 Completed,
40 PageLimit,
41 TimeLimit,
42 Unreachable(String),
43 Blocked(String),
44 RobotsBlocked,
45}
46
47impl StopReason {
48 pub fn is_complete(&self) -> bool {
50 matches!(self, StopReason::Completed)
51 }
52
53 pub fn crawl_ran(&self) -> bool {
55 matches!(
56 self,
57 StopReason::Completed | StopReason::PageLimit | StopReason::TimeLimit
58 )
59 }
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
64pub struct Progress {
65 pub pages_done: u32,
66 pub queued: u32,
67 pub failures: u32,
68 pub depth: u16,
69 pub elapsed_ms: u64,
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
73pub struct CrawlOutput {
74 pub origin: Url,
76 pub pages: Vec<PageRecord>,
77 pub links: LinkGraph,
78 pub robots: Option<RobotsFile>,
79 pub sitemap: SitemapSummary,
80 pub stop: StopReason,
81 pub duration_ms: u64,
82}