假设我正在编写一个函数,该函数修剪&str左右的空格,然后将其解析为泛型类型(这是一个简化的示例:我的实际函数是从正则表达式中获取几个捕获组).

fn trim_and_parse<T: FromStr>(s: &str) -> T {
  s.trim().parse().unwrap()
}

例如,我可以这样做

let n: u32 = trim_and_parse("  24  ");
let inner: String = trim_and_parse("  hi ");

这很有效,但第二个是分配新的String.如果我可以返回输入的一部分,我会很高兴的:

let inner: &str = trim_and_parse("  hi ");

这是行不通的,因为&str不是FromStr,我不确定它是否真的有意义.有没有什么我可以做的来使这个接口工作,这样如果我使用u32作为类型参数,那么它就会将经过修剪的字符串解析成一个数字,但是我可以使用其他的类型参数来获得原始字符串的一部分?

我试着做一些实验,比如

trait MyFromStr {
    fn from_str(s: &str) -> Self;
}

impl MyFromStr for &str {
    fn from_str(s: &str) -> Self {
        s
    }
}

得到lifetime may not live long enough分,这是很公平的.有没有其他方法可以让这件事奏效?

推荐答案

要做到这一点,可以将该特性声明为终生特性:

trait MyFromStr<'a>: Sized {
    type Err;
    fn from_str(s: &'a str) -> Result<Self, Self::Err>;
}

impl<'a> MyFromStr<'a> for &'a str {
    type Err = std::convert::Infallible;
    fn from_str(s: &'a str) -> Result<Self, Self::Err> {
        Ok(s)
    }
}

impl<'a> MyFromStr<'a> for i32 {
    type Err = std::num::ParseIntError;
    fn from_str(s: &'a str) -> Result<Self, Self::Err> {
        s.parse()
    }
}

fn trim_and_parse<'a, T: MyFromStr<'a>>(s: &'a str) -> T
where
    T::Err: std::fmt::Debug,
{
    MyFromStr::from_str(s.trim()).unwrap()
}

Rust相关问答推荐

获取字符串切片(&;str)上的切片([ia..ib])返回字符串

在Rust中有没有办法在没有UB的情况下在指针和U64之间进行转换?

如何go 除铁 rust 中路径组件的第一项和最后一项?

有没有办法指定只在Rust的测试中有效的断言?

如何用Axum/Tower压缩Html内容?

如何使用RefCell::JOYMOMTborrow 对 struct 不同字段的可变引用

为什么这个变量不需要是可变的?

如何从ruust中的fig.toml中读取?

`*mut[T]`与`*mut T`的区别

循环访问枚举中的不同集合

为什么比较Option<;字符串>;具有常数Option<&;str>;需要显式类型转换吗?

为什么 `Deref` 没有在 `Cell` 上实现?

为什么我必须使用 PhantomData?在这种情况下它在做什么?

在Rust中实现Trie数据 struct 的更好方式

有什么方法可以通过使用生命周期来减轻嵌套生成器中的当生成器产生时borrow 可能仍在使用错误?

在 Rust 中,Weak 如何知道内部值何时被删除?

返回引用字符串的future

我如何将 google_gmail1::Gmail> 传递给线程生成?

Rust 中的通用 From 实现

当值是新类型包装器时,对键的奇怪 HashMap 生命周期要求