@@ -377,12 +377,15 @@ impl ComponentTypes {
377377 ///
378378 /// As per the Canonical ABI, when the representation is larger than MAX_FLAT_RESULTS
379379 /// or MAX_FLAT_PARAMS, the core wasm function will take a pointer to the arg/result list.
380- /// Returns (param_iterator, result_iterator )
380+ /// Returns (param_storage, result_storage )
381381 pub fn flat_func_type (
382382 & self ,
383383 ty : & TypeFunc ,
384384 context : FlatFuncTypeContext ,
385- ) -> ( FlatTypesStorage , FlatTypesStorage ) {
385+ ) -> (
386+ FlatTypesStorage < MAX_FLAT_PARAMS_ABI > ,
387+ FlatTypesStorage < MAX_FLAT_RESULTS_ABI > ,
388+ ) {
386389 let mut params_storage = self
387390 . flat_interface_type ( & InterfaceType :: Tuple ( ty. params ) , MAX_FLAT_PARAMS )
388391 . unwrap_or_else ( || {
@@ -408,19 +411,23 @@ impl ComponentTypes {
408411 ( params_storage, results_storage)
409412 }
410413
411- fn flat_interface_type ( & self , ty : & InterfaceType , limit : usize ) -> Option < FlatTypesStorage > {
414+ fn flat_interface_type < const N : usize > (
415+ & self ,
416+ ty : & InterfaceType ,
417+ limit : usize ,
418+ ) -> Option < FlatTypesStorage < N > > {
412419 // Helper routines
413- let push = |storage : & mut FlatTypesStorage , t32 : FlatType , t64 : FlatType | -> bool {
420+ let push = |storage : & mut FlatTypesStorage < N > , t32 : FlatType , t64 : FlatType | -> bool {
414421 storage. push ( t32, t64) ;
415422 ( storage. len as usize ) <= limit
416423 } ;
417424
418- let push_discrim = |storage : & mut FlatTypesStorage | -> bool {
425+ let push_discrim = |storage : & mut FlatTypesStorage < N > | -> bool {
419426 push ( storage, FlatType :: I32 , FlatType :: I32 )
420427 } ;
421428
422429 let push_storage =
423- |storage : & mut FlatTypesStorage , other : Option < FlatTypesStorage > | -> bool {
430+ |storage : & mut FlatTypesStorage < N > , other : Option < FlatTypesStorage < N > > | -> bool {
424431 other
425432 . and_then ( |other| {
426433 let len = usize:: from ( storage. len ) ;
@@ -440,45 +447,46 @@ impl ComponentTypes {
440447 // * None => No field
441448 // * Some(None) => Invalid storage (overflow)
442449 // * Some(storage) => Valid storage
443- let push_storage_variant_case =
444- | storage : & mut FlatTypesStorage , case : Option < Option < FlatTypesStorage > > | -> bool {
445- match case {
446- None => true ,
447- Some ( case ) => {
448- case . and_then ( | case| {
449- // Discriminant will make size[ case] = limit overshoot
450- ( ( 1 + case. len as usize ) < = limit) . then ( || {
451- // Skip 1 for discriminant
452- let dst = storage
453- . memory32
454- . iter_mut ( )
455- . zip ( & mut storage . memory64 )
456- . skip ( 1 ) ;
457- for ( i , ( ( t32 , t64 ) , ( dst32 , dst64 ) ) ) in case
458- . memory32
459- . iter ( )
460- . take ( case . len as usize )
461- . zip ( case. memory64 . iter ( ) )
462- . zip ( dst )
463- . enumerate ( )
464- {
465- if i + 1 < usize :: from ( storage . len ) {
466- // Populated Index
467- dst32 . join ( * t32 ) ;
468- dst64 . join ( * t64 ) ;
469- } else {
470- // New Index
471- storage . len += 1 ;
472- * dst32 = * t32 ;
473- * dst64 = * t64 ;
474- }
450+ let push_storage_variant_case = | storage : & mut FlatTypesStorage < N > ,
451+ case : Option < Option < FlatTypesStorage < N > > > |
452+ -> bool {
453+ match case {
454+ None => true ,
455+ Some ( case) => {
456+ case. and_then ( |case| {
457+ // Discriminant will make size[ case] = limit overshoot
458+ ( ( 1 + case . len as usize ) <= limit ) . then ( || {
459+ // Skip 1 for discriminant
460+ let dst = storage
461+ . memory32
462+ . iter_mut ( )
463+ . zip ( & mut storage . memory64 )
464+ . skip ( 1 ) ;
465+ for ( i , ( ( t32 , t64 ) , ( dst32 , dst64 ) ) ) in case
466+ . memory32
467+ . iter ( )
468+ . take ( case. len as usize )
469+ . zip ( case . memory64 . iter ( ) )
470+ . zip ( dst )
471+ . enumerate ( )
472+ {
473+ if i + 1 < usize :: from ( storage . len ) {
474+ // Populated Index
475+ dst32 . join ( * t32 ) ;
476+ dst64 . join ( * t64 ) ;
477+ } else {
478+ // New Index
479+ storage . len += 1 ;
480+ * dst32 = * t32 ;
481+ * dst64 = * t64 ;
475482 }
476- } )
483+ }
477484 } )
478- . is_some ( )
479- }
485+ } )
486+ . is_some ( )
480487 }
481- } ;
488+ }
489+ } ;
482490
483491 // Logic
484492 let mut storage_buf = FlatTypesStorage :: new ( ) ;
@@ -1364,6 +1372,15 @@ pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
13641372 MAX_FLAT_RESULTS
13651373} ;
13661374
1375+ /// Maximum number of parameters that a core wasm function exported/imports through
1376+ /// components can contain according to the Canonical ABI. In particular, this
1377+ /// can includes one potential extra return pointer for canon.lower methods.
1378+ pub const MAX_FLAT_PARAMS_ABI : usize = MAX_FLAT_PARAMS + 1 ;
1379+
1380+ /// Maximum number of results that a core wasm function exported/imports through
1381+ /// components can contain according to the Canonical ABI.
1382+ pub const MAX_FLAT_RESULTS_ABI : usize = MAX_FLAT_RESULTS ;
1383+
13671384const fn add_flat ( a : Option < u8 > , b : Option < u8 > ) -> Option < u8 > {
13681385 const MAX : u8 = MAX_FLAT_TYPES as u8 ;
13691386 let sum = match ( a, b) {
@@ -1395,11 +1412,11 @@ const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
13951412/// that's 24 bytes. Otherwise `FlatType` is 1 byte large and
13961413/// `MAX_FLAT_TYPES` is 16, so it should ideally be more space-efficient to
13971414/// use a flat array instead of a heap-based vector.
1398- pub struct FlatTypesStorage {
1415+ pub struct FlatTypesStorage < const N : usize > {
13991416 /// Representation for 32-bit memory
1400- pub memory32 : [ FlatType ; MAX_FLAT_TYPES ] ,
1417+ pub memory32 : [ FlatType ; N ] ,
14011418 /// Representation for 64-bit memory
1402- pub memory64 : [ FlatType ; MAX_FLAT_TYPES ] ,
1419+ pub memory64 : [ FlatType ; N ] ,
14031420
14041421 /// Tracks the number of flat types pushed into this storage. If this is
14051422 /// `MAX_FLAT_TYPES + 1` then this storage represents an un-reprsentable
@@ -1409,21 +1426,21 @@ pub struct FlatTypesStorage {
14091426 pub len : u8 ,
14101427}
14111428
1412- impl FlatTypesStorage {
1429+ impl < const N : usize > FlatTypesStorage < N > {
14131430 /// Create a new, empty storage for flat types
1414- pub const fn new ( ) -> FlatTypesStorage {
1431+ pub const fn new ( ) -> FlatTypesStorage < N > {
14151432 FlatTypesStorage {
1416- memory32 : [ FlatType :: I32 ; MAX_FLAT_TYPES ] ,
1417- memory64 : [ FlatType :: I32 ; MAX_FLAT_TYPES ] ,
1433+ memory32 : [ FlatType :: I32 ; N ] ,
1434+ memory64 : [ FlatType :: I32 ; N ] ,
14181435 len : 0 ,
14191436 }
14201437 }
14211438
14221439 /// Returns a reference to flat type representation
14231440 pub fn as_flat_types ( & self ) -> Option < FlatTypes < ' _ > > {
14241441 let len = usize:: from ( self . len ) ;
1425- if len > MAX_FLAT_TYPES {
1426- assert_eq ! ( len, MAX_FLAT_TYPES + 1 ) ;
1442+ if len > N {
1443+ assert_eq ! ( len, N + 1 ) ;
14271444 None
14281445 } else {
14291446 Some ( FlatTypes {
@@ -1441,15 +1458,15 @@ impl FlatTypesStorage {
14411458 /// unrepresentable with a flat list of types.
14421459 pub fn push ( & mut self , t32 : FlatType , t64 : FlatType ) -> bool {
14431460 let len = usize:: from ( self . len ) ;
1444- if len < MAX_FLAT_TYPES {
1461+ if len < N {
14451462 self . memory32 [ len] = t32;
14461463 self . memory64 [ len] = t64;
14471464 self . len += 1 ;
14481465 true
14491466 } else {
14501467 // If this was the first one to go over then flag the length as
14511468 // being incompatible with a flat representation.
1452- if len == MAX_FLAT_TYPES {
1469+ if len == N {
14531470 self . len += 1 ;
14541471 }
14551472 false
0 commit comments