use std::{fmt::Write, fs::{self, File, OpenOptions}, io::{BufRead, BufReader, BufWriter, Read, Write as OtherWrite}, ops::AddAssign, path::PathBuf, str::FromStr, time::Instant};
use chrono::{NaiveTime, TimeDelta};
use itertools::Itertools;
use std::io::Seek;
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about)]
struct Args {
file: std::path::PathBuf,
#[arg(short, long, default_value_t = 0, allow_hyphen_values(true))]
delta: i32,
#[arg(short, long)]
output: Option<String>
}
fn main() {
let args = Args::parse();
let mut input = File::open(args.file.clone()).unwrap();
let mut output = String::new();
process(&mut input, &mut output, args.delta);
if let Some(output_file_name) = args.output {
let full_file = output_file_name + ".srt";
fs::write(full_file, output).unwrap();
} else {
fs::write(&args.file, output).unwrap();
}
}
fn update_timestamp(s: &str, delta: i32) -> String {
let t = NaiveTime::parse_from_str(s.trim(), "%H:%M:%S,%3f")
.expect("Failed to parse timestamp");
let new_t = t.overflowing_add_signed(TimeDelta::milliseconds(delta as i64)).0;
new_t.format("%H:%M:%S,%3f").to_string()
}
fn process(input: &mut File, output: &mut String, delta: i32) {
let mut reader = BufReader::new(input);
let mut temp = String::with_capacity(30);
'outer: loop {
reader.read_line(output).unwrap();
temp.clear();
reader.read_line(&mut temp).unwrap();
let (start, end) = temp.trim().split_once("-->").unwrap();
let (start, end) = (update_timestamp(start, delta), update_timestamp(end, delta));
output.write_fmt(format_args!("{start} --> {end}\n")).unwrap();
while &temp != "\n" {
temp.clear();
let status = reader.read_line(&mut temp).unwrap();
if status == 0 {break 'outer;}
output.push_str(&temp);
}
}
}
#[cfg(test)]
mod tests {
use crate::update_timestamp;
use super::*;
#[test]
fn test_timestamp_update() {
assert_eq!(update_timestamp(&"00:00:24,000", 1), String::from("00:00:24,001"));
assert_eq!(update_timestamp(&"00:00:24,000", 1001), String::from("00:00:25,001"));
assert_eq!(update_timestamp(&"00:00:24,000", 60000), String::from("00:01:24,000"));
}
#[test]
fn test_consitency() {
let mut input = File::open("./test.srt").unwrap();
let mut og = String::new();
input.read_to_string(&mut og).unwrap();
input.rewind().unwrap();
let mut output = String::new();
process(&mut input, &mut output, 0);
assert_eq!(og, output);
input.rewind().unwrap();
output.clear();
process(&mut input, &mut output, 123456);
fs::write("temp.srt", &output).unwrap();
let mut input2 = File::open("./temp.srt").unwrap();
output.clear();
process(&mut input2, &mut output, -123456);
drop(input2);
fs::remove_file(PathBuf::from("./temp.srt")).unwrap();
assert_eq!(og, output);
}
}