Rust for Beginners: Dive into coding with these 5 Projects to boost your skills
Dan Mugisho M.
Posted on January 14, 2024
Welcome to the thrilling world of Rust programming! Whether you're a coding enthusiast embarking on your programming journey or a seasoned developer eager to add a new language to your arsenal, Rust offers an exciting playground for honing your skills. In this article, I'll guide you through an engaging exploration, providing you with five hands-on projects designed specifically for beginners.
Rust isn't just a programming language; it's a mindset—a commitment to performance, safety, and concurrency. As you navigate through these carefully curated projects, you'll not only grasp the fundamentals of Rust but also witness firsthand its power in creating efficient, reliable, and high-performance code.
Each project serves as a stepping stone, gradually introducing you to Rust's syntax, principles, and unique features. From simple yet impactful tasks to more complex challenges, these projects are crafted to provide a well-rounded learning experience. So, buckle up and get ready to dive headfirst into the world of Rust, where your coding adventure begins!
Without further ado, let's explore "Rust for Beginners: Dive into Coding with These 5 Projects to boost your skills" and uncover the exciting possibilities that await you on your Rustic coding journey.
To-Do List App
Building a To-Do List application in Rust is a great way to get hands-on experience with the language and its ecosystem. Below is a simple step-by-step guide to help you get started with creating a basic console-based To-Do List application in Rust.
Step 1: Set Up Your Rust Environment
If you haven't installed Rust, you can do so by following the instructions on the official Rust website: https://www.rust-lang.org/tools/install.
Step 2: Create a New Rust Project
Open a terminal and run the following commands:
# Create a new Rust project
$ cargo new todo_app
# Navigate to the project directory
$ cd todo_app
Step 3: Define Your To-Do Item Structure
Edit the src/main.rs
file to define the structure for your To-Do items:
Step 4: Implement To-Do List Operations
Update src/main.rs
to implement basic operations like adding, listing, and completing To-Do items:
// src/main.rs
use std::io;
struct TodoItem {
id: u64,
title: String,
completed: bool,
}
struct TodoList {
items: Vec<TodoItem>,
}
impl TodoList {
fn new() -> TodoList {
TodoList { items: Vec::new() }
}
fn add_item(&mut self, title: String) {
let id = self.items.len() as u64 + 1;
let new_item = TodoItem {
id,
title: title.clone(),
completed: false,
};
self.items.push(new_item);
println!("Added: {}", title);
}
fn list_items(&self) {
if self.items.is_empty() {
println!("Your to-do list is empty.");
} else {
println!("Your to-do list:");
for item in &self.items {
let status = if item.completed { "[X]" } else { "[ ]" };
println!("{} {} - {}", status, item.id, item.title);
}
}
}
fn complete_item(&mut self, id: u64) {
if let Some(item) = self.items.iter_mut().find(|i| i.id == id) {
item.completed = true;
println!("Completed: {}", item.title);
} else {
println!("Item with ID {} not found.", id);
}
}
}
fn main() {
let mut todo_list = TodoList::new();
loop {
println!("1. Add Item");
println!("2. List Items");
println!("3. Complete Item");
println!("4. Exit");
let mut choice = String::new();
io::stdin().read_line(&mut choice).expect("Failed to read line");
let choice: u32 = match choice.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
match choice {
1 => {
println!("Enter the title of the new item:");
let mut title = String::new();
io::stdin().read_line(&mut title).expect("Failed to read line");
todo_list.add_item(title.trim().to_string());
}
2 => {
todo_list.list_items();
}
3 => {
println!("Enter the ID of the completed item:");
let mut id = String::new();
io::stdin().read_line(&mut id).expect("Failed to read line");
let id: u64 = match id.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
todo_list.complete_item(id);
}
4 => {
println!("Exiting the program.");
break;
}
_ => {
println!("Invalid choice. Please enter a number between 1 and 4.");
}
}
}
}
Step 5: Run Your To-Do List Application
Run your application using:
cargo run
Follow the on-screen instructions to add, list, and complete To-Do items in your Rust To-Do List application.
Calculator App
Building a basic calculator in Rust is a great way to practice the language and its fundamental concepts.
Step 1: Set Up Your Rust Environment
Step 2: Create a New Rust Project
# Create a new Rust project
$ cargo new calculator_app
$ cd calculator_app
Step 3: Implement the Calculator Logic
Edit the src/main.rs
file to implement the calculator logic:
// src/main.rs
use std::io;
fn main() {
loop {
println!("Simple Calculator");
println!("1. Addition");
println!("2. Subtraction");
println!("3. Multiplication");
println!("4. Division");
println!("5. Exit");
let mut choice = String::new();
io::stdin().read_line(&mut choice).expect("Failed to read line");
let choice: u32 = match choice.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
if choice == 5 {
println!("Exiting the calculator.");
break;
}
println!("Enter the first number:");
let mut num1 = String::new();
io::stdin().read_line(&mut num1).expect("Failed to read line");
let num1: f64 = match num1.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("Invalid input. Please enter a valid number.");
continue;
}
};
println!("Enter the second number:");
let mut num2 = String::new();
io::stdin().read_line(&mut num2).expect("Failed to read line");
let num2: f64 = match num2.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("Invalid input. Please enter a valid number.");
continue;
}
};
match choice {
1 => {
let result = num1 + num2;
println!("Result: {}", result);
}
2 => {
let result = num1 - num2;
println!("Result: {}", result);
}
3 => {
let result = num1 * num2;
println!("Result: {}", result);
}
4 => {
if num2 != 0.0 {
let result = num1 / num2;
println!("Result: {}", result);
} else {
println!("Error: Division by zero.");
}
}
_ => {
println!("Invalid choice. Please enter a number between 1 and 5.");
}
}
}
}
Step 4: Run Your Calculator
cargo run
Simple Blog Platform
Building a simple blog platform in Rust involves creating a web server, handling HTTP requests, and interacting with a database. Here, I'll guide you through creating a basic blog platform using the Actix web framework and SQLite as the database.
Note that this is a minimal example for learning purposes. In a real-world scenario, you'd want to consider security, user authentication, and additional features.
Step 1: Set Up Your Rust Environment
Step 2: Create a New Rust Project
# Create a new Rust project
$ cargo new new simple_blog
$ cd new simple_blog
Step 3: Add Dependencies to Cargo.toml
Edit the Cargo.toml
file to include the necessary dependencies:
[dependencies]
actix-web = "4.0"
actix-rt = "2.5"
sqlx = "0.5"
sqlx-core = "0.5"
sqlx-migrate = "0.5"
sqlx-derive = "0.5"
dotenv = "0.17"
Run cargo build
to fetch and build the dependencies.
Step 4: Set Up Your Database
Create a .env
file in your project directory with the following content:
DATABASE_URL=sqlite:./blog.db
Step 5: Define the Database Schema
Create a migrations
directory and add a file named 20220101000000_init.sql
:
-- migrations/20220101000000_init.sql
-- create the posts table
CREATE TABLE posts (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL
);
Step 6: Set Up Database Connection
Create a src/db.rs
file for handling the database connection:
// src/db.rs
use sqlx::sqlite::SqlitePool;
use sqlx::Pool;
use std::env;
pub async fn init_pool() -> Pool<SqlitePool> {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env");
SqlitePool::connect(&database_url)
.await
.expect("Failed to connect to the database")
}
Step 7: Implement the Blog Platform
Edit the src/main.rs
file with the following code:
// src/main.rs
use actix_web::{web, App, HttpServer, Responder};
use sqlx::sqlite::SqlitePool;
use sqlx::Row;
use dotenv::dotenv;
mod db;
async fn index(pool: web::Data<SqlitePool>) -> impl Responder {
let mut conn = pool.acquire().await.expect("Failed to acquire a database connection");
let result = sqlx::query!("SELECT id, title, content FROM posts")
.fetch_all(&mut conn)
.await
.expect("Failed to fetch posts from the database");
let posts: Vec<String> = result
.iter()
.map(|row| format!("{}: {}\n{}", row.id, row.title, row.content))
.collect();
posts.join("\n")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
let pool = db::init_pool().await;
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Step 8: Run the Application
cargo run
Visit http://127.0.0.1:8080 to see your simple blog platform in action.
This is a basic example, and you can extend it by adding features such as creating, updating, and deleting posts, handling user authentication, and improving the frontend using a front-end framework. Remember to handle errors and ensure security in a production environment.
Weather App
Building a weather app in Rust involves interacting with a weather API to fetch real-time weather data and presenting it to users. Here's a simple example using the Actix web framework and the OpenWeatherMap API.
Step 1: Set Up Your Rust Environment
Step 2: Create a New Rust Project
# Create a new Rust project
$ cargo new weather_app
$ cd weather_app
Step 3: Add Dependencies to Cargo.toml
Edit the Cargo.toml
file to include the necessary dependencies:
[dependencies]
actix-web = "4.0"
reqwest = "0.11"
serde = "1.0"
serde_json = "1.0"
dotenv = "0.17"
Run cargo build
to fetch and build the dependencies.
Step 4: Set Up Your OpenWeatherMap API Key
Create a .env
file in your project directory with the following content:
OPENWEATHERMAP_API_KEY=your_api_key_here
Replace your_api_key_here
with your actual OpenWeatherMap API key.
Step 5: Implement the Weather App
Edit the src/main.rs
file with the following code:
// src/main.rs
use actix_web::{web, App, HttpServer, HttpResponse};
use reqwest::Client;
use serde::Deserialize;
use std::env;
#[derive(Deserialize)]
struct WeatherResponse {
main: Main,
name: String,
}
#[derive(Deserialize)]
struct Main {
temp: f32,
}
async fn index() -> HttpResponse {
let api_key = env::var("OPENWEATHERMAP_API_KEY").expect("OPENWEATHERMAP_API_KEY is not set in .env");
let city = "London"; // You can replace this with the desired city
let url = format!(
"http://api.openweathermap.org/data/2.5/weather?q={}&appid={}&units=metric",
city, api_key
);
let response = Client::new().get(&url).send().await;
match response {
Ok(res) => {
let weather_data: WeatherResponse = res.json().await.expect("Failed to parse JSON response");
let temperature = weather_data.main.temp;
let city_name = weather_data.name;
HttpResponse::Ok().body(format!("Weather in {}: {:.1}°C", city_name, temperature))
}
Err(_) => HttpResponse::InternalServerError().body("Failed to fetch weather data"),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv::dotenv().ok();
HttpServer::new(|| {
App::new().route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Step 6: Run the Application
cargo run
Visit http://127.0.0.1:8080 to see the current weather in the specified city.
This serves as a foundation; consider refining it by incorporating user city input, refining error handling, and enhancing the frontend with a robust framework. Prioritize error management and security measures for production readiness.
Budget Manager App
Building a simple budget manager in Rust involves creating a command-line application that allows users to manage their income, expenses, and view the overall budget. Here's a basic example to get you started:
Step 1: Set Up Your Rust Environment
Step 2: Create a New Rust Project
cargo new budget_manager
cd budget_manager
Step 3: Implement the Budget Manager
Edit the src/main.rs
file with the following code:
// src/main.rs
use std::io;
struct BudgetManager {
income: f64,
expenses: f64,
}
impl BudgetManager {
fn new() -> Self {
Self {
income: 0.0,
expenses: 0.0,
}
}
fn add_income(&mut self, amount: f64) {
self.income += amount;
println!("Income added: ${}", amount);
}
fn add_expense(&mut self, amount: f64) {
self.expenses += amount;
println!("Expense added: ${}", amount);
}
fn view_budget(&self) {
let balance = self.income - self.expenses;
println!("Income: ${}", self.income);
println!("Expenses: ${}", self.expenses);
println!("Balance: ${}", balance);
}
}
fn main() {
let mut budget_manager = BudgetManager::new();
loop {
println!("Budget Manager");
println!("1. Add Income");
println!("2. Add Expense");
println!("3. View Budget");
println!("4. Exit");
let mut choice = String::new();
io::stdin().read_line(&mut choice).expect("Failed to read line");
let choice: u32 = match choice.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
match choice {
1 => {
println!("Enter the income amount:");
let mut amount = String::new();
io::stdin().read_line(&mut amount).expect("Failed to read line");
let amount: f64 = match amount.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
budget_manager.add_income(amount);
}
2 => {
println!("Enter the expense amount:");
let mut amount = String::new();
io::stdin().read_line(&mut amount).expect("Failed to read line");
let amount: f64 = match amount.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
budget_manager.add_expense(amount);
}
3 => {
budget_manager.view_budget();
}
4 => {
println!("Exiting the budget manager.");
break;
}
_ => {
println!("Invalid choice. Please enter a number between 1 and 4.");
}
}
}
}
Step 4: Run the Application
cargo run
Follow the on-screen instructions to add income, expenses, and view your budget.
Feel free to enhance and customize the applications based on your learning goals and preferences. This is a basic example to get you started with Rust programming. If you have any questions or want to share your thoughts, please feel free to leave a comment or reach out to me. Let's continue to explore the vast possibilities of Rust together.
☞ Follow me on Twitter & Linkedin
☞ Kindly subscribe for my upcoming articles
Posted on January 14, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
January 14, 2024