subrip/
lib.rs

1#![deny(missing_docs)]
2/*!
3  A toolkit for parsing, authoring, and working with .srt files.
4*/
5use std::{fmt, time::Duration};
6
7pub use parser::parse;
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11mod parser;
12pub mod utils;
13
14#[derive(Debug)]
15#[non_exhaustive]
16/// Error type for crate
17pub enum Error {
18    /// Parsing did not make it through the entire file.
19    ///
20    /// Existing tools seem pretty forgiving with parsing SRT files,
21    /// so you may occasionally find junk at the bottom of the file.
22    ///
23    /// This error includes whatever we could parse, as well as the index
24    /// where parsing began to fail.
25    ParseError(Vec<Subtitle>, usize),
26}
27
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29#[derive(Debug, Clone, PartialEq)]
30/// A single Subtitle record with timing and text information.
31///
32/// the [`std::fmt::Display`] impl for this type will reproduce
33/// the SRT formatted text.
34pub struct Subtitle {
35    /// The index within the SRT file. The spec says this should be a number
36    /// that increases through the file, but this is should not be relied upon.
37    /// see [`utils::out_of_order_subs`] for more information.
38    pub idx: u32,
39    /// The timestamp where this subtitle should appear on screen.
40    pub start: Duration,
41    /// The timestamp where this subtitle should be removed from the screen.
42    pub end: Duration,
43    /// The contents of the subtitle text.
44    ///
45    /// This may contain some rudimetary formatting tags `<b>...</b>` which we
46    /// currently make no effort to parse.
47    pub text: String,
48}
49
50fn fmt_duration_srt(d: Duration, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51    let millis = d.as_millis() as u64;
52    let secs = millis / 1000;
53    let millis = millis % 1000;
54    let minutes = secs / 60;
55    let secs = secs % 60;
56    let hours = minutes / 60;
57    let minutes = minutes % 60;
58    write!(f, "{}:{}:{},{}", hours, minutes, secs, millis)
59}
60
61impl fmt::Display for Subtitle {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        writeln!(f, "{}", self.idx)?;
64        fmt_duration_srt(self.start, f)?;
65        write!(f, " --> ")?;
66        fmt_duration_srt(self.end, f)?;
67        writeln!(f)?;
68        writeln!(f, "{}", self.text)?;
69        writeln!(f)
70    }
71}