@@ -75,7 +75,6 @@ struct Includes {
7575 needs_wit : bool ,
7676 needs_memory : bool ,
7777 needs_array : bool ,
78- needs_map : bool ,
7978}
8079
8180#[ derive( Default ) ]
@@ -436,9 +435,6 @@ impl Cpp {
436435 if self . dependencies . needs_bit {
437436 self . include ( "<bit>" ) ;
438437 }
439- if self . dependencies . needs_map {
440- self . include ( "<map>" ) ;
441- }
442438 }
443439
444440 fn start_new_file ( & mut self , condition : Option < bool > ) -> FileContext {
@@ -1746,10 +1742,31 @@ impl CppInterfaceGenerator<'_> {
17461742 )
17471743 }
17481744 TypeDefKind :: Map ( key, value) => {
1749- self . r#gen . dependencies . needs_map = true ;
1750- let k = self . type_name ( key, from_namespace, flavor) ;
1751- let v = self . type_name ( value, from_namespace, flavor) ;
1752- format ! ( "std::map<{k}, {v}>" )
1745+ let element_flavor = match flavor {
1746+ Flavor :: BorrowedArgument | Flavor :: Argument ( AbiVariant :: GuestImport ) => {
1747+ Flavor :: BorrowedArgument
1748+ }
1749+ _ => Flavor :: InStruct ,
1750+ } ;
1751+ let k = self . type_name ( key, from_namespace, element_flavor) ;
1752+ let v = self . type_name ( value, from_namespace, element_flavor) ;
1753+ match flavor {
1754+ Flavor :: BorrowedArgument => {
1755+ self . r#gen . dependencies . needs_span = true ;
1756+ format ! ( "std::span<std::pair<{k}, {v}> const>" )
1757+ }
1758+ Flavor :: Argument ( var)
1759+ if matches ! ( var, AbiVariant :: GuestImport )
1760+ || self . r#gen . opts . api_style == APIStyle :: Symmetric =>
1761+ {
1762+ self . r#gen . dependencies . needs_span = true ;
1763+ format ! ( "std::span<std::pair<{k}, {v}> const>" )
1764+ }
1765+ _ => {
1766+ self . r#gen . dependencies . needs_wit = true ;
1767+ format ! ( "wit::map<{k}, {v}>" )
1768+ }
1769+ }
17531770 }
17541771 TypeDefKind :: Unknown => todo ! ( ) ,
17551772 } ,
@@ -3559,28 +3576,28 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
35593576 let val = format ! ( "map{tmp}" ) ;
35603577 let ptr = format ! ( "ptr{tmp}" ) ;
35613578 let len = format ! ( "len{tmp}" ) ;
3562- let idx = format ! ( "idx{tmp}" ) ;
3563- let entry_name = format ! ( "entry{tmp}" ) ;
35643579 let entry = self . r#gen . sizes . record ( [ * key, * value] ) ;
35653580 let size = entry. size . format ( POINTER_SIZE_EXPRESSION ) ;
35663581 let align = entry. align . format ( POINTER_SIZE_EXPRESSION ) ;
3582+ // The canonical ABI entry layout can differ from the C++ entry
3583+ // layout (see wit-bindgen#1592), so always allocate a fresh ABI
3584+ // buffer rather than reusing the source map's storage.
35673585 self . push_str ( & format ! ( "auto&& {val} = {};\n " , operands[ 0 ] ) ) ;
35683586 self . push_str ( & format ! ( "auto {len} = (size_t)({val}.size());\n " ) ) ;
35693587 uwriteln ! (
35703588 self . src,
35713589 "auto {ptr} = ({ptr_type})({len} > 0 ? cabi_realloc(nullptr, 0, {align}, {len} * {size}) : nullptr);" ,
35723590 ptr_type = self . r#gen. r#gen. opts. ptr_type( )
35733591 ) ;
3574- uwriteln ! ( self . src, "size_t {idx} = 0;" ) ;
3575- uwriteln ! ( self . src, "for ( auto& {entry_name} : {val}) {{ " ) ;
3576- uwriteln ! ( self . src, "auto iter_map_key = {entry_name}.first ;" ) ;
3577- uwriteln ! ( self . src, "auto& iter_map_value = {entry_name}.second ;" ) ;
3578- uwriteln ! ( self . src, "auto base = {ptr} + {idx} * {size} ;" ) ;
3592+ uwriteln ! ( self . src, "for ( size_t i = 0; i < {len}; ++i) {{ " ) ;
3593+ uwriteln ! ( self . src, "auto base = {ptr} + i * {size}; " ) ;
3594+ uwriteln ! ( self . src, "auto&& iter_entry = {val}[i] ;" ) ;
3595+ uwriteln ! ( self . src, "auto&& iter_map_key = iter_entry.first ;" ) ;
3596+ uwriteln ! ( self . src, "auto&& iter_map_value = iter_entry.second ;" ) ;
35793597 uwrite ! ( self . src, "{}" , body. 0 ) ;
3580- uwriteln ! ( self . src, "++{idx};" ) ;
35813598 uwriteln ! ( self . src, "}}" ) ;
35823599 if realloc. is_some ( ) {
3583- // ownership transfers
3600+ uwriteln ! ( self . src , "{}.leak();" , operands [ 0 ] ) ;
35843601 }
35853602 results. push ( ptr) ;
35863603 results. push ( len) ;
@@ -3590,16 +3607,24 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
35903607 let tmp = self . tmp ( ) ;
35913608 let entry = self . r#gen . sizes . record ( [ * key, * value] ) ;
35923609 let size = entry. size . format ( POINTER_SIZE_EXPRESSION ) ;
3593- let key_type = self . r#gen . type_name ( key, & self . namespace , Flavor :: InStruct ) ;
3594- let value_type = self
3595- . r#gen
3596- . type_name ( value, & self . namespace , Flavor :: InStruct ) ;
3610+ let flavor = if self . r#gen . r#gen . opts . api_style == APIStyle :: Symmetric
3611+ && matches ! ( self . variant, AbiVariant :: GuestExport )
3612+ {
3613+ Flavor :: BorrowedArgument
3614+ } else {
3615+ Flavor :: InStruct
3616+ } ;
3617+ let key_type = self . r#gen . type_name ( key, & self . namespace , flavor) ;
3618+ let value_type = self . r#gen . type_name ( value, & self . namespace , flavor) ;
35973619 let len = format ! ( "len{tmp}" ) ;
35983620 let base = format ! ( "base{tmp}" ) ;
35993621 let result = format ! ( "result{tmp}" ) ;
36003622 uwriteln ! ( self . src, "auto {base} = {};" , operands[ 0 ] ) ;
36013623 uwriteln ! ( self . src, "auto {len} = {};" , operands[ 1 ] ) ;
3602- uwriteln ! ( self . src, "std::map<{key_type}, {value_type}> {result};" ) ;
3624+ uwriteln ! (
3625+ self . src,
3626+ "auto {result} = wit::map<{key_type}, {value_type}>::allocate({len});"
3627+ ) ;
36033628 if self . r#gen . r#gen . opts . api_style == APIStyle :: Symmetric
36043629 && matches ! ( self . variant, AbiVariant :: GuestExport )
36053630 {
@@ -3613,12 +3638,22 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
36133638 let body_value = & body. 1 [ 1 ] ;
36143639 uwriteln ! (
36153640 self . src,
3616- "{result}.insert( std::make_pair({}, {}));" ,
3641+ "{result}.initialize(i, std::make_pair({}, {}));" ,
36173642 move_if_necessary( body_key) ,
36183643 move_if_necessary( body_value)
36193644 ) ;
36203645 uwriteln ! ( self . src, "}}" ) ;
3621- results. push ( move_if_necessary ( & result) ) ;
3646+
3647+ if self . r#gen . r#gen . opts . api_style == APIStyle :: Symmetric
3648+ && matches ! ( self . variant, AbiVariant :: GuestExport )
3649+ {
3650+ results. push ( format ! ( "{result}.get_const_view()" ) ) ;
3651+ self . leak_on_insertion . replace ( format ! (
3652+ "if ({len}>0) _deallocate.push_back((void*){result}.leak());\n "
3653+ ) ) ;
3654+ } else {
3655+ results. push ( move_if_necessary ( & result) ) ;
3656+ }
36223657 }
36233658 abi:: Instruction :: IterMapKey { .. } => {
36243659 results. push ( "iter_map_key" . to_string ( ) ) ;
0 commit comments