如何遍历HashMap<Vec<u8>,Vec<u8>> 修复E0277 Sized trait未实现错误
问题描述
尝试遍历键、值均为Vec<u8>类型的HashMap实现哈希表序列化功能,初始实现代码如下:
pub fn serialize_hashmap(data: &HashMap<Vec<u8>, Vec<u8>>) -> Result<Vec<u8>, String> { let mut serialized_data = Vec::new(); for (hash, password_data) in &data { serialized_data.extend_from_slice(&hash); let password_data_length: u64 = password_data.len().try_into().unwrap(); serialized_data.write_u64::<NativeEndian>(password_data_length).unwrap(); // TODO add error handling serialized_data.extend_from_slice(&password_data); } return Ok(serialized_data); }
编译时抛出如下错误:
error[E0277]: the size for values of type `[_]` cannot be known at compilation time --> src/main.rs:8:10 | 8 | for (hash, password_data) in &data { | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[_]` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[_]` cannot be known at compilation time --> src/main.rs:8:34 | 8 | for (hash, password_data) in &data { | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[_]` = note: only the last element of a tuple may have a dynamically sized type
最初推测问题源于HashMap为动态分配、大小在运行时才确定,需要确认Rust是否支持遍历这类动态分配的HashMap,以及该场景的常规实现方式。
原因说明
该报错和HashMap动态分配的特性无关。Rust原生支持遍历持有Vec<u8>类型键值的HashMap,这是非常常规的操作,不存在语法层面的限制。
报错的核心原因是代码缺少必要的类型、trait导入,编译器无法正确识别&data的迭代器返回值类型,才误判出动态大小类型[_]未实现Sized特征的错误。
修复方案
- 补全所有依赖导入:
- 标准库
HashMap类型:use std::collections::HashMap; - 长度转换需要的
TryIntotrait:use std::convert::TryInto; - 字节写入方法对应的trait:如果使用
byteorder库提供的write_u64方法,需要导入use byteorder::{WriteBytesExt, NativeEndian};,同时引入标准库std::io::Writetrait。
- 标准库
- 补全序列化逻辑的边界信息:原逻辑没有写入key的长度,反序列化时无法切割连续字节的key/value边界,常规实现需要为每个键值对先写入key长度、再写入key内容,再写入value长度、value内容,可额外在序列化结果头部写入键值对总数,方便反序列化时判断终止。
- 替换所有
unwrap()为错误传递,符合函数返回Result的设计。
修复后的可运行代码如下:
use std::collections::HashMap; use std::convert::TryInto; use std::io::Write; use byteorder::{NativeEndian, WriteBytesExt}; pub fn serialize_hashmap(data: &HashMap<Vec<u8>, Vec<u8>>) -> Result<Vec<u8>, String> { let mut serialized_data = Vec::new(); // 写入总键值对数,辅助反序列化 let entry_count: u64 = data.len().try_into().map_err(|e| e.to_string())?; serialized_data.write_u64::<NativeEndian>(entry_count).map_err(|e| e.to_string())?; for (hash, password_data) in data { // 写入key长度,标记key边界 let key_len: u64 = hash.len().try_into().map_err(|e| e.to_string())?; serialized_data.write_u64::<NativeEndian>(key_len).map_err(|e| e.to_string())?; serialized_data.extend_from_slice(hash); let password_data_length: u64 = password_data.len().try_into().map_err(|e| e.to_string())?; serialized_data.write_u64::<NativeEndian>(password_data_length).map_err(|e| e.to_string())?; serialized_data.extend_from_slice(password_data); } Ok(serialized_data) }
补全导入后,迭代器返回的元素类型为(&Vec<u8>, &Vec<u8>),两个值都是编译期大小确定的胖指针,不会再触发Sized相关的编译错误。
内容的提问来源于stack exchange,提问作者Dyskord
相关产品推荐
相关产品推荐

