rust 为str、String、borrown和owned实现From和Into

wmomyfyw  于 2023-02-04  发布在  其他
关注(0)|答案(2)|浏览(161)

我正在尝试减少代码中的样板文件,我已经尝试使用Cow、Borrow或AsRef将这些实现组合在一起,但是编译器抱怨Address没有实现trait sized。
要实现所有的case &str vs String和Address vs &Address,我当前的代码感觉有些多余

pub struct Address(String);

impl From<String> for Address {
    fn from(bytes: String) -> Self {
        Self(String::from_utf8(Vec::from(bytes)).unwrap())
    }
}

impl From<String> for &Address {
    fn from(bytes: String) -> Self {
        &Address(String::from_utf8(Vec::from(bytes)).unwrap())
    }
}

impl From<&str> for Address {
    fn from(str: &str) -> Self {
        Self(str.to_string())
    }
}

impl From<&str> for &Address {
    fn from(str: &str) -> Self {
        &Address(str.to_string())
    }
}

impl<'b> Into<&'b str> for Address {
    fn into(self) -> &'b str {
        self.0.as_str()
    }
}

impl<'b> Into<&'b str> for &Address {
    fn into(self) -> &'b str {
        self.0.as_str()
    }
}

impl<'b> Into<String> for Address {
    fn into(self) -> String {
        self.0.to_string()
    }
}

impl<'b> Into<String> for &Address {
    fn into(self) -> String {
        self.0.to_string()
    }
}
xzv2uavs

xzv2uavs1#

您可能只需要以下四个impls:

pub struct Address(String);

impl From<String> for Address {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl<'a> From<&'a str> for Address {
    fn from(s: &'a str) -> Self {
        Address(s.to_string())
    }
}

impl From<Address> for String {
    fn from(a: Address) -> Self {
        a.0
    }
}

impl<'a> From<&'a Address> for &'a str {
    fn from(a: &'a Address) -> Self {
        &a.0
    }
}
kuarbcqp

kuarbcqp2#

  • String::from_utf8(Vec::from(bytes)).unwrap()没有意义。bytes在您的例子中已经是UTF8字符串,所以这整行是多余的。您的意思是bytes是Vec<u8>吗?
  • impl From<X> for &Address没有意义。引用不拥有对象,必须有人拥有Address对象。impl From<X> for Address是您真正想要的并且已经拥有的对象。
  • impl Into<&str>是没有意义的,Into取得所有权。你不能消费一个对象,然后返回对它的引用。同样,必须有人拥有它。你可能需要AsRef<str>Deref<Target=str>
  • impl Into<String> for &Address也不常见。AsRef<str>Deref<Target=str>对于几乎所有情况都足够了,如果您需要消耗转换,请使用impl From<Address> for String从不实现Into,始终实现From。(From隐含Into

所以我会这么做:

use std::ops::Deref;

pub struct Address(String);

impl From<String> for Address {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for Address {
    fn from(s: &str) -> Self {
        Self(s.to_string())
    }
}

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

impl Deref for Address {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

// Unusual, but of course possible:
impl From<Address> for String {
    fn from(addr: Address) -> String {
        addr.0
    }
}

下面是如何执行转换,这与通常的Rust行为一致:

fn main() {
    // String to Address
    let s: String = "AAA".to_string();
    let _addr: Address = s.into();
    //or
    let s: String = "AAA".to_string();
    let _addr = Address::from(s);

    // &str to Address
    let s: &str = "AAA";
    let _addr: Address = s.into();
    // or
    let _addr = Address::from(s);

    // Address to &str
    let addr: Address = Address("AAA".to_string());
    let _s: &str = &addr;

    // Address to String
    let addr: Address = Address("AAA".to_string());
    let _s: String = addr.to_string();
    // Or also:
    let _s: String = addr.into();
}

相关问题