1use crate::types::*;
2
3use core::{mem, slice};
4
5pub trait Parse<Input>: Sized {
7 fn parse(input: Input) -> Option<Self>;
8}
9
10impl<'src> Parse<&'src [u8]> for Event<'src> {
11 #[inline]
12 fn parse(input: &[u8]) -> Option<Event> {
13 let first = input.get(0)?;
14 match first & 0xF0 {
15 0x80 => {
16 let velocity = *input.get(2)?;
17 let note = *input.get(1)?;
18 Some(Event::Midi(MidiEvent {
19 channel: first & 0x0F,
20 event: MidiEventType::NoteOff(note.into(), velocity & 0x7F),
21 }))
22 }
23 0x90 => {
24 let velocity = *input.get(2)?;
25 let note = *input.get(1)?;
26 Some(Event::Midi(MidiEvent {
27 channel: first & 0x0F,
28 event: MidiEventType::NoteOn(note.into(), velocity & 0x7F),
29 }))
30 }
31 0xA0 => {
32 let pressure = *input.get(2)?;
33 let note = *input.get(1)?;
34 Some(Event::Midi(MidiEvent {
35 channel: first & 0x0F,
36 event: MidiEventType::PolyphonicPressure(note.into(), pressure & 0x7F),
37 }))
38 }
39 0xB0 => {
40 let value = *input.get(2)?;
41 let controller = *input.get(1)?;
42 Some(Event::Midi(MidiEvent {
43 channel: first & 0x0F,
44 event: MidiEventType::Controller(controller & 0x7F, value & 0x7F),
45 }))
46 }
47 0xC0 => {
48 let program = *input.get(1)?;
49 Some(Event::Midi(MidiEvent {
50 channel: first & 0x0F,
51 event: MidiEventType::ProgramChange(program & 0x7F),
52 }))
53 }
54 0xD0 => {
55 let pressure = *input.get(1)?;
56 Some(Event::Midi(MidiEvent {
57 channel: first & 0x0F,
58 event: MidiEventType::ChannelPressure(pressure & 0x7F),
59 }))
60 }
61 0xE0 => {
62 let msb = *input.get(2)?;
63 let lsb = *input.get(1)?;
64 Some(Event::Midi(MidiEvent {
65 channel: first & 0x0F,
66 event: MidiEventType::PitchBend(lsb & 0x7F, msb & 0x7F),
67 }))
68 }
69 0xF0 => match first & 0x0F {
70 0x00 => {
71 let mut end_idx = 0;
72 loop {
73 match input.get(end_idx) {
74 Some(0xF7) | None => break,
75 _ => (),
76 }
77 end_idx += 1;
78 }
79 unsafe {
80 let pointer = input.as_ptr().offset(1);
81 Some(Event::SysEx(slice::from_raw_parts(pointer, end_idx - 1)))
82 }
83 }
84 _ => None,
85 },
86 _ => None,
87 }
88 }
89}
90
91impl Parse<&'_ [u8]> for MidiEvent {
92 #[inline]
93 fn parse(input: &[u8]) -> Option<MidiEvent> {
94 match Event::parse(input) {
95 Some(Event::Midi(evt)) => Some(evt),
96 _ => None,
97 }
98 }
99}
100
101impl Parse<u8> for Note {
102 #[inline]
103 fn parse(input: u8) -> Option<Self> {
104 if input & 0x80 == 0x80 {
105 None
106 } else {
107 Some(unsafe { mem::transmute(input) })
108 }
109 }
110}