Skip to content

Commit f196aac

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 edd5ca2 commit f196aac

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
@@ -75,10 +75,72 @@ pub enum Status {
7575
End,
7676
}
7777

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

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

0 commit comments

Comments
 (0)