midi2 0.11.1

Ergonomic, versatile, strong types wrapping MIDI 2.0 message data.
Documentation
use crate::{
    detail::{BitOps, Encode7Bit},
    ux::{u14, u4, u7},
};

pub trait UmpSchema {}
pub trait BytesSchema {}

pub trait UmpSchemaRepr<U: UmpSchema>: Sized {
    fn read(buffer: &[u32]) -> Self;
    fn write(buffer: &mut [u32], value: Self);
}

pub trait BytesSchemaRepr<U: BytesSchema>: Sized {
    fn read(buffer: &[u8]) -> Self;
    fn write(buffer: &mut [u8], value: Self);
}

pub struct Ump<const D1: u32, const D2: u32, const D3: u32, const D4: u32>;
pub struct Bytes<const B1: u8, const B2: u8, const B3: u8>;

impl<const D1: u32, const D2: u32, const D3: u32, const D4: u32> UmpSchema for Ump<D1, D2, D3, D4> {}
impl<const B1: u8, const B2: u8, const B3: u8> BytesSchema for Bytes<B1, B2, B3> {}

macro_rules! bool_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr,$bit_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for bool {
            fn read(buffer: &[u32]) -> Self {
                buffer[$buffer_index].bit($bit_index)
            }
            fn write(buffer: &mut [u32], v: Self) {
                buffer[$buffer_index].set_bit($bit_index, v);
            }
        }
    };
}

bool_ump_property_impl!(0x0000_0001, 0x0, 0x0, 0x0, 0, 31);
bool_ump_property_impl!(0x0000_0002, 0x0, 0x0, 0x0, 0, 30);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0000_0000_0001,
    0x0,
    0x0,
    1,
    31
);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0000_0000_0010,
    0x0,
    0x0,
    1,
    30
);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0000_0000_0100,
    0x0,
    0x0,
    1,
    29
);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0000_0000_1000,
    0x0,
    0x0,
    1,
    28
);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0000_0001_0000,
    0x0,
    0x0,
    1,
    27
);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0001_0000_0000,
    0x0,
    0x0,
    1,
    23
);
bool_ump_property_impl!(
    0x0,
    0b0000_0000_0000_0000_0000_0010_0000_0000,
    0x0,
    0x0,
    1,
    22
);
bool_ump_property_impl!(
    0b0000_0000_0000_0000_1000_0000_0000_0000,
    0x0,
    0x0,
    0x0,
    0,
    16
);
bool_ump_property_impl!(
    0x0,
    0b1000_0000_0000_0000_0000_0000_0000_0000,
    0x0,
    0x0,
    1,
    0
);

macro_rules! u4_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr,$nibble_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for u4 {
            fn read(buffer: &[u32]) -> Self {
                buffer[$buffer_index].nibble($nibble_index)
            }
            fn write(buffer: &mut [u32], v: Self) {
                buffer[$buffer_index].set_nibble($nibble_index, v);
            }
        }
    };
}

u4_ump_property_impl!(0xF000_0000, 0x0, 0x0, 0x0, 0, 0);
u4_ump_property_impl!(0x0F00_0000, 0x0, 0x0, 0x0, 0, 1);
u4_ump_property_impl!(0x00F0_0000, 0x0, 0x0, 0x0, 0, 2);
u4_ump_property_impl!(0x000F_0000, 0x0, 0x0, 0x0, 0, 3);
u4_ump_property_impl!(0x0000_F000, 0x0, 0x0, 0x0, 0, 4);
u4_ump_property_impl!(0x0000_0F00, 0x0, 0x0, 0x0, 0, 5);
u4_ump_property_impl!(0x0000_00F0, 0x0, 0x0, 0x0, 0, 6);
u4_ump_property_impl!(0x0000_000F, 0x0, 0x0, 0x0, 0, 7);
u4_ump_property_impl!(0x0, 0x0F00_0000, 0x0, 0x0, 1, 1);

macro_rules! u4_bytes_property_impl {
    ($bytes1:expr,$bytes2:expr,$bytes3:expr,$buffer_index:expr,$nibble_index:expr) => {
        impl BytesSchemaRepr<Bytes<$bytes1, $bytes2, $bytes3>> for u4 {
            fn read(buffer: &[u8]) -> Self {
                buffer[$buffer_index].nibble($nibble_index)
            }
            fn write(buffer: &mut [u8], v: Self) {
                buffer[$buffer_index].set_nibble($nibble_index, v);
            }
        }
    };
}

