FromStr în Rust

Trait-ul care face un tip „citibil” din text; după implementare, "...".parse::<Tip>() funcționează.

Sintaxă
impl FromStr for Tip {
    type Err = TipEroare;
    fn from_str(s: &str) -> Result<Self, Self::Err> { ... }
}

let t: Tip = "text".parse()?;

Ce face FromStr

FromStr are o singură metodă, from_str, care transformă un &str în tipul tău sau returnează o eroare. Toate numerele, bool, char, IpAddr îl au deja. Odată implementat pentru tipul tău, poți folosi str::parse, care este forma obișnuită de apel.

Tipul erorii se alege cu type Err. Pentru programe mici un String cu mesajul ajunge; în biblioteci se folosește un tip de eroare propriu, cu Display.

Parametri

Parametru Descriere
type Err Tipul erorii.
from_str(s) Primește textul și returnează Result<Self, Self::Err>.

Ce returnează

Result<Self, Self::Err>.

Exemple

Exemplul 1: O dată în format românesc

use std::str::FromStr;

#[derive(Debug)]
struct Data {
    zi: u8,
    luna: u8,
    an: u16,
}

impl FromStr for Data {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let parti: Vec<&str> = s.trim().split('.').collect();
        let [zi, luna, an] = parti[..] else {
            return Err(format!("„{s}” nu are forma zz.ll.aaaa"));
        };
        let zi: u8 = zi.parse().map_err(|_| format!("zi invalidă: {zi}"))?;
        let luna: u8 = luna.parse().map_err(|_| format!("lună invalidă: {luna}"))?;
        let an: u16 = an.parse().map_err(|_| format!("an invalid: {an}"))?;
        if !(1..=31).contains(&zi) || !(1..=12).contains(&luna) {
            return Err(format!("dată imposibilă: {s}"));
        }
        Ok(Data { zi, luna, an })
    }
}

fn main() {
    for t in ["19.10.2026", "1.12.1918", "31.13.2026", "2026-10-19", "aa.10.2026"] {
        match t.parse::<Data>() {
            Ok(d) => println!("{t}: anul {}, luna {}, ziua {}", d.an, d.luna, d.zi),
            Err(e) => println!("{t}: eroare – {e}"),
        }
    }
}

Rezultat

19.10.2026: anul 2026, luna 10, ziua 19
1.12.1918: anul 1918, luna 12, ziua 1
31.13.2026: eroare – dată imposibilă: 31.13.2026
2026-10-19: eroare – „2026-10-19” nu are forma zz.ll.aaaa
aa.10.2026: eroare – zi invalidă: aa

Exemplul 2: Un enum citit din text

use std::str::FromStr;

#[derive(Debug, PartialEq)]
enum Culoare {
    Rosu,
    Galben,
    Albastru,
}

impl FromStr for Culoare {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "roșu" | "rosu" => Ok(Culoare::Rosu),
            "galben" => Ok(Culoare::Galben),
            "albastru" => Ok(Culoare::Albastru),
            _ => Err(format!("culoare necunoscută: {s}")),
        }
    }
}

fn main() {
    let tricolor: Result<Vec<Culoare>, _> = "albastru galben ROȘU"
        .split_whitespace()
        .map(str::parse)
        .collect();
    println!("{tricolor:?}");
    println!("{:?}", Culoare::from_str("verde"));
    println!("{}", "galben".parse() == Ok(Culoare::Galben));
}

Rezultat

Ok([Albastru, Galben, Rosu])
Err("culoare necunoscută: verde")
true

Greșeli frecvente

  • Scrii o funcție separată fn din_text(s: &str) în loc de FromStr. Merge, dar pierzi parse() și integrarea cu restul bibliotecii.
  • Uiți use std::str::FromStr; când apelezi direct Culoare::from_str. Pentru parse() importul nu este necesar.

Comenzi înrudite

  • str::parse: Transformă textul într-o altă valoare (număr, bool, char, IP, tip propriu) și returnează Result.
  • TryFrom: Conversii care pot eșua și returnează Result: u8::try_from(300) dă Err. Implementarea aduce și try_into().
  • From: Trait-ul pentru conversii care nu pot eșua: Tinta::from(x). Implementându-l, primești gratuit și x.into().
  • ToString: Trait-ul metodei to_string(); există automat pentru orice tip cu Display, deci nu se implementează direct.