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> {
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} impl<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}