2 min read

Rust Book - Chapter 7.3

Paths for referring to an item in a module tree
💡
The following are my notes as I study the section

A path is Rust is used to refer to an item in the module tree. It can take two forms:

  • Absolute path: usually begins from the root crate
  • Relative path: starts from the current module and uses self, or super identifier

We generally reference an item in a path using identifiers followed by double colons ::.

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

fn eat_at_restaurant() {
    //absolute path
    crate::front_of_house::hosting::add_to_waitlist();

    //relative path
    front_of_house::hosting::add_to_waitlist();
}

Starting relative paths with super

super allows us build relative paths starting at the parent module, rather than the current module. This is similar to doing .. in a file system path.

Making Structs and Enums public

pub can be used to designate structs and enums as public, however for structs, this doesn't automatically make the struct's fields public. We'd have to use pub on each field on a case-by-case basis. And this makes sense.

mod back_of_house {
    pub struct Lunch {
        pub soup: String,
        accompaniment: String,
    }

    impl Lunch {
        pub fn early(soup: &str) -> Lunch {
            Lunch {
                soup: String::from(soup),
                accompaniment: String::from("fufu"), // a base common in West-African Countries
            }
        }
    }
}

pub fn eat_at_restaurant() {
    //order early lunch - okra soup
    let mut meal = back_of_house::Lunch::early("Okra");

    //change our mind about what soup we'd like
    meal.soup = String::from("Egusi");
    println!("I'd like {} soup please", meal.soup);
    
    //If we tried to change the accompaniment 
    //by uncommenting it, code won't compile 
    //as we're not allowed to modify the private field
    //meal.accompaniment = String::from("Amala");
} 

It's slightly different for enums. If we make an enum public, all of its variants are then public. I think this feels natural. Enums aren't very useful unless their variants are public. It'd also be annoying to have to annotate all enum variants with pub in every case. Whereas for structs, they can be useful without their fields being public.

For struct fields, everything is private by default unless annotated with pub.

mod back_of_house {
    pub enum Appetizer {
        Salad,
        PepperedSnail,
        PepperSoup,
    }
}

pub fn eat_at_restaurant() {
    //order an Appetizer
    let appetizer = back_of_house::Appetizer::PepperedSnail;
}

Summary

A package can contain both src/main.rs binary crate root as well as src/lib.rs library crate root. A package can have its functionality in the library crate, and just enough code in the binary crate to start an executable that calls the library crate. This also lets other projects benefit from most of the functionality that the package provides.