@@ -13,11 +13,12 @@ use bincode::{BorrowDecode, Decode, Encode};
1313#[ cfg( unix) ]
1414use bstr:: BStr ;
1515
16- /// Similar to `OsStr`, but requires zero-copy to construct from either ansi or wide characters on Windows.
16+ /// Similar to `OsStr`, but requires zero-copy to construct from either wide characters on Windows.
1717#[ derive( Encode , BorrowDecode , Clone , Copy , PartialEq , Eq ) ]
1818pub struct NativeStr < ' a > {
19- #[ cfg( windows) ]
20- is_wide : bool ,
19+ // On unix, this is the raw bytes of the OsStr.
20+ // On windows, this is safely transmuted from `&[u16]` in `NativeStr::from_wide`. We don't declare it as `&[u16]` to allow `BorrowDecode`.
21+ // Transmuting back to `&[u16]` would be unsafe because of different alignments between `u8` and `u16` (See `to_os_string`).
2122 data : & ' a [ u8 ] ,
2223}
2324
@@ -46,11 +47,7 @@ impl<'a> NativeStr<'a> {
4647 let mut data = Vec :: < u8 , _ > :: with_capacity_in ( self . data . len ( ) , alloc) ;
4748 data. extend_from_slice ( self . data ) ;
4849 let data = data. leak :: < ' new_alloc > ( ) ;
49- NativeStr {
50- data,
51- #[ cfg( windows) ]
52- is_wide : self . is_wide ,
53- }
50+ NativeStr { data }
5451 }
5552
5653 #[ cfg( unix) ]
@@ -59,16 +56,10 @@ impl<'a> NativeStr<'a> {
5956 Self { data : bytes }
6057 }
6158
62- #[ cfg( windows) ]
63- #[ must_use]
64- pub const fn from_ansi ( bytes : & ' a [ u8 ] ) -> Self {
65- Self { is_wide : false , data : bytes }
66- }
67-
6859 #[ cfg( windows) ]
6960 pub fn from_wide ( wide : & ' a [ u16 ] ) -> Self {
7061 use bytemuck:: must_cast_slice;
71- Self { is_wide : true , data : must_cast_slice ( wide) }
62+ Self { data : must_cast_slice ( wide) }
7263 }
7364
7465 #[ cfg( unix) ]
@@ -90,20 +81,11 @@ impl<'a> NativeStr<'a> {
9081 use std:: os:: windows:: ffi:: OsStringExt ;
9182
9283 use bytemuck:: { allocation:: pod_collect_to_vec, try_cast_slice} ;
93- use winsafe:: {
94- MultiByteToWideChar ,
95- co:: { CP , MBC } ,
96- } ;
97-
98- if self . is_wide {
99- if let Ok ( wide) = try_cast_slice :: < u8 , u16 > ( self . data ) {
100- OsString :: from_wide ( wide)
101- } else {
102- let wide = pod_collect_to_vec :: < u8 , u16 > ( self . data ) ;
103- OsString :: from_wide ( & wide)
104- }
84+
85+ if let Ok ( wide) = try_cast_slice :: < u8 , u16 > ( self . data ) {
86+ OsString :: from_wide ( wide)
10587 } else {
106- let wide = MultiByteToWideChar ( CP :: ACP , MBC :: ERR_INVALID_CHARS , self . data ) . unwrap ( ) ;
88+ let wide = pod_collect_to_vec :: < u8 , u16 > ( self . data ) ;
10789 OsString :: from_wide ( & wide)
10890 }
10991 }
@@ -227,15 +209,6 @@ mod tests {
227209 #[ cfg( windows) ]
228210 use super :: * ;
229211
230- #[ cfg( windows) ]
231- #[ test]
232- fn test_from_ansi ( ) {
233- let ansi_str = "hello" ;
234- let native_str = NativeStr :: from_ansi ( ansi_str. as_bytes ( ) ) ;
235- let os_string = native_str. to_os_string ( ) ;
236- assert_eq ! ( os_string. to_str( ) . unwrap( ) , ansi_str) ;
237- }
238-
239212 #[ cfg( windows) ]
240213 #[ test]
241214 fn test_from_wide ( ) {
0 commit comments