subx-cli 1.7.4

AI subtitle processing CLI tool, which automatically matches, renames, and converts subtitle files.
Documentation
//! ASS/SSA serializer.

use crate::Result;
use crate::core::formats::Subtitle;

use super::time::format_ass_time;

/// Serialize a [`Subtitle`] into a canonical ASS/SSA document.
///
/// The output uses the SubX canonical form: a single `[Script Info]`
/// header, a default `[V4+ Styles]` block, and an `[Events]` section
/// where each entry is emitted as a `Dialogue:` line with the default
/// style.
pub(super) fn serialize(subtitle: &Subtitle) -> Result<String> {
    let mut output = String::new();
    output.push_str("[Script Info]\n");
    output.push_str("; Script generated by SubX\n");
    output.push_str("ScriptType: v4.00+\n\n");
    output.push_str("[V4+ Styles]\n");
    output.push_str("Format: Name,Fontname,Fontsize,PrimaryColour,SecondaryColour,OutlineColour,BackColour,Bold,Italic,Underline,StrikeOut,ScaleX,ScaleY,Spacing,Angle,BorderStyle,Outline,Shadow,Alignment,MarginL,MarginR,MarginV,Encoding\n");
    output.push_str("Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1\n\n");
    output.push_str("[Events]\n");
    output.push_str("Format: Layer,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text\n");
    for entry in &subtitle.entries {
        let text = entry.text.replace('\n', "\\N");
        let start = format_ass_time(entry.start_time);
        let end = format_ass_time(entry.end_time);
        output.push_str(&format!(
            "Dialogue: 0,{},{},Default,,0000,0000,0000,,{}\n",
            start, end, text
        ));
    }
    Ok(output)
}