Crates are the compiled entities that get distributed on machines to execute. All the code of a crate is contained in an implicit root module. This code can then be split up by the developer into code units called modules, which in fact form a hierarchy of sub-modules under the root module. That way the organization of our code can be greatly improved. An evident candidate for a module is the tests code, which we discussed in Chapter 3, Using Functions and Control Structures in the The tests module section.
Modules can also be defined inside other modules, as so-called nested modules. Modules do not get compiled individually; only crates get compiled. All module code is inserted into the crate source file before compilation starts.
In previous chapters, we used built-in modules from the std crate, such as io, str, and vec. The std crate contains many modules and functions that are used in real projects; the most common types, traits, functions, and macros (such as println!) are declared in the prelude module.
A module typically contains a collection of code items such as traits, structs, methods, other functions, and even nested modules. The module's name defines a namespace for all objects it contains. We define a module with the mod keyword and a lowercase name (like game1) as follows:
mod game1 { // all of the module's code items go in here }
Similar to Java, each file is a module, and for every code file the compiler defines an implicit module, even when it does not contain the mod keyword. As we will see in the Importing modules and file hierarchy section, such a code file can be imported in the current code file with mod filename;.
Suppose game1 is the name of a module that contains a function, func2. If you want to use this function in code external to this module, you would address it as game1::func2. But whether this is possible depends on the visibility of func2.