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}