1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Port of `bun.StringMap` (`src/bun.zig`).
//!
//! A `StringArrayHashMap<Box<[u8]>>` plus a `dupe_keys` flag controlling
//! whether `insert` clones the key bytes. Values are always cloned.
use bun_alloc::AllocError;
use crate::array_hash_map::StringArrayHashMap;
pub struct StringMap {
pub map: StringArrayHashMap<Box<[u8]>>,
pub dupe_keys: bool,
}
impl StringMap {
/// Zig `init(allocator, dupe_keys)` — allocator dropped (global mimalloc).
pub fn init(dupe_keys: bool) -> Self {
Self {
map: StringArrayHashMap::default(),
dupe_keys,
}
}
pub fn clone(&self) -> Result<Self, AllocError> {
Ok(Self {
map: self.map.clone()?,
dupe_keys: self.dupe_keys,
})
}
#[inline]
#[cfg(bao_nightly)]
pub fn keys(&self) -> &[Box<[u8]>] {
self.map.keys()
}
/// Dual-mode: stable returns the api2 mirror's slice (see
/// array_hash_map::keys).
#[inline]
#[cfg(not(bao_nightly))]
pub fn keys(&self) -> &[bun_alloc::core_alloc::AllocBox<[u8], bun_alloc::core_alloc::Global>] {
self.map.keys()
}
#[inline]
pub fn values(&self) -> &[Box<[u8]>] {
self.map.values()
}
#[inline]
pub fn count(&self) -> usize {
self.map.count()
}
/// Zig `insert` / `put`: dupe `value`; dupe `key` only when `dupe_keys`
/// and the key is new. (When `dupe_keys == false` Zig stored a borrowed
/// slice; here `Box<[u8]>` forces a copy regardless — the flag is kept for
/// API parity and to skip the redundant second copy.)
pub fn insert(&mut self, key: &[u8], value: &[u8]) -> Result<(), AllocError> {
let entry = self.map.get_or_put(key)?;
// get_or_put already boxed `key` on miss; the Zig `dupe_keys` branch
// would dupe again here — that's the same allocation, so skip it.
let _ = self.dupe_keys;
*entry.value_ptr = Box::from(value);
Ok(())
}
/// Alias matching Zig `pub const put = insert;`.
#[inline]
pub fn put(&mut self, key: &[u8], value: &[u8]) -> Result<(), AllocError> {
self.insert(key, value)
}
pub fn get(&self, key: &[u8]) -> Option<&[u8]> {
self.map.get(key).map(|v| &**v)
}
// Zig `sort` takes an `anytype` ctx; defer until a caller needs it.
// TODO(port): StringMap::sort — wire once ArrayHashMap::sort lands.
// `deinit` → Drop on the inner Vecs.
}
// ported from: src/bun.zig