Skip to content

Commit 1097cda

Browse files
committed
Deduplicate map lift logic between HashMap implementations
1 parent 504c7eb commit 1097cda

1 file changed

Lines changed: 30 additions & 39 deletions

File tree

  • crates/wasmtime/src/runtime/component/func

crates/wasmtime/src/runtime/component/func/typed.rs

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,15 +2241,18 @@ where
22412241
}
22422242
}
22432243

2244-
fn lift_map<K, V>(
2244+
/// Shared helper that validates a map's memory region and lifts each
2245+
/// (key, value) pair, forwarding them to `insert`.
2246+
fn lift_map_pairs<K, V>(
22452247
cx: &mut LiftContext<'_>,
22462248
key_ty: InterfaceType,
22472249
value_ty: InterfaceType,
22482250
ptr: usize,
22492251
len: usize,
2250-
) -> Result<HashMap<K, V>>
2252+
mut insert: impl FnMut(K, V) -> Result<()>,
2253+
) -> Result<()>
22512254
where
2252-
K: Lift + Eq + Hash,
2255+
K: Lift,
22532256
V: Lift,
22542257
{
22552258
let tuple_abi = CanonicalAbiInfo::record_static(&[K::ABI, V::ABI]);
@@ -2267,7 +2270,6 @@ where
22672270
bail!("map pointer is not aligned");
22682271
}
22692272

2270-
let mut result = HashMap::with_capacity(len)?;
22712273
for i in 0..len {
22722274
let entry_base = ptr + (i * tuple_size);
22732275

@@ -2280,18 +2282,33 @@ where
22802282
let value_bytes = &cx.memory()[entry_base + value_field..][..V::SIZE32];
22812283
let value = V::linear_lift_from_memory(cx, value_ty, value_bytes)?;
22822284

2283-
result.insert(key, value)?;
2285+
insert(key, value)?;
22842286
}
22852287

2288+
Ok(())
2289+
}
2290+
2291+
fn lift_map<K, V>(
2292+
cx: &mut LiftContext<'_>,
2293+
key_ty: InterfaceType,
2294+
value_ty: InterfaceType,
2295+
ptr: usize,
2296+
len: usize,
2297+
) -> Result<HashMap<K, V>>
2298+
where
2299+
K: Lift + Eq + Hash,
2300+
V: Lift,
2301+
{
2302+
let mut result = HashMap::with_capacity(len)?;
2303+
lift_map_pairs(cx, key_ty, value_ty, ptr, len, |k, v| {
2304+
result.insert(k, v)?;
2305+
Ok(())
2306+
})?;
22862307
Ok(result)
22872308
}
22882309

22892310
// =============================================================================
22902311
// std::collections::HashMap<K, V> support for component model `map<K, V>`
2291-
//
2292-
// This mirrors the wasmtime_environ::collections::HashMap implementation above
2293-
// but works with the standard library HashMap type, which is what users will
2294-
// naturally reach for.
22952312

22962313
#[cfg(feature = "std")]
22972314
unsafe impl<K, V> ComponentType for std::collections::HashMap<K, V>
@@ -2422,37 +2439,11 @@ where
24222439
K: Lift + Eq + Hash,
24232440
V: Lift,
24242441
{
2425-
let tuple_abi = CanonicalAbiInfo::record_static(&[K::ABI, V::ABI]);
2426-
let tuple_size = tuple_abi.size32 as usize;
2427-
let tuple_align = tuple_abi.align32 as usize;
2428-
2429-
match len
2430-
.checked_mul(tuple_size)
2431-
.and_then(|total| ptr.checked_add(total))
2432-
{
2433-
Some(n) if n <= cx.memory().len() => {}
2434-
_ => bail!("map pointer/length out of bounds of memory"),
2435-
}
2436-
if ptr % tuple_align != 0 {
2437-
bail!("map pointer is not aligned");
2438-
}
2439-
24402442
let mut result = std::collections::HashMap::with_capacity(len);
2441-
for i in 0..len {
2442-
let entry_base = ptr + (i * tuple_size);
2443-
2444-
let mut field_offset = 0usize;
2445-
let key_field = K::ABI.next_field32_size(&mut field_offset);
2446-
let key_bytes = &cx.memory()[entry_base + key_field..][..K::SIZE32];
2447-
let key = K::linear_lift_from_memory(cx, key_ty, key_bytes)?;
2448-
2449-
let value_field = V::ABI.next_field32_size(&mut field_offset);
2450-
let value_bytes = &cx.memory()[entry_base + value_field..][..V::SIZE32];
2451-
let value = V::linear_lift_from_memory(cx, value_ty, value_bytes)?;
2452-
2453-
result.insert(key, value);
2454-
}
2455-
2443+
lift_map_pairs(cx, key_ty, value_ty, ptr, len, |k, v| {
2444+
result.insert(k, v);
2445+
Ok(())
2446+
})?;
24562447
Ok(result)
24572448
}
24582449

0 commit comments

Comments
 (0)