Skip to main content

hadris_iso/
io.rs

1use core::{
2    fmt,
3    ops::{Add, AddAssign},
4};
5
6pub use super::super::{Parsable, Read, ReadExt, Seek, Writable, Write};
7pub use hadris_io::{Error, ErrorKind, Result, SeekFrom, try_io_result_option};
8
9/// A Logical Sector, size has to be 2^n and > 2048
10#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
11pub struct LogicalSector(pub usize);
12
13impl Add<usize> for LogicalSector {
14    type Output = Self;
15
16    fn add(self, rhs: usize) -> Self::Output {
17        Self(self.0 + rhs)
18    }
19}
20
21impl AddAssign<usize> for LogicalSector {
22    fn add_assign(&mut self, rhs: usize) {
23        self.0 += rhs;
24    }
25}
26
27/// A Logical Sector, size has to be 2^n and > 512
28#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
29struct _LogicalBlock(pub usize);
30
31/// Represents IsoCursor.
32pub struct IsoCursor<DATA: Seek> {
33    /// The `data` field.
34    pub data: DATA,
35    /// The `sector_size` field.
36    pub sector_size: usize,
37}
38
39io_transform! {
40
41impl<DATA: Read + Seek> Read for IsoCursor<DATA> {
42    type Error = <DATA as Read>::Error;
43
44    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
45        self.data.read(buf).await
46    }
47
48    async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
49        self.data.read_exact(buf).await
50    }
51}
52
53impl<DATA: Seek> Seek for IsoCursor<DATA> {
54    type Error = DATA::Error;
55
56    async fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
57        self.data.seek(pos).await
58    }
59
60    async fn stream_position(&mut self) -> Result<u64, Self::Error> {
61        self.data.stream_position().await
62    }
63
64    async fn seek_relative(&mut self, offset: i64) -> Result<(), Self::Error> {
65        self.data.seek_relative(offset).await
66    }
67}
68
69impl<DATA: Seek> IsoCursor<DATA> {
70    /// Performs the `new` operation.
71    pub fn new(data: DATA, sector_size: usize) -> Self {
72        Self { data, sector_size }
73    }
74
75    /// Consumes the cursor and returns its underlying data source.
76    pub fn into_inner(self) -> DATA {
77        self.data
78    }
79
80    /// Performs the `pad_align_sector` operation.
81    pub async fn pad_align_sector(&mut self) -> Result<LogicalSector> {
82        let stream_pos = self.stream_position().await.map_err(Error::erase)?;
83        let sector_size_minus_one = self.sector_size as u64 - 1;
84        let aligned_pos = (stream_pos + sector_size_minus_one) & !sector_size_minus_one;
85        if aligned_pos != stream_pos {
86            self.seek(SeekFrom::Start(aligned_pos))
87                .await
88                .map_err(Error::erase)?;
89        }
90        Ok(LogicalSector(
91            (aligned_pos / self.sector_size as u64) as usize,
92        ))
93    }
94
95    /// Performs the `seek_sector` operation.
96    pub async fn seek_sector(&mut self, sector: LogicalSector) -> Result<u64> {
97        self.seek(SeekFrom::Start(sector.0 as u64 * self.sector_size as u64))
98            .await
99            .map_err(Error::erase)
100    }
101}
102
103impl<DATA: Write + Seek> Write for IsoCursor<DATA> {
104    type Error = <DATA as Write>::Error;
105
106    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
107        self.data.write(buf).await
108    }
109
110    async fn flush(&mut self) -> Result<(), Self::Error> {
111        self.data.flush().await
112    }
113
114    async fn write_all(&mut self, buf: &[u8]) -> Result<()> {
115        self.data.write_all(buf).await
116    }
117}
118
119} // io_transform!
120
121impl<DATA: Seek> fmt::Debug for IsoCursor<DATA> {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        f.debug_struct("Cursor").finish()
124    }
125}