Трейт FromStr
Трейт FromStr позволяет преобразовать строку
в значение некоторого типа. Он содержит один
обязательный метод from_str, который принимает
ссылку на строку и возвращает результат преобразования
в виде Result. Если преобразование прошло
успешно, возвращается вариант Ok со значением,
а если строка имеет неверный формат - вариант
Err с ошибкой. Трейт FromStr
используется методом parse, который есть
у строк.
Синтаксис
impl FromStr for MyType
{
type Err = MyError;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
// ...
}
}
Пример
Давайте реализуем трейт FromStr для структуры
Point, которая хранит координаты точки в формате
"x,y":
use std::str::FromStr;
#[derive(Debug)]
struct Point
{
x: i32,
y: i32,
}
impl FromStr for Point
{
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
let parts: Vec<&str> = s.split(',').collect();
if parts.len() != 2
{
return Err(String::from("invalid format"));
}
let x = parts[0].trim().parse::<i32>()
.map_err(|_| String::from("invalid x"))?;
let y = parts[1].trim().parse::<i32>()
.map_err(|_| String::from("invalid y"))?;
Ok(Point { x, y })
}
}
fn main()
{
let res = Point::from_str("1,2");
println!("{:?}", res);
}
Результат выполнения кода:
Ok(Point { x: 1, y: 2 })
Пример
Давайте проверим, как ведёт себя from_str
при неверном формате строки:
use std::str::FromStr;
#[derive(Debug)]
struct Point
{
x: i32,
y: i32,
}
impl FromStr for Point
{
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
let parts: Vec<&str> = s.split(',').collect();
if parts.len() != 2
{
return Err(String::from("invalid format"));
}
let x = parts[0].trim().parse::<i32>()
.map_err(|_| String::from("invalid x"))?;
let y = parts[1].trim().parse::<i32>()
.map_err(|_| String::from("invalid y"))?;
Ok(Point { x, y })
}
}
fn main()
{
let res = Point::from_str("abc");
println!("{:?}", res);
}
Результат выполнения кода:
Err("invalid format")
Пример
Трейт FromStr работает в связке с методом
parse, который автоматически вызывает
from_str. Давайте воспользуемся этим:
use std::str::FromStr;
#[derive(Debug)]
struct Point
{
x: i32,
y: i32,
}
impl FromStr for Point
{
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
let parts: Vec<&str> = s.split(',').collect();
if parts.len() != 2
{
return Err(String::from("invalid format"));
}
let x = parts[0].trim().parse::<i32>()
.map_err(|_| String::from("invalid x"))?;
let y = parts[1].trim().parse::<i32>()
.map_err(|_| String::from("invalid y"))?;
Ok(Point { x, y })
}
}
fn main()
{
let res: Result<Point, String> = "3,4".parse();
println!("{:?}", res);
}
Результат выполнения кода:
Ok(Point { x: 3, y: 4 })