1
1
use crate :: { Error , SourceFile , SourceName , SourcePos } ;
2
+ use std:: borrow:: Cow ;
2
3
use std:: path:: { Path , PathBuf } ;
3
4
4
5
/// A file context manages finding and loading files.
@@ -55,15 +56,8 @@ pub trait FileContext: Sized + std::fmt::Debug {
55
56
] ;
56
57
// Note: Should a "full stack" of bases be used here?
57
58
// Or is this fine?
58
- let base = from. file_url ( ) ;
59
- if let Some ( ( path, mut file) ) = base
60
- . rfind ( '/' )
61
- . map ( |p| base. split_at ( p + 1 ) . 0 )
62
- . map ( |base| {
63
- do_find_file ( self , & format ! ( "{}{}" , base, url) , names)
64
- } )
65
- . unwrap_or_else ( || do_find_file ( self , url, names) ) ?
66
- {
59
+ let url = relative ( from. file_url ( ) , url) ;
60
+ if let Some ( ( path, mut file) ) = do_find_file ( self , & url, names) ? {
67
61
let source = SourceName :: imported ( path, from) ;
68
62
Ok ( Some ( SourceFile :: read ( & mut file, source) ?) )
69
63
} else {
@@ -89,15 +83,8 @@ pub trait FileContext: Sized + std::fmt::Debug {
89
83
] ;
90
84
// Note: Should a "full stack" of bases be used here?
91
85
// Or is this fine?
92
- let base = from. file_url ( ) ;
93
- if let Some ( ( path, mut file) ) = base
94
- . rfind ( '/' )
95
- . map ( |p| base. split_at ( p + 1 ) . 0 )
96
- . map ( |base| {
97
- do_find_file ( self , & format ! ( "{}{}" , base, url) , names)
98
- } )
99
- . unwrap_or_else ( || do_find_file ( self , url, names) ) ?
100
- {
86
+ let url = relative ( from. file_url ( ) , url) ;
87
+ if let Some ( ( path, mut file) ) = do_find_file ( self , & url, names) ? {
101
88
let source = SourceName :: used ( path, from) ;
102
89
Ok ( Some ( SourceFile :: read ( & mut file, source) ?) )
103
90
} else {
@@ -119,7 +106,16 @@ pub trait FileContext: Sized + std::fmt::Debug {
119
106
) -> Result < Option < ( String , Self :: File ) > , Error > ;
120
107
}
121
108
122
- /// Find a file for `@use`
109
+ /// Make a url relative to a given base.
110
+ fn relative < ' a > ( base : & str , url : & ' a str ) -> Cow < ' a , str > {
111
+ base. rfind ( '/' )
112
+ . map ( |p| base. split_at ( p + 1 ) . 0 )
113
+ . map ( |base| format ! ( "{}{}" , base, url) . into ( ) )
114
+ . unwrap_or_else ( || url. into ( ) )
115
+ }
116
+
117
+ /// Find a file in a given filecontext matching a url over a set of
118
+ /// name rules.
123
119
fn do_find_file < FC : FileContext > (
124
120
ctx : & FC ,
125
121
url : & str ,
@@ -194,28 +190,16 @@ impl FileContext for FsFileContext {
194
190
& self ,
195
191
name : & str ,
196
192
) -> Result < Option < ( String , Self :: File ) > , Error > {
197
- // TODO: Use rsplit_once when MSRV is 1.52 or above.
198
- let ( parent, name) = if let Some ( pos) = name. find ( '/' ) {
199
- ( Some ( & name[ ..pos + 1 ] ) , & name[ pos + 1 ..] )
200
- } else {
201
- ( None , name)
202
- } ;
203
193
if !name. is_empty ( ) {
204
194
for base in & self . path {
205
- use std:: fmt:: Write ;
206
- let mut full = String :: new ( ) ;
207
- if !base. as_os_str ( ) . is_empty ( ) {
208
- write ! ( & mut full, "{}/" , base. display( ) ) . unwrap ( ) ;
209
- }
210
- if let Some ( parent) = parent {
211
- full. push_str ( parent) ;
212
- }
213
- full. push_str ( name) ;
195
+ let full = base. join ( name) ;
214
196
if Path :: new ( & full) . is_file ( ) {
215
197
tracing:: debug!( ?full, "opening file" ) ;
216
198
return match Self :: File :: open ( & full) {
217
- Ok ( file) => Ok ( Some ( ( full, file) ) ) ,
218
- Err ( e) => Err ( Error :: Input ( full, e) ) ,
199
+ Ok ( file) => Ok ( Some ( ( name. to_string ( ) , file) ) ) ,
200
+ Err ( e) => {
201
+ Err ( Error :: Input ( full. display ( ) . to_string ( ) , e) )
202
+ }
219
203
} ;
220
204
}
221
205
tracing:: trace!( ?full, "Not found" ) ;
0 commit comments