Skip to content

Commit cd02439

Browse files
committed
feat(wit): add map type support
Signed-off-by: Yordis Prieto <[email protected]>
1 parent 1cba20d commit cd02439

File tree

35 files changed

+1199
-39
lines changed

35 files changed

+1199
-39
lines changed

crates/wasm-compose/src/encoding.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ impl<'a> TypeEncoder<'a> {
650650
ComponentDefinedType::Record(r) => self.record(state, r),
651651
ComponentDefinedType::Variant(v) => self.variant(state, v),
652652
ComponentDefinedType::List(ty) => self.list(state, *ty),
653+
ComponentDefinedType::Map(key, value) => self.map(state, *key, *value),
653654
ComponentDefinedType::FixedSizeList(ty, elements) => {
654655
self.fixed_size_list(state, *ty, *elements)
655656
}
@@ -713,6 +714,19 @@ impl<'a> TypeEncoder<'a> {
713714
index
714715
}
715716

717+
fn map(
718+
&self,
719+
state: &mut TypeState<'a>,
720+
key: ct::ComponentValType,
721+
value: ct::ComponentValType,
722+
) -> u32 {
723+
let key = self.component_val_type(state, key);
724+
let value = self.component_val_type(state, value);
725+
let index = state.cur.encodable.type_count();
726+
state.cur.encodable.ty().defined_type().map(key, value);
727+
index
728+
}
729+
716730
fn fixed_size_list(
717731
&self,
718732
state: &mut TypeState<'a>,
@@ -1253,6 +1267,10 @@ impl DependencyRegistrar<'_, '_> {
12531267
ComponentDefinedType::List(t)
12541268
| ComponentDefinedType::FixedSizeList(t, _)
12551269
| ComponentDefinedType::Option(t) => self.val_type(*t),
1270+
ComponentDefinedType::Map(k, v) => {
1271+
self.val_type(*k);
1272+
self.val_type(*v);
1273+
}
12561274
ComponentDefinedType::Own(r) | ComponentDefinedType::Borrow(r) => {
12571275
self.ty(ComponentAnyTypeId::Resource(*r))
12581276
}

crates/wasm-encoder/src/component/types.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,13 @@ impl ComponentDefinedTypeEncoder<'_> {
593593
ty.into().encode(self.0);
594594
}
595595

596+
/// Define a map type.
597+
pub fn map(self, key: impl Into<ComponentValType>, value: impl Into<ComponentValType>) {
598+
self.0.push(0x63);
599+
key.into().encode(self.0);
600+
value.into().encode(self.0);
601+
}
602+
596603
/// Define a fixed size list type.
597604
pub fn fixed_size_list(self, ty: impl Into<ComponentValType>, elements: u32) {
598605
self.0.push(0x67);

crates/wasm-encoder/src/reencode/component.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,12 @@ pub mod component_utils {
768768
wasmparser::ComponentDefinedType::List(t) => {
769769
defined.list(reencoder.component_val_type(t));
770770
}
771+
wasmparser::ComponentDefinedType::Map(k, v) => {
772+
defined.map(
773+
reencoder.component_val_type(k),
774+
reencoder.component_val_type(v),
775+
);
776+
}
771777
wasmparser::ComponentDefinedType::FixedSizeList(t, elements) => {
772778
defined.fixed_size_list(reencoder.component_val_type(t), elements);
773779
}

crates/wasmparser/src/readers/component/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ pub enum ComponentDefinedType<'a> {
440440
Variant(Box<[VariantCase<'a>]>),
441441
/// The type is a list of the given value type.
442442
List(ComponentValType),
443+
/// The type is a map of the given key and value types.
444+
Map(ComponentValType, ComponentValType),
443445
/// The type is a fixed size list of the given value type.
444446
FixedSizeList(ComponentValType, u32),
445447
/// The type is a tuple of the given value types.
@@ -481,6 +483,7 @@ impl<'a> ComponentDefinedType<'a> {
481483
.collect::<Result<_>>()?,
482484
),
483485
0x70 => ComponentDefinedType::List(reader.read()?),
486+
0x63 => ComponentDefinedType::Map(reader.read()?, reader.read()?),
484487
0x6f => ComponentDefinedType::Tuple(
485488
reader
486489
.read_iter(MAX_WASM_TUPLE_TYPES, "tuple types")?

crates/wasmparser/src/validator/component.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,9 @@ impl ComponentState {
951951
ComponentDefinedType::List(ty)
952952
| ComponentDefinedType::FixedSizeList(ty, _)
953953
| ComponentDefinedType::Option(ty) => types.type_named_valtype(ty, set),
954+
ComponentDefinedType::Map(k, v) => {
955+
types.type_named_valtype(k, set) && types.type_named_valtype(v, set)
956+
}
954957

955958
// The resource referred to by own/borrow must be named.
956959
ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
@@ -3928,6 +3931,10 @@ impl ComponentState {
39283931
crate::ComponentDefinedType::List(ty) => Ok(ComponentDefinedType::List(
39293932
self.create_component_val_type(ty, offset)?,
39303933
)),
3934+
crate::ComponentDefinedType::Map(key, value) => Ok(ComponentDefinedType::Map(
3935+
self.create_component_val_type(key, offset)?,
3936+
self.create_component_val_type(value, offset)?,
3937+
)),
39313938
crate::ComponentDefinedType::FixedSizeList(ty, elements) => {
39323939
if !self.features.cm_fixed_size_list() {
39333940
bail!(

crates/wasmparser/src/validator/component_types.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,8 @@ pub enum ComponentDefinedType {
14511451
Variant(VariantType),
14521452
/// The type is a list.
14531453
List(ComponentValType),
1454+
/// The type is a map.
1455+
Map(ComponentValType, ComponentValType),
14541456
/// The type is a fixed size list.
14551457
FixedSizeList(ComponentValType, u32),
14561458
/// The type is a tuple.
@@ -1494,6 +1496,11 @@ impl TypeData for ComponentDefinedType {
14941496
Self::Variant(v) => v.info,
14951497
Self::Tuple(t) => t.info,
14961498
Self::List(ty) | Self::FixedSizeList(ty, _) | Self::Option(ty) => ty.info(types),
1499+
Self::Map(k, v) => {
1500+
let mut info = k.info(types);
1501+
info.combine(v.info(types), 0).unwrap();
1502+
info
1503+
}
14971504
Self::Result { ok, err } => {
14981505
let default = TypeInfo::new();
14991506
let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
@@ -1514,7 +1521,7 @@ impl ComponentDefinedType {
15141521
.cases
15151522
.values()
15161523
.any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1517-
Self::List(_) => true,
1524+
Self::List(_) | Self::Map(_, _) => true,
15181525
Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
15191526
Self::Flags(_)
15201527
| Self::Enum(_)
@@ -1542,7 +1549,7 @@ impl ComponentDefinedType {
15421549
types,
15431550
lowered_types,
15441551
),
1545-
Self::List(_) => {
1552+
Self::List(_) | Self::Map(_, _) => {
15461553
lowered_types.try_push(ValType::I32) && lowered_types.try_push(ValType::I32)
15471554
}
15481555
Self::FixedSizeList(ty, length) => {
@@ -1622,6 +1629,7 @@ impl ComponentDefinedType {
16221629
ComponentDefinedType::Flags(_) => "flags",
16231630
ComponentDefinedType::Option(_) => "option",
16241631
ComponentDefinedType::List(_) => "list",
1632+
ComponentDefinedType::Map(_, _) => "map",
16251633
ComponentDefinedType::FixedSizeList(_, _) => "fixed size list",
16261634
ComponentDefinedType::Result { .. } => "result",
16271635
ComponentDefinedType::Own(_) => "own",
@@ -1646,7 +1654,9 @@ impl ComponentDefinedType {
16461654

16471655
ComponentDefinedType::Variant(ty) => ty.lower_gc(types, abi, options, offset, core),
16481656

1649-
ComponentDefinedType::List(ty) | ComponentDefinedType::FixedSizeList(ty, _) => {
1657+
ComponentDefinedType::List(ty)
1658+
| ComponentDefinedType::Map(ty, _)
1659+
| ComponentDefinedType::FixedSizeList(ty, _) => {
16501660
let id = match core.as_concrete_ref() {
16511661
Some(id) => id,
16521662
None => bail!(
@@ -2498,6 +2508,10 @@ impl TypeAlloc {
24982508
| ComponentDefinedType::Option(ty) => {
24992509
self.free_variables_valtype(ty, set);
25002510
}
2511+
ComponentDefinedType::Map(k, v) => {
2512+
self.free_variables_valtype(k, set);
2513+
self.free_variables_valtype(v, set);
2514+
}
25012515
ComponentDefinedType::Result { ok, err } => {
25022516
if let Some(ok) = ok {
25032517
self.free_variables_valtype(ok, set);
@@ -2640,6 +2654,9 @@ impl TypeAlloc {
26402654
ComponentDefinedType::List(ty)
26412655
| ComponentDefinedType::FixedSizeList(ty, _)
26422656
| ComponentDefinedType::Option(ty) => self.type_named_valtype(ty, set),
2657+
ComponentDefinedType::Map(k, v) => {
2658+
self.type_named_valtype(k, set) && self.type_named_valtype(v, set)
2659+
}
26432660

26442661
// own/borrow themselves don't have to be named, but the resource
26452662
// they refer to must be named.
@@ -2832,6 +2849,10 @@ where
28322849
| ComponentDefinedType::Option(ty) => {
28332850
any_changed |= self.remap_valtype(ty, map);
28342851
}
2852+
ComponentDefinedType::Map(k, v) => {
2853+
any_changed |= self.remap_valtype(k, map);
2854+
any_changed |= self.remap_valtype(v, map);
2855+
}
28352856
ComponentDefinedType::Result { ok, err } => {
28362857
if let Some(ok) = ok {
28372858
any_changed |= self.remap_valtype(ok, map);
@@ -3724,6 +3745,13 @@ impl<'a> SubtypeCx<'a> {
37243745
(Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
37253746
(List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
37263747
(List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
3748+
(Map(ak, av), Map(bk, bv)) => {
3749+
self.component_val_type(ak, bk, offset)
3750+
.with_context(|| "type mismatch in map key")?;
3751+
self.component_val_type(av, bv, offset)
3752+
.with_context(|| "type mismatch in map value")
3753+
}
3754+
(Map(_, _), b) => bail!(offset, "expected {}, found map", b.desc()),
37273755
(FixedSizeList(a, asize), FixedSizeList(b, bsize)) => {
37283756
if asize != bsize {
37293757
bail!(offset, "expected fixed size {bsize}, found size {asize}")

crates/wasmprinter/src/component.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ impl Printer<'_, '_> {
169169
Ok(())
170170
}
171171

172+
pub(crate) fn print_map_type(
173+
&mut self,
174+
state: &State,
175+
key_ty: &ComponentValType,
176+
value_ty: &ComponentValType,
177+
) -> Result<()> {
178+
self.start_group("map ")?;
179+
self.print_component_val_type(state, key_ty)?;
180+
self.result.write_str(" ")?;
181+
self.print_component_val_type(state, value_ty)?;
182+
self.end_group()?;
183+
Ok(())
184+
}
185+
172186
pub(crate) fn print_fixed_size_list_type(
173187
&mut self,
174188
state: &State,
@@ -278,6 +292,7 @@ impl Printer<'_, '_> {
278292
ComponentDefinedType::Record(fields) => self.print_record_type(state, fields)?,
279293
ComponentDefinedType::Variant(cases) => self.print_variant_type(state, cases)?,
280294
ComponentDefinedType::List(ty) => self.print_list_type(state, ty)?,
295+
ComponentDefinedType::Map(key, value) => self.print_map_type(state, key, value)?,
281296
ComponentDefinedType::FixedSizeList(ty, elements) => {
282297
self.print_fixed_size_list_type(state, ty, *elements)?
283298
}

crates/wit-component/src/encoding.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ impl TypeContents {
324324
}
325325
TypeDefKind::Enum(_) => Self::empty(),
326326
TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::LIST,
327+
TypeDefKind::Map(k, v) => {
328+
Self::for_type(resolve, k) | Self::for_type(resolve, v) | Self::LIST
329+
}
327330
TypeDefKind::FixedSizeList(t, _elements) => Self::for_type(resolve, t),
328331
TypeDefKind::Type(t) => Self::for_type(resolve, t),
329332
TypeDefKind::Future(_) => Self::empty(),

crates/wit-component/src/encoding/types.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ pub trait ValtypeEncoder<'a> {
185185
encoder.list(ty);
186186
ComponentValType::Type(index)
187187
}
188+
TypeDefKind::Map(key_ty, value_ty) => {
189+
let key = self.encode_valtype(resolve, key_ty)?;
190+
let value = self.encode_valtype(resolve, value_ty)?;
191+
let (index, encoder) = self.defined_type();
192+
encoder.map(key, value);
193+
ComponentValType::Type(index)
194+
}
188195
TypeDefKind::FixedSizeList(ty, elements) => {
189196
let ty = self.encode_valtype(resolve, ty)?;
190197
let (index, encoder) = self.defined_type();

crates/wit-component/src/printing.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,14 @@ impl<O: Output> WitPrinter<O> {
606606
self.print_type_name(resolve, ty)?;
607607
self.output.generic_args_end();
608608
}
609+
TypeDefKind::Map(key_ty, value_ty) => {
610+
self.output.ty("map", TypeKind::BuiltIn);
611+
self.output.generic_args_start();
612+
self.print_type_name(resolve, key_ty)?;
613+
self.output.str(", ");
614+
self.print_type_name(resolve, value_ty)?;
615+
self.output.generic_args_end();
616+
}
609617
TypeDefKind::FixedSizeList(ty, size) => {
610618
self.output.ty("list", TypeKind::BuiltIn);
611619
self.output.generic_args_start();
@@ -787,6 +795,9 @@ impl<O: Output> WitPrinter<O> {
787795
TypeDefKind::List(inner) => {
788796
self.declare_list(resolve, ty.name.as_deref(), inner)?
789797
}
798+
TypeDefKind::Map(key, value) => {
799+
self.declare_map(resolve, ty.name.as_deref(), key, value)?
800+
}
790801
TypeDefKind::FixedSizeList(inner, size) => {
791802
self.declare_fixed_size_list(resolve, ty.name.as_deref(), inner, *size)?
792803
}
@@ -1003,6 +1014,31 @@ impl<O: Output> WitPrinter<O> {
10031014
Ok(())
10041015
}
10051016

1017+
fn declare_map(
1018+
&mut self,
1019+
resolve: &Resolve,
1020+
name: Option<&str>,
1021+
key_ty: &Type,
1022+
value_ty: &Type,
1023+
) -> Result<()> {
1024+
if let Some(name) = name {
1025+
self.output.keyword("type");
1026+
self.output.str(" ");
1027+
self.print_name_type(name, TypeKind::Map);
1028+
self.output.str(" = ");
1029+
self.output.ty("map", TypeKind::BuiltIn);
1030+
self.output.str("<");
1031+
self.print_type_name(resolve, key_ty)?;
1032+
self.output.str(", ");
1033+
self.print_type_name(resolve, value_ty)?;
1034+
self.output.str(">");
1035+
self.output.semicolon();
1036+
return Ok(());
1037+
}
1038+
1039+
Ok(())
1040+
}
1041+
10061042
fn declare_fixed_size_list(
10071043
&mut self,
10081044
resolve: &Resolve,
@@ -1343,6 +1379,8 @@ pub enum TypeKind {
13431379
InterfacePath,
13441380
/// A list type name.
13451381
List,
1382+
/// A map type name.
1383+
Map,
13461384
/// A namespace declaration.
13471385
NamespaceDeclaration,
13481386
/// A namespace when printing a path, for example in `use`.

0 commit comments

Comments
 (0)