1
- use std:: { collections:: HashMap , path:: PathBuf } ;
1
+ use std:: { collections:: HashMap , env , path:: PathBuf , time :: SystemTime } ;
2
2
3
3
use magnus:: {
4
4
eval, exception, function, method,
@@ -8,6 +8,7 @@ use magnus::{
8
8
} ;
9
9
use structopt:: StructOpt ;
10
10
use wizer:: Wizer ;
11
+ use wasi_virt;
11
12
12
13
static RUBY_WASM : value:: Lazy < RModule > =
13
14
value:: Lazy :: new ( |ruby| ruby. define_module ( "RubyWasmExt" ) . unwrap ( ) ) ;
@@ -222,6 +223,96 @@ impl ComponentEncode {
222
223
}
223
224
}
224
225
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
+
225
316
#[ magnus:: init]
226
317
fn init ( ruby : & Ruby ) -> Result < ( ) , Error > {
227
318
let module = RUBY_WASM . get_inner_with ( ruby) ;
@@ -266,5 +357,12 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
266
357
) ?;
267
358
component_encode. define_method ( "encode" , method ! ( ComponentEncode :: encode, 0 ) ) ?;
268
359
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
+
269
367
Ok ( ( ) )
270
368
}
0 commit comments