1#![warn(missing_docs)]
46#![forbid(unsafe_code)]
47
48mod audio;
49pub mod byteorder;
50mod crc;
51pub mod decode;
52pub mod encode;
53pub mod metadata;
54pub mod stream;
55
56#[derive(Debug)]
58#[non_exhaustive]
59pub enum Error {
60 Io(std::io::Error),
62 Utf8(Box<std::string::FromUtf8Error>),
64 MissingFlacTag,
66 MissingStreaminfo,
68 MultipleStreaminfo,
70 MultipleSeekTable,
72 MultipleVorbisComment,
74 InvalidSeekTableSize,
77 InvalidSeekTablePoint,
79 Cuesheet(metadata::CuesheetError),
81 InvalidPictureType,
83 MultiplePngIcon,
85 MultipleGeneralIcon,
87 ReservedMetadataBlock,
89 InvalidMetadataBlock,
91 InvalidMetadataBlockSize,
94 InsufficientApplicationBlock,
97 ExcessiveVorbisEntries,
99 ExcessiveStringLength,
101 ExcessivePictureSize,
103 ShortBlock,
105 ExcessiveBlockSize,
107 InvalidSyncCode,
109 InvalidBlockSize,
111 BlockSizeMismatch,
113 InvalidSampleRate,
115 NonSubsetSampleRate,
117 NonSubsetBitsPerSample,
119 SampleRateMismatch,
121 ExcessiveChannels,
123 InvalidChannels,
125 ChannelsMismatch,
127 InvalidBitsPerSample,
129 ExcessiveBps,
131 BitsPerSampleMismatch,
133 InvalidFrameNumber,
135 InvalidSeek,
137 ExcessiveFrameNumber,
139 Crc8Mismatch,
141 Crc16Mismatch,
143 InvalidSubframeHeader,
145 InvalidSubframeHeaderType,
147 ExcessiveWastedBits,
149 MissingResiduals,
151 InvalidCodingMethod,
153 InvalidPartitionOrder,
155 InvalidFixedOrder,
157 InvalidLpcOrder,
159 InvalidQlpPrecision,
161 NegativeLpcShift,
163 NoBestLpcOrder,
165 InsufficientLpcSamples,
167 ZeroLpCoefficients,
169 LpNegativeShiftError,
171 AccumulatorOverflow,
173 TooManySamples,
175 ExcessiveTotalSamples,
177 NoSamples,
179 SampleCountMismatch,
181 ResidualOverflow,
183 SamplesNotDivisibleByChannels,
185 InvalidTotalBytes,
187 InvalidTotalSamples,
189}
190
191impl From<std::io::Error> for Error {
192 #[inline]
193 fn from(error: std::io::Error) -> Self {
194 Self::Io(error)
195 }
196}
197
198impl From<std::string::FromUtf8Error> for Error {
199 #[inline]
200 fn from(error: std::string::FromUtf8Error) -> Self {
201 Self::Utf8(Box::new(error))
202 }
203}
204
205impl From<metadata::CuesheetError> for Error {
206 fn from(error: metadata::CuesheetError) -> Self {
207 Self::Cuesheet(error)
208 }
209}
210
211impl std::error::Error for Error {}
212
213impl std::fmt::Display for Error {
214 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
215 match self {
216 Self::Io(e) => e.fmt(f),
217 Self::Utf8(e) => e.fmt(f),
218 Self::Cuesheet(e) => e.fmt(f),
219 Self::MissingFlacTag => "missing FLAC tag".fmt(f),
220 Self::MissingStreaminfo => "STREAMINFO block not first in file".fmt(f),
221 Self::MultipleStreaminfo => "multiple STREAMINFO blocks found in file".fmt(f),
222 Self::MultipleSeekTable => "multiple SEEKTABLE blocks found in file".fmt(f),
223 Self::MultipleVorbisComment => "multiple VORBIS_COMMENT blocks found in file".fmt(f),
224 Self::InvalidSeekTableSize => "invalid SEEKTABLE block size".fmt(f),
225 Self::InvalidSeekTablePoint => "invalid SEEKTABLE point".fmt(f),
226 Self::InvalidPictureType => "reserved PICTURE type".fmt(f),
227 Self::MultiplePngIcon => "multiple PNG icons in PICTURE blocks".fmt(f),
228 Self::MultipleGeneralIcon => "multiple general file icons in PICTURE blocks".fmt(f),
229 Self::ReservedMetadataBlock => "reserved metadata block".fmt(f),
230 Self::InvalidMetadataBlock => "invalid metadata block".fmt(f),
231 Self::InvalidMetadataBlockSize => "invalid metadata block size".fmt(f),
232 Self::InsufficientApplicationBlock => "APPLICATION block too small for data".fmt(f),
233 Self::ExcessiveVorbisEntries => "excessive number of VORBIS_COMMENT entries".fmt(f),
234 Self::ExcessiveStringLength => "excessive string length".fmt(f),
235 Self::ExcessivePictureSize => "excessive PICTURE data size".fmt(f),
236 Self::ExcessiveBlockSize => "excessive metadata block size".fmt(f),
237 Self::InvalidSyncCode => "invalid frame sync code".fmt(f),
238 Self::InvalidBlockSize => "invalid frame block size".fmt(f),
239 Self::ShortBlock => "block size <= 14 must be last in stream".fmt(f),
240 Self::BlockSizeMismatch => {
241 "block size in frame larger than maximum block size in STREAMINFO".fmt(f)
242 }
243 Self::InvalidSampleRate => "invalid frame sample rate".fmt(f),
244 Self::NonSubsetSampleRate => "sample rate undefined for subset stream".fmt(f),
245 Self::NonSubsetBitsPerSample => "bits-per-sample undefined for subset stream".fmt(f),
246 Self::SampleRateMismatch => {
247 "sample rate in frame differs from sample rate in STREAMINFO".fmt(f)
248 }
249 Self::ExcessiveChannels => "excessive channel count".fmt(f),
250 Self::InvalidChannels => "invalid frame channel assignment".fmt(f),
251 Self::ChannelsMismatch => {
252 "channel count in frame differs from channel count in STREAMINFO".fmt(f)
253 }
254 Self::InvalidBitsPerSample => "invalid frame bits-per-sample".fmt(f),
255 Self::ExcessiveBps => "bits-per-sample higher than 32".fmt(f),
256 Self::BitsPerSampleMismatch => {
257 "bits-per-sample in frame differs from bits-per-sample in STREAMINFO".fmt(f)
258 }
259 Self::InvalidFrameNumber => "invalid frame number".fmt(f),
260 Self::InvalidSeek => "seeking beyond end of stream".fmt(f),
261 Self::ExcessiveFrameNumber => "excessive frame number".fmt(f),
262 Self::Crc8Mismatch => "CRC-8 mismatch in frame header".fmt(f),
263 Self::Crc16Mismatch => "CRC-16 mismatch in frame footer".fmt(f),
264 Self::InvalidSubframeHeader => "invalid subframe header".fmt(f),
265 Self::InvalidSubframeHeaderType => "invalid subframe header type".fmt(f),
266 Self::ExcessiveWastedBits => "excessive number of wasted BPS".fmt(f),
267 Self::MissingResiduals => "insufficient number of residuals".fmt(f),
268 Self::InvalidCodingMethod => "invalid residual coding method".fmt(f),
269 Self::InvalidPartitionOrder => "invalid residual partition order".fmt(f),
270 Self::InvalidFixedOrder => "invalid FIXED subframe predictor order".fmt(f),
271 Self::InvalidLpcOrder => "invalid LPC subframe predictor order".fmt(f),
272 Self::InvalidQlpPrecision => "invalid QLP precision bits".fmt(f),
273 Self::NegativeLpcShift => "negative shift in LPC subframe".fmt(f),
274 Self::NoBestLpcOrder => "no best LPC order found".fmt(f),
275 Self::InsufficientLpcSamples => {
276 "insufficient samples to calculate LPC parameters".fmt(f)
277 }
278 Self::ZeroLpCoefficients => "LP coefficients are all 0".fmt(f),
279 Self::LpNegativeShiftError => "excessive negative shift in LP quantization".fmt(f),
280 Self::AccumulatorOverflow => "accumulator overflow in LPC subframe".fmt(f),
281 Self::TooManySamples => "more samples in stream than indicated in STREAMINFO".fmt(f),
282 Self::ExcessiveTotalSamples => "too many samples requested".fmt(f),
283 Self::NoSamples => "no samples written to encoder".fmt(f),
284 Self::SampleCountMismatch => "samples written to stream differ from expected".fmt(f),
285 Self::ResidualOverflow => "residual value too large".fmt(f),
286 Self::SamplesNotDivisibleByChannels => {
287 "number of samples not divisible number number of channels".fmt(f)
288 }
289 Self::InvalidTotalBytes => "invalid total byte count".fmt(f),
290 Self::InvalidTotalSamples => "invalid total samples count".fmt(f),
291 }
292 }
293}
294
295impl From<Error> for std::io::Error {
296 fn from(err: Error) -> Self {
297 match err {
298 Error::Io(io) => io,
299 Error::Utf8(e) => std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()),
300 other => std::io::Error::new(std::io::ErrorKind::InvalidData, other.to_string()),
301 }
302 }
303}
304
305struct Counter<F> {
306 stream: F,
307 count: u64,
308}
309
310impl<F> Counter<F> {
311 fn new(stream: F) -> Self {
312 Self { stream, count: 0 }
313 }
314
315 fn stream(&mut self) -> &mut F {
316 &mut self.stream
317 }
318}
319
320impl<F: std::io::Read> std::io::Read for Counter<F> {
321 #[inline]
322 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
323 self.stream.read(buf).inspect(|bytes| {
324 self.count += u64::try_from(*bytes).unwrap();
325 })
326 }
327}
328
329impl<F: std::io::Write> std::io::Write for Counter<F> {
330 #[inline]
331 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
332 self.stream.write(buf).inspect(|bytes| {
333 self.count += u64::try_from(*bytes).unwrap();
334 })
335 }
336
337 #[inline]
338 fn flush(&mut self) -> std::io::Result<()> {
339 self.stream.flush()
340 }
341}