please summarize this part of a chapter of a book on rust programming, outlining each section with explanations:   “ Rust comes equipped with a large set of tools that makes it easy to organize, struc- ture, test, and comment it. The ecosystem values good documentation style, which is the reason Rust has a built-in commenting system that generates code documen- tation on the fly, and even tests the code in your comments so your documentation is never out-of-date. 
A widely supported linter called Clippy is the de facto standard in the Rust world. It comes with many preset rules and helps point out best practices or missing implementations. In addition, Rust’s package manager Cargo helps autoformat your code based on predefined rules. 
In the preceding chapter, we built out API routes for our Q&A applications, extracted information out of URL parameters, and most importantly, added our own structures and error implementations and handling. We added all this into the main.rs file, which grew with every route handler we added. 
Clearly, this file does too much. Even for a large application, the main.rs file should just connect all the pieces and start the server instead of owning any real implementa- tion logic. In addition, we added a lot of custom code that could use some explanations. We could use Rust’s built-in capabilities of splitting code and documenting it. 
We start off this chapter by looking at the module system to see how to split your code and how to make it public or private. Later, we’ll add comments, write code exam- ples in doc comments, and lint and format our code. 
5.1 :Modularizing your code 
So far, we put every line of code in the main.rs file of our project. This can work well for a small mock server you want to run and maintain in your service architecture, because it is easier to maintain, and not a lot will change after the initial creation. 
A larger and more actively maintained project, however, is better served by group- ing logical components together and moving them into their own folders and files. This makes it easier to work on multiple parts of the application at the same time, as well as to focus on parts of the code that change often versus the parts that don’t. 
Rust differentiates between applications and libraries. If you create a new applica- tion via cargo new APP_NAME, it will create a main.rs file for you. A new library project is created by using --lib and would create a lib.rs file instead of main.rs. 
The main difference is that a library crate won’t create an executable (binary). It is meant to provide a public interface to an underlying functionality. A binary crate, on the other hand, where the main.rs file holds the code that starts your application, will create a binary that you can use to execute and start the application. In our case, this is the start of our web server. Everything else—route handlers, errors, and parsing parameters—can be moved into their own logical units and files. 

5.2
Rust uses modules to group code together. The mod keyword indicates a new mod- ule, which has to have a name. Let’s see how we group our errors and error han- dling together. 
mod error { 
    #[derive(Debug)]
enum Error {
    ParseError(std::num::ParseIntError),
    MissingParameters,
    QuestionNotFound,
} 
impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 
match *self {
    Error::ParseError(ref err) => {
        write!(f, "Cannot parse parameter: {}", err)
    },
Error::MissingParameters => write!(f, "Missing parameter"), 
Error::QuestionNotFound => write!(f, "Question not found"), } 
    impl Reject for Error {}
} 
A Rust naming convention dictates using snake_case when naming modules: lower- case letters with an underscore to separate words. Therefore, we named our module error instead of Error. 
That seems rather easy, and it is. However, our code stops compiling, and we get a few errors (the important pieces are highlighted in bold, and clipped duplicates are indicated via ...): 
$ cargo build 
   Compiling ch_04 v0.1.0
     (/Users/gruberbastian/CodingIsFun/RWD/code/ch_04/final)
error[E0433]: failed to resolve:
    use of undeclared type `Error`
   --> src/main.rs:110:26
    |
110 |                 .map_err(Error::ParseError)?,
    |                          ^^^^^ use of undeclared type `Error`
error[E0433]: failed to resolve: use of undeclared type `Error` --> src/main.rs:115:26 
| ... 
error[E0405]: cannot find trait `Reject` in this scope
  --> src/main.rs:76:10
   |
76 |     impl Reject for Error {}
   |          ^^^^^^ not found in this scope
| 
help: consider importing one of these items
   |
60 | | 60 | | 
... 
use crate::Reject;
use warp::reject::Reject;
error[E0412]: cannot find type `Error` in this scope
  --> src/main.rs:80:35
   |
80 |     if let Some(error) = r.find::<Error>() {
   |                                   ^^^^^ not found in this scope
   |
help: consider importing one of these items
   |
1  | use core::fmt::Error;
   |
1  | use serde::__private::doc::Error;
   |
1  | use serde::__private::fmt::Error;
   |
1  | use serde::de::Error;
   |
     and 9 other candidates
... Some errors have detailed explanations: E0405, E0412, E0433. For more information about an error, try `rustc --explain E0405`. warning: `ch_04` (bin "ch_04") generated 1 warning error: could not compile `ch_04` due to 8 previous errors; 1 warning emitted 
These two compiler-errors teach us a lot about the module system in Rust: 
 Inside the error module, we can’t access the Reject trait from Warp, but even so we imported it in the same file (error in in line 76). 
 The rest of the application can’t find the Error enum anymore, since it’s now moved into its own module (error in lines 110 and 80). 
The first one (Reject:notfoundinthisscope) indicates that the modules are operat- ing in a new, separate scope. Everything we need inside them, we have to import. 
Listing 5.2 Moving the Warp Reject trait from the main.rs imports into our error module ... 
use warp::{ filters::{body::BodyDeserializeError, cors::CorsForbidden}, http::Method, http::StatusCode, reject::Reject, Filter, Rejection, Reply, 
}; 
mod error { 
    use warp::reject::Reject;
    #[derive(Debug)]
    enum Error {
        ParseError(std::num::ParseIntError),
        MissingParameters,
        QuestionNotFound,
} 
... } 
... 
We remove the import of Reject from the beginning of the main.rs file and move it into our error module. Since we don’t use Reject anywhere else, the compiler error disappears, and we are left with a bunch more, which have all the same source. 
By moving the Error enum behind a module, the rest of the code can’t find it anymore. We need to make sure to update the path to the enum in the rest of the code. The extract_pagination function is a perfect example to work through the process of updating the code to our new module. We start by changing the error return value from Error to error::Error. This is how we access an entity behind a module: by writing down the module name and using the double-colon (::) to access the enum behind it. 
Listing 5.3 Adding the namespace to import the Error enum from the new error module 
fn extract_pagination(
    params: HashMap<String, String>
) -> Result<Pagination, error::Error> { ... 
    Err(Error::MissingParameters)
}
This, however, brings up a new error: 
enum `Error` is private
private enumrustcE0603 // https://doc.rust-lang.org/error-index.html#E0603 
It tells us that the Error enum is private. All types and functions in Rust are private by default, and if we want to expose them, we have to use the pub keyword. 
        mod error {
            use warp::reject::Reject;
#[derive(Debug)] pub enum Error { 
               ParseError(std::num::ParseIntError),
               MissingParameters,
               QuestionNotFound,
} 
... } 
... One logical piece is still outside our error module: the return_error function, which 
would make sense to also include in this module. 
Listing 5.5 Moving return_error into the error module with all its needed imports ... 
        mod error {
            use warp::{
               filters::{
                   body::BodyDeserializeError,
                   cors::CorsForbidden,
}, 
               reject::Reject,
               Rejection,
               Reply,
               http::StatusCode,
}; 
... 
async fn return_error(r: Rejection) -> Result<impl Reply, Rejection> { if let Some(error) = r.find::<Error>() { 
                   Ok(warp::reply::with_status(
                       error.to_string(),
                       StatusCode::RANGE_NOT_SATISFIABLE,
                   ))
               } else if let Some(error) = r.find::<CorsForbidden>() {
                   Ok(warp::reply::with_status(
                       error.to_string(),
                       StatusCode::FORBIDDEN,
)) } else if let Some(error) = r.find::<BodyDeserializeError>() { 
                   Ok(warp::reply::with_status(
                       error.to_string(),
)) } else { 
5.1 Modularizing your code 121 StatusCode::UNPROCESSABLE_ENTITY, 
            Ok(warp::reply::with_status(
                "Route not found".to_string(),
                StatusCode::NOT_FOUND,
)) } 
} 
} ... 
That’s all: the compiler error disappears, and we can move on to the next. We simply have to add error:: in front of every Error enum usage in our code to solve the remaining compiler errors. 
We move the use of StatusCode, Reply, Rejection, and the two Warp filters we were using uniquely for this function also inside the module and remove them from the overall imports at the beginning of the main.rs file (with the exception of Status- Code, which we also use in our route handler functions). 
We need to fix two errors after doing this:  Make our return_error function public. 
 Call error::return_error in our routes building instead of plain return_error. Listing 5.6 Making the return_error function public for other modules to access it 
