Skip to content

Commit 44e451a

Browse files
committed
feat: payload from sysex packets
Allow payload bytes to be read from individual sysex packets. This should allow the use case where people don't handle the full message but manually buffer the payload on a per-packet basis.
1 parent 3f47e53 commit 44e451a

File tree

2 files changed

+412
-0
lines changed

2 files changed

+412
-0
lines changed

midi2/src/sysex7/packet.rs

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,72 @@ pub enum Status {
7171
End,
7272
}
7373

74+
pub struct PayloadIterator<'a> {
75+
data: &'a [u32; 2],
76+
index: usize,
77+
}
78+
79+
impl core::iter::Iterator for PayloadIterator<'_> {
80+
type Item = crate::ux::u7;
81+
fn next(&mut self) -> Option<Self::Item> {
82+
use crate::detail::BitOps;
83+
if self.index >= self.packet_size() {
84+
return None;
85+
}
86+
let v = self.data[(self.index + 2) / 4].septet((self.index + 2) % 4);
87+
self.index += 1;
88+
Some(v)
89+
}
90+
91+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
92+
use crate::detail::BitOps;
93+
if self.index + n >= self.packet_size() {
94+
self.index = (self.index + n).min(6);
95+
return None;
96+
}
97+
let v = self.data[(self.index + n + 2) / 4].septet((self.index + n + 2) % 4);
98+
self.index += n + 1;
99+
Some(v)
100+
}
101+
102+
fn size_hint(&self) -> (usize, Option<usize>) {
103+
let len = self.len();
104+
(len, Some(len))
105+
}
106+
107+
fn count(self) -> usize {
108+
self.len()
109+
}
110+
}
111+
112+
impl core::iter::FusedIterator for PayloadIterator<'_> {}
113+
114+
impl core::iter::ExactSizeIterator for PayloadIterator<'_> {
115+
fn len(&self) -> usize {
116+
self.packet_size() - self.index
117+
}
118+
}
119+
120+
impl PayloadIterator<'_> {
121+
fn packet_size(&self) -> usize {
122+
use crate::detail::BitOps;
123+
let len = u8::from(self.data[0].nibble(3)) as usize;
124+
debug_assert!(len <= 6);
125+
len
126+
}
127+
}
128+
74129
impl Packet {
75130
pub fn status(&self) -> Status {
76131
status_from_data(&self.0[..]).unwrap()
77132
}
133+
134+
pub fn payload(&self) -> PayloadIterator {
135+
PayloadIterator {
136+
data: &self.0,
137+
index: 0,
138+
}
139+
}
78140
}
79141

