@@ -1088,7 +1088,7 @@ fn is_prim_type_id(resolve: &Resolve, id: TypeId) -> bool {
10881088 | TypeDefKind :: Stream ( _)
10891089 | TypeDefKind :: Unknown => false ,
10901090 TypeDefKind :: FixedLengthList ( ..) => todo ! ( ) ,
1091- TypeDefKind :: Map ( .. ) => todo ! ( ) ,
1091+ TypeDefKind :: Map ( key , value ) => is_prim_type ( resolve , key ) && is_prim_type ( resolve , value ) ,
10921092 }
10931093}
10941094
@@ -1174,7 +1174,12 @@ pub fn push_ty_name(resolve: &Resolve, ty: &Type, src: &mut String) {
11741174 }
11751175 TypeDefKind :: Unknown => unreachable ! ( ) ,
11761176 TypeDefKind :: FixedLengthList ( ..) => todo ! ( ) ,
1177- TypeDefKind :: Map ( ..) => todo ! ( ) ,
1177+ TypeDefKind :: Map ( key, value) => {
1178+ src. push_str ( "map_" ) ;
1179+ push_ty_name ( resolve, key, src) ;
1180+ src. push_str ( "_" ) ;
1181+ push_ty_name ( resolve, value, src) ;
1182+ }
11781183 }
11791184 }
11801185 }
@@ -1383,12 +1388,12 @@ impl Return {
13831388 TypeDefKind :: Tuple ( _)
13841389 | TypeDefKind :: Record ( _)
13851390 | TypeDefKind :: List ( _)
1391+ | TypeDefKind :: Map ( _, _)
13861392 | TypeDefKind :: Variant ( _) => { }
13871393
13881394 TypeDefKind :: Resource => todo ! ( "return_single for resource" ) ,
13891395 TypeDefKind :: Unknown => unreachable ! ( ) ,
13901396 TypeDefKind :: FixedLengthList ( ..) => todo ! ( ) ,
1391- TypeDefKind :: Map ( ..) => todo ! ( ) ,
13921397 }
13931398
13941399 self . retptrs . push ( * orig_ty) ;
@@ -1735,6 +1740,23 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
17351740 self . finish_typedef_struct ( id) ;
17361741 }
17371742
1743+ fn type_map ( & mut self , id : TypeId , _name : & str , key : & Type , value : & Type , docs : & Docs ) {
1744+ self . src . h_defs ( "\n " ) ;
1745+ self . docs ( docs, SourceType :: HDefs ) ;
1746+ let map_ty = self . r#gen . type_name ( & Type :: Id ( id) ) ;
1747+ let entry_ty = format ! ( "{map_ty}_entry_t" ) ;
1748+ uwriteln ! ( self . src. h_defs, "typedef struct {entry_ty} {{" ) ;
1749+ self . print_ty ( SourceType :: HDefs , key) ;
1750+ self . src . h_defs ( " key;\n " ) ;
1751+ self . print_ty ( SourceType :: HDefs , value) ;
1752+ self . src . h_defs ( " value;\n " ) ;
1753+ uwriteln ! ( self . src. h_defs, "}} {entry_ty};" ) ;
1754+ self . start_typedef_struct ( id) ;
1755+ uwriteln ! ( self . src. h_defs, "{entry_ty} *ptr;" ) ;
1756+ self . src . h_defs ( "size_t len;\n " ) ;
1757+ self . finish_typedef_struct ( id) ;
1758+ }
1759+
17381760 fn type_fixed_length_list (
17391761 & mut self ,
17401762 _id : TypeId ,
@@ -1844,6 +1866,24 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a>
18441866 self . print_typedef_target ( id) ;
18451867 }
18461868
1869+ fn anonymous_type_map ( & mut self , id : TypeId , key : & Type , value : & Type , _docs : & Docs ) {
1870+ let map_ty = self . r#gen . type_name ( & Type :: Id ( id) ) ;
1871+ let entry_ty = format ! ( "{map_ty}_entry_t" ) ;
1872+ uwriteln ! ( self . src. h_defs, "\n typedef struct {entry_ty} {{" ) ;
1873+ self . print_ty ( SourceType :: HDefs , key) ;
1874+ self . src . h_defs ( " key;\n " ) ;
1875+ self . print_ty ( SourceType :: HDefs , value) ;
1876+ self . src . h_defs ( " value;\n " ) ;
1877+ uwriteln ! ( self . src. h_defs, "}} {entry_ty};" ) ;
1878+ self . src . h_defs ( "\n typedef " ) ;
1879+ self . src . h_defs ( "struct {\n " ) ;
1880+ uwriteln ! ( self . src. h_defs, "{entry_ty} *ptr;" ) ;
1881+ self . src . h_defs ( "size_t len;\n " ) ;
1882+ self . src . h_defs ( "}" ) ;
1883+ self . src . h_defs ( " " ) ;
1884+ self . print_typedef_target ( id) ;
1885+ }
1886+
18471887 fn anonymous_type_future ( & mut self , id : TypeId , _ty : & Option < Type > , _docs : & Docs ) {
18481888 self . src . h_defs ( "\n typedef uint32_t " ) ;
18491889 self . print_typedef_target ( id) ;
@@ -2005,6 +2045,21 @@ impl InterfaceGenerator<'_> {
20052045 uwriteln ! ( self . src. c_helpers, "}}" ) ;
20062046 }
20072047
2048+ TypeDefKind :: Map ( key, value) => {
2049+ self . src . c_helpers ( "size_t map_len = ptr->len;\n " ) ;
2050+ uwriteln ! ( self . src. c_helpers, "if (map_len > 0) {{" ) ;
2051+ let map_ty = self . r#gen . type_name ( & Type :: Id ( id) ) ;
2052+ let entry_ty = format ! ( "{map_ty}_entry_t" ) ;
2053+ uwriteln ! ( self . src. c_helpers, "{entry_ty} *map_ptr = ptr->ptr;" ) ;
2054+ self . src
2055+ . c_helpers ( "for (size_t i = 0; i < map_len; i++) {\n " ) ;
2056+ self . free ( key, "&map_ptr[i].key" ) ;
2057+ self . free ( value, "&map_ptr[i].value" ) ;
2058+ self . src . c_helpers ( "}\n " ) ;
2059+ uwriteln ! ( self . src. c_helpers, "free(map_ptr);" ) ;
2060+ uwriteln ! ( self . src. c_helpers, "}}" ) ;
2061+ }
2062+
20082063 TypeDefKind :: Variant ( v) => {
20092064 self . src . c_helpers ( "switch ((int32_t) ptr->tag) {\n " ) ;
20102065 for ( i, case) in v. cases . iter ( ) . enumerate ( ) {
@@ -2045,7 +2100,6 @@ impl InterfaceGenerator<'_> {
20452100 }
20462101 TypeDefKind :: Unknown => unreachable ! ( ) ,
20472102 TypeDefKind :: FixedLengthList ( ..) => todo ! ( ) ,
2048- TypeDefKind :: Map ( ..) => todo ! ( ) ,
20492103 }
20502104 if c_helpers_body_start == self . src . c_helpers . len ( ) {
20512105 self . src . c_helpers . as_mut_string ( ) . truncate ( c_helpers_start) ;
@@ -2739,7 +2793,9 @@ void {name}_return({return_ty}) {{
27392793
27402794 TypeDefKind :: Unknown => false ,
27412795 TypeDefKind :: FixedLengthList ( ..) => todo ! ( ) ,
2742- TypeDefKind :: Map ( ..) => todo ! ( ) ,
2796+ TypeDefKind :: Map ( key, value) => {
2797+ self . contains_droppable_borrow ( key) || self . contains_droppable_borrow ( value)
2798+ }
27432799 }
27442800 } else {
27452801 false
@@ -3609,6 +3665,11 @@ impl Bindgen for FunctionBindgen<'_, '_> {
36093665 results. push ( format ! ( "(uint8_t *) ({}).ptr" , operands[ 0 ] ) ) ;
36103666 results. push ( format ! ( "({}).len" , operands[ 0 ] ) ) ;
36113667 }
3668+ Instruction :: MapLower { .. } => {
3669+ let _body = self . blocks . pop ( ) . unwrap ( ) ;
3670+ results. push ( format ! ( "(uint8_t *) ({}).ptr" , operands[ 0 ] ) ) ;
3671+ results. push ( format ! ( "({}).len" , operands[ 0 ] ) ) ;
3672+ }
36123673
36133674 Instruction :: ListLift { element, ty, .. } => {
36143675 self . assert_no_droppable_borrows ( "list" , & Type :: Id ( * ty) ) ;
@@ -3621,7 +3682,19 @@ impl Bindgen for FunctionBindgen<'_, '_> {
36213682 list_name, elem_name, operands[ 0 ] , operands[ 1 ]
36223683 ) ) ;
36233684 }
3685+ Instruction :: MapLift { ty, .. } => {
3686+ let _body = self . blocks . pop ( ) . unwrap ( ) ;
3687+ self . assert_no_droppable_borrows ( "map" , & Type :: Id ( * ty) ) ;
3688+ let map_name = self . r#gen . r#gen . type_name ( & Type :: Id ( * ty) ) ;
3689+ let entry_name = format ! ( "{map_name}_entry_t" ) ;
3690+ results. push ( format ! (
3691+ "({}) {{ ({}*)({}), ({}) }}" ,
3692+ map_name, entry_name, operands[ 0 ] , operands[ 1 ]
3693+ ) ) ;
3694+ }
36243695 Instruction :: IterElem { .. } => results. push ( "e" . to_string ( ) ) ,
3696+ Instruction :: IterMapKey { .. } => results. push ( "map_key" . to_string ( ) ) ,
3697+ Instruction :: IterMapValue { .. } => results. push ( "map_value" . to_string ( ) ) ,
36253698 Instruction :: IterBasePointer => results. push ( "base" . to_string ( ) ) ,
36263699
36273700 Instruction :: CallWasm { sig, .. } => {
@@ -3956,6 +4029,28 @@ impl Bindgen for FunctionBindgen<'_, '_> {
39564029 uwriteln ! ( self . src, "free({ptr});" ) ;
39574030 uwriteln ! ( self . src, "}}" ) ;
39584031 }
4032+ Instruction :: GuestDeallocateMap { key, value } => {
4033+ let ( body, results) = self . blocks . pop ( ) . unwrap ( ) ;
4034+ assert ! ( results. is_empty( ) ) ;
4035+ let len = self . locals . tmp ( "len" ) ;
4036+ uwriteln ! ( self . src, "size_t {len} = {};" , operands[ 1 ] ) ;
4037+ uwriteln ! ( self . src, "if ({len} > 0) {{" ) ;
4038+ let ptr = self . locals . tmp ( "ptr" ) ;
4039+ uwriteln ! ( self . src, "uint8_t *{ptr} = {};" , operands[ 0 ] ) ;
4040+ let i = self . locals . tmp ( "i" ) ;
4041+ uwriteln ! ( self . src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{" ) ;
4042+ let size = self . r#gen . r#gen . sizes . record ( [ * key, * value] ) . size ;
4043+ uwriteln ! (
4044+ self . src,
4045+ "uint8_t *base = {ptr} + {i} * {};" ,
4046+ size. format( POINTER_SIZE_EXPRESSION )
4047+ ) ;
4048+ uwriteln ! ( self . src, "(void) base;" ) ;
4049+ uwrite ! ( self . src, "{body}" ) ;
4050+ uwriteln ! ( self . src, "}}" ) ;
4051+ uwriteln ! ( self . src, "free({ptr});" ) ;
4052+ uwriteln ! ( self . src, "}}" ) ;
4053+ }
39594054
39604055 Instruction :: Flush { amt } => {
39614056 results. extend ( operands. iter ( ) . take ( * amt) . cloned ( ) ) ;
@@ -4109,7 +4204,7 @@ pub fn is_arg_by_pointer(resolve: &Resolve, ty: &Type) -> bool {
41094204 TypeDefKind :: Resource => todo ! ( "is_arg_by_pointer for resource" ) ,
41104205 TypeDefKind :: Unknown => unreachable ! ( ) ,
41114206 TypeDefKind :: FixedLengthList ( ..) => todo ! ( ) ,
4112- TypeDefKind :: Map ( ..) => todo ! ( ) ,
4207+ TypeDefKind :: Map ( ..) => true ,
41134208 } ,
41144209 Type :: String => true ,
41154210 _ => false ,
0 commit comments