initial
This commit is contained in:
+133
@@ -0,0 +1,133 @@
|
||||
#[macro_use]
|
||||
extern crate failure;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
|
||||
use regex::Regex;
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::io;
|
||||
use std::str::FromStr;
|
||||
|
||||
fn main() {
|
||||
let argv =
|
||||
clap::App::new("srtune")
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.arg(clap::Arg::with_name("input")
|
||||
.value_name("INFILE")
|
||||
.required(true)
|
||||
.index(1)
|
||||
.help("Input file"),
|
||||
)
|
||||
.arg(clap::Arg::with_name("output")
|
||||
.value_name("OUTFILE")
|
||||
.required(true)
|
||||
.index(2)
|
||||
.help("Output file"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let inf = argv.value_of("input").unwrap();
|
||||
let outf = argv.value_of("output").unwrap();
|
||||
|
||||
let source = read_file(inf);
|
||||
|
||||
let mut lines = source.lines();
|
||||
|
||||
let mut subs = vec![];
|
||||
|
||||
while let Some(x) = lines.next() {
|
||||
if x.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 236
|
||||
// 00:18:01,755 --> 00:18:03,774
|
||||
// (掃除機の音)
|
||||
// う~ん…。
|
||||
if let Ok(num) = u32::from_str(x) {
|
||||
// println!("Entry {}", num);
|
||||
let datesrow = lines.next().expect("expected date row");
|
||||
if datesrow.contains(" --> ") {
|
||||
let mut halves = datesrow.split(" --> ");
|
||||
let start = parse_time(halves.next().expect("expected two halves")).expect("invalid time");
|
||||
let end = parse_time(halves.next().expect("expected two halves")).expect("invalid time");
|
||||
|
||||
//println!("{} -> {} secs", start, end);
|
||||
|
||||
let mut text = vec![];
|
||||
while let Some(x) = lines.next() {
|
||||
if x.is_empty() {
|
||||
break;
|
||||
}
|
||||
text.push(x);
|
||||
}
|
||||
|
||||
let text = text.join("\n");
|
||||
|
||||
//println!("Lines: {}", text);
|
||||
|
||||
subs.push(Subtitle {
|
||||
num, start, end, text
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Parsed {} entries.", subs.len());
|
||||
|
||||
//println!("{:?}", parsed);
|
||||
}
|
||||
|
||||
struct Subtitle {
|
||||
num : u32,
|
||||
start: f32,
|
||||
end: f32,
|
||||
text: String
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref DATE_RE: Regex = Regex::new(r"(\d+):(\d+):(\d+),(\d+)").unwrap();
|
||||
}
|
||||
|
||||
fn parse_time(time : &str) -> Result<f32, ()> {
|
||||
// 00:18:01,755
|
||||
match DATE_RE.captures(time) {
|
||||
Some(caps) => {
|
||||
Ok(f32::from_str(caps.get(1).unwrap().as_str()).unwrap()*3600f32 +
|
||||
f32::from_str(caps.get(2).unwrap().as_str()).unwrap()*60f32 +
|
||||
f32::from_str(caps.get(3).unwrap().as_str()).unwrap()+
|
||||
f32::from_str(caps.get(4).unwrap().as_str()).unwrap() * 0.001f32)
|
||||
},
|
||||
None => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a file to string; panics on error.
|
||||
fn read_file<P: AsRef<Path>>(path: P) -> String {
|
||||
let path = path.as_ref();
|
||||
let mut file = File::open(path).expect(&format!("Could not open file: {:?}", path));
|
||||
|
||||
let mut buf = String::with_capacity(file_len(&mut file).expect("Er testing file len"));
|
||||
file.read_to_string(&mut buf)
|
||||
.expect(&format!("Error reading file {:?}", path));
|
||||
buf
|
||||
}
|
||||
|
||||
fn file_len(file : &mut File) -> io::Result<usize> {
|
||||
let old_pos = file.seek(SeekFrom::Current(0))?;
|
||||
let len = file.seek(SeekFrom::End(0))?;
|
||||
|
||||
// Avoid seeking a third time when we were already at the end of the
|
||||
// stream. The branch is usually way cheaper than a seek operation.
|
||||
if old_pos != len {
|
||||
file.seek(SeekFrom::Start(old_pos))?;
|
||||
}
|
||||
|
||||
Ok(len as usize)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user