pgs_parse/pgs_parser.rs
1//! This module defines the `PgsParser` struct and its associated methods for parsing and handling PGS (Presentation Graphics Stream) files.
2
3use log::{debug, error, trace};
4
5use crate::{pgs_reader::PgsReader, pgs_segment::PgsSegment, Error, PgsDisplaySet, PgsFile, PgsOdsSegment, PgsPcsSegment, PgsPdsSegment, PgsSegmentHeader, PgsSegmentType, PgsWdsSegment, Result};
6
7/// A parser for PGS files.
8///
9/// This struct is responsible for parsing PGS files into segments and creating display sets from those segments.
10///
11/// # Fields
12/// - `sup_file_path`: The path to the SUP file to be parsed.
13/// - `segments`: A vector storing the parsed PGS segments.
14/// - `display_sets`: A vector of display sets created from the parsed segments.
15#[derive(Debug)]
16pub struct PgsParser<'a> {
17 sup_file_path: &'a str,
18 segments: Vec<PgsSegment>,
19 display_sets: Vec<PgsDisplaySet>
20}
21
22impl<'a> PgsParser<'a> {
23 /// Creates a new `PgsParser` instance.
24 ///
25 /// # Arguments
26 /// * `sup_file_path` - The path to the SUP file to be parsed.
27 ///
28 /// # Returns
29 /// A new `PgsParser` instance with empty segments and display sets.
30 fn new(sup_file_path: &'a str) -> Self {
31 PgsParser {
32 segments: Vec::new(),
33 display_sets: Vec::new(),
34 sup_file_path
35 }
36 }
37
38 /// Returns a reference to the vector of display sets.
39 ///
40 /// # Returns
41 /// A reference to the `Vec<PgsDisplaySet>`.
42 pub fn get_display_sets(&self) -> &Vec<PgsDisplaySet> {
43 self.display_sets.as_ref()
44 }
45
46 /// Reads and parses a segment from the given file.
47 ///
48 /// # Arguments
49 /// * `file` - A mutable reference to the `PgsFile` from which to read the segment.
50 ///
51 /// # Returns
52 /// A `Result` containing either a `PgsSegment` or an `Error` if reading or parsing fails.
53 fn read_segment(&mut self, file: &mut PgsFile) -> Result<PgsSegment> {
54 let buffer = file.read_n_bytes::<13>()?;
55 let header = PgsSegmentHeader::from_data(&buffer)?;
56
57 let pg = header.segment_type;
58 if pg == PgsSegmentType::ERR {
59 return Err(Error::ReadInvalidSegment);
60 }
61
62 if header.segment_type == PgsSegmentType::END {
63 return Ok(PgsSegment::End);
64 }
65
66 let mut buffer = vec![0; header.segment_length as usize];
67 file.read_bytes(buffer.as_mut_slice())?;
68
69 let segment = match header.segment_type {
70 PgsSegmentType::PCS => {
71 PgsSegment::Pcs(PgsPcsSegment::from_data(header, &buffer)?)
72 },
73 PgsSegmentType::WDS => {
74 PgsSegment::Wds(PgsWdsSegment::from_data(header, &buffer)?)
75 },
76 PgsSegmentType::PDS => {
77 PgsSegment::Pds(PgsPdsSegment::from_data(header, &buffer)?)
78 },
79 PgsSegmentType::ODS => {
80 PgsSegment::Ods(PgsOdsSegment::from_data(header, &buffer)?)
81 },
82 _ => PgsSegment::End
83 };
84
85 Ok(segment)
86 }
87
88 /// Parses the PGS file and reads all segments.
89 ///
90 /// This method continuously reads segments from the file until the end of the file is reached.
91 ///
92 /// # Returns
93 /// A `Result` indicating success or failure of the parsing process.
94 fn parse_inner(&mut self) -> Result<()> {
95 let mut file = PgsReader::open(self.sup_file_path)?;
96 debug!("{:?}", file);
97
98 loop {
99 match self.read_segment(&mut file) {
100 Ok(segment) => {
101 trace!("{:?}", segment);
102 self.segments.push(segment);
103 if file.is_eof()? {
104 return Ok(());
105 }
106 },
107 Err(error) => {
108 error!("{:?}", error);
109 return Err(error)
110 }
111 }
112 }
113 }
114
115 /// Creates display sets from the parsed segments.
116 ///
117 /// This method processes the segments to construct display sets and adds them to the `display_sets` vector.
118 ///
119 /// # Returns
120 /// A `Result` indicating success or failure of the display set creation process.
121 fn create_display_sets(&mut self) -> Result<()> {
122 let mut ds = PgsDisplaySet::new();
123 self.segments.iter().for_each(|segment| {
124 match segment {
125 PgsSegment::Pcs(pcs) => ds.pcs = Some(pcs.clone()),
126 PgsSegment::Wds(wds) => ds.wds = Some(wds.clone()),
127 PgsSegment::Ods(ods) => ds.ods = Some(ods.clone()),
128 PgsSegment::Pds(pds) => ds.pds = Some(pds.clone()),
129 PgsSegment::End => {
130 self.display_sets.push(ds.clone());
131 ds.clean();
132 }
133 }
134 });
135
136 Ok(())
137 }
138
139 /// Parses a PGS file and creates display sets.
140 ///
141 /// # Arguments
142 /// * `sup_file_path` - The path to the SUP file to be parsed.
143 ///
144 /// # Returns
145 /// A `Result` containing either the `PgsParser` instance or an `Error` if the parsing fails.
146 pub fn parse(sup_file_path: &'a str) -> Result<PgsParser<'a>> {
147 let mut parser = PgsParser::new(sup_file_path);
148 parser.parse_inner()?;
149 parser.create_display_sets()?;
150 Ok(parser)
151 }
152}