用rust中的各种表示处理枚举的规范方法
在我的Rust程序中,我为每个大陆使用一个枚举。亚洲、欧洲等。然而,此枚举对应于数据库定义中的整数,它可以从外部源构造,并可以在需要时转换为另一个“类型” 比如说用rust中的各种表示处理枚举的规范方法,rust,Rust,在我的Rust程序中,我为每个大陆使用一个枚举。亚洲、欧洲等。然而,此枚举对应于数据库定义中的整数,它可以从外部源构造,并可以在需要时转换为另一个“类型” 比如说 enum ContinentKind { Asia, Europe, Africa, America, Oceania, } impl ContinentKind { fn new(external_input: &str) -> Result<ContinentK
enum ContinentKind {
Asia,
Europe,
Africa,
America,
Oceania,
}
impl ContinentKind {
fn new(external_input: &str) -> Result<ContinentKind, String> {
match external_input {
"ASIA" => Ok(ContinentKind::Asia),
"EUROPE" => Ok(ContinentKind::Europe),
"AFRICA" => Ok(ContinentKind::Africa),
"AMERICA" => Ok(ContinentKind::America),
"OCEANIA" => Ok(ContinentKind::Oceania),
_ => Err("Wrong external input".to_string()),
}
}
fn id(&self) -> u32 {
match *self {
ContinentKind::Asia => 1,
ContinentKind::Europe => 2,
ContinentKind::Africa => 3,
ContinentKind::America => 4,
ContinentKind::Oceania => 5,
}
}
fn api_string(&self) -> String {
match *self {
ContinentKind::Asia => String::from("I love Asia"),
ContinentKind::Europe => String::from("I travel to Europe"),
ContinentKind::Africa => String::from("Hello Africa"),
ContinentKind::America => String::from("North and South America"),
ContinentKind::Oceania => String::from("O C E A N I A"),
}
}
}
当我打电话时,乍一看代码是有效的,但我想知道是否有更好的方法来实现这一点,这需要更少的代码
let my_type = ContinentKind::America;
println!("{}", my_type.id());
println!("{}", my_type.api_string());
let another_type = ContinentKind::new("AFRICA");
match another_type {
Ok(v)=> println!("{}", v.id()),
_ => println!("an error happend"),
}
我的意思是最终创建这样的结构:
struct Continent {
id: u32,
kind: ContinentKind,
externaL_str : String,
internal_str: String,
}
lazy_static! {
static ref ASIA: Continent = Continent::new(1, ContinentKind::Asia, "ASIA", "I love Asia");
static ref EUROPE: Continent = Continent::new(2, ContinentKind::Europe, "EUROPE", "I travel to Europe");
// ...
}
它有两个构造,从\u id或从\u external\u str,类型嵌套
例如:
#[derive(Debug)]
struct Continent {
id: u32,
kind: ContinentKind,
external_str : String,
internal_str: String,
}
impl Continent {
fn from_external_string(external_input: &str) -> Result<Continent, String> {
match external_input {
"ASIA" => Ok(Continent{id: 1, kind:ContinentKind::Asia, external_str: String::from("ASIA"), internal_str:String::from("I love Asia")}),
"EUROPE" => Ok(Continent{id: 2, kind:ContinentKind::Europe, external_str: String::from("EUROPE"), internal_str:String::from("I travel to Europe")}),
"AFRICA" => Ok(Continent{id: 3, kind:ContinentKind::Africa, external_str: String::from("AFRICA"), internal_str:String::from("Hello Africa")}),
"AMERICA" => Ok(Continent{id: 4, kind:ContinentKind::America, external_str: String::from("AMERICA"), internal_str:String::from("North and South America")}),
"OCEANIA" => Ok(Continent{id: 5, kind:ContinentKind::Oceania, external_str: String::from("OCEANIA"), internal_str:String::from("O C E A N I A")}),
_ => Err("Wrong external input".to_string()),
}
}
fn from_database_id(id: u32) -> Result<Continent, String> {
match id {
1 => Ok(Continent{id: 1, kind:ContinentKind::Asia, external_str: String::from("ASIA"), internal_str:String::from("I love Asia")}),
2 => Ok(Continent{id: 2, kind:ContinentKind::Europe, external_str: String::from("EUROPE"), internal_str:String::from("I travel to Europe")}),
3 => Ok(Continent{id: 3, kind:ContinentKind::Africa, external_str: String::from("AFRICA"), internal_str:String::from("Hello Africa")}),
4 => Ok(Continent{id: 4, kind:ContinentKind::America, external_str: String::from("AMERICA"), internal_str:String::from("North and South America")}),
5 => Ok(Continent{id: 5, kind:ContinentKind::Oceania, external_str: String::from("OCEANIA"), internal_str:String::from("O C E A N I A")}),
_ => Err("Wrong external input".to_string()),
}
}
}
#[派生(调试)]
构造大陆{
id:u32,
善良的,善良的,
外部_str:String,
内部_str:String,
}
欧洲大陆{
fn来自外部字符串(外部输入:&str)->结果{
匹配外部输入{
“ASIA”=>Ok(大陆{id:1,种类:大陆种类::亚洲,外部_str:String::from(“亚洲”)、内部_str:String::from(“我爱亚洲”)),
“欧洲”=>Ok(大陆{id:2,种类:大陆种类::欧洲,外部字符串::来自(“欧洲”),内部字符串::来自(“我到欧洲旅行”),
“非洲”=>Ok(大陆{id:3,种类:大陆种类::非洲,外部字符:字符串::来自(“非洲”),内部字符:字符串::来自(“你好非洲”),
“美洲”=>Ok(大陆{id:4,种类:大陆种类::美洲,外部字符:字符串::来自(“美洲”),内部字符:字符串::来自(“北美和南美”),
“OCEANIA”=>Ok(大陆{id:5,种类:大陆种类::OCEANIA,外部字符串::from(“OCEANIA”),内部字符串::from(“O C E A N I A”),
_=>错误(“错误的外部输入”。到_字符串()),
}
}
fn来自_数据库_id(id:u32)->结果{
匹配id{
1=>Ok(大陆{id:1,种类:大陆种类::亚洲,外部_str:String::from(“亚洲”),内部_str:String::from(“我爱亚洲”)),
2=>Ok(大陆{id:2,种类:大陆种类::欧洲,外部字符串::来自(“欧洲”),内部字符串::来自(“我到欧洲旅行”),
3=>Ok(大陆{id:3,种类:大陆种类::非洲,外部字符:字符串::来自(“非洲”),内部字符:字符串::来自(“你好非洲”),
4=>Ok(大陆{id:4,种类:大陆种类::美洲,外部的字符串::来自(“美洲”),内部的字符串::来自(“北美和南美”),
5=>Ok(大陆{id:5,种类:大陆种类::大洋洲,外部字符串::from(“大洋洲”),内部字符串::from(“Oceania”),
_=>错误(“错误的外部输入”。到_字符串()),
}
}
}
对于数字覆盖,您可以内联指定以下内容:
#[repr(u32)]
enum Continent {
Asia = 1,
Europe = 2,
...
}
然后,您可以使用类似板条箱的工具,从/尝试为您从
实现中派生出。类似地,您可以使用类似板条箱的方法来派生字符串转换
与您描述的结构相比,这些结构的优点是不占用存储信息冗余副本的额外内存,而需要在运行时执行匹配(这会产生一些开销)而不是简单的结构字段查找。可以稍微清理一下的一种方法是使用lazy\u static
将值转换为静态全局值。它的核心是这样的:
struct Continent {
id: u32,
kind: ContinentKind,
externaL_str : String,
internal_str: String,
}
lazy_static! {
static ref ASIA: Continent = Continent::new(1, ContinentKind::Asia, "ASIA", "I love Asia");
static ref EUROPE: Continent = Continent::new(2, ContinentKind::Europe, "EUROPE", "I travel to Europe");
// ...
}
然后,您可以构建大陆::from_external_string
和大陆::from_database_id
,以返回对这些的引用(如果确实需要值而不是引用,则可以复制)
注意:一般来说,我不喜欢使用global来管理这类事情,但如果您真的想使用硬编码枚举,这至少可以将需要保持同步的位降到最低。考虑使用claret。
impl ContinentKind {
fn to_continent(&self) -> &'static Continent {
match self {
ContinentKind::Asia => &*ASIA,
ContinentKind::Europe => &*EUROPE,
// ...
}
}
fn id(&self) -> u32 {
self.to_continent().id
}
// ...
}