lncr
lncr

Reputation: 886

Is it possible to have a module which is partially accessible outside of a crate and partially only inside the crate?

Is there any better way than just put everything in the same module?

sub_module.rs

pub struct GiantStruct { /* */ }

impl GiantStruct {

    // this method needs to be called from outside of the crate.
    pub fn do_stuff( /* */ ) { /* */ };
}

lib.rs

pub mod sub_module;
use sub_module::GiantStruct;

pub struct GiantStructBuilder{ /* */ }

impl GiantStructBuilder{
    pub fn new_giant_struct(&mut self) -> GiantStruct {
        // Do stuff depending on the fields of the current
        // GiantStructBuilder
    }
}

The problem is with GiantStructBuilder::new_giant_struct(); this method should create a new GiantStruct but to do this you either need pub fn new() -> GiantStruct inside of sub_module.rs or all fields of GiantStruct have to be public. Both options allow for access from outside of my crate.

While writing this question, I realized that I could do something like this:

sub_module.rs

pub struct GiantStruct { /* */ }

impl GiantStruct {
    // now you can't call this method without an appropriate
    // GiantStructBuilder
    pub fn new(&mut GiantStructBuilder) -> GiantStruct { /* */ };

    pub fn do_stuff( /* */ ) { /* */ };
}

However, this seems really counterintuitive as normally the caller is the thing that is acting while the function variables are what is is acted upon, which is obviously not the case when doing it like this. So I would still like to know if there is any better way...

Upvotes: 2

Views: 80

Answers (1)

Lukazoid
Lukazoid

Reputation: 19426

You could use the newly stabilized pub(restricted) privacy.

This will allow you to expose types/functions to only a limited module tree, e.g.

pub struct GiantStruct { /* */ }

impl GiantStruct {
    // Only visible to functions in the same crate
    pub(crate) fn new() -> GiantStruct { /* */ };

    // this method needs to be called from outside of the crate.
    pub fn do_stuff( /* */ ) { /* */ };
}

Or you could apply this to fields on your GiantStruct to allow you to create it from GiantStructBuilder:

pub struct GiantStruct { 
    pub(crate) my_field: u32,
}

Instead of crate you could also use super to specify it's only public to the parent module.

Upvotes: 2

Related Questions