【问题标题】:Flatten a Map<Vec<u8>, Vec<u8>> into a Vec<u8> and then return it to a Map<Vec<u8>, Vec<u8>>将 Map<Vec<u8>, Vec<u8>> 展平为 Vec<u8>,然后将其返回到 Map<Vec<u8>, Vec<u8>>
【发布时间】:2020-10-28 06:30:38
【问题描述】:

我在HashMap&lt;Vec&lt;u8&gt;, Vec&lt;u8&gt;&gt; 中有数据,我想将该数据作为字节缓冲区(单个Vec&lt;u8&gt;)写入文件,然后从文件中读回并重建HashMap 结构。

是否有一种既定的算法可以像这样展平和恢复地图?我可以将元数据写入文件以区分数据分区的位置等。由于这个项目的性质,我不能使用结构化序列化——我正在加密数据和文件。

【问题讨论】:

  • 简单写(V, V)有什么问题,其中V是一对(len, bytes)
  • 考虑过做类似的事情,但不太热衷于使用元组来解决这个问题。如果我说采用 hashmap 并将键和值都过滤到 Vec&lt;(u8, Vec&lt;u8&gt;)&gt; 中,其中第一个值是 len,第二个是字节列表,仍然很难知道哪个项目是键,哪个是价值。
  • 你可以把它的值存储在它的键之后,让我展示一下
  • 当然,会很感激的。
  • 可以说,无论格式如何,将哈希图展平为文件序列化。因此,您可能想澄清您可以使用和不能使用的内容。例如,使用 serde,您可以将数据序列化为 JSON,然后加密生成的字符串并将其写入文件。

标签: vector rust hashmap bytebuffer


【解决方案1】:

您可以使用以下格式存储它:

value1_len | value1_bytes | key1_len | key1_bytes | value2_len | value2_bytes | key2_len | key2_bytes | ...

使用标准库 (playground) 可以很容易地完成什么:

use std::collections::HashMap;
use std::convert::TryInto;

fn serialize(map: &HashMap<Vec<u8>, Vec<u8>>) -> Vec<u8> {
    map.iter().fold(Vec::new(), |mut acc, (k, v)| {
        acc.extend(&k.len().to_le_bytes());
        acc.extend(k.as_slice());
        acc.extend(&v.len().to_le_bytes());
        acc.extend(v.as_slice());
        acc
    })
}

fn read_vec(input: &mut &[u8]) -> Vec<u8> {
    let (len, rest) = input.split_at(std::mem::size_of::<usize>());
    let len = usize::from_le_bytes(len.try_into().unwrap());
    let (v, rest) = rest.split_at(len);
    *input = rest;
    v.to_vec()
}

fn deserialize(bytes: &Vec<u8>) -> HashMap<Vec<u8>, Vec<u8>> {
    let mut map = HashMap::new();

    let mut left = &bytes[..];
    while left.len() > 0 {
        let k = read_vec(&mut left);
        let v = read_vec(&mut left);
        map.insert(k, v);
    }

    map
}

fn main() {
    let mut map = HashMap::new();
    map.insert(vec![1, 2, 3], vec![4, 5, 6]);
    map.insert(vec![4, 5, 6], vec![1, 2, 3]);
    map.insert(vec![1, 5, 3], vec![4, 2, 6]);

    let array = serialize(&map);
    let recovered_map = deserialize(&array);

    assert_eq!(map, recovered_map);
}

【讨论】:

  • 我最终使用了 bincode,但我喜欢你的解决方案。我可能仍会使用它的变体并将其添加为可选 API。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-31
  • 1970-01-01
  • 2022-07-06
  • 2023-02-03
  • 1970-01-01
相关资源
最近更新 更多