问题
我想编写一个函数,它允许我将类型A(在本例中为u8
)转换为类型B(一个自定义类型),然后再从类型B转换回类型A。根据entry about the traits From
and Into
of Rust by Example的第一段:From
和Into
特性是内在联系的,这实际上是它实现的一部分。如果你能够将类型A从类型B转换过来,那么你应该很容易相信我们应该能够将类型B转换成类型A。
然而,实现From
(即impl From<A> for B
)允许我从A转换到B,并且 * 只能 * A转换到B,除了两种不同的方式(仍然不确定为什么需要两种方式,但无论如何)。我可以使用相同的实现从B转换到A吗?或者没有办法使用已经存在的信息吗?
我所尝试的
我尝试在NormalMneumonic
类型上实现From
(在本例中为TryFrom
),如下所示
impl TryFrom<&str> for NormalMneumonic {
type Error = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"JP" => Ok(Self::Jump),
// --snip--
_ => Err("Input is not a normal menumonic."),
}
}
}
有了它我就能
let mneumonic_1 /*: Result<NormalMneumonic, _>*/ = NormalMneumonic::try_from("JP");
let mneumonic_2: Result<NormalMneumonic, _> = "JP".try_into();
assert_eq!(mneumonic_1, mneumonic_2);
但是我还没有找到一种方法来将NormalMneumonic
转换回&str
。
let mneumonic_string = NormalMneumonic::Jump.try_into(); // or perhaps &str::try_from(NormalMneumonic::Jump)
一些背景
我正在尝试用Rust为一个简化的汇编语言编写一个汇编器和一个链接器,我定义了一个数据类型来帮助实现这一点,它只是一个枚举,每个有效的枚举都有一个变量。
在编写汇编程序时,我需要读取一些文本文件并写入一些二进制文件,在链接时,我需要读回一些二进制文件并写入另一个二进制文件,考虑到这一点,我一直在寻找一种方法,在字符串切片(&str
)或字节(u8
)与NormalMneumonic
变体之间来回转换。
从我提到的引文中,我认为在类型之间来回转换是From
特性的用例,但似乎这本书在这种情况下只是使用了误导性的语言。
2条答案
按热度按时间ojsjcaue1#
不,
From<A> for B
实现不会创建From<B> for A
实现。From
trait只由一个方法fn from(a: A) -> B
组成。仅用这个签名,您就能创建所有A
和B
的反向实现吗?当然不能!而且编译器不会查看现有实现的主体来尝试推导其他实现。首先,许多转换是有损耗的,许多转换是容易出错的,并且可能在转换一个方向时遇到障碍,而在转换相反的方向时却不存在。因此,即使编译器查看了现有的实现,它也是不实际的,甚至一般来说是不可能的。从我提到的引文中,我认为在类型之间来回转换是
From
特性的用例,但似乎这本书在这种情况下只是使用了误导性的语言。事实上,你误解了这句话,它实际上是在不同的语境下把同样的话重复了两遍:* “convert type A from type B”* 与 “convert type B to type A” 是相同的操作,都是
B -> A
,只是短语的主语改变了。这反映了From
和Into
之间的唯一区别。语法A::from(b)
和b.into()
(带有推断的A
)不能用单个trait完成。如果您希望在处理枚举时更轻松一些,如前所述,strum crate提供了许多派生宏,用于:
IntoStaticStr
和/或ToString
EnumString
u8
转换:FromRepr
#[repr(u8)]
,则可以仅使用as u8
转换为u8
)有关其他选项,请参阅这些现有答案:
mnemlml82#
也许strum_macros能帮上忙。
它可以生成将枚举值转换为&str的代码