You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为winit的KeyCode枚举变体存储布尔值?替代HashMap方案

用数组替代HashMap存储winit按键状态的方案

核心思路

winit的KeyCode枚举提供了静态数组VARIANTS,包含所有按键变体。我们可以基于这个数组的长度创建固定大小的布尔数组,再通过VARIANTS的索引实现按键与数组位置的映射,完全替代HashMap的动态哈希表结构。

基础实现(无额外依赖)

use winit::keyboard::KeyCode;

// 编译期确定按键总数,直接使用winit提供的VARIANTS长度
const KEY_TOTAL: usize = KeyCode::VARIANTS.len();

struct InputState {
    key_states: [bool; KEY_TOTAL],
}

impl InputState {
    // 初始化所有按键状态为false
    pub fn new() -> Self {
        Self {
            key_states: [false; KEY_TOTAL],
        }
    }

    // 获取指定按键的按下状态
    pub fn is_pressed(&self, key: KeyCode) -> bool {
        // 从VARIANTS中查找按键对应的索引
        match KeyCode::VARIANTS.iter().position(|&k| k == key) {
            Some(idx) => self.key_states[idx],
            None => false, // 理论上不会触发,所有KeyCode都在VARIANTS中
        }
    }

    // 更新指定按键的状态
    pub fn set_pressed(&mut self, key: KeyCode, pressed: bool) {
        if let Some(idx) = KeyCode::VARIANTS.iter().position(|&k| k == key) {
            self.key_states[idx] = pressed;
        }
    }
}

性能优化(预建索引映射)

如果担心每次position查找的开销,可以预构建一次KeyCode到索引的映射,后续直接通过映射快速访问:

use winit::keyboard::KeyCode;
use std::collections::HashMap;
use once_cell::sync::Lazy;

const KEY_TOTAL: usize = KeyCode::VARIANTS.len();

// 静态懒加载的索引映射,程序启动时仅初始化一次
static KEY_INDEX_MAP: Lazy<HashMap<KeyCode, usize>> = Lazy::new(|| {
    KeyCode::VARIANTS
        .iter()
        .enumerate()
        .map(|(idx, &key)| (key, idx))
        .collect()
});

struct InputState {
    key_states: [bool; KEY_TOTAL],
}

impl InputState {
    pub fn new() -> Self {
        Self { key_states: [false; KEY_TOTAL] }
    }

    pub fn is_pressed(&self, key: KeyCode) -> bool {
        self.key_states[KEY_INDEX_MAP[&key]]
    }

    pub fn set_pressed(&mut self, key: KeyCode, pressed: bool) {
        self.key_states[KEY_INDEX_MAP[&key]] = pressed;
    }
}

注:此方案需要依赖once_cell crate来实现静态懒加载。

为什么不用enum_map?

enum_map要求枚举实现其Enum trait,但KeyCode定义在winit crate内部,受限于Rust的孤儿规则,我们无法为外部枚举手动实现该trait,因此这种方案不可行。

内容的提问来源于stack exchange,提问作者Mateusz Kolpa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 05:48:23