@@ -3,14 +3,17 @@ use crate::error;
33use crate :: helpers:: OutputLimitedBuffer ;
44use magnus:: {
55 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 ,
77} ;
8+ use rb_sys:: ruby_rarray_flags:: RARRAY_EMBED_FLAG ;
89use std:: cell:: RefCell ;
910use std:: fs;
11+ use std:: path:: Path ;
1012use std:: { fs:: File , path:: PathBuf } ;
1113use wasmtime_wasi:: p2:: pipe:: MemoryInputPipe ;
1214use wasmtime_wasi:: p2:: { OutputFile , WasiCtx , WasiCtxBuilder } ;
1315use wasmtime_wasi:: preview1:: WasiP1Ctx ;
16+ use wasmtime_wasi:: { DirPerms , FilePerms } ;
1417
1518enum ReadStream {
1619 Inherit ,
@@ -51,6 +54,7 @@ struct WasiConfigInner {
5154 env : Option < Opaque < RHash > > ,
5255 args : Option < Opaque < RArray > > ,
5356 deterministic : bool ,
57+ mapped_directories : Option < Opaque < RArray > > ,
5458}
5559
5660impl WasiConfigInner {
@@ -70,6 +74,9 @@ impl WasiConfigInner {
7074 if let Some ( v) = self . args . as_ref ( ) {
7175 marker. mark ( * v) ;
7276 }
77+ if let Some ( v) = self . mapped_directories . as_ref ( ) {
78+ marker. mark ( * v) ;
79+ }
7380 }
7481}
7582
@@ -233,6 +240,37 @@ impl WasiConfig {
233240 rb_self
234241 }
235242
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+
236274 pub fn build_p1 ( & self , ruby : & Ruby ) -> Result < WasiP1Ctx , Error > {
237275 let mut builder = self . build_impl ( ruby) ?;
238276 let ctx = builder. build_p1 ( ) ;
@@ -317,6 +355,63 @@ impl WasiConfig {
317355 deterministic_wasi_ctx:: add_determinism_to_wasi_ctx_builder ( & mut builder) ;
318356 }
319357
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+
320415 Ok ( builder)
321416 }
322417}
@@ -355,5 +450,10 @@ pub fn init() -> Result<(), Error> {
355450
356451 class. define_method ( "set_argv" , method ! ( WasiConfig :: set_argv, 1 ) ) ?;
357452
453+ class. define_method (
454+ "set_mapped_directory" ,
455+ method ! ( WasiConfig :: set_mapped_directory, 4 ) ,
456+ ) ?;
457+
358458 Ok ( ( ) )
359459}
0 commit comments