80142
fn status_from_data(data: &[u32]) -> Result<Status, error::InvalidData> {
@@ -168,4 +230,149 @@ mod tests {
168230
Status::End,
169231
);
170232
}
233+
234+
#[test]
235+
fn payload_empty() {
236+
assert_eq!(
237+
Packet::try_from(&[0x3000_0000, 0x0000_0000][..])
238+
.unwrap()
239+
.payload()
240+
.collect::<std::vec::Vec<ux::u7>>(),
241+
std::vec::Vec::<ux::u7>::new(),
242+
);
243+
}
244+
245+
#[test]
246+
fn payload_one_item() {
247+
assert_eq!(
248+
Packet::try_from(&[0x3001_7F00, 0x0000_0000][..])
249+
.unwrap()
250+
.payload()
251+
.collect::<std::vec::Vec<ux::u7>>(),
252+
std::vec![ux::u7::new(0x7F),]
253+
);
254+
}
255+
256+
#[test]
257+
fn payload_two_items() {
258+
assert_eq!(
259+
Packet::try_from(&[0x3002_0102, 0x0000_0000][..])
260+
.unwrap()
261+
.payload()
262+
.collect::<std::vec::Vec<ux::u7>>(),
263+
std::vec![ux::u7::new(0x01), ux::u7::new(0x02)],
264+
);
265+
}
266+
267+
#[test]
268+
fn payload_full_payload() {
269+
assert_eq!(
270+
Packet::try_from(&[0x3006_0102, 0x0304_0506][..])
271+
.unwrap()
272+
.payload()
273+
.collect::<std::vec::Vec<ux::u7>>(),
274+
std::vec![
275+
ux::u7::new(0x01),
276+
ux::u7::new(0x02),
277+
ux::u7::new(0x03),
278+
ux::u7::new(0x04),
279+
ux::u7::new(0x05),
280+
ux::u7::new(0x06),
281+
],
282+
);
283+
}
284+
285+
#[test]
286+
#[allow(clippy::iter_nth_zero)]
287+
fn payload_nth_0() {
288+
assert_eq!(
289+
Packet::try_from(&[0x3006_0102, 0x0304_0506][..])
290+
.unwrap()
291+
.payload()
292+
.nth(0),
293+
Some(ux::u7::new(0x01)),
294+
);
295+
}
296+
297+
#[test]
298+
fn payload_nth_1() {
299+
assert_eq!(
300+
Packet::try_from(&[0x3006_0102, 0x0304_0506][..])
301+
.unwrap()
302+
.payload()
303+
.nth(1),
304+
Some(ux::u7::new(0x02)),
305+
);
306+
}
307+
308+
#[test]
309+
fn payload_nth_5() {
310+
assert_eq!(
311+
Packet::try_from(&[0x3006_0102, 0x0304_0506][..])
312+
.unwrap()
313+
.payload()
314+
.nth(5),
315+
Some(ux::u7::new(0x06)),
316+
);
317+
}
318+
319+
#[test]
320+
fn payload_nth_6() {
321+
assert_eq!(
322+
Packet::try_from(&[0x3006_0102, 0x0304_0506][..])
323+
.unwrap()
324+
.payload()
325+
.nth(6),
326+
None,
327+
);
328+
}
329+
330+
#[test]
331+
fn payload_nth_6_followed_by_next_should_return_none() {
332+
let buffer = [0x3006_0102, 0x0304_0506];
333+
let message = Packet::try_from(&buffer[..]).unwrap();
334+
let mut iter = message.payload();
335+
assert_eq!(iter.nth(6), None);
336+
assert_eq!(iter.next(), None);
337+
}
338+
339+
#[test]
340+
fn payload_call_next_and_the_iterator_length_should_be_one_fewer() {
341+
let buffer = [0x3006_0102, 0x0304_0506];
342+
let message = Packet::try_from(&buffer[..]).unwrap();
343+
let mut iter = message.payload();
344+
assert_eq!(iter.len(), 6);
345+
iter.next();
346+
assert_eq!(iter.len(), 5);
347+
}
348+
349+
#[test]
350+
fn payload_exhaustive_nth_should_leave_iter_length_0() {
351+
let buffer = [0x3006_0102, 0x0304_0506];
352+
let message = Packet::try_from(&buffer[..]).unwrap();
353+
let mut iter = message.payload();
354+
assert_eq!(iter.len(), 6);
355+
iter.nth(6);
356+
assert_eq!(iter.len(), 0);
357+
}
358+
359+
#[test]
360+
fn payload_over_exhaustive_nth_should_leave_iter_length_0() {
361+
let buffer = [0x3006_0102, 0x0304_0506];
362+
let message = Packet::try_from(&buffer[..]).unwrap();
363+
let mut iter = message.payload();
364+
assert_eq!(iter.len(), 6);
365+
iter.nth(7);
366+
assert_eq!(iter.len(), 0);
367+
}
368+
369+
#[test]
370+
fn payload_nth_should_leave_iter_with_n_fewer_length() {
371+
let buffer = [0x3006_0102, 0x0304_0506];
372+
let message = Packet::try_from(&buffer[..]).unwrap();
373+
let mut iter = message.payload();
374+
assert_eq!(iter.len(), 6);
375+
iter.nth(2);
376+
assert_eq!(iter.len(), 3);
377+
}
171378
}

0 commit comments

Comments
 (0)