1- //! `pathlib.PurePosixPath ` spelling and ordering over raw path bytes .
1+ //! `pathlib` spelling, ordering and stat reads for startup stamps on each platform .
22
3- use std:: ffi:: OsString ;
4- use std:: os :: unix :: ffi :: { OsStrExt , OsStringExt } ;
3+ use std:: ffi:: OsStr ;
4+ use std:: fs :: Metadata ;
55use std:: path:: { Path , PathBuf } ;
66
7+ use crate :: startup_inputs:: constants:: PATH_FILE_SUFFIX ;
8+ #[ cfg( unix) ]
79use crate :: startup_inputs:: constants:: { CURRENT , SEPARATOR } ;
810
911/// The root a POSIX path keeps: two leading slashes stay two, more collapse to one.
12+ #[ cfg( unix) ]
1013fn root ( bytes : & [ u8 ] ) -> & [ u8 ] {
1114 match bytes {
1215 [ SEPARATOR , SEPARATOR , rest @ ..] if rest. first ( ) != Some ( & SEPARATOR ) => & bytes[ ..2 ] ,
@@ -16,11 +19,14 @@ fn root(bytes: &[u8]) -> &[u8] {
1619}
1720
1821/// `str(PurePosixPath(path, *children))`.
19- pub ( crate ) fn pure ( path : & Path , children : & [ & [ u8 ] ] ) -> PathBuf {
22+ #[ cfg( unix) ]
23+ pub ( crate ) fn pure ( path : & Path , children : & [ & OsStr ] ) -> PathBuf {
24+ use std:: os:: unix:: ffi:: { OsStrExt , OsStringExt } ;
25+
2026 let bytes: & [ u8 ] = path. as_os_str ( ) . as_bytes ( ) ;
2127 let mut text: Vec < u8 > = root ( bytes) . to_vec ( ) ;
2228 let parts = std:: iter:: once ( bytes)
23- . chain ( children. iter ( ) . copied ( ) )
29+ . chain ( children. iter ( ) . map ( |child| child . as_bytes ( ) ) )
2430 . flat_map ( |segment| segment. split ( |byte| * byte == SEPARATOR ) )
2531 . filter ( |part| !part. is_empty ( ) && * part != CURRENT ) ;
2632 let mut first: bool = true ;
@@ -34,22 +40,82 @@ pub(crate) fn pure(path: &Path, children: &[&[u8]]) -> PathBuf {
3440 if text. is_empty ( ) {
3541 text. extend_from_slice ( CURRENT ) ;
3642 }
37- PathBuf :: from ( OsString :: from_vec ( text) )
43+ PathBuf :: from ( std:: ffi:: OsString :: from_vec ( text) )
44+ }
45+
46+ /// `str(PureWindowsPath(path, *children))` through the platform path rules.
47+ #[ cfg( not( unix) ) ]
48+ pub ( crate ) fn pure ( path : & Path , children : & [ & OsStr ] ) -> PathBuf {
49+ let mut joined: PathBuf = path. components ( ) . collect ( ) ;
50+ for child in children {
51+ joined. push ( child) ;
52+ }
53+ joined
3854}
3955
4056/// `str(Path(path).absolute())` against the working directory `cwd`.
4157pub ( crate ) fn absolute ( path : & Path , cwd : & Path ) -> PathBuf {
42- if root ( path. as_os_str ( ) . as_bytes ( ) ) . is_empty ( ) {
43- pure ( cwd, & [ path. as_os_str ( ) . as_bytes ( ) ] )
44- } else {
58+ if path. has_root ( ) && ( cfg ! ( unix) || path. is_absolute ( ) ) {
4559 pure ( path, & [ ] )
60+ } else {
61+ pure ( cwd, & [ path. as_os_str ( ) ] )
4662 }
4763}
4864
4965/// The `/`-separated parts `PurePosixPath` orders paths by.
50- pub ( crate ) fn order_key ( path : & Path ) -> Vec < & [ u8 ] > {
66+ #[ cfg( unix) ]
67+ pub ( crate ) fn order_key ( path : & Path ) -> Vec < Vec < u8 > > {
68+ use std:: os:: unix:: ffi:: OsStrExt ;
69+
5170 path. as_os_str ( )
5271 . as_bytes ( )
5372 . split ( |byte| * byte == SEPARATOR )
73+ . map ( <[ u8 ] >:: to_vec)
74+ . collect ( )
75+ }
76+
77+ /// The case-folded parts `PureWindowsPath` orders paths by.
78+ #[ cfg( not( unix) ) ]
79+ pub ( crate ) fn order_key ( path : & Path ) -> Vec < Vec < u8 > > {
80+ path. components ( )
81+ . map ( |part| {
82+ part. as_os_str ( )
83+ . to_string_lossy ( )
84+ . to_lowercase ( )
85+ . into_bytes ( )
86+ } )
5487 . collect ( )
5588}
89+
90+ /// Whether `glob("*.pth")` matches a directory entry name on this platform.
91+ pub ( crate ) fn is_path_file ( name : & OsStr ) -> bool {
92+ if cfg ! ( unix) {
93+ name. as_encoded_bytes ( ) . ends_with ( PATH_FILE_SUFFIX )
94+ } else {
95+ name. to_string_lossy ( )
96+ . to_lowercase ( )
97+ . as_bytes ( )
98+ . ends_with ( PATH_FILE_SUFFIX )
99+ }
100+ }
101+
102+ /// `os.stat(path).st_mtime_ns`.
103+ #[ cfg( unix) ]
104+ pub ( crate ) fn modified_ns ( metadata : & Metadata ) -> std:: io:: Result < i64 > {
105+ use std:: os:: unix:: fs:: MetadataExt ;
106+
107+ Ok ( metadata. mtime ( ) * 1_000_000_000 + metadata. mtime_nsec ( ) )
108+ }
109+
110+ /// `os.stat(path).st_mtime_ns` from the platform modification time, negative before 1970.
111+ #[ cfg( not( unix) ) ]
112+ pub ( crate ) fn modified_ns ( metadata : & Metadata ) -> std:: io:: Result < i64 > {
113+ let modified: std:: time:: SystemTime = metadata. modified ( ) ?;
114+ let ( nanos, sign) : ( u128 , i64 ) = match modified. duration_since ( std:: time:: UNIX_EPOCH ) {
115+ Ok ( elapsed) => ( elapsed. as_nanos ( ) , 1 ) ,
116+ Err ( before) => ( before. duration ( ) . as_nanos ( ) , -1 ) ,
117+ } ;
118+ i64:: try_from ( nanos)
119+ . map ( |value| sign * value)
120+ . map_err ( std:: io:: Error :: other)
121+ }
0 commit comments