Skip to main content

atmos/os_lib/
web_storage.rs

1// src/os_lib/web_storage.rs
2// Web Storage (localStorage / sessionStorage) シリアライゼーション純粋モジュール
3
4extern crate alloc;
5use alloc::collections::BTreeMap;
6use alloc::string::String;
7use alloc::vec::Vec;
8
9/// BTreeMap を長さプレフィックス付きバイナリ形式にシリアライズする。
10pub fn ls_serialize(map: &BTreeMap<String, String>) -> Vec<u8> {
11    let mut out = Vec::new();
12    for (k, v) in map.iter() {
13        let kb = k.as_bytes();
14        let vb = v.as_bytes();
15        out.extend_from_slice(&(kb.len() as u32).to_le_bytes());
16        out.extend_from_slice(kb);
17        out.extend_from_slice(&(vb.len() as u32).to_le_bytes());
18        out.extend_from_slice(vb);
19    }
20    out
21}
22
23/// バイナリ形式から BTreeMap を復元する。
24/// 破損データ(境界外オフセット、切断されたデータ)に対しても安全に復元可能な部分までを抽出し、
25/// パニックを起こさない堅牢な設計とする。
26pub fn ls_deserialize(data: &[u8]) -> BTreeMap<String, String> {
27    let mut map = BTreeMap::new();
28    let mut pos = 0usize;
29    while pos + 8 <= data.len() {
30        let klen = u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize;
31        pos += 4;
32        if pos + klen > data.len() {
33            break;
34        }
35        let k = alloc::string::String::from_utf8_lossy(&data[pos..pos + klen]).into_owned();
36        pos += klen;
37        if pos + 4 > data.len() {
38            break;
39        }
40        let vlen = u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize;
41        pos += 4;
42        if pos + vlen > data.len() {
43            break;
44        }
45        let v = alloc::string::String::from_utf8_lossy(&data[pos..pos + vlen]).into_owned();
46        pos += vlen;
47        map.insert(k, v);
48    }
49    map
50}