@@ -3,14 +3,17 @@ use crate::error;
3
3
use crate :: helpers:: OutputLimitedBuffer ;
4
4
use magnus:: {
5
5
class, function, gc:: Marker , method, typed_data:: Obj , value:: Opaque , DataTypeFunctions , Error ,
6
- Module , Object , RArray , RHash , RString , Ruby , TryConvert , TypedData ,
6
+ Module , Object , RArray , RHash , RString , Ruby , Symbol , TryConvert , TypedData ,
7
7
} ;
8
+ use rb_sys:: ruby_rarray_flags:: RARRAY_EMBED_FLAG ;
8
9
use std:: cell:: RefCell ;
9
10
use std:: fs;
11
+ use std:: path:: Path ;
10
12
use std:: { fs:: File , path:: PathBuf } ;
11
13
use wasmtime_wasi:: p2:: pipe:: MemoryInputPipe ;
12
14
use wasmtime_wasi:: p2:: { OutputFile , WasiCtx , WasiCtxBuilder } ;
13
15
use wasmtime_wasi:: preview1:: WasiP1Ctx ;
16
+ use wasmtime_wasi:: { DirPerms , FilePerms } ;
14
17
15
18
enum ReadStream {
16
19
Inherit ,
@@ -51,6 +54,7 @@ struct WasiConfigInner {
51
54
env : Option < Opaque < RHash > > ,
52
55
args : Option < Opaque < RArray > > ,
53
56
deterministic : bool ,
57
+ mapped_directories : Option < Opaque < RArray > > ,
54
58
}
55
59
56
60
impl WasiConfigInner {
@@ -70,6 +74,9 @@ impl WasiConfigInner {
70
74
if let Some ( v) = self . args . as_ref ( ) {
71
75
marker. mark ( * v) ;
72
76
}
77
+ if let Some ( v) = self . mapped_directories . as_ref ( ) {
78
+ marker. mark ( * v) ;
79
+ }
73
80
}
74
81
}
75
82
@@ -233,6 +240,37 @@ impl WasiConfig {
233
240
rb_self
234
241
}
235
242
243
+ /// @yard
244
+ /// Set mapped directory for host path and guest path.
245
+ /// @param host_path [String]
246
+ /// @param guest_path [String]
247
+ /// @param dir_perms [Symbol] Directory permissions, one of :read, :mutate, or :all
248
+ /// @param file_perms [Symbol] File permissions, one of :read, :write, or :all
249
+ /// @def set_mapped_directory(host_path, guest_path, dir_perms, file_perms)
250
+ /// @return [WasiConfig] +self+
251
+ pub fn set_mapped_directory (
252
+ rb_self : RbSelf ,
253
+ host_path : RString ,
254
+ guest_path : RString ,
255
+ dir_perms : Symbol ,
256
+ file_perms : Symbol ,
257
+ ) -> RbSelf {
258
+ let mut inner = rb_self. inner . borrow_mut ( ) ;
259
+ if inner. mapped_directories . is_none ( ) {
260
+ inner. mapped_directories = Some ( RArray :: new ( ) . into ( ) ) ;
261
+ }
262
+ let mapped_directory = RArray :: new ( ) ;
263
+ mapped_directory. push ( host_path) . unwrap ( ) ;
264
+ mapped_directory. push ( guest_path) . unwrap ( ) ;
265
+ mapped_directory. push ( dir_perms) . unwrap ( ) ;
266
+ mapped_directory. push ( file_perms) . unwrap ( ) ;
267
+
268
+ let ruby = Ruby :: get ( ) . unwrap ( ) ;
269
+ let mapped_directories = ruby. get_inner ( inner. mapped_directories . unwrap ( ) ) ;
270
+ mapped_directories. push ( mapped_directory) . unwrap ( ) ;
271
+ rb_self
272
+ }
273
+
236
274
pub fn build_p1 ( & self , ruby : & Ruby ) -> Result < WasiP1Ctx , Error > {
237
275
let mut builder = self . build_impl ( ruby) ?;
238
276
let ctx = builder. build_p1 ( ) ;
@@ -317,6 +355,63 @@ impl WasiConfig {
317
355
deterministic_wasi_ctx:: add_determinism_to_wasi_ctx_builder ( & mut builder) ;
318
356
}
319
357
358
+ if let Some ( mapped_directories) = inner. mapped_directories . as_ref ( ) {
359
+ for item in unsafe { ruby. get_inner ( * mapped_directories) . as_slice ( ) } {
360
+ let mapped_directory = RArray :: try_convert ( * item) ?;
361
+ if mapped_directory. len ( ) == 4 {
362
+ let host_path =
363
+ RString :: try_convert ( mapped_directory. entry ( 0 ) ?) ?. to_string ( ) ?;
364
+ let guest_path =
365
+ RString :: try_convert ( mapped_directory. entry ( 1 ) ?) ?. to_string ( ) ?;
366
+ let dir_perms = Symbol :: from_value ( mapped_directory. entry ( 2 ) ?)
367
+ . unwrap ( )
368
+ . name ( ) ?;
369
+ let file_perms = Symbol :: from_value ( mapped_directory. entry ( 3 ) ?)
370
+ . unwrap ( )
371
+ . name ( ) ?;
372
+
373
+ let host_path_dir = Path :: new ( & host_path) ;
374
+ let guest_path_path = guest_path. as_str ( ) ;
375
+
376
+ // Convert to FilePerms and DirPerms enums
377
+ let dir_perms_flags;
378
+ match dir_perms {
379
+ std:: borrow:: Cow :: Borrowed ( "read" ) => dir_perms_flags = DirPerms :: READ ,
380
+ std:: borrow:: Cow :: Borrowed ( "mutate" ) => dir_perms_flags = DirPerms :: MUTATE ,
381
+ std:: borrow:: Cow :: Borrowed ( "all" ) => dir_perms_flags = DirPerms :: all ( ) ,
382
+ _ => {
383
+ return Err ( error ! (
384
+ "Invalid dir_perms: {}. Use one of :read, :mutate, or :all" ,
385
+ dir_perms
386
+ ) )
387
+ }
388
+ }
389
+
390
+ let file_perms_flags;
391
+ match file_perms {
392
+ std:: borrow:: Cow :: Borrowed ( "read" ) => file_perms_flags = FilePerms :: READ ,
393
+ std:: borrow:: Cow :: Borrowed ( "write" ) => file_perms_flags = FilePerms :: WRITE ,
394
+ std:: borrow:: Cow :: Borrowed ( "all" ) => file_perms_flags = FilePerms :: all ( ) ,
395
+ _ => {
396
+ return Err ( error ! (
397
+ "Invalid file_perms: {}. Use one of :read, :write, or :all" ,
398
+ file_perms
399
+ ) )
400
+ }
401
+ }
402
+
403
+ builder
404
+ . preopened_dir (
405
+ host_path_dir,
406
+ guest_path_path,
407
+ dir_perms_flags,
408
+ file_perms_flags,
409
+ )
410
+ . map_err ( |e| error ! ( "{}" , e) ) ?;
411
+ }
412
+ }
413
+ }
414
+
320
415
Ok ( builder)
321
416
}
322
417
}
@@ -355,5 +450,10 @@ pub fn init() -> Result<(), Error> {
355
450
356
451
class. define_method ( "set_argv" , method ! ( WasiConfig :: set_argv, 1 ) ) ?;
357
452
453
+ class. define_method (
454
+ "set_mapped_directory" ,
455
+ method ! ( WasiConfig :: set_mapped_directory, 4 ) ,
456
+ ) ?;
457
+
358
458
Ok ( ( ) )
359
459
}
0 commit comments