I am making my own crate bridging between a very simple Rust library and a specific complex technology. Because the crate being bridged focuses on simplicity I really want my library to be as simple, only have one entry point, and keep the public accessible signature as consistent and easy as possible.
My struct Foo
originally was the only entry point to my library. But to provide more flexibility I provided a builder FooBuilder
. The builder could be used by more advanced users wanting to specify their own specific config to the library, but the actual reason is to make the library easier to configure for users needing to specify some properties to use the library because their actual code slightly
deviates from the default implementation.
The user currently can access the builder using Foo::builder()
as desired. But FooBuilder
needs to be public for Foo::builder()
to work. However, I don't want the library to make FooBuilder
accessible so the user can also call FooBuilder::default()
itself.
I fear that having FooBuilder
accessible could confuse users not being familiar with the builder design pattern.
Is there a way to only make Foo::builder()
accessible from my library but hide the FooBuilder
struct?
mod my_lib {
pub struct Foo {
x: String,
}
impl Foo {
pub fn new(x: String) -> Self {
Self { x }
}
pub fn builder() -> FooBuilder {
FooBuilder::default()
}
pub fn print_x(&self) {
println!("{}", self.x);
}
}
// Has to be default, otherwise: `error: type `FooBuilder` is private`
// I don't want FooBuilder to be accessible directly. Only Foo::builder() should be an entrypoint to FooBuilder.
pub struct FooBuilder {
x: String,
}
impl FooBuilder {
pub fn default() -> Self {
Self {x: "default".into()}
}
pub fn build(self) -> Foo {
Foo {x: self.x}
}
pub fn with_x(mut self, x: String) -> Self {
self.x = x;
self
}
}
}
fn main() {
// Only this should work:
//let builder = my_lib::Foo::builder().with_x("lol".into());
// This shouldn't work:
let builder = my_lib::FooBuilder::default().with_x("lol".into());
let foo = builder.build();
foo.print_x();
}