| Crates.io | mojique |
| lib.rs | mojique |
| version | 0.1.1 |
| created_at | 2025-07-19 00:09:16.774029+00 |
| updated_at | 2025-07-19 00:27:13.756773+00 |
| description | A safe Rust wrapper and pool implementation around libmagic |
| homepage | |
| repository | https://github.com/LawnGnome/mojique |
| max_upload_size | |
| id | 1759809 |
| size | 58,097 |
mojique implements a safe Rust wrapper around libmagic, providing a
Send-safe Handle into the library, along with an optional Pool that can
be used to provide thread-safe access to libmagic.
It's probably easiest to look at the documentation, but if you want a very basic example just to get a taste of the API, here's how to detect the type of a path given as a command line argument:
use std::path::PathBuf;
use mojique::{Config, DefaultConfig};
fn main() -> anyhow::Result<()> {
let path: PathBuf = std::env::args_os()
.nth(1)
.ok_or_else(|| anyhow::anyhow!("no path given as a command line argument"))?
.into();
let mut handle = DefaultConfig::default().build_handle()?;
let desc = handle.file(path)?;
println!("{desc}");
Ok(())
}
(Nobody's actually asked any questions yet, but here are the questions I expect to be asked eventually if this sees any real use.)
magic?The venerable magic crate has existed for over a decade, and also
provides a safe wrapper around libmagic. I elected to write my own take on this
for a few reasons:
magic API a little unwieldy, especially around the hidden
state types.Read support within the API, which magic doesn't currently
provide.All that said, if magic suits your purposes, you should use magic. It's
considerably more battle tested.
For now, there are two major omissions in the API:
magic_check and
magic_compile functions. I don't need them, and my suspicion is that the
average user also doesn't.magic_getparam and
magic_setparam, respectively.If you do need either of these functions, note the Handle::raw method, which
gives you direct access to the underlying magic_t * in a safe way to use with
magic-sys, which is re-exported from mojique. (Well, until you
actually make an FFI call, at which point you'll have to use unsafe.)
In theory, it should be possible to implement a Handle::async_read method
that takes an AsyncRead and bridges it into libmagic.
Realistically, though, this is going to be executor-dependent. On Tokio, you'd
want to use SyncIoBridge to get in there. So, for now, I think it's best left
as an exercise for the reader.
This is something Trail of Bits did with PolyFile for Python. I definitely understand the impulse.
For now, I don't really have the time to implement this. But never say never. (And if someone out there does do so, please let me know! I'd love to use it.)