feat: ✨ error_handling
This commit is contained in:
parent
42bd5132d5
commit
889c95e58f
2 changed files with 90 additions and 0 deletions
6
24-error_handling/Cargo.toml
Normal file
6
24-error_handling/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "error_handling"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
84
24-error_handling/src/main.rs
Normal file
84
24-error_handling/src/main.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
use std::{
|
||||||
|
error::Error,
|
||||||
|
io::{self, Read},
|
||||||
|
net::TcpListener,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Normally main functions return nothing in Rust
|
||||||
|
// but we're allowed to return numeric values
|
||||||
|
// it's convention from C and Rust wanted to fit for this also.
|
||||||
|
// If your process works successfully you just return 0
|
||||||
|
// else you return something other then zero.
|
||||||
|
// You can specify these returns by Termination trait
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
println!("Hello, world!");
|
||||||
|
|
||||||
|
// This is a way to handle a case/error, because you are handling every situation
|
||||||
|
// I like this because I can clearly decide what to do
|
||||||
|
// but I can accept that it's too much verbose for some cases,
|
||||||
|
// especially if you want to just do things for error/none cases
|
||||||
|
// so we have "if let" for this
|
||||||
|
match read_from_connection("127.0.0.1:1") {
|
||||||
|
//if everything is good it will be Ok state,
|
||||||
|
Ok(buffer) => println!("{:#?}", buffer),
|
||||||
|
//if we got an error it will be Err state
|
||||||
|
Err(err_val) => eprintln!("Error: Read from socket | {}", err_val),
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = -4.0;
|
||||||
|
// This "if let" allows us to apply action for each case separately
|
||||||
|
// This is good if you want to just take an action for errors or vice versa
|
||||||
|
if let None = square_rooter(input) {
|
||||||
|
// This part will work because
|
||||||
|
// I wrote my function to return None if it gets negative number
|
||||||
|
println!("{} is not positive number", input)
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = input * -1.0;
|
||||||
|
if let Some(result) = square_rooter(input) {
|
||||||
|
// This part will work because
|
||||||
|
// I wrote my function to return Some(square root of input) if it gets positive number
|
||||||
|
println!("{} is the result !", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This question mark says it will just return early if it reaches None or Err case
|
||||||
|
// It eliminates boilerplates
|
||||||
|
// This must return code earlier if you don't start the code with higher privileges
|
||||||
|
// because port 1 is belongs to operating system
|
||||||
|
// You will see an error with an output code
|
||||||
|
// We can return this output code because we defined that main function can do this
|
||||||
|
// (in function header we gave output type)
|
||||||
|
read_from_connection("127.0.0.1:1")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is just a scenario for returning Result
|
||||||
|
// Basically it's trying to listen a socket and get data from it
|
||||||
|
// We have a lot of '?' in this function to eliminate boilerplate
|
||||||
|
fn read_from_connection(addr: &str) -> Result<Vec<u8>, io::Error> {
|
||||||
|
// This tries binding to socket
|
||||||
|
let tcp_listener = TcpListener::bind(addr)?;
|
||||||
|
// This tries accepting connection from socket
|
||||||
|
let mut tcp_stream = tcp_listener.accept()?.0;
|
||||||
|
let mut buffer = vec![];
|
||||||
|
// This tries read value from socket
|
||||||
|
tcp_stream.read_to_end(&mut buffer)?;
|
||||||
|
Ok(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is an example about another boilerplate eliminator.
|
||||||
|
// It just calculates square root of a number
|
||||||
|
//
|
||||||
|
// It's basically this:
|
||||||
|
//
|
||||||
|
// if input > 0.0 {
|
||||||
|
// Some(input.sqrt())
|
||||||
|
// } else {
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Actual function is not that performant as above
|
||||||
|
// but it can be useful
|
||||||
|
fn square_rooter(input: f64) -> Option<f64> {
|
||||||
|
(input > 0.0).then(|| input.sqrt())
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue