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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
29struct _LogicalBlock(pub usize);
30
31pub struct IsoCursor<DATA: Seek> {
33 pub data: DATA,
35 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 pub fn new(data: DATA, sector_size: usize) -> Self {
72 Self { data, sector_size }
73 }
74
75 pub fn into_inner(self) -> DATA {
77 self.data
78 }
79
80 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 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} impl<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}