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}