@@ -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 , Symbol , Ruby , 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,54 @@ 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 ) ?) . unwrap ( ) . name ( ) ?;
367
+ let file_perms = Symbol :: from_value ( mapped_directory. entry ( 3 ) ?) . unwrap ( ) . name ( ) ?;
368
+
369
+ let host_path_dir = Path :: new ( & host_path) ;
370
+ let guest_path_path = guest_path. as_str ( ) ;
371
+
372
+ // Convert to FilePerms and DirPerms enums
373
+ let dir_perms_flags;
374
+ match dir_perms {
375
+ std:: borrow:: Cow :: Borrowed ( "read" ) => dir_perms_flags = DirPerms :: READ ,
376
+ std:: borrow:: Cow :: Borrowed ( "mutate" ) => dir_perms_flags = DirPerms :: MUTATE ,
377
+ std:: borrow:: Cow :: Borrowed ( "all" ) => dir_perms_flags = DirPerms :: all ( ) ,
378
+ _ => {
379
+ return Err ( error ! (
380
+ "Invalid dir_perms: {}. Use one of :read, :mutate, or :all" ,
381
+ dir_perms
382
+ ) )
383
+ }
384
+ }
385
+
386
+ let file_perms_flags;
387
+ match file_perms {
388
+ std:: borrow:: Cow :: Borrowed ( "read" ) => file_perms_flags = FilePerms :: READ ,
389
+ std:: borrow:: Cow :: Borrowed ( "write" ) => file_perms_flags = FilePerms :: WRITE ,
390
+ std:: borrow:: Cow :: Borrowed ( "all" ) => file_perms_flags = FilePerms :: all ( ) ,
391
+ _ => {
392
+ return Err ( error ! (
393
+ "Invalid file_perms: {}. Use one of :read, :write, or :all" ,
394
+ file_perms
395
+ ) )
396
+ }
397
+ }
398
+
399
+ builder
400
+ . preopened_dir ( host_path_dir, guest_path_path, dir_perms_flags, file_perms_flags)
401
+ . map_err ( |e| error ! ( "{}" , e) ) ?;
402
+ }
403
+ }
404
+ }
405
+
320
406
Ok ( builder)
321
407
}
322
408
}
@@ -355,5 +441,10 @@ pub fn init() -> Result<(), Error> {
355
441
356
442
class. define_method ( "set_argv" , method ! ( WasiConfig :: set_argv, 1 ) ) ?;
357
443
444
+ class. define_method (
445
+ "set_mapped_directory" ,
446
+ method ! ( WasiConfig :: set_mapped_directory, 4 ) ,
447
+ ) ?;
448
+
358
449
Ok ( ( ) )
359
450
}
0 commit comments