use crate::error::WebDriverResult;
use base64::{Engine, prelude::BASE64_STANDARD};
use std::convert::Infallible;
use std::future::Future;
use std::io;
use std::panic::AssertUnwindSafe;
use std::path::Path;
use std::sync::LazyLock;
use std::thread;
use std::time::Duration;
fn no_unwind<T>(f: impl FnOnce() -> T) -> T {
let res = std::panic::catch_unwind(AssertUnwindSafe(f));
res.unwrap_or_else(|_| {
struct Abort;
impl Drop for Abort {
fn drop(&mut self) {
eprintln!("unrecoverable error reached aborting...");
std::process::abort()
}
}
let _abort_on_unwind = Abort;
unreachable!("thirtyfour global runtime panicked")
})
}
static GLOBAL_RT: LazyLock<tokio::runtime::Handle> = LazyLock::new(|| {
no_unwind(|| {
let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
let handle = rt.handle().clone();
thread::spawn(move || -> ! {
async fn forever() -> ! {
match std::future::pending::<Infallible>().await {}
}
no_unwind(move || rt.block_on(forever()))
});
handle
})
});
const BOX_FUTURE_THRESHOLD: usize = 512;
#[doc(hidden)]
pub fn block_on<F>(future: F) -> F::Output
where
F: Future + Send,
F::Output: Send,
{
if size_of::<F>() > BOX_FUTURE_THRESHOLD {
block_on_inner(Box::pin(future))
} else {
block_on_inner(future)
}
}
fn block_on_inner<F: Future>(future: F) -> F::Output {
GLOBAL_RT.block_on(future)
}
pub(crate) async fn write_file(
path: impl AsRef<Path>,
bytes: impl Into<Vec<u8>>,
) -> io::Result<()> {
async fn inner(path: &Path, bytes: Vec<u8>) -> io::Result<()> {
let path = path.to_owned();
tokio::task::spawn_blocking(move || std::fs::write(path, bytes)).await?
}
inner(path.as_ref(), bytes.into()).await
}
pub async fn sleep(duration: Duration) {
tokio::time::sleep(duration).await
}
pub fn base64_encode(data: &[u8]) -> String {
BASE64_STANDARD.encode(data)
}
pub fn base64_decode(data: &str) -> WebDriverResult<Vec<u8>> {
let value = BASE64_STANDARD.decode(data)?;
Ok(value)
}