mojique
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.
Basic usage
It's probably easiest to look [at the documentation][docs], 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 PathBuf;
use ;
FAQ
(Nobody's actually asked any questions yet, but here are the questions I expect to be asked eventually if this sees any real use.)
Why not [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:
- I needed to be able to perform magic checks in parallel within a set of Tokio tasks, which implied some sort of pool or thread-local architecture.
- I found the
magic
API a little unwieldy, especially around the hidden state types. - I wanted
Read
support within the API, whichmagic
doesn't currently provide.
All that said, if magic
suits your purposes, you should use magic
. It's
considerably more battle tested.
What parts of the libmagic API are not exposed?
For now, there are two major omissions in the API:
- Support for database manipulation, specifically the
magic_check
andmagic_compile
functions. I don't need them, and my suspicion is that the average user also doesn't. - Support for getting and setting parameters using
magic_getparam
andmagic_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
.)
What about async support?
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.
What about a pure Rust implementation of the magic algorithm?
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.)