... 
mod error { ... 
pub async fn return_error(r: Rejection) -> Result<impl Reply, Rejection> { println!("{:?}", r); if let Some(error) = r.find::<Error>() { 
            Ok(warp::reply::with_status(
                error.to_string(),
                StatusCode::UNPROCESSABLE_ENTITY
)) ... 
} } 
} ... 
#[tokio::main]
async fn main() {
let store = Store::new(); 
let store_filter = warp::any().map(move || store.clone()); 
... 
let routes = get_questions .or(update_question) .or(add_question) .or(add_answer) .or(delete_question) .with(cors) .recover(error::return_error); 
    warp::serve(routes)
        .run(([127, 0, 0, 1], 3030))
        .await;
} 
We accomplished the first step of simplifying and grouping our code. Everything to do with errors goes into its own module from now on. This also has the advantage of seeing which types we need to import from other libraries or our application. It seems that the error module is application code agnostic, which leads to the revelation that this piece of code can be a library, maintained by another team or imported in more than one micro service, for example. 
Practical folder structure for different use cases 
The next step is to move code out of the main.rs file and into its own folder or single file. Which direction you go depends on the complexity of code you want to group together. You can have a folder called error, with files for each error type and func- tionality. Or you can have a single file called error.rs that contains the group of code we just put together into a module. Let’s go down the latter route first and create a file called error.rs that lives on the same level as main.rs. 


Listing 5.7 Moving the error module from main.rs into a newly created error.rs file 
mod error {
  use warp::{
      filters::{
          body::BodyDeserializeError,
          cors::CorsForbidden,
      },
      reject::Reject,
      Rejection,
      Reply,
      http::StatusCode,
}; 
  #[derive(Debug)]
  pub enum Error {
      ParseError(std::num::ParseIntError),

