rama_http/protocols/rss/error.rs
1//! Error types returned by the RSS / Atom streaming readers.
2
3use std::fmt;
4
5use super::Feed;
6use super::atom::AtomFeed;
7use super::rss2::Rss2Feed;
8
9/// Returned when the document cannot be turned into a feed at all — either
10/// nothing recognisable as an RSS 2.0 / Atom 1.0 root was seen, or strict
11/// mode rejected a structural violation in the header.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct FeedParseError {
14 pub message: String,
15}
16
17impl FeedParseError {
18 pub(super) fn new(msg: impl Into<String>) -> Self {
19 Self {
20 message: msg.into(),
21 }
22 }
23}
24
25impl fmt::Display for FeedParseError {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 write!(f, "feed parse error: {}", self.message)
28 }
29}
30
31impl std::error::Error for FeedParseError {}
32
33/// Returned by [`Rss2FeedStream::collect`], [`AtomFeedStream::collect`] and
34/// [`FeedStream::collect`] when an item / entry fails to parse partway
35/// through the stream. The `partial` feed holds the header that was parsed
36/// at stream construction *and* every item / entry that succeeded before
37/// the failure, so callers can keep what's salvageable.
38///
39/// Use [`Rss2FeedStream::collect_lossy`] / [`AtomFeedStream::collect_lossy`]
40/// /[`FeedStream::collect_lossy`] when per-item errors should be skipped
41/// silently instead of short-circuiting.
42///
43/// [`Rss2FeedStream::collect`]: super::Rss2FeedStream::collect
44/// [`AtomFeedStream::collect`]: super::AtomFeedStream::collect
45/// [`FeedStream::collect`]: super::FeedStream::collect
46/// [`Rss2FeedStream::collect_lossy`]: super::Rss2FeedStream::collect_lossy
47/// [`AtomFeedStream::collect_lossy`]: super::AtomFeedStream::collect_lossy
48/// [`FeedStream::collect_lossy`]: super::FeedStream::collect_lossy
49#[derive(Debug, Clone, PartialEq)]
50pub struct CollectError<F> {
51 /// The underlying per-item parse error.
52 pub error: FeedParseError,
53 /// The header plus every item / entry that was parsed before the error.
54 /// The header is always populated; the items list may be empty if the
55 /// failure happened on the very first item.
56 pub partial: F,
57}
58
59impl<F: fmt::Debug> fmt::Display for CollectError<F> {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 write!(f, "collect failed: {} (partial feed retained)", self.error)
62 }
63}
64
65impl<F: fmt::Debug> std::error::Error for CollectError<F> {
66 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
67 Some(&self.error)
68 }
69}
70
71/// Per-format convenience alias.
72pub type Rss2CollectError = CollectError<Rss2Feed>;
73/// Per-format convenience alias.
74pub type AtomCollectError = CollectError<AtomFeed>;
75/// Format-agnostic alias.
76pub type FeedCollectError = CollectError<Feed>;