Two crates sharing an internal function

I've got code for an MSD radix sort which can optionally run multithreaded via rayon. I'd like to move that parallel sort out to its own crate. Then you don't take the rayon dependency if you don't want it.

The two sorts share the core function to partition an input slice into a bunch of buckets. That function would ordinarily be private. But if I want to use that function in the serial crate (mmm, cereal crate) and the parallel crate, keeping it private is tricky.

I could:

  • Make it a public API in a third crate so it doesn't clutter up either of the main crates' APIs
  • Make it a public API of the serial crate, with docs explaining it's only exposed out of necessity and you probably don't want it, but described enough you could use it in theory
  • Make it a public API of the serial crate, but only document "here be dragons; this is exposed for other_crate_name to use"
  • Duplicate the function in the parallel and serial crates so it's not a public API anywhere

Right now my top preference is a third crate, probably. Is one of the other options more idiomatic, e.g. is it a common/accepted wart to say "this thing is nominally public but really for one 'friend' crate", or to accept internal code duplication in this kind of situation? Is there some other, better approach? (Thanks!)

You can make it a single crate and use a feature https://doc.rust-lang.org/cargo/reference/features.html.
This way users will be able to choose if they want the multi threaded sort and additional dependency or not. You can also choose which will be the default.

2 Likes

Thank you! I'd heard of features, but hadn't occurred to me they could change dependencies as well as code (even, though, in retrospect, reducing dependencies is probably a quite common use case).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.