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
use std::{fs::{File, Metadata}, io::{Read, Seek}};
use crate::pgs_error::{Result, Error};
/// A wrapper around a `File` that includes file metadata and provides methods to read data.
///
/// This struct provides methods to read bytes from a file and check if the end of the file has been reached.
/// It also maintains file metadata for boundary checking.
#[derive(Debug)]
pub struct PgsFile {
file: File,
metadata: Metadata
}
impl PgsFile {
/// Creates a new `PgsFile` instance.
///
/// # Arguments
/// * `file` - The `File` instance to be wrapped by `PgsFile`.
///
/// # Returns
/// Returns a `Result` containing either a `PgsFile` instance or an `Error` if file metadata retrieval fails.
pub(crate) fn new(file: File) -> Result<Self> {
Ok(PgsFile {
metadata: file.metadata()?,
file
})
}
/// Returns a reference to the file metadata.
///
/// # Returns
/// Returns a reference to the `Metadata` associated with the file.
pub fn metadata(&self) -> &Metadata {
&self.metadata
}
/// Reads bytes from the file into the provided buffer.
///
/// # Arguments
/// * `buffer` - A mutable byte slice where the data will be read into.
///
/// # Returns
/// Returns a `Result` indicating success or an `Error` if reading the bytes fails or if the read operation would
/// exceed the file's length.
pub fn read_bytes(&mut self, buffer: &mut [u8]) -> Result<()> {
if self.file.stream_position()? + buffer.len() as u64 > self.metadata.len() {
return Err(Error::File(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "end of file")));
}
self.file.read_exact(buffer)?;
Ok(())
}
/// Reads a fixed number of bytes from the file into a fixed-size array.
///
/// # Type Parameters
/// * `N` - The number of bytes to read, defined as a constant generic parameter.
///
/// # Returns
/// Returns a `Result` containing either a fixed-size array of bytes or an `Error` if reading the bytes fails or if
/// the read operation would exceed the file's length.
pub fn read_n_bytes<const N: usize>(&mut self) -> Result<[u8; N]> {
if self.file.stream_position()? + N as u64 > self.metadata.len() {
return Err(Error::File(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "end of file")));
}
let mut buffer: [u8; N] = [0; N];
self.file.read_exact(&mut buffer)?;
Ok(buffer)
}
/// Checks if the current position in the file is at or past the end of the file.
///
/// # Returns
///
/// Returns a `Result` containing a boolean value. `true` indicates that the end of the file has been reached or
/// exceeded, while `false` indicates that there is more data to read.
pub fn is_eof(&mut self) -> Result<bool> {
Ok(self.file.stream_position()? >= self.metadata.len())
}
}