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
impl SectorReadFormat
Sourcepub fn sector_size(&self) -> usize
pub fn sector_size(&self) -> usize
Bytes returned per sector for this format.
Examples found in repository?
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
impl Clone for SectorReadFormat
Source§fn clone(&self) -> SectorReadFormat
fn clone(&self) -> SectorReadFormat
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more