hymmalm — Rust wrapper
Rust binding for license-management-core. All licensing behavior — JWS verification, status rules, machine fingerprint, REST flow, retry policy, clock-tamper resistance — lives in the native core; this crate only marshals. See the repository root README for the architecture.
Usage
use ;
let mut client = new?;
let status = client.check?; // trial bootstrap on first run
if status == InvalidTrial
Offline verification only (no network, e.g. checking a provisioned file):
let status = verify?;
Errors are hymmalm::LicenseError { code, detail } — code is the native
hlm_err (e.g. -7 network failure, -12 invalid API key, -13 trial
quota exceeded) and detail carries the server's human-readable refusal
reason when it sent one.
Native core — self-contained build
Unlike the Python/.NET wrappers, this crate vendors the C core: the
sources are copied under csrc/ (maintained by sync-csrc.sh; CI fails if
they drift from the canonical ../../src) and build.rs compiles them with
the cc crate, linking statically. There is no shared library to build,
ship, or locate — a plain cargo build produces a self-contained binary,
and the published crates.io tarball carries everything it needs. You only
need a C compiler (cc/clang on Unix, MSVC on Windows; the Windows build
links winhttp/bcrypt/ws2_32/advapi32 automatically).
On Linux/macOS the HTTP transport dlopen()s the system libcurl at runtime
(any distro flavor works); no curl development package is needed at build
time.
After changing the canonical C core, re-run ./sync-csrc.sh and commit the
refreshed copies — never edit csrc/ directly.
Publishing
CI publishes to crates.io automatically on v* release tags (the crates
job, authenticated by the CARGO_REGISTRY_TOKEN secret). cargo package
runs on every CI build to prove the standalone tarball compiles. The
integration tests are not packaged (they replay ../../tests/vectors from
the repo checkout).
Threading
The native handle must not be used from two threads at once, so
LicenseClient is Send but not Sync: move it between threads freely,
or wrap it in a Mutex to share it — which is exactly the Tauri pattern
below.
Using from Tauri
The crate is Tauri-ready as-is (static native core, no runtime files to
bundle). Hold the client in managed state behind a Mutex and expose the
operations as commands:
use Mutex;
use ;
;
(tauri is not a dependency of this crate — the snippet goes in your app.)
Tests
tests/vectors.rs replays the same signed vectors as the C suite;
tests/flow.rs runs the full client flow (trial → activate → offline cache →
deactivate, plus error classification) against a hand-rolled local mock API in
a single sequential test. The flow test needs libcurl present at runtime (it
is on any normal Linux/macOS install).