#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(all(feature = "tao", feature = "winit", not(docsrs)))]
compile_error!("features `tao` and `winit` are mutually exclusive");
#[cfg(not(any(feature = "tao", feature = "winit")))]
compile_error!("enable exactly one backend feature: `tao` or `winit`");
mod block_on;
#[cfg(feature = "event")]
pub mod event;
use std::fmt;
use std::future::Future;
#[cfg(feature = "event")]
use std::ops::AsyncFnOnce;
#[cfg(any(
all(feature = "tao", not(target_os = "ios")),
all(feature = "winit", not(any(target_os = "ios", target_arch = "wasm32")))
))]
pub trait EventLoopBlockOn {
fn block_on<F>(&mut self, future: F) -> Result<F::Output, BlockOnError>
where
F: Future;
#[cfg(feature = "event")]
fn block_on_with_events<F, Output>(&mut self, handler: F) -> Result<Output, BlockOnError>
where
F: AsyncFnOnce(event::Event) -> Output;
}
#[derive(Debug, Eq, PartialEq)]
pub enum BlockOnError {
EventLoopExited,
Backend(String),
}
impl fmt::Display for BlockOnError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::EventLoopExited => {
formatter.write_str("event loop exited before the future completed")
}
Self::Backend(message) => write!(formatter, "event loop error: {message}"),
}
}
}
impl std::error::Error for BlockOnError {}
#[cfg(all(feature = "tao", not(target_os = "ios")))]
impl EventLoopBlockOn for tao::event_loop::EventLoop<()> {
fn block_on<F>(&mut self, future: F) -> Result<F::Output, BlockOnError>
where
F: Future,
{
block_on::tao::block_on(self, future)
}
#[cfg(feature = "event")]
fn block_on_with_events<F, Output>(&mut self, handler: F) -> Result<Output, BlockOnError>
where
F: AsyncFnOnce(event::Event) -> Output,
{
block_on::tao::block_on_with_events(self, handler)
}
}
#[cfg(all(feature = "winit", not(any(target_os = "ios", target_arch = "wasm32"))))]
impl EventLoopBlockOn for winit::event_loop::EventLoop<()> {
fn block_on<F>(&mut self, future: F) -> Result<F::Output, BlockOnError>
where
F: Future,
{
block_on::winit::block_on(self, future)
}
#[cfg(feature = "event")]
fn block_on_with_events<F, Output>(&mut self, handler: F) -> Result<Output, BlockOnError>
where
F: AsyncFnOnce(event::Event) -> Output,
{
block_on::winit::block_on_with_events(self, handler)
}
}
#[cfg(test)]
mod tests {
use super::BlockOnError;
#[test]
fn block_on_errors_have_stable_display_messages() {
assert_eq!(
BlockOnError::EventLoopExited.to_string(),
"event loop exited before the future completed"
);
assert_eq!(
BlockOnError::Backend("unavailable".to_owned()).to_string(),
"event loop error: unavailable"
);
}
}