use self::errors::*;
use crate::errors::Result as SubtitleParserResult;
use crate::timetypes::{TimePoint, TimeSpan};
use crate::{SubtitleEntry, SubtitleFileInterface, SubtitleFormat};
use failure::ResultExt;
use vobsub;
#[allow(missing_docs)]
pub mod errors {
use vobsub;
define_error!(Error, ErrorKind);
#[derive(Debug, Fail)]
pub enum ErrorKind {
VobSubError { cause: vobsub::ErrorKind },
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::VobSubError { cause } => writeln!(f, "VobSub error: {}", cause),
}
}
}
}
#[derive(Debug, Clone)]
pub struct VobFile {
data: Vec<u8>,
lines: Vec<VobSubSubtitle>,
}
#[derive(Debug, Clone)]
struct VobSubSubtitle {
timespan: TimeSpan,
}
impl VobFile {
pub fn parse(b: &[u8]) -> SubtitleParserResult<Self> {
let lines = vobsub::subtitles(b)
.map(|sub_res| -> vobsub::Result<VobSubSubtitle> {
let sub = sub_res?;
Ok(VobSubSubtitle {
timespan: TimeSpan {
start: TimePoint::from_msecs((sub.start_time() * 1000.0) as i64),
end: TimePoint::from_msecs((sub.end_time() * 1000.0) as i64),
},
})
})
.collect::<vobsub::Result<Vec<VobSubSubtitle>>>()
.map_err(|e| ErrorKind::VobSubError {
cause: vobsub::ErrorKind::from(e),
})
.with_context(|_| crate::errors::ErrorKind::ParsingError)?;
Ok(VobFile {
data: b.to_vec(),
lines: lines,
})
}
}
impl SubtitleFileInterface for VobFile {
fn get_subtitle_entries(&self) -> SubtitleParserResult<Vec<SubtitleEntry>> {
Ok(self
.lines
.iter()
.map(|vsub| SubtitleEntry {
timespan: vsub.timespan,
line: None,
})
.collect())
}
fn update_subtitle_entries(&mut self, _: &[SubtitleEntry]) -> SubtitleParserResult<()> {
Err(crate::errors::ErrorKind::UpdatingEntriesNotSupported {
format: SubtitleFormat::VobSubSub,
}
.into())
}
fn to_data(&self) -> SubtitleParserResult<Vec<u8>> {
Ok(self.data.clone())
}
}