1- use std:: { collections:: HashMap , path:: PathBuf } ;
1+ use std:: { collections:: HashMap , env , path:: PathBuf , time :: SystemTime } ;
22
33use magnus:: {
44 eval, exception, function, method,
@@ -8,6 +8,7 @@ use magnus::{
88} ;
99use structopt:: StructOpt ;
1010use wizer:: Wizer ;
11+ use wasi_virt;
1112
1213static RUBY_WASM : value:: Lazy < RModule > =
1314 value:: Lazy :: new ( |ruby| ruby. define_module ( "RubyWasmExt" ) . unwrap ( ) ) ;
@@ -222,6 +223,96 @@ impl ComponentEncode {
222223 }
223224}
224225
226+ #[ wrap( class = "RubyWasmExt::WasiVirt" ) ]
227+ struct WasiVirt ( std:: cell:: RefCell < Option < wasi_virt:: WasiVirt > > ) ;
228+
229+ impl WasiVirt {
230+ fn new ( ) -> Self {
231+ Self ( std:: cell:: RefCell :: new ( Some ( wasi_virt:: WasiVirt :: new ( ) ) ) )
232+ }
233+
234+ fn virt < R > (
235+ & self ,
236+ body : impl FnOnce ( & mut wasi_virt:: WasiVirt ) -> Result < R , Error > ,
237+ ) -> Result < R , Error > {
238+ let mut virt = self . 0 . take ( ) . ok_or_else ( || {
239+ Error :: new (
240+ exception:: standard_error ( ) ,
241+ "wasi virt is already consumed" . to_string ( ) ,
242+ )
243+ } ) ?;
244+ let result = body ( & mut virt) ?;
245+ self . 0 . replace ( Some ( virt) ) ;
246+ Ok ( result)
247+ }
248+
249+ fn allow_all ( & self ) -> Result < ( ) , Error > {
250+ self . virt ( |virt| {
251+ virt. allow_all ( ) ;
252+ Ok ( ( ) )
253+ } )
254+ }
255+
256+ fn map_dir ( & self , guest_dir : String , host_dir : String ) -> Result < ( ) , Error > {
257+ self . virt ( |virt| {
258+ virt. fs ( ) . virtual_preopen ( guest_dir, host_dir) ;
259+ Ok ( ( ) )
260+ } )
261+ }
262+
263+ fn finish ( & self ) -> Result < bytes:: Bytes , Error > {
264+ self . virt ( |virt| {
265+ let result = virt. finish ( ) . map_err ( |e| {
266+ Error :: new (
267+ exception:: standard_error ( ) ,
268+ format ! ( "failed to generate virtualization adapter: {}" , e) ,
269+ )
270+ } ) ?;
271+ Ok ( result. adapter . into ( ) )
272+ } )
273+ }
274+
275+ fn compose ( & self , component_bytes : bytes:: Bytes ) -> Result < bytes:: Bytes , Error > {
276+ let virt_adapter = self . finish ( ) ?;
277+ let tmpdir = env:: temp_dir ( ) ;
278+ let tmp_virt = tmpdir. join ( format ! ( "virt{}.wasm" , timestamp( ) ) ) ;
279+ std:: fs:: write ( & tmp_virt, & virt_adapter) . map_err ( |e| {
280+ Error :: new (
281+ exception:: standard_error ( ) ,
282+ format ! ( "failed to write virt adapter: {}" , e) ,
283+ )
284+ } ) ?;
285+ let tmp_component = tmpdir. join ( format ! ( "component{}.wasm" , timestamp( ) ) ) ;
286+ std:: fs:: write ( & tmp_component, & component_bytes) . map_err ( |e| {
287+ Error :: new (
288+ exception:: standard_error ( ) ,
289+ format ! ( "failed to write component: {}" , e) ,
290+ )
291+ } ) ?;
292+
293+ use wasm_compose:: { composer, config} ;
294+ let config = config:: Config {
295+ definitions : vec ! [ tmp_virt] ,
296+ ..Default :: default ( )
297+ } ;
298+ let composer = composer:: ComponentComposer :: new ( & tmp_component, & config) ;
299+ let composed = composer. compose ( ) . map_err ( |e| {
300+ Error :: new (
301+ exception:: standard_error ( ) ,
302+ format ! ( "failed to compose component: {}" , e) ,
303+ )
304+ } ) ?;
305+ return Ok ( composed. into ( ) ) ;
306+
307+ fn timestamp ( ) -> u64 {
308+ match SystemTime :: now ( ) . duration_since ( SystemTime :: UNIX_EPOCH ) {
309+ Ok ( n) => n. as_secs ( ) ,
310+ Err ( _) => panic ! ( ) ,
311+ }
312+ }
313+ }
314+ }
315+
225316#[ magnus:: init]
226317fn init ( ruby : & Ruby ) -> Result < ( ) , Error > {
227318 let module = RUBY_WASM . get_inner_with ( ruby) ;
@@ -266,5 +357,12 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
266357 ) ?;
267358 component_encode. define_method ( "encode" , method ! ( ComponentEncode :: encode, 0 ) ) ?;
268359
360+ let wasi_virt = module. define_class ( "WasiVirt" , ruby. class_object ( ) ) ?;
361+ wasi_virt. define_singleton_method ( "new" , function ! ( WasiVirt :: new, 0 ) ) ?;
362+ wasi_virt. define_method ( "allow_all" , method ! ( WasiVirt :: allow_all, 0 ) ) ?;
363+ wasi_virt. define_method ( "map_dir" , method ! ( WasiVirt :: map_dir, 2 ) ) ?;
364+ wasi_virt. define_method ( "finish" , method ! ( WasiVirt :: finish, 0 ) ) ?;
365+ wasi_virt. define_method ( "compose" , method ! ( WasiVirt :: compose, 1 ) ) ?;
366+
269367 Ok ( ( ) )
270368}
0 commit comments