u4_bytes_property_impl!(0xF0, 0x0, 0x0, 0, 0);
u4_bytes_property_impl!(0x0F, 0x0, 0x0, 0, 1);
u4_bytes_property_impl!(0x0, 0xF0, 0x0, 1, 0);
u4_bytes_property_impl!(0x0, 0x0F, 0x0, 1, 1);
u4_bytes_property_impl!(0x0, 0x0, 0xF0, 2, 0);
u4_bytes_property_impl!(0x0, 0x0, 0x0F, 2, 1);

macro_rules! u7_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr,$octet_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for u7 {
            fn read(buffer: &[u32]) -> Self {
                buffer[$buffer_index].septet($octet_index)
            }
            fn write(buffer: &mut [u32], v: Self) {
                buffer[$buffer_index].set_septet($octet_index, (v));
            }
        }
    };
}

u7_ump_property_impl!(0x7F00_0000, 0x0, 0x0, 0x0, 0, 0);
u7_ump_property_impl!(0x007F_0000, 0x0, 0x0, 0x0, 0, 1);
u7_ump_property_impl!(0x0000_7F00, 0x0, 0x0, 0x0, 0, 2);
u7_ump_property_impl!(0x0000_007F, 0x0, 0x0, 0x0, 0, 3);
u7_ump_property_impl!(0x0, 0x7F00_0000, 0x0, 0x0, 1, 0);
u7_ump_property_impl!(0x0, 0x007F_0000, 0x0, 0x0, 1, 1);
u7_ump_property_impl!(0x0, 0x0000_7F00, 0x0, 0x0, 1, 2);
u7_ump_property_impl!(0x0, 0x0000_007F, 0x0, 0x0, 1, 3);

macro_rules! u7_bytes_property_impl {
    ($bytes1:expr,$bytes2:expr,$bytes3:expr,$buffer_index:expr) => {
        impl BytesSchemaRepr<Bytes<$bytes1, $bytes2, $bytes3>> for u7 {
            fn read(buffer: &[u8]) -> Self {
                buffer[$buffer_index].septet(0)
            }
            fn write(buffer: &mut [u8], v: Self) {
                buffer[$buffer_index].set_septet(0, v);
            }
        }
    };
}

u7_bytes_property_impl!(0x7F, 0x0, 0x0, 0);
u7_bytes_property_impl!(0x0, 0x7F, 0x0, 1);
u7_bytes_property_impl!(0x0, 0x0, 0x7F, 2);

macro_rules! u8_bytes_property_impl {
    ($bytes1:expr,$bytes2:expr,$bytes3:expr,$buffer_index:expr) => {
        impl BytesSchemaRepr<Bytes<$bytes1, $bytes2, $bytes3>> for u8 {
            fn read(buffer: &[u8]) -> Self {
                buffer[$buffer_index]
            }
            fn write(buffer: &mut [u8], v: Self) {
                buffer[$buffer_index] = v;
            }
        }
    };
}

u8_bytes_property_impl!(0xFF, 0x0, 0x0, 0);
u8_bytes_property_impl!(0x0, 0xFF, 0x0, 1);
u8_bytes_property_impl!(0x0, 0x0, 0xFF, 2);

macro_rules! u8_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr,$octet_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for u8 {
            fn read(buffer: &[u32]) -> Self {
                buffer[$buffer_index].octet($octet_index)
            }
            fn write(buffer: &mut [u32], v: Self) {
                buffer[$buffer_index].set_octet($octet_index, v);
            }
        }
    };
}

u8_ump_property_impl!(0xFF00_0000, 0x0, 0x0, 0x0, 0, 0);
u8_ump_property_impl!(0x00FF_0000, 0x0, 0x0, 0x0, 0, 1);
u8_ump_property_impl!(0x0000_FF00, 0x0, 0x0, 0x0, 0, 2);
u8_ump_property_impl!(0x0000_00FF, 0x0, 0x0, 0x0, 0, 3);
u8_ump_property_impl!(0x0, 0xFF00_0000, 0x0, 0x0, 1, 0);
u8_ump_property_impl!(0x0, 0x00FF_0000, 0x0, 0x0, 1, 1);
u8_ump_property_impl!(0x0, 0x0000_FF00, 0x0, 0x0, 1, 2);
u8_ump_property_impl!(0x0, 0x0000_00FF, 0x0, 0x0, 1, 3);
u8_ump_property_impl!(0x0, 0x0, 0xFF00_0000, 0x0, 2, 0);
u8_ump_property_impl!(0x0, 0x0, 0x00FF_0000, 0x0, 2, 1);
u8_ump_property_impl!(0x0, 0x0, 0x0000_FF00, 0x0, 2, 2);
u8_ump_property_impl!(0x0, 0x0, 0x0000_00FF, 0x0, 2, 3);
u8_ump_property_impl!(0x0, 0x0, 0x0, 0xFF00_0000, 3, 0);
u8_ump_property_impl!(0x0, 0x0, 0x0, 0x00FF_0000, 3, 1);
u8_ump_property_impl!(0x0, 0x0, 0x0, 0x0000_FF00, 3, 2);
u8_ump_property_impl!(0x0, 0x0, 0x0, 0x0000_00FF, 3, 3);

