1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.


use self::errors::*;
use {SubtitleEntry, SubtitleFile, SubtitleFormat};
use errors::Result as SubtitleParserResult;
use timetypes::{TimePoint, TimeSpan};

use vobsub;

/// `.sub` `VobSub`-parser-specific errors
#[allow(missing_docs)]
pub mod errors {
    use vobsub;

    // see https://docs.rs/error-chain
    error_chain! {
        foreign_links {
            VobSubError(vobsub::Error)
            /// Error from the `vobsub` crate
            ;
        }
    }
}


#[derive(Debug, Clone)]
/// Represents a `.sub` (`VobSub`) file.
pub struct VobFile {
    /// Saves the file data.
    data: Vec<u8>,

    /// The (with vobsub) extracted subtitle lines.
    lines: Vec<VobSubSubtitle>,
}

#[derive(Debug, Clone)]
/// Represents a line in a `VobSub` `.sub` file.
struct VobSubSubtitle {
    timespan: TimeSpan,
}

impl VobFile {
    /// Parse contents of a `VobSub` `.sub` file to `VobFile`.
    pub fn parse(b: &[u8]) -> SubtitleParserResult<Self> {
        let lines = vobsub::subtitles(b)
            .map(|sub_res| -> vobsub::Result<VobSubSubtitle> {
                let sub = sub_res?;

                // only extract the timestamps, discard the big image data
                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(Error::from)?;

        Ok(VobFile {
            data: b.to_vec(),
            lines: lines,
        })
    }
}

impl SubtitleFile 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(
            ::errors::ErrorKind::UpdatingEntriesNotSupported(SubtitleFormat::VobSubSub).into(),
        )
    }

    fn to_data(&self) -> SubtitleParserResult<Vec<u8>> {
        Ok(self.data.clone())
    }
}