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 ChannelCountMismatch,
191 ChannelLengthMismatch,
193}
194
195impl From<std::io::Error> for Error {
196 #[inline]
197 fn from(error: std::io::Error) -> Self {
198 Self::Io(error)
199 }
200}
201
202impl From<std::string::FromUtf8Error> for Error {
203 #[inline]
204 fn from(error: std::string::FromUtf8Error) -> Self {
205 Self::Utf8(Box::new(error))
206 }
207}
208
209impl From<metadata::CuesheetError> for Error {
210 fn from(error: metadata::CuesheetError) -> Self {
211 Self::Cuesheet(error)
212 }
213}
214
215impl std::error::Error for Error {}
216
217impl std::fmt::Display for Error {
218 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
219 match self {
220 Self::Io(e) => e.fmt(f),
221 Self::Utf8(e) => e.fmt(f),
222 Self::Cuesheet(e) => e.fmt(f),
223 Self::MissingFlacTag => "missing FLAC tag".fmt(f),
224 Self::MissingStreaminfo => "STREAMINFO block not first in file".fmt(f),
225 Self::MultipleStreaminfo => "multiple STREAMINFO blocks found in file".fmt(f),
226 Self::MultipleSeekTable => "multiple SEEKTABLE blocks found in file".fmt(f),
227 Self::MultipleVorbisComment => "multiple VORBIS_COMMENT blocks found in file".fmt(f),
228 Self::InvalidSeekTableSize => "invalid SEEKTABLE block size".fmt(f),
229 Self::InvalidSeekTablePoint => "invalid SEEKTABLE point".fmt(f),
230 Self::InvalidPictureType => "reserved PICTURE type".fmt(f),
231 Self::MultiplePngIcon => "multiple PNG icons in PICTURE blocks".fmt(f),
232 Self::MultipleGeneralIcon => "multiple general file icons in PICTURE blocks".fmt(f),
233 Self::ReservedMetadataBlock => "reserved metadata block".fmt(f),
234 Self::InvalidMetadataBlock => "invalid metadata block".fmt(f),
235 Self::InvalidMetadataBlockSize => "invalid metadata block size".fmt(f),
236 Self::InsufficientApplicationBlock => "APPLICATION block too small for data".fmt(f),
237 Self::ExcessiveVorbisEntries => "excessive number of VORBIS_COMMENT entries".fmt(f),
238 Self::ExcessiveStringLength => "excessive string length".fmt(f),
239 Self::ExcessivePictureSize => "excessive PICTURE data size".fmt(f),
240 Self::ExcessiveBlockSize => "excessive metadata block size".fmt(f),
241 Self::InvalidSyncCode => "invalid frame sync code".fmt(f),
242 Self::InvalidBlockSize => "invalid frame block size".fmt(f),
243 Self::ShortBlock => "block size <= 14 must be last in stream".fmt(f),
244 Self::BlockSizeMismatch => {
245 "block size in frame larger than maximum block size in STREAMINFO".fmt(f)
246 }
247 Self::InvalidSampleRate => "invalid frame sample rate".fmt(f),
248 Self::NonSubsetSampleRate => "sample rate undefined for subset stream".fmt(f),
249 Self::NonSubsetBitsPerSample => "bits-per-sample undefined for subset stream".fmt(f),
250 Self::SampleRateMismatch => {
251 "sample rate in frame differs from sample rate in STREAMINFO".fmt(f)
252 }
253 Self::ExcessiveChannels => "excessive channel count".fmt(f),
254 Self::InvalidChannels => "invalid frame channel assignment".fmt(f),
255 Self::ChannelsMismatch => {
256 "channel count in frame differs from channel count in STREAMINFO".fmt(f)
257 }
258 Self::InvalidBitsPerSample => "invalid frame bits-per-sample".fmt(f),
259 Self::ExcessiveBps => "bits-per-sample higher than 32".fmt(f),
260 Self::BitsPerSampleMismatch => {
261 "bits-per-sample in frame differs from bits-per-sample in STREAMINFO".fmt(f)
262 }
263 Self::InvalidFrameNumber => "invalid frame number".fmt(f),
264 Self::InvalidSeek => "seeking beyond end of stream".fmt(f),
265 Self::ExcessiveFrameNumber => "excessive frame number".fmt(f),
266 Self::Crc8Mismatch => "CRC-8 mismatch in frame header".fmt(f),
267 Self::Crc16Mismatch => "CRC-16 mismatch in frame footer".fmt(f),
268 Self::InvalidSubframeHeader => "invalid subframe header".fmt(f),
269 Self::InvalidSubframeHeaderType => "invalid subframe header type".fmt(f),
270 Self::ExcessiveWastedBits => "excessive number of wasted BPS".fmt(f),
271 Self::MissingResiduals => "insufficient number of residuals".fmt(f),
272 Self::InvalidCodingMethod => "invalid residual coding method".fmt(f),
273 Self::InvalidPartitionOrder => "invalid residual partition order".fmt(f),
274 Self::InvalidFixedOrder => "invalid FIXED subframe predictor order".fmt(f),
275 Self::InvalidLpcOrder => "invalid LPC subframe predictor order".fmt(f),
276 Self::InvalidQlpPrecision => "invalid QLP precision bits".fmt(f),
277 Self::NegativeLpcShift => "negative shift in LPC subframe".fmt(f),
278 Self::NoBestLpcOrder => "no best LPC order found".fmt(f),
279 Self::InsufficientLpcSamples => {
280 "insufficient samples to calculate LPC parameters".fmt(f)
281 }
282 Self::ZeroLpCoefficients => "LP coefficients are all 0".fmt(f),
283 Self::LpNegativeShiftError => "excessive negative shift in LP quantization".fmt(f),
284 Self::AccumulatorOverflow => "accumulator overflow in LPC subframe".fmt(f),
285 Self::TooManySamples => "more samples in stream than indicated in STREAMINFO".fmt(f),
286 Self::ExcessiveTotalSamples => "too many samples requested".fmt(f),
287 Self::NoSamples => "no samples written to encoder".fmt(f),
288 Self::SampleCountMismatch => "samples written to stream differ from expected".fmt(f),
289 Self::ResidualOverflow => "residual value too large".fmt(f),
290 Self::SamplesNotDivisibleByChannels => {
291 "number of samples not divisible number number of channels".fmt(f)
292 }
293 Self::InvalidTotalBytes => "invalid total byte count".fmt(f),
294 Self::InvalidTotalSamples => "invalid total samples count".fmt(f),
295 Self::ChannelCountMismatch => {
296 "number of written channels differs from encoder's channel count".fmt(f)
297 }
298 Self::ChannelLengthMismatch => "number of written channels are not consistent".fmt(f),
299 }
300 }
301}
302
303impl From<Error> for std::io::Error {
304 fn from(err: Error) -> Self {
305 match err {
306 Error::Io(io) => io,
307 Error::Utf8(e) => std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()),
308 other => std::io::Error::new(std::io::ErrorKind::InvalidData, other.to_string()),
309 }
310 }
311}
312
313struct Counter<F> {
314 stream: F,
315 count: u64,
316}
317
318impl<F> Counter<F> {
319 fn new(stream: F) -> Self {
320 Self { stream, count: 0 }
321 }
322
323 fn stream(&mut self) -> &mut F {
324 &mut self.stream
325 }
326}
327
328impl<F: std::io::Read> std::io::Read for Counter<F> {
329 #[inline]
330 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
331 self.stream.read(buf).inspect(|bytes| {
332 self.count += u64::try_from(*bytes).unwrap();
333 })
334 }
335}
336
337impl<F: std::io::Write> std::io::Write for Counter<F> {
338 #[inline]
339 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
340 self.stream.write(buf).inspect(|bytes| {
341 self.count += u64::try_from(*bytes).unwrap();
342 })
343 }
344
345 #[inline]
346 fn flush(&mut self) -> std::io::Result<()> {
347 self.stream.flush()
348 }
349}