Skip to main content

parse_subject

Function parse_subject 

Source
pub fn parse_subject(subject: &str) -> Option<SubjectParts>
Expand description

Parse a multi-part Usenet/email subject line.

Recognises five marker formats (in priority order):

  1. Parenthesised fraction: (03/17) or ( 3 / 17 )
  2. Bracketed fraction: [2/4] (only when both sides are digits)
  3. English “Part N/M” (case-insensitive)
  4. English “Part N of M” / part3of17 (case-insensitive)
  5. Dash-separated fraction: - 03/17

Leading Re:, Fwd:, and Fw: prefixes are stripped before matching (repeatedly, to handle nested re-forwards). The extracted part marker is removed from the subject to produce base_subject.

§Return value

Returns None only when:

  • subject is empty, or
  • subject contains a yEnc marker (those posts use a distinct encoding that is explicitly out of scope for this crate).

Otherwise returns Some(SubjectParts). When no part-marker pattern matches, part_index and part_total are both None and base_subject is the prefix-stripped, trimmed input.

§Zero totals

A subject like "file.bin (3/0)" produces part_total = Some(0). This is nonsensical but is passed through verbatim since the crate cannot know whether the source is malformed or intentional. Callers that pass part_total directly to PartCollection::with_total should validate that the total is non-zero before doing so.

§Never panics

This function never panics on any input, including strings containing arbitrary Unicode code points.

§Examples

use uuencoding_multi::parse_subject;

// Parenthesised fraction — the most common Usenet format.
let sp = parse_subject("bigfile.rar (2/5)").unwrap();
assert_eq!(sp.part_index, Some(2));
assert_eq!(sp.part_total, Some(5));
assert_eq!(sp.base_subject, "bigfile.rar");
use uuencoding_multi::parse_subject;

// Re: prefix is stripped before matching.
let sp = parse_subject("Re: archive.tar.gz (03/17)").unwrap();
assert_eq!(sp.part_index, Some(3));
assert_eq!(sp.part_total, Some(17));
use uuencoding_multi::parse_subject;

// yEnc subject → None (out of scope for this crate).
assert!(parse_subject("\"file.nfo\" yEnc (1/3)").is_none());
use uuencoding_multi::parse_subject;

// Empty input → None.
assert!(parse_subject("").is_none());
use uuencoding_multi::parse_subject;

// No marker → Some with None fields and subject preserved.
let sp = parse_subject("just a plain subject").unwrap();
assert_eq!(sp.part_index, None);
assert_eq!(sp.part_total, None);
assert_eq!(sp.base_subject, "just a plain subject");