Skip to content

Commit 972f639

Browse files
Ben LeadbetterBenLeadbetter
authored andcommitted
feat!: packet types
Packet types for each ump message type. Messages are formed of packets. The Packets trait has Item = Packet.
1 parent 61ac321 commit 972f639

32 files changed

+1311
-87
lines changed

midi2_proc/src/derives.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,16 +375,25 @@ pub fn debug(item: TokenStream1) -> TokenStream1 {
375375
_ => panic!("Only enums and structs supported"),
376376
};
377377
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
378-
let buffer_id = common::buffer_generic(generics)
379-
.expect("Expected buffer generic")
380-
.ident();
378+
379+
let buffer_id = if ident == "Packet" {
380+
// special handling
381+
// always a u32 slice
382+
quote! {crate::buffer::UNIT_ID_U32}
383+
} else {
384+
let buffer_ident = common::buffer_generic(generics)
385+
.expect("Expected buffer generic")
386+
.ident();
387+
quote! {<<#buffer_ident as crate::buffer::Buffer>::Unit as crate::buffer::UnitPrivate>::UNIT_ID}
388+
};
389+
381390
quote! {
382391
impl #impl_generics core::fmt::Debug for #ident #ty_generics #where_clause {
383392
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
384393
use crate::BufferAccess as BufferAccessDeriveDebug;
385394

386395
fmt.write_fmt(format_args!("{}([", stringify!(#ident)))?;
387-
match <<#buffer_id as crate::buffer::Buffer>::Unit as crate::buffer::UnitPrivate>::UNIT_ID {
396+
match #buffer_id {
388397
crate::buffer::UNIT_ID_U8 => {
389398
use crate::buffer::SpecialiseU8 as SpecialiseU8DeriveDebug;
390399

midi2_proc/src/generate_ci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ fn try_from_slice_impl(root_ident: &syn::Ident, properties: &[Property]) -> Toke
542542
type Error = crate::error::InvalidData;
543543
fn try_from(buffer: &'a [u8]) -> core::result::Result<Self, Self::Error> {
544544
if buffer.len() < <Self as crate::traits::MinSize<&[u8]>>::MIN_SIZE {
545-
return Err(crate::error::InvalidData("Slice is too short"));
545+
return Err(crate::error::InvalidData(crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT));
546546
}
547547
if buffer[5] != VERSION {
548548
return Err(crate::error::InvalidData("Incorrect CI version"));

src/channel_voice1.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod control_change;
77
mod key_pressure;
88
mod note_off;
99
mod note_on;
10+
mod packet;
1011
mod pitch_bend;
1112
mod program_change;
1213

@@ -15,6 +16,7 @@ pub use control_change::*;
1516
pub use key_pressure::*;
1617
pub use note_off::*;
1718
pub use note_on::*;
19+
pub use packet::Packet;
1820
pub use pitch_bend::*;
1921
pub use program_change::*;
2022

@@ -52,7 +54,9 @@ impl<'a, U: crate::buffer::Unit> core::convert::TryFrom<&'a [U]> for ChannelVoic
5254
type Error = crate::error::InvalidData;
5355
fn try_from(buffer: &'a [U]) -> Result<Self, Self::Error> {
5456
if buffer.is_empty() {
55-
return Err(crate::error::InvalidData("Slice is too short"));
57+
return Err(crate::error::InvalidData(
58+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT,
59+
));
5660
};
5761
Ok(match status(buffer) {
5862
channel_pressure::STATUS => ChannelPressure::try_from(buffer)?.into(),
@@ -183,7 +187,7 @@ mod test {
183187
fn packets() {
184188
let message = ChannelVoice1::try_from(&[0x2FD6_0900_u32][..]).unwrap();
185189
let mut packets = message.packets();
186-
assert_eq!(packets.next(), Some(&[0x2FD6_0900_u32][..]));
190+
assert_eq!(&*packets.next().unwrap(), &[0x2FD6_0900_u32][..]);
187191
assert_eq!(packets.next(), None);
188192
}
189193

src/channel_voice1/channel_pressure.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ mod tests {
9797
fn from_empty_data() {
9898
assert_eq!(
9999
ChannelPressure::try_from(&<[u32; 0] as Default>::default()[..]),
100-
Err(crate::error::InvalidData("Slice is too short")),
100+
Err(crate::error::InvalidData(
101+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT
102+
)),
101103
);
102104
}
103105

src/channel_voice1/control_change.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ mod tests {
137137
let buffer = [0x2AB7_3637_u32];
138138
let message = ControlChange::try_from(&buffer[..]).unwrap();
139139
let mut packets = message.packets();
140-
assert_eq!(packets.next(), Some(&[0x2AB7_3637_u32][..]));
140+
assert_eq!(&*packets.next().unwrap(), &[0x2AB7_3637_u32][..]);
141141
assert_eq!(packets.next(), None);
142142
}
143143
}

src/channel_voice1/packet.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use crate::{channel_voice1, error};
2+
3+
#[derive(Eq, PartialEq, Clone, midi2_proc::Debug)]
4+
pub struct Packet(pub [u32; 1]);
5+
6+
impl crate::traits::BufferAccess<[u32; 1]> for Packet {
7+
fn buffer_access(&self) -> &[u32; 1] {
8+
&self.0
9+
}
10+
fn buffer_access_mut(&mut self) -> &mut [u32; 1]
11+
where
12+
[u32; 1]: crate::buffer::BufferMut,
13+
{
14+
&mut self.0
15+
}
16+
}
17+
18+
impl<'a> core::convert::TryFrom<&'a [u32]> for Packet {
19+
type Error = error::InvalidData;
20+
fn try_from(data: &'a [u32]) -> Result<Self, Self::Error> {
21+
if data.is_empty() {
22+
return Err(error::InvalidData(
23+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT,
24+
));
25+
}
26+
27+
use crate::detail::BitOps;
28+
if u8::from(data[0].nibble(0)) != channel_voice1::UMP_MESSAGE_TYPE {
29+
return Err(error::InvalidData(
30+
crate::detail::common_err_strings::ERR_INCORRECT_UMP_MESSAGE_TYPE,
31+
));
32+
}
33+
34+
Ok(Packet({
35+
let mut buffer = [0x0; 1];
36+
buffer[..data.len()].copy_from_slice(data);
37+
buffer
38+
}))
39+
}
40+
}
41+
42+
impl core::ops::Deref for Packet {
43+
type Target = [u32];
44+
fn deref(&self) -> &Self::Target {
45+
&self.0[..]
46+
}
47+
}
48+
49+
impl crate::Grouped<[u32; 1]> for Packet {
50+
fn group(&self) -> crate::ux::u4 {
51+
use crate::detail::BitOps;
52+
self.0[0].nibble(1)
53+
}
54+
fn set_group(&mut self, group: crate::ux::u4)
55+
where
56+
[u32; 1]: crate::buffer::BufferMut,
57+
{
58+
use crate::detail::BitOps;
59+
self.0[0].set_nibble(1, group);
60+
}
61+
}
62+
63+
impl crate::Channeled<[u32; 1]> for Packet {
64+
fn channel(&self) -> crate::ux::u4 {
65+
use crate::detail::BitOps;
66+
self.0[0].nibble(3)
67+
}
68+
fn set_channel(&mut self, channel: crate::ux::u4)
69+
where
70+
[u32; 1]: crate::buffer::BufferMut,
71+
{
72+
use crate::detail::BitOps;
73+
self.0[0].set_nibble(3, channel);
74+
}
75+
}
76+
77+
#[cfg(test)]
78+
mod tests {
79+
use super::*;
80+
use pretty_assertions::assert_eq;
81+
82+
#[test]
83+
fn construction() {
84+
assert!(Packet::try_from(&[0x2000_0000][..]).is_ok());
85+
}
86+
87+
#[test]
88+
fn construction_incorrect_ump_message_type() {
89+
assert_eq!(
90+
Packet::try_from(&[0x0000_0000][..]),
91+
Err(error::InvalidData(
92+
crate::detail::common_err_strings::ERR_INCORRECT_UMP_MESSAGE_TYPE
93+
)),
94+
);
95+
}
96+
97+
#[test]
98+
fn construction_short_slice() {
99+
assert_eq!(
100+
Packet::try_from(&[][..]),
101+
Err(error::InvalidData(
102+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT
103+
)),
104+
);
105+
}
106+
}

src/channel_voice2.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod controller;
1010
mod key_pressure;
1111
mod note_off;
1212
mod note_on;
13+
mod packet;
1314
mod per_note_management;
1415
mod per_note_pitch_bend;
1516
mod program_change;
@@ -28,6 +29,7 @@ pub use controller::Controller;
2829
pub use key_pressure::*;
2930
pub use note_off::*;
3031
pub use note_on::*;
32+
pub use packet::Packet;
3133
pub use per_note_management::*;
3234
pub use per_note_pitch_bend::*;
3335
pub use program_change::*;
@@ -74,7 +76,9 @@ impl<'a> TryFrom<&'a [u32]> for ChannelVoice2<&'a [u32]> {
7476
type Error = crate::error::InvalidData;
7577
fn try_from(buffer: &'a [u32]) -> Result<Self, Self::Error> {
7678
if buffer.is_empty() {
77-
return Err(crate::error::InvalidData("Slice is too short"));
79+
return Err(crate::error::InvalidData(
80+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT,
81+
));
7882
};
7983

8084
use crate::detail::BitOps;
@@ -148,7 +152,7 @@ mod test {
148152

149153
let message = ChannelVoice2::try_from(&[0x4BAC_5900, 0xC0B83064][..]).unwrap();
150154
let mut packets = message.packets();
151-
assert_eq!(packets.next(), Some(&[0x4BAC_5900, 0xC0B83064][..]));
155+
assert_eq!(&*packets.next().unwrap(), &[0x4BAC_5900, 0xC0B83064][..]);
152156
assert_eq!(packets.next(), None);
153157
}
154158

src/channel_voice2/assignable_controller.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ mod tests {
109109
let buffer = [0x4C38_5138, 0x3F3ADD42];
110110
let message = AssignableController::try_from(&buffer[..]).unwrap();
111111
let mut packets = message.packets();
112-
assert_eq!(packets.next(), Some(&[0x4C38_5138, 0x3F3ADD42][..]));
112+
assert_eq!(&*packets.next().unwrap(), &[0x4C38_5138, 0x3F3ADD42][..]);
113113
assert_eq!(packets.next(), None);
114114
}
115115
}

src/channel_voice2/packet.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use crate::{channel_voice2, error};
2+
3+
#[derive(Eq, PartialEq, Clone, midi2_proc::Debug)]
4+
pub struct Packet(pub(crate) [u32; 2]);
5+
6+
impl crate::traits::BufferAccess<[u32; 2]> for Packet {
7+
fn buffer_access(&self) -> &[u32; 2] {
8+
&self.0
9+
}
10+
fn buffer_access_mut(&mut self) -> &mut [u32; 2]
11+
where
12+
[u32; 2]: crate::buffer::BufferMut,
13+
{
14+
&mut self.0
15+
}
16+
}
17+
18+
impl<'a> core::convert::TryFrom<&'a [u32]> for Packet {
19+
type Error = error::InvalidData;
20+
fn try_from(data: &'a [u32]) -> Result<Self, Self::Error> {
21+
if data.is_empty() {
22+
return Err(error::InvalidData(
23+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT,
24+
));
25+
}
26+
27+
use crate::detail::BitOps;
28+
if u8::from(data[0].nibble(0)) != channel_voice2::UMP_MESSAGE_TYPE {
29+
return Err(error::InvalidData(
30+
crate::detail::common_err_strings::ERR_INCORRECT_UMP_MESSAGE_TYPE,
31+
));
32+
}
33+
34+
Ok(Packet({
35+
let mut buffer = [0x0; 2];
36+
buffer[..data.len()].copy_from_slice(data);
37+
buffer
38+
}))
39+
}
40+
}
41+
42+
impl core::ops::Deref for Packet {
43+
type Target = [u32];
44+
fn deref(&self) -> &Self::Target {
45+
&self.0[..]
46+
}
47+
}
48+
49+
impl crate::Grouped<[u32; 2]> for Packet {
50+
fn group(&self) -> crate::ux::u4 {
51+
use crate::detail::BitOps;
52+
self.0[0].nibble(1)
53+
}
54+
fn set_group(&mut self, group: crate::ux::u4)
55+
where
56+
[u32; 2]: crate::buffer::BufferMut,
57+
{
58+
use crate::detail::BitOps;
59+
self.0[0].set_nibble(1, group);
60+
}
61+
}
62+
63+
impl crate::Channeled<[u32; 2]> for Packet {
64+
fn channel(&self) -> crate::ux::u4 {
65+
use crate::detail::BitOps;
66+
self.0[0].nibble(3)
67+
}
68+
fn set_channel(&mut self, channel: crate::ux::u4)
69+
where
70+
[u32; 2]: crate::buffer::BufferMut,
71+
{
72+
use crate::detail::BitOps;
73+
self.0[0].set_nibble(3, channel);
74+
}
75+
}
76+
77+
#[cfg(test)]
78+
mod tests {
79+
use super::*;
80+
use pretty_assertions::assert_eq;
81+
82+
#[test]
83+
fn construction() {
84+
assert!(Packet::try_from(&[0x4000_0000][..]).is_ok());
85+
}
86+
87+
#[test]
88+
fn construction_incorrect_ump_message_type() {
89+
assert_eq!(
90+
Packet::try_from(&[0x0000_0000][..]),
91+
Err(error::InvalidData(
92+
crate::detail::common_err_strings::ERR_INCORRECT_UMP_MESSAGE_TYPE
93+
)),
94+
);
95+
}
96+
97+
#[test]
98+
fn construction_short_slice() {
99+
assert_eq!(
100+
Packet::try_from(&[][..]),
101+
Err(error::InvalidData(
102+
crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT
103+
)),
104+
);
105+
}
106+
}

src/detail.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod bit_ops;
22
mod encode_7bit;
33

4+
pub mod common_err_strings;
45
pub mod common_properties;
56
pub mod helpers;
67
pub mod property;

0 commit comments

Comments
 (0)