1+ //! Canonical Function Executor for WebAssembly Components
2+ //!
3+ //! This module provides execution of canonical functions (canon.lift and canon.lower)
4+ //! and integrates with the wasip2 host implementation for WASI preview2 support.
5+
6+ extern crate alloc;
7+
8+ use crate :: bounded_component_infra:: ComponentProvider ;
9+ use crate :: canonical_abi:: ComponentValue ;
10+ use wrt_error:: { Error , Result } ;
11+ use wrt_runtime:: wasip2_host:: Wasip2Host ;
12+ use wrt_foundation:: float_repr:: { FloatBits32 , FloatBits64 } ;
13+ use alloc:: vec:: Vec ;
14+ use alloc:: string:: String ;
15+
16+ /// Canonical function types
17+ #[ derive( Debug , Clone ) ]
18+ pub enum CanonicalFunction {
19+ /// Canon.lift - exports a component function by lifting core WASM function
20+ Lift {
21+ func_idx : u32 ,
22+ opts : CanonicalOptions ,
23+ } ,
24+ /// Canon.lower - imports a host function by lowering to core WASM
25+ Lower {
26+ func_idx : u32 ,
27+ interface : String ,
28+ function : String ,
29+ opts : CanonicalOptions ,
30+ } ,
31+ }
32+
33+ /// Canonical ABI options
34+ #[ derive( Debug , Clone , Default ) ]
35+ pub struct CanonicalOptions {
36+ pub memory : Option < u32 > ,
37+ pub realloc : Option < u32 > ,
38+ pub post_return : Option < u32 > ,
39+ pub string_encoding : StringEncoding ,
40+ }
41+
42+ /// String encoding for canonical ABI
43+ #[ derive( Debug , Clone ) ]
44+ pub enum StringEncoding {
45+ Utf8 ,
46+ Utf16 ,
47+ Latin1 ,
48+ }
49+
50+ impl Default for StringEncoding {
51+ fn default ( ) -> Self {
52+ StringEncoding :: Utf8
53+ }
54+ }
55+
56+ /// Executor for canonical functions with wasip2 support
57+ pub struct CanonicalExecutor {
58+ /// WASI Preview2 host implementation
59+ wasip2 : Wasip2Host ,
60+ /// Registered canonical functions
61+ canonicals : Vec < CanonicalFunction > ,
62+ }
63+
64+ impl CanonicalExecutor {
65+ pub fn new ( ) -> Self {
66+ Self {
67+ wasip2 : Wasip2Host :: new ( ) ,
68+ canonicals : Vec :: new ( ) ,
69+ }
70+ }
71+
72+ /// Register a canonical function
73+ pub fn register_canonical ( & mut self , func : CanonicalFunction ) -> u32 {
74+ let idx = self . canonicals . len ( ) as u32 ;
75+ self . canonicals . push ( func) ;
76+ idx
77+ }
78+
79+ /// Execute a canon.lower import (host function call)
80+ pub fn execute_canon_lower (
81+ & mut self ,
82+ interface : & str ,
83+ function : & str ,
84+ args : Vec < ComponentValue > ,
85+ memory : Option < & mut [ u8 ] > ,
86+ ) -> Result < Vec < ComponentValue > > {
87+ eprintln ! ( "[CANON_EXECUTOR] Executing canon.lower: {}::{}" , interface, function) ;
88+
89+ // Convert ComponentValue to wasip2 Value format
90+ let wasip2_args = self . convert_to_wasip2_values ( args) ?;
91+
92+ // Dispatch to wasip2 host
93+ let wasip2_results = self . wasip2 . dispatch ( interface, function, wasip2_args, memory) ?;
94+
95+ // Convert results back to ComponentValue
96+ let results = self . convert_from_wasip2_values ( wasip2_results) ?;
97+
98+ eprintln ! ( "[CANON_EXECUTOR] Canon.lower completed with {} results" , results. len( ) ) ;
99+ Ok ( results)
100+ }
101+
102+ /// Execute a canon.lift export (component function export)
103+ pub fn execute_canon_lift (
104+ & mut self ,
105+ func_idx : u32 ,
106+ args : Vec < ComponentValue > ,
107+ _opts : & CanonicalOptions ,
108+ ) -> Result < Vec < ComponentValue > > {
109+ eprintln ! ( "[CANON_EXECUTOR] Executing canon.lift: func_idx={}" , func_idx) ;
110+
111+ // Canon.lift would call the underlying core WASM function
112+ // This requires integration with the core WASM engine
113+ // For now, return a placeholder
114+
115+ Err ( Error :: runtime_not_implemented ( "Canon.lift execution not yet implemented" ) )
116+ }
117+
118+ /// Convert ComponentValue to wasip2 Value
119+ fn convert_to_wasip2_values ( & self , values : Vec < ComponentValue > ) -> Result < Vec < wrt_foundation:: values:: Value > > {
120+ use wrt_foundation:: values:: Value ;
121+
122+ let mut result = Vec :: new ( ) ;
123+ for val in values {
124+ let wasip2_val = match val {
125+ ComponentValue :: Bool ( b) => Value :: I32 ( if b { 1 } else { 0 } ) ,
126+ ComponentValue :: S8 ( i) => Value :: I32 ( i as i32 ) ,
127+ ComponentValue :: U8 ( u) => Value :: I32 ( u as i32 ) ,
128+ ComponentValue :: S16 ( i) => Value :: I32 ( i as i32 ) ,
129+ ComponentValue :: U16 ( u) => Value :: I32 ( u as i32 ) ,
130+ ComponentValue :: S32 ( i) => Value :: I32 ( i) ,
131+ ComponentValue :: U32 ( u) => Value :: I32 ( u as i32 ) ,
132+ ComponentValue :: S64 ( i) => Value :: I64 ( i) ,
133+ ComponentValue :: U64 ( u) => Value :: I64 ( u as i64 ) ,
134+ ComponentValue :: F32 ( f) => Value :: F32 ( FloatBits32 :: from_f32 ( f) ) ,
135+ ComponentValue :: F64 ( f) => Value :: F64 ( FloatBits64 :: from_f64 ( f) ) ,
136+ _ => {
137+ eprintln ! ( "[CANON_EXECUTOR] Unsupported ComponentValue type for conversion" ) ;
138+ return Err ( Error :: runtime_error ( "Unsupported value type" ) ) ;
139+ }
140+ } ;
141+ result. push ( wasip2_val) ;
142+ }
143+ Ok ( result)
144+ }
145+
146+ /// Convert wasip2 Value to ComponentValue
147+ fn convert_from_wasip2_values ( & self , values : Vec < wrt_foundation:: values:: Value > ) -> Result < Vec < ComponentValue > > {
148+ use wrt_foundation:: values:: Value ;
149+
150+ let mut result = Vec :: new ( ) ;
151+ for val in values {
152+ let comp_val = match val {
153+ Value :: I32 ( i) => ComponentValue :: S32 ( i) ,
154+ Value :: I64 ( i) => ComponentValue :: S64 ( i) ,
155+ Value :: F32 ( f) => ComponentValue :: F32 ( f. to_f32 ( ) ) ,
156+ Value :: F64 ( f) => ComponentValue :: F64 ( f. to_f64 ( ) ) ,
157+ _ => {
158+ eprintln ! ( "[CANON_EXECUTOR] Unsupported Value type for conversion" ) ;
159+ return Err ( Error :: runtime_error ( "Unsupported value type" ) ) ;
160+ }
161+ } ;
162+ result. push ( comp_val) ;
163+ }
164+ Ok ( result)
165+ }
166+ }
167+
168+ /// Create a global canonical executor instance
169+ #[ cfg( feature = "std" ) ]
170+ pub fn create_canonical_executor ( ) -> CanonicalExecutor {
171+ CanonicalExecutor :: new ( )
172+ }
173+
174+ /// Check if a function name represents a wasip2 canonical import
175+ pub fn is_wasip2_canonical ( name : & str ) -> bool {
176+ name. starts_with ( "wasi:" ) && name. contains ( "@0.2" )
177+ }
0 commit comments