feed-parser 2.0.0

A simple RSS 1.0 / RSS 2.0 / Atom feed parser
Documentation
**English** | [日本語]errors.ja.md

# Error Handling

Every parser returns `ParseResult<Vec<Feed>>`, an alias for
`Result<Vec<Feed>, ParseError>`. Malformed input is returned as an error; it never
panics.

```rust
use feed_parser::parsers::{errors::ParseError, rss2};

match rss2::parse(document) {
    Ok(feeds) => println!("{} entries", feeds.len()),
    Err(ParseError::MissingField(field)) => eprintln!("entry is missing {field}"),
    Err(e) => eprintln!("could not parse the feed: {e}"),
}
```

## Variants

`ParseError` is `#[non_exhaustive]`, so a `match` over it needs a wildcard arm and new
variants can be added without a major release.

| Variant | Returned when |
|--|--|
| `XmlParseError` | The document is not well-formed XML — an unclosed tag, a mismatched end tag, a bad attribute. Wraps `quick_xml::Error`. |
| `DeserializeError` | An entry is valid XML but does not fit `Feed`, typically because unescaped markup spanning several lines left real child elements inside a text field. Wraps `quick_xml::DeError`. |
| `MissingField` | An entry has no `<title>`, or no usable `<link>`. Carries the field name. |
| `InvalidFeedFormat` | The document ends while an entry is still open. Carries a description. |
| `Utf8Error` | The document contains a byte sequence that is not valid UTF-8. |
| `IoError` | Writing the normalized intermediate XML failed. |

## One bad entry fails the document

`parse` returns either every entry or an error. A single entry that cannot be
deserialized aborts the call rather than being skipped, so a partial result is never
mistaken for a complete one.

To tolerate broken entries in a feed you do not control, split the document and parse
the entries separately, or match on the error and fall back to whatever your
application considers reasonable.

## Errors carry their source

`ParseError` implements `std::error::Error`, so the variants that wrap another error
expose it through `source()`, and the type composes with `anyhow`, `eyre` and the
`?` operator in the usual way.

```rust
fn load(document: &str) -> anyhow::Result<Vec<feed_parser::parsers::Feed>> {
    Ok(feed_parser::parsers::rss2::parse(document)?)
}
```