Skip to content

Commit

Permalink
lesson 0 and lesson 1
Browse files Browse the repository at this point in the history
  • Loading branch information
stream-rahul committed Jan 25, 2025
1 parent 03522e3 commit 20ef71a
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 58 deletions.
37 changes: 20 additions & 17 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
# Rust specific
/target/
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
# Binaries and debug files
*.exe
*.pdb
*.dll
*.so
*.dylib

# IDE specific
.idea/
.vscode/
*.swp
*.swo

# Debug files
debug/
release/

# System specific
.DS_Store
thumbs.db

# Jekyll build directories
_site/
.sass-cache/
.jekyll-cache/

# VS Code settings
.vscode/

# IDE files
.idea/
*.swp
2 changes: 1 addition & 1 deletion _posts/2024-01-25-lesson0.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ categories: rust
permalink: /lesson0/
---

# Lesson 0: Hello World in Rust 🌟
# Lesson 0: A copy program 🌟


```rust
Expand Down
102 changes: 83 additions & 19 deletions _posts/2024-01-26-lesson1.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,97 @@
---
layout: default
title: "Lesson 1: Variables and Data Types in Rust"
title: "Lesson 1 : Chnage Directory Program
date: 2024-01-26
categories: rust
permalink: /lesson1/ # ← Added trailing slash
permalink: /lesson1/
---
# Lesson 1: Variables and Data Types in Rust 🔢
# Lesson 1: Change Directory 🔢
Welcome to **Lesson 1**! In this tutorial, we'll dive into variables and data types in Rust, a statically typed language that ensures type safety and performance. Let’s explore!
```rust
---
## 📝 What You'll Learn
By the end of this lesson, you’ll understand:
- The difference between mutable and immutable variables.
- How Rust handles data types.
- Writing efficient and safe code with Rust's type system.
---
use std::env; // (1) Imports `env` module; compile-time resolves
use std::ffi::OsString; // (2) `OsString` - platform-native string, byte-based
use std::io::{self, Write}; // (3) Imports `io` module, `Write` trait for streams
use std::process; // (4) Imports `process` module for program control
## 🔍 Variables in Rust
fn report_error(msg: &str, exit_code: i32, // (5) `&str` - slice, immutable view into UTF-8 data
show_error: bool) -> ! { // (6) `bool` - single byte, conditional jumps at ASM level
eprintln!("Error: {}", msg); // (7) Macro `eprintln!` -> stderr, buffered output likely
// may involve mutex locks internally for sync.

In Rust, variables are **immutable by default**. If you need to change their value, you can make them mutable with the `mut` keyword.
if show_error { // (8) `if` statement; CPU branch instruction, predicate eval
let error = io::Error::last_os_error(); // (9) Syscall `last_os_error()` retrieves thread-local
// errno, potential context switch into kernel.
eprintln!("System error: {} (code {})", // (10) Formatting via macros - alloc on stack? or heap?
error,
error.raw_os_error().unwrap_or(-1)); // (11) `.unwrap_or()` avoids panic, returns -1 on None
// loss of error info if None ever occurs.
}

### Immutable Variables
```rust
fn main() {
let x = 5; // Immutable variable
println!("The value of x is: {}", x);
process::exit(exit_code); // (12) `process::exit()` - system call `exit()`, process term.
// OS cleans resources; memory, file descriptors.
}

fn main() { // (13) `main` entry point, symbol resolved by linker at build.
let args: Vec<OsString> = env::args_os().collect(); // (14) `env::args_os()` - syscall to get OS args as bytes
// allocates `Vec` on heap, dynamic size.
// `OsString` avoids UTF-8 validation overhead.
let target_dir = if args.len() < 2 { // (15) `args.len()` - reads `Vec` length from heap metadata
// integer compare instruction by CPU.
// Default to user profile directory
match env::var_os("USERPROFILE") { // (16) `env::var_os()` - syscall `getenv` or similar for env var
// OS-specific call, kernel interaction, perf varies.
Some(path) => path, // (17) `Some(path)` - pattern match, compiler generates code
// for case analysis, avoids null pointer checks.
None => report_error("Home directory not found.", // (18) `None` branch in `match`, jump to error path.
1, false), // string literal in RODATA section of executable.
}
} else { // (19) `else` branch, another conditional jump at ASM level.
args[1].clone() // (20) `args[1]` - Vec index access, bound check potentially
// `clone()` triggers allocation if OsString not Copy.
// heap allocation possible for new OsString.
};

// Convert OsString to &str for error checking
let target_str = target_dir.to_str().unwrap_or_else(|| { // (21) `to_str()` UTF-8 validation, creates &str slice
// if valid, else `None`. Overhead for UTF-8.
report_error("Invalid target directory encoding.", // (22) Closure for error handling on invalid UTF-8.
1, false) // Closure compiled as separate anonymous function.
});

if target_str.is_empty() { // (23) `target_str.is_empty()` - string slice metadata check
// very cheap, just a size comparison instruction.
report_error("Invalid target directory.", // (24) String literal again in read-only memory.
1, false); // no heap allocation for string literal itself.
}

if let Err(e) = env::set_current_dir(&target_dir) { // (25) `env::set_current_dir()` - syscall `chdir()`, changes CWD
// kernel operation, potential perf impact.
// `&target_dir` - borrow, no ownership transfer.
eprintln!("Failed to change directory to '{}'", // (26) Format string for error message, heap allocation?
target_str); // `target_str` is borrowed &str, no copy.
report_error(&format!("{}", e), 1, true); // (27) `format!("{}", e)` - creates new String on heap
// alloc/dealloc overhead if error path taken often.
// `&format!()` - borrow to report_error.
}

println!("Current directory is {}", target_str); // (28) `println!` macro, stdout, buffered output.
// similar internals to `eprintln!`.
}
```













```
Binary file removed programs/00helloworld.exe
Binary file not shown.
7 changes: 0 additions & 7 deletions programs/00helloworld.rs

This file was deleted.

14 changes: 0 additions & 14 deletions programs/README.md

This file was deleted.

6 changes: 6 additions & 0 deletions programs/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Hello, this is a test file!
It contains multiple lines
to test our file copying program.

Feel free to copy me to another location.
1234567890
44 changes: 44 additions & 0 deletions src/changedir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::env;
use std::ffi::OsString;
use std::io::{self, Write};
use std::process;

fn report_error(msg: &str, exit_code: i32, show_error: bool) -> ! {
eprintln!("Error: {}", msg);

if show_error {
let error = io::Error::last_os_error();
eprintln!("System error: {} (code {})", error, error.raw_os_error().unwrap_or(-1));
}

process::exit(exit_code);
}

fn main() {
let args: Vec<OsString> = env::args_os().collect();
let target_dir = if args.len() < 2 {
// Default to user profile directory
match env::var_os("USERPROFILE") {
Some(path) => path,
None => report_error("Home directory not found.", 1, false),
}
} else {
args[1].clone()
};

// Convert OsString to &str for error checking
let target_str = target_dir.to_str().unwrap_or_else(|| {
report_error("Invalid target directory encoding.", 1, false)
});

if target_str.is_empty() {
report_error("Invalid target directory.", 1, false);
}

if let Err(e) = env::set_current_dir(&target_dir) {
eprintln!("Failed to change directory to '{}'", target_str);
report_error(&format!("{}", e), 1, true);
}

println!("Current directory is {}", target_str);
}
52 changes: 52 additions & 0 deletions src/helloworld.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
use std::process;

const BUF_SIZE: usize = 256;

fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("Usage: {} file1 file2", args[0]);
process::exit(1);
}

let mut in_file = match File::open(&args[1]) {
Ok(file) => file,
Err(err) => {
eprintln!("{}: {}", args[1], err);
process::exit(2);
}
};

let mut out_file = match File::create(&args[2]) {
Ok(file) => file,
Err(err) => {
drop(in_file);
eprintln!("{}: {}", args[2], err);
process::exit(3);
}
};

let mut buffer = [0u8; BUF_SIZE];

loop {
let bytes_in = match in_file.read(&mut buffer) {
Ok(n) => n,
Err(err) => {
eprintln!("Error reading file: {}", err);
process::exit(4);
}
};

if bytes_in == 0 {
break;
}

if let Err(err) = out_file.write_all(&buffer[..bytes_in]) {
eprintln!("Fatal write error: {}", err);
process::exit(4);
}
}
}
3 changes: 3 additions & 0 deletions src/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Hello, this is a test file!
It contains multiple lines
to test our file copy program.
3 changes: 3 additions & 0 deletions src/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Hello, this is a test file!
It contains multiple lines
to test our file copy program.

0 comments on commit 20ef71a

Please sign in to comment.