@@ -75,6 +75,7 @@ struct Includes {
7575 needs_wit : bool ,
7676 needs_memory : bool ,
7777 needs_array : bool ,
78+ needs_map : bool ,
7879}
7980
8081#[ derive( Default ) ]
@@ -435,6 +436,9 @@ impl Cpp {
435436 if self . dependencies . needs_bit {
436437 self . include ( "<bit>" ) ;
437438 }
439+ if self . dependencies . needs_map {
440+ self . include ( "<map>" ) ;
441+ }
438442 }
439443
440444 fn start_new_file ( & mut self , condition : Option < bool > ) -> FileContext {
@@ -914,7 +918,7 @@ impl CppInterfaceGenerator<'_> {
914918 TypeDefKind :: Stream ( _) => todo ! ( "generate for stream" ) ,
915919 TypeDefKind :: Handle ( _) => todo ! ( "generate for handle" ) ,
916920 TypeDefKind :: FixedLengthList ( _, _) => todo ! ( ) ,
917- TypeDefKind :: Map ( _ , _ ) => todo ! ( ) ,
921+ TypeDefKind :: Map ( k , v ) => self . type_map ( id , name , k , v , & ty . docs ) ,
918922 TypeDefKind :: Unknown => unreachable ! ( ) ,
919923 }
920924 }
@@ -1741,7 +1745,12 @@ impl CppInterfaceGenerator<'_> {
17411745 self . type_name( ty, from_namespace, flavor)
17421746 )
17431747 }
1744- TypeDefKind :: Map ( _, _) => todo ! ( ) ,
1748+ 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}>" )
1753+ }
17451754 TypeDefKind :: Unknown => todo ! ( ) ,
17461755 } ,
17471756 Type :: ErrorContext => todo ! ( ) ,
@@ -2266,7 +2275,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for CppInterfaceGenerator<'a>
22662275 _value : & wit_bindgen_core:: wit_parser:: Type ,
22672276 _docs : & wit_bindgen_core:: wit_parser:: Docs ,
22682277 ) {
2269- todo ! ( "map types are not yet supported in the C++ backend" )
2278+ // nothing to do here
22702279 }
22712280
22722281 fn type_builtin (
@@ -3540,12 +3549,107 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
35403549 }
35413550 abi:: Instruction :: AsyncTaskReturn { .. } => todo ! ( ) ,
35423551 abi:: Instruction :: DropHandle { .. } => todo ! ( ) ,
3543- abi:: Instruction :: MapLower { .. }
3544- | abi:: Instruction :: MapLift { .. }
3545- | abi:: Instruction :: IterMapKey { .. }
3546- | abi:: Instruction :: IterMapValue { .. }
3547- | abi:: Instruction :: GuestDeallocateMap { .. } => {
3548- todo ! ( "map types are not yet supported in this backend" )
3552+ abi:: Instruction :: MapLower {
3553+ key,
3554+ value,
3555+ realloc,
3556+ } => {
3557+ let tmp = self . tmp ( ) ;
3558+ let body = self . blocks . pop ( ) . unwrap ( ) ;
3559+ let val = format ! ( "map{tmp}" ) ;
3560+ let ptr = format ! ( "ptr{tmp}" ) ;
3561+ let len = format ! ( "len{tmp}" ) ;
3562+ let idx = format ! ( "idx{tmp}" ) ;
3563+ let entry = self . r#gen . sizes . record ( [ * key, * value] ) ;
3564+ let size = entry. size . format ( POINTER_SIZE_EXPRESSION ) ;
3565+ let align = entry. align . format ( POINTER_SIZE_EXPRESSION ) ;
3566+ self . push_str ( & format ! ( "auto&& {val} = {};\n " , operands[ 0 ] ) ) ;
3567+ self . push_str ( & format ! ( "auto {len} = (size_t)({val}.size());\n " ) ) ;
3568+ uwriteln ! (
3569+ self . src,
3570+ "auto {ptr} = ({ptr_type})({len} > 0 ? cabi_realloc(nullptr, 0, {align}, {len} * {size}) : nullptr);" ,
3571+ ptr_type = self . r#gen. r#gen. opts. ptr_type( )
3572+ ) ;
3573+ uwriteln ! ( self . src, "size_t {idx} = 0;" ) ;
3574+ uwriteln ! (
3575+ self . src,
3576+ "for (auto&& [iter_map_key, iter_map_value] : {val}) {{"
3577+ ) ;
3578+ uwriteln ! ( self . src, "auto base = {ptr} + {idx} * {size};" ) ;
3579+ uwrite ! ( self . src, "{}" , body. 0 ) ;
3580+ uwriteln ! ( self . src, "++{idx};" ) ;
3581+ uwriteln ! ( self . src, "}}" ) ;
3582+ if realloc. is_some ( ) {
3583+ // ownership transfers
3584+ }
3585+ results. push ( ptr) ;
3586+ results. push ( len) ;
3587+ }
3588+ abi:: Instruction :: MapLift { key, value, .. } => {
3589+ let body = self . blocks . pop ( ) . unwrap ( ) ;
3590+ let tmp = self . tmp ( ) ;
3591+ let entry = self . r#gen . sizes . record ( [ * key, * value] ) ;
3592+ let size = entry. size . format ( POINTER_SIZE_EXPRESSION ) ;
3593+ let key_type =
3594+ self . r#gen
3595+ . type_name ( key, & self . namespace , Flavor :: InStruct ) ;
3596+ let value_type =
3597+ self . r#gen
3598+ . type_name ( value, & self . namespace , Flavor :: InStruct ) ;
3599+ let len = format ! ( "len{tmp}" ) ;
3600+ let base = format ! ( "base{tmp}" ) ;
3601+ let result = format ! ( "result{tmp}" ) ;
3602+ uwriteln ! ( self . src, "auto {base} = {};" , operands[ 0 ] ) ;
3603+ uwriteln ! ( self . src, "auto {len} = {};" , operands[ 1 ] ) ;
3604+ uwriteln ! (
3605+ self . src,
3606+ "std::map<{key_type}, {value_type}> {result};"
3607+ ) ;
3608+ if self . r#gen . r#gen . opts . api_style == APIStyle :: Symmetric
3609+ && matches ! ( self . variant, AbiVariant :: GuestExport )
3610+ {
3611+ assert ! ( self . needs_dealloc) ;
3612+ uwriteln ! ( self . src, "if ({len}>0) _deallocate.push_back({base});" ) ;
3613+ }
3614+ uwriteln ! ( self . src, "for (unsigned i=0; i<{len}; ++i) {{" ) ;
3615+ uwriteln ! ( self . src, "auto base = {base} + i * {size};" ) ;
3616+ uwrite ! ( self . src, "{}" , body. 0 ) ;
3617+ let body_key = & body. 1 [ 0 ] ;
3618+ let body_value = & body. 1 [ 1 ] ;
3619+ uwriteln ! (
3620+ self . src,
3621+ "{result}.insert(std::make_pair({}, {}));" ,
3622+ move_if_necessary( body_key) ,
3623+ move_if_necessary( body_value)
3624+ ) ;
3625+ uwriteln ! ( self . src, "}}" ) ;
3626+ results. push ( move_if_necessary ( & result) ) ;
3627+ }
3628+ abi:: Instruction :: IterMapKey { .. } => {
3629+ results. push ( "iter_map_key" . to_string ( ) ) ;
3630+ }
3631+ abi:: Instruction :: IterMapValue { .. } => {
3632+ results. push ( "iter_map_value" . to_string ( ) ) ;
3633+ }
3634+ abi:: Instruction :: GuestDeallocateMap { key, value } => {
3635+ let ( body, results) = self . blocks . pop ( ) . unwrap ( ) ;
3636+ assert ! ( results. is_empty( ) ) ;
3637+ let tmp = self . tmp ( ) ;
3638+ let ptr = self . tempname ( "ptr" , tmp) ;
3639+ let len = self . tempname ( "len" , tmp) ;
3640+ uwriteln ! ( self . src, "uint8_t* {ptr} = {};" , operands[ 0 ] ) ;
3641+ uwriteln ! ( self . src, "size_t {len} = {};" , operands[ 1 ] ) ;
3642+ let i = self . tempname ( "i" , tmp) ;
3643+ uwriteln ! ( self . src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{" ) ;
3644+ let entry = self . r#gen . sizes . record ( [ * key, * value] ) ;
3645+ let size = entry. size . format ( POINTER_SIZE_EXPRESSION ) ;
3646+ uwriteln ! ( self . src, "uint8_t* base = {ptr} + {i} * {size};" ) ;
3647+ uwriteln ! ( self . src, "(void) base;" ) ;
3648+ uwrite ! ( self . src, "{body}" ) ;
3649+ uwriteln ! ( self . src, "}}" ) ;
3650+ uwriteln ! ( self . src, "if ({len} > 0) {{" ) ;
3651+ uwriteln ! ( self . src, "free((void*) ({ptr}));" ) ;
3652+ uwriteln ! ( self . src, "}}" ) ;
35493653 }
35503654 }
35513655 }
0 commit comments