[英]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.