macro_rules! u14_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr,$word_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for u14 {
            fn read(buffer: &[u32]) -> Self {
                u14::from_u7s(&[
                    buffer[$buffer_index].septet(2 * $word_index),
                    buffer[$buffer_index].septet(2 * $word_index + 1),
                ])
            }
            fn write(buffer: &mut [u32], v: Self) {
                let mut u7s = [u7::default(); 2];
                v.to_u7s(&mut u7s);
                buffer[$buffer_index].set_septet(2 * $word_index, u7s[0]);
                buffer[$buffer_index].set_septet(2 * $word_index + 1, u7s[1]);
            }
        }
    };
}

u14_ump_property_impl!(0x7F7F_0000, 0x0, 0x0, 0x0, 0, 0);
u14_ump_property_impl!(0x0000_7F7F, 0x0, 0x0, 0x0, 0, 1);
u14_ump_property_impl!(0x0, 0x7F7F_0000, 0x0, 0x0, 1, 0);
u14_ump_property_impl!(0x0, 0x0000_7F7F, 0x0, 0x0, 1, 1);
u14_ump_property_impl!(0x0, 0x0, 0x7F7F_0000, 0x0, 2, 0);
u14_ump_property_impl!(0x0, 0x0, 0x0000_7F7F, 0x0, 2, 1);
u14_ump_property_impl!(0x0, 0x0, 0x0, 0x7F7F_0000, 3, 0);
u14_ump_property_impl!(0x0, 0x0, 0x0, 0x0000_7F7F, 3, 1);

impl BytesSchemaRepr<Bytes<0x0, 0x7F, 0x7F>> for u14 {
    fn read(buffer: &[u8]) -> Self {
        u14::from_u7s(&[buffer[1].septet(0), buffer[2].septet(0)])
    }
    fn write(buffer: &mut [u8], v: Self) {
        let mut u7s = [u7::default(); 2];
        v.to_u7s(&mut u7s);
        buffer[1].set_septet(0, u7s[0]);
        buffer[2].set_septet(0, u7s[1]);
    }
}

macro_rules! u16_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr,$word_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for u16 {
            fn read(buffer: &[u32]) -> Self {
                buffer[$buffer_index].word($word_index)
            }
            fn write(buffer: &mut [u32], v: Self) {
                buffer[$buffer_index].set_word($word_index, v);
            }
        }
    };
}

u16_ump_property_impl!(0xFFFF_0000, 0x0, 0x0, 0x0, 0, 0);
u16_ump_property_impl!(0x0000_FFFF, 0x0, 0x0, 0x0, 0, 1);
u16_ump_property_impl!(0x0, 0xFFFF_0000, 0x0, 0x0, 1, 0);
u16_ump_property_impl!(0x0, 0x0000_FFFF, 0x0, 0x0, 1, 1);
u16_ump_property_impl!(0x0, 0x0, 0xFFFF_0000, 0x0, 2, 0);
u16_ump_property_impl!(0x0, 0x0, 0x0000_FFFF, 0x0, 2, 1);
u16_ump_property_impl!(0x0, 0x0, 0x0, 0xFFFF_0000, 3, 0);
u16_ump_property_impl!(0x0, 0x0, 0x0, 0x0000_FFFF, 3, 1);

macro_rules! u32_ump_property_impl {
    ($ump1:expr,$ump2:expr,$ump3:expr,$ump4:expr,$buffer_index:expr) => {
        impl UmpSchemaRepr<Ump<$ump1, $ump2, $ump3, $ump4>> for u32 {
            fn read(buffer: &[u32]) -> Self {
                buffer[$buffer_index]
            }
            fn write(buffer: &mut [u32], v: Self) {
                buffer[$buffer_index] = v;
            }
        }
    };
}

u32_ump_property_impl!(0xFFFF_FFFF, 0x0, 0x0, 0x0, 0);
u32_ump_property_impl!(0x0, 0xFFFF_FFFF, 0x0, 0x0, 1);
u32_ump_property_impl!(0x0, 0x0, 0xFFFF_FFFF, 0x0, 2);
u32_ump_property_impl!(0x0, 0x0, 0x0, 0xFFFF_FFFF, 3);