11use std:: {
2+ cell:: RefCell ,
23 ffi:: OsStr ,
34 io:: { self , Read , Write } ,
45 sync:: Arc ,
@@ -8,11 +9,10 @@ use interprocess::local_socket::{Stream, prelude::*};
89use native_str:: NativeStr ;
910use vite_path:: AbsolutePath ;
1011use vite_task_ipc_shared:: { GetEnvResponse , IPC_ENV_NAME , Request } ;
11- use wincode:: { SchemaRead , config:: DefaultConfig } ;
1212
1313pub struct Client {
14- stream : Stream ,
15- scratch : Vec < u8 > ,
14+ stream : RefCell < Stream > ,
15+ scratch : RefCell < Vec < u8 > > ,
1616}
1717
1818impl Client {
@@ -31,7 +31,7 @@ impl Client {
3131 for ( name, value) in envs {
3232 if name. as_ref ( ) == IPC_ENV_NAME {
3333 let stream = Stream :: connect ( resolve_name ( value. as_ref ( ) ) ?) ?;
34- return Ok ( Some ( Self { stream , scratch : Vec :: new ( ) } ) ) ;
34+ return Ok ( Some ( Self :: from_stream ( stream ) ) ) ;
3535 }
3636 }
3737 Ok ( None )
@@ -44,15 +44,19 @@ impl Client {
4444 /// Returns an error if the connection cannot be established.
4545 pub fn from_name ( name : & OsStr ) -> io:: Result < Self > {
4646 let stream = Stream :: connect ( resolve_name ( name) ?) ?;
47- Ok ( Self { stream, scratch : Vec :: new ( ) } )
47+ Ok ( Self :: from_stream ( stream) )
48+ }
49+
50+ const fn from_stream ( stream : Stream ) -> Self {
51+ Self { stream : RefCell :: new ( stream) , scratch : RefCell :: new ( Vec :: new ( ) ) }
4852 }
4953
5054 /// `path` can be a file or a directory; for a directory, all files inside it are ignored.
5155 ///
5256 /// # Errors
5357 ///
5458 /// Returns an error if the request fails to send.
55- pub fn ignore_input ( & mut self , path : & AbsolutePath ) -> io:: Result < ( ) > {
59+ pub fn ignore_input ( & self , path : & AbsolutePath ) -> io:: Result < ( ) > {
5660 let ns = path_to_native_str ( path) ;
5761 self . send ( & Request :: IgnoreInput ( & ns) )
5862 }
@@ -62,15 +66,15 @@ impl Client {
6266 /// # Errors
6367 ///
6468 /// Returns an error if the request fails to send.
65- pub fn ignore_output ( & mut self , path : & AbsolutePath ) -> io:: Result < ( ) > {
69+ pub fn ignore_output ( & self , path : & AbsolutePath ) -> io:: Result < ( ) > {
6670 let ns = path_to_native_str ( path) ;
6771 self . send ( & Request :: IgnoreOutput ( & ns) )
6872 }
6973
7074 /// # Errors
7175 ///
7276 /// Returns an error if the request fails to send.
73- pub fn disable_cache ( & mut self ) -> io:: Result < ( ) > {
77+ pub fn disable_cache ( & self ) -> io:: Result < ( ) > {
7478 self . send ( & Request :: DisableCache )
7579 }
7680
@@ -79,38 +83,42 @@ impl Client {
7983 ///
8084 /// # Errors
8185 ///
82- /// Returns an error if the request or response fails, or the response id mismatches .
83- pub fn get_env ( & mut self , name : & OsStr , tracked : bool ) -> io:: Result < Option < Arc < OsStr > > > {
86+ /// Returns an error if the request or response fails.
87+ pub fn get_env ( & self , name : & OsStr , tracked : bool ) -> io:: Result < Option < Arc < OsStr > > > {
8488 let name = Box :: < NativeStr > :: from ( name) ;
8589
8690 self . send ( & Request :: GetEnv { name : & name, tracked } ) ?;
87- let get_env_response = self . recv :: < GetEnvResponse > ( ) ?;
88-
89- Ok ( get_env_response
90- . env_value
91- . map ( |env_value| Arc :: < OsStr > :: from ( env_value. to_cow_os_str ( ) . as_ref ( ) ) ) )
91+ self . recv_with ( |bytes| {
92+ let response: GetEnvResponse < ' _ > = wincode:: deserialize_exact ( bytes)
93+ . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
94+ Ok ( response
95+ . env_value
96+ . map ( |env_value| Arc :: < OsStr > :: from ( env_value. to_cow_os_str ( ) . as_ref ( ) ) ) )
97+ } )
9298 }
9399
94- fn send ( & mut self , request : & Request < ' _ > ) -> io:: Result < ( ) > {
100+ fn send ( & self , request : & Request < ' _ > ) -> io:: Result < ( ) > {
95101 let bytes = wincode:: serialize ( request)
96102 . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
97103 let len = u32:: try_from ( bytes. len ( ) )
98104 . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: InvalidData , "request too large" ) ) ?;
99- self . stream . write_all ( & len. to_le_bytes ( ) ) ?;
100- self . stream . write_all ( & bytes) ?;
101- self . stream . flush ( ) ?;
105+ let mut stream = self . stream . borrow_mut ( ) ;
106+ stream. write_all ( & len. to_le_bytes ( ) ) ?;
107+ stream. write_all ( & bytes) ?;
108+ stream. flush ( ) ?;
102109 Ok ( ( ) )
103110 }
104111
105- fn recv < ' a , T : SchemaRead < ' a , DefaultConfig , Dst = T > > ( & ' a mut self ) -> io:: Result < T > {
112+ fn recv_with < T > ( & self , extract : impl FnOnce ( & [ u8 ] ) -> io:: Result < T > ) -> io:: Result < T > {
113+ let mut stream = self . stream . borrow_mut ( ) ;
114+ let mut scratch = self . scratch . borrow_mut ( ) ;
106115 let mut len_bytes = [ 0u8 ; 4 ] ;
107- self . stream . read_exact ( & mut len_bytes) ?;
116+ stream. read_exact ( & mut len_bytes) ?;
108117 let len = u32:: from_le_bytes ( len_bytes) as usize ;
109- self . scratch . clear ( ) ;
110- self . scratch . resize ( len, 0 ) ;
111- self . stream . read_exact ( & mut self . scratch ) ?;
112- wincode:: deserialize_exact ( & self . scratch )
113- . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) )
118+ scratch. clear ( ) ;
119+ scratch. resize ( len, 0 ) ;
120+ stream. read_exact ( & mut scratch) ?;
121+ extract ( & scratch)
114122 }
115123}
116124
0 commit comments