Skip to content

Commit

Permalink
release day 25 to day 27
Browse files Browse the repository at this point in the history
  • Loading branch information
0xbojiTheSecond committed Jan 2, 2025
1 parent 48e1770 commit 3ea156e
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/day25_to_day27/custom_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use std::error::Error;
use std::fmt;

// Custom error type
#[derive(Debug)]
pub enum CalculationError {
DivisionByZero,
Overflow,
InvalidInput(String),
}

// Implement Display for our error type
impl fmt::Display for CalculationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CalculationError::DivisionByZero => write!(f, "division by zero"),
CalculationError::Overflow => write!(f, "calculation overflow"),
CalculationError::InvalidInput(msg) => write!(f, "invalid input: {}", msg),
}
}
}

// Implement the Error trait
impl Error for CalculationError {}

// Function that uses our custom error type
fn divide(a: i32, b: i32) -> Result<i32, CalculationError> {
if b == 0 {
return Err(CalculationError::DivisionByZero);
}

if a == i32::MIN && b == -1 {
return Err(CalculationError::Overflow);
}

Ok(a / b)
}

pub fn run() {
println!("\nCustom Error Examples:");

// Test various scenarios
let test_cases = vec![
(10, 2),
(10, 0),
(i32::MIN, -1),
];

for (a, b) in test_cases {
match divide(a, b) {
Ok(result) => println!("{} / {} = {}", a, b, result),
Err(e) => println!("Error: {}", e),
}
}
}
54 changes: 54 additions & 0 deletions src/day25_to_day27/error_handling.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::fs::File;
use std::io::{self, Read};

pub fn run() {
println!("\nError Handling Examples:");

// Example 1: Basic error handling with match
match read_username_from_file("username.txt") {
Ok(username) => println!("Username: {}", username),
Err(e) => println!("Error reading username: {}", e),
}

// Example 2: Using the ? operator
if let Err(e) = read_username_concise("username.txt") {
println!("Error reading username (concise): {}", e);
}

// Example 3: Demonstrating panic
demonstrate_panic();
}

// Example function that returns a Result
fn read_username_from_file(filename: &str) -> Result<String, io::Error> {
let mut file = match File::open(filename) {
Ok(file) => file,
Err(e) => return Err(e),
};

let mut username = String::new();
match file.read_to_string(&mut username) {
Ok(_) => Ok(username),
Err(e) => Err(e),
}
}

// Same function using the ? operator for more concise error handling
fn read_username_concise(filename: &str) -> Result<String, io::Error> {
let mut username = String::new();
File::open(filename)?.read_to_string(&mut username)?;
Ok(username)
}

// Function demonstrating when to use panic!
fn demonstrate_panic() {
let names = vec!["Alice", "Bob", "Charlie"];

// Safe access
if let Some(name) = names.get(1) {
println!("Safely accessed name: {}", name);
}

// This would panic - uncomment to see
// let name = &names[5]; // This will panic!
}
41 changes: 41 additions & 0 deletions src/day25_to_day27/integration_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
pub fn run() {
println!("\nIntegration Tests Example");
println!("(See tests directory for integration tests)");
}

// Public API to be tested in integration tests
pub struct Calculator {
value: i32,
}

impl Calculator {
pub fn new() -> Self {
Calculator { value: 0 }
}

pub fn add(&mut self, x: i32) {
self.value += x;
}

pub fn subtract(&mut self, x: i32) {
self.value -= x;
}

pub fn get_value(&self) -> i32 {
self.value
}
}

// Note: Integration tests should be placed in the tests directory
// Create a file: tests/calculator_tests.rs with the following content:
/*
use your_crate_name::Calculator;
#[test]
fn test_calculator_integration() {
let mut calc = Calculator::new();
calc.add(5);
calc.subtract(2);
assert_eq!(calc.get_value(), 3);
}
*/
16 changes: 16 additions & 0 deletions src/day25_to_day27/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pub mod error_handling;
pub mod custom_errors;
pub mod result_option;
pub mod testing;
pub mod test_organization;
pub mod integration_tests;

pub fn run() {
println!("Days 25-27: Error Handling and Testing");
error_handling::run();
custom_errors::run();
result_option::run();
testing::run();
test_organization::run();
integration_tests::run();
}
78 changes: 78 additions & 0 deletions src/day25_to_day27/result_option.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
pub fn run() {
println!("\nResult and Option Examples:");

// Option examples
demonstrate_option();

// Result examples
demonstrate_result();

// Combining Option and Result
demonstrate_combined();
}

fn demonstrate_option() {
println!("\nOption Examples:");

let numbers = vec![1, 2, 3, 4, 5];

// Using map with Option
let first: Option<&i32> = numbers.first();
let plus_one: Option<i32> = first.map(|n| n + 1);
println!("First number plus one: {:?}", plus_one);

// Using and_then
let maybe_string = Some("Hello");
let maybe_len = maybe_string.and_then(|s| Some(s.len()));
println!("String length: {:?}", maybe_len);

// Using filter
let even_first = first.filter(|n| *n % 2 == 0);
println!("First even number: {:?}", even_first);
}

fn demonstrate_result() {
println!("\nResult Examples:");

// Chaining Results
let result = parse_and_multiply("5")
.and_then(|n| multiply_by_two(n))
.map_err(|e| format!("Calculation error: {}", e));

println!("Result of calculation: {:?}", result);
}

fn demonstrate_combined() {
println!("\nCombined Option and Result Examples:");

let numbers = vec![1, 2, 3, 4, 5];
let index = 2;

let result = get_number(&numbers, index)
.ok_or_else(|| "Index out of bounds".to_string())
.and_then(|n| multiply_by_two(n));

match result {
Ok(n) => println!("Number at index {} multiplied by 2: {}", index, n),
Err(e) => println!("Error: {}", e),
}
}

// Helper functions
fn parse_and_multiply(s: &str) -> Result<i32, String> {
s.parse::<i32>()
.map_err(|e| e.to_string())
.map(|n| n * 2)
}

fn multiply_by_two(n: i32) -> Result<i32, String> {
if n > i32::MAX / 2 {
Err("Overflow would occur".to_string())
} else {
Ok(n * 2)
}
}

fn get_number(numbers: &[i32], index: usize) -> Option<i32> {
numbers.get(index).copied()
}
50 changes: 50 additions & 0 deletions src/day25_to_day27/test_organization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
pub fn run() {
println!("\nTest Organization Examples (see test modules below)");
}

// Public function to test
pub fn process_data(data: &str) -> Result<String, String> {
// Call private helper function
let processed = internal_process(data)?;
Ok(processed)
}

// Private helper function
fn internal_process(data: &str) -> Result<String, String> {
if data.is_empty() {
return Err("Data cannot be empty".to_string());
}
Ok(data.to_uppercase())
}

#[cfg(test)]
mod tests {
use super::*;

// Test helper function
fn setup_test_data() -> String {
"test data".to_string()
}

#[test]
fn test_process_data_success() {
let data = setup_test_data();
assert!(process_data(&data).is_ok());
}

#[test]
fn test_process_data_empty() {
assert!(process_data("").is_err());
}

// Nested test module
mod internal_tests {
use super::*;

#[test]
fn test_internal_process() {
let result = internal_process("hello");
assert_eq!(result.unwrap(), "HELLO");
}
}
}
49 changes: 49 additions & 0 deletions src/day25_to_day27/testing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
pub fn run() {
println!("\nTesting Examples (see test cases below)");
}

pub fn add(a: i32, b: i32) -> i32 {
a + b
}

pub fn divide(a: i32, b: i32) -> Option<i32> {
if b == 0 {
None
} else {
Some(a / b)
}
}

pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_add() {
assert_eq!(add(2, 2), 4);
assert_eq!(add(-1, 1), 0);
assert_eq!(add(0, 0), 0);
}

#[test]
fn test_divide() {
assert_eq!(divide(10, 2), Some(5));
assert_eq!(divide(3, 0), None);
}

#[test]
fn test_greet() {
assert_eq!(greet("Alice"), "Hello, Alice!");
assert_ne!(greet("Bob"), "Hi, Bob!");
}

#[test]
#[should_panic(expected = "panic message")]
fn test_panic() {
panic!("panic message");
}
}

0 comments on commit 3ea156e

Please sign in to comment.