-1

Is it possible to share functions between two Rust libraries, but not make them public, ie visible from binaries?

For example, I have two libraries.

  • Lib A contains two functions, one of which is public, the other is not (f1)
  • Lib B can use the public function of Lib A, and it wants to use the private function (f1) of Lib A also, but can't
  • Components M, N, O, ... etc ..., use both Lib A and Lib B. Although Lib B should be able to see f1 from Lib A, I don't want the components M, N, O, ..., to be able to see f1 directly. They need to use f1 only via the public functions of Lib B... (Or Lib A)

Valid function calls might look like this:

Component M -> LibA:: pub fn funcA
Component N -> LibB:: pub fn funcAA -> LibA:: pub fn funcA
Component O -> LibB:: pub fn funcAA -> LibA:: (private) fn funcB

But this would not be valid:

Component M -> LibA:: (private) fn funcB

I would guess the answer to this is no, and that I would have to combine both my Lib A and Lib B into a single library, most likely by adding an additional module layer.

This is not ideal because Lib A and Lib B accomplish the same job but with very different APIs. It should NOT be possible to mix the functions from Lib A with function calls from Lib B. On an abstract level, they are supposed to represent very different concepts / methods of doing something.

In some sense, imagine that Lib A and Lib B present two very different APIs for interacting with a database.

Lib B is essentially a higher order wrapper around Lib A. They do the same things, ultimately, but can't be mixed together.

FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

1 Answers1

0

It is not possible as stated. The nice way to do it is to create a third library for the shared parts, so that both LibA and LibB uses LibInner. Then the shared parts will be public in LibInner, but not exposed to used users of LibA and LibB, so they can still provide a clean api.

The other way (which I would consider more of a ugly hack) is to add a feature flag to LibA, so it exposes those extra endpoints if the flag is enabled but not otherwise. Also, due to the way features of dependencies are handled, this will keep the "secret" internals of LibA hidden to users of either LibA or LibB, but will expose them to any crate that uses both LibA and LibB.

Rasmus Kaj
  • 4,224
  • 1
  • 20
  • 23
  • 1
    Regarding your first suggestion, how would I do that? If I create `LibInner` as you describe, presumably the functions need to be "public" there. So if I understand correctly - and please do correct me if I am wrong here - your thinking is that I just don't add an explicit dependency to that `LibInner` library, FROM my Components, but I DO add a dependency from `LibA` and `LibB`, and this will cause the public function of `LibInner` NOT to be seen inside the Components? – FreelanceConsultant Aug 24 '23 at 19:00
  • 1
    Yes. The public/private distinction is about abstraction (not secrecy) anyway (as code from any language can always be disasembled). – Rasmus Kaj Aug 29 '23 at 06:35
  • 1
    Ok thanks, just wanted to check we were thinking along the same lines – FreelanceConsultant Aug 29 '23 at 08:13