midly/
smf.rs

1//! Specific to the SMF packaging of MIDI streams.
2
3use crate::{
4    event::TrackEvent,
5    prelude::*,
6    primitive::{Format, Timing},
7    riff,
8};
9
10/// How many events per byte to estimate when allocating memory for events while parsing.
11///
12/// A value that is too large (ie. too few bytes/event), will overallocate, while a value that is
13/// too small (ie. too many bytes/event) will underallocate.
14///
15/// Usually, since memory is cheap it's better to overallocate, since reallocating the buffer may
16/// result in costly memory moves.
17/// This means that it's better to err on the large side (too few bytes/event).
18///
19/// Real-world tests show that without running status, the average is a little above 4 bytes/event,
20/// and with running status enabled it's a little above 3 bytes/event.
21/// This makes sense, since it's DeltaTime [+ Status] + Key + Velocity for NoteOn and NoteOff
22/// events, which should make up the bulk of most MIDI files.
23///
24/// Erring on the large side for events/byte (erring on the small side for bytes/event), we can
25/// approximate to 3 bytes/event.
26#[cfg(feature = "alloc")]
27const BYTES_TO_EVENTS: f32 = 1.0 / 3.0;
28
29/// How many bytes per event to estimate when allocating memory when writing.
30///
31/// A value that is too large will overallocate space for bytes, while a value that's too small
32/// will underallocate bytes.
33///
34/// Since the writer uses running status by default, a value a bit over `3` will allocate enough for
35/// almost all cases (Except for eg. info tracks, which usually have a high byte/event count
36/// because they contain text. However these tracks are small enough that reallocating doesn't
37/// matter too much).
38#[cfg(feature = "alloc")]
39const EVENTS_TO_BYTES: f32 = 3.4;
40
41/// How many bytes must a MIDI body have in order to enable multithreading.
42///
43/// When writing, the MIDI body size is estimated from the event count using `BYTES_PER_EVENT`.
44#[cfg(feature = "parallel")]
45const PARALLEL_ENABLE_THRESHOLD: usize = 3 * 1024;
46
47/// A single track: simply a list of track events.
48///
49/// Only available with the `alloc` feature enabled.
50#[cfg(feature = "alloc")]
51pub type Track<'a> = Vec<TrackEvent<'a>>;
52
53/// Represents a single `.mid` Standard Midi File.
54/// If you're casually looking to parse a `.mid` file, this is the type you're looking for.
55///
56/// This type is only available with the `alloc` feature enabled.
57/// If you're looking for a fully `no_std` alternative, see the [`parse`](fn.parse.html) function.
58#[cfg(feature = "alloc")]
59#[derive(Clone, PartialEq, Eq, Debug, Hash)]
60pub struct Smf<'a> {
61    /// The header of this MIDI file, indicating tempo information and track format.
62    pub header: Header,
63    /// A list of tracks within this MIDI file.
64    ///
65    /// Each track consists simply of a list of events (ie. there is no track metadata).
66    pub tracks: Vec<Track<'a>>,
67}
68#[cfg(feature = "alloc")]
69impl<'a> Smf<'a> {
70    /// Create a new empty `Smf` with zero tracks, using the given header.
71    #[inline]
72    pub fn new(header: Header) -> Smf<'a> {
73        Smf {
74            header,
75            tracks: vec![],
76        }
77    }
78
79    /// Parse a `.mid` Standard Midi File from its raw bytes.
80    /// If you casually want to parse `.mid` files, this is the function you're looking for.
81    pub fn parse(raw: &[u8]) -> Result<Smf> {
82        let (header, tracks) = parse(raw)?;
83        let track_count_hint = tracks.track_count_hint;
84        let tracks = tracks.collect_tracks()?;
85        validate_smf(&header, track_count_hint, tracks.len())?;
86        Ok(Smf { header, tracks })
87    }
88
89    /// Encodes and writes the file to the given generic writer.
90    ///
91    /// Note that this function requires a `midly::io::Write` writer, not a `std::io::Write` writer.
92    /// This makes it possible to support `no_std` environments, as well as custom writer errors.
93    /// If you're looking to write to a `File`, see the [`save`](#method.save) method.
94    /// If you're looking to write to a `std::io::Write` writer, see the
95    /// [`write_std`](#method.write_std) method.
96    ///
97    /// This function is always available, even in `no_std` environments.
98    #[inline]
99    pub fn write<W: Write>(&self, out: &mut W) -> WriteResult<W> {
100        write(&self.header, &self.tracks, out)
101    }
102
103    /// Encodes and writes the file to the given `std::io::Write` writer.
104    ///
105    /// This function is similar to the [`write`](#method.write) method, but writes to a
106    /// `std::io::Write` writer instead of a `midly::io::Write` writer.
107    ///
108    /// This function is only available with the `std` feature enabled.
109    #[cfg(feature = "std")]
110    #[inline]
111    pub fn write_std<W: io::Write>(&self, out: W) -> io::Result<()> {
112        write_std(&self.header, &self.tracks, out)
113    }
114
115    /// Encodes and writes the file to the given path.
116    ///
117    /// This function is only available with the `std` feature enabled.
118    #[cfg(feature = "std")]
119    #[inline]
120    pub fn save<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
121        /// A non-generic, non-inline function.
122        /// This means that this function will be compiled and monomorphized once, and reused for
123        /// every call to `save`.
124        fn save_impl(smf: &Smf, path: &Path) -> io::Result<()> {
125            smf.write(&mut IoWrap(File::create(path)?))
126        }
127        save_impl(self, path.as_ref())
128    }
129
130    /// Remove any lifetimed data from this event to create an `Smf` with `'static`
131    /// lifetime that can be stored and moved everywhere, solving borrow checker issues.
132    ///
133    /// This method creates a copy of the `Smf` structure. See the `make_static` method for an
134    /// in-place solution.
135    ///
136    /// WARNING: Any bytestrings, including meta messages, SysEx dumps and escape sequences will be
137    /// replaced by empty bytestrings.
138    pub fn to_static(&self) -> Smf<'static> {
139        self.clone().make_static()
140    }
141
142    /// Remove any lifetimed data from this event to create an `Smf` with `'static`
143    /// lifetime that can be stored and moved everywhere, solving borrow checker issues.
144    ///
145    /// This method consumes the `Smf` structure, reusing the backing memory.
146    ///
147    /// WARNING: Any bytestrings, including meta messages, SysEx dumps and escape sequences will be
148    /// replaced by empty bytestrings.
149    pub fn make_static(mut self) -> Smf<'static> {
150        for track in self.tracks.iter_mut() {
151            for ev in track.iter_mut() {
152                *ev = ev.to_static();
153            }
154        }
155        unsafe { mem::transmute::<Smf<'a>, Smf<'static>>(self) }
156    }
157}
158
159/// A track, represented as a `Vec` of events along with their originating bytes.
160///
161/// This type alias is only available with the `alloc` feature enabled.
162#[cfg(feature = "alloc")]
163pub type BytemappedTrack<'a> = Vec<(&'a [u8], TrackEvent<'a>)>;
164
165/// A `.mid` Standard Midi File, but keeps a mapping to the raw bytes that make up each event.
166///
167/// This type is only available with the `alloc` feature enabled.
168#[cfg(feature = "alloc")]
169#[derive(Clone, PartialEq, Eq, Debug, Hash)]
170pub struct SmfBytemap<'a> {
171    /// The header of this file.
172    pub header: Header,
173    /// A list of tracks, along with the bytemap of their events.
174    pub tracks: Vec<BytemappedTrack<'a>>,
175}
176#[cfg(feature = "alloc")]
177impl<'a> SmfBytemap<'a> {
178    /// Create a new empty `SmfBytemap` with zero tracks, using the given header.
179    #[inline]
180    pub fn new(header: Header) -> SmfBytemap<'a> {
181        SmfBytemap {
182            header,
183            tracks: vec![],
184        }
185    }
186
187    /// Parse a Standard Midi File from its raw bytes, keeping a map to the original bytes that
188    /// make up each event.
189    pub fn parse(raw: &[u8]) -> Result<SmfBytemap> {
190        let (header, tracks) = parse(raw)?;
191        let track_count_hint = tracks.track_count_hint;
192        let tracks = tracks.collect_bytemapped()?;
193        validate_smf(&header, track_count_hint, tracks.len())?;
194        Ok(SmfBytemap { header, tracks })
195    }
196
197    /// Encodes and writes the *events* (not the bytemap) to the given generic writer.
198    #[inline]
199    pub fn write<W: Write>(&self, out: &mut W) -> WriteResult<W> {
200        write(
201            &self.header,
202            self.tracks
203                .iter()
204                .map(|bytemapped| bytemapped.iter().map(|(_b, ev)| ev)),
205            out,
206        )
207    }
208
209    /// Encodes and writes the *events* (not the bytemap) to the given `std::io::Write` writer.
210    ///
211    /// This function is only available with the `std` feature enabled.
212    #[cfg(feature = "std")]
213    #[inline]
214    pub fn write_std<W: io::Write>(&self, out: W) -> io::Result<()> {
215        write_std(
216            &self.header,
217            self.tracks
218                .iter()
219                .map(|bytemapped| bytemapped.iter().map(|(_b, ev)| ev)),
220            out,
221        )
222    }
223
224    /// Creates/overwrites the file at the given path and writes the *events* (not the bytemap) to
225    /// it.
226    ///
227    /// This function is only available with the `std` feature enabled.
228    #[cfg(feature = "std")]
229    #[inline]
230    pub fn save<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
231        /// A non-generic, non-inline function.
232        /// This means that this function will be compiled and monomorphized once, and reused for
233        /// every call to `save`.
234        fn save_impl(smf: &SmfBytemap, path: &Path) -> io::Result<()> {
235            smf.write(&mut IoWrap(File::create(path)?))
236        }
237        save_impl(self, path.as_ref())
238    }
239}
240
241#[cfg(feature = "alloc")]
242fn validate_smf(header: &Header, track_count_hint: u16, track_count: usize) -> Result<()> {
243    if cfg!(feature = "strict") {
244        ensure!(
245            track_count_hint as usize == track_count,
246            err_malformed!("file has a different amount of tracks than declared")
247        );
248        ensure!(
249            header.format != Format::SingleTrack || track_count == 1,
250            err_malformed!("singletrack format file has multiple tracks")
251        );
252    }
253    Ok(())
254}
255
256/// Parse a raw MIDI file lazily, yielding its header and a lazy track iterator.
257/// No allocations are made.
258///
259/// The track iterator that is returned yields event iterators, which in turn yield concrete events.
260///
261/// This function is always available, even in `no_std` environments.
262pub fn parse(raw: &[u8]) -> Result<(Header, TrackIter)> {
263    let raw = match raw.get(..4) {
264        Some(b"RIFF") => riff::unwrap(raw)?,
265        Some(b"MThd") => raw,
266        _ => bail!(err_invalid!("not a midi file")),
267    };
268    let mut chunks = ChunkIter::new(raw);
269    let (header, track_count) = match chunks.next() {
270        Some(maybe_chunk) => match maybe_chunk.context(err_invalid!("invalid midi header"))? {
271            Chunk::Header(header, track_count) => Ok((header, track_count)),
272            Chunk::Track(_) => Err(err_invalid!("expected header, found track")),
273        },
274        None => Err(err_invalid!("no midi header chunk")),
275    }?;
276    let tracks = chunks.as_tracks(track_count);
277    Ok((header, tracks))
278}
279
280/// Encode and write a generic MIDI file into the given generic writer.
281/// The MIDI file is represented by a header and a list of tracks.
282///
283/// # Errors
284///
285/// The MIDI writer raises almost no errors by itself, it only bubbles errors from the underlying
286/// writer.
287/// The only exception to this rule are extreme cases that break the limits of the MIDI spec: if
288/// there are more than 65535 tracks, if the data for a single event is 256MB or larger, or if the
289/// total size of any track is 4GB or larger.
290///
291/// # Implementation notes
292///
293/// Currently this function will attempt to use multiple threads to encode the file if possible and
294/// the file is large enough to make it worth it.
295///
296/// Otherwise, each track will be written to an in-memory buffer before writing to disk.
297///
298/// If allocation is disabled, but the writer is seekable, the file will be written once and it
299/// will be seeked back in order to write down the chunk sizes.
300///
301/// Otherwise, encoding will happen twice: once to determine the size of the chunks and once again
302/// to actually write down the file.
303pub fn write<'a, T, E, W>(header: &Header, tracks: T, out: &mut W) -> WriteResult<W>
304where
305    T: IntoIterator<Item = E>,
306    T::IntoIter: ExactSizeIterator + Clone + Send,
307    E: IntoIterator<Item = &'a TrackEvent<'a>>,
308    E::IntoIter: Clone + Send,
309    W: Write,
310{
311    let tracks = tracks.into_iter().map(|events| events.into_iter());
312    //Write the header first
313    Chunk::write_header(header, tracks.len(), out)?;
314
315    //Try to write the file in parallel
316    #[cfg(feature = "parallel")]
317    {
318        //Figure out whether multithreading is worth it
319        let event_count = tracks
320            .clone()
321            .map(|track| track.into_iter().size_hint().0)
322            .sum::<usize>();
323        if (event_count as f32 * EVENTS_TO_BYTES) > PARALLEL_ENABLE_THRESHOLD as f32 {
324            use rayon::prelude::*;
325
326            //Write out the tracks in parallel into several different buffers
327            let mut track_chunks = Vec::new();
328            tracks
329                .collect::<Vec<_>>()
330                .into_par_iter()
331                .map(|track| {
332                    let mut track_chunk = Vec::new();
333                    Chunk::write_to_vec(track, &mut track_chunk)?;
334                    Ok(track_chunk)
335                })
336                .collect_into_vec(&mut track_chunks);
337
338            //Write down the tracks sequentially and in order
339            for result in track_chunks {
340                let track_chunk = result.map_err(W::invalid_input)?;
341                out.write(&track_chunk)?;
342            }
343            return Ok(());
344        }
345    }
346
347    #[cfg(feature = "alloc")]
348    {
349        //Write the tracks into a buffer before writing out to the file
350        let mut buf = Vec::new();
351        for track in tracks {
352            Chunk::write_to_vec(track, &mut buf).map_err(|msg| W::invalid_input(msg))?;
353            out.write(&buf)?;
354        }
355        return Ok(());
356    }
357
358    #[allow(unreachable_code)]
359    {
360        if let Some(out) = out.make_seekable() {
361            //Write down using seeks if the writer is seekable
362            for track in tracks {
363                Chunk::write_seek(track, out)?;
364            }
365            return Ok(());
366        }
367
368        //Last resort: do probe-writing.
369        //Two passes are done: one to find out the size of the chunk and another to actually
370        //write the chunk.
371        for track in tracks {
372            Chunk::write_probe(track, out)?;
373        }
374        Ok(())
375    }
376}
377
378/// Similar to [`write`](fn.write.html), but writes to a `std::io::Write` writer instead of a
379/// `midly::io::Write` writer.
380///
381/// This function is only available with the `std` feature enabled.
382#[cfg(feature = "std")]
383#[inline]
384pub fn write_std<'a, T, E, W>(header: &Header, tracks: T, out: W) -> io::Result<()>
385where
386    T: IntoIterator<Item = E>,
387    T::IntoIter: ExactSizeIterator + Clone + Send,
388    E: IntoIterator<Item = &'a TrackEvent<'a>>,
389    E::IntoIter: Clone + Send,
390    W: io::Write,
391{
392    write(header, tracks, &mut IoWrap(out))
393}
394
395#[derive(Clone, Debug)]
396struct ChunkIter<'a> {
397    /// Starts at the current index, ends at EOF.
398    raw: &'a [u8],
399}
400impl<'a> ChunkIter<'a> {
401    #[inline]
402    fn new(raw: &'a [u8]) -> ChunkIter {
403        ChunkIter { raw }
404    }
405
406    #[inline]
407    fn as_tracks(self, track_count_hint: u16) -> TrackIter<'a> {
408        TrackIter {
409            chunks: self,
410            track_count_hint,
411        }
412    }
413}
414impl<'a> Iterator for ChunkIter<'a> {
415    type Item = Result<Chunk<'a>>;
416    #[inline]
417    fn next(&mut self) -> Option<Result<Chunk<'a>>> {
418        //Flip around option and result
419        match Chunk::read(&mut self.raw) {
420            Ok(Some(chunk)) => Some(Ok(chunk)),
421            Ok(None) => None,
422            Err(err) => {
423                //Ensure `Chunk::read` isn't called again, by setting read pointer to EOF (len 0)
424                //This is to prevent use of corrupted state (such as reading a new Chunk from the
425                //middle of a malformed message)
426                self.raw = &[];
427                Some(Err(err))
428            }
429        }
430    }
431}
432
433#[derive(Copy, Clone, Debug)]
434enum Chunk<'a> {
435    Header(Header, u16),
436    Track(&'a [u8]),
437}
438impl<'a> Chunk<'a> {
439    /// Should be called with a byte slice at least as large as the chunk (ideally until EOF).
440    /// The slice will be modified to point to the next chunk.
441    /// If we're *exactly* at EOF (slice length 0), returns a None signalling no more chunks.
442    fn read(raw: &mut &'a [u8]) -> Result<Option<Chunk<'a>>> {
443        Ok(loop {
444            if raw.is_empty() {
445                break None;
446            }
447            let id = raw
448                .split_checked(4)
449                .ok_or(err_invalid!("failed to read chunkid"))?;
450            let len = u32::read(raw).context(err_invalid!("failed to read chunklen"))?;
451            let chunkdata = match raw.split_checked(len as usize) {
452                Some(chunkdata) => chunkdata,
453                None => {
454                    if cfg!(feature = "strict") {
455                        bail!(err_malformed!("reached eof before chunk ended"));
456                    } else {
457                        //Just use the remainder of the file
458                        mem::replace(raw, &[])
459                    }
460                }
461            };
462            match id {
463                b"MThd" => {
464                    let (header, track_count) = Header::read(chunkdata)?;
465                    break Some(Chunk::Header(header, track_count));
466                }
467                b"MTrk" => {
468                    break Some(Chunk::Track(chunkdata));
469                }
470                //Unknown chunk, just ignore and read the next one
471                _ => (),
472            }
473        })
474    }
475
476    /// Write a header chunk into a writer.
477    fn write_header<W: Write>(header: &Header, track_count: usize, out: &mut W) -> WriteResult<W> {
478        let mut header_chunk = [0; 4 + 4 + 6];
479        let track_count = u16::try_from(track_count)
480            .map_err(|_| W::invalid_input("track count exceeds 16 bit range"))?;
481        let header = header.encode(track_count);
482        header_chunk[0..4].copy_from_slice(&b"MThd"[..]);
483        header_chunk[4..8].copy_from_slice(&(header.len() as u32).to_be_bytes()[..]);
484        header_chunk[8..].copy_from_slice(&header[..]);
485        out.write(&header_chunk[..])?;
486        Ok(())
487    }
488
489    /// Write a single track chunk using the probe method.
490    ///
491    /// When probing, the chunk is written twice: one to find out the length of the chunk and again
492    /// to actually write the chunk contents.
493    fn write_probe<W: Write>(
494        track: impl Iterator<Item = &'a TrackEvent<'a>> + Clone,
495        out: &mut W,
496    ) -> WriteResult<W> {
497        let mut counter = WriteCounter(0);
498        Self::write_raw(track.clone(), &mut counter).map_err(W::invalid_input)?;
499        let len = Self::check_len::<W, _>(counter.0)?;
500        let mut head = [b'M', b'T', b'r', b'k', 0, 0, 0, 0];
501        head[4..8].copy_from_slice(&len);
502        out.write(&head)?;
503        Self::write_raw(track, out)?;
504        Ok(())
505    }
506
507    /// Write a single chunk using the seek method.
508    ///
509    /// The chunk is written once, then the writer is seeked back and the chunk length is written
510    /// last.
511    fn write_seek<W: Write + Seek>(
512        track: impl Iterator<Item = &'a TrackEvent<'a>>,
513        out: &mut W,
514    ) -> WriteResult<W> {
515        out.write(b"MTrk\0\0\0\0")?;
516        let start = out.tell()?;
517        Self::write_raw(track, out)?;
518        let len = Self::check_len::<W, _>(out.tell()? - start)?;
519        out.write_at(&len, start - 4)?;
520        Ok(())
521    }
522
523    /// Write a chunk to an in-memory `Vec`.
524    ///
525    /// Because the output is in-memory, the chunk can simply wind back and write the chunk length
526    /// last.
527    #[cfg(feature = "alloc")]
528    fn write_to_vec(
529        track: impl Iterator<Item = &'a TrackEvent<'a>>,
530        out: &mut Vec<u8>,
531    ) -> WriteResult<Vec<u8>> {
532        let cap = (track.size_hint().0 as f32 * EVENTS_TO_BYTES) as usize;
533        out.clear();
534        out.reserve(8 + cap);
535        out.extend_from_slice(b"MTrk\0\0\0\0");
536        Self::write_raw(track, out)?;
537        let len = Self::check_len::<Vec<u8>, _>(out.len() - 8)?;
538        out[4..8].copy_from_slice(&len);
539        Ok(())
540    }
541
542    /// Auxiliary method. Iterate over the events of a track and write them out.
543    fn write_raw<W: Write>(
544        track: impl Iterator<Item = &'a TrackEvent<'a>>,
545        out: &mut W,
546    ) -> WriteResult<W> {
547        let mut running_status = None;
548        for ev in track {
549            ev.write(&mut running_status, out)?;
550        }
551        Ok(())
552    }
553
554    /// Auxiliary method. Given an arbitrary-width length, fit it into a 32-bit big-endian integer,
555    /// reporting an error if it does not fit.
556    fn check_len<W, T>(len: T) -> StdResult<[u8; 4], W::Error>
557    where
558        u32: TryFrom<T>,
559        W: Write,
560    {
561        let len = u32::try_from(len)
562            .map_err(|_| W::invalid_input("midi chunk size exceeds 32 bit range"))?;
563        Ok(len.to_be_bytes())
564    }
565}
566
567/// A MIDI file header, indicating metadata about the file.
568#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
569pub struct Header {
570    /// Information about how should the tracks be laid out when playing them back.
571    pub format: Format,
572    /// Tempo information about the file.
573    ///
574    /// Usually it's not possible to determine the timing of a file with just this field, the first
575    /// few events of the first track must be parsed in the best case, and in the worst case the
576    /// file might have changing tempos along the song.
577    pub timing: Timing,
578}
579impl Header {
580    /// Create a new header from its raw parts.
581    #[inline]
582    pub fn new(format: Format, timing: Timing) -> Header {
583        Header { format, timing }
584    }
585
586    /// Read the contents of a header chunk, including the `Header` and the track count.
587    fn read(mut raw: &[u8]) -> Result<(Header, u16)> {
588        let format = Format::read(&mut raw)?;
589        let track_count = u16::read(&mut raw)?;
590        let timing = Timing::read(&mut raw)?;
591        Ok((Header::new(format, timing), track_count))
592    }
593    fn encode(&self, track_count: u16) -> [u8; 6] {
594        let mut bytes = [0; 6];
595        bytes[0..2].copy_from_slice(&self.format.encode()[..]);
596        bytes[2..4].copy_from_slice(&track_count.to_be_bytes()[..]);
597        bytes[4..6].copy_from_slice(&self.timing.encode()[..]);
598        bytes
599    }
600}
601
602/// An iterator over all *tracks* in a Standard Midi File.
603/// Created by the [`parse`](fn.parse.html) function.
604///
605/// This type is always available, even in `no_std` environments.
606#[derive(Clone, Debug)]
607pub struct TrackIter<'a> {
608    chunks: ChunkIter<'a>,
609    track_count_hint: u16,
610}
611impl<'a> TrackIter<'a> {
612    /// Create an event iterator from raw SMF bytes, excluding the header.
613    ///
614    /// The main way to obtain raw SMF without a header is the [`unread`](#method.unread) method.
615    #[inline]
616    pub fn new(raw: &[u8]) -> TrackIter {
617        TrackIter {
618            chunks: ChunkIter::new(raw),
619            track_count_hint: 0,
620        }
621    }
622
623    /// Peek at the remaining unparsed bytes in the file.
624    #[inline]
625    pub fn unread(&self) -> &'a [u8] {
626        self.chunks.raw
627    }
628
629    /// Parse and collect the remaining unparsed tracks into a `Vec` of tracks.
630    ///
631    /// This function is only available with the `alloc` feature enabled.
632    #[cfg(feature = "alloc")]
633    pub fn collect_tracks(self) -> Result<Vec<Track<'a>>> {
634        self.generic_collect(EventIter::into_vec)
635    }
636
637    /// Parse and collect the remaining unparsed tracks into a `Vec` of tracks, keeping a mapping
638    /// to the original bytes that make up each event.
639    ///
640    /// This function is only available with the `alloc` feature enabled.
641    #[cfg(feature = "alloc")]
642    pub fn collect_bytemapped(self) -> Result<Vec<BytemappedTrack<'a>>> {
643        self.generic_collect(|events| events.bytemapped().into_vec())
644    }
645
646    #[cfg(feature = "alloc")]
647    #[inline]
648    fn generic_collect<T: Send + 'a>(
649        self,
650        collect: impl Fn(EventIter<'a>) -> Result<Vec<T>> + Send + Sync,
651    ) -> Result<Vec<Vec<T>>> {
652        //Attempt to use multiple threads if possible and advantageous
653        #[cfg(feature = "parallel")]
654        {
655            if self.unread().len() >= PARALLEL_ENABLE_THRESHOLD {
656                use rayon::prelude::*;
657
658                let chunk_vec = self.collect::<Result<Vec<_>>>()?;
659                return chunk_vec
660                    .into_par_iter()
661                    .map(collect)
662                    .collect::<Result<Vec<Vec<T>>>>();
663            }
664        }
665        //Fall back to single-threaded
666        self.map(|r| r.and_then(&collect))
667            .collect::<Result<Vec<Vec<T>>>>()
668    }
669}
670impl<'a> Iterator for TrackIter<'a> {
671    type Item = Result<EventIter<'a>>;
672
673    #[inline]
674    fn size_hint(&self) -> (usize, Option<usize>) {
675        (
676            self.track_count_hint as usize,
677            Some(self.track_count_hint as usize),
678        )
679    }
680
681    #[inline]
682    fn next(&mut self) -> Option<Result<EventIter<'a>>> {
683        loop {
684            if let Some(chunk) = self.chunks.next() {
685                self.track_count_hint = self.track_count_hint.saturating_sub(1);
686                match chunk {
687                    Ok(Chunk::Track(track)) => break Some(Ok(EventIter::new(track))),
688                    //Read another header (?)
689                    Ok(Chunk::Header(..)) => {
690                        if cfg!(feature = "strict") {
691                            break Some(Err(err_malformed!("found duplicate header").into()));
692                        } else {
693                            //Ignore duplicate header
694                        }
695                    }
696                    //Failed to read chunk
697                    Err(err) => {
698                        if cfg!(feature = "strict") {
699                            break Some(Err(err).context(err_malformed!("invalid chunk")));
700                        } else {
701                            //Ignore invalid chunk
702                        }
703                    }
704                }
705            } else {
706                break None;
707            }
708        }
709    }
710}
711
712trait EventKind<'a> {
713    type Event: 'a;
714    fn read_ev(raw: &mut &'a [u8], running_status: &mut Option<u8>) -> Result<Self::Event>;
715}
716
717#[derive(Clone, Debug)]
718struct EventIterGeneric<'a, T> {
719    raw: &'a [u8],
720    running_status: Option<u8>,
721    _kind: PhantomData<T>,
722}
723impl<'a, T: EventKind<'a>> EventIterGeneric<'a, T> {
724    #[inline]
725    fn new(raw: &[u8]) -> EventIterGeneric<T> {
726        EventIterGeneric {
727            raw,
728            running_status: None,
729            _kind: PhantomData,
730        }
731    }
732
733    /// Get the remaining unread bytes.
734    #[inline]
735    fn unread(&self) -> &'a [u8] {
736        self.raw
737    }
738
739    /// Get the current running status of the track.
740    #[inline]
741    fn running_status(&self) -> Option<u8> {
742        self.running_status
743    }
744
745    /// Modify the current running status of the track.
746    #[inline]
747    fn running_status_mut(&mut self) -> &mut Option<u8> {
748        &mut self.running_status
749    }
750
751    #[cfg(feature = "alloc")]
752    #[inline]
753    fn estimate_events(&self) -> usize {
754        (self.raw.len() as f32 * BYTES_TO_EVENTS) as usize
755    }
756
757    #[cfg(feature = "alloc")]
758    #[inline]
759    fn into_vec(mut self) -> Result<Vec<T::Event>> {
760        let mut events = Vec::with_capacity(self.estimate_events());
761        while !self.raw.is_empty() {
762            match T::read_ev(&mut self.raw, &mut self.running_status) {
763                Ok(ev) => events.push(ev),
764                Err(err) => {
765                    self.raw = &[];
766                    if cfg!(feature = "strict") {
767                        Err(err).context(err_malformed!("malformed event"))?;
768                    } else {
769                        //Stop reading track silently on failure
770                        break;
771                    }
772                }
773            }
774        }
775        Ok(events)
776    }
777}
778impl<'a, T: EventKind<'a>> Iterator for EventIterGeneric<'a, T> {
779    type Item = Result<T::Event>;
780    #[inline]
781    fn next(&mut self) -> Option<Self::Item> {
782        if !self.raw.is_empty() {
783            match T::read_ev(&mut self.raw, &mut self.running_status) {
784                Ok(ev) => Some(Ok(ev)),
785                Err(err) => {
786                    self.raw = &[];
787                    if cfg!(feature = "strict") {
788                        Some(Err(err).context(err_malformed!("malformed event")))
789                    } else {
790                        None
791                    }
792                }
793            }
794        } else {
795            None
796        }
797    }
798}
799
800/// An iterator over the events of a single track.
801/// Yielded by the [`TrackIter`](struct.TrackIter.html) iterator.
802///
803/// This iterator is lazy, it parses events as it goes, and therefore produces `Result<TrackEvent>>`
804/// rather than `TrackEvent`.
805///
806/// This type is always available, even in `no_std` environments.
807#[derive(Clone, Debug)]
808pub struct EventIter<'a> {
809    inner: EventIterGeneric<'a, Self>,
810}
811impl<'a> EventKind<'a> for EventIter<'a> {
812    type Event = TrackEvent<'a>;
813    #[inline]
814    fn read_ev(raw: &mut &'a [u8], rs: &mut Option<u8>) -> Result<TrackEvent<'a>> {
815        TrackEvent::read(raw, rs)
816    }
817}
818impl<'a> EventIter<'a> {
819    /// Create an event iterator from raw track bytes.
820    ///
821    /// It can be hard to obtain raw track bytes.
822    /// Usually these raw track bytes are obtained from the [`unread`](#method.unread) method on an
823    /// event iterator.
824    #[inline]
825    pub fn new(raw: &[u8]) -> EventIter {
826        EventIter {
827            inner: EventIterGeneric::new(raw),
828        }
829    }
830
831    /// Get the remaining unparsed event bytes.
832    #[inline]
833    pub fn unread(&self) -> &'a [u8] {
834        self.inner.unread()
835    }
836
837    /// Get the current running status of the track.
838    #[inline]
839    pub fn running_status(&self) -> Option<u8> {
840        self.inner.running_status()
841    }
842
843    /// Modify the current running status of the track.
844    #[inline]
845    pub fn running_status_mut(&mut self) -> &mut Option<u8> {
846        self.inner.running_status_mut()
847    }
848
849    /// Make this event iterator keep track of the raw bytes that make up each event.
850    #[inline]
851    pub fn bytemapped(self) -> EventBytemapIter<'a> {
852        EventBytemapIter {
853            inner: EventIterGeneric {
854                raw: self.inner.raw,
855                running_status: self.inner.running_status,
856                _kind: PhantomData,
857            },
858        }
859    }
860
861    /// Collects the remaining unparsed events into a `Track`.
862    ///
863    /// This function is a smarter version of `Iterator::collect`, as it guesses allocations and
864    /// is usually optimized better than its naive counterpart.
865    ///
866    /// This function is only available with the `alloc` feature enabled.
867    #[cfg(feature = "alloc")]
868    #[inline]
869    pub fn into_vec(self) -> Result<Track<'a>> {
870        self.inner.into_vec()
871    }
872}
873impl<'a> Iterator for EventIter<'a> {
874    type Item = Result<TrackEvent<'a>>;
875    #[inline]
876    fn next(&mut self) -> Option<Self::Item> {
877        self.inner.next()
878    }
879}
880
881/// An iterator over the events of a single track that keeps track of the raw bytes that make up
882/// each event.
883/// Created by the [`EventIter::bytemapped`](struct.EventIter.html#method.bytemapped) method.
884///
885/// This iterator is lazy, it parses events as it goes, and therefore produces
886/// `Result<(&[u8], TrackEvent)>>` rather than just `(&[u8], TrackEvent)`.
887///
888/// This type is always available, even in `no_std` environments.
889#[derive(Clone, Debug)]
890pub struct EventBytemapIter<'a> {
891    inner: EventIterGeneric<'a, Self>,
892}
893impl<'a> EventKind<'a> for EventBytemapIter<'a> {
894    type Event = (&'a [u8], TrackEvent<'a>);
895    #[inline]
896    fn read_ev(raw: &mut &'a [u8], rs: &mut Option<u8>) -> Result<Self::Event> {
897        TrackEvent::read_bytemap(raw, rs)
898    }
899}
900impl<'a> EventBytemapIter<'a> {
901    /// Create an event iterator from raw track bytes.
902    ///
903    /// It can be hard to obtain raw track bytes.
904    /// Usually these raw track bytes are obtained from the [`unread`](#method.unread) method on an
905    /// event iterator.
906    #[inline]
907    pub fn new(raw: &[u8]) -> EventBytemapIter {
908        EventBytemapIter {
909            inner: EventIterGeneric::new(raw),
910        }
911    }
912
913    /// Get the remaining unparsed event bytes.
914    #[inline]
915    pub fn unread(&self) -> &'a [u8] {
916        self.inner.unread()
917    }
918
919    /// Get the current running status of the track.
920    #[inline]
921    pub fn running_status(&self) -> Option<u8> {
922        self.inner.running_status()
923    }
924
925    /// Modify the current running status of the track.
926    #[inline]
927    pub fn running_status_mut(&mut self) -> &mut Option<u8> {
928        self.inner.running_status_mut()
929    }
930
931    /// Stop collecting bytemap information for any remaining events.
932    #[inline]
933    pub fn not_bytemapped(self) -> EventIter<'a> {
934        EventIter {
935            inner: EventIterGeneric {
936                raw: self.inner.raw,
937                running_status: self.inner.running_status,
938                _kind: PhantomData,
939            },
940        }
941    }
942
943    /// Collects the remaining unparsed events into a `Vec<(&[u8], TrackEvent)>`.
944    ///
945    /// This function is a smarter version of `Iterator::collect`, as it guesses allocations and
946    /// is usually optimized better than its naive counterpart.
947    ///
948    /// This function is only available with the `alloc` feature enabled.
949    #[cfg(feature = "alloc")]
950    #[inline]
951    pub fn into_vec(self) -> Result<Vec<(&'a [u8], TrackEvent<'a>)>> {
952        self.inner.into_vec()
953    }
954}
955impl<'a> Iterator for EventBytemapIter<'a> {
956    type Item = Result<(&'a [u8], TrackEvent<'a>)>;
957    #[inline]
958    fn next(&mut self) -> Option<Self::Item> {
959        self.inner.next()
960    }
961}