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