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 seek_sector(&mut self, sector: LogicalSector) -> Result<u64> {
82 self.seek(SeekFrom::Start(sector.0 as u64 * self.sector_size as u64))
83 .await
84 .map_err(Error::erase)
85 }
86}
87
88impl<DATA: Write + Seek> IsoCursor<DATA> {
89 pub async fn pad_align_sector(&mut self) -> Result<LogicalSector> {
97 const ZEROES: [u8; 512] = [0u8; 512];
98 let stream_pos = self.stream_position().await.map_err(Error::erase)?;
99 let sector_size_minus_one = self.sector_size as u64 - 1;
100 let aligned_pos = (stream_pos + sector_size_minus_one) & !sector_size_minus_one;
101 let mut remaining = (aligned_pos - stream_pos) as usize;
102 while remaining > 0 {
103 let n = remaining.min(ZEROES.len());
104 self.write_all(&ZEROES[..n]).await.map_err(Error::erase)?;
105 remaining -= n;
106 }
107 Ok(LogicalSector(
108 (aligned_pos / self.sector_size as u64) as usize,
109 ))
110 }
111}
112
113impl<DATA: Write + Seek> Write for IsoCursor<DATA> {
114 type Error = <DATA as Write>::Error;
115
116 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
117 self.data.write(buf).await
118 }
119
120 async fn flush(&mut self) -> Result<(), Self::Error> {
121 self.data.flush().await
122 }
123
124 async fn write_all(&mut self, buf: &[u8]) -> Result<()> {
125 self.data.write_all(buf).await
126 }
127}
128
129} impl<DATA: Seek> fmt::Debug for IsoCursor<DATA> {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 f.debug_struct("Cursor").finish()
134 }
135}