Projects / Crates

Here are some Rust crates or projects I either wrote or worked on enough to be one of the maintainers. It doesn’t count stuff I wrote for work, unless it really feels like “mine” (which means just ffi-support, really).

See also: https://crates.io/users/thomcc, https://github.com/thomcc, …

bad3d

Every so often I miss game development, and really feel the itch to get in there with some good ol math and computational geometry. This is where I go. Some features:

  • Working 3D physics code that
    • Supports rigidbody collisions of anything that can be made up by a list of convex polyhedra.
    • Uses a fancy immediate-mode API that eventually I had hoped to make into something vaguely declarative (imagine: React-but-for-3d-scenes).
    • The immediate mode API made it really annoying to implement a good broadphase so it doesn’t have one. (Look, it’s my project, I get to make the call that I’m only doing the fun bits)
  • Working 3D collision detection code (Obvious given the first one).
    • The algorithms it uses are GJK for detecting collisions and a slightly-modified EPA for producing the response.
    • Works pretty well, and uses SIMD accelerated code for finding the support point.
    • I found out that somehow collision detection driver loop (e.g. the non-SIMD part) spends 30% of it’s time in memcpy!? I need to get back and fix this…
  • A implementation of 3D convex-hull, with support for producing an approximated hull with no more than N vertices
    • Uses a greedy algorithm I stole shamelessly after seeing it in bullet3d and being enchanted by its simplicity.
    • My implementation is worse under most metrics, but it’s mine (and also it’s useful for EPA).
  • A implementation of constructive-solid-geometry operations (e.g. shape booleans).
    • This is buggy. I have a proof of why it should be correct, and yet it’s buggy 😭.
  • A half-edge/wing-edge mesh data structure
    • Uses indices to avoid the hairy maze of pointers you often see.
    • Might be where the bug in the CSG code lies but I suspect it’s either the BSP or in the math behind my so-called “proof of correctness”.
  • Honestly probably some other weird shit, I really threw whatever I wanted in here without concern for it having a sane feature-set.

This one isn’t actually published on crates.io because some parts are buggy, others are unreasonably slow, and others still suffer from dubious design decisions. It’s a lot of fun to hack on, though.

rusqlite / libsqlite3-sys

This started out as a thing I would poke for work, and now I’m a comaintainer of it. It has a lot of warts on it’s API, and maybe I’ll write about them at some point, but I hope to fix them.

arcstr

This is a thin-pointer reference counted string type. It can be constructed from a string literal for nearly zero cost (const-compatible, no allocations, clone/drop of the literal-based ArcStrs don’t even need to perform atomic operations).

const AMAZING: ArcStr = arcstr::literal!("amazing constant");
assert_eq!(AMAZING, "amazing constant");

let wow: ArcStr = arcstr::literal!("Wow!");
assert_eq!("Wow!", wow);

It’s one of my most recent (uh, as of 8/2020) projects, but I like it a lot.

I’m particuarly proud of it’s testing: - It has 95% test coverage (haven’t tested a couple fatal error cases like OOM or refcount overflow, but the handling for those is “abort”…). - It runs its tests under checkers like miri, Address Sanitizer, Memory Sanitizer, and Thread Sanitizer. - It has a (smaller than I’d like but you have to stop somewhere) loom-based verification harness. - And it tests on Linux (both 64-bit and 32-bit x86), macOS, Windows (both MSVC and GNU toolchains), 32 and 64-bit ARM, and 64-bit MIPS (which is the easiest big-endian target available). Much of the weird platforms run via cross (e.g. qemu). - This is clearly overkill, but I kinda want to reuse the .github/workflows/ci.yml moving forward.

The tests really put github actions to work. Can’t believe they let me do this for free!

almost

This is a library for comparing floating point numbers that IMO is better than the popular crates for doing so (like approx). Some key ideas:

  1. All comparisons with arbitrary numbers should be relative by default. They should not force users to understand terminology like ULP, and they should not use hybrid relative/absolute behavior as that breaks scale independence.
  2. All comparisons with zero should use an absolute tolerance.
  3. It’s possible to pick a default tolerance

base16

I wrote this because the hex crate was too slow. It might be obsolete now, but…. taking a look the hex crate is still unreasonably slow. (Look, I don’t ask for much, but honestly the strings you get passed as input could be quite large…)

ffi-support

I wrote this for my work at Mozilla, and probably won’t maintain it now that I’ve been laid off. Still, it took a lot of care and effot, and I think it’s a good approach if you’re manually writing FFI code to expose Rust to something else.

handy

This is basically a rewrite of the HandleMap type from ffi-support. I actually think the implementation in ffi-support is cleaner and elegant, but handy has more features and is probably more efficient. For pure-rust use cases, most of the code I had using handy I’ve moved over to index_vec, though.

index_vec

This lets helps define newtype-style wrappers around usize and use them with special Vecs and slices. The technique is used heavily in rustc, but the code in rustc isn’t public, and doesn’t compile on stable even if it was.

The API has a bit of jank to it because it was when I was in my phase where I refused to use proc_macro crates due to the build overhead. Now I’m a bit more pragmatic… but still wish it they didn’t cause such a compile-time hit.

thin_str

Like arcstr but for Box<str> and worse. Just use arcstr. The overhead is small. Maybe I’ll eventually update this one with the ability to initialize it from a literal though…

tearor

I wrote a whole blog post on this one. Also probably don’t use it? Actually, I’ve been meaning to write a followup on “when might using it be a good idea”. It’s good for a few cases.

more-asserts

This is one of my first crates and it’s eh. It was better when #[macro_use] was conditional, as it is more_asserts::assert_lt!(...) is just tedious. Somehow it’s one of my most popular? Being early is better than being good, I guess…

chek

This is a less tedious to type version of more-asserts. It also has a mode to automatically outline your assertions, but I didn’t realize how important that was so I didn’t enable it by default.

That said nobody uses it they just use more-asserts. I’ve been tempted to deprecate the former for it, but… eh. That code still works fine, why put people through the churn?

core_detect

This is a no_std version of the std::is_x86_feature_detected! macro.

On x86/x86_64, runtime feature detection is done via the cpuid instruction, and so it doesn’t require the stdlib.

atomic_float

Small crate providing AtomicF32 and AtomicF64 types that act more or less identically to the integer atomic types in the stdlib.