pgs_parse/pgs_file.rs
1use std::{fs::{File, Metadata}, io::{Read, Seek}};
2
3use crate::pgs_error::{Result, Error};
4
5/// A wrapper around a `File` that includes file metadata and provides methods to read data.
6///
7/// This struct provides methods to read bytes from a file and check if the end of the file has been reached.
8/// It also maintains file metadata for boundary checking.
9#[derive(Debug)]
10pub struct PgsFile {
11 file: File,
12 metadata: Metadata
13}
14
15impl PgsFile {
16 /// Creates a new `PgsFile` instance.
17 ///
18 /// # Arguments
19 /// * `file` - The `File` instance to be wrapped by `PgsFile`.
20 ///
21 /// # Returns
22 /// Returns a `Result` containing either a `PgsFile` instance or an `Error` if file metadata retrieval fails.
23 pub(crate) fn new(file: File) -> Result<Self> {
24 Ok(PgsFile {
25 metadata: file.metadata()?,
26 file
27 })
28 }
29
30 /// Returns a reference to the file metadata.
31 ///
32 /// # Returns
33 /// Returns a reference to the `Metadata` associated with the file.
34 pub fn metadata(&self) -> &Metadata {
35 &self.metadata
36 }
37
38 /// Reads bytes from the file into the provided buffer.
39 ///
40 /// # Arguments
41 /// * `buffer` - A mutable byte slice where the data will be read into.
42 ///
43 /// # Returns
44 /// Returns a `Result` indicating success or an `Error` if reading the bytes fails or if the read operation would
45 /// exceed the file's length.
46 pub fn read_bytes(&mut self, buffer: &mut [u8]) -> Result<()> {
47 if self.file.stream_position()? + buffer.len() as u64 > self.metadata.len() {
48 return Err(Error::File(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "end of file")));
49 }
50 self.file.read_exact(buffer)?;
51 Ok(())
52 }
53
54 /// Reads a fixed number of bytes from the file into a fixed-size array.
55 ///
56 /// # Type Parameters
57 /// * `N` - The number of bytes to read, defined as a constant generic parameter.
58 ///
59 /// # Returns
60 /// Returns a `Result` containing either a fixed-size array of bytes or an `Error` if reading the bytes fails or if
61 /// the read operation would exceed the file's length.
62 pub fn read_n_bytes<const N: usize>(&mut self) -> Result<[u8; N]> {
63 if self.file.stream_position()? + N as u64 > self.metadata.len() {
64 return Err(Error::File(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "end of file")));
65 }
66 let mut buffer: [u8; N] = [0; N];
67 self.file.read_exact(&mut buffer)?;
68 Ok(buffer)
69 }
70
71 /// Checks if the current position in the file is at or past the end of the file.
72 ///
73 /// # Returns
74 ///
75 /// Returns a `Result` containing a boolean value. `true` indicates that the end of the file has been reached or
76 /// exceeded, while `false` indicates that there is more data to read.
77 pub fn is_eof(&mut self) -> Result<bool> {
78 Ok(self.file.stream_position()? >= self.metadata.len())
79 }
80}