ass_editor/formats/srt/
export.rs1use super::SrtFormat;
4use crate::core::{EditorDocument, EditorError};
5use crate::formats::{FormatExporter, FormatInfo, FormatOptions, FormatResult};
6use std::io::Write;
7
8impl FormatExporter for SrtFormat {
9 fn format_info(&self) -> &FormatInfo {
10 &self.info
11 }
12
13 fn export_to_writer(
14 &self,
15 document: &EditorDocument,
16 writer: &mut dyn Write,
17 options: &FormatOptions,
18 ) -> Result<FormatResult, EditorError> {
19 let events = document.parse_script_with(|script| {
21 if let Some(ass_core::parser::ast::Section::Events(events)) =
23 script.find_section(ass_core::parser::ast::SectionType::Events)
24 {
25 events
27 .iter()
28 .map(|event| {
29 (
30 event.event_type,
31 event.start.to_string(),
32 event.end.to_string(),
33 event.text.to_string(),
34 )
35 })
36 .collect::<Vec<_>>()
37 } else {
38 Vec::new()
39 }
40 })?;
41
42 let mut srt_content = String::new();
43 let mut subtitle_num = 1;
44 let mut warnings = Vec::new();
45
46 for (event_type, start, end, text) in &events {
47 if event_type.as_str() != "Dialogue" {
49 continue;
50 }
51
52 let start_time = match Self::format_srt_time(start) {
54 Ok(time) => time,
55 Err(e) => {
56 warnings.push(format!(
57 "Invalid start time for subtitle {subtitle_num}: {e}"
58 ));
59 continue;
60 }
61 };
62
63 let end_time = match Self::format_srt_time(end) {
64 Ok(time) => time,
65 Err(e) => {
66 warnings.push(format!("Invalid end time for subtitle {subtitle_num}: {e}"));
67 continue;
68 }
69 };
70
71 let mut text = text.clone();
73
74 text = text.replace("\\N", "\n");
76 text = text.replace("\\n", "\n");
77
78 text = Self::convert_ass_to_srt_styling(&text);
80
81 srt_content.push_str(&format!("{subtitle_num}\n"));
83 srt_content.push_str(&format!("{start_time} --> {end_time}\n"));
84 srt_content.push_str(&text);
85 srt_content.push_str("\n\n");
86
87 subtitle_num += 1;
88 }
89
90 let bytes = if options.encoding.eq_ignore_ascii_case("UTF-8") {
92 srt_content.into_bytes()
93 } else {
94 warnings.push(format!(
95 "Encoding '{}' not supported, using UTF-8 instead",
96 options.encoding
97 ));
98 srt_content.into_bytes()
99 };
100
101 writer
102 .write_all(&bytes)
103 .map_err(|e| EditorError::IoError(format!("Failed to write SRT content: {e}")))?;
104
105 let mut result = FormatResult::success(subtitle_num - 1)
106 .with_metadata("exported_format".to_string(), "SRT".to_string())
107 .with_metadata(
108 "subtitles_exported".to_string(),
109 (subtitle_num - 1).to_string(),
110 );
111
112 if !warnings.is_empty() {
113 result = result.with_warnings(warnings);
114 }
115
116 Ok(result)
117 }
118}