├── 05-generics-traits └── README.md ├── 06-c-ffi └── README.md ├── 04-parallelizing └── README.md ├── LICENSE ├── 02-simple-cli └── README.md ├── README.md ├── 01-toolchain └── README.md └── 03-crates └── README.md /05-generics-traits/README.md: -------------------------------------------------------------------------------- 1 | # Week 5: Generics and Traits 2 | -------------------------------------------------------------------------------- /06-c-ffi/README.md: -------------------------------------------------------------------------------- 1 | # Week 6: Integrating Rust and C/C++ 2 | -------------------------------------------------------------------------------- /04-parallelizing/README.md: -------------------------------------------------------------------------------- 1 | # Week 4: Parallelizing Line Counting 2 | 3 | Rust is a strong language for parallelizing computations. Our use case of enumerating lines of code 4 | is easily parallelizable. 5 | 6 | Using Rust’s standard library, we will: 7 | * Allow multiple files to be processed in parallel 8 | * Aggregate line counts across multiple threads 9 | 10 | ## Requirements 11 | * Your program should adhere to the requirements outlined in v0.2.0. 12 | * Your program should have an additional option “-j, --threads”, that takes an integer value 13 | (e.g., 4, 6, 8, etc.) which specifies the number of threads that the program will use to process 14 | files in parallel. 15 | * Your program’s output should be deterministic. That is, its output between runs should be identical. 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 ACM at UCLA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /02-simple-cli/README.md: -------------------------------------------------------------------------------- 1 | # Week 2: A Simple CLI Line Counter 2 | 3 | This week's lesson is centered around building a simple application that takes input from the command-line. 4 | In summary, you will write an application that takes in a single filename or "-" (stdin). 5 | It will read in the file, then output the number of lines in the file. 6 | 7 | We will learn: 8 | * Reading a file line-by-line in Rust 9 | * Parsing command-line arguments using `std::env` 10 | 11 | ## Your Task 12 | 13 | * Create a program that takes in a single filename or "-" (for stdin) as the command-line argument. (Note: don't use any external crates, use `std::env`). 14 | * The program should read the file (or stdin), counting the number of lines. 15 | * The program should print a line with a single number, the total number of lines in the file. 16 | * Print descriptive error messages! Don't just use `unwrap()`, but instead `expect()`. 17 | 18 | To accomplish this task, you should take a look at the following resources: 19 | * [Documentation](https://doc.rust-lang.org/std/env/fn.args.html) on `std::env::args()` 20 | * This [blog post](https://kerkour.com/rust-read-file) on different ways of reading from a file 21 | * Rust by Example [page](https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html) on opening a file 22 | * This [documentation](https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next) on Rust iterators (specifically `next()` and `skip()`) 23 | * Documentation on [`Result`](https://doc.rust-lang.org/std/result/) and [`Option`](https://doc.rust-lang.org/std/option/), which are important types for representing errors or "nulls" 24 | * This [blog post](https://phrohdoh.com/blog/read-from-file-or-stdin-rust/) on reading either from a file or from stdin 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learning Rust in 6 weeks 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) ![Creative Commons Attribution 4.0 International License logo](https://i.creativecommons.org/l/by/4.0/80x15.png) 4 | 5 | A collection of learning resources for Rust beginners, taught through the creation of a 6 | line-counting toy project! 7 | 8 | ## Abstract 9 | 10 | You will create a program to count lines of code (e.g., `wc -l`), eventually counting individual comments 11 | and empty lines, before finally parallelizing your program to count lines in multiple files at once. 12 | Counting lines may seem like a simple task, but it can involve a surprising amount of depth. This project 13 | will give you a tour of the main features of Rust. 14 | 15 | There are a handful of other programs out there that accomplish what this toy does. Take a look at them 16 | to get a feel for what you’ll be making: 17 | * https://github.com/XAMPPRocky/tokei 18 | * https://github.com/cgag/loc 19 | 20 | ## Table of Contents 21 | 22 | * Week 1: The Rust Toolchain 23 | * Week 2: A Simple CLI Line Counter 24 | * Week 3: Working with External Dependencies 25 | * Week 4: Parallelizing Line Counting 26 | * Week 5: Generics and Traits 27 | * Week 6: Integrating Rust and C/C++ 28 | 29 | ## Goals 30 | 31 | You will learn: 32 | * Basics of Rust syntax 33 | * Rust’s toolchain 34 | * How to work with strings 35 | * How to interact with the filesystem 36 | * How to work with multiple threads to parallelize your code 37 | 38 | You should already know: 39 | * Another programming language 40 | * How to navigate and use your computer with a terminal 41 | 42 | Note that the point of this repository is to focus on learning by doing. Expect to play with the code, ask lots of questions, and 43 | carefully read linked resources! 44 | 45 | ## Companion Repository 46 | 47 | You should use the [companion repository](https://github.com/uclaacm/rustlings-toy-project) as a template and 48 | starting point for your code for the toy line counting project. It contains test cases to help validate 49 | the correctness of your code after each week. 50 | 51 | ## Licensing and Attribution 52 | 53 | Notes in this repository are published with the [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/). 54 | 55 | Code samples in this repository are published with the [MIT license](LICENSE). 56 | 57 | If you use our material, please let us know! We'd love to hear how you used them, what worked, what didn't, 58 | and how we can improve upon them. 59 | -------------------------------------------------------------------------------- /01-toolchain/README.md: -------------------------------------------------------------------------------- 1 | # Week 1: The Rust Toolchain 2 | 3 | Rust has a highly integrated toolchain. The version of the Rust compiler you’re using, the version 4 | of the package manager you’re using, and more are all widely controlled by a single command-line 5 | application: `rustup`. 6 | 7 | We will learn how to: 8 | * Install `rustup` 9 | * Use `cargo` 10 | * Create a new project with Rust 11 | * The difference between a Rust binary and a Rust library 12 | * Basic workflow for compiling and running Rust programs 13 | 14 | ## Setting up our Development Environment 15 | 16 | 1. Install rustup by following the instructions given here: https://rustup.rs/ 17 | 2. Install the latest stable version of Rust as the installation toolchain walks you through it. 18 | 19 | More information is available [here](https://doc.rust-lang.org/book/ch01-01-installation.html). 20 | 21 | ## Creating a New Project 22 | 23 | First, create a new project for your application with the command `cargo new NAME_OF_MY_PROJECT`. 24 | This will create a folder named whatever you may have provided as the positional argument of the 25 | command **relative to your current working directory**. This means that if you ran this command in 26 | the directory `/home/me`, it would be created as `/home/me/NAME_OF_MY_PROJECT`. This might end up 27 | being a place that's difficult to reach with your graphical file browser -- be careful! 28 | 29 | Alternatively, you can initialize an existing folder or git repository with `cargo init .`. 30 | 31 | More information is available [here](https://doc.rust-lang.org/book/ch01-03-hello-cargo.html). 32 | 33 | ## What's in a Rust Project? 34 | 35 | To keep things consistent, let's create a sample project: `cargo new myproject`. 36 | 37 | Let's take a look inside our folder to see what that command created for us: 38 | 39 | ``` 40 | $ find project 41 | myproject 42 | myproject/src 43 | myproject/src/main.rs 44 | # ...probably a bunch of .git stuff 45 | myproject/Cargo.toml 46 | ``` 47 | 48 | Let's start with the top level: `Cargo.toml`. 49 | 50 | ```toml 51 | [package] 52 | name = "myproject" 53 | version = "0.1.0" 54 | edition = "2021" 55 | 56 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 57 | 58 | [dependencies] 59 | 60 | ``` 61 | 62 | This is our package manifest, containing all of the important information about what our package is and what it does. 63 | Later on, this file will contain important information like which packages `myproject` depends on. 64 | 65 | The file `myproject/src/main.rs` is the entry point of the program. By default, this currently contains only 66 | 67 | ```rust 68 | fn main() { 69 | println!("Hello, world!"); 70 | } 71 | ``` 72 | 73 | ## Running our Code 74 | 75 | Rust is a **compiled language**, like C++. This means that to run your program, we first need to build it. Typically, this 76 | would mean writing a `Makefile` or running some compiler commands to package all our source code up nicely. With Rust, this 77 | is as easy as running `cargo run`: 78 | 79 | ``` 80 | $ cargo run 81 | Compiling example v0.1.0 (/home/me/projects/myproject) 82 | Finished dev [unoptimized + debuginfo] target(s) in 5.53s 83 | Running `target/debug/example` 84 | Hello, world! 85 | ``` 86 | 87 | Depending on which operating system you're using, your output might vary a bit, but the important part is the "Hello, world!". 88 | We now have a running Rust program! 89 | 90 | ## Binary vs Library 91 | 92 | Rust has a distinction between a library and binary crate. A binary can be run directly, and it is often used as the 93 | command-line interface (CLI) application. A library typically contains a reusable set of data types and functions. 94 | That other binaries or libraries can depend on. In a single Rust project, a library and a binary can coexist to 95 | help with organizing the codebase. 96 | 97 | ## Your Task 98 | 99 | * Open the pre-designated file `example.txt` and print out each line in the file 100 | 101 | You can start with the template provided by the [companion repository](https://github.com/uclaacm/rustlings-toy-project), which also has test cases for each week. 102 | 103 | Take a look at the following resources to help you get started with this project: 104 | 105 | * Rust by Example [page](https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html) on opening files for reading. 106 | * Rust by Example [page](https://doc.rust-lang.org/rust-by-example/std_misc/file/read_lines.html) on reading lines in a file. 107 | 108 | Don't worry if you don't know exactly what is going on in each line of Rust code. The goal is for you to have the chance to 109 | play around with some Rust code and get familiar with the syntax. 110 | 111 | ## Learning Rust 112 | 113 | The most valuable resource for learning Rust is [The Book](https://doc.rust-lang.org/stable/book/). 114 | Specifically, take a look at the [programming concepts](https://doc.rust-lang.org/book/ch03-00-common-programming-concepts.html) to familiarize yourself with Rust syntax and idioms. 115 | 116 | This [resource](https://fasterthanli.me/articles/a-half-hour-to-learn-rust) exists if you want to speedrun Rust syntax in 30 minutes. 117 | 118 | A good way to familiarize yourself with Rust syntax is by looking at [Rust by Example](https://doc.rust-lang.org/rust-by-example/). 119 | -------------------------------------------------------------------------------- /03-crates/README.md: -------------------------------------------------------------------------------- 1 | # Week 3: Working with External Dependencies 2 | 3 | Now that we’ve grown at least a little accustomed to Rust’s syntax, let’s get familiar with its 4 | ecosystem of packages. The Rust standard library is known for being “to-the-point” compared to 5 | languages like Go or Python, but that’s not a bad thing. There are many high-quality 6 | community-maintained packages (called “crates”) that can do almost anything under the sun for 7 | you. For our application, we will investigate the `clap` crate for argument parsing. 8 | 9 | We will learn how to: 10 | * Use dependencies from [crates.io](crates.io) 11 | * Parse arguments using [clap](https://docs.rs/clap/latest/clap/) 12 | * Basic introduction to macros 13 | * Option to aggregate lines across all files or distinguish file types 14 | * Use a hash table to keep track of different file types 15 | * Format strings 16 | 17 | ## Your Task 18 | 19 | In addition to the basic line counting program from the previous weeks, the following must be supported: 20 | * The program should accept a single positional argument, a **directory**, and it should recursively count the lines of all the 21 | files in the directory. 22 | * Useful help message should be printed when run with `--help`. 23 | * Print helpful error messages 24 | * If run **with** the `-A` option, the program’s output should be exactly as follows for each filename extension (one string per line, with a trailing newline): 25 | 26 | ``` 27 | There are N lines of code in [EXTNAME] files. 28 | There are N empty lines in [EXTNAME] files. 29 | NN.NN% of the lines in [EXTNAME] files are empty. 30 | ``` 31 | 32 | * If run **without** the `-A` option, the program’s output should be exactly as follows (one string per line, with a trailing newline): 33 | 34 | ``` 35 | There are N lines of code. 36 | There are N empty lines. 37 | NN.NN% of the lines are empty. 38 | ``` 39 | 40 | ## Depending on `clap` 41 | 42 | Most Rust libraries (crates) that you will encounter are typically hosted on [crates.io](crates.io). These crates will also have documentation 43 | available on [docs.rs](docs.rs). For the line counting program, we will use the popular [`clap`](https://crates.io/crates/clap) crate for command-line argument parsing. 44 | The corresponding documentation for this crate is available [here](https://docs.rs/clap/latest/clap/). 45 | 46 | To depend on `clap`, it is as simple as navigating to the `clap` crates.io [page](https://crates.io/crates/clap), copy one line of TOML (for example, `clap = "3.1.18"`), and pasting it into your `Cargo.toml` file under the dependencies section: 47 | 48 | ```toml 49 | [dependencies] 50 | clap = "3.1.18" 51 | ``` 52 | 53 | For most crates, that is all you need to do to let `cargo` know that your program is depending on it. 54 | In this case, we actually want to enable a special `clap` feature, so it will look slightly different: 55 | 56 | ```toml 57 | [dependencies] 58 | clap = { version = "3.1.18", features = ["derive"] } 59 | ``` 60 | 61 | Then, you can use `clap` in your program like so: 62 | 63 | ```rust 64 | use clap; 65 | 66 | fn main() { 67 | // code that uses clap... 68 | } 69 | ``` 70 | 71 | When you build and run your code, then `cargo` will automatically download and compile the dependencies. 72 | The `clap` [documentation](https://docs.rs/clap/latest/clap/#example) provides many examples of how you can use it. 73 | You can read about how to specify the exact version or version range of the package you want [here](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html). 74 | 75 | ## Introduction to Macros 76 | 77 | To make coding CLIs easier, `clap` provides macros that generate Rust code at compile time. 78 | For example, let's look at an example struct that you could write that supports `clap` argument parsing: 79 | 80 | ```rust 81 | use clap::Parser; 82 | 83 | #[derive(Parser, Debug)] 84 | #[clap(author, version, about)] 85 | struct Args { 86 | /// File name. 87 | file: String, 88 | 89 | /// Fun level. 90 | #[clap(short, long, default_value_t = 100)] 91 | fun: usize, 92 | } 93 | ``` 94 | 95 | Let's walk through this step by step. The idea of the `clap` derive macro is to help generate a CLI based on 96 | the fields in an user-defined struct. This struct is marked with the attributes `Parser` (to ensure that it 97 | can parse CLI arguments), and `Debug` (to automatically provide a way to debug print out the struct). 98 | Then, the `clap` attribute macro is used to tell it to encorporate author, version, and about information 99 | int othe CLI. This information is automatically taken from the `Cargo.toml` file. 100 | 101 | The struct itself has two fields, which will be automatically transformed into CLI arguments. 102 | The first field is the file name, which is by default a required positional 103 | argument. 104 | The second field is the fun level, which is an optional named argument. The fun level has a default value of 100. 105 | The cool thing about the macros that `clap` provides is that the doc comments (specified with `///`) 106 | will actually be transformed into help messages! This illustrates the power of macros. Such a short piece of code 107 | can generate an entire functional CLI. 108 | 109 | More information about macros is available in the [book](https://doc.rust-lang.org/book/ch19-06-macros.html). 110 | 111 | ## Hash Tables for Each File Type 112 | 113 | You should use a hash table to keep track of the number of lines corresponding to each file type. 114 | For our purposes, the file type is just the extension. For example, `rs` is the file type of `main.rs`. 115 | You can learn more about Rust `HashMap`s by looking at the [documentation](https://doc.rust-lang.org/std/collections/struct.HashMap.html). 116 | 117 | Additionally, you should take a look at the following resources: 118 | * [Documentation](https://doc.rust-lang.org/std/fmt/index.html) on formatting strings 119 | * [Documentation](https://doc.rust-lang.org/std/fs/fn.read_dir.html) with example on how to recursively get all files in a directory 120 | --------------------------------------------------------------------------------