@@ -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,40 @@ 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 mapped_directory = RArray :: new ( ) ;
259
+ mapped_directory. push ( host_path) . unwrap ( ) ;
260
+ mapped_directory. push ( guest_path) . unwrap ( ) ;
261
+ mapped_directory. push ( dir_perms) . unwrap ( ) ;
262
+ mapped_directory. push ( file_perms) . unwrap ( ) ;
263
+
264
+ let init_directory = RArray :: new ( ) ;
265
+
266
+ let mut inner = rb_self. inner . borrow_mut ( ) ;
267
+ if inner. mapped_directories . is_none ( ) {
268
+ inner. mapped_directories = Some ( init_directory. into ( ) ) ;
269
+ }
270
+
271
+ let ruby = Ruby :: get ( ) . unwrap ( ) ;
272
+ let mapped_directories = ruby. get_inner ( inner. mapped_directories . unwrap ( ) ) ;
273
+ mapped_directories. push ( mapped_directory) . unwrap ( ) ;
274
+ rb_self
275
+ }
276
+
236
277
pub fn build_p1 ( & self , ruby : & Ruby ) -> Result < WasiP1Ctx , Error > {
237
278
let mut builder = self . build_impl ( ruby) ?;
238
279
let ctx = builder. build_p1 ( ) ;
@@ -317,6 +358,63 @@ impl WasiConfig {
317
358
deterministic_wasi_ctx:: add_determinism_to_wasi_ctx_builder ( & mut builder) ;
318
359
}
319
360
361
+ if let Some ( mapped_directories) = inner. mapped_directories . as_ref ( ) {
362
+ for item in unsafe { ruby. get_inner ( * mapped_directories) . as_slice ( ) } {
363
+ let mapped_directory = RArray :: try_convert ( * item) ?;
364
+ if mapped_directory. len ( ) == 4 {
365
+ let host_path =
366
+ RString :: try_convert ( mapped_directory. entry ( 0 ) ?) ?. to_string ( ) ?;
367
+ let guest_path =
368
+ RString :: try_convert ( mapped_directory. entry ( 1 ) ?) ?. to_string ( ) ?;
369
+ let dir_perms = Symbol :: from_value ( mapped_directory. entry ( 2 ) ?)
370
+ . unwrap ( )
371
+ . name ( ) ?;
372
+ let file_perms = Symbol :: from_value ( mapped_directory. entry ( 3 ) ?)
373
+ . unwrap ( )
374
+ . name ( ) ?;
375
+
376
+ let host_path_dir = Path :: new ( & host_path) ;
377
+ let guest_path_path = guest_path. as_str ( ) ;
378
+
379
+ // Convert to FilePerms and DirPerms enums
380
+ let dir_perms_flags;
381
+ match dir_perms {
382
+ std:: borrow:: Cow :: Borrowed ( "read" ) => dir_perms_flags = DirPerms :: READ ,
383
+ std:: borrow:: Cow :: Borrowed ( "mutate" ) => dir_perms_flags = DirPerms :: MUTATE ,
384
+ std:: borrow:: Cow :: Borrowed ( "all" ) => dir_perms_flags = DirPerms :: all ( ) ,
385
+ _ => {
386
+ return Err ( error ! (
387
+ "Invalid dir_perms: {}. Use one of :read, :mutate, or :all" ,
388
+ dir_perms
389
+ ) )
390
+ }
391
+ }
392
+
393
+ let file_perms_flags;
394
+ match file_perms {
395
+ std:: borrow:: Cow :: Borrowed ( "read" ) => file_perms_flags = FilePerms :: READ ,
396
+ std:: borrow:: Cow :: Borrowed ( "write" ) => file_perms_flags = FilePerms :: WRITE ,
397
+ std:: borrow:: Cow :: Borrowed ( "all" ) => file_perms_flags = FilePerms :: all ( ) ,
398
+ _ => {
399
+ return Err ( error ! (
400
+ "Invalid file_perms: {}. Use one of :read, :write, or :all" ,
401
+ file_perms
402
+ ) )
403
+ }
404
+ }
405
+
406
+ builder
407
+ . preopened_dir (
408
+ host_path_dir,
409
+ guest_path_path,
410
+ dir_perms_flags,
411
+ file_perms_flags,
412
+ )
413
+ . map_err ( |e| error ! ( "{}" , e) ) ?;
414
+ }
415
+ }
416
+ }
417
+
320
418
Ok ( builder)
321
419
}
322
420
}
@@ -355,5 +453,10 @@ pub fn init() -> Result<(), Error> {
355
453
356
454
class. define_method ( "set_argv" , method ! ( WasiConfig :: set_argv, 1 ) ) ?;
357
455
456
+ class. define_method (
457
+ "set_mapped_directory" ,
458
+ method ! ( WasiConfig :: set_mapped_directory, 4 ) ,
459
+ ) ?;
460
+
358
461
Ok ( ( ) )
359
462
}
0 commit comments