如何实现一个方法来使用&amp; str,Box <str>,Rc <str>等?

时间:2018-05-22 09:25:37

标签: rust

我有以某种方式转换字符串引用的代码,例如采取第一个字母

trait Tr {
    fn trim_indent(self) -> Self;
}

impl<'a> Tr for &'a str {
    fn trim_indent(self) -> Self {
        &self[..1] // some transformation here
    }
}

fn main() {
    let s = "aaa".trim_indent();
    println!("{}", s);
}

现在我尝试将此代码概括为实现AsRef<str>的任何特定类型。我的最后一次尝试是

use std::ops::Deref;

trait Tr<'a> {
    fn trim_indent(self) -> Deref<Target = str> + 'a + Sized;
}

impl<'a, T: AsRef<str>> Tr<'a> for T {
    fn trim_indent(self) -> Deref<Target = str> + 'a + Sized {
        self.as_ref()[..1] // some transformation here
    }
}

fn main() {
    let s = "aaa".trim_indent();
    println!("{}", s);
}

我被卡住了因为没有Sized我在编译时遇到类型未知的错误,但是Size我得到一个错误,我无法明确使用标记特征。

1 个答案:

答案 0 :(得分:2)

无论您从哪种类型开始,&str切片的最终类型始终为&str,因此您的返回类型必须为&str

然后,实现特征引用类型的问题,以便您可以将输入和输出生命周期联系在一起:

use std::rc::Rc;

trait Tr<'a> {
    fn trim_indent(self) -> &'a str;
}

impl<'a, T> Tr<'a> for &'a T
where
    T: AsRef<str> + 'a,
{
    fn trim_indent(self) -> &'a str {
        &self.as_ref()[..1] // Take the first **byte**
    }
}

fn main() {
    let s: &str = "aaa";
    println!("{}", s.trim_indent());

    let s: Box<str> = Box::from("bbb");
    println!("{}", s.trim_indent());

    let s: Rc<str> = Rc::from("ccc");
    println!("{}", s.trim_indent());
}

在这种情况下,由于您列出的所有类型都会实现Deref,因此您只需实现&str的特征,所有类型都可以使用它:

trait Tr {
    fn trim_indent(&self) -> &str;
}

impl Tr for str {
    fn trim_indent(&self) -> &str {
        &self[..1]
    }
}

另见: