@@ -17,9 +17,9 @@ type StrVec<'a> = SmallVec<[&'a str; 8]>;
1717impl SugarPath for Path {
1818 fn normalize ( & self ) -> PathBuf {
1919 let peekable = self . components ( ) . peekable ( ) ;
20- let mut components = to_normalized_components ( peekable) ;
20+ let components = to_normalized_components ( peekable) ;
2121
22- normalize_inner ( & mut components)
22+ normalize_inner ( & components)
2323 }
2424
2525 fn absolutize ( & self ) -> PathBuf {
@@ -51,8 +51,8 @@ impl SugarPath for Path {
5151 // a UNC path at this points, because UNC paths are always absolute.
5252 let mut components: ComponentVec = components. collect ( ) ;
5353 components. insert ( 1 , Component :: RootDir ) ;
54- let mut components = to_normalized_components ( components. into_iter ( ) . peekable ( ) ) ;
55- normalize_inner ( & mut components)
54+ let components = to_normalized_components ( components. into_iter ( ) . peekable ( ) ) ;
55+ normalize_inner ( & components)
5656 } else {
5757 base. to_mut ( ) . push ( self ) ;
5858 base. normalize ( )
@@ -167,19 +167,77 @@ impl SugarPath for Path {
167167}
168168
169169#[ inline]
170- fn normalize_inner ( components : & mut ComponentVec ) -> PathBuf {
170+ fn normalize_inner ( components : & ComponentVec ) -> PathBuf {
171171 if components. is_empty ( ) {
172172 return PathBuf :: from ( "." ) ;
173173 }
174174
175- if cfg ! ( target_family = "windows" )
176- && components. len ( ) == 1
177- && matches ! ( components[ 0 ] , Component :: Prefix ( _) )
178- {
179- components. push ( Component :: CurDir )
175+ let sep = std:: path:: MAIN_SEPARATOR_STR ;
176+ let mut result = std:: ffi:: OsString :: with_capacity (
177+ components. iter ( ) . map ( |c| c. as_os_str ( ) . len ( ) ) . sum :: < usize > ( ) + components. len ( ) ,
178+ ) ;
179+ let mut need_sep = false ;
180+
181+ for c in components. iter ( ) {
182+ match c {
183+ #[ cfg( target_family = "windows" ) ]
184+ Component :: Prefix ( p) => {
185+ if let std:: path:: Prefix :: UNC ( server, share) = p. kind ( ) {
186+ // Reconstruct UNC prefix from structured data to ensure
187+ // correct backslash separators regardless of input format.
188+ result. push ( "\\ \\ " ) ;
189+ result. push ( server) ;
190+ result. push ( "\\ " ) ;
191+ result. push ( share) ;
192+ } else {
193+ result. push ( p. as_os_str ( ) ) ;
194+ }
195+ need_sep = false ;
196+ }
197+ #[ cfg( not( target_family = "windows" ) ) ]
198+ Component :: Prefix ( _) => unreachable ! ( ) ,
199+ Component :: RootDir => {
200+ result. push ( sep) ;
201+ need_sep = false ;
202+ }
203+ Component :: Normal ( s) => {
204+ if need_sep {
205+ result. push ( sep) ;
206+ }
207+ result. push ( s) ;
208+ need_sep = true ;
209+ }
210+ Component :: ParentDir => {
211+ if need_sep {
212+ result. push ( sep) ;
213+ }
214+ result. push ( ".." ) ;
215+ need_sep = true ;
216+ }
217+ Component :: CurDir => {
218+ if need_sep {
219+ result. push ( sep) ;
220+ }
221+ result. push ( "." ) ;
222+ need_sep = true ;
223+ }
224+ }
225+ }
226+
227+ // Prefix-only: append trailing separator or CurDir.
228+ // e.g. \\server\share → \\server\share\, C: → C:.
229+ #[ cfg( target_family = "windows" ) ]
230+ if components. len ( ) == 1 {
231+ if let Some ( Component :: Prefix ( p) ) = components. first ( ) {
232+ if matches ! ( p. kind( ) , std:: path:: Prefix :: UNC ( _, _) ) {
233+ result. push ( "\\ " ) ;
234+ } else {
235+ result. push ( "." ) ;
236+ }
237+ }
180238 }
181239
182- components . iter ( ) . collect ( )
240+ PathBuf :: from ( result )
183241}
184242
185243impl < T : Deref < Target = str > > SugarPath for T {
0 commit comments