@@ -10,27 +10,27 @@ pub mod path_splitting {
1010
1111 /// Errors encountered during path splitting.
1212 #[ derive( Debug , Display , Error ) ]
13- pub enum PathSplitError {
14- /// entry path format error : {0:?}
15- PathFormat ( String ) ,
16- /// duplicate path used for file and directory : {0:?}
17- DuplicateFileDirPath ( String ) ,
13+ pub enum PathSplitError < ' a > {
14+ /// entry path {0:?} would escape extraction dir : {0:?}
15+ ExtractionPathEscapesDirectory ( & ' a str , & ' static str ) ,
16+ /// duplicate entry path {0:?} used : {0:?}
17+ DuplicatePath ( & ' a str , & ' static str ) ,
1818 }
1919
2020 /* NB: path_to_string() performs some of this logic, but is intended to coerce filesystems
2121 * paths into zip entry names, whereas we are processing entry names from a zip archive, so we
2222 * perform much less error handling. */
2323 pub ( crate ) fn normalize_parent_dirs < ' a > (
2424 entry_path : & ' a str ,
25- ) -> Result < ( Vec < & ' a str > , bool ) , PathSplitError > {
25+ ) -> Result < ( Vec < & ' a str > , bool ) , PathSplitError < ' a > > {
2626 /* The ZIP spec states (APPNOTE 4.4.17) that file paths are in Unix format, and Unix
2727 * filesystems treat a backslash as a normal character. Thus they should be allowed on Unix
2828 * and replaced with \u{fffd} on Windows. */
2929 if entry_path. starts_with ( '/' ) {
30- return Err ( PathSplitError :: PathFormat ( format ! (
31- "path {:?} began with '/' and is absolute" ,
32- entry_path
33- ) ) ) ;
30+ return Err ( PathSplitError :: ExtractionPathEscapesDirectory (
31+ entry_path ,
32+ "path began with '/' and is absolute" ,
33+ ) ) ;
3434 }
3535 let is_dir = is_dir ( entry_path) ;
3636
@@ -45,10 +45,10 @@ pub mod path_splitting {
4545 /* If ".." is present, pop off the last element or return an error. */
4646 ".." => {
4747 if ret. pop ( ) . is_none ( ) {
48- return Err ( PathSplitError :: PathFormat ( format ! (
49- "path {:?} has too many '..' components and would escape the containing dir" ,
50- entry_path
51- ) ) ) ;
48+ return Err ( PathSplitError :: ExtractionPathEscapesDirectory (
49+ entry_path ,
50+ "path has too many '..' components and would escape the containing dir" ,
51+ ) ) ;
5252 }
5353 }
5454 _ => {
@@ -57,10 +57,10 @@ pub mod path_splitting {
5757 }
5858 }
5959 if ret. is_empty ( ) {
60- return Err ( PathSplitError :: PathFormat ( format ! (
61- "path {:?} resolves to the top-level directory" ,
62- entry_path
63- ) ) ) ;
60+ return Err ( PathSplitError :: ExtractionPathEscapesDirectory (
61+ entry_path ,
62+ "path resolves to the top-level directory" ,
63+ ) ) ;
6464 }
6565
6666 Ok ( ( ret, is_dir) )
@@ -113,7 +113,7 @@ pub mod path_splitting {
113113 * any other data for the top-level extraction directory. */
114114 pub ( crate ) fn lexicographic_entry_trie < ' a , Data > (
115115 all_entries : impl IntoIterator < Item = ( & ' a str , Data ) > ,
116- ) -> Result < BTreeMap < & ' a str , Box < FSEntry < ' a , Data > > > , PathSplitError >
116+ ) -> Result < BTreeMap < & ' a str , Box < FSEntry < ' a , Data > > > , PathSplitError < ' a > >
117117 where
118118 Data : DirByMode ,
119119 {
@@ -139,10 +139,10 @@ pub mod path_splitting {
139139 . or_insert_with ( || Box :: new ( FSEntry :: Dir ( DirEntry :: default ( ) ) ) ) ;
140140 cur_dir = match next_subdir. as_mut ( ) {
141141 FSEntry :: File ( _) => {
142- return Err ( PathSplitError :: DuplicateFileDirPath ( format ! (
143- "a file was already registered at the same path as the dir entry {:?}" ,
144- entry_path
145- ) ) ) ;
142+ return Err ( PathSplitError :: DuplicatePath (
143+ entry_path ,
144+ "a file was already registered at the same path as this dir entry" ,
145+ ) ) ;
146146 }
147147 FSEntry :: Dir ( ref mut subdir) => subdir,
148148 }
@@ -152,10 +152,10 @@ pub mod path_splitting {
152152 /* We can't handle duplicate file paths, as that might mess up our
153153 * parallelization strategy. */
154154 if cur_dir. children . contains_key ( filename) {
155- return Err ( PathSplitError :: DuplicateFileDirPath ( format ! (
156- "another file or directory was already registered at the same path as the file entry {:?}" ,
157- entry_path
158- ) ) ) ;
155+ return Err ( PathSplitError :: DuplicatePath (
156+ entry_path ,
157+ "an entry was already registered at the same path as this file entry" ,
158+ ) ) ;
159159 }
160160 cur_dir
161161 . children
@@ -166,10 +166,10 @@ pub mod path_splitting {
166166 * path, as it's not clear how to merge the possibility of two separate file
167167 * permissions. */
168168 if cur_dir. properties . replace ( data) . is_some ( ) {
169- return Err ( PathSplitError :: DuplicateFileDirPath ( format ! (
170- "another directory was already registered at the path {:?}" ,
171- entry_path
172- ) ) ) ;
169+ return Err ( PathSplitError :: DuplicatePath (
170+ entry_path ,
171+ "another directory was already registered at this path" ,
172+ ) ) ;
173173 }
174174 }
175175 }
@@ -640,11 +640,18 @@ pub mod split_extraction {
640640 /// zip error: {0}
641641 Zip ( #[ from] ZipError ) ,
642642 /// path split error: {0}
643- PathSplit ( # [ from ] PathSplitError ) ,
643+ PathSplit ( String ) ,
644644 /// handle creation error: {0}
645645 HandleCreation ( #[ from] HandleCreationError ) ,
646646 }
647647
648+ impl < ' a > From < PathSplitError < ' a > > for SplitExtractionError {
649+ fn from ( e : PathSplitError < ' a > ) -> Self {
650+ let msg = format ! ( "{}" , e) ;
651+ Self :: PathSplit ( msg)
652+ }
653+ }
654+
648655 /* TODO: make this share code with find_data_start()! */
649656 fn get_or_find_data_start < InF > ( data : & ZipFileData , input_file : InF ) -> Result < u64 , ZipError >
650657 where
0 commit comments