[英]How to implement a global and mutable HashMap with str as key and Trait as values?
我正在尝试实现值键对,其键是字符串,值是实现一些预定义函数的对象类型。 我遇到的问题是 Trait(在这种情况下我将其用作一种继承)没有预定义的大小并且不是安全的线程。
/// _State line to define the basis of the 'State'
/// type with signatures of specific functions
pub trait _State {
fn as_string(&self, text: String) -> String;
fn print(&self);
}
/// Status type to add your custom colors
pub struct RGBState {
name: String,
color: (u8, u8, u8),
character: String,
}
/// Default state type using preconfigured ANSI colors
pub struct State {
name: String,
color: Color,
character: String,
}
lazy_static! {
static ref StateOK: Mutex<State> = {
let mut state = State{
name: String::from("OK"),
color: Color::Green,
character: "+".to_string()
};
Mutex::new(state)
};
static ref STATES: Mutex<HashMap<&'static str, &'static Lazy<Mutex<dyn _State + 'static>>>> = {
let mut _states = HashMap::from(
[
(
"OK",
Lazy::new(StateOK)
)
]
);
Mutex::new(_states)
};
}
所有源代码都在 github 上提供(不可编译 yet): https ://github.com/mauricelambert/TerminalMessages
我使用外部库lazy_static 。
我想我应该使用 Mutex、Lazy 或其他允许我创建可变和全局值的类型。
我不知道如何定义我将在值中定义的对象的大小,这些对象可以是不同类型,其共同基础是函数签名。
我的代码的总体目的是在 Rust 中实现一个 DLL,该 DLL 具有其他语言的接口,允许在控制台中显示格式化和彩色消息。 消息格式的每个元素都必须由开发人员“配置”(颜色、表示消息类型的字符、进度条等......)。 它必须能够通过调用必须指定消息类型和消息内容的函数来使用这些消息类型中的任何一种。
我在 Python 中实现了类似的代码,其源代码在 github 上: https ://github.com/mauricelambert/PythonToolsKit/blob/main/PythonToolsKit/PrintF.py。 这是一个屏幕截图,代表我想在这个 DLL 中实现的内容:! TerminalMessages 演示
我对所有关于 Rust 和代码优化最佳实践的建议感兴趣。
我认为您的代码中存在一些误解,imo:
HashMap
中,您需要将它们包装在Box
中,因为正如您已经意识到的那样,特征对象不是Sized
。Mutex
中,因为整个HashMap
已经在Mutex
中。考虑到这一点,这是一个有效的实现:
use std::{collections::HashMap, sync::Mutex};
use lazy_static::lazy_static;
/// Preconfigured ANSI colors constants
#[derive(Clone)]
pub enum Color {
Black, // 0
Red, // 1
Green, // 2
Yellow, // 3
Blue, // 4
Purple, // 5
Cyan, // 6
White, // 7
}
impl Color {
fn value(&self) -> i32 {
match *self {
Color::Black => 0,
Color::Red => 1,
Color::Green => 2,
Color::Yellow => 3,
Color::Blue => 4,
Color::Purple => 5,
Color::Cyan => 6,
Color::White => 7,
}
}
}
/// _State line to define the basis of the 'State'
/// type with signatures of specific functions
pub trait _State {
fn as_string(&self, text: String) -> String;
fn print(&self);
}
/// Default state type using preconfigured ANSI colors
#[derive(Clone)]
pub struct State {
name: String,
color: Color,
character: String,
}
impl _State for State {
fn as_string(&self, text: String) -> String {
format!(
"\x1b[3{color}m[{character}] {text}\x1b[0m",
color = self.color.value(),
character = self.character,
text = text,
)
}
fn print(&self) {
println!("{}", self.as_string(self.name.clone()));
}
}
lazy_static! {
static ref STATE_OK: State = {
State {
name: String::from("OK"),
color: Color::Green,
character: "+".to_string(),
}
};
static ref STATES: Mutex<HashMap<&'static str, Box<dyn _State + Send>>> = {
let _states: HashMap<&'static str, Box<dyn _State + Send>> = HashMap::from([
("OK", Box::new(STATE_OK.clone()) as Box<dyn _State + Send>),
(
"NOK",
Box::new(State {
name: String::from("NOK"),
color: Color::Yellow,
character: "-".to_string(),
}) as Box<dyn _State + Send>,
),
]);
Mutex::new(_states)
};
}
fn main() {
println!("{}", STATES.lock().unwrap().len());
for (key, value) in &*STATES.lock().unwrap() {
println!("{}:", key);
value.print();
println!("");
}
}
这些更多是我的意见,要么接受,要么离开。
trait _State
依赖于Send
,因为它们都必须是Send
才能存储在HashMap
中。 这使得HashMap
定义更清晰state_entry
辅助函数以简化初始化use std::{collections::HashMap, sync::Mutex};
use lazy_static::lazy_static;
/// Preconfigured ANSI colors constants
#[derive(Clone)]
pub enum Color {
Black, // 0
Red, // 1
Green, // 2
Yellow, // 3
Blue, // 4
Purple, // 5
Cyan, // 6
White, // 7
}
impl Color {
fn value(&self) -> i32 {
match *self {
Color::Black => 0,
Color::Red => 1,
Color::Green => 2,
Color::Yellow => 3,
Color::Blue => 4,
Color::Purple => 5,
Color::Cyan => 6,
Color::White => 7,
}
}
}
/// _State line to define the basis of the 'State'
/// type with signatures of specific functions
pub trait _State: Send {
fn as_string(&self, text: String) -> String;
fn print(&self);
}
/// Default state type using preconfigured ANSI colors
#[derive(Clone)]
pub struct State {
name: String,
color: Color,
character: String,
}
impl _State for State {
fn as_string(&self, text: String) -> String {
format!(
"\x1b[3{color}m[{character}] {text}\x1b[0m",
color = self.color.value(),
character = self.character,
text = text,
)
}
fn print(&self) {
println!("{}", self.as_string(self.name.clone()));
}
}
fn state_entry(
name: &'static str,
entry: impl _State + 'static,
) -> (&'static str, Box<dyn _State>) {
(name, Box::new(entry))
}
lazy_static! {
static ref STATE_OK: State = {
State {
name: String::from("OK"),
color: Color::Green,
character: "+".to_string(),
}
};
static ref STATES: Mutex<HashMap<&'static str, Box<dyn _State>>> = {
Mutex::new(HashMap::from([
state_entry("OK", STATE_OK.clone()),
state_entry(
"NOK",
State {
name: String::from("NOK"),
color: Color::Yellow,
character: "-".to_string(),
},
),
state_entry(
"ERROR",
State {
name: String::from("ERROR"),
color: Color::Red,
character: "!".to_string(),
},
),
]))
};
}
fn main() {
println!("{} entries\n", STATES.lock().unwrap().len());
for (key, value) in &*STATES.lock().unwrap() {
println!("{}:", key);
value.print();
println!("");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.