1use serde::Deserialize;
7use serde::Serialize;
8
9use std::fmt::Display;
10use std::str;
11use time::format_description::BorrowedFormatItem;
12use time::macros::format_description;
13
14use crate::error;
15use time::Time;
16
17use super::ssa::SSA;
18use super::vtt::{VTTLine, VTT};
19
20const TIME_FORMAT: &[BorrowedFormatItem] =
21 format_description!("[hour]:[minute]:[second],[subsecond digits:3]");
22
23#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
36pub struct SRT {
37 pub lines: Vec<SRTLine>,
38}
39
40#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
44pub struct SRTLine {
45 pub sequence_number: u32,
46 pub start: Time,
47 pub end: Time,
48 pub text: String,
49}
50
51impl SRT {
52 pub fn parse<S: AsRef<str>>(content: S) -> Result<SRT, SRTError> {
54 let mut line_num = 0;
55
56 let mut blocks = vec![vec![]];
57 for line in content.as_ref().lines() {
58 if line.trim().is_empty() {
59 if !blocks.last().unwrap().is_empty() {
60 blocks.push(vec![])
61 }
62 } else {
63 blocks.last_mut().unwrap().push(line)
64 }
65 }
66 if blocks.last().is_some_and(|b| b.is_empty()) {
67 blocks.remove(blocks.len() - 1);
68 }
69
70 let mut lines = vec![];
71 for block in blocks {
72 line_num += 1;
73
74 let mut block_lines = block.into_iter();
75
76 let sequence_number = block_lines
78 .next()
79 .ok_or(SRTError::new(
80 SRTErrorKind::Parse("invalid sequence number".to_string()),
81 line_num,
82 ))?
83 .trim()
84 .parse::<u32>()
85 .map_err(|e| SRTError::new(SRTErrorKind::Parse(e.to_string()), line_num))?;
86 line_num += 1;
87 let (start, end) = {
89 let (start, end) = block_lines
90 .next()
91 .ok_or(SRTError::new(
92 SRTErrorKind::Parse("invalid time range".to_string()),
93 line_num,
94 ))?
95 .split_once("-->")
96 .ok_or(SRTError::new(
97 SRTErrorKind::Parse("invalid time range".to_string()),
98 line_num,
99 ))?;
100 let start_time = Time::parse(start.trim(), TIME_FORMAT)
101 .map_err(|e| SRTError::new(SRTErrorKind::Parse(e.to_string()), line_num))?;
102 let end_time = Time::parse(end.trim(), TIME_FORMAT)
103 .map_err(|e| SRTError::new(SRTErrorKind::Parse(e.to_string()), line_num))?;
104 (start_time, end_time)
105 };
106 line_num += 1;
107 line_num += block_lines.len();
108 let text = block_lines.collect::<Vec<&str>>().join("\r\n");
110
111 lines.push(SRTLine {
112 sequence_number,
113 start,
114 end,
115 text,
116 })
117 }
118
119 Ok(SRT { lines })
120 }
121
122 pub fn to_ssa(&self) -> SSA {
124 self.to_vtt().to_ssa()
125 }
126 pub fn to_vtt(&self) -> VTT {
128 VTT {
129 regions: vec![],
130 styles: vec![],
131 lines: self
132 .lines
133 .iter()
134 .map(|l| VTTLine {
135 identifier: Some(l.sequence_number.to_string()),
136 start: l.start,
137 end: l.end,
138 text: l.text.replace("\r\n", "\n"),
139 ..Default::default()
140 })
141 .collect(),
142 }
143 }
144}
145
146impl Display for SRT {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 let mut blocks = vec![];
149
150 for line in &self.lines {
151 let mut block = vec![];
152
153 block.push(line.sequence_number.to_string());
154 block.push(format!(
155 "{} --> {}",
156 line.start.format(TIME_FORMAT).unwrap(),
157 line.end.format(TIME_FORMAT).unwrap()
158 ));
159 block.push(line.text.clone());
160
161 blocks.push(block)
162 }
163
164 write!(
165 f,
166 "{}",
167 blocks
168 .into_iter()
169 .map(|b| b.join("\r\n"))
170 .collect::<Vec<String>>()
171 .join("\r\n\r\n")
172 )
173 }
174}
175
176error! {
177 SRTError => SRTErrorKind {
178 Parse(String),
179 }
180}