0

I've just split my program into an executable and a large file full of struct definitions (structs.rs).

In order to use the structs and their fields for the main executable, I have to prepend each struct definition, and every field definition with pub.

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Foo {
    pub bar: u8,
    pub baz: [u8; 4]
}

This reduces readability.

Is there a way of avoiding all of these pubs?

Or should I be using another way of decomposing my program into multiple files?

fadedbee
  • 42,671
  • 44
  • 178
  • 308
  • 2
    I believe it's a fairly common practice, so probably there's no other way. However you may try to write a (quite simple) proc-macro that marks all of the fields as pub. – Kitsu Jul 05 '20 at 07:19
  • 4
    “ This reduces readability.” does it though? – mcarton Jul 05 '20 at 09:57
  • @mcarton I see your point, but something is wrong if 900 lines of a 1000 line source file begin "pub". – fadedbee Jul 05 '20 at 10:41
  • 3
    Something is wrong if 90% of your lines of code are field declarations. And do you also complain that they all end with a comma in that case? – mcarton Jul 05 '20 at 11:03
  • @mcarton Perhaps it's because I'm new to Rust and "pub" at the start of each line is still very noticeable to me, whereas experience of other languages means I register trailing commas less strongly. Also, I'm probably doing it wrong by using lots of structs with public fields, which is a C hangover. – fadedbee Jul 05 '20 at 11:50
  • @mcarton it may reduce readability if you're coming from e.g. scala where the default is public and you need to add `private` to mark things as such. I'd be very surprised if it's not a highly subjective thing. Though one could argue that the public API should be super easy to read (even to the detriment of all that's private), and adding `pub` in front of everything impedes that – joel Jul 05 '20 at 13:59
  • 2
    In Rust, by default a file is a module, it's not as free as C where it's totally up to you what you put in which header or source file. Putting struct definitions in one file and impls in another file is not the normal way to do things in Rust - don't think in terms of header files and source files like in C. However, if you really want to do things your own way instead of the idiomatic Rust way, then this might be useful: [Split a module across several files](https://stackoverflow.com/questions/22596920/split-a-module-across-several-files) – Jesper Jul 05 '20 at 20:30

1 Answers1

1

This is expected. Modules and crates are a privacy boundary in Rust. The default privacy level for structs and their fields is "same module and its submodules", so parent modules and sibling modules need to have a permission to touch struct's fields.

In Rust structs typically have only a few fields, but the fields may have important invariants to uphold. For example, if Vec.len was public, you could cause unsafe out of bounds access. As a precaution, Rust requires programmers to think through whether they can allow access to each field.

It's unusual to have thousands of structs or structs with thousands of fields, unless they're mirroring some external data definition. If that's the case, consider auto-generating struct definitions with a macro or build.rs.

Kornel
  • 97,764
  • 37
  • 219
  • 309