mysql - 使用 mysql crate 时如何将 MySQL 枚举转换为 Rust 枚举?

标签 mysql rust

我想从 MySQL 表中读取枚举,但无法将表中的字符串枚举转换为真正的 Rust 枚举。

我有哪些选择? documentation告诉我应该实现 FromValue 特性:

Cargo.toml

[dependencies]
mysql = "15.1.0"
strum = "0.14.0"
strum_macros = "0.14.0"
use mysql::{
    prelude::{ConvIr, FromValue},
    Value,
};
use std::str::{from_utf8, FromStr};
use strum_macros::{AsStaticStr, EnumString};

#[derive(Debug, PartialEq, Eq, EnumString, AsStaticStr)]
pub enum UserRole {
    ADMIN,
    USER,
}

#[derive(Debug)]
pub struct EnumIr {
    bytes: Vec<u8>,
}

impl ConvIr<UserRole> for EnumIr {
    fn new(v: Value) -> mysql::error::Result<EnumIr> {
        match v {
            Value::Bytes(bytes) => match from_utf8(&*bytes) {
                Ok(_) => Ok(EnumIr { bytes: bytes }),
                Err(_) => Err(mysql::FromValueError(Value::Bytes(bytes))),
            },
            v => Err(mysql::FromValueError(v)),
        }
    }
    fn commit(self) -> UserRole {
        unsafe { UserRole::from_str(from_utf8(&self.bytes).unwrap()).unwrap() }
    }
    fn rollback(self) -> Value {
        Value::Bytes(self.bytes)
    }
}

impl FromValue for UserRole {
    type Intermediate = EnumIr;
}

fn main() {
    println!("Hello, world!");
}

此操作失败并显示以下错误消息:

error[E0053]: method `new` has an incompatible type for trait
  --> src/main.rs:20:5
   |
20 |     fn new(v: Value) -> mysql::error::Result<EnumIr> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `mysql_common::value::convert::FromValueError`, found enum `mysql::error::Error`
   |
   = note: expected type `fn(mysql_common::value::Value) -> std::result::Result<EnumIr, mysql_common::value::convert::FromValueError>`
              found type `fn(mysql_common::value::Value) -> std::result::Result<EnumIr, mysql::error::Error>`

有没有人设法完成转换或者是否有更好的方法?

最佳答案

如错误消息所述(稍微清理了一下):

expected type `fn(Value) -> Result<EnumIr, FromValueError>`
   found type `fn(Value) -> Result<EnumIr, mysql::Error>`

你不能返回错误的类型;这只是静态类型语言的基本条件。返回正确的类型:Result<EnumIr, mysql::FromValueError> .

我还更改了您的代码,以避免将数据进行虚假的第二次解析:

#[derive(Debug)]
pub struct EnumIr {
    string: String,
}

impl ConvIr<UserRole> for EnumIr {
    fn new(v: Value) -> Result<EnumIr, mysql::FromValueError> {
        match v {
            Value::Bytes(bytes) => match String::from_utf8(bytes) {
                Ok(string) => Ok(EnumIr { string }),
                Err(e) => Err(mysql::FromValueError(Value::Bytes(e.into_bytes()))),
            },
            v => Err(mysql::FromValueError(v)),
        }
    }

    fn commit(self) -> UserRole {
        self.string.parse().unwrap()
    }

    fn rollback(self) -> Value {
        Value::Bytes(self.string.into_bytes())
    }
}

您似乎也应该尝试解析 new 中的枚举。方法,因为这是唯一允许 Result 的方法:

#[derive(Debug)]
pub struct EnumIr {
    role: UserRole,
    string: String,
}

impl ConvIr<UserRole> for EnumIr {
    fn new(v: Value) -> Result<EnumIr, mysql::FromValueError> {
        match v {
            Value::Bytes(bytes) => match String::from_utf8(bytes) {
                Ok(string) => match string.parse() {
                    Ok(role) => Ok(EnumIr { role, string }),
                    Err(_) => Err(mysql::FromValueError(Value::Bytes(string.into_bytes()))),
                },
                Err(e) => Err(mysql::FromValueError(Value::Bytes(e.into_bytes()))),
            },
            v => Err(mysql::FromValueError(v)),
        }
    }

    fn commit(self) -> UserRole {
        self.role
    }

    fn rollback(self) -> Value {
        Value::Bytes(self.string.into_bytes())
    }
}

关于mysql - 使用 mysql crate 时如何将 MySQL 枚举转换为 Rust 枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55102158/

相关文章:

python - 如何将日期时间插入Mysql?

mysql - spring mvc不会连接到不同计算机上的mysql数据库

mysql - 如何向现有数据添加逗号

rust - 是否可以通过 channel 使用 Any 特征?

methods - 如果我不指定数字的类型,为什么 count_ones 不起作用?

rust - 如何解决可变借用和不可变借用的共存问题?

mysql - 如何将数据从一个表插入另一个表的特定列?

rust - 写!引用时宏不会在单独的方法中编译

regex - 在Rust中使用正则表达式查询MongoDB

MYSQL 将 float 转换为日期时间