use crate::{
event::MidiMessage,
live::{LiveEvent, SystemRealtime},
prelude::*,
};
#[derive(Clone, Debug, Default)]
pub struct MidiStream<B = DefaultBuffer> {
status: Option<u8>,
data: B,
}
impl MidiStream {
#[inline]
pub fn new() -> MidiStream {
MidiStream::default()
}
}
impl<B: Buffer> MidiStream<B> {
#[inline]
pub fn with_buffer(mut buf: B) -> MidiStream<B> {
buf.clear();
MidiStream {
status: None,
data: buf,
}
}
#[inline]
fn event(&mut self, status: u8, mut handle_ev: impl FnMut(LiveEvent)) {
if let Ok(ev) = LiveEvent::read(status, self.data.as_slice()) {
handle_ev(ev);
}
}
#[inline]
fn feed_byte(&mut self, byte: u8, mut handle_ev: impl FnMut(LiveEvent)) {
if let Some(byte) = u7::try_from(byte) {
if let Some(status) = self.status {
match self.data.push(&[byte]) {
Ok(()) => {
if self.data.as_slice().len() == MidiMessage::msg_length(status) {
self.event(status, handle_ev);
self.data.clear();
}
}
Err(()) => {
self.status = None;
self.data.clear();
}
}
}
} else {
if let 0xF8..=0xFF = byte {
handle_ev(LiveEvent::Realtime(SystemRealtime::new(byte)));
} else {
if let Some(status) = self.status {
self.event(status, handle_ev);
}
self.status = Some(byte);
self.data.clear();
}
}
}
pub fn feed(&mut self, bytes: &[u8], mut handle_ev: impl FnMut(LiveEvent)) {
for &byte in bytes {
self.feed_byte(byte, &mut handle_ev);
}
}
pub fn flush(&mut self, handle_ev: impl FnMut(LiveEvent)) {
if let Some(status) = self.status.take() {
self.event(status, handle_ev);
self.status = None;
self.data.clear();
}
}
}
pub trait Buffer {
fn push(&mut self, data: &[u7]) -> StdResult<(), ()>;
fn clear(&mut self);
fn as_slice(&self) -> &[u7];
}
#[cfg(feature = "alloc")]
impl Buffer for Vec<u7> {
#[inline]
fn push(&mut self, data: &[u7]) -> StdResult<(), ()> {
self.extend_from_slice(data);
Ok(())
}
#[inline]
fn clear(&mut self) {
Vec::clear(self)
}
#[inline]
fn as_slice(&self) -> &[u7] {
self
}
}
#[macro_export]
macro_rules! stack_buffer {
{
@impl_def {$($attr:meta)*} {$($pub:ident)?} {$name:ident} {$size:expr}
} => {
$(#[$attr])*
#[derive(Clone)]
$($pub)? struct $name {
buf: [$crate::num::u7; $size],
len: usize,
}
impl core::hash::Hash for $name {
#[inline]
fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
h.write($crate::num::u7::slice_as_int(&self.buf[..self.len]));
h.write(&[0xFF]);
}
}
impl core::fmt::Debug for $name {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, concat!(stringify!($name), "["))?;
for databyte in self.buf.iter() {
write!(f, "{:02x}", databyte.as_int())?;
}
write!(f, "]")?;
Ok(())
}
}
impl $name {
pub const MAX_CAP: usize = $size;
#[inline]
$($pub)? const fn new() -> $name {
$name {
buf: [$crate::num::u7::new(0); $size],
len: 0,
}
}
}
impl core::default::Default for $name {
#[inline]
fn default() -> $name {
Self::new()
}
}
impl $crate::stream::Buffer for $name {
#[inline]
fn push(&mut self, data: &[$crate::num::u7]) -> core::result::Result<(), ()> {
let new_len = self.len + data.len();
if new_len > Self::MAX_CAP {
Err(())
} else {
self.buf[self.len..new_len].copy_from_slice(data);
self.len = new_len;
Ok(())
}
}
#[inline]
fn clear(&mut self) {
self.len = 0;
}
#[inline]
fn as_slice(&self) -> &[$crate::num::u7] {
&self.buf[..self.len]
}
}
};
{
$(#[$attr:meta])*
struct $name:ident([u8; $size:expr]);
}=> {
$crate::stack_buffer!(@impl_def {$($attr)*} {} {$name} {$size});
};
{
$(#[$attr:meta])*
pub struct $name:ident([u8; $size:expr]);
}=> {
$crate::stack_buffer!(@impl_def {$($attr)*} {pub} {$name} {$size});
};
}
macro_rules! default_buffer_def {
($($item:item)*) => {
#[derive(Clone, Hash, Default)]
$($item)*
};
}
pub use self::default_buf_impl::DefaultBuffer;
#[cfg(feature = "alloc")]
mod default_buf_impl {
use super::*;
default_buffer_def! {
pub struct DefaultBuffer {
buf: Vec<u7>,
}
}
impl fmt::Debug for DefaultBuffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DefaultBuffer[")?;
for databyte in self.buf.iter() {
write!(f, "{:02x}", databyte.as_int())?;
}
write!(f, "]")?;
Ok(())
}
}
impl DefaultBuffer {
const MAX_CAP: usize = 256 * 1024;
#[inline]
pub const fn max_cap(&self) -> usize {
Self::MAX_CAP
}
#[inline]
pub const fn new() -> DefaultBuffer {
DefaultBuffer { buf: Vec::new() }
}
}
impl Buffer for DefaultBuffer {
#[inline]
fn push(&mut self, data: &[u7]) -> StdResult<(), ()> {
if self.buf.len() + data.len() > Self::MAX_CAP {
Err(())
} else {
self.buf.extend_from_slice(data);
Ok(())
}
}
#[inline]
fn clear(&mut self) {
self.buf.clear()
}
#[inline]
fn as_slice(&self) -> &[u7] {
&self.buf[..]
}
}
}
#[cfg(not(feature = "alloc"))]
mod default_buf_impl {
use super::*;
default_buffer_def! {
pub struct DefaultBuffer {
buf: InnerBuf,
}
}
stack_buffer! {
struct InnerBuf([u8; 16*1024]);
}
impl fmt::Debug for DefaultBuffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.buf, f)
}
}
impl DefaultBuffer {
#[inline]
pub const fn max_cap(&self) -> usize {
InnerBuf::MAX_CAP
}
#[inline]
pub const fn new() -> DefaultBuffer {
DefaultBuffer {
buf: InnerBuf::new(),
}
}
}
impl Buffer for DefaultBuffer {
#[inline]
fn push(&mut self, data: &[u7]) -> StdResult<(), ()> {
self.buf.push(data)
}
#[inline]
fn clear(&mut self) {
self.buf.clear()
}
#[inline]
fn as_slice(&self) -> &[u7] {
self.buf.as_slice()
}
}
}