Skip to content

Commit

Permalink
Removes Read implementation from ClustersReader
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon committed Sep 28, 2024
1 parent b3513b2 commit 11c0274
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 76 deletions.
96 changes: 54 additions & 42 deletions src/cluster.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::disk::DiskPartition;
use crate::ExFat;
use std::cmp::min;
use std::io::{Read, Seek, SeekFrom};
use std::io::{Seek, SeekFrom};
use std::sync::Arc;
use thiserror::Error;

/// A cluster reader to read all data in a cluster chain.
pub(crate) struct ClustersReader<P: DiskPartition> {
/// Struct to read all data in a cluster chain.
pub struct ClustersReader<P: DiskPartition> {
exfat: Arc<ExFat<P>>,
chain: Vec<usize>,
data_length: u64,
Expand Down Expand Up @@ -72,6 +72,57 @@ impl<P: DiskPartition> ClustersReader<P> {
pub fn cluster(&self) -> usize {
self.chain[(self.offset / self.exfat.params.cluster_size()) as usize]
}

pub fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
use std::io::{Error, ErrorKind};

// Check if the actual read is required.
if buf.is_empty() || self.offset == self.data_length {
return Ok(0);
}

// Get remaining data in the current cluster.
let cluster_size = self.exfat.params.cluster_size();
let cluster_remaining = cluster_size - self.offset % cluster_size;
let remaining = min(cluster_remaining, self.data_length - self.offset);

// Get the offset in the partition.
let cluster = self.chain[(self.offset / cluster_size) as usize];
let offset = match self.exfat.params.cluster_offset(cluster) {
Some(v) => v + self.offset % cluster_size,
None => {
return Err(Error::new(
ErrorKind::Other,
format!("cluster #{cluster} is not available"),
));
}
};

// Read image.
let amount = min(buf.len(), remaining as usize);

if let Err(e) = self.exfat.partition.read_exact(offset, &mut buf[..amount]) {
return Err(Error::new(ErrorKind::Other, Box::new(e)));
}

self.offset += amount as u64;

Ok(amount)
}

pub fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), std::io::Error> {
while !buf.is_empty() {
let n = self.read(buf)?;

if n == 0 {
return Err(std::io::Error::from(std::io::ErrorKind::UnexpectedEof));
}

buf = &mut buf[n..];
}

Ok(())
}
}

impl<P: DiskPartition> Seek for ClustersReader<P> {
Expand Down Expand Up @@ -113,45 +164,6 @@ impl<P: DiskPartition> Seek for ClustersReader<P> {
}
}

impl<P: DiskPartition> Read for ClustersReader<P> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
use std::io::{Error, ErrorKind};

// Check if the actual read is required.
if buf.is_empty() || self.offset == self.data_length {
return Ok(0);
}

// Get remaining data in the current cluster.
let cluster_size = self.exfat.params.cluster_size();
let cluster_remaining = cluster_size - self.offset % cluster_size;
let remaining = min(cluster_remaining, self.data_length - self.offset);

// Get the offset in the partition.
let cluster = self.chain[(self.offset / cluster_size) as usize];
let offset = match self.exfat.params.cluster_offset(cluster) {
Some(v) => v + self.offset % cluster_size,
None => {
return Err(Error::new(
ErrorKind::Other,
format!("cluster #{cluster} is not available"),
));
}
};

// Read image.
let amount = min(buf.len(), remaining as usize);

if let Err(e) = self.exfat.partition.read_exact(offset, &mut buf[..amount]) {
return Err(Error::new(ErrorKind::Other, Box::new(e)));
}

self.offset += amount as u64;

Ok(amount)
}
}

/// Represents an error for [`new()`][ClustersReader::new()].
#[derive(Debug, Error)]
pub enum NewError {
Expand Down
2 changes: 1 addition & 1 deletion src/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::ExFat;
use std::sync::Arc;
use thiserror::Error;

/// Represents a directory in the exFAT.
/// Represents a directory in an exFAT filesystem.
pub struct Directory<P: DiskPartition> {
exfat: Arc<ExFat<P>>,
name: String,
Expand Down
1 change: 0 additions & 1 deletion src/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::FileAttributes;
use byteorder::{ByteOrder, LE};
use std::cmp::min;
use std::fmt::{Display, Formatter};
use std::io::Read;
use thiserror::Error;

/// A struct to read directory entries.
Expand Down
30 changes: 1 addition & 29 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::entries::StreamEntry;
use crate::timestamp::Timestamps;
use crate::ExFat;
use std::io::{empty, Empty};
use std::io::{IoSliceMut, Read, Seek, SeekFrom};
use std::io::{Read, Seek, SeekFrom};
use std::sync::Arc;
use thiserror::Error;

Expand Down Expand Up @@ -98,34 +98,6 @@ impl<P: DiskPartition> Read for File<P> {
Reader::Empty(r) => r.read(buf),
}
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> std::io::Result<usize> {
match &mut self.reader {
Reader::Cluster(r) => r.read_vectored(bufs),
Reader::Empty(r) => r.read_vectored(bufs),
}
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
match &mut self.reader {
Reader::Cluster(r) => r.read_to_end(buf),
Reader::Empty(r) => r.read_to_end(buf),
}
}

fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
match &mut self.reader {
Reader::Cluster(r) => r.read_to_string(buf),
Reader::Empty(r) => r.read_to_string(buf),
}
}

fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
match &mut self.reader {
Reader::Cluster(r) => r.read_exact(buf),
Reader::Empty(r) => r.read_exact(buf),
}
}
}

/// Encapsulate the either [`ClustersReader`] or [`Empty`].
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use core::fmt::Debug;
use std::sync::Arc;
use thiserror::Error;

pub mod cluster;
mod cluster;
mod directory;
mod disk;
pub mod entries;
Expand Down Expand Up @@ -293,8 +293,8 @@ impl FileAttributes {
}
}

/// Contains objects for the opened exFAT.
pub(crate) struct ExFat<P: DiskPartition> {
/// Contains objects for opened exFAT filesystem.
struct ExFat<P: DiskPartition> {
partition: P,
params: Params,
fat: Fat,
Expand Down

0 comments on commit 11c0274

Please sign in to comment.