Skip to main content

indexflow_sitemap/
error.rs

1use thiserror::Error;
2
3/// Errors produced by sitemap download, decompression, or (strict) expansion.
4///
5/// Streaming XML parse itself is **fault-tolerant** and does not surface as an
6/// error: malformed documents yield a partial [`crate::ParsedSitemap`] instead.
7#[derive(Debug, Error)]
8pub enum SitemapError {
9    /// Underlying `quick-xml` tokenizer failure (reserved for strict parsers).
10    #[error("XML parser error: {0}")]
11    Xml(#[from] quick_xml::Error),
12
13    /// Gzip inflate failed (truncated stream, CRC mismatch, …).
14    #[error("Decompression error: {0}")]
15    Decompression(String),
16
17    /// Inflated payload exceeded the configured uncompressed-size cap.
18    ///
19    /// This is the primary defence against gzip/deflate bombs.
20    #[error("decompression bomb: inflated size exceeds {limit} bytes")]
21    DecompressionBomb { limit: usize },
22
23    /// HTTP response body (or declared `Content-Length`) exceeded the download cap.
24    #[error("payload too large: {size} bytes exceeds limit {limit}")]
25    PayloadTooLarge { size: u64, limit: u64 },
26
27    /// Byte stream could not be decoded as UTF-8 / UTF-16.
28    #[error("encoding error: {0}")]
29    Encoding(String),
30
31    /// A URL failed to parse (kept for callers that validate locs strictly).
32    #[error("Invalid URL: {0}")]
33    InvalidUrl(#[from] url::ParseError),
34
35    /// Local I/O failure while reading decompressed bytes.
36    #[error("I/O error: {0}")]
37    Io(#[from] std::io::Error),
38
39    /// HTTP transport error from `reqwest`.
40    #[cfg(feature = "fetch")]
41    #[error("Network error: {0}")]
42    Network(#[from] reqwest::Error),
43
44    /// Non-success HTTP status from the sitemap origin.
45    #[error("HTTP response error with status: {0}")]
46    HttpStatus(u16),
47
48    /// Recursive expansion exceeded the caller-supplied depth budget.
49    ///
50    /// `expand_all` isolates this per-child (it skips instead of failing the
51    /// whole tree). Exposed so strict callers can treat it as fatal.
52    #[error("Max recursive depth exceeded ({0})")]
53    MaxDepthExceeded(u8),
54
55    /// A sitemap index loc pointed at an already-visited ancestor (cycle).
56    ///
57    /// `expand_all` isolates this per-child. Exposed so strict callers can
58    /// treat it as fatal.
59    #[error("Circular reference detected for sitemap: {0}")]
60    CircularReference(String),
61}