      MissingParameters,
      QuestionNotFound,
  }
... } 
Notice that the code listing shows the content of error.rs this time. But inside the file is nothing new. Once we exclude this module from the main.rs file, however, we run into a bunch of new compiler errors—which makes sense. The compiler cannot find the error implementation anymore. To reference code from another file, we have to use the mod keyword. 
Listing 5.8 Adding the error module to our dependency tree by adding it to main.rs 
...
use std::sync::Arc;
use tokio::sync::RwLock;
mod error; 
... 
Since our code lives in another file and everything is private by default in Rust, we need to add pub in front of our module definition. 
Listing 5.9 Making the error module accessible for other modules via the pub keyword pub mod error { ... } 
We can see the downside of this decision rather quickly when updating our code. To return an Error enum from a function, now we now need two different error refer- ences first. 
Listing 5.10 The current structure requires two modules with the same name 
... 
fn extract_pagination(
    params: HashMap<String, String>
) -> Result<Pagination, error::error::Error> { ... 
The use of mod {} creates a distinct scope, even if it’s the only module in the file. That scope makes the extra error:: necessary. We therefore get rid of the module declara- tion inside error.rs. 
Listing 5.11 Removing the redundant mod keyword in errors.rs 
use warp::{
    filters::{
        body::BodyDeserializeError,
        cors::CorsForbidden,
    },
    reject::Reject,
    Rejection,
    Reply,
    http::StatusCode,
}; 
... 
pub async fn return_error(r: Rejection) -> Result<impl Reply, Rejection> { println!("{:?}", r); if let Some(error) = r.find::<Error>() { 
        Ok(warp::reply::with_status(
            error.to_string(),
            StatusCode::UNPROCESSABLE_ENTITY
        ))
    } else if let Some(error) = r.find::<CorsForbidden>() {
        Ok(warp::reply::with_status(
            error.to_string(),
            StatusCode::FORBIDDEN
        ))
    } else if let Some(error) = r.find::<BodyDeserializeError>() {
        Ok(warp::reply::with_status(
            error.to_string(),
            StatusCode::UNPROCESSABLE_ENTITY
)) } else { 
        Ok(warp::reply::with_status(
            "Route not found".to_string(),
            StatusCode::NOT_FOUND,
)) } 
} 
And without changing anything in main.rs, our code works. So why do we use mod instead of use when working with our own files? The mod keyword tells our compiler the path to a module, and it stores it for future use. The use keyword uses the mod- ule and tells the compiler this: a module is available, and here is the path to it so I can use it in this file. 
It becomes clearer when we continue moving bits and pieces from the main.rs file into new folders and files. Have a look at this book’s GitHub repository (https://github .com/Rust-Web-Development/code) to see the full code, since this would take too 

many pages to show here. We will, however, show how the mod system works with dif- ferent files and folders. 
We move our store logic into its own file, and as we did with error, declare it inside main.rs via mod store. We could choose to move every model or type into its own file, under the folder types. We also go on and move out the route handlers into a folder called routes and have a file for the answer and question handlers each. The structure looks like this: 
$ tree . 
. ├── Cargo.lock ├── Cargo.toml ├── questions.json └── src 
├── error.rs ├── main.rs ├── routes 
		│  ├── answer.rs  
		│  ├── mod.rs  
		│  └── question.rs └── types  ├── answer.rs ├── mod.rs ├── pagination.rs └── question.rs  3 directories, 12 files
		 Based on that example, we can explain how Rust is communicating and exposing the logic inside the various files. We use the mod keyword to include the modules in the main.rs file.  Listing 5.12 Adding the modules to the source tree by adding them to the main.rs file  use warp::{
		    Filter,
		     http::Method,
		};
		 mod error;
		mod store;
		mod types;
		mod routes;
		 #[tokio::main]
		async fn main() {
		 let store = store::Store::new(); let store_filter = warp::any().map(move || store.clone());  ... }  



We include error and store based on the filename we gave the files that the logic is stored in, and it is on the same hierarchy level as the main.rs file. Therefore, we don’t need a special pub mod {} inside error.rs or store.rs. Figure 5.1 gives an overview of how we connect the different files through mod.rs files and mod imports. 


The types and routes are different, though. We created folders that contain multiple files. We create a mod.rs file in the folders and expose the modules (files) inside them via the pub mod keyword. 
Listing 5.13 src/routes/mod.rs 
    pub mod question;
    pub mod answer;
And we do the same with our types. 
Listing 5.14 src/types/mod.rs 
    pub mod question;
    pub mod answer;
    pub mod pagination;
We access one module from another via the use keyword and use the project hierar- chy (folder structure) to access them. Look at the answer.rs file and how we import the Store. 
Listing 5.15 src/routes/answer.rs 
       use std::collections::HashMap;
       use warp::http::StatusCode;
        use crate::store::Store;
... 
We use the use crate::... combination to access modules in our own crate. This is pos- sible because we imported all submodules inside the main.rs file via mod store, and so forth. To summarize: 
		  The main.rs file has to import all the other modules via the mod keyword.  
		  Files in folders need to be exposed via a mod.rs file and use the pub mod key-  words to make them available to the other modules (including main.rs).  
		  Submodules can then import functionality from other modules via the use  crate:: keyword combination.  
5.1.3 Creating libraries and sub-crates 
Once your codebase is growing, it can be helpful to split independent functionality into libraries that live next to your application in the same repository. We saw earlier that our error implementation is application agnostic and might also be useful for other applications in the future. 
Where should code live? 
You can choose to have one big file of code, split code into multiple files, create folders for these files, or create whole new crates for subfunctionality in your codebase. Each decision has upsides and downsides. Using sub-crates can make workflows harder. 
A rule of thumb can be your team size. How many people need to work on a certain functionality? How often does this functionality change? And do you need this piece of code you want to split out of a larger file in more than one project? 
If you need the code in more than one project, it’s best to use a sub-crate and live also with the downsides of having it in a different Git repository where you have to be aware to always keep it in sync and update it through a separate Git flow. If you don’t need this piece of code in a different project, folders and separate files are the best way of going about it in the beginning. 
Remember that books serve a teaching purpose, and a choice shown here might not be the best in a real-world scenario. Since we can’t develop a large and complex enough application in one or two chapters, splitting out code in a sub-crate rarely makes sense other than to show what you would do if you have to. 
We are currently developing a Rust binary (created with cargo new at the beginning of the book). But Cargo also offers a way to create a library, which would create a lib.rs file instead of main.rs. Section 5.2 will show more differences between a library and a binary crate. Figure 5.2 shows how we add the new library to the rest of the codebase. 

Figure 5.2 After creating a new library in our application folder, we can add it to the Cargo dependencies and specify a local path; afterward, we use it as any other external library in our files. 
Let’s navigate to the root folder of our project and create a new library: 
$ cargo new handle-errors --lib
We then move all the code in error.rs into PROJECT_NAME/handle-errors/src/ lib.rs. 
Listing 5.16 handle-errors/src/lib.rs 
use warp::{ filters::{body::BodyDeserializeError, cors::CorsForbidden}, http::StatusCode, 


    reject::Reject,
    Rejection, Reply,
};
#[derive(Debug)]
pub enum Error {
    ParseError(std::num::ParseIntError),
    MissingParameters,
    QuestionNotFound,
} ... 
After we delete error.rs, we get a few errors. That is to be expected, since our code is relying on this module. We have to go through a couple of steps: 
	.	1  Let the Rust compiler know where to find the new error code.  
	.	2  Import the error code from the new location instead of the old one.  
We use our Cargo.toml file to import external libraries into our project. Even though handle-errors lives in the same repository, it is still an external library that we need to explicitly include. Instead of fetching the code from a Git repository somewhere from the internet or crates.io, we specify a local path for it. “