Ce face From
From<T> descrie cum se construiește un tip din altul, fără posibilitate de eroare: String::from("text"), f64::from(3_i32), Vec::from([1, 2, 3]). Convenția este să-l folosești doar pentru conversii sigure și evidente; pentru cele care pot eșua există TryFrom.
Când scrii impl From<A> for B, Rust îți dă automat și impl Into<B> for A, deci poți scrie și let b: B = a.into();. De aceea se implementează mereu From, niciodată Into direct.
Un loc important este tratarea erorilor: operatorul ? convertește automat eroarea cu From. Dacă tipul tău de eroare are impl From<ParseIntError>, poți folosi ? pe parse() într-o funcție care returnează eroarea ta.
Parametri
| Parametru | Descriere |
|---|---|
from(valoare) |
Primește valoarea sursă (prin valoare, deci o consumă) și returnează tipul nou. |
Ce returnează
O valoare de tipul țintă.
Exemple
Exemplul 1: Conversie între două tipuri proprii
struct Celsius(f64);
struct Fahrenheit(f64);
impl From<Celsius> for Fahrenheit {
fn from(c: Celsius) -> Self {
Fahrenheit(c.0 * 9.0 / 5.0 + 32.0)
}
}
fn main() {
let f = Fahrenheit::from(Celsius(25.0));
println!("25°C = {:.1}°F", f.0);
let g: Fahrenheit = Celsius(-10.0).into(); // into vine automat
println!("-10°C = {:.1}°F", g.0);
println!("{} {:?} {}", f64::from(7_i32), Vec::from([1, 2]), String::from('ș'));
}
Rezultat
25°C = 77.0°F
-10°C = 14.0°F
7 [1, 2] ș
Exemplul 2: From pentru erori și operatorul ?
use std::fmt;
use std::num::ParseIntError;
#[derive(Debug)]
enum EroareComanda {
CantitateInvalida(ParseIntError),
StocInsuficient,
}
impl From<ParseIntError> for EroareComanda {
fn from(e: ParseIntError) -> Self {
EroareComanda::CantitateInvalida(e)
}
}
impl fmt::Display for EroareComanda {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EroareComanda::CantitateInvalida(e) => write!(f, "cantitate invalidă: {e}"),
EroareComanda::StocInsuficient => write!(f, "nu avem destul în stoc"),
}
}
}
fn comanda(text: &str, stoc: u32) -> Result<u32, EroareComanda> {
let cantitate: u32 = text.trim().parse()?; // ParseIntError devine EroareComanda
if cantitate > stoc {
return Err(EroareComanda::StocInsuficient);
}
Ok(stoc - cantitate)
}
fn main() {
for t in ["3", "abc", "50"] {
match comanda(t, 10) {
Ok(rest) => println!("{t}: comandă primită, rămân {rest}"),
Err(e) => println!("{t}: {e}"),
}
}
}
Rezultat
3: comandă primită, rămân 7
abc: cantitate invalidă: invalid digit found in string
50: nu avem destul în stoc
Greșeli frecvente
- Implementezi
Intoîn loc deFrom. Merge, dar pierziFrom; implementeazăFromși primești ambele. - Folosești
Frompentru o conversie care poate pierde date sau eșua (de exemplui64→u8). Pentru acestea esteTryFrom.
Comenzi înrudite
Into: Perechea lui From văzută din partea sursei: x.into() convertește în tipul cerut; util în parametri generici.TryFrom: Conversii care pot eșua și returnează Result: u8::try_from(300) dă Err. Implementarea aduce și try_into().FromStr: Trait-ul care face un tip „citibil” din text; după implementare, „…”.parse::<Tip>() funcționează.String::from: Creează un String nou (deținut) din &str, char sau alt text, copiind conținutul pe heap.