Skip to main content

clack_common/events/io/
buffer.rs

1use crate::events::UnknownEvent;
2use crate::events::event_types::TransportEvent;
3use crate::events::io::implementation::{InputEventBuffer, OutputEventBuffer};
4use crate::events::io::{InputEvents, OutputEvents, TryPushError};
5use crate::utils::{check_clap_size_overflow, usize_to_clap_size};
6use clap_sys::events::clap_event_header;
7use core::mem::MaybeUninit;
8use std::fmt::{Debug, Formatter};
9use std::ops::{Index, Range};
10
11#[repr(C, align(8))]
12#[derive(Copy, Clone)]
13struct AlignedEventHeader(clap_event_header);
14
15/// A buffer for ordered storing of heterogeneous [`UnknownEvent`]s.
16///
17/// This type is useful for dynamic storage of arbitrary events, as [`UnknownEvent`]s are
18/// dynamically-sized types (DSTs) and can not be simply stored in e.g. a [`Vec`].
19///
20/// This type is also useful as the backing storage for plugin events, as it implements both the
21/// [`InputEventBuffer`] and the [`OutputEventBuffer`] traits.
22///
23/// # Example
24///
25/// ```
26/// use clack_common::events::event_types::ParamGestureBeginEvent;
27/// use clack_common::events::EventHeader;
28/// use clack_common::events::io::EventBuffer;
29/// use clack_common::utils::ClapId;
30///
31/// const MY_PARAM_ID: ClapId = ClapId::new(2);
32///
33/// let mut buffer = EventBuffer::new();
34/// assert!(buffer.is_empty());
35///
36/// let some_event = ParamGestureBeginEvent::new(6, MY_PARAM_ID);
37/// buffer.push(&some_event);
38/// assert_eq!(1, buffer.len());
39/// assert_eq!(&buffer[0], &some_event);
40/// ```
41///
42/// # Realtime Safety
43///
44/// This type is backed by `Vec` internally, and therefore holds similar realtime properties.
45/// Reading from it is always realtime-safe, but pushing new events to it may not be.
46///
47/// To avoid allocations, hosts should use the [`with_capacity`](EventBuffer::with_capacity)
48/// to pre-allocate a reasonable amount of space for plugins to send their events.
49///
50/// However, this is always a best-effort, and not a guarantee.
51pub struct EventBuffer {
52    headers: Vec<MaybeUninit<AlignedEventHeader>>, // force 64-bit alignment
53    indexes: Vec<usize>,
54}
55
56#[inline]
57pub(crate) fn byte_index_to_value_index<T>(size: usize) -> usize {
58    let type_size = size_of::<T>();
59    if type_size == 0 {
60        0
61    } else {
62        size.div_ceil(type_size)
63    }
64}
65
66impl EventBuffer {
67    /// Creates a new, empty [`EventBuffer`].
68    #[inline]
69    pub const fn new() -> Self {
70        Self {
71            headers: Vec::new(),
72            indexes: Vec::new(),
73        }
74    }
75
76    /// Creates a new empty [`EventBuffer`], but with enough pre-allocated capacity for the given
77    /// number of standard events.
78    ///
79    /// Because CLAP events can have any arbitrary size, this method can only pre-allocate on a
80    /// best-effort basis, only reserving enough space for the largest standard CLAP events.
81    ///
82    /// # Realtime Safety
83    ///
84    /// This method always allocates and is not realtime-safe, unless `events` is zero.
85    #[inline]
86    pub fn with_capacity(events: usize) -> Self {
87        Self {
88            // TransportEvent is the largest standard CLAP event.
89            headers: Vec::with_capacity(events * size_of::<TransportEvent>()),
90            indexes: Vec::with_capacity(events),
91        }
92    }
93
94    /// Clears the buffer, removing all events.
95    ///
96    /// Note that this has no effect on the allocated capacity of the buffer.
97    pub fn clear(&mut self) {
98        self.indexes.clear();
99        self.headers.clear();
100    }
101
102    /// Returns the number of events in this buffer.
103    #[inline]
104    pub fn len(&self) -> u32 {
105        #[allow(clippy::cast_possible_truncation)] // We always check this can never overflow u32
106        {
107            self.indexes.len() as u32
108        }
109    }
110
111    /// Returns `true` if this buffer has no events in it (i.e. if `len == 0`), `false` otherwise.
112    #[inline]
113    pub fn is_empty(&self) -> bool {
114        self.indexes.is_empty()
115    }
116
117    /// Returns the event located at the given `index`.
118    ///
119    /// If `index` is out of bounds, this returns [`None`].
120    pub fn get(&self, index: u32) -> Option<&UnknownEvent> {
121        let header_index = *self.indexes.get(index as usize)?;
122        // SAFETY: Registered indexes always have actual event headers written by append_header_data
123        // PANIC: We used registered indexes, this should never panic
124        let event = unsafe { self.headers[header_index].assume_init_ref() };
125        let event_size = event.0.size as usize;
126        let header_end_index =
127            byte_index_to_value_index::<AlignedEventHeader>(event_size) + header_index;
128
129        let event = &self.headers[header_index..header_end_index];
130
131        // SAFETY: we know the [0..event_size] slice is initialized
132        let event_bytes =
133            unsafe { core::slice::from_raw_parts(event.as_ptr() as *const u8, event_size) };
134
135        // SAFETY: the event header was written from a valid UnknownEvent in append_header_data
136        Some(unsafe { UnknownEvent::from_bytes_unchecked(event_bytes) })
137    }
138
139    /// Returns an iterator of all the events contained in this buffer.
140    #[inline]
141    pub fn iter(&self) -> EventBufferIter<'_> {
142        EventBufferIter {
143            buffer: self,
144            range: 0..self.len(),
145        }
146    }
147
148    /// Sorts the events contained in this buffer, based on their time.
149    ///
150    /// It is necessary to sort the events before passing them to a plugin.
151    pub fn sort(&mut self) {
152        // this needs to be an unstable sort, as the std stable sort might allocate
153        self.indexes.sort_unstable_by_key(|&i| {
154            // SAFETY: Registered indexes always have actual event headers written by append_header_data
155            // PANIC: We used registered indexes, this should never panic
156            let event = unsafe { self.headers[i].assume_init_ref() };
157            // include the original event index, so events with the same timestamp preserve insertion order
158            (event.0.time, i)
159        })
160    }
161
162    /// Inserts a given `event` at the given `position`, shifting all events after it to the right.
163    ///
164    /// # Panics
165    ///
166    /// Panics if `position > len`.
167    pub fn insert<E: AsRef<UnknownEvent> + ?Sized>(&mut self, event: &E, position: usize) {
168        let index = self.append_header_data(event.as_ref());
169        self.indexes.insert(position, index);
170    }
171
172    /// Pushes all events produced by the given `events` iterator at the end of the buffer.
173    pub fn push_all<'a, E: AsRef<UnknownEvent> + ?Sized + 'a>(
174        &mut self,
175        events: impl IntoIterator<Item = &'a E>,
176    ) {
177        for e in events {
178            self.push(e);
179        }
180    }
181
182    /// Pushes the given event into the buffer.
183    ///
184    /// The event is always added at the end of the buffer.
185    pub fn push<E: AsRef<UnknownEvent> + ?Sized>(&mut self, event: &E) {
186        // Check the event buffer length cound never overflows u32.
187        check_clap_size_overflow(self.indexes.len().saturating_add(1));
188
189        let index = self.append_header_data(event.as_ref());
190        self.indexes.push(index);
191    }
192
193    /// Produces an [`InputEvents`] that wraps this buffer as an [`InputEventBuffer`] implementation.
194    ///
195    /// This helper method is strictly equivalent to using [`InputEvents::from_buffer`].
196    #[inline]
197    pub fn as_input(&self) -> InputEvents<'_> {
198        InputEvents::from_buffer(self)
199    }
200
201    /// Produces an [`OutputEvents`] that wraps this buffer as an [`OutputEventBuffer`] implementation.
202    ///
203    /// This helper method is strictly equivalent to using [`OutputEvents::from_buffer`].
204    #[inline]
205    pub fn as_output(&mut self) -> OutputEvents<'_> {
206        OutputEvents::from_buffer(self)
207    }
208
209    fn append_header_data(&mut self, event: &UnknownEvent) -> usize {
210        let index = self.headers.len();
211        let event_bytes = event.as_bytes();
212        let bytes = self.allocate_mut(event_bytes.len());
213
214        // PANIC: bytes is guaranteed by allocate_mut to be just the right size
215        bytes.copy_from_slice(event_bytes);
216        index
217    }
218
219    fn allocate_mut(&mut self, byte_size: usize) -> &mut [u8] {
220        let previous_len = self.headers.len();
221        let headers_size = byte_index_to_value_index::<AlignedEventHeader>(byte_size);
222        self.headers
223            .resize(previous_len + headers_size, MaybeUninit::zeroed());
224
225        // PANIC: we just resized, this should not panic unless there is a bug in the implementation
226        let new_elements = &mut self.headers[previous_len..];
227
228        // SAFETY: casting anything to bytes is always safe
229        let new_bytes = unsafe {
230            core::slice::from_raw_parts_mut(
231                new_elements.as_mut_ptr() as *mut u8,
232                size_of_val(new_elements),
233            )
234        };
235
236        // PANIC: this should not panic unless there is a bug in the implementation
237        &mut new_bytes[..byte_size]
238    }
239}
240
241impl<'a> IntoIterator for &'a EventBuffer {
242    type Item = &'a UnknownEvent;
243    type IntoIter = EventBufferIter<'a>;
244
245    #[inline]
246    fn into_iter(self) -> Self::IntoIter {
247        self.iter()
248    }
249}
250
251impl InputEventBuffer for EventBuffer {
252    #[inline]
253    fn len(&self) -> u32 {
254        EventBuffer::len(self)
255    }
256
257    #[inline]
258    fn get(&self, index: u32) -> Option<&UnknownEvent> {
259        EventBuffer::get(self, index)
260    }
261}
262
263impl OutputEventBuffer for EventBuffer {
264    fn try_push(&mut self, event: &UnknownEvent) -> Result<(), TryPushError> {
265        self.push(event);
266
267        Ok(())
268    }
269}
270
271impl Default for EventBuffer {
272    #[inline]
273    fn default() -> Self {
274        Self::new()
275    }
276}
277
278impl Debug for EventBuffer {
279    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
280        let mut list = f.debug_list();
281        for event in self {
282            if let Some(event) = event.as_core_event() {
283                list.entry(&event);
284            } else {
285                list.entry(&event);
286            }
287        }
288
289        list.finish()
290    }
291}
292
293const INDEX_ERROR: &str = "Indexed EventBuffer out of bounds";
294
295impl Index<usize> for EventBuffer {
296    type Output = UnknownEvent;
297
298    #[inline]
299    fn index(&self, index: usize) -> &Self::Output {
300        self.get(usize_to_clap_size(index)).expect(INDEX_ERROR)
301    }
302}
303
304/// An iterator over the events contained in an [`EventBuffer`].
305pub struct EventBufferIter<'a> {
306    buffer: &'a EventBuffer,
307    range: Range<u32>,
308}
309
310impl<'a> Iterator for EventBufferIter<'a> {
311    type Item = &'a UnknownEvent;
312
313    fn next(&mut self) -> Option<Self::Item> {
314        let next_index = self.range.next()?;
315        self.buffer.get(next_index)
316    }
317}
318
319#[cfg(test)]
320mod test {
321    use crate::events::Event;
322    use crate::events::event_types::MidiEvent;
323    use crate::events::io::EventBuffer;
324
325    #[test]
326    fn it_works() {
327        let event_0 = MidiEvent::new(0, 0, [0; 3]);
328        let event_1 = MidiEvent::new(1, 0, [1; 3]);
329        let event_2 = MidiEvent::new(2, 0, [2; 3]);
330        let event_3 = MidiEvent::new(3, 0, [3; 3]);
331
332        let events_1 = [event_1, event_2];
333        let events_2 = [event_0, event_3];
334
335        let mut buffer = EventBuffer::new();
336        buffer.push_all(
337            [events_1, events_2]
338                .iter()
339                .flatten()
340                .map(|e| e.as_unknown()),
341        );
342
343        buffer.sort();
344
345        assert_eq!(Some(&event_0), buffer.get(0).unwrap().as_event());
346        assert_eq!(Some(&event_1), buffer.get(1).unwrap().as_event());
347        assert_eq!(Some(&event_2), buffer.get(2).unwrap().as_event());
348        assert_eq!(Some(&event_3), buffer.get(3).unwrap().as_event());
349    }
350}