midi2-dev / bl-midi2-rs

Ergonomic, versatile, strong types wrapping MIDI 2.0 message data.
https://crates.io/crates/midi2
Apache License 2.0
18 stars 2 forks source link

Feature | Improve array constructors #19

Closed BenLeadbetter closed 1 month ago

BenLeadbetter commented 1 month ago

Context

In order to create a messages backed by a simple array (a pretty common use case) we had dedicated new_arr and new_arr_bytes constructors which would construct messages backed by [u32; 4] and [u8; 3] respectively. This was ok, but if I wanted to create a message backed with a [u32; 2] I would need to use try_new, even though I know at compile time that the buffer would be large enough to fit the message.

Additionally, the conversion traits FromUmp, IntoUmp, FromBytes, IntoBytes, RebufferFrom and RebufferInto would only be available in their fallible versions if the target message was an array because we didn't have compile-time checks on the minimum message size.

The Changes

new

All messages, when backed by an array type buffer have a new new constructor specialisation. The size of the target array is checked at compile time, so that new will be valid so long as the array has a size larger than the messages minimum representable size.

let sysex = Sysex7::<[u32; 2]>::new();
let big_sysex = Sysex7::<[u32; 16]>::new();
let small_sysex = Sysex7::<[u32; 1]>::new(); // won't compile

⚠️ Breaking Change ⚠️

We remove the new_arr and new_arr_bytes constructors in favour of using the more flexible and more consistent new constructor on the explicit array generic specialisation.

let message_128 = ChannelPressure::<[u32; 4]>::new();
let message_64 = ChannelPressure::<[u32; 2]>::new();

Conversion Traits

When message is fixed size and the target message is array-backed, and the array has a size greater than the smallest representable size for the message, the conversion traits FromUmp, IntoUmp, FromBytes, IntoBytes, RebufferFrom and RebufferInto can be used in their non-fallible forms.

let message = ChannelPressure::<[u8; 3]>::new();
let message: ChannelPressure<[u32; 4]> = message.into_ump();