Antes que nada, ya toque rust hace un par de años pero nada mas despues de eso, tocando tipos de datos y sintaxis. Pero quiero aprender mas de este camion que detona cualquier brenchmark.
Refrescando y aprendiendo mas de las bases
Primero me puse a buscar algun curso en español en yt que valiera la pena y en eso me encontre este de 4 horas en español que es un gusto bueno.

Despues de una hora de repaso cree mi primer projecto Cargo del 2024.
fn main() {
println!("Hello, chupapis!");
}Si, que esperaba xD.

Creando algo mas elaborado
Anyways, no podía quedarme solo con eso. Quería hacer algo simple para empezar. que mejor que un CLI que cree un usuario y que al final te diga su información.
fn main() {
println!("Hello, chupapis!");
}
struct User {
name: String,
age: i8,
email: String,
birthday: // No hay Date .___.
}Mmhhhh….. Rust no tiene algún tipo Date 🥲
Ante estos problemas: “Toca preguntar a ChatGPT 👍”.

Que pro! 😯 y me dio este ejemplo:
use chrono::NaiveDate;
fn main() {
let user = User {
name: String::from("Diego"),
age: 22,
email: String::from("diego@example.com"),
birthday: NaiveDate::from_ymd(2002, 3, 28), // Año, mes, día
};
println!(
"Nombre: {}, Edad: {}, Email: {}, Cumpleaños: {}",
user.name, user.age, user.email, user.birthday
);
}
struct User {
name: String,
age: i8,
email: String,
birthday: NaiveDate,
}Lo que no sabia es que….

from_ymd esta deprecado 🥲
Pero los problemas están para solucionarse. Usare el recomendado from_ymd_opt .
fn main() {
let user = User {
name: String::from("Diego Musagy"),
age: 22,
email: String::from("diego.1203.dm@gmail.com"),
birthday: NaiveDate::from_ymd_opt(2002, 3, 28)
.expect("Fecha inválida"),
};
println!(
"Nombre: {}, Edad: {}, Email: {}, Cumpleaños: {}",
user.name, user.age, user.email, user.birthday
);
}
struct User {
name: String,
age: i8,
email: String,
birthday: NaiveDate,
}Ahora si esto ya era otra cosita pues. 😎
Pero aun le faltaba la interactividad así que ahora tenia que aprender a recibir el input.
use std::io::stdin as input;Sip, para que sea mas ameno.

Y después de unos minutos tuve esto. 💀
use chrono::NaiveDate;
use std::io::stdin as input;
fn main() {
let mut name = String::from("");
let mut age_str = String::from("");
let age: u8;
let mut email = String::from("");
let mut bd_year_str = String::from("");
let bd_year: i32;
let mut bd_month_str = String::from("");
let bd_month: u32;
let mut bd_day_str = String::from("");
let bd_day: u32;
println!("¿Cual es tu nombre?");
input().read_line(&mut name)
.expect("error al leer la entrada");
println!("¿Cual es tu edad?");
input().read_line(&mut age_str)
.expect("error al leer la entrada");
age = age_str.trim()
.parse()
.expect("Por favor. Inserte un numero correcto.");
println!("¿Cual es tu email?");
input().read_line(&mut email)
.expect("error al leer la entrada");
println!("¿Cual es tu cumpleaños?");
println!("\tAño: ");
input().read_line(&mut bd_year_str)
.expect("error al leer la entrada");
println!("\tMes: ");
input().read_line(&mut bd_month_str)
.expect("error al leer la entrada");
println!("\tDia: ");
input().read_line(&mut bd_day_str)
.expect("error al leer la entrada");
bd_year = bd_year_str.trim()
.parse()
.expect("Por favor. Inserte un numero correcto.");
bd_month = bd_month_str.trim()
.parse()
.expect("Por favor. Inserte un numero correcto.");
bd_day = bd_day_str.trim()
.parse()
.expect("Por favor. Inserte un numero correcto.");
let birthday = NaiveDate::from_ymd_opt(bd_year, bd_month, bd_day)
.expect("Fecha invalida");
let user = User {
name,
age,
email,
birthday,
};
println!(
"Nombre: {}, Edad: {}, Email: {}, Cumpleaños: {}",
user.name, user.age, user.email, user.birthday
);
}
struct User {
name: String,
age: u8,
email: String,
birthday: NaiveDate,
}Si, mucho “repetirme a mi mismo” pero funcional al final del día.
Vamos a refactorizarlo.
Primer lo que hice fue un read_line genérico. la responsabilidad de la variable para obtener el contenido “RAW”. Quedaría en la propia función para que el propio scope elimine la variable al finalizar la función. Y claro lo único que retornaría seria un string limpio y si salto de linea \n. 👍
fn read_line (placeholder: &str) -> String {
println!("{}", placeholder);
let mut input_var= String::from("");
input()
.read_line(&mut input_var)
.expect("error al leer la entrada");
input_var.trim().to_string()
}Ahora en el caso de los integer primero hice algo así:
fn read_u8(placeholder: &str) -> u8 {
loop {
let raw = read_line(placeholder);
match raw.parse() {
Ok(value) => return value,
Err(_) => println!("Inserte un numero valido")
};
}
}
fn read_i32(placeholder: &str) -> i32 {
loop {
let raw = read_line(placeholder);
match raw.parse() {
Ok(value) => return value,
Err(_) => println!("Inserte un numero valido")
};
}
}
fn read_u32(placeholder: &str) -> u32 {
loop {
let raw = read_line(placeholder);
match raw.parse() {
Ok(value) => return value,
Err(_) => println!("Inserte un numero valido")
};
}
}pero siento que algo esta mal xD
Me tocaría aprender “genéricos” para poder poner cualquier tipo de dato que quiera como lo hacemos con los genéricos de Typescript.
function firstElement<T>(array: T[]): T | undefined {
return array[0];
}
let primerNumero = firstElement([1, 2, 3]); // T es number
let primeraPalabra = firstElement(["a", "b", "c"]); // T es stringEsto ya era algo avanzado suponía, así que me fui a preguntarle a real Chatgpt.
Me dio esto de acá.
fn read_int<T: std::str::FromStr>(placeholder: &str) -> T
where
T::Err: std::fmt::Debug,
{
loop {
let raw = read_line(placeholder);
match raw.parse::<T>() {
Ok(value) => return value,
Err(_) => println!("Por favor, ingrese un número válido."),
}
}
}lo mas exótico seria ese “tipo” del genérico, std::str::FromStr y lo que me dijo fue:

Lo único que puedo decir que ya se porque Rust es muy seguro, limitándote inclusive con genéricos, indicándole las operaciones necesarias a HACER para que funcione correctamente la…. función valga la redundancia xD
y lo que saque al final fue esta función.
fn read_int<T: std::str::FromStr>(placeholder: &str) -> T {
loop {
let raw = read_line(placeholder);
match raw.parse::<T>() {
Ok(value) => return value,
Err(_) => println!("Inserte un numero valido")
};
}
}Al no usar el error que devuelve el parse si falla en el match, simplemente le quito el where que es sintaxis que aun no conozco pero supongo que habrá sido para validad que el error se pueda imprimir. Así quedando algo mas limpio.
Y ya por ultimo hacer una función para leer una fecha.
fn read_date(placeholder: &str) -> NaiveDate {
println!("{}", placeholder);
let year = read_int("Año: ");
let month = read_int("Mes: ");
let day = read_int("Dia: ");
NaiveDate::from_ymd_opt(year, month, day)
.expect("Fecha invalida")
}Y el read_int ya devuelve los tipos necesarios que necesita el método from_ymd_opt automáticamente.
Refactorizo el main y quedaría así:
use chrono::NaiveDate;
use std::io::stdin as input;
fn main() {
let name = read_line("¿Cual es tu nombre?");
let age = read_int("¿Cual es tu edad?");
let email = read_line("¿Cual es tu Email?");
let birthday = read_date("¿Cual es tu cumpleaños?");
let user = User {
name,
age,
email,
birthday
};
println!("Hello, chupapis!");
println!(
"Nombre: {}, Edad: {}, Email: {}, Cumpleaños: {}",
user.name, user.age, user.email, user.birthday
);
}
fn read_line (placeholder: &str) -> String {
println!("{}", placeholder);
let mut input_var= String::from("");
input()
.read_line(&mut input_var)
.expect("error al leer la entrada");
input_var.trim().to_string()
}
fn read_int<T: std::str::FromStr>(placeholder: &str) -> T {
loop {
let raw = read_line(placeholder);
match raw.parse::<T>() {
Ok(value) => return value,
Err(_) => println!("Inserte un numero valido")
};
}
}
fn read_date(placeholder: &str) -> NaiveDate {
println!("{}", placeholder);
let year = read_int("Año: ");
let month = read_int("Mes: ");
let day = read_int("Dia: ");
NaiveDate::from_ymd_opt(year, month, day)
.expect("Fecha invalida")
}
struct User {
name: String,
age: u8,
email: String,
birthday: NaiveDate
}y al ejecutarlo logro tener este resultado:

Y eso seria todo por ahora. Supongo que el siguiente paso es hacer una api REST. Y me pondré a ver cual escoger entre Actix, Axum o Rocket.