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
31pub struct IsoCursor<DATA: Seek> {
32    pub data: DATA,
33    pub sector_size: usize,
34}
35
36io_transform! {
37
38impl<DATA: Read + Seek> Read for IsoCursor<DATA> {
39    async fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
40        self.data.read(buf).await
41    }
42
43    async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
44        self.data.read_exact(buf).await
45    }
46}
47
48impl<DATA: Seek> Seek for IsoCursor<DATA> {
49    async fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
50        self.data.seek(pos).await
51    }
52
53    async fn stream_position(&mut self) -> Result<u64> {
54        self.data.stream_position().await
55    }
56
57    async fn seek_relative(&mut self, offset: i64) -> Result<()> {
58        self.data.seek_relative(offset).await
59    }
60}
61
62impl<DATA: Seek> IsoCursor<DATA> {
63    pub fn new(data: DATA, sector_size: usize) -> Self {
64        Self { data, sector_size }
65    }
66
67    pub async fn pad_align_sector(&mut self) -> Result<LogicalSector> {
68        let stream_pos = self.stream_position().await?;
69        let sector_size_minus_one = self.sector_size as u64 - 1;
70        let aligned_pos = (stream_pos + sector_size_minus_one) & !sector_size_minus_one;
71        if aligned_pos != stream_pos {
72            self.seek(SeekFrom::Start(aligned_pos)).await?;
73        }
74        Ok(LogicalSector(
75            (aligned_pos / self.sector_size as u64) as usize,
76        ))
77    }
78
79    pub async fn seek_sector(&mut self, sector: LogicalSector) -> Result<u64> {
80        self.seek(SeekFrom::Start(sector.0 as u64 * self.sector_size as u64)).await
81    }
82}
83
84impl<DATA: Write + Seek> Write for IsoCursor<DATA> {
85    async fn write(&mut self, buf: &[u8]) -> Result<usize> {
86        self.data.write(buf).await
87    }
88
89    async fn flush(&mut self) -> Result<()> {
90        self.data.flush().await
91    }
92
93    async fn write_all(&mut self, buf: &[u8]) -> Result<()> {
94        self.data.write_all(buf).await
95    }
96}
97
98} // io_transform!
99
100impl<DATA: Seek> fmt::Debug for IsoCursor<DATA> {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        f.debug_struct("Cursor").finish()
103    }
104}