Files
authy-oidc/src/server/caches/mime.rs
2026-03-20 19:48:18 +01:00

69 lines
1.9 KiB
Rust

//! Mime mmagic analogous to [`magic::Cookie`] BUT [`Sync`]
// I don't think I can do better with thread exclusive `libmagic`
use std::cell::OnceCell;
use magic::{Cookie, cookie};
#[derive(Debug, thiserror::Error)]
pub enum NewCookieError {
#[error(transparent)]
MimeCookieOpen(#[from] magic::cookie::OpenError),
#[error(transparent)]
MimeDBLoad(#[from] magic::cookie::LoadError<magic::cookie::Open>),
// #[error(transparent)]
// MimeDBPath(#[from] magic::cookie::InvalidDatabasePathError),
}
pub struct Mime {
magic_dbs: magic::cookie::DatabasePaths,
}
impl Mime {
thread_local! {
static COOKIE_CELL: OnceCell<Cookie<cookie::Load>> = const { OnceCell::new() };
}
fn use_cookie<F, T>(&self, f: F) -> Result<T, NewCookieError>
where
F: FnOnce(&Cookie<cookie::Load>) -> T,
{
Self::COOKIE_CELL.with(|cookie| {
let may_cookie = cookie.get_or_try_init::<_, NewCookieError>(move || {
let cookie = magic::Cookie::open(magic::cookie::Flags::MIME)?;
Ok(cookie.load(&self.magic_dbs)?)
});
match may_cookie {
Ok(c) => Ok(f(c)),
Err(e) => Err(e),
}
})
}
#[must_use]
pub const fn new(magic_dbs: magic::cookie::DatabasePaths) -> Self {
Self { magic_dbs }
}
/// Cookie initialization is delayed, so each call might be the creation of the cookie if its
/// the first use of the cookie in this thread.
///
/// # Errors
///
/// First layer error fails if new cookie creation failed. Second layer error represents if the
/// mime search was successful.
pub fn buffer(
&self,
buffer: &[u8],
) -> Result<Result<String, magic::cookie::Error>, NewCookieError> {
self.use_cookie(|c| c.buffer(buffer))
}
}
// fn __ace(c: Mime) {
// fn __ace_inner(c: impl Sync + Send) {}
// __ace_inner(c);
// }