#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use super::types::layout::DirectoryLayout;
pub const OPTICAL_SECTOR_SIZE: usize = 2048;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SessionInfo {
pub session_number: u16,
pub start_sector: u32,
pub end_sector: u32,
pub is_last_session: bool,
}
impl SessionInfo {
pub const fn new(session_number: u16, start_sector: u32, end_sector: u32) -> Self {
Self {
session_number,
start_sector,
end_sector,
is_last_session: false,
}
}
#[inline]
pub const fn sector_count(&self) -> u32 {
self.end_sector - self.start_sector + 1
}
#[inline]
pub const fn byte_size(&self) -> u64 {
self.sector_count() as u64 * OPTICAL_SECTOR_SIZE as u64
}
pub const fn as_last(mut self) -> Self {
self.is_last_session = true;
self
}
}
impl core::fmt::Display for SessionInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"session {} (sectors {}-{})",
self.session_number, self.start_sector, self.end_sector
)
}
}
impl Default for SessionInfo {
fn default() -> Self {
Self {
session_number: 1,
start_sector: 0,
end_sector: 0,
is_last_session: true,
}
}
}
#[cfg(feature = "alloc")]
pub trait OpticalMetadataWriter {
type Options;
type Error;
fn write_metadata<W: hadris_io::Write + hadris_io::Seek>(
writer: &mut W,
root: &DirectoryLayout,
options: &Self::Options,
) -> Result<(), Self::Error>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum OpticalMediaType {
#[default]
CdRom = 0,
CdR = 1,
CdRw = 2,
DvdRom = 3,
DvdR = 4,
DvdPlusR = 5,
DvdRw = 6,
DvdPlusRw = 7,
DvdRam = 8,
BdRom = 9,
BdR = 10,
BdRe = 11,
}
impl core::fmt::Display for OpticalMediaType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::CdRom => write!(f, "CD-ROM"),
Self::CdR => write!(f, "CD-R"),
Self::CdRw => write!(f, "CD-RW"),
Self::DvdRom => write!(f, "DVD-ROM"),
Self::DvdR => write!(f, "DVD-R"),
Self::DvdPlusR => write!(f, "DVD+R"),
Self::DvdRw => write!(f, "DVD-RW"),
Self::DvdPlusRw => write!(f, "DVD+RW"),
Self::DvdRam => write!(f, "DVD-RAM"),
Self::BdRom => write!(f, "BD-ROM"),
Self::BdR => write!(f, "BD-R"),
Self::BdRe => write!(f, "BD-RE"),
}
}
}
impl OpticalMediaType {
#[inline]
pub const fn is_writable(&self) -> bool {
!matches!(self, Self::CdRom | Self::DvdRom | Self::BdRom)
}
#[inline]
pub const fn is_rewritable(&self) -> bool {
matches!(
self,
Self::CdRw | Self::DvdRw | Self::DvdPlusRw | Self::DvdRam | Self::BdRe
)
}
#[inline]
pub const fn is_write_once(&self) -> bool {
matches!(self, Self::CdR | Self::DvdR | Self::DvdPlusR | Self::BdR)
}
#[inline]
pub const fn capacity(&self) -> u64 {
match self {
Self::CdRom | Self::CdR | Self::CdRw => 700 * 1024 * 1024,
Self::DvdRom
| Self::DvdR
| Self::DvdPlusR
| Self::DvdRw
| Self::DvdPlusRw
| Self::DvdRam => 4_700_000_000,
Self::BdRom | Self::BdR | Self::BdRe => 25_000_000_000,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_session_info() {
let session = SessionInfo::new(1, 0, 999).as_last();
assert_eq!(session.session_number, 1);
assert_eq!(session.sector_count(), 1000);
assert_eq!(session.byte_size(), 1000 * 2048);
assert!(session.is_last_session);
}
#[test]
fn test_media_type() {
assert!(!OpticalMediaType::CdRom.is_writable());
assert!(OpticalMediaType::CdR.is_writable());
assert!(OpticalMediaType::CdR.is_write_once());
assert!(!OpticalMediaType::CdR.is_rewritable());
assert!(OpticalMediaType::CdRw.is_rewritable());
assert!(!OpticalMediaType::CdRw.is_write_once());
}
}