Skip to main content

SectorReadFormat

Enum SectorReadFormat 

Source
pub enum SectorReadFormat {
    Audio,
    Mode1Cooked,
    Mode1Raw,
    Mode2Raw,
}
Expand description

Selects the type and layout of sectors returned when reading from an optical drive.

This is the crate’s platform-independent representation of the sector type and main-channel fields requested by the MMC READ CD command (0xBE) or the equivalent platform API.

ReadOptions defaults to Audio, so callers reading audio tracks normally do not need to select a format. For a data track, call CdReader::detect_track_format and pass the result to ReadOptions::with_format. Detection chooses Mode1Cooked for Mode 1 tracks and Mode2Raw for Mode 2 tracks.

Selecting a format does not convert the sectors. It tells the drive what sector type and fields to return, so the selection must match the track being read. A mismatched format may be rejected by the library or the drive.

The Raw variants return the complete 2,352-byte main-channel sector. They do not include subchannel data or C2 error information. Use sector_size to obtain the number of bytes returned per sector for any variant.

Variants§

§

Audio

CD-DA audio as 2,352 bytes of headerless PCM per sector.

The samples are signed 16-bit little-endian stereo at 44.1 kHz. Each sector contains 588 stereo sample frames and represents 1/75 second of audio. The returned bytes can be passed directly to create_wav.

§

Mode1Cooked

The 2,048-byte user-data field from a Mode 1 sector.

The drive omits the sync pattern, sector header, Error Detection Code (EDC), reserved bytes, and Error Correction Code (ECC). This is usually the preferred representation for reading filesystems; concatenating the cooked sectors of a typical ISO 9660 track produces a directly usable disc image.

§

Mode1Raw

A complete 2,352-byte Mode 1 main-channel sector.

This includes the 12-byte sync pattern, 4-byte header, 2,048-byte user data field, EDC, reserved bytes, and ECC. Use this when preserving or inspecting the original sector framing. For normal filesystem access, Mode1Cooked is usually more convenient.

§

Mode2Raw

A complete 2,352-byte Mode 2 main-channel sector.

This is the only Mode 2 representation provided by the crate. Mode 2 XA tracks can mix Form 1 and Form 2 sectors within the same track: Form 1 carries 2,048 bytes of user data with stronger error correction, while Form 2 carries 2,324 bytes of user data.

The form is recorded in each sector’s XA subheader. The crate does not expose a cooked Mode 2 reader or a public XA payload parser, so callers must inspect each sector and extract the appropriate payload themselves.

Implementations§

Source§

impl SectorReadFormat

Source

pub fn sector_size(&self) -> usize

Bytes returned per sector for this format.

Examples found in repository?
examples/save_data_track.rs (line 52)
26fn main() -> Result<(), Box<dyn std::error::Error>> {
27    let output_dir = common::fresh_output_dir("save_data_track")?;
28    let reader = CdReader::open_default()?;
29    let toc = reader.read_toc()?;
30
31    // There is no `find_data_track` helper in the crate — the idiom is a plain
32    // filter on the TOC, since "data track" is simply `!is_audio`.
33    let data_track = toc
34        .tracks
35        .iter()
36        .find(|track| !track.is_audio)
37        .ok_or("no data track on this disc (need a mixed-mode / enhanced CD)")?;
38
39    let format = reader.detect_track_format(data_track)?;
40    println!("Data track #{} detected as {format:?}\n", data_track.number);
41
42    match format {
43        SectorReadFormat::Mode1Cooked => {
44            // Cooked Mode 1 strips sync/header/EDC/ECC, leaving exactly the
45            // 2048-byte user data per sector — i.e. the raw ISO 9660 image.
46            let iso_path = output_dir.join(format!("track{:02}.iso", data_track.number));
47            let bytes = stream_track_to_file(&reader, &toc, data_track.number, format, &iso_path)?;
48
49            println!(
50                "Wrote {} ({bytes} bytes, {} sectors)\n",
51                iso_path.display(),
52                bytes / format.sector_size() as u64
53            );
54            print_mount_hint(&iso_path.display().to_string());
55        }
56        SectorReadFormat::Mode2Raw => {
57            // Mode 2 forms are a per-sector property; producing a clean cooked
58            // payload requires inspecting each sector's XA subheader, which is
59            // left to the consumer. We save the complete raw sectors so nothing
60            // is lost.
61            let bin_path = output_dir.join(format!("track{:02}.mode2.bin", data_track.number));
62            let bytes = stream_track_to_file(&reader, &toc, data_track.number, format, &bin_path)?;
63
64            println!(
65                "This is a Mode 2 track. Saved complete raw sectors to {} \
66                 ({bytes} bytes, {} sectors).",
67                bin_path.display(),
68                bytes / format.sector_size() as u64
69            );
70            println!(
71                "Extracting a mountable filesystem from Mode 2 is consumer territory: \
72                 each sector's XA subheader decides which bytes are user data."
73            );
74        }
75        other => {
76            return Err(format!(
77                "data track #{} detected as {other:?}, which is unexpected for a data track",
78                data_track.number
79            )
80            .into());
81        }
82    }
83
84    Ok(())
85}

Trait Implementations§

Source§

impl Clone for SectorReadFormat

Source§

fn clone(&self) -> SectorReadFormat

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for SectorReadFormat

Source§

impl Debug for SectorReadFormat

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for SectorReadFormat

Source§

impl PartialEq for SectorReadFormat

Source§

fn eq(&self, other: &SectorReadFormat) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for SectorReadFormat

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.