use crate::events::UnknownEvent;
use crate::events::io::implementation::{OutputEventBuffer, raw_output_events};
use crate::events::io::void_output_events;
use clap_sys::events::clap_output_events;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::marker::PhantomData;
#[repr(C)]
pub struct OutputEvents<'a> {
inner: clap_output_events,
_lifetime: PhantomData<(&'a clap_output_events, *const ())>,
}
impl<'a> OutputEvents<'a> {
#[inline]
pub const unsafe fn from_raw_mut(raw: &mut clap_output_events) -> &'a mut Self {
&mut *(raw as *mut _ as *mut _)
}
#[inline]
pub const fn as_raw(&mut self) -> &clap_output_events {
unsafe { &*(self as *const _ as *const _) }
}
#[inline]
pub const unsafe fn as_raw_mut(&mut self) -> &mut clap_output_events {
unsafe { &mut *(self as *mut _ as *mut _) }
}
#[inline]
pub const fn from_buffer<O: OutputEventBuffer>(buffer: &'a mut O) -> Self {
Self {
inner: raw_output_events(buffer),
_lifetime: PhantomData,
}
}
#[inline]
pub const fn void() -> Self {
Self {
inner: void_output_events(),
_lifetime: PhantomData,
}
}
#[inline]
pub fn try_push<E: AsRef<UnknownEvent>>(&mut self, event: E) -> Result<(), TryPushError> {
let try_push = self.inner.try_push.ok_or(TryPushError)?;
if !unsafe { try_push(&self.inner, event.as_ref().as_raw()) } {
Err(TryPushError {})
} else {
Ok(())
}
}
}
#[non_exhaustive]
#[derive(Debug, Default, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
pub struct TryPushError;
impl TryPushError {
#[inline]
pub const fn new() -> Self {
Self {}
}
}
impl Display for TryPushError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("Failed to push event into output event buffer")
}
}
impl Error for TryPushError {}
impl<'a, I: OutputEventBuffer> From<&'a mut I> for OutputEvents<'a> {
#[inline]
fn from(implementation: &'a mut I) -> Self {
Self::from_buffer(implementation)
}
}
impl OutputEventBuffer for OutputEvents<'_> {
#[inline]
fn try_push(&mut self, event: &UnknownEvent) -> Result<(), TryPushError> {
OutputEvents::try_push(self, event)
}
}
impl<'a: 'b, 'b> Extend<&'b UnknownEvent> for OutputEvents<'a> {
#[inline]
fn extend<T: IntoIterator<Item = &'b UnknownEvent>>(&mut self, iter: T) {
#[allow(unused_must_use)]
for event in iter {
self.try_push(event);
}
}
}
#[cfg(test)]
mod test {
extern crate static_assertions as sa;
use super::*;
sa::assert_not_impl_any!(OutputEvents<'static>: Send, Sync);
}