ass_core/parser/script/serialize.rs
1//! ASS source serialization for the [`Script`] container.
2//!
3//! Implements [`Script::to_ass_string`], which renders every section back to
4//! canonical ASS text, honoring the stored styles and events format lines when
5//! present.
6
7use alloc::string::String;
8
9use crate::parser::ast::Section;
10
11use super::Script;
12
13impl Script<'_> {
14 /// Convert script to ASS string representation
15 ///
16 /// Generates the complete ASS script with all sections in order.
17 /// Respects the stored format lines for styles and events if available.
18 ///
19 /// # Examples
20 ///
21 /// ```rust
22 /// # use ass_core::parser::Script;
23 /// let script = Script::parse("[Script Info]\nTitle: Test").unwrap();
24 /// let ass_string = script.to_ass_string();
25 /// assert!(ass_string.contains("[Script Info]"));
26 /// assert!(ass_string.contains("Title: Test"));
27 /// ```
28 #[must_use]
29 pub fn to_ass_string(&self) -> alloc::string::String {
30 let mut result = String::new();
31
32 for (idx, section) in self.sections.iter().enumerate() {
33 // Add newline between sections (but not before first)
34 if idx > 0 {
35 result.push('\n');
36 }
37
38 match section {
39 Section::ScriptInfo(info) => {
40 result.push_str(&info.to_ass_string());
41 }
42 Section::Styles(styles) => {
43 result.push_str("[V4+ Styles]\n");
44
45 // Add format line if available
46 if let Some(format) = &self.styles_format {
47 result.push_str("Format: ");
48 result.push_str(&format.join(", "));
49 result.push('\n');
50 }
51
52 // Add each style
53 for style in styles {
54 if let Some(format) = &self.styles_format {
55 result.push_str(&style.to_ass_string_with_format(format));
56 } else {
57 result.push_str(&style.to_ass_string());
58 }
59 result.push('\n');
60 }
61 }
62 Section::Events(events) => {
63 result.push_str("[Events]\n");
64
65 // Add format line if available
66 if let Some(format) = &self.events_format {
67 result.push_str("Format: ");
68 result.push_str(&format.join(", "));
69 result.push('\n');
70 }
71
72 // Add each event
73 for event in events {
74 if let Some(format) = &self.events_format {
75 result.push_str(&event.to_ass_string_with_format(format));
76 } else {
77 result.push_str(&event.to_ass_string());
78 }
79 result.push('\n');
80 }
81 }
82 Section::Fonts(fonts) => {
83 result.push_str("[Fonts]\n");
84 for font in fonts {
85 result.push_str(&font.to_ass_string());
86 }
87 }
88 Section::Graphics(graphics) => {
89 result.push_str("[Graphics]\n");
90 for graphic in graphics {
91 result.push_str(&graphic.to_ass_string());
92 }
93 }
94 }
95 }
96
97 result
98 }
99}