使用 FromStr 为自定义类型实现 parse

下面示例展示如何为一个结构体实现 FromStr,以便支持:

let v: Stringable = "hello".parse().unwrap();

示例代码

#[derive(Debug)]
struct Stringable {
    content: String,
}

impl std::str::FromStr for Stringable {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s != "" {
            Ok(Stringable {
                content: s.to_string(),
            })
        } else {
            Err(())
        }
    }
}

用法示例

fn main() {
    let s: Stringable = "abc".parse().unwrap();
    println!("{:?}", s);
}

输出:

Stringable { content: "abc" }

使用 FromInto 实现类型转换

FromInto 是一对相关的 trait,用于实现类型之间的转换。

From<T> - 从类型 T 转换

实现 From<T> 后,可以使用 From::from()T::from() 进行转换:

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(value: i32) -> Self {
        Number { value }
    }
}

// 使用方式
fn main() {
    let num = Number::from(42);
    // 或者
    let num: Number = 42.into();
    println!("{:?}", num);
}

Into<T> - 转换为类型 T

IntoFrom 的逆操作。当你实现了 From<T>Into 会自动实现:

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(value: i32) -> Self {
        Number { value }
    }
}

fn main() {
    let num: Number = 42.into();
    println!("{:?}", num);
}

使用 TryFromTryInto 实现可能失败的类型转换

当转换可能失败时,使用 TryFromTryInto,它们返回 Result 类型。

TryFrom<T> - 尝试从类型 T 转换

#[derive(Debug, PartialEq)]
struct PositiveNumber {
    value: i32,
}

impl std::convert::TryFrom<i32> for PositiveNumber {
    type Error = String;

    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value > 0 {
            Ok(PositiveNumber { value })
        } else {
            Err(format!("{} is not positive", value))
        }
    }
}

// 使用方式
fn main() {
    match PositiveNumber::try_from(42) {
        Ok(num) => println!("{:?}", num),
        Err(e) => println!("Error: {}", e),
    }
    
    // 或者使用 ?
    let num: PositiveNumber = 42.try_into().unwrap();
}

TryInto<T> - 尝试转换为类型 T

#[derive(Debug, PartialEq)]
struct PositiveNumber {
    value: i32,
}

impl std::convert::TryFrom<i32> for PositiveNumber {
    type Error = String;

    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value > 0 {
            Ok(PositiveNumber { value })
        } else {
            Err(format!("{} is not positive", value))
        }
    }
}

fn main() {
    let num: Result<PositiveNumber, _> = (-5).try_into();
    match num {
        Ok(n) => println!("{:?}", n),
        Err(e) => println!("Error: {}", e),
    }
}

使用 AsRefAsMut 实现引用转换

AsRef<T> - 获取不可变引用

struct MyString {
    data: String,
}

impl AsRef<str> for MyString {
    fn as_ref(&self) -> &str {
        &self.data
    }
}

fn print_str(s: &str) {
    println!("{}", s);
}

fn main() {
    let my_str = MyString {
        data: "hello".to_string(),
    };
    print_str(my_str.as_ref());
    // 或者直接使用,因为 AsRef 会自动调用
    print_str(&my_str);
}

AsMut<T> - 获取可变引用

struct MyVec {
    data: Vec<i32>,
}

impl AsMut<Vec<i32>> for MyVec {
    fn as_mut(&mut self) -> &mut Vec<i32> {
        &mut self.data
    }
}

fn modify_vec(v: &mut Vec<i32>) {
    v.push(42);
}

fn main() {
    let mut my_vec = MyVec { data: vec![1, 2, 3] };
    modify_vec(my_vec.as_mut());
    println!("{:?}", my_vec.data);
}

使用 Borrow 实现借用

Borrow 类似于 AsRef,但语义上表示”借用”关系,通常用于哈希表和比较操作:

use std::borrow::Borrow;

#[derive(Debug)]
struct MyString {
    data: String,
}

impl Borrow<str> for MyString {
    fn borrow(&self) -> &str {
        &self.data
    }
}

fn main() {
    let my_str = MyString {
        data: "hello".to_string(),
    };
    let s: &str = my_str.borrow();
    println!("{}", s);
}

使用 ToOwned 实现克隆

ToOwnedClone 的泛型版本,用于从借用类型创建拥有类型:

use std::borrow::ToOwned;

#[derive(Debug, Clone)]
struct MyString {
    data: String,
}

impl ToOwned for MyString {
    type Owned = MyString;

    fn to_owned(&self) -> Self::Owned {
        MyString {
            data: self.data.clone(),
        }
    }
}

fn main() {
    let borrowed = MyString {
        data: "hello".to_string(),
    };
    let owned: MyString = borrowed.to_owned();
    println!("{:?}", owned);
}

使用 FromIterator 从迭代器创建集合

FromIterator 允许从迭代器创建集合类型:

use std::iter::FromIterator;

#[derive(Debug)]
struct MyVec {
    items: Vec<i32>,
}

impl FromIterator<i32> for MyVec {
    fn from_iter<T: IntoIterator<Item = i32>>(iter: T) -> Self {
        let items: Vec<i32> = iter.into_iter().collect();
        MyVec { items }
    }
}

fn main() {
    let my_vec: MyVec = (1..=5).collect();
    println!("{:?}", my_vec);
    
    // 或者显式调用
    let my_vec = MyVec::from_iter(1..=5);
    println!("{:?}", my_vec);
}

总结

Trait 用途 返回类型 示例
FromStr 从字符串解析 Result<Self, Self::Err> "123".parse::<i32>()
From<T> 从类型 T 转换 Self Number::from(42)
Into<T> 转换为类型 T T 42.into()
TryFrom<T> 尝试从类型 T 转换 Result<Self, Self::Error> PositiveNumber::try_from(42)
TryInto<T> 尝试转换为类型 T Result<T, <T as TryFrom>::Error> 42.try_into()
AsRef<T> 获取不可变引用 &T my_str.as_ref()
AsMut<T> 获取可变引用 &mut T my_vec.as_mut()
Borrow<T> 借用 &T my_str.borrow()
ToOwned 创建拥有类型 Self::Owned borrowed.to_owned()
FromIterator<T> 从迭代器创建集合 Self (1..5).collect()