1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*!
# CDTOC: Errors
*/
use crate::TocKind;
use std::{
error::Error,
fmt,
};
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
/// # Error Type.
pub enum TocError {
/// # CDDA Sample Rate.
///
/// The total number of samples for a given audio track on a CD must be
/// evenly divisible by `588`, the number of samples per sector.
CDDASampleCount,
/// # Invalid characters.
///
/// CDTOC metadata tags comprise HEX-encoded decimals separated by `+`
/// signs. The only other character allowed is an `X`, used to indicate a
/// leading data session.
CDTOCChars,
/// # Invalid Checksum File.
///
/// This is a catch-all error used when an AccurateRip or CTDB checksum
/// manifest contains some sort of logical error (i.e. preventing it being
/// parsed).
Checksums,
/// # Invalid Format For Operation.
///
/// This is a catch-all error used when a given disc format is incompatible
/// with the operation, such as [`TocKind::DataFirst`] w/ [`Toc::set_audio_leadin`](crate::Toc::set_audio_leadin).
Format(TocKind),
/// # Leadin Too Small.
///
/// Audio CDs require a leadin of at least `150`.
LeadinSize,
/// # No Audio.
///
/// At least one audio track is required for a table of contents.
NoAudio,
/// # No Checksums.
///
/// This error is used when an AccurateRip or CTDB checksum manifest yields
/// no valid checksums.
NoChecksums,
/// # Invalid sector count.
///
/// The stated number of audio tracks should match the number of sectors
/// provided (once data and leadout values have been separated).
SectorCount(u8, usize),
/// # Sector Ordering.
///
/// Audio CD sectors must be sequentially ordered and non-overlapping, and
/// the data session, if any, must come either immediately before or after
/// the audio set. The leadout must be larger than every other sector.
SectorOrder,
/// # Sector Size.
///
/// Sector values cannot exceed [`u32::MAX`].
SectorSize,
/// # Track Count.
///
/// Audio CDs support a maximum of 99 tracks.
TrackCount,
#[cfg(feature = "accuraterip")]
/// # AccurateRip Decode.
AccurateRipDecode,
#[cfg(feature = "accuraterip")]
/// # Drive Offset Decode.
DriveOffsetDecode,
#[cfg(feature = "accuraterip")]
/// # No Drive Offsets.
NoDriveOffsets,
#[cfg(feature = "cddb")]
/// # CDDB Decode.
CddbDecode,
#[cfg(feature = "sha1")]
/// # SHA1/Base64 Decode.
ShaB64Decode,
}
impl fmt::Display for TocError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::CDDASampleCount => "Invalid CDDA sample count.",
Self::CDTOCChars => "Invalid character(s), expecting only 0-9, A-F, +, and (rarely) X.",
Self::Checksums => "Unable to parse checksums.",
Self::Format(kind) => return write!(f, "This operation can't be applied to {kind} discs."),
Self::LeadinSize => "Leadin must be at least 150.",
Self::NoAudio => "At least one audio track is required.",
Self::NoChecksums => "No checksums were present.",
Self::SectorCount(expected, found) => return write!(f, "Expected {expected} audio sectors, found {found}."),
Self::SectorOrder => "Sectors are incorrectly ordered or overlap.",
Self::SectorSize => "Sector sizes may not exceed four bytes (u32).",
Self::TrackCount => "The number of audio tracks must be between 1..=99.",
#[cfg(feature = "accuraterip")] Self::AccurateRipDecode => "Invalid AccurateRip ID string.",
#[cfg(feature = "accuraterip")] Self::DriveOffsetDecode => "Unable to parse drive offsets.",
#[cfg(feature = "accuraterip")] Self::NoDriveOffsets => "No drive offsets were found.",
#[cfg(feature = "cddb")] Self::CddbDecode => "Invalid CDDB ID string.",
#[cfg(feature = "sha1")] Self::ShaB64Decode => "Invalid sha/base64 ID string.",
})
}
}
impl Error for TocError {}