Files
songbird/src/events/data.rs
Kyle Simpson 94157b12bc Docs: Move to new intra-doc links, make events non-exhaustive. (#19)
Far cleaner and more reliable than the old doc-link pattern. Also allowed me to spot some event types and sources which should have been made non_exhaustive.
2020-11-24 19:52:23 +00:00

89 lines
2.6 KiB
Rust

use super::*;
use std::{cmp::Ordering, time::Duration};
/// Internal representation of an event, as handled by the audio context.
pub struct EventData {
pub(crate) event: Event,
pub(crate) fire_time: Option<Duration>,
pub(crate) action: Box<dyn EventHandler>,
}
impl EventData {
/// Create a representation of an event and its associated handler.
///
/// An event handler, `action`, receives an [`EventContext`] and optionally
/// produces a new [`Event`] type for itself. Returning `None` will
/// maintain the same event type, while removing any [`Delayed`] entries.
/// Event handlers will be re-added with their new trigger condition,
/// or removed if [`Cancel`]led
///
/// [`EventContext`]: EventContext
/// [`Event`]: Event
/// [`Delayed`]: Event::Delayed
/// [`Cancel`]: Event::Cancel
pub fn new<F: EventHandler + 'static>(event: Event, action: F) -> Self {
Self {
event,
fire_time: None,
action: Box::new(action),
}
}
/// Computes the next firing time for a timer event.
pub fn compute_activation(&mut self, now: Duration) {
match self.event {
Event::Periodic(period, phase) => {
self.fire_time = Some(now + phase.unwrap_or(period));
},
Event::Delayed(offset) => {
self.fire_time = Some(now + offset);
},
_ => {},
}
}
}
impl std::fmt::Debug for EventData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(
f,
"Event {{ event: {:?}, fire_time: {:?}, action: <fn> }}",
self.event, self.fire_time
)
}
}
/// Events are ordered/compared based on their firing time.
impl Ord for EventData {
fn cmp(&self, other: &Self) -> Ordering {
if self.fire_time.is_some() && other.fire_time.is_some() {
let t1 = self
.fire_time
.as_ref()
.expect("T1 known to be well-defined by above.");
let t2 = other
.fire_time
.as_ref()
.expect("T2 known to be well-defined by above.");
t1.cmp(&t2)
} else {
Ordering::Equal
}
}
}
impl PartialOrd for EventData {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for EventData {
fn eq(&self, other: &Self) -> bool {
self.fire_time == other.fire_time
}
}
impl Eq for EventData {}