我想从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())
}
}