use crate::events::UnknownEvent;
use crate::events::event_types::TransportEvent;
use crate::events::io::implementation::{InputEventBuffer, OutputEventBuffer};
use crate::events::io::{InputEvents, OutputEvents, TryPushError};
use crate::utils::{check_clap_size_overflow, usize_to_clap_size};
use clap_sys::events::clap_event_header;
use core::mem::MaybeUninit;
use std::fmt::{Debug, Formatter};
use std::ops::{Index, Range};
#[repr(C, align(8))]
#[derive(Copy, Clone)]
struct AlignedEventHeader(clap_event_header);
pub struct EventBuffer {
headers: Vec<MaybeUninit<AlignedEventHeader>>, indexes: Vec<usize>,
}
#[inline]
pub(crate) fn byte_index_to_value_index<T>(size: usize) -> usize {
let type_size = size_of::<T>();
if type_size == 0 {
0
} else {
size.div_ceil(type_size)
}
}
impl EventBuffer {
#[inline]
pub const fn new() -> Self {
Self {
headers: Vec::new(),
indexes: Vec::new(),
}
}
#[inline]
pub fn with_capacity(events: usize) -> Self {
Self {
headers: Vec::with_capacity(events * size_of::<TransportEvent>()),
indexes: Vec::with_capacity(events),
}
}
pub fn clear(&mut self) {
self.indexes.clear();
self.headers.clear();
}
#[inline]
pub fn len(&self) -> u32 {
#[allow(clippy::cast_possible_truncation)] {
self.indexes.len() as u32
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.indexes.is_empty()
}
pub fn get(&self, index: u32) -> Option<&UnknownEvent> {
let header_index = *self.indexes.get(index as usize)?;
let event = unsafe { self.headers[header_index].assume_init_ref() };
let event_size = event.0.size as usize;
let header_end_index =
byte_index_to_value_index::<AlignedEventHeader>(event_size) + header_index;
let event = &self.headers[header_index..header_end_index];
let event_bytes =
unsafe { core::slice::from_raw_parts(event.as_ptr() as *const u8, event_size) };
Some(unsafe { UnknownEvent::from_bytes_unchecked(event_bytes) })
}
#[inline]
pub fn iter(&self) -> EventBufferIter<'_> {
EventBufferIter {
buffer: self,
range: 0..self.len(),
}
}
pub fn sort(&mut self) {
self.indexes.sort_unstable_by_key(|i| {
let event = unsafe { self.headers[*i].assume_init_ref() };
event.0.time
})
}
pub fn insert<E: AsRef<UnknownEvent> + ?Sized>(&mut self, event: &E, position: usize) {
let index = self.append_header_data(event.as_ref());
self.indexes.insert(position, index);
}
pub fn push_all<'a, E: AsRef<UnknownEvent> + ?Sized + 'a>(
&mut self,
events: impl IntoIterator<Item = &'a E>,
) {
for e in events {
self.push(e);
}
}
pub fn push<E: AsRef<UnknownEvent> + ?Sized>(&mut self, event: &E) {
check_clap_size_overflow(self.indexes.len().saturating_add(1));
let index = self.append_header_data(event.as_ref());
self.indexes.push(index);
}
#[inline]
pub fn as_input(&self) -> InputEvents<'_> {
InputEvents::from_buffer(self)
}
#[inline]
pub fn as_output(&mut self) -> OutputEvents<'_> {
OutputEvents::from_buffer(self)
}
fn append_header_data(&mut self, event: &UnknownEvent) -> usize {
let index = self.headers.len();
let event_bytes = event.as_bytes();
let bytes = self.allocate_mut(event_bytes.len());
bytes.copy_from_slice(event_bytes);
index
}
fn allocate_mut(&mut self, byte_size: usize) -> &mut [u8] {
let previous_len = self.headers.len();
let headers_size = byte_index_to_value_index::<AlignedEventHeader>(byte_size);
self.headers
.resize(previous_len + headers_size, MaybeUninit::zeroed());
let new_elements = &mut self.headers[previous_len..];
let new_bytes = unsafe {
core::slice::from_raw_parts_mut(
new_elements.as_mut_ptr() as *mut u8,
size_of_val(new_elements),
)
};
&mut new_bytes[..byte_size]
}
}
impl<'a> IntoIterator for &'a EventBuffer {
type Item = &'a UnknownEvent;
type IntoIter = EventBufferIter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl InputEventBuffer for EventBuffer {
#[inline]
fn len(&self) -> u32 {
EventBuffer::len(self)
}
#[inline]
fn get(&self, index: u32) -> Option<&UnknownEvent> {
EventBuffer::get(self, index)
}
}
impl OutputEventBuffer for EventBuffer {
fn try_push(&mut self, event: &UnknownEvent) -> Result<(), TryPushError> {
self.push(event);
Ok(())
}
}
impl Default for EventBuffer {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl Debug for EventBuffer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut list = f.debug_list();
for event in self {
if let Some(event) = event.as_core_event() {
list.entry(&event);
} else {
list.entry(&event);
}
}
list.finish()
}
}
const INDEX_ERROR: &str = "Indexed EventBuffer out of bounds";
impl Index<usize> for EventBuffer {
type Output = UnknownEvent;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
self.get(usize_to_clap_size(index)).expect(INDEX_ERROR)
}
}
pub struct EventBufferIter<'a> {
buffer: &'a EventBuffer,
range: Range<u32>,
}
impl<'a> Iterator for EventBufferIter<'a> {
type Item = &'a UnknownEvent;
fn next(&mut self) -> Option<Self::Item> {
let next_index = self.range.next()?;
self.buffer.get(next_index)
}
}
#[cfg(test)]
mod test {
use crate::events::Event;
use crate::events::event_types::MidiEvent;
use crate::events::io::EventBuffer;
#[test]
fn it_works() {
let event_0 = MidiEvent::new(0, 0, [0; 3]);
let event_1 = MidiEvent::new(1, 0, [1; 3]);
let event_2 = MidiEvent::new(2, 0, [2; 3]);
let event_3 = MidiEvent::new(3, 0, [3; 3]);
let events_1 = [event_1, event_2];
let events_2 = [event_0, event_3];
let mut buffer = EventBuffer::new();
buffer.push_all(
[events_1, events_2]
.iter()
.flatten()
.map(|e| e.as_unknown()),
);
buffer.sort();
assert_eq!(Some(&event_0), buffer.get(0).unwrap().as_event());
assert_eq!(Some(&event_1), buffer.get(1).unwrap().as_event());
assert_eq!(Some(&event_2), buffer.get(2).unwrap().as_event());
assert_eq!(Some(&event_3), buffer.get(3).unwrap().as_event());
}
}