我正在为我的一个项目创建一个Bit enum,我经历了与as u32(或任何其他类型)语法的一些奇怪的交互.我有Into u8,u16,.. u128为我的Bit enum实现,所以我在测试中无意地使用了Bit as u32,有点假设它是.into()的语法糖.我运行了一些失败的测试,试图找到我发现的错误,我的Bit enum是这样布局的:

pub enum Bit {
    On,
    Off,
}

我一时兴起将其改为:

pub enum Bit {
    Off,
    On,
}

没多想.我重新运行了测试,看看哪个测试再次失败,令我惊讶的是,另外2个测试通过了!

我做了一些额外的挖掘,来回切换OnOff,并将as u32更改为.into()呼叫.as u32似乎完全忽略了任何Into实现,只是转换比特.这有点道理,但例如u32 as f64如何工作?您不能简单地在那里转换位.它到底是做什么的?

看看suggested question,我的Enum似乎正在使用TryFrom实现(这也是实现的).但这对我来说没有意义,为什么rust会使用TryFrom实现,而这可能会对具体实现的Into感到panic ?但即使这样的解释也没有意义,因为TryFrom实现专门将0映射到Bit::Off、1映射到Bit::On以及所有其他值映射到错误.

通常我会查看相关文档,但我不知道在哪里可以找到相关文档,因为它更多的是一种语言功能,而不是某个东西的实现,指向该功能的指针也有帮助!

链接至操场:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c06998e915b2b4aa44d58ec67d21eabb

作为参考,这是我使用as u32的地方:

fn bits_flipped(left: &BitString, right: &BitString) -> u32 {
    assert_eq!(
        left.len(),
        right.len(),
        "the length of the bitstrings is not equal. Left is {} and right is {}",
        left.len(),
        right.len()
    );

    let mut difference: u32 = 0;
    for i in 0..left.len() {
        difference += (left[i] ^ right[i]) as u32; // This line was causing issues
    }

    difference
}

这是我用于Into实现的宏:

macro_rules! bit_into_type {
    ($t:ty) => {
        impl Into<$t> for Bit {
            #![allow(clippy::from_over_into)]
            fn into(self) -> $t {
                match self {
                    Self::On => 1,
                    Self::Off => 0,
                }
            }
        }
    };
}

最后,这是我用于TryFrom实现的宏:

macro_rules! bit_try_from {
    ($t:ty) => {
        impl TryFrom<$t> for Bit {
            type Error = String;

            fn try_from(value: $t) -> Result<Self, Self::Error> {
                match value {
                    0 => Ok(Bit::Off),
                    1 => Ok(Bit::On),
                    value => Err(format!("Cannot represent {} as a single bit", value)),
                }
            }
        }
    };
}

推荐答案

Enum::Variant as NumberType检索变体的discriminant.

If no discriminant is explicitly assigned, the first variant is assigned zero and the next variants are assigned increasing discriminants.

as f32/f64采用整判定式并将其转换为浮点数.

Rust相关问答推荐

如何处理动态 struct 实例化?

如何为utoipa中的可选查询参数生成OpenAPI模式?

使用pyo3::Types::PyIterator的无限内存使用量

这是不是在不造成嵌套的情况下从枚举中取出想要的变体的惯用方法?

创建Rust中元对象协议的动态对象 Select /重新分配机制

`Pin`有没有不涉及不安全代码的目的?

在Rust中,Box:ed struct 与普通 struct 在删除顺序上有区别吗?

如何处理闭包中的生命周期以及作为参数和返回类型的闭包?

std mpsc 发送者通道在闭包中使用时关闭

Rust 如何将链表推到前面?

当没有实际结果时,如何在 Rust 中强制执行错误处理?

方法可以被误认为是标准特性方法

在给定 Rust 谓词的情况下,将 Some 转换为 None 的惯用方法是什么?

如何从 x86_64 Mac 构建 M1 Mac?

打印 `format_args!` 时borrow 时临时值丢失

为什么 File::read_to_end 缓冲区容量越大越慢?

`use std::error::Error` 声明中断编译

有没有办法阻止 rust-analyzer 使非活动代码变暗?

隐式类型闭包的错误生命周期推断

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