在使用mysql包时,如何将MySQL枚举转换为Rust枚举?

问题描述 投票:1回答:1

我想从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>`

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

mysql rust
1个回答
0
投票

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

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())
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.