Skip to main content

anitomy_ng/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Rust port of [erengy/anitomy](https://github.com/erengy/anitomy), an
6//! anime video filename parser.
7//!
8//! The public API (`ElementKind`, `Element`, `Options`, `parse`) matches
9//! upstream; [`detail`] holds the implementation, one module per upstream
10//! C++ header. See `anitomy/tests/conformance.rs` for the harness that
11//! checks output against upstream's and anitopy's fixture suites.
12//!
13//! Pure, safe Rust: no `unsafe`, no C dependencies, so it cross-compiles
14//! and builds wheels anywhere `rustc` runs.
15//!
16//! This crate parses untrusted, arbitrary filenames, so it must never panic
17//! on any input; a panic here would be a denial-of-service bug. The lints
18//! below turn the usual panic
19//! sources (`.unwrap()`, `.expect()`, `panic!`, `unreachable!`, direct
20//! `s[i]` indexing) into hard errors under `cargo clippy` (see
21//! `tests/no_panic.rs` for a runtime check of the same property, which
22//! catches what lints can't, e.g. integer overflow). Prefer `.get(i)`,
23//! pattern matching, `?`, and `.unwrap_or(...)` instead.
24
25#![forbid(unsafe_code)]
26#![deny(
27    clippy::unwrap_used,
28    clippy::expect_used,
29    clippy::panic,
30    clippy::unreachable,
31    clippy::indexing_slicing
32)]
33
34mod detail;
35mod element;
36mod options;
37
38pub use element::{Element, ElementKind, ParseElementKindError};
39pub use options::Options;
40
41/// Port of the free function `anitomy::parse` in `include/anitomy.hpp`.
42///
43/// `input` must be UTF-8 encoded and should be in composed form (NFC/NFKC).
44/// Returns parsed elements ordered by their position in `input`; there may
45/// be multiple elements of the same kind.
46pub fn parse(input: &str, options: Options) -> Vec<Element> {
47    let tokens = detail::tokenizer::tokenize(input, &options);
48    detail::parser::parse(tokens, &